diff options
Diffstat (limited to 'src/map')
82 files changed, 7947 insertions, 6844 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index d6a1bd8ef..ac78e8c84 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -5,63 +5,73 @@ #include "HPMmap.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" + +#include "common/HPMi.h" +#include "common/conf.h" +#include "common/console.h" +#include "common/core.h" +#include "common/db.h" +#include "common/des.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/mapindex.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/spinlock.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/buyingstore.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/packets_struct.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pc_groups.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/searchstore.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "map/vending.h" + +// HPMDataCheck comes after all the other includes +#include "common/HPMDataCheck.h" + #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pc_groups.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "searchstore.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/des.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/mapindex.h" -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" - -#include "../common/HPMDataCheck.h" struct HPM_atcommand_list { //tracking currently not enabled @@ -118,6 +128,10 @@ bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataType ret->HPDataSRCPtr = (void**)(&((struct battleground_data *)ptr)->hdata); ret->hdatac = &((struct battleground_data *)ptr)->hdatac; break; + case HPDT_AUTOTRADE_VEND: + ret->HPDataSRCPtr = (void**)(&((struct autotrade_vending *)ptr)->hdata); + ret->hdatac = &((struct autotrade_vending *)ptr)->hdatac; + break; default: return false; } @@ -125,34 +139,35 @@ bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataType } void HPM_map_plugin_load_sub(struct hplugin *plugin) { - plugin->hpi->addCommand = HPM->import_symbol("addCommand",plugin->idx); - plugin->hpi->addScript = HPM->import_symbol("addScript",plugin->idx); - plugin->hpi->addPCGPermission = HPM->import_symbol("addGroupPermission",plugin->idx); + plugin->hpi->sql_handle = map->mysql_handle; + plugin->hpi->addCommand = atcommand->create; + plugin->hpi->addScript = script->addScript; + plugin->hpi->addPCGPermission = HPM_map_add_group_permission; } bool HPM_map_add_atcommand(char *name, AtCommandFunc func) { unsigned int i = 0; - + for(i = 0; i < atcommand_list_items; i++) { if( !strcmpi(atcommand_list[i].name,name) ) { ShowDebug("HPM_map_add_atcommand: duplicate command '%s', skipping...\n", name); return false; } } - + i = atcommand_list_items; - + RECREATE(atcommand_list, struct HPM_atcommand_list , ++atcommand_list_items); - + safestrncpy(atcommand_list[i].name, name, sizeof(atcommand_list[i].name)); atcommand_list[i].func = func; - + return true; } void HPM_map_atcommands(void) { unsigned int i; - + for(i = 0; i < atcommand_list_items; i++) { atcommand->add(atcommand_list[i].name,atcommand_list[i].func,true); } @@ -163,9 +178,9 @@ void HPM_map_atcommands(void) { **/ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask) { unsigned char index = pcg->HPMpermissions_count; - + RECREATE(pcg->HPMpermissions, struct pc_groups_new_permission, ++pcg->HPMpermissions_count); - + pcg->HPMpermissions[index].pID = pluginID; pcg->HPMpermissions[index].name = aStrdup(name); pcg->HPMpermissions[index].mask = mask; @@ -175,6 +190,7 @@ void HPM_map_do_init(void) { HPM->load_sub = HPM_map_plugin_load_sub; HPM->grabHPDataSub = HPM_map_grabHPData; HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer); + HPM_shared_symbols(SERVER_TYPE_MAP); } void HPM_map_do_final(void) { @@ -191,6 +207,5 @@ void HPM_map_do_final(void) { } aFree(pcg->HPMpermissions); } - HPM->datacheck_final(); } diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index 0c727d017..00a8f43c3 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -8,9 +8,9 @@ #error You should never include HPMmap.h from a plugin. #endif -#include "../common/cbasetypes.h" -#include "../map/atcommand.h" -#include "../common/HPM.h" +#include "map/atcommand.h" +#include "common/cbasetypes.h" +#include "common/HPM.h" struct hplugin; struct map_session_data; diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 90bb55694..ac1b4d837 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -9,18 +9,20 @@ CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h) COMMON_D = ../common COMMON_H = $(wildcard $(COMMON_D)/*.h) SYSINFO_INC = $(COMMON_D)/sysinfo.inc +COMMON_INCLUDE = -I.. -LIBCONFIG_D = ../../3rdparty/libconfig +THIRDPARTY_D = ../../3rdparty +THIRDPARTY_INCLUDE = -I$(THIRDPARTY_D) + +LIBCONFIG_D = $(THIRDPARTY_D)/libconfig LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \ scanner.o strbuf.o) LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \ scanctx.h scanner.h strbuf.h wincompat.h) -LIBCONFIG_INCLUDE = -I$(LIBCONFIG_D) -MT19937AR_D = ../../3rdparty/mt19937ar +MT19937AR_D = $(THIRDPARTY_D)/mt19937ar MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h -MT19937AR_INCLUDE = -I$(MT19937AR_D) MAP_C = atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \ chrif.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \ @@ -111,7 +113,7 @@ map-server: ../../map-server@EXEEXT@ obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql @echo " CC $<" - @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files $(COMMON_D)/obj_all/common.a: diff --git a/src/map/atcommand.c b/src/map/atcommand.c index a1666b44e..beeccaddd 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4,60 +4,61 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP +#include "config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP #include "atcommand.h" +#include "map/HPMmap.h" +#include "map/battle.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pc_groups.h" // groupid2name +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/searchstore.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/core.h" +#include "common/malloc.h" +#include "common/mmo.h" // MAX_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "HPMmap.h" -#include "battle.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pc_groups.h" // groupid2name -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "searchstore.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/core.h" -#include "../common/malloc.h" -#include "../common/mmo.h" // MAX_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct atcommand_interface atcommand_s; +struct atcommand_interface *atcommand; static char atcmd_output[CHAT_SIZE_MAX]; static char atcmd_player_name[NAME_LENGTH]; @@ -66,6 +67,7 @@ static char atcmd_player_name[NAME_LENGTH]; struct atcmd_binding_data* get_atcommandbind_byname(const char* name) { int i = 0; + nullpo_retr(NULL, name); if( *name == atcommand->at_symbol || *name == atcommand->char_symbol ) name++; // for backwards compatibility @@ -75,18 +77,16 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) { } const char* atcommand_msgsd(struct map_session_data *sd, int msg_number) { - if( !(msg_number >= 0 && msg_number < MAX_MSG) ) - return "??"; - if( !sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number] ) + Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG); + if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number]) return atcommand->msg_table[0][msg_number]; return atcommand->msg_table[sd->lang_id][msg_number]; } const char* atcommand_msgfd(int fd, int msg_number) { - struct map_session_data *sd = session_isValid(fd) ? session[fd]->session_data : NULL; - if( !(msg_number >= 0 && msg_number < MAX_MSG) ) - return "??"; - if( !sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number] ) + struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL; + Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG); + if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number]) return atcommand->msg_table[0][msg_number]; return atcommand->msg_table[sd->lang_id][msg_number]; } @@ -95,13 +95,12 @@ const char* atcommand_msgfd(int fd, int msg_number) { // Return the message string of the specified number by [Yor] //----------------------------------------------------------- const char* atcommand_msg(int msg_number) { - if (msg_number >= 0 && msg_number < MAX_MSG) { - if(atcommand->msg_table[map->default_lang_id][msg_number] != NULL && atcommand->msg_table[map->default_lang_id][msg_number][0] != '\0') - return atcommand->msg_table[map->default_lang_id][msg_number]; - - if(atcommand->msg_table[0][msg_number] != NULL && atcommand->msg_table[0][msg_number][0] != '\0') - return atcommand->msg_table[0][msg_number]; - } + Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG); + if (atcommand->msg_table[map->default_lang_id][msg_number] != NULL && atcommand->msg_table[map->default_lang_id][msg_number][0] != '\0') + return atcommand->msg_table[map->default_lang_id][msg_number]; + + if(atcommand->msg_table[0][msg_number] != NULL && atcommand->msg_table[0][msg_number][0] != '\0') + return atcommand->msg_table[0][msg_number]; return "??"; } @@ -119,11 +118,12 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { FILE *fp; static int called = 1; + nullpo_retr(false, cfg_name); if ((fp = fopen(cfg_name, "r")) == NULL) { ShowError("Messages file not found: %s\n", cfg_name); return false; } - + if( !atcommand->max_message_table ) atcommand->expand_message_table(); @@ -134,7 +134,7 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { continue; if (strcmpi(w1, "import") == 0) { - msg_config_read(w2, true); + atcommand->msg_read(w2, true); } else { msg_number = atoi(w1); if (msg_number >= 0 && msg_number < MAX_MSG) { @@ -152,9 +152,8 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { } } } - fclose(fp); - + if( ++called == 1 ) { //Original if( script->lang_export_fp ) { int i; @@ -178,7 +177,7 @@ bool msg_config_read(const char *cfg_name, bool allow_override) { *------------------------------------------*/ void do_final_msg(void) { int i, j; - + for(i = 0; i < atcommand->max_message_table; i++) { for (j = 0; j < MAX_MSG; j++) { if( atcommand->msg_table[i][j] ) @@ -186,7 +185,7 @@ void do_final_msg(void) { } aFree(atcommand->msg_table[i]); } - + if( atcommand->msg_table ) aFree(atcommand->msg_table); } @@ -198,8 +197,6 @@ static inline const char* atcommand_help_string(AtCommandInfo *info) { return info->help; } - - /*========================================== * @send (used for testing packet sends from the client) *------------------------------------------*/ @@ -209,9 +206,10 @@ ACMD(send) 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) ) { + if (!*message + || !((sscanf(message, "len %x", &type)==1 && (len=1, true)) + || sscanf(message, "%x", &type)==1) + ) { clif->message(fd, msg_fd(fd,900)); // Usage: clif->message(fd, msg_fd(fd,901)); // @send len <packet hex number> clif->message(fd, msg_fd(fd,902)); // @send <packet hex number> {<value>}* @@ -221,7 +219,7 @@ ACMD(send) #define PARSE_ERROR(error,p) do {\ clif->message(fd, (error));\ - sprintf(atcmd_output, ">%s", (p));\ + safesnprintf(atcmd_output, sizeof(atcmd_output), ">%s", (p));\ clif->message(fd, atcmd_output);\ } while(0) //define PARSE_ERROR @@ -248,7 +246,7 @@ ACMD(send) int off = 2; if (len) { // show packet length - sprintf(atcmd_output, msg_fd(fd,904), type, packet_db[type].len); // Packet 0x%x length: %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, packet_db[type].len); // Packet 0x%x length: %d clif->message(fd, atcmd_output); return true; } @@ -256,7 +254,7 @@ ACMD(send) len=packet_db[type].len; if (len == 0) { // unknown packet - ERROR - sprintf(atcmd_output, msg_fd(fd,905), type); // Unknown packet: 0x%x + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,905), type); // Unknown packet: 0x%x clif->message(fd, atcmd_output); return false; } else if (len == -1) { @@ -436,9 +434,9 @@ ACMD(mapmove) { 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 || + (sscanf(message, "%15s %5hd %5hd", map_name, &x, &y) < 3 && + sscanf(message, "%15[^,],%5hd,%5hd", map_name, &x, &y) < 1)) { clif->message(fd, msg_fd(fd,909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>). return false; } @@ -457,7 +455,7 @@ ACMD(mapmove) { return false; } - if ((x || y) && map->getcell(m, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) { + if ((x || y) && map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) { //This is to prevent the pc->setpos call from printing an error. clif->message(fd, msg_fd(fd,2)); if (!map->search_freecell(NULL, m, &x, &y, 10, 10, 1)) @@ -488,7 +486,7 @@ ACMD(where) { memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,910)); // Please enter a player name (usage: @where <char name>). return false; } @@ -514,7 +512,7 @@ ACMD(where) { ACMD(jumpto) { struct map_session_data *pl_sd = NULL; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). return false; } @@ -545,7 +543,7 @@ ACMD(jumpto) { } pc->setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); - sprintf(atcmd_output, msg_fd(fd,4), pl_sd->status.name); // Jumped to %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,4), pl_sd->status.name); // Jumped to %s clif->message(fd, atcmd_output); return true; @@ -560,7 +558,7 @@ ACMD(jump) memset(atcmd_output, '\0', sizeof(atcmd_output)); - sscanf(message, "%hd %hd", &x, &y); + sscanf(message, "%5hd %5hd", &x, &y); if (map->list[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif->message(fd, msg_fd(fd,248)); // You are not authorized to warp from your current map. @@ -572,20 +570,20 @@ ACMD(jump) return false; } - if ((x || y) && map->getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) { + if ((x || y) && map->getcell(sd->bl.m, &sd->bl, x, y, CELL_CHKNOPASS)) { //This is to prevent the pc->setpos call from printing an error. clif->message(fd, msg_fd(fd,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 && sd->bl.x == x && sd->bl.y == y ) { + if (x && y && sd->bl.x == x && sd->bl.y == y) { clif->message(fd, msg_fd(fd,253)); // You already are at your destination! return false; } pc->setpos(sd, sd->mapindex, x, y, CLR_TELEPORT); - sprintf(atcmd_output, msg_fd(fd,5), sd->bl.x, sd->bl.y); // Jumped to %d %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,5), sd->bl.x, sd->bl.y); // Jumped to %d %d clif->message(fd, atcmd_output); return true; } @@ -663,7 +661,7 @@ ACMD(who) { break; } } - clif->colormes(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/ + clif->messagecolor_self(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/ StrBuf->Clear(&buf); count++; } @@ -733,18 +731,18 @@ ACMD(whogm) if (pl_level > level) { if (pc_isinvisible(pl_sd)) continue; - sprintf(atcmd_output, msg_fd(fd,913), pl_sd->status.name); // Name: %s (GM) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,913), pl_sd->status.name); // Name: %s (GM) clif->message(fd, atcmd_output); count++; continue; } - sprintf(atcmd_output, msg_fd(fd,914), // Name: %s (GM:%d) | Location: %s %d %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,915), // BLvl: %d | Job: %s (Lvl: %d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,915), // BLvl: %d | Job: %s (Lvl: %d) pl_sd->status.base_level, pc->job_name(pl_sd->status.class_), pl_sd->status.job_level); clif->message(fd, atcmd_output); @@ -752,7 +750,7 @@ ACMD(whogm) p = party->search(pl_sd->status.party_id); g = pl_sd->guild; - sprintf(atcmd_output,msg_fd(fd,916), // Party: '%s' | Guild: '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,916), // Party: '%s' | Guild: '%s' p?p->party.name:msg_fd(fd,917), g?g->name:msg_fd(fd,917)); // None. clif->message(fd, atcmd_output); @@ -765,7 +763,7 @@ ACMD(whogm) else if (count == 1) clif->message(fd, msg_fd(fd,151)); // 1 GM found. else { - sprintf(atcmd_output, msg_fd(fd,152), count); // %d GMs found. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,152), count); // %d GMs found. clif->message(fd, atcmd_output); } @@ -819,8 +817,8 @@ ACMD(speed) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &speed) < 1) { - sprintf(atcmd_output, msg_fd(fd,918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>). + if (!*message || sscanf(message, "%12d", &speed) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>). clif->message(fd, atcmd_output); return false; } @@ -861,7 +859,6 @@ ACMD(storage) return true; } - /*========================================== * *------------------------------------------*/ @@ -875,12 +872,12 @@ ACMD(guildstorage) if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading) return false; - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } - if (sd->state.storage_flag == 2) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { clif->message(fd, msg_fd(fd,251)); return false; } @@ -901,7 +898,7 @@ ACMD(option) { int param1 = 0, param2 = 0, param3 = 0; - if (!message || !*message || sscanf(message, "%d %d %d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) + if (!*message || sscanf(message, "%12d %12d %12d", ¶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; @@ -974,10 +971,10 @@ ACMD(jobchange) { int job = 0, upper = 0; const char* text; - if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) { + if (!*message || sscanf(message, "%12d %12d", &job, &upper) < 1) { upper = 0; - if( message ) { + if (*message) { int i; bool found = false; @@ -1068,7 +1065,7 @@ ACMD(kami) memset(atcmd_output, '\0', sizeof(atcmd_output)); if(*(info->command + 4) != 'c' && *(info->command + 4) != 'C') { - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,980)); // Please enter a message (usage: @kami <message>). return false; } @@ -1079,7 +1076,7 @@ ACMD(kami) else intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW); } else { - if(!message || !*message || (sscanf(message, "%u %199[^\n]", &color, atcmd_output) < 2)) { + if(!*message || (sscanf(message, "%10u %199[^\n]", &color, atcmd_output) < 2)) { clif->message(fd, msg_fd(fd,981)); // Please enter color and message (usage: @kamic <color> <message>). return false; } @@ -1100,12 +1097,12 @@ ACMD(heal) { int hp = 0, sp = 0; // [Valaris] thanks to fov - sscanf(message, "%d %d", &hp, &sp); + sscanf(message, "%12d %12d", &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->message(fd, msg_fd(fd,157)); // HP and SP have already been recovered. @@ -1124,7 +1121,7 @@ ACMD(heal) if ( hp < 0 && sp <= 0 ) { status->damage(NULL, &sd->bl, -hp, -sp, 0, 0); - clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0); + clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0); clif->message(fd, msg_fd(fd,156)); // HP or/and SP modified. return true; } @@ -1135,7 +1132,7 @@ ACMD(heal) status->heal(&sd->bl, hp, 0, 0); else { status->damage(NULL, &sd->bl, -hp, 0, 0, 0); - clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0); + clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0); } } @@ -1164,15 +1161,15 @@ ACMD(item) memset(item_name, '\0', sizeof(item_name)); - if (!strcmpi(info->command,"itembound") && (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 2 && - sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2 + if (!strcmpi(info->command,"itembound") && (!*message || ( + sscanf(message, "\"%99[^\"]\" %12d %12d", item_name, &number, &bound) < 2 && + sscanf(message, "%99s %12d %12d", item_name, &number, &bound) < 2 ))) { clif->message(fd, msg_fd(fd,295)); // Please enter an item name or ID (usage: @itembound <item name/ID> <quantity> <bound_type>). return false; - } else if (!message || !*message - || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 - && sscanf(message, "%99s %d", item_name, &number) < 1 + } else if (!*message + || ( sscanf(message, "\"%99[^\"]\" %12d", item_name, &number) < 1 + && sscanf(message, "%99s %12d", item_name, &number) < 1 )) { clif->message(fd, msg_fd(fd,983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). return false; @@ -1255,15 +1252,15 @@ ACMD(item2) memset(item_name, '\0', sizeof(item_name)); - if (!strcmpi(info->command,"itembound2") && (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 && - sscanf(message, "%99s %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) { + if (!strcmpi(info->command,"itembound2") && (!*message || ( + sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 && + sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) { clif->message(fd, msg_fd(fd,296)); // Please enter all parameters (usage: @itembound2 <item name/ID> <quantity> clif->message(fd, msg_fd(fd,297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>). return false; - } else 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 + } else if (!*message + || ( sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 + && sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 )) { clif->message(fd, msg_fd(fd,984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> clif->message(fd, msg_fd(fd,985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>). @@ -1344,7 +1341,7 @@ ACMD(itemreset) 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); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND); } } clif->message(fd, msg_fd(fd,20)); // All of your items have been removed. @@ -1359,7 +1356,7 @@ ACMD(baselevelup) { int level=0, i=0, status_point=0; - if (!message || !*message || !(level = atoi(message))) { + if (!*message || !(level = atoi(message))) { clif->message(fd, msg_fd(fd,986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>). return false; } @@ -1418,7 +1415,7 @@ ACMD(joblevelup) { int level=0; - if (!message || !*message || !(level = atoi(message))) { + if (!*message || !(level = atoi(message))) { clif->message(fd, msg_fd(fd,987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>). return false; } @@ -1443,7 +1440,7 @@ ACMD(joblevelup) 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 subtract more points. + pc->resetskill(sd, PCRESETSKILL_NONE); //Reset skills since we need to subtract more points. if (sd->status.skill_point < level) sd->status.skill_point = 0; else @@ -1468,7 +1465,7 @@ ACMD(help) { char *default_command = "help"; AtCommandInfo *tinfo = NULL; - if (!message || !*message) { + if (!*message) { command_name = default_command; // If no command_name specified, display help for @help. } else { if (*message == atcommand->at_symbol || *message == atcommand->char_symbol) @@ -1477,7 +1474,7 @@ ACMD(help) { } if (!atcommand->can_use2(sd, command_name, COMMAND_ATCOMMAND)) { - sprintf(atcmd_output, msg_fd(fd,153), message); // "%s is Unknown Command" + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,153), message); // "%s is Unknown Command" clif->message(fd, atcmd_output); atcommand->get_suggestions(sd, command_name, true); return false; @@ -1486,13 +1483,13 @@ ACMD(help) { tinfo = atcommand->get_info_byname(atcommand->check_alias(command_name)); if ( !tinfo || tinfo->help == NULL ) { - sprintf(atcmd_output, msg_fd(fd,988), atcommand->at_symbol, command_name); // There is no help for %c%s. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,988), atcommand->at_symbol, command_name); // There is no help for %c%s. clif->message(fd, atcmd_output); atcommand->get_suggestions(sd, command_name, true); return false; } - sprintf(atcmd_output, msg_fd(fd,989), atcommand->at_symbol, command_name); // Help for command %c%s: + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,989), atcommand->at_symbol, command_name); // Help for command %c%s: clif->message(fd, atcmd_output); { // Display aliases @@ -1523,25 +1520,37 @@ ACMD(help) { return true; } -// helper function, used in foreach calls to stop auto-attack timers -// parameter: '0' - everyone, 'id' - only those attacking someone with that id +/** + * Helper function, used in foreach calls to stop auto-attack timers. + * + * @see map_foreachinmap + * + * Arglist parameters: + * - (int) id: If 0, stop any attacks. Otherwise, the target block list id to stop attacking. + */ 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)) - { + struct unit_data *ud = NULL; + int id = 0; + nullpo_ret(bl); + + ud = unit->bl2ud(bl); + id = va_arg(ap, int); + + if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target)) { unit->stop_attack(bl); return 1; } return 0; } + /*========================================== * *------------------------------------------*/ int atcommand_pvpoff_sub(struct block_list *bl,va_list ap) { TBL_PC* sd = (TBL_PC*)bl; + nullpo_ret(bl); clif->pvpset(sd, 0, 0, 2); if (sd->pvp_timer != INVALID_TIMER) { timer->delete(sd->pvp_timer, pc->calc_pvprank_timer); @@ -1576,6 +1585,7 @@ ACMD(pvpoff) int atcommand_pvpon_sub(struct block_list *bl,va_list ap) { TBL_PC* sd = (TBL_PC*)bl; + nullpo_ret(bl); if (sd->pvp_timer == INVALID_TIMER) { sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0); sd->pvp_rank = 0; @@ -1656,8 +1666,8 @@ ACMD(model) 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_fd(fd,991), // Please enter at least one value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>). + if (!*message || sscanf(message, "%12d %12d %12d", &hair_style, &hair_color, &cloth_color) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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->message(fd, atcmd_output); return false; @@ -1687,8 +1697,8 @@ ACMD(dye) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) { - sprintf(atcmd_output, msg_fd(fd,992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>). + if (!*message || sscanf(message, "%12d", &cloth_color) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>). clif->message(fd, atcmd_output); return false; } @@ -1713,8 +1723,8 @@ ACMD(hair_style) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) { - sprintf(atcmd_output, msg_fd(fd,993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>). + if (!*message || sscanf(message, "%12d", &hair_style) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>). clif->message(fd, atcmd_output); return false; } @@ -1739,8 +1749,8 @@ ACMD(hair_color) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) { - sprintf(atcmd_output, msg_fd(fd,994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>). + if (!*message || sscanf(message, "%12d", &hair_color) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>). clif->message(fd, atcmd_output); return false; } @@ -1813,7 +1823,7 @@ ACMD(go) { memset(map_name, '\0', sizeof(map_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%11s", map_name) < 1) { + if (!*message || sscanf(message, "%11s", map_name) < 1) { // no value matched so send the list of locations const char* text; @@ -1822,7 +1832,7 @@ ACMD(go) { clif->message(fd, msg_fd(fd,38)); // Invalid location number, or name. - if( text ) {// send the text to the client + if (text) { // send the text to the client clif->messageln( fd, text ); } @@ -1913,18 +1923,18 @@ ACMD(monster) memset(monster, '\0', sizeof(monster)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,80)); // Please specify a display name or monster name/id. return false; } - if (sscanf(message, "\"%23[^\"]\" %23s %d", name, monster, &number) > 1 || - sscanf(message, "%23s \"%23[^\"]\" %d", monster, name, &number) > 1) { + if (sscanf(message, "\"%23[^\"]\" %23s %12d", name, monster, &number) > 1 || + sscanf(message, "%23s \"%23[^\"]\" %12d", monster, name, &number) > 1) { //All data can be left as it is. - } else if ((count=sscanf(message, "%23s %d %23s", monster, &number, name)) > 1) { + } else if ((count=sscanf(message, "%23s %12d %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) { + } else if (sscanf(message, "%23s %23s %12d", 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. @@ -1945,7 +1955,7 @@ ACMD(monster) if (number <= 0) number = 1; - if( !name[0] ) + 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 @@ -1975,7 +1985,7 @@ ACMD(monster) if (number == count) clif->message(fd, msg_fd(fd,39)); // All monster summoned! else { - sprintf(atcmd_output, msg_fd(fd,240), count); // %d monster(s) summoned! + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,240), count); // %d monster(s) summoned! clif->message(fd, atcmd_output); } else { @@ -1991,12 +2001,10 @@ ACMD(monster) *------------------------------------------*/ int atkillmonster_sub(struct block_list *bl, va_list ap) { - struct mob_data *md; - int flag; - - nullpo_ret(md=(struct mob_data *)bl); - flag = va_arg(ap, int); + struct mob_data *md = (struct mob_data *)bl; + int flag = va_arg(ap, int); + nullpo_ret(bl); if (md->guardian_data) return 0; //Do not touch WoE mobs! @@ -2013,9 +2021,9 @@ ACMD(killmonster) { memset(map_name, '\0', sizeof(map_name)); - if (!message || !*message || sscanf(message, "%15s", map_name) < 1) + if (!*message || sscanf(message, "%15s", map_name) < 1) { map_id = sd->bl.m; - else { + } else { if ((map_id = map->mapname2mapid(map_name)) < 0) map_id = sd->bl.m; } @@ -2039,27 +2047,27 @@ ACMD(refine) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) { + if (!*message || sscanf(message, "%12d %12d", &position, &refine) < 2) { clif->message(fd, msg_fd(fd,996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>). - sprintf(atcmd_output, msg_fd(fd,997), EQP_HEAD_LOW); // %d: Lower Headgear + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,997), EQP_HEAD_LOW); // %d: Lower Headgear clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,998), EQP_HAND_R); // %d: Right Hand + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,998), EQP_HAND_R); // %d: Right Hand clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,999), EQP_GARMENT); // %d: Garment + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,999), EQP_GARMENT); // %d: Garment clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1000), EQP_ACC_L); // %d: Left Accessory + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1000), EQP_ACC_L); // %d: Left Accessory clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1001), EQP_ARMOR); // %d: Body Armor + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1001), EQP_ARMOR); // %d: Body Armor clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1002), EQP_HAND_L); // %d: Left Hand + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1002), EQP_HAND_L); // %d: Left Hand clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1003), EQP_SHOES); // %d: Shoes + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1003), EQP_SHOES); // %d: Shoes clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1004), EQP_ACC_R); // %d: Right Accessory + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1004), EQP_ACC_R); // %d: Right Accessory clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1005), EQP_HEAD_TOP); // %d: Top Headgear + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1005), EQP_HEAD_TOP); // %d: Top Headgear clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1006), EQP_HEAD_MID); // %d: Mid Headgear + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1006), EQP_HEAD_MID); // %d: Mid Headgear clif->message(fd, atcmd_output); return false; } @@ -2086,9 +2094,9 @@ ACMD(refine) if (sd->status.inventory[idx].refine != final_refine) { sd->status.inventory[idx].refine = final_refine; current_position = sd->status.inventory[idx].equip; - pc->unequipitem(sd, idx, 3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); clif->refine(fd, 0, idx, sd->status.inventory[idx].refine); - clif->delitem(sd, idx, 1, 3); + clif->delitem(sd, idx, 1, DELITEM_MATERIALCHANGE); clif->additem(sd, idx, 1, 0); pc->equipitem(sd, idx, current_position); clif->misceffect(&sd->bl, 3); @@ -2101,7 +2109,7 @@ ACMD(refine) else if (count == 1) clif->message(fd, msg_fd(fd,167)); // 1 item has been refined. else { - sprintf(atcmd_output, msg_fd(fd,168), count); // %d items have been refined. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,168), count); // %d items have been refined. clif->message(fd, atcmd_output); } @@ -2121,9 +2129,9 @@ ACMD(produce) 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 + if (!*message || ( + sscanf(message, "\"%99[^\"]\" %12d %12d", item_name, &attribute, &star) < 1 && + sscanf(message, "%99s %12d %12d", item_name, &attribute, &star) < 1 )) { clif->message(fd, msg_fd(fd,1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>). return false; @@ -2158,7 +2166,7 @@ ACMD(produce) if ((flag = pc->additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND))) clif->additem(sd, 0, 0, flag); } else { - sprintf(atcmd_output, msg_fd(fd,169), item_id, item_data->name); // The item (%d: '%s') is not equipable. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,169), item_id, item_data->name); // The item (%d: '%s') is not equipable. clif->message(fd, atcmd_output); return false; } @@ -2175,16 +2183,16 @@ ACMD(memo) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if( !message || !*message || sscanf(message, "%d", &position) < 1 ) + if (!*message || sscanf(message, "%d", &position) < 1) { int i; clif->message(sd->fd, msg_fd(fd,868)); // "Your current memo positions are:" 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); + safesnprintf(atcmd_output, sizeof(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_fd(fd,171), i); // %d - void + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,171), i); // %d - void clif->message(sd->fd, atcmd_output); } return true; @@ -2192,7 +2200,7 @@ ACMD(memo) if( position < 0 || position >= MAX_MEMOPOINTS ) { - sprintf(atcmd_output, msg_fd(fd,1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>). + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>). clif->message(fd, atcmd_output); return false; } @@ -2210,13 +2218,13 @@ ACMD(gat) { 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", + safesnprintf(atcmd_output, sizeof(atcmd_output), "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", map->list[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)); + map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), + map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), + map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), + map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), + map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); clif->message(fd, atcmd_output); } @@ -2231,7 +2239,7 @@ ACMD(displaystatus) { int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0; - if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { + if (!*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { clif->message(fd, msg_fd(fd,1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). return false; } @@ -2254,7 +2262,7 @@ ACMD(statuspoint) int point; unsigned int new_status_point; - if (!message || !*message || (point = atoi(message)) == 0) { + if (!*message || (point = atoi(message)) == 0) { clif->message(fd, msg_fd(fd,1010)); // Please enter a number (usage: @stpoint <number of points>). return false; } @@ -2302,7 +2310,7 @@ ACMD(skillpoint) int point; unsigned int new_skill_point; - if (!message || !*message || (point = atoi(message)) == 0) { + if (!*message || (point = atoi(message)) == 0) { clif->message(fd, msg_fd(fd,1011)); // Please enter a number (usage: @skpoint <number of points>). return false; } @@ -2349,12 +2357,12 @@ ACMD(zeny) { int zeny=0, ret=-1; - if (!message || !*message || (zeny = atoi(message)) == 0) { + if (!*message || (zeny = atoi(message)) == 0) { clif->message(fd, msg_fd(fd,1012)); // Please enter an amount (usage: @zeny <amount>). return false; } - if(zeny > 0){ + if(zeny > 0) { if((ret=pc->getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL)) == 1) clif->message(fd, msg_fd(fd,149)); // Unable to increase the number/value. } @@ -2382,7 +2390,7 @@ ACMD(param) { memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { + if (!*message || sscanf(message, "%d", &value) < 1 || value == 0) { clif->message(fd, msg_fd(fd,1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). return false; } @@ -2446,7 +2454,7 @@ ACMD(stat_all) { stats[4] = &sd->status.dex; stats[5] = &sd->status.luk; - if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { + if (!*message || sscanf(message, "%d", &value) < 1 || value == 0) { value = pc_maxparameter(sd); max = pc_maxparameter(sd); } else { @@ -2495,7 +2503,7 @@ ACMD(guildlevelup) { int16 added_level; struct guild *guild_info; - if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) { + if (!*message || sscanf(message, "%d", &level) < 1 || level == 0) { clif->message(fd, msg_fd(fd,1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). return false; } @@ -2536,7 +2544,7 @@ ACMD(makeegg) struct item_data *item_data; int id, pet_id; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). return false; } @@ -2590,7 +2598,7 @@ ACMD(petfriendly) int friendly; struct pet_data *pd; - if (!message || !*message || (friendly = atoi(message)) < 0) { + if (!*message || (friendly = atoi(message)) < 0) { clif->message(fd, msg_fd(fd,1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). return false; } @@ -2626,7 +2634,7 @@ ACMD(pethungry) int hungry; struct pet_data *pd; - if (!message || !*message || (hungry = atoi(message)) < 0) { + if (!*message || (hungry = atoi(message)) < 0) { clif->message(fd, msg_fd(fd,1017)); // Please enter a valid number (usage: @pethungry <0-100>). return false; } @@ -2682,7 +2690,7 @@ ACMD(petrename) ACMD(recall) { struct map_session_data *pl_sd = NULL; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1018)); // Please enter a player name (usage: @recall <char name/ID>). return false; } @@ -2710,7 +2718,7 @@ ACMD(recall) { return false; } pc->setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); - sprintf(atcmd_output, msg_fd(fd,46), pl_sd->status.name); // %s recalled! + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,46), pl_sd->status.name); // %s recalled! clif->message(fd, atcmd_output); return true; @@ -2725,12 +2733,12 @@ ACMD(char_block) memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1021)); // Please enter a player name (usage: @block <char name>). return false; } - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2761,7 +2769,7 @@ ACMD(char_ban) memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { + if (!*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { clif->message(fd, msg_fd(fd,1022)); // Please enter ban time and a player name (usage: @ban <time> <char name>). return false; } @@ -2826,7 +2834,8 @@ ACMD(char_ban) return false; } - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charban") ? 6 : 2, year, month, day, hour, minute, second); // type: 2 - ban; 6 - charban + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, + !strcmpi(info->command,"charban") ? CHAR_ASK_NAME_CHARBAN : CHAR_ASK_NAME_BAN, year, month, day, hour, minute, second); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2839,13 +2848,13 @@ ACMD(char_unblock) { memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1024)); // Please enter a player name (usage: @unblock <char name>). return false; } // 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 + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, CHAR_ASK_NAME_UNBLOCK, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2858,13 +2867,14 @@ ACMD(char_unban) { memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1025)); // Please enter a player name (usage: @unban <char name>). return false; } // send answer to login server via char-server - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charunban") ? 7 : 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban account; type 7 - unban character + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, + !strcmpi(info->command,"charunban") ? CHAR_ASK_NAME_CHARUNBAN : CHAR_ASK_NAME_UNBAN, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2955,6 +2965,7 @@ ACMD(doommap) *------------------------------------------*/ void atcommand_raise_sub(struct map_session_data* sd) { + nullpo_retv(sd); status->revive(&sd->bl, 100, 100); clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); @@ -3008,7 +3019,7 @@ ACMD(kick) memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1026)); // Please enter a player name (usage: @kick <char name/ID>). return false; } @@ -3018,7 +3029,7 @@ ACMD(kick) return false; } - if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { clif->message(fd, msg_fd(fd,81)); // Your GM level don't authorize you to do this action on this player. return false; @@ -3038,7 +3049,7 @@ ACMD(kickall) struct s_mapiterator* iter; iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) + 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) @@ -3072,8 +3083,8 @@ ACMD(questskill) { uint16 skill_id, index; - if (!message || !*message || (skill_id = atoi(message)) <= 0) - {// also send a list of skills applicable to this command + if (!*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 @@ -3101,7 +3112,7 @@ ACMD(questskill) return false; } - pc->skill(sd, skill_id, 1, 0); + pc->skill(sd, skill_id, 1, SKILL_GRANT_PERMANENT); clif->message(fd, msg_fd(fd,70)); // You have learned the skill. return true; @@ -3114,8 +3125,8 @@ ACMD(lostskill) { uint16 skill_id, index; - if (!message || !*message || (skill_id = atoi(message)) <= 0) - {// also send a list of skills applicable to this command + if (!*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 @@ -3130,7 +3141,7 @@ ACMD(lostskill) return false; } - if ( !( index = skill->get_index(skill_id) ) ) { + if (!( index = skill->get_index(skill_id))) { clif->message(fd, msg_fd(fd,198)); // This skill number doesn't exist. return false; } @@ -3161,7 +3172,7 @@ ACMD(spiritball) max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF); - if( !message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs ) + if (!*message || (number = atoi(message)) < 0 || number > max_spiritballs) { char msg[CHAT_SIZE_MAX]; safesnprintf(msg, sizeof(msg), msg_fd(fd,1028), max_spiritballs); // Please enter an amount (usage: @spiritball <number: 0-%d>). @@ -3187,7 +3198,7 @@ ACMD(party) memset(party_name, '\0', sizeof(party_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", party_name) < 1) { clif->message(fd, msg_fd(fd,1029)); // Please enter a party name (usage: @party <party_name>). return false; } @@ -3207,7 +3218,7 @@ ACMD(guild) memset(guild_name, '\0', sizeof(guild_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", guild_name) < 1) { clif->message(fd, msg_fd(fd,1030)); // Please enter a guild name (usage: @guild <guild_name>). return false; } @@ -3223,8 +3234,7 @@ ACMD(guild) ACMD(breakguild) { if (sd->status.guild_id) { // Check if the player has a guild - struct guild *g; - g = sd->guild; // Search the guild + struct guild *g = sd->guild; // Search the guild if (g) { // Check if guild was found if (sd->state.gmaster_flag) { // Check if player is guild master int ret = 0; @@ -3333,24 +3343,24 @@ ACMD(idsearch) memset(item_name, '\0', sizeof(item_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%99s", item_name) < 0) { + if (!*message || sscanf(message, "%99s", item_name) < 0) { clif->message(fd, msg_fd(fd,1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>). return false; } - sprintf(atcmd_output, msg_fd(fd,77), item_name); // Search results for '%s' (name: id): + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,77), item_name); // Search results for '%s' (name: id): clif->message(fd, atcmd_output); match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0); if (match > MAX_SEARCH) { - sprintf(atcmd_output, msg_fd(fd,269), MAX_SEARCH, match); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, match); clif->message(fd, atcmd_output); match = MAX_SEARCH; } for(i = 0; i < match; i++) { - sprintf(atcmd_output, msg_fd(fd,78), item_array[i]->jname, item_array[i]->nameid); // %s: %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,78), item_array[i]->jname, item_array[i]->nameid); // %s: %d clif->message(fd, atcmd_output); } - sprintf(atcmd_output, msg_fd(fd,79), match); // %d results found. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,79), match); // %d results found. clif->message(fd, atcmd_output); return true; @@ -3374,7 +3384,7 @@ ACMD(recallall) count = 0; iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { + 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. @@ -3393,7 +3403,7 @@ ACMD(recallall) clif->message(fd, msg_fd(fd,92)); // All characters recalled! if (count) { - sprintf(atcmd_output, msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. clif->message(fd, atcmd_output); } @@ -3414,7 +3424,7 @@ ACMD(guildrecall) memset(guild_name, '\0', sizeof(guild_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", guild_name) < 1) { clif->message(fd, msg_fd(fd,1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>). return false; } @@ -3434,7 +3444,7 @@ ACMD(guildrecall) count = 0; iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) + 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)) @@ -3447,10 +3457,10 @@ ACMD(guildrecall) } mapit->free(iter); - sprintf(atcmd_output, msg_fd(fd,93), g->name); // All online characters of the %s guild have been recalled to your position. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,93), g->name); // All online characters of the %s guild have been recalled to your position. clif->message(fd, atcmd_output); if (count) { - sprintf(atcmd_output, msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. clif->message(fd, atcmd_output); } @@ -3471,7 +3481,7 @@ ACMD(partyrecall) memset(party_name, '\0', sizeof(party_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", party_name) < 1) { clif->message(fd, msg_fd(fd,1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>). return false; } @@ -3503,10 +3513,10 @@ ACMD(partyrecall) } mapit->free(iter); - sprintf(atcmd_output, msg_fd(fd,95), p->party.name); // All online characters of the %s party have been recalled to your position. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,95), p->party.name); // All online characters of the %s party have been recalled to your position. clif->message(fd, atcmd_output); if (count) { - sprintf(atcmd_output, msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. clif->message(fd, atcmd_output); } @@ -3654,7 +3664,7 @@ ACMD(reloadscript) { //atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { + for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) { if (pl_sd->npc_id || pl_sd->npc_shopid) { if (pl_sd->state.using_fake_npc) { clif->clearunit_single(pl_sd->npc_id, CLR_OUTSIGHT, pl_sd->fd); @@ -3673,7 +3683,7 @@ ACMD(reloadscript) { } mapit->free(iter); - flush_fifos(); + sockt->flush_fifos(); map->reloadnpc(true); // reload config files seeking for npcs script->reload(); npc->reload(); @@ -3705,7 +3715,7 @@ ACMD(mapinfo) { memset(mapname, '\0', sizeof(mapname)); memset(direction, '\0', sizeof(direction)); - sscanf(message, "%d %23[^\n]", &list, mapname); + sscanf(message, "%12d %23[^\n]", &list, mapname); if (list < 0 || list > 3) { clif->message(fd, msg_fd(fd,1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). @@ -3740,7 +3750,7 @@ ACMD(mapinfo) { } mapit->free(iter); - sprintf(atcmd_output, msg_fd(fd,1040), mapname, map->list[m_id].zone->name, map->list[m_id].users, map->list[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1040), mapname, map->list[m_id].zone->name, map->list[m_id].users, map->list[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1041)); // ------ Map Flags ------ if (map->list[m_id].flag.town) @@ -3793,7 +3803,7 @@ ACMD(mapinfo) { strcat(atcmd_output, msg_fd(fd,1064)); // NoMemo | clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1065), // No Exp Penalty: %s | No Zeny Penalty: %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1065), // No Exp Penalty: %s | No Zeny Penalty: %s (map->list[m_id].flag.noexppenalty) ? msg_fd(fd,1066) : msg_fd(fd,1067), (map->list[m_id].flag.nozenypenalty) ? msg_fd(fd,1066) : msg_fd(fd,1067)); // On / Off clif->message(fd, atcmd_output); @@ -3802,10 +3812,10 @@ ACMD(mapinfo) { if (!map->list[m_id].save.map) clif->message(fd, msg_fd(fd,1068)); // No Save (Return to last Save Point) else if (map->list[m_id].save.x == -1 || map->list[m_id].save.y == -1 ) { - sprintf(atcmd_output, msg_fd(fd,1069), mapindex_id2name(map->list[m_id].save.map)); // No Save, Save Point: %s,Random + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1069), mapindex_id2name(map->list[m_id].save.map)); // No Save, Save Point: %s,Random clif->message(fd, atcmd_output); } else { - sprintf(atcmd_output, msg_fd(fd,1070), // No Save, Save Point: %s,%d,%d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1070), // No Save, Save Point: %s,%d,%d mapindex_id2name(map->list[m_id].save.map),map->list[m_id].save.x,map->list[m_id].save.y); clif->message(fd, atcmd_output); } @@ -3873,10 +3883,10 @@ ACMD(mapinfo) { case 1: clif->message(fd, msg_fd(fd,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) ) + 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_fd(fd,1099), // Player '%s' (session #%d) | Location: %d,%d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1099), // Player '%s' (session #%d) | Location: %d,%d pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); clif->message(fd, atcmd_output); } @@ -3900,27 +3910,27 @@ ACMD(mapinfo) { default: strcpy(direction, msg_fd(fd,1110)); break; // Unknown } if(strcmp(nd->name,nd->exname) == 0) - sprintf(atcmd_output, msg_fd(fd,1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d - ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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_fd(fd,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); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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->message(fd, atcmd_output); } break; case 3: clif->message(fd, msg_fd(fd,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) ) + 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_fd(fd,1114), // Chat: %s | Player: %s | Location: %d %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1114), // Chat: %s | Player: %s | Location: %d %d cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1115), // Users: %d/%d | Password: %s | Public: %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1115), // Users: %d/%d | Password: %s | Public: %s cd->users, cd->limit, cd->pass, (cd->pub) ? msg_fd(fd,1116) : msg_fd(fd,1117)); // Yes / No clif->message(fd, atcmd_output); } @@ -3945,14 +3955,14 @@ ACMD(mount_peco) return false; } - if( sd->sc.data[SC_ALL_RIDING] ) { + if (sd->sc.data[SC_ALL_RIDING]) { clif->message(fd, msg_fd(fd,1476)); // You are already mounting something else return false; } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) { - if( !pc->checkskill(sd,RK_DRAGONTRAINING) ) { - sprintf(atcmd_output, msg_fd(fd,213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount! + if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) { + if (!pc->checkskill(sd,RK_DRAGONTRAINING)) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount! clif->message(fd, atcmd_output); return false; } @@ -3965,13 +3975,13 @@ ACMD(mount_peco) } return true; } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { - if( !pc->checkskill(sd,RA_WUGRIDER) ) { - sprintf(atcmd_output, msg_fd(fd,213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount! + if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) { + if (!pc->checkskill(sd,RA_WUGRIDER)) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount! clif->message(fd, atcmd_output); return false; } - if( !pc_isridingwug(sd) ) { + if (!pc_isridingwug(sd)) { clif->message(sd->fd,msg_fd(fd,1121)); // You have mounted your Warg. pc->setridingwug(sd, true); } else { @@ -3980,8 +3990,8 @@ ACMD(mount_peco) } return true; } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { - if( !pc_ismadogear(sd) ) { + if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) { + if (!pc_ismadogear(sd)) { clif->message(sd->fd,msg_fd(fd,1123)); // You have mounted your Mado Gear. pc->setmadogear(sd, true); } else { @@ -3990,10 +4000,10 @@ ACMD(mount_peco) } return true; } - if( sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2 ) { + if (sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2) { if (!pc_isridingpeco(sd)) { // if actually no peco if (!pc->checkskill(sd, KN_RIDING)) { - sprintf(atcmd_output, msg_fd(fd,213), skill->get_desc(KN_RIDING)); // You need %s to mount! + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(KN_RIDING)); // You need %s to mount! clif->message(fd, atcmd_output); return false; } @@ -4024,7 +4034,7 @@ ACMD(guildspy) { clif->message(fd, msg_fd(fd,1125)); // The mapserver has spy command support disabled. return false; } - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", guild_name) < 1) { clif->message(fd, msg_fd(fd,1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>). return false; } @@ -4033,11 +4043,11 @@ ACMD(guildspy) { (g = guild->search(atoi(message))) != NULL) { if (sd->guildspy == g->guild_id) { sd->guildspy = 0; - sprintf(atcmd_output, msg_fd(fd,103), g->name); // No longer spying on the %s guild. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,103), g->name); // No longer spying on the %s guild. clif->message(fd, atcmd_output); } else { sd->guildspy = g->guild_id; - sprintf(atcmd_output, msg_fd(fd,104), g->name); // Spying on the %s guild. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,104), g->name); // Spying on the %s guild. clif->message(fd, atcmd_output); } } else { @@ -4064,7 +4074,7 @@ ACMD(partyspy) { return false; } - if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", party_name) < 1) { clif->message(fd, msg_fd(fd,1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>). return false; } @@ -4073,11 +4083,11 @@ ACMD(partyspy) { (p = party->search(atoi(message))) != NULL) { if (sd->partyspy == p->party.party_id) { sd->partyspy = 0; - sprintf(atcmd_output, msg_fd(fd,105), p->party.name); // No longer spying on the %s party. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,105), p->party.name); // No longer spying on the %s party. clif->message(fd, atcmd_output); } else { sd->partyspy = p->party.party_id; - sprintf(atcmd_output, msg_fd(fd,106), p->party.name); // Spying on the %s party. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,106), p->party.name); // Spying on the %s party. clif->message(fd, atcmd_output); } } else { @@ -4124,7 +4134,7 @@ ACMD(nuke) { memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1128)); // Please enter a player name (usage: @nuke <char name>). return false; } @@ -4154,7 +4164,7 @@ ACMD(tonpc) { memset(npcname, 0, sizeof(npcname)); - if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) { + if (!*message || sscanf(message, "%23[^\n]", npcname) < 1) { clif->message(fd, msg_fd(fd,1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>). return false; } @@ -4181,7 +4191,7 @@ ACMD(shownpc) memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { + if (!*message || sscanf(message, "%23[^\n]", NPCname) < 1) { clif->message(fd, msg_fd(fd,1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>). return false; } @@ -4206,7 +4216,7 @@ ACMD(hidenpc) memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { + if (!*message || sscanf(message, "%23[^\n]", NPCname) < 1) { clif->message(fd, msg_fd(fd,1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>). return false; } @@ -4225,7 +4235,7 @@ ACMD(loadnpc) { FILE *fp; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1132)); // Please enter a script file name (usage: @loadnpc <file name>). return false; } @@ -4254,7 +4264,7 @@ ACMD(unloadnpc) memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%24[^\n]", NPCname) < 1) { + if (!*message || sscanf(message, "%24[^\n]", NPCname) < 1) { clif->message(fd, msg_fd(fd,1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>). return false; } @@ -4374,6 +4384,11 @@ void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int const int factor_day = 1440; //24*60 = 1440 const int factor_hour = 60; + nullpo_retv(year); + nullpo_retv(month); + nullpo_retv(day); + nullpo_retv(hour); + nullpo_retv(minute); *year = jailtime/factor_year; jailtime -= *year*factor_year; *month = jailtime/factor_month; @@ -4403,7 +4418,7 @@ ACMD(jail) { memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1134)); // Please enter a player name (usage: @jail <char_name>). return false; } @@ -4454,7 +4469,7 @@ ACMD(unjail) { memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>). return false; } @@ -4490,7 +4505,7 @@ ACMD(jailfor) { int jailtime = 0,x,y; short m_index = 0; - if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { + if (!*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { clif->message(fd, msg_fd(fd,400)); //Usage: @jailfor <time> <character name> return false; } @@ -4564,9 +4579,9 @@ ACMD(jailfor) { clif->message(fd, msg_fd(fd,121)); // Player unjailed } else { atcommand->get_jail_time(jailtime,&year,&month,&day,&hour,&minute); - sprintf(atcmd_output,msg_fd(fd,402),msg_fd(fd,1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,402),msg_fd(fd,1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes clif->message(pl_sd->fd, atcmd_output); - sprintf(atcmd_output,msg_fd(fd,402),msg_fd(fd,1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,402),msg_fd(fd,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->message(fd, atcmd_output); } } else if (jailtime < 0) { @@ -4591,7 +4606,6 @@ ACMD(jailfor) { return true; } - //By Coltaro ACMD(jailtime) { @@ -4614,7 +4628,7 @@ ACMD(jailtime) //Get remaining jail time atcommand->get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); - sprintf(atcmd_output,msg_fd(fd,402),msg_fd(fd,1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,402),msg_fd(fd,1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes clif->message(fd, atcmd_output); @@ -4628,7 +4642,7 @@ ACMD(disguise) { int id = 0; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). return false; } @@ -4679,7 +4693,7 @@ ACMD(disguiseall) struct map_session_data *pl_sd; struct s_mapiterator* iter; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>). return false; } @@ -4713,7 +4727,7 @@ ACMD(disguiseguild) memset(monster, '\0', sizeof(monster)); memset(guild_name, '\0', sizeof(guild_name)); - if( !message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild_name) < 2 ) { + if (!*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild_name) < 2) { clif->message(fd, msg_fd(fd,1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>). return false; } @@ -4749,7 +4763,6 @@ ACMD(disguiseguild) return true; } - /*========================================== * @undisguise by [Yor] *------------------------------------------*/ @@ -4795,17 +4808,17 @@ ACMD(undisguiseguild) memset(guild_name, '\0', sizeof(guild_name)); - if(!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + if (!*message || sscanf(message, "%23[^\n]", guild_name) < 1) { clif->message(fd, msg_fd(fd,1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>). return false; } - if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(message))) == NULL ) { + if ((g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,94)); // Incorrect name/ID, or no one from the guild is online. return false; } - for(i = 0; i < g->max_member; i++) { + for (i = 0; i < g->max_member; i++) { struct map_session_data *pl_sd = g->member[i].sd; if (pl_sd && pl_sd->disguise != -1) pc->disguise(pl_sd, -1); @@ -4839,7 +4852,6 @@ ACMD(exp) return true; } - /*========================================== * @broadcast by [Valaris] *------------------------------------------*/ @@ -4847,12 +4859,12 @@ ACMD(broadcast) { memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1149)); // Please enter a message (usage: @broadcast <message>). return false; } - sprintf(atcmd_output, "%s: %s", sd->status.name, message); + safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message); intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT); return true; @@ -4865,12 +4877,12 @@ ACMD(localbroadcast) { memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1150)); // Please enter a message (usage: @localbroadcast <message>). return false; } - sprintf(atcmd_output, "%s: %s", sd->status.name, message); + safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message); clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP); @@ -4888,7 +4900,7 @@ ACMD(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) { + if (!*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) { clif->message(fd, msg_fd(fd,1151)); // Please enter two e-mail addresses (usage: @email <current@email> <new@email>). return false; } @@ -4919,7 +4931,7 @@ ACMD(effect) { int type = 0, flag = 0; - if (!message || !*message || sscanf(message, "%d", &type) < 1) { + if (!*message || sscanf(message, "%d", &type) < 1) { clif->message(fd, msg_fd(fd,1152)); // Please enter an effect number (usage: @effect <effect number>). return false; } @@ -4937,7 +4949,7 @@ ACMD(killer) { sd->state.killer = !sd->state.killer; - if(sd->state.killer) + if (sd->state.killer) clif->message(fd, msg_fd(fd,241)); else { clif->message(fd, msg_fd(fd,292)); @@ -4953,9 +4965,9 @@ ACMD(killer) ACMD(killable) { sd->state.killable = !sd->state.killable; - if(sd->state.killable) + if (sd->state.killable) { clif->message(fd, msg_fd(fd,242)); - else { + } else { clif->message(fd, msg_fd(fd,288)); map->foreachinrange(atcommand->stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id); } @@ -4992,7 +5004,7 @@ ACMD(npcmove) { memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) { + if (!*message || sscanf(message, "%12d %12d %23[^\n]", &x, &y, atcmd_player_name) < 3) { clif->message(fd, msg_fd(fd,1153)); // Usage: @npcmove <X> <Y> <npc_name> return false; } @@ -5030,7 +5042,7 @@ ACMD(addwarp) memset(warpname, '\0', sizeof(warpname)); - if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) { + if (!*message || sscanf(message, "%31s %12d %12d %23[^\n]", mapname, &x, &y, warpname) < 4) { clif->message(fd, msg_fd(fd,1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name> return false; } @@ -5038,7 +5050,7 @@ ACMD(addwarp) m = mapindex->name2id(mapname); if( m == 0 ) { - sprintf(atcmd_output, msg_fd(fd,1157), mapname); // Unknown map '%s'. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1157), mapname); // Unknown map '%s'. clif->message(fd, atcmd_output); return false; } @@ -5047,7 +5059,7 @@ ACMD(addwarp) if( nd == NULL ) return false; - sprintf(atcmd_output, msg_fd(fd,1158), nd->exname); // New warp NPC '%s' created. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1158), nd->exname); // New warp NPC '%s' created. clif->message(fd, atcmd_output); return true; } @@ -5059,7 +5071,7 @@ ACMD(addwarp) ACMD(follow) { struct map_session_data *pl_sd = NULL; - if (!message || !*message) { + if (!*message) { if (sd->followtarget == -1) return false; pc->stop_following (sd); @@ -5067,7 +5079,7 @@ ACMD(follow) { return true; } - if ( (pl_sd = map->nick2sd((char *)message)) == NULL ) + if ((pl_sd = map->nick2sd((char *)message)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; @@ -5084,7 +5096,6 @@ ACMD(follow) { return true; } - /*========================================== * @dropall by [MouseJstr] * Drop all your possession on the ground @@ -5096,7 +5107,7 @@ ACMD(dropall) 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->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd, i, sd->status.inventory[i].amount); } } @@ -5111,9 +5122,9 @@ ACMD(storeall) { int i; - if (sd->state.storage_flag != 1) { + if (sd->state.storage_flag != STORAGE_FLAG_NORMAL) { //Open storage. - if( storage->open(sd) == 1 ) { + if (storage->open(sd) == 1) { clif->message(fd, msg_fd(fd,1161)); // You currently cannot open your storage. return false; } @@ -5122,7 +5133,7 @@ ACMD(storeall) 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->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); storage->add(sd, i, sd->status.inventory[i].amount); } } @@ -5136,7 +5147,7 @@ ACMD(clearstorage) { int i, j; - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } @@ -5164,12 +5175,12 @@ ACMD(cleargstorage) return false; } - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } - if (sd->state.storage_flag == 2) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { clif->message(fd, msg_fd(fd,251)); return false; } @@ -5200,7 +5211,7 @@ ACMD(clearcart) return false; } - if( sd->state.vending == 1 ) { + if (sd->state.vending) { clif->message(fd, msg_fd(fd,548)); // You can't clean a cart while vending! return false; } @@ -5230,7 +5241,7 @@ ACMD(skillid) { DBData *data; char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN]; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). return false; } @@ -5241,11 +5252,11 @@ ACMD(skillid) { for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { int idx = skill->get_index(DB->data2i(data)); - if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->db[idx].desc, message, skillen) == 0) { - sprintf(atcmd_output, msg_fd(fd,1164), DB->data2i(data), skill->db[idx].desc, key.str); // skill %d: %s (%s) + if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->dbs->db[idx].desc, message, skillen) == 0) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); // skill %d: %s (%s) clif->message(fd, atcmd_output); - } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->db[idx].desc,message) ) ) { - snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd,1164), DB->data2i(data), skill->db[idx].desc, key.str); + } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->dbs->db[idx].desc,message) ) ) { + snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); found++; } } @@ -5253,7 +5264,7 @@ ACMD(skillid) { dbi_destroy(iter); if( found ) { - sprintf(atcmd_output, msg_fd(fd,1398), found); // -- Displaying first %d partial matches + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1398), found); // -- Displaying first %d partial matches clif->message(fd, atcmd_output); } @@ -5275,19 +5286,19 @@ ACMD(useskill) { uint16 skill_lv; char target[100]; - if(!message || !*message || sscanf(message, "%hu %hu %23[^\n]", &skill_id, &skill_lv, target) != 3) { + if (!*message || sscanf(message, "%5hu %5hu %23[^\n]", &skill_id, &skill_lv, target) != 3) { clif->message(fd, msg_fd(fd,1165)); // Usage: @useskill <skill ID> <skill level> <target> return false; } - if(!strcmp(target,"self")) + if (!strcmp(target,"self")) pl_sd = sd; //quick keyword - else if ( (pl_sd = map->nick2sd(target)) == NULL ) { + else if ((pl_sd = map->nick2sd(target)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } - if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { clif->message(fd, msg_fd(fd,81)); // Your GM level don't authorized you to do this action on this player. return false; @@ -5320,13 +5331,13 @@ ACMD(displayskill) { uint16 skill_id; uint16 skill_lv = 1; - if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1) { + if (!*message || sscanf(message, "%5hu %5hu", &skill_id, &skill_lv) < 1) { clif->message(fd, msg_fd(fd,1166)); // Usage: @displayskill <skill ID> {<skill level>} return false; } st = status->get_status_data(&sd->bl); tick = timer->gettick(); - clif->skill_damage(&sd->bl,&sd->bl, tick, st->amotion, st->dmotion, 1, 1, skill_id, skill_lv, 5); + clif->skill_damage(&sd->bl,&sd->bl, tick, st->amotion, st->dmotion, 1, 1, skill_id, skill_lv, BDT_SPLASH); clif->skill_nodamage(&sd->bl, &sd->bl, skill_id, skill_lv, 1); clif->skill_poseffect(&sd->bl, skill_id, skill_lv, sd->bl.x, sd->bl.y, tick); return true; @@ -5343,7 +5354,7 @@ ACMD(skilltree) { char target[NAME_LENGTH]; struct skill_tree_entry *ent; - if(!message || !*message || sscanf(message, "%hu %23[^\r\n]", &skill_id, target) != 2) { + if(!*message || sscanf(message, "%5hu %23[^\r\n]", &skill_id, target) != 2) { clif->message(fd, msg_fd(fd,1167)); // Usage: @skilltree <skill ID> <target> return false; } @@ -5356,7 +5367,7 @@ ACMD(skilltree) { c = pc->calc_skilltree_normalize_job(pl_sd); c = pc->mapid2jobid(c, pl_sd->status.sex); - sprintf(atcmd_output, msg_fd(fd,1168), pc->job_name(c), pc->checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points). + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1168), pc->job_name(c), pc->checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points). clif->message(fd, atcmd_output); ARR_FIND( 0, MAX_SKILL_TREE, j, pc->skill_tree[c][j].id == 0 || pc->skill_tree[c][j].id == skill_id ); @@ -5373,7 +5384,7 @@ ACMD(skilltree) { { if( ent->need[j].id && pc->checkskill(sd,ent->need[j].id) < ent->need[j].lv) { - sprintf(atcmd_output, msg_fd(fd,1170), ent->need[j].lv, skill->db[ent->need[j].id].desc); // Player requires level %d of skill %s. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1170), ent->need[j].lv, skill->dbs->db[ent->need[j].id].desc); // Player requires level %d of skill %s. clif->message(fd, atcmd_output); meets = 0; } @@ -5386,9 +5397,10 @@ ACMD(skilltree) { } // Hand a ring with partners name on it to this char -void getring(struct map_session_data* sd) { +void atcommand_getring(struct map_session_data* sd) { int flag, item_id; struct item item_tmp; + nullpo_retv(sd); item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F; memset(&item_tmp, 0, sizeof(item_tmp)); @@ -5400,7 +5412,7 @@ void getring(struct map_session_data* sd) { 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } @@ -5412,7 +5424,7 @@ ACMD(marry) { struct map_session_data *pl_sd = NULL; char player_name[NAME_LENGTH] = ""; - if (!message || !*message || sscanf(message, "%23s", player_name) != 1) { + if (!*message || sscanf(message, "%23s", player_name) != 1) { clif->message(fd, msg_fd(fd,1172)); // Usage: @marry <char name> return false; } @@ -5425,8 +5437,8 @@ ACMD(marry) { if (pc->marriage(sd, pl_sd) == 0) { clif->message(fd, msg_fd(fd,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); + atcommand->getring(sd); // Auto-give named rings (Aru) + atcommand->getring(pl_sd); return true; } @@ -5441,12 +5453,12 @@ ACMD(marry) { ACMD(divorce) { if (pc->divorce(sd) != 0) { - sprintf(atcmd_output, msg_fd(fd,1175), sd->status.name); // '%s' is not married. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1175), sd->status.name); // '%s' is not married. clif->message(fd, atcmd_output); return false; } - sprintf(atcmd_output, msg_fd(fd,1176), sd->status.name); // '%s' and his/her partner are now divorced. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1176), sd->status.name); // '%s' and his/her partner are now divorced. clif->message(fd, atcmd_output); return true; } @@ -5459,7 +5471,7 @@ ACMD(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 }; - if((i = sscanf(message, "%d %d", &j, &k)) < 1) { + if((i = sscanf(message, "%12d %12d", &j, &k)) < 1) { clif->message(fd, msg_fd(fd,1177)); // Usage: @changelook {<position>} <view id> clif->message(fd, msg_fd(fd,1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe return false; @@ -5536,17 +5548,17 @@ ACMD(changegm) { return false; } - if( map->list[sd->bl.m].flag.guildlock || map->list[sd->bl.m].flag.gvg_castle ) { + if (map->list[sd->bl.m].flag.guildlock || map->list[sd->bl.m].flag.gvg_castle) { clif->message(fd, msg_fd(fd,1182)); // You cannot change guild leaders in this map. return false; } - if( !message[0] ) { + if (!message[0]) { clif->message(fd, msg_fd(fd,1183)); // Usage: @changegm <guild_member_name> return false; } - if((pl_sd=map->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { + if ((pl_sd=map->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { clif->message(fd, msg_fd(fd,1184)); // Target character must be online and be a guild member. return false; } @@ -5561,7 +5573,7 @@ ACMD(changegm) { *------------------------------------------*/ ACMD(changeleader) { - if( !message[0] ) { + if (!message[0]) { clif->message(fd, msg_fd(fd,1185)); // Usage: @changeleader <party_member_name> return false; } @@ -5587,7 +5599,7 @@ ACMD(partyoption) return false; } - ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd ); + ARR_FIND(0, MAX_PARTY, mi, p->data[mi].sd == sd); if (mi == MAX_PARTY) return false; //Shouldn't happen @@ -5597,13 +5609,13 @@ ACMD(partyoption) return false; } - if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) + if (!*message || sscanf(message, "%15s %15s", w1, w2) < 2) { clif->message(fd, msg_fd(fd,1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no> return false; } - option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); + option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); // TODO: Add documentation for these values //Change item share type. if (option != p->party.item) @@ -5623,7 +5635,7 @@ ACMD(autoloot) int rate; // autoloot command without value - if(!message || !*message) + if (!*message) { if (sd->state.autoloot) rate = 0; @@ -5656,7 +5668,7 @@ ACMD(autolootitem) int i; int action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset - if (message && *message) { + if (*message) { if (message[0] == '+') { message++; action = 1; @@ -5680,7 +5692,7 @@ ACMD(autolootitem) } } - switch(action) { + switch (action) { case 1: ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); if (i != AUTOLOOTITEM_SIZE) { @@ -5693,7 +5705,7 @@ ACMD(autolootitem) return false; } sd->state.autolootid[i] = item_data->nameid; // Autoloot Activated - sprintf(atcmd_output, msg_fd(fd,1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} clif->message(fd, atcmd_output); sd->state.autolooting = 1; break; @@ -5704,7 +5716,7 @@ ACMD(autolootitem) return false; } sd->state.autolootid[i] = 0; - sprintf(atcmd_output, msg_fd(fd,1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. clif->message(fd, atcmd_output); ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); if (i == AUTOLOOTITEM_SIZE) { @@ -5712,7 +5724,7 @@ ACMD(autolootitem) } break; case 3: - sprintf(atcmd_output, msg_fd(fd,1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,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->message(fd, msg_fd(fd,1197)); // "@alootid reset" will clear your autolootitem list. @@ -5729,7 +5741,7 @@ ACMD(autolootitem) 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); + safesnprintf(atcmd_output, sizeof(atcmd_output), "'%s'/'%s' {%d}", item_data->name, item_data->jname, item_data->nameid); clif->message(fd, atcmd_output); } } @@ -5753,7 +5765,7 @@ ACMD(autoloottype) { enum item_types type = -1; int ITEM_NONE = 0; - if (message && *message) { + if (*message) { if (message[0] == '+') { message++; action = 1; @@ -5798,7 +5810,7 @@ ACMD(autoloottype) { return false; } sd->state.autoloottype |= (1<<type); // Stores the type - sprintf(atcmd_output, msg_fd(fd,1492), itemdb->typename(type)); // Autolooting item type: '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1492), itemdb->typename(type)); // Autolooting item type: '%s' clif->message(fd, atcmd_output); break; case 2: @@ -5807,7 +5819,7 @@ ACMD(autoloottype) { return false; } sd->state.autoloottype &= ~(1<<type); - sprintf(atcmd_output, msg_fd(fd,1494), itemdb->typename(type)); // Removed item type: '%s' from your autoloottype list. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1494), itemdb->typename(type)); // Removed item type: '%s' from your autoloottype list. clif->message(fd, atcmd_output); break; case 3: @@ -5826,7 +5838,7 @@ ACMD(autoloottype) { clif->message(fd, msg_fd(fd,1496)); // Item types on your autoloottype list: for(i=0; i < IT_MAX; i++) { if (sd->state.autoloottype&(1<<i)) { - sprintf(atcmd_output, " '%s'", itemdb->typename(i)); + safesnprintf(atcmd_output, sizeof(atcmd_output), " '%s'", itemdb->typename(i)); clif->message(fd, atcmd_output); } } @@ -5991,7 +6003,7 @@ ACMD(sound) memset(sound_file, '\0', sizeof(sound_file)); - if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { + if(!*message || sscanf(message, "%99[^\n]", sound_file) < 1) { clif->message(fd, msg_fd(fd,1217)); // Please enter a sound filename (usage: @sound <filename>). return false; } @@ -6014,7 +6026,7 @@ ACMD(mobsearch) int number = 0; struct s_mapiterator* it; - if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) { + if (!*message || sscanf(message, "%99[^\n]", mob_name) < 1) { clif->message(fd, msg_fd(fd,1218)); // Please enter a monster name (usage: @mobsearch <monster name>). return false; } @@ -6075,14 +6087,14 @@ ACMD(cleanmap) { } ACMD(cleanarea) { - int x0 = 0, y0 = 0, x1 = 0, y1 = 0; + int x0 = 0, y0 = 0, x1 = 0, y1 = 0, n = 0; - if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) { + if (!*message || (n=sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1)) < 1) { map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, AREA_SIZE * 2, BL_ITEM); - } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) { - map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, x0, BL_ITEM); - } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) { + } else if (n == 4) { map->foreachinarea(atcommand->cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM); + } else { + map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, x0, BL_ITEM); } clif->message(fd, msg_fd(fd,1221)); // All dropped items have been cleaned up. @@ -6106,13 +6118,13 @@ ACMD(npctalk) return false; if(!ifcolor) { - if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { + if (!*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { clif->message(fd, msg_fd(fd,1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>). return false; } } else { - if (!message || !*message || sscanf(message, "%u %23[^,], %99[^\n]", &color, name, mes) < 3) { + if (!*message || sscanf(message, "%12u %23[^,], %99[^\n]", &color, name, mes) < 3) { clif->message(fd, msg_fd(fd,1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>). return false; } @@ -6137,13 +6149,13 @@ ACMD(pettalk) char mes[100],temp[100]; struct pet_data *pd; - if ( battle_config.min_chat_delay ) { + if (battle_config.min_chat_delay) { if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 ) return true; sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } - if(!sd->status.pet_id || !(pd=sd->pd)) + if (!sd->status.pet_id || !(pd=sd->pd)) { clif->message(fd, msg_fd(fd,184)); return false; @@ -6154,13 +6166,13 @@ ACMD(pettalk) (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; - if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { + if (!*message || sscanf(message, "%99[^\n]", mes) < 1) { clif->message(fd, msg_fd(fd,1224)); // Please enter a message (usage: @pettalk <message>). return false; } if (message[0] == '/') - {// pet emotion processing + { // pet emotion processing const char* emo[] = { "/!", "/?", "/ho", "/lv", "/swt", "/ic", "/an", "/ag", "/$", "/...", "/scissors", "/rock", "/paper", "/korea", "/lv2", "/thx", "/wah", "/sry", "/heh", "/swt2", @@ -6244,11 +6256,10 @@ ACMD(users) /*========================================== * *------------------------------------------*/ -ACMD(reset) -{ +ACMD(reset) { pc->resetstate(sd); - pc->resetskill(sd,1); - sprintf(atcmd_output, msg_fd(fd,208), sd->status.name); // '%s' skill and stats points reseted! + pc->resetskill(sd, PCRESETSKILL_RESYNC); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,208), sd->status.name); // '%s' skill and stats points reseted! clif->message(fd, atcmd_output); return true; } @@ -6264,7 +6275,7 @@ ACMD(summon) struct mob_data *md; int64 tick=timer->gettick(); - if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) + if (!*message || sscanf(message, "%23s %12d", name, &duration) < 1) { clif->message(fd, msg_fd(fd,1225)); // Please enter a monster name (usage: @summon <monster name> {duration}). return false; @@ -6288,9 +6299,9 @@ ACMD(summon) if(!md) return false; - md->master_id=sd->bl.id; - md->special_state.ai=1; - md->deletetimer=timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0); + md->master_id = sd->bl.id; + md->special_state.ai = AI_ATTACK; + md->deletetimer = timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0); clif->specialeffect(&md->bl,344,AREA); mob->spawn(md); sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); @@ -6309,7 +6320,7 @@ ACMD(adjgroup) { int new_group = 0; - if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { + if (!*message || sscanf(message, "%12d", &new_group) != 1) { clif->message(fd, msg_fd(fd,1226)); // Usage: @adjgroup <group_id> return false; } @@ -6331,7 +6342,7 @@ ACMD(adjgroup) ACMD(trade) { struct map_session_data *pl_sd = NULL; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1230)); // Please enter a player name (usage: @trade <char name>). return false; } @@ -6353,7 +6364,7 @@ ACMD(setbattleflag) { char flag[128], value[128]; - if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) { + if (!*message || sscanf(message, "%127s %127s", flag, value) != 2) { clif->message(fd, msg_fd(fd,1231)); // Usage: @setbattleflag <flag> <value> return false; } @@ -6374,18 +6385,18 @@ ACMD(setbattleflag) ACMD(unmute) { struct map_session_data *pl_sd = NULL; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1234)); // Please enter a player name (usage: @unmute <char name>). return false; } - if ( (pl_sd = map->nick2sd((char *)message)) == NULL ) + if ((pl_sd = map->nick2sd((char *)message)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } - if(!pl_sd->sc.data[SC_NOCHAT]) { + if (!pl_sd->sc.data[SC_NOCHAT]) { clif->message(sd->fd,msg_fd(fd,1235)); // Player is not muted. return false; } @@ -6423,14 +6434,13 @@ ACMD(uptime) * @changesex <sex> * => Changes one's sex. Argument sex can be 0 or 1, m or f, male or female. *------------------------------------------*/ -ACMD(changesex) -{ +ACMD(changesex) { int i; - pc->resetskill(sd,4); + pc->resetskill(sd, PCRESETSKILL_CHSEX); // to avoid any problem with equipment and invalid sex, equipment is unequipped. - for( i=0; i<EQI_MAX; i++ ) - if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3); + for (i=0; i<EQI_MAX; i++) + if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); chrif->changesex(sd, true); return true; } @@ -6442,17 +6452,17 @@ ACMD(mute) { struct map_session_data *pl_sd = NULL; int manner; - if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) { + if (!*message || sscanf(message, "%12d %23[^\n]", &manner, atcmd_player_name) < 1) { clif->message(fd, msg_fd(fd,1237)); // Usage: @mute <time> <char name> return false; } - if ( (pl_sd = map->nick2sd(atcmd_player_name)) == NULL ) { + if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } - if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { clif->message(fd, msg_fd(fd,81)); // Your GM level don't authorize you to do this action on this player. return false; @@ -6461,7 +6471,7 @@ ACMD(mute) { clif->manner_message(sd, 0); clif->manner_message(pl_sd, 5); - if( pl_sd->status.manner < manner ) { + if (pl_sd->status.manner < manner) { pl_sd->status.manner -= manner; sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0); } else { @@ -6503,7 +6513,7 @@ ACMD(identify) { int i,num; - for(i=num=0;i<MAX_INVENTORY;i++){ + for (i=num=0;i<MAX_INVENTORY;i++) { if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){ num++; } @@ -6519,9 +6529,9 @@ ACMD(identify) ACMD(misceffect) { int effect = 0; - if (!message || !*message) + if (!*message) return false; - if (sscanf(message, "%d", &effect) < 1) + if (sscanf(message, "%12d", &effect) < 1) return false; clif->misceffect(&sd->bl,effect); @@ -6555,7 +6565,7 @@ ACMD(mobinfo) memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_output2, '\0', sizeof(atcmd_output2)); - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>). return false; } @@ -6573,7 +6583,7 @@ ACMD(mobinfo) } if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_fd(fd,269), MAX_SEARCH, count); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, count); clif->message(fd, atcmd_output); count = MAX_SEARCH; } @@ -6596,27 +6606,26 @@ ACMD(mobinfo) // stats if (monster->mexp) - sprintf(atcmd_output, msg_fd(fd,1240), monster->name, monster->jname, monster->sprite, monster->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1240), monster->name, monster->jname, monster->sprite, monster->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d) else - sprintf(atcmd_output, msg_fd(fd,1241), monster->name, monster->jname, monster->sprite, monster->vd.class_); // Monster: '%s'/'%s'/'%s' (%d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1241), monster->name, monster->jname, monster->sprite, monster->vd.class_); // Monster: '%s'/'%s'/'%s' (%d) clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1242), monster->lv, monster->status.max_hp, base_exp, job_exp, MOB_HIT(monster), MOB_FLEE(monster)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1242), monster->lv, monster->status.max_hp, base_exp, job_exp, MOB_HIT(monster), MOB_FLEE(monster)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d monster->status.def, monster->status.mdef, monster->status.str, monster->status.agi, monster->status.vit, monster->status.int_, monster->status.dex, monster->status.luk); clif->message(fd, atcmd_output); - #ifdef RENEWAL - sprintf(atcmd_output, msg_fd(fd,1291), // ATK : %d~%d MATK : %d~%d Range : %d~%d~%d Size : %s Race : %s Element : %s(Lv : %d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1291), // ATK : %d~%d MATK : %d~%d Range : %d~%d~%d Size : %s Race : %s Element : %s(Lv : %d) MOB_ATK1(monster), MOB_ATK2(monster), MOB_MATK1(monster), MOB_MATK2(monster), monster->status.rhw.range, monster->range2 , monster->range3, msize[monster->status.size], mrace[monster->status.race], melement[monster->status.def_ele], monster->status.ele_lv); #else - sprintf(atcmd_output, msg_fd(fd,1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) monster->status.rhw.atk, monster->status.rhw.atk2, monster->status.rhw.range, monster->range2 , monster->range3, msize[monster->status.size], mrace[monster->status.race], melement[monster->status.def_ele], monster->status.ele_lv); @@ -6663,7 +6672,7 @@ ACMD(mobinfo) clif->message(fd, atcmd_output); // mvp if (monster->mexp) { - sprintf(atcmd_output, msg_fd(fd,1247), monster->mexp); // MVP Bonus EXP:%u + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1247), monster->mexp); // MVP Bonus EXP:%u clif->message(fd, atcmd_output); safestrncpy(atcmd_output, msg_fd(fd,1248), sizeof(atcmd_output)); // MVP Items: @@ -6700,7 +6709,7 @@ ACMD(showmobs) int number = 0; struct s_mapiterator* it; - if( sscanf(message, "%99[^\n]", mob_name) < 0 ) { + if (sscanf(message, "%99[^\n]", mob_name) < 0) { clif->message(fd, msg_fd(fd,546)); // Please enter a mob name/id (usage: @showmobs <mob name/id>) return false; } @@ -6745,7 +6754,7 @@ ACMD(showmobs) continue; if( mob_id != -1 && md->class_ != mob_id ) continue; - if( md->special_state.ai || md->master_id ) + if (md->special_state.ai != AI_NONE || md->master_id) continue; // hide slaves and player summoned mobs if( md->spawn_timer != INVALID_TIMER ) continue; // hide mobs waiting for respawn @@ -6766,19 +6775,19 @@ ACMD(homlevel) { int level = 0; enum homun_type htype; - if( !message || !*message || ( level = atoi(message) ) < 1 ) { + if (!*message || ( level = atoi(message) ) < 1) { clif->message(fd, msg_fd(fd,1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). return false; } - if( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } hd = sd->hd; - if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) { + if ((htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID) { ShowError("atcommand_homlevel: invalid homun class %d (player %s)\n", hd->homunculus.class_,sd->status.name); return false; } @@ -6836,12 +6845,12 @@ ACMD(hommutate) { int homun_id; enum homun_type m_class, m_id; - if( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } - if( !message || !*message ) { + if (!*message) { homun_id = 6048 + (rnd() % 4); } else { homun_id = atoi(message); @@ -6864,15 +6873,15 @@ ACMD(hommutate) { ACMD(makehomun) { int homunid; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). return false; } homunid = atoi(message); - if( homunid == -1 && sd->status.hom_id && !(sd->hd && homun_alive(sd->hd)) ) { - if( !sd->hd ) + if (homunid == -1 && sd->status.hom_id && !(sd->hd && homun_alive(sd->hd))) { + if (!sd->hd) homun->call(sd); else if( sd->hd->homunculus.vaporize ) homun->ressurect(sd, 100, sd->bl.x, sd->bl.y); @@ -6881,12 +6890,12 @@ ACMD(makehomun) { return true; } - if ( sd->status.hom_id ) { + if (sd->status.hom_id) { clif->message(fd, msg_fd(fd,450)); return false; } - if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 ) + if (homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1) { clif->message(fd, msg_fd(fd,1257)); // Invalid Homunculus ID. return false; @@ -6903,12 +6912,12 @@ ACMD(homfriendly) { int friendly = 0; - if ( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>). return false; } @@ -6928,12 +6937,12 @@ ACMD(homhungry) { int hungry = 0; - if ( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>). return false; } @@ -6953,8 +6962,8 @@ ACMD(homtalk) { char mes[100],temp[100]; - if ( battle_config.min_chat_delay ) { - if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 ) + if (battle_config.min_chat_delay) { + if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) return true; sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } @@ -6964,12 +6973,12 @@ ACMD(homtalk) (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; - if ( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } - if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { + if (!*message || sscanf(message, "%99[^\n]", mes) < 1) { clif->message(fd, msg_fd(fd,1260)); // Please enter a message (usage: @homtalk <message>). return false; } @@ -6987,7 +6996,7 @@ ACMD(hominfo) { struct homun_data *hd; struct status_data *st; - if ( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } @@ -7024,7 +7033,7 @@ ACMD(homstats) struct s_homunculus *hom; int lv, min, max, evo; - if ( !homun_alive(sd->hd) ) { + if (!homun_alive(sd->hd)) { clif->message(fd, msg_fd(fd,1254)); // You do not have a homunculus. return false; } @@ -7086,10 +7095,10 @@ ACMD(homstats) ACMD(homshuffle) { - if(!sd->hd) + if (!sd->hd) return false; // nothing to do - if(!homun->shuffle(sd->hd)) + if (!homun->shuffle(sd->hd)) return false; clif->message(sd->fd, msg_fd(fd,1275)); // Homunculus stats altered. @@ -7106,7 +7115,7 @@ ACMD(iteminfo) struct item_data *item_array[MAX_SEARCH]; int i, count = 1; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>). return false; } @@ -7119,27 +7128,27 @@ ACMD(iteminfo) } if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_fd(fd,269), MAX_SEARCH, count); // Displaying first %d out of %d matches + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, count); // Displaying first %d out of %d matches clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (i = 0; i < count; i++) { struct item_data *item_data = item_array[i]; - sprintf(atcmd_output, msg_fd(fd,1277), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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_fd(fd,1278) : msg_fd(fd,1279) // None / With script ); clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f clif->message(fd, atcmd_output); if (item_data->maxchance == -1) safestrncpy(atcmd_output, msg_fd(fd,1281), sizeof(atcmd_output)); // - Available in the shops only. else if ( !battle_config.atcommand_mobinfo_type ) { if( item_data->maxchance ) - sprintf(atcmd_output, msg_fd(fd,1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%% + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%% else safestrncpy(atcmd_output, msg_fd(fd,1283), sizeof(atcmd_output)); // - Monsters don't drop this item. } @@ -7157,7 +7166,7 @@ ACMD(whodrops) struct item_data *item_array[MAX_SEARCH]; int i,j, count = 1; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>). return false; } @@ -7170,25 +7179,25 @@ ACMD(whodrops) } if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_fd(fd,269), MAX_SEARCH, count); // Displaying first %d out of %d matches + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, count); // Displaying first %d out of %d matches clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (i = 0; i < count; i++) { struct item_data *item_data = item_array[i]; - sprintf(atcmd_output, msg_fd(fd,1285), item_data->jname,item_data->slot); // Item: '%s'[%d] + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1285), item_data->jname,item_data->slot); // Item: '%s'[%d] clif->message(fd, atcmd_output); if (item_data->mob[0].chance == 0) { safestrncpy(atcmd_output, msg_fd(fd,1286), sizeof(atcmd_output)); // - Item is not dropped by mobs. clif->message(fd, atcmd_output); } else { - sprintf(atcmd_output, msg_fd(fd,1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed): + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed): clif->message(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.); + safesnprintf(atcmd_output, sizeof(atcmd_output), "- %s (%02.02f%%)", mob->db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.); clif->message(fd, atcmd_output); } } @@ -7202,7 +7211,7 @@ ACMD(whereis) int count; int i, j, k; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>). return false; } @@ -7221,7 +7230,7 @@ ACMD(whereis) } if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_fd(fd,269), MAX_SEARCH, count); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, count); clif->message(fd, atcmd_output); count = MAX_SEARCH; } @@ -7244,9 +7253,9 @@ ACMD(whereis) } ACMD(version) { - sprintf(atcmd_output, msg_fd(fd,1296), sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); // Hercules %d-bit for %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1296), sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); // Hercules %d-bit for %s clif->message(fd, atcmd_output); - sprintf(atcmd_output, msg_fd(fd,1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts) clif->message(fd, atcmd_output); return true; @@ -7255,7 +7264,7 @@ ACMD(version) { /*========================================== * @mutearea by MouseJstr *------------------------------------------*/ -int atcommand_mutearea_sub(struct block_list *bl,va_list ap) +int atcommand_mutearea_sub(struct block_list *bl, va_list ap) { // As it is being used [ACMD(mutearea)] there's no need to be a bool, but if there's need to reuse it, it's better to be this way int time, id; @@ -7279,7 +7288,7 @@ int atcommand_mutearea_sub(struct block_list *bl,va_list ap) ACMD(mutearea) { int time; - if (!message || !*message) { + if (!*message) { clif->message(fd, msg_fd(fd,1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). return false; } @@ -7293,23 +7302,22 @@ ACMD(mutearea) { return true; } - ACMD(rates) { char buf[CHAT_SIZE_MAX]; memset(buf, '\0', sizeof(buf)); - snprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,1298), // Experience rates: Base %.2fx / Job %.2fx + safesnprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,1298), // Experience rates: Base %.2fx / Job %.2fx battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.); clif->message(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,1299), // Normal Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx + safesnprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,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->message(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,1300), // Boss Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx + safesnprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,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->message(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx + safesnprintf(buf, CHAT_SIZE_MAX, msg_fd(fd,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->message(fd, buf); @@ -7332,12 +7340,12 @@ ACMD(me) (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; - if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) { + if (!*message || sscanf(message, "%199[^\n]", tempmes) < 0) { clif->message(fd, msg_fd(fd,1302)); // Please enter a message (usage: @me <message>). return false; } - sprintf(atcmd_output, msg_fd(fd,270), sd->status.name, tempmes); // *%s %s* + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,270), sd->status.name, tempmes); // *%s %s* clif->disp_overhead(&sd->bl, atcmd_output); return true; @@ -7378,17 +7386,17 @@ ACMD(sizeall) 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 ) { + 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 ) + if (size == SZ_MEDIUM) clif->specialeffect(&pl_sd->bl,420,AREA); - else if( size == SZ_BIG ) + else if (size == SZ_BIG) clif->specialeffect(&pl_sd->bl,422,AREA); } } @@ -7407,20 +7415,20 @@ ACMD(sizeguild) memset(guild_name, '\0', sizeof(guild_name)); - if( !message || !*message || sscanf(message, "%d %23[^\n]", &size, guild_name) < 2 ) { + if (!*message || sscanf(message, "%d %23[^\n]", &size, guild_name) < 2) { clif->message(fd, msg_fd(fd,1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>). return false; } - if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL ) { + if ((g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL) { clif->message(fd, msg_fd(fd,94)); // Incorrect name/ID, or no one from the guild is online. return false; } 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 ) { + 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); @@ -7460,9 +7468,9 @@ ACMD(monsterignore) *------------------------------------------*/ ACMD(fakename) { - if( !message || !*message ) + if (!*message) { - if( sd->fakename[0] ) + if (sd->fakename[0]) { sd->fakename[0] = '\0'; clif->charnameack(0, &sd->bl); @@ -7476,7 +7484,7 @@ ACMD(fakename) return false; } - if( strlen(message) < 2 ) + if (strlen(message) < 2) { clif->message(sd->fd, msg_fd(fd,1309)); // Fake name must be at least two characters. return false; @@ -7484,7 +7492,7 @@ ACMD(fakename) safestrncpy(sd->fakename, message, sizeof(sd->fakename)); clif->charnameack(0, &sd->bl); - if( sd->disguise ) // Another packet should be sent so the client updates the name for sd + if (sd->disguise) // Another packet should be sent so the client updates the name for sd clif->charnameack(sd->fd, &sd->bl); clif->message(sd->fd, msg_fd(fd,1310)); // Fake name enabled. @@ -7495,11 +7503,11 @@ ACMD(fakename) * Ragnarok Resources *------------------------------------------*/ ACMD(mapflag) { -#define CHECKFLAG( cmd ) do { if ( map->list[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd); } while(0) +#define CHECKFLAG( cmd ) do { if (map->list[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd);} while(0) #define SETFLAG( cmd ) do { \ - if ( strcmp( flag_name , #cmd ) == 0 ) { \ + if (strcmp( flag_name , #cmd ) == 0) { \ map->list[ sd->bl.m ].flag.cmd = flag; \ - sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag); \ + safesnprintf(atcmd_output, sizeof(atcmd_output),"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag); \ clif->message(sd->fd,atcmd_output); \ return true; \ } \ @@ -7510,7 +7518,7 @@ ACMD(mapflag) { memset(flag_name, '\0', sizeof(flag_name)); - if (!message || !*message || (sscanf(message, "%99s %hd", flag_name, &flag) < 1)) { + if (!*message || (sscanf(message, "%99s %5hd", flag_name, &flag) < 1)) { clif->message(sd->fd,msg_fd(fd,1311)); // Enabled Mapflags in this map: clif->message(sd->fd,"----------------------------------"); CHECKFLAG(autotrade); CHECKFLAG(allowks); CHECKFLAG(nomemo); CHECKFLAG(noteleport); @@ -7533,18 +7541,18 @@ ACMD(mapflag) { } for (i = 0; flag_name[i]; i++) flag_name[i] = TOLOWER(flag_name[i]); //lowercase - if ( strcmp( flag_name , "gvg" ) == 0 ) { + if (strcmp( flag_name , "gvg" ) == 0) { if( flag && !map->list[sd->bl.m].flag.gvg ) map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)); else if ( !flag && map->list[sd->bl.m].flag.gvg ) map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone); } else if ( strcmp( flag_name , "pvp" ) == 0 ) { - if( flag && !map->list[sd->bl.m].flag.pvp ) + if ( flag && !map->list[sd->bl.m].flag.pvp ) map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)); else if ( !flag && map->list[sd->bl.m].flag.pvp ) map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone); } else if ( strcmp( flag_name , "battleground" ) == 0 ) { - if( flag && !map->list[sd->bl.m].flag.battleground ) + if ( flag && !map->list[sd->bl.m].flag.battleground ) map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_BG_NAME)); else if ( !flag && map->list[sd->bl.m].flag.battleground ) map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone); @@ -7636,36 +7644,36 @@ ACMD(invite) { unsigned int did = sd->duel_group; struct map_session_data *target_sd = map->nick2sd((char *)message); - if(did == 0) + if (did == 0) { // "Duel: @invite without @duel." clif->message(fd, msg_fd(fd,350)); return false; } - 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->message(fd, msg_fd(fd,351)); return false; } - if(target_sd == NULL) { + if (target_sd == NULL) { // "Duel: Player not found." clif->message(fd, msg_fd(fd,352)); return false; } - if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { + if (target_sd->duel_group > 0 || target_sd->duel_invite > 0) { // "Duel: Player already in duel." clif->message(fd, msg_fd(fd,353)); return false; } - if(battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m) + if (battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m) { // "Duel: You can't invite %s because he/she isn't in the same map." - sprintf(atcmd_output, msg_fd(fd,364), message); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,364), message); clif->message(fd, atcmd_output); return false; } @@ -7679,18 +7687,18 @@ ACMD(invite) { ACMD(duel) { unsigned int maxpl = 0; - if(sd->duel_group > 0) { + if (sd->duel_group > 0) { duel->showinfo(sd->duel_group, sd); return true; } - if(sd->duel_invite > 0) { + if (sd->duel_invite > 0) { // "Duel: @duel without @reject." clif->message(fd, msg_fd(fd,355)); return false; } - if(!duel->checktime(sd)) { + if (!duel->checktime(sd)) { char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_fd(fd,356), battle_config.duel_time_interval); @@ -7698,9 +7706,9 @@ ACMD(duel) { return false; } - if( message[0] ) { - if(sscanf(message, "%u", &maxpl) >= 1) { - if(maxpl < 2 || maxpl > 65535) { + if (message[0]) { + if (sscanf(message, "%12u", &maxpl) >= 1) { + if (maxpl < 2 || maxpl > 65535) { clif->message(fd, msg_fd(fd,357)); // "Duel: Invalid value." return false; } @@ -7708,10 +7716,10 @@ ACMD(duel) { } else { struct map_session_data *target_sd; target_sd = map->nick2sd((char *)message); - if(target_sd != NULL) { + if (target_sd != NULL) { unsigned int newduel; - if((newduel = duel->create(sd, 2)) != -1) { - if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { + if ((newduel = duel->create(sd, 2)) != -1) { + if (target_sd->duel_group > 0 || target_sd->duel_invite > 0) { clif->message(fd, msg_fd(fd,353)); // "Duel: Player already in duel." return false; } @@ -7730,9 +7738,8 @@ ACMD(duel) { return true; } - ACMD(leave) { - if(sd->duel_group <= 0) { + if (sd->duel_group <= 0) { // "Duel: @leave without @duel." clif->message(fd, msg_fd(fd,358)); return false; @@ -7743,7 +7750,7 @@ ACMD(leave) { } ACMD(accept) { - if(!duel->checktime(sd)) { + if (!duel->checktime(sd)) { char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_fd(fd,356), battle_config.duel_time_interval); @@ -7751,14 +7758,14 @@ ACMD(accept) { return false; } - if(sd->duel_invite <= 0) { + if (sd->duel_invite <= 0) { // "Duel: @accept without invitation." clif->message(fd, msg_fd(fd,360)); return false; } - 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 ) { + 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->message(fd, msg_fd(fd,351)); return false; @@ -7771,7 +7778,7 @@ ACMD(accept) { } ACMD(reject) { - if(sd->duel_invite <= 0) { + if (sd->duel_invite <= 0) { // "Duel: @reject without invitation." clif->message(fd, msg_fd(fd,362)); return false; @@ -7792,25 +7799,27 @@ ACMD(cash) int value; int ret=0; - if( !message || !*message || (value = atoi(message)) == 0 ) { + if (!*message || (value = atoi(message)) == 0) { clif->message(fd, msg_fd(fd,1322)); // Please enter an amount. return false; } - if( !strcmpi(info->command,"cash") ) { + if (!strcmpi(info->command,"cash")) { if( value > 0 ) { if( (ret=pc->getcash(sd, value, 0)) >= 0){ // If this option is set, the message is already sent by pc function if( !battle_config.cashshop_show_points ){ sprintf(output, msg_fd(fd,505), ret, sd->cashPoints); clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } } else clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, 0)) >= 0){ sprintf(output, msg_fd(fd,410), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } else clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value. } @@ -7821,13 +7830,15 @@ ACMD(cash) if( !battle_config.cashshop_show_points ){ sprintf(output, msg_fd(fd,506), ret, sd->kafraPoints); clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } } else clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, -value)) >= 0){ sprintf(output, msg_fd(fd,411), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } else clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value. } @@ -7841,17 +7852,17 @@ ACMD(clone) { int x=0,y=0,flag=0,master=0,i=0; struct map_session_data *pl_sd=NULL; - if (!message || !*message) { + if (!*message) { clif->message(sd->fd,msg_fd(fd,1323)); // You must enter a player name or ID. return false; } - if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { + if ((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } - if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { clif->message(fd, msg_fd(fd,126)); // Cannot clone a player of higher GM level than yourself. return false; } @@ -7860,7 +7871,7 @@ ACMD(clone) { flag = 1; else if (strcmpi(info->command, "slaveclone") == 0) { flag = 2; - if(pc_isdead(sd)){ + if (pc_isdead(sd)){ //"Unable to spawn slave clone." clif->message(fd, msg_fd(fd,129+flag*2)); return false; @@ -7876,14 +7887,14 @@ ACMD(clone) { 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); + } while (map->getcell(sd->bl.m, &sd->bl, 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) { + if ((x = mob->clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) { clif->message(fd, msg_fd(fd,128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. return true; } @@ -7897,7 +7908,7 @@ ACMD(clone) { *-------------------------------------*/ ACMD(noask) { - if(sd->state.noask) { + if (sd->state.noask) { clif->message(fd, msg_fd(fd,391)); // Autorejecting is deactivated. sd->state.noask = 0; } else { @@ -7914,12 +7925,12 @@ ACMD(noask) *-------------------------------------*/ ACMD(request) { - if (!message || !*message) { + if (!*message) { clif->message(sd->fd,msg_fd(fd,277)); // Usage: @request <petition/message to online GMs>. return false; } - sprintf(atcmd_output, msg_fd(fd,278), message); // (@request): %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,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->message(sd->fd,msg_fd(fd,279)); // @request sent. @@ -7940,10 +7951,10 @@ ACMD(feelreset) /*========================================== * AUCTION SYSTEM *------------------------------------------*/ -ACMD(auction) { - - if( !battle_config.feature_auction ) { - clif->colormes(sd->fd,COLOR_RED,msg_fd(fd,1484)); +ACMD(auction) +{ + if (!battle_config.feature_auction) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_fd(fd,1484)); return false; } @@ -7955,31 +7966,22 @@ ACMD(auction) { /*========================================== * Kill Steal Protection *------------------------------------------*/ -ACMD(ksprotection) -{ +ACMD(ksprotection) { if( sd->state.noks ) { - sd->state.noks = 0; + sd->state.noks = KSPROTECT_NONE; clif->message(fd, msg_fd(fd,1325)); // [ K.S Protection Inactive ] - } - else - { - if( !message || !*message || !strcmpi(message, "party") ) - { // Default is Party - sd->state.noks = 2; - clif->message(fd, msg_fd(fd,1326)); // [ K.S Protection Active - Option: Party ] - } - else if( !strcmpi(message, "self") ) - { - sd->state.noks = 1; - clif->message(fd, msg_fd(fd,1327)); // [ K.S Protection Active - Option: Self ] - } - else if( !strcmpi(message, "guild") ) - { - sd->state.noks = 3; - clif->message(fd, msg_fd(fd,1328)); // [ K.S Protection Active - Option: Guild ] - } - else - clif->message(fd, msg_fd(fd,1329)); // Usage: @noks <self|party|guild> + } else if (!*message || strcmpi(message, "party") == 0) { + // Default is Party + sd->state.noks = KSPROTECT_PARTY; + clif->message(fd, msg_fd(fd,1326)); // [ K.S Protection Active - Option: Party ] + } else if( strcmpi(message, "self") == 0 ) { + sd->state.noks = KSPROTECT_SELF; + clif->message(fd, msg_fd(fd,1327)); // [ K.S Protection Active - Option: Self ] + } else if( strcmpi(message, "guild") == 0 ) { + sd->state.noks = KSPROTECT_GUILD; + clif->message(fd, msg_fd(fd,1328)); // [ K.S Protection Active - Option: Guild ] + } else { + clif->message(fd, msg_fd(fd,1329)); // Usage: @noks <self|party|guild> } return true; } @@ -8001,15 +8003,15 @@ ACMD(allowks) ACMD(resetstat) { pc->resetstate(sd); - sprintf(atcmd_output, msg_fd(fd,207), sd->status.name); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,207), sd->status.name); clif->message(fd, atcmd_output); return true; } ACMD(resetskill) { - pc->resetskill(sd,1); - sprintf(atcmd_output, msg_fd(fd,206), sd->status.name); + pc->resetskill(sd, PCRESETSKILL_RESYNC); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,206), sd->status.name); clif->message(fd, atcmd_output); return true; } @@ -8229,13 +8231,13 @@ ACMD(delitem) { int nameid, amount = 0, total, idx; struct item_data* id; - if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 ) + if (!*message || (sscanf(message, "\"%99[^\"]\" %12d", item_name, &amount) < 2 && sscanf(message, "%99s %12d", item_name, &amount) < 2) || amount < 1) { clif->message(fd, msg_fd(fd,1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). return false; } - if( ( id = itemdb->search_name(item_name) ) != NULL || ( id = itemdb->exists(atoi(item_name)) ) != NULL ) + if ((id = itemdb->search_name(item_name)) != NULL || (id = itemdb->exists(atoi(item_name))) != NULL) { nameid = id->nameid; } @@ -8255,13 +8257,13 @@ ACMD(delitem) { {// 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); + pc->delitem(sd, idx, delamount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND); amount-= delamount; } // notify target - sprintf(atcmd_output, msg_fd(fd,113), total-amount); // %d item(s) removed by a GM. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,113), total-amount); // %d item(s) removed by a GM. clif->message(sd->fd, atcmd_output); // notify source @@ -8271,12 +8273,12 @@ ACMD(delitem) { } else if( amount ) { - sprintf(atcmd_output, msg_fd(fd,115), total-amount, total-amount, total); // %d item(s) removed. Player had only %d on %d items. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,115), total-amount, total-amount, total); // %d item(s) removed. Player had only %d on %d items. clif->message(fd, atcmd_output); } else { - sprintf(atcmd_output, msg_fd(fd,114), total); // %d item(s) removed from the player. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,114), total); // %d item(s) removed from the player. clif->message(fd, atcmd_output); } return true; @@ -8368,7 +8370,7 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand dbi_destroy(iter); clif->message(fd,line_buff); - sprintf(atcmd_output, msg_fd(fd,274), count); // "%d commands found." + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,274), count); // "%d commands found." clif->message(fd, atcmd_output); return; @@ -8413,7 +8415,7 @@ ACMD(cashmount) ACMD(accinfo) { char query[NAME_LENGTH]; - if (!message || !*message || strlen(message) > NAME_LENGTH ) { + if (!*message || strlen(message) > NAME_LENGTH ) { clif->message(fd, msg_fd(fd,1365)); // Usage: @accinfo/@accountinfo <account_id/char name> clif->message(fd, msg_fd(fd,1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario". return false; @@ -8434,7 +8436,7 @@ ACMD(set) { bool is_str = false; size_t len; - if( !message || !*message || (toset = sscanf(message, "%31s %128[^\n]s", reg, val)) < 1 ) { + if (!*message || (toset = sscanf(message, "%31s %127[^\n]s", reg, val)) < 1) { clif->message(fd, msg_fd(fd,1367)); // Usage: @set <variable name> <value> clif->message(fd, msg_fd(fd,1368)); // Usage: ex. "@set PoringCharVar 50" clif->message(fd, msg_fd(fd,1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String" @@ -8517,16 +8519,16 @@ ACMD(set) { switch( data->type ) { case C_INT: - sprintf(atcmd_output,msg_fd(fd,1373),reg,data->u.num); // %s value is now :%d + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1373),reg,data->u.num); // %s value is now :%d break; case C_STR: - sprintf(atcmd_output,msg_fd(fd,1374),reg,data->u.str); // %s value is now :%s + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1374),reg,data->u.str); // %s value is now :%s break; case C_CONSTSTR: - sprintf(atcmd_output,msg_fd(fd,1375),reg); // %s is empty + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1375),reg); // %s is empty break; default: - sprintf(atcmd_output,msg_fd(fd,1376),reg,data->type); // %s data type is not supported :%u + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1376),reg,data->type); // %s data type is not supported :%u break; } clif->message(fd, atcmd_output); @@ -8544,12 +8546,12 @@ ACMD(addperm) { bool add = (strcmpi(info->command, "addperm") == 0) ? true : false; int i; - if( !message || !*message ) { - sprintf(atcmd_output, msg_fd(fd,1378),command); // Usage: %s <permission_name> + if (!*message) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1378),command); // Usage: %s <permission_name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { - sprintf(atcmd_output,"- %s",pcg->permissions[i].name); + safesnprintf(atcmd_output, sizeof(atcmd_output),"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } return false; @@ -8557,28 +8559,28 @@ ACMD(addperm) { ARR_FIND(0, perm_size, i, strcmpi(pcg->permissions[i].name, message) == 0); if( i == perm_size ) { - sprintf(atcmd_output,msg_fd(fd,1380),message); // '%s' is not a known permission. + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1380),message); // '%s' is not a known permission. clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { - sprintf(atcmd_output,"- %s",pcg->permissions[i].name); + safesnprintf(atcmd_output, sizeof(atcmd_output),"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } return false; } if( add && (sd->extra_temp_permissions&pcg->permissions[i].permission) ) { - sprintf(atcmd_output, msg_fd(fd,1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission. clif->message(fd, atcmd_output); return false; } else if ( !add && !(sd->extra_temp_permissions&pcg->permissions[i].permission) ) { - sprintf(atcmd_output, msg_fd(fd,1382),sd->status.name,pcg->permissions[i].name); // User '%s' doesn't possess the '%s' permission. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1382),sd->status.name,pcg->permissions[i].name); // User '%s' doesn't possess the '%s' permission. clif->message(fd, atcmd_output); - sprintf(atcmd_output,msg_fd(fd,1383),sd->status.name); // -- User '%s' Permissions + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1383),sd->status.name); // -- User '%s' Permissions clif->message(fd, atcmd_output); for( i = 0; i < perm_size; i++ ) { if( sd->extra_temp_permissions&pcg->permissions[i].permission ) { - sprintf(atcmd_output,"- %s",pcg->permissions[i].name); + safesnprintf(atcmd_output, sizeof(atcmd_output),"- %s",pcg->permissions[i].name); clif->message(fd, atcmd_output); } } @@ -8590,21 +8592,21 @@ ACMD(addperm) { else sd->extra_temp_permissions &=~ pcg->permissions[i].permission; - sprintf(atcmd_output, msg_fd(fd,1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. clif->message(fd, atcmd_output); return true; } ACMD(unloadnpcfile) { - if( !message || !*message ) { + if (!*message) { clif->message(fd, msg_fd(fd,1385)); // Usage: @unloadnpcfile <file name> return false; } - if( npc->unloadfile(message) ) + if (npc->unloadfile(message)) { clif->message(fd, msg_fd(fd,1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. - else { + } else { clif->message(fd, msg_fd(fd,1387)); // File not found. return false; } @@ -8617,14 +8619,12 @@ ACMD(cart) { sd->status.skill[idx].flag = (x)?1:0; \ } while(0) - int val; + int val = atoi(message); bool need_skill = pc->checkskill(sd, MC_PUSHCART) ? false : true; unsigned int index = skill->get_index(MC_PUSHCART); - if (message) - val = atoi(message); - if( !message || !*message || val < 0 || val > MAX_CARTS ) { - sprintf(atcmd_output, msg_fd(fd,1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). + if (!*message || val < 0 || val > MAX_CARTS) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). clif->message(fd, atcmd_output); return false; } @@ -8661,16 +8661,16 @@ ACMD(join) char name[HCS_NAME_LENGTH], pass[HCS_NAME_LENGTH]; enum channel_operation_status ret = HCS_STATUS_OK; - if (!message || !*message || sscanf(message, "%19s %19s", name, pass) < 1) { - sprintf(atcmd_output, msg_fd(fd,1399),command); // Unknown Channel (usage: %s <#channel_name>) + if (!*message || sscanf(message, "%19s %19s", name, pass) < 1) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1399),command); // Unknown Channel (usage: %s <#channel_name>) clif->message(fd, atcmd_output); return false; } chan = channel->search(name, sd); - if(!chan) { - sprintf(atcmd_output, msg_fd(fd,1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>) + if (!chan) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>) clif->message(fd, atcmd_output); return false; } @@ -8678,19 +8678,19 @@ ACMD(join) ret = channel->join(chan, sd, pass, false); if (ret == HCS_STATUS_ALREADY) { - sprintf(atcmd_output, msg_fd(fd,1436),name); // You're already in the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1436),name); // You're already in the '%s' channel clif->message(fd, atcmd_output); return false; } if (ret == HCS_STATUS_NOPERM) { - sprintf(atcmd_output, msg_fd(fd,1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>) clif->message(fd, atcmd_output); return false; } if (ret == HCS_STATUS_BANNED) { - sprintf(atcmd_output, msg_fd(fd,1438),name); // You cannot join the '%s' channel because you've been banned from it + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1438),name); // You cannot join the '%s' channel because you've been banned from it clif->message(fd, atcmd_output); return false; } @@ -8698,51 +8698,52 @@ ACMD(join) return true; } /* [Ind/Hercules] */ -static inline void atcmd_channel_help(int fd, const char *command, bool can_create) { - sprintf(atcmd_output, msg_fd(fd,1404),command); // %s failed. +void atcommand_channel_help(int fd, const char *command, bool can_create) { + nullpo_retv(command); + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1404),command); // %s failed. clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1414));// --- Available options: if( can_create ) { - sprintf(atcmd_output, msg_fd(fd,1415),command);// -- %s create <channel name> <channel password> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1415),command);// -- %s create <channel name> <channel password> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1416));// - creates a new channel } - sprintf(atcmd_output, msg_fd(fd,1417),command);// -- %s list + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1417),command);// -- %s list clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1418));// - lists public channels if( can_create ) { - sprintf(atcmd_output, msg_fd(fd,1419),command);// -- %s list colors + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1419),command);// -- %s list colors clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1420));// - lists colors available to select for custom channels - sprintf(atcmd_output, msg_fd(fd,1421),command);// -- %s setcolor <channel name> <color name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1421),command);// -- %s setcolor <channel name> <color name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1422));// - changes <channel name> color to <color name> } - sprintf(atcmd_output, msg_fd(fd,1423),command);// -- %s leave <channel name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1423),command);// -- %s leave <channel name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1424));// - leaves <channel name> - sprintf(atcmd_output, msg_fd(fd,1427),command);// -- %s bindto <channel name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1427),command);// -- %s bindto <channel name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1428));// - binds global chat to <channel name>, making anything you type in global be sent to the channel - sprintf(atcmd_output, msg_fd(fd,1429),command);// -- %s unbind + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1430));// - unbinds your global chat from its attached channel (if binded) - sprintf(atcmd_output, msg_fd(fd,1429),command);// -- %s unbind + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind clif->message(fd, atcmd_output); if( can_create ) { - sprintf(atcmd_output, msg_fd(fd,1456),command);// -- %s ban <channel name> <character name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1456),command);// -- %s ban <channel name> <character name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1457));// - bans <character name> from <channel name> channel - sprintf(atcmd_output, msg_fd(fd,1458),command);// -- %s banlist <channel name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1458),command);// -- %s banlist <channel name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1459));// - lists all banned characters from <channel name> channel - sprintf(atcmd_output, msg_fd(fd,1460),command);// -- %s unban <channel name> <character name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1460),command);// -- %s unban <channel name> <character name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1461));// - unbans <character name> from <channel name> channel - sprintf(atcmd_output, msg_fd(fd,1467),command);// -- %s unbanall <channel name> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1467),command);// -- %s unbanall <channel name> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1468));// - unbans everyone from <channel name> - sprintf(atcmd_output, msg_fd(fd,1462),command);// -- %s setopt <channel name> <option name> <option value> + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1462),command);// -- %s setopt <channel name> <option name> <option value> clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1463));// - adds or removes <option name> with <option value> to <channel name> channel } @@ -8754,20 +8755,20 @@ ACMD(channel) { unsigned char k = 0; sub1[0] = sub2[0] = sub3[0] = '\0'; - if (!message || !*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) { - atcmd_channel_help(fd,command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); + if (!*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) { + atcommand->channel_help(fd,command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); return true; } if (strcmpi(subcmd,"create") == 0 && (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) { // sub1 = channel name; sub2 = password; sub3 = unused size_t len = strlen(sub1); - const char *pass = *sub2 ? sub2 : NULL; + const char *pass = *sub2 ? sub2 : ""; if (sub1[0] != '#') { clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#' return false; } else if (len < 3 || len > HCS_NAME_LENGTH) { - sprintf(atcmd_output, msg_fd(fd,1406), HCS_NAME_LENGTH);// Channel length must be between 3 and %d + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1406), HCS_NAME_LENGTH);// Channel length must be between 3 and %d clif->message(fd, atcmd_output); return false; } else if (sub3[0] != '\0') { @@ -8775,7 +8776,7 @@ ACMD(channel) { return false; } if (strcmpi(sub1 + 1, channel->config->local_name) == 0 || strcmpi(sub1 + 1, channel->config->ally_name) == 0 || strdb_exists(channel->db, sub1 + 1)) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } @@ -8788,36 +8789,28 @@ ACMD(channel) { } else if (strcmpi(subcmd,"list") == 0) { // sub1 = list type; sub2 = unused; sub3 = unused if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) { - char mout[40]; for (k = 0; k < channel->config->colors_count; k++) { - unsigned short msg_len = 1; - msg_len += sprintf(mout, "[ %s list colors ] : %s", command, channel->config->colors_name[k]); - - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); + safesnprintf(atcmd_output, sizeof(atcmd_output), "[ %s list colors ] : %s", command, channel->config->colors_name[k]); + + clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output); } } else { DBIterator *iter = db_iterator(channel->db); bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false; clif->message(fd, msg_fd(fd,1410)); // -- Public Channels if (channel->config->local) { - sprintf(atcmd_output, msg_fd(fd,1409), channel->config->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users ) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1409), channel->config->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users ) clif->message(fd, atcmd_output); } if (channel->config->ally && sd->status.guild_id) { struct guild *g = sd->guild; if( !g ) { dbi_destroy(iter); return false; } - sprintf(atcmd_output, msg_fd(fd,1409), channel->config->ally_name, db_size(g->channel->users));// - #%s ( %d users ) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1409), channel->config->ally_name, db_size(g->channel->users));// - #%s ( %d users ) clif->message(fd, atcmd_output); } for (chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter)) { if (show_all || chan->type == HCS_TYPE_PUBLIC || chan->type == HCS_TYPE_IRC) { - sprintf(atcmd_output, msg_fd(fd,1409), chan->name, db_size(chan->users));// - #%s ( %d users ) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1409), chan->name, db_size(chan->users));// - #%s ( %d users ) clif->message(fd, atcmd_output); } } @@ -8831,13 +8824,13 @@ ACMD(channel) { } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } @@ -8847,12 +8840,12 @@ ACMD(channel) { break; } if (k == channel->config->colors_count) { - sprintf(atcmd_output, msg_fd(fd,1411), sub2);// Unknown color '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1411), sub2);// Unknown color '%s' clif->message(fd, atcmd_output); return false; } chan->color = k; - sprintf(atcmd_output, msg_fd(fd,1413), sub1, channel->config->colors_name[k]);// '%s' channel color updated to '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1413), sub1, channel->config->colors_name[k]);// '%s' channel color updated to '%s' clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"leave") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused @@ -8865,7 +8858,7 @@ ACMD(channel) { break; } if (k == sd->channel_count) { - sprintf(atcmd_output, msg_fd(fd,1425),sub1);// You're not part of the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel clif->message(fd, atcmd_output); return false; } @@ -8881,7 +8874,7 @@ ACMD(channel) { } else { channel->leave(sd->channels[k],sd); } - sprintf(atcmd_output, msg_fd(fd,1426),sub1); // You've left the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1426),sub1); // You've left the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"bindto") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused @@ -8895,13 +8888,13 @@ ACMD(channel) { break; } if (k == sd->channel_count) { - sprintf(atcmd_output, msg_fd(fd,1425),sub1);// You're not part of the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel clif->message(fd, atcmd_output); return false; } sd->gcbind = sd->channels[k]; - sprintf(atcmd_output, msg_fd(fd,1431),sub1); // Your global chat is now bound to the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1431),sub1); // Your global chat is now bound to the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"unbind") == 0) { // sub1 = unused; sub2 = unused; sub3 = unused @@ -8910,7 +8903,7 @@ ACMD(channel) { return false; } - sprintf(atcmd_output, msg_fd(fd,1433),sd->gcbind->name); // Your global chat is no longer bound to the '#%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1433),sd->gcbind->name); // Your global chat is no longer bound to the '#%s' channel clif->message(fd, atcmd_output); sd->gcbind = NULL; @@ -8926,19 +8919,19 @@ ACMD(channel) { } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { - sprintf(atcmd_output, msg_fd(fd,1434), sub4);// Player '%s' was not found + if (!*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) { - sprintf(atcmd_output, msg_fd(fd,1434), sub4);// Player '%s' was not found + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } @@ -8946,13 +8939,13 @@ ACMD(channel) { ret = channel->ban(chan, sd, pl_sd); if (ret == HCS_STATUS_NOPERM) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } if (ret == HCS_STATUS_ALREADY) { - sprintf(atcmd_output, msg_fd(fd,1465), pl_sd->status.name);// Player '%s' is already banned from this channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1465), pl_sd->status.name);// Player '%s' is already banned from this channel clif->message(fd, atcmd_output); return false; } @@ -8962,7 +8955,7 @@ ACMD(channel) { return false; } - sprintf(atcmd_output, msg_fd(fd,1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"unban") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused @@ -8975,34 +8968,34 @@ ACMD(channel) { return false; } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } - if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { - sprintf(atcmd_output, msg_fd(fd,1434), sub4);// Player '%s' was not found + if (!*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) { + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) { - sprintf(atcmd_output, msg_fd(fd,1434), sub4);// Player '%s' was not found + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found clif->message(fd, atcmd_output); return false; } ret = channel->unban(chan, sd, pl_sd); if (ret == HCS_STATUS_NOPERM) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } if (ret == HCS_STATUS_ALREADY) { - sprintf(atcmd_output, msg_fd(fd,1440), pl_sd->status.name);// Player '%s' is not banned from this channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1440), pl_sd->status.name);// Player '%s' is not banned from this channel clif->message(fd, atcmd_output); return false; } - sprintf(atcmd_output, msg_fd(fd,1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"unbanall") == 0) { enum channel_operation_status ret = HCS_STATUS_OK; @@ -9012,23 +9005,23 @@ ACMD(channel) { return false; } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } ret = channel->unban(chan, sd, NULL); if (ret == HCS_STATUS_NOPERM) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } if (ret == HCS_STATUS_ALREADY) { - sprintf(atcmd_output, msg_fd(fd,1439), sub1);// Channel '%s' has no banned players + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1439), sub1);// Channel '%s' has no banned players clif->message(fd, atcmd_output); return false; } - sprintf(atcmd_output, msg_fd(fd,1442),sub1); // Removed all bans from '%s' channel + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1442),sub1); // Removed all bans from '%s' channel clif->message(fd, atcmd_output); } else if (strcmpi(subcmd,"banlist") == 0) { // sub1 = channel name; sub2 = unused; sub3 = unused @@ -9041,21 +9034,21 @@ ACMD(channel) { return false; } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } if (chan->owner != sd->status.char_id && !isA) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } if (!chan->banned) { - sprintf(atcmd_output, msg_fd(fd,1439), sub1);// Channel '%s' has no banned players + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1439), sub1);// Channel '%s' has no banned players clif->message(fd, atcmd_output); return false; } - sprintf(atcmd_output, msg_fd(fd,1443), chan->name);// -- '%s' ban list + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1443), chan->name);// -- '%s' ban list clif->message(fd, atcmd_output); iter = db_iterator(chan->banned); @@ -9063,9 +9056,9 @@ ACMD(channel) { struct channel_ban_entry *entry = DB->data2ptr(data); if (!isA) - sprintf(atcmd_output, msg_fd(fd,1444), entry->name);// - %s %s + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1444), entry->name);// - %s %s else - sprintf(atcmd_output, msg_fd(fd,1445), entry->name, key.i);// - %s (%d) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1445), entry->name, key.i);// - %s (%d) clif->message(fd, atcmd_output); } @@ -9082,12 +9075,12 @@ ACMD(channel) { return false; } if (!(chan = channel->search(sub1, sd))) { - sprintf(atcmd_output, msg_fd(fd,1407), sub1);// Channel '%s' is not available + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1407), sub1);// Channel '%s' is not available clif->message(fd, atcmd_output); return false; } if (chan->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - sprintf(atcmd_output, msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1412), sub1);// You're not the owner of channel '%s' clif->message(fd, atcmd_output); return false; } @@ -9100,27 +9093,27 @@ ACMD(channel) { break; } if (k == 3) { - sprintf(atcmd_output, msg_fd(fd,1447), sub2);// '%s' is not a known channel option + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1447), sub2);// '%s' is not a known channel option clif->message(fd, atcmd_output); clif->message(fd, msg_fd(fd,1448)); // -- Available options for (k = 1; k < 3; k++) { - sprintf(atcmd_output, msg_fd(fd,1444), opt_str[k]);// - '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1444), opt_str[k]);// - '%s' clif->message(fd, atcmd_output); } return false; } if (sub3[0] == '\0') { if (k == HCS_OPT_MSG_DELAY) { - sprintf(atcmd_output, msg_fd(fd,1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10) clif->message(fd, atcmd_output); return false; } else if (chan->options & k) { - sprintf(atcmd_output, msg_fd(fd,1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0' clif->message(fd, atcmd_output); return false; } else { channel->set_options(chan, chan->options | k); - sprintf(atcmd_output, msg_fd(fd,1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' clif->message(fd, atcmd_output); return true; } @@ -9128,42 +9121,42 @@ ACMD(channel) { int v = atoi(sub3); if (k == HCS_OPT_MSG_DELAY) { if (v < 0 || v > 10) { - sprintf(atcmd_output, msg_fd(fd,1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10) + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10) clif->message(fd, atcmd_output); return false; } if (v == 0) { channel->set_options(chan, chan->options&~k); chan->msg_delay = 0; - sprintf(atcmd_output, msg_fd(fd,1453), opt_str[k],chan->name,v);// option '%s' is now disabled for channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1453), opt_str[k],chan->name,v);// option '%s' is now disabled for channel '%s' clif->message(fd, atcmd_output); return true; } else { channel->set_options(chan, chan->options | k); chan->msg_delay = v; - sprintf(atcmd_output, msg_fd(fd,1452), opt_str[k],chan->name,v);// option '%s' is now enabled for channel '%s' with %d seconds + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1452), opt_str[k],chan->name,v);// option '%s' is now enabled for channel '%s' with %d seconds clif->message(fd, atcmd_output); return true; } } else { if (v) { if (chan->options & k) { - sprintf(atcmd_output, msg_fd(fd,1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0' clif->message(fd, atcmd_output); return false; } else { channel->set_options(chan, chan->options | k); - sprintf(atcmd_output, msg_fd(fd,1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' clif->message(fd, atcmd_output); } } else { if (!(chan->options & k)) { - sprintf(atcmd_output, msg_fd(fd,1454), opt_str[k],chan->name); // option '%s' is not enabled on channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1454), opt_str[k],chan->name); // option '%s' is not enabled on channel '%s' clif->message(fd, atcmd_output); return false; } else { channel->set_options(chan, chan->options&~k); - sprintf(atcmd_output, msg_fd(fd,1453), opt_str[k],chan->name);// option '%s' is now disabled for channel '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1453), opt_str[k],chan->name);// option '%s' is now disabled for channel '%s' clif->message(fd, atcmd_output); return true; } @@ -9171,27 +9164,18 @@ ACMD(channel) { } } } else { - atcmd_channel_help(fd, command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); + atcommand->channel_help(fd, command, (channel->config->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))); } return true; } /* debug only, delete after */ ACMD(fontcolor) { unsigned char k; - unsigned short msg_len = 1; - char mout[40]; - if( !message || !*message ) { - for( k = 0; k < channel->config->colors_count; k++ ) { - msg_len += sprintf(mout, "[ %s ] : %s", command, channel->config->colors_name[k]); - - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); + if (!*message) { + for (k = 0; k < channel->config->colors_count; k++) { + safesnprintf(atcmd_output, sizeof(atcmd_output), "[ %s ] : %s", command, channel->config->colors_name[k]); + clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output); } return false; } @@ -9206,27 +9190,21 @@ ACMD(fontcolor) { break; } if( k == channel->config->colors_count ) { - sprintf(atcmd_output, msg_fd(fd,1411), message);// Unknown color '%s' + safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1411), message);// Unknown color '%s' clif->message(fd, atcmd_output); return false; } sd->fontcolor = k + 1; - msg_len += sprintf(mout, "Color changed to '%s'", channel->config->colors_name[k]); + safesnprintf(atcmd_output, sizeof(atcmd_output), "Color changed to '%s'", channel->config->colors_name[k]); + clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output); - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); return true; } ACMD(searchstore){ int val = atoi(message); - switch( val ) { + switch (val) { case 0://EFFECTTYPE_NORMAL case 1://EFFECTTYPE_CASH break; @@ -9259,10 +9237,10 @@ ACMD(costume){ }; unsigned short k = 0, len = ARRAYLENGTH(names); - if( !message || !*message ) { + if (!*message) { for( k = 0; k < len; k++ ) { if( sd->sc.data[name2id[k]] ) { - sprintf(atcmd_output,msg_fd(fd,1473),names[k]);//Costume '%s' removed. + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1473),names[k]);//Costume '%s' removed. clif->message(sd->fd,atcmd_output); status_change_end(&sd->bl,name2id[k],INVALID_TIMER); return true; @@ -9270,7 +9248,7 @@ ACMD(costume){ } clif->message(sd->fd,msg_fd(fd,1472)); for( k = 0; k < len; k++ ) { - sprintf(atcmd_output,msg_fd(fd,1471),names[k]);//-- %s + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1471),names[k]);//-- %s clif->message(sd->fd,atcmd_output); } return false; @@ -9278,7 +9256,7 @@ ACMD(costume){ for( k = 0; k < len; k++ ) { if( sd->sc.data[name2id[k]] ) { - sprintf(atcmd_output,msg_fd(fd,1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it. + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it. clif->message(sd->fd,atcmd_output); return false; } @@ -9289,7 +9267,7 @@ ACMD(costume){ break; } if( k == len ) { - sprintf(atcmd_output,msg_fd(fd,1469),message);// '%s' is not a known costume + safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1469),message);// '%s' is not a known costume clif->message(sd->fd,atcmd_output); return false; } @@ -9301,13 +9279,13 @@ ACMD(costume){ /* for debugging purposes (so users can easily provide us with debug info) */ /* should be trashed as soon as its no longer necessary */ ACMD(skdebug) { - sprintf(atcmd_output,"second: %u; third: %u", sd->sktree.second, sd->sktree.third); + safesnprintf(atcmd_output, sizeof(atcmd_output),"second: %u; third: %u", sd->sktree.second, sd->sktree.third); clif->message(fd,atcmd_output); - sprintf(atcmd_output,"pc_calc_skilltree_normalize_job: %d",pc->calc_skilltree_normalize_job(sd)); + safesnprintf(atcmd_output, sizeof(atcmd_output),"pc_calc_skilltree_normalize_job: %d",pc->calc_skilltree_normalize_job(sd)); clif->message(fd,atcmd_output); - sprintf(atcmd_output,"change_lv_2nd/3rd: %d/%d",sd->change_level_2nd,sd->change_level_3rd); + safesnprintf(atcmd_output, sizeof(atcmd_output),"change_lv_2nd/3rd: %d/%d",sd->change_level_2nd,sd->change_level_3rd); clif->message(fd,atcmd_output); - sprintf(atcmd_output,"pc_calc_skillpoint:%d",pc->calc_skillpoint(sd)); + safesnprintf(atcmd_output, sizeof(atcmd_output),"pc_calc_skillpoint:%d",pc->calc_skillpoint(sd)); clif->message(fd,atcmd_output); return true; } @@ -9317,27 +9295,27 @@ ACMD(skdebug) { ACMD(cddebug) { int i; struct skill_cd* cd = NULL; - - if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) { + + if (!(cd = idb_get(skill->cd_db,sd->status.char_id))) { clif->message(fd,"No cool down list found"); } else { clif->messages(fd,"Found %d registered cooldowns",cd->cursor); for(i = 0; i < cd->cursor; i++) { if( cd->entry[i] ) { const struct TimerData *td = timer->get(cd->entry[i]->timer); - + if( !td || td->func != skill->blockpc_end ) { - clif->messages(fd,"Found invalid entry in slot %d for skill %s",i,skill->db[cd->entry[i]->skidx].name); + clif->messages(fd,"Found invalid entry in slot %d for skill %s",i,skill->dbs->db[cd->entry[i]->skidx].name); sd->blockskill[cd->entry[i]->skidx] = false; } } } } - - if( !cd || (message && *message && !strcmpi(message,"reset")) ) { + + if (!cd || (*message && !strcmpi(message,"reset"))) { for(i = 0; i < MAX_SKILL; i++) { if( sd->blockskill[i] ) { - clif->messages(fd,"Found skill '%s', unblocking...",skill->db[i].name); + clif->messages(fd,"Found skill '%s', unblocking...",skill->dbs->db[i].name); sd->blockskill[i] = false; } } @@ -9347,12 +9325,12 @@ ACMD(cddebug) { timer->delete(cd->entry[i]->timer,skill->blockpc_end); ers_free(skill->cd_entry_ers, cd->entry[i]); } - + idb_remove(skill->cd_db,sd->status.char_id); ers_free(skill->cd_ers, cd); } } - + return true; } @@ -9361,15 +9339,15 @@ ACMD(cddebug) { **/ ACMD(lang) { uint8 i; - - if( !message || !*message ) { + + if (!*message) { clif->messages(fd,"Usage: @%s <Language>",info->command); clif->messages(fd,"There are %d languages available:",script->max_lang_id); for(i = 0; i < script->max_lang_id; i++) clif->messages(fd,"- %s",script->languages[i]); return false; } - + for(i = 0; i < script->max_lang_id; i++) { if( strcmpi(message,script->languages[i]) == 0 ) { if( i == sd->lang_id ) { @@ -9381,14 +9359,14 @@ ACMD(lang) { break; } } - + if( i == script->max_lang_id ) { clif->messages(fd,"'%s' did not match any language available",message); clif->messages(fd,"There are %d languages available:",script->max_lang_id); for(i = 0; i < script->max_lang_id; i++) clif->messages(fd,"- %s",script->languages[i]); } - + return true; } /** @@ -9680,9 +9658,10 @@ void atcommand_basecommands(void) { #undef ACMD_DEF #undef ACMD_DEF2 -bool atcommand_add(char *name,AtCommandFunc func, bool replace) { +bool atcommand_add(char *name, AtCommandFunc func, bool replace) { AtCommandInfo* cmd; + nullpo_retr(false, name); if( (cmd = atcommand->exists(name)) ) { //caller will handle/display on false if( !replace ) return false; @@ -9959,11 +9938,12 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa } for(i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) { if( info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd ) { - if( pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv ) { - clif->colormes(sd->fd,COLOR_RED,"This command is disabled in this area"); + if (pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv) { + clif->messagecolor_self(sd->fd, COLOR_RED, "This command is disabled in this area"); return true; - } else + } else { break;/* already found the matching command, no need to keep checking -- just go on */ + } } } } @@ -10004,6 +9984,7 @@ void atcommand_config_read(const char* config_filename) { const char *symbol = NULL; int num_aliases = 0; + nullpo_retv(config_filename); if (libconfig->read_file(&atcommand_config, config_filename)) return; @@ -10126,7 +10107,11 @@ void atcommand_config_read(const char* config_filename) { * 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 atcommand_command_type2idx(AtCommandType type) +{ + Assert_retr(0, type > 0); + return (type-1); +} /** * Loads permissions for groups to use commands. @@ -10137,6 +10122,8 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo *atcmd; + nullpo_retv(groups); + nullpo_retv(commands_); for (atcmd = dbi_first(iter); dbi_exists(iter); atcmd = dbi_next(iter)) { int i; CREATE(atcmd->at_groups, char, sz); @@ -10176,10 +10163,10 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command config_setting_is_aggregate(cmd) && config_setting_length(cmd) == 2 ) { - if (config_setting_get_bool_elem(cmd, AtCommandType2idx(COMMAND_ATCOMMAND))) { + if (config_setting_get_bool_elem(cmd, atcommand_command_type2idx(COMMAND_ATCOMMAND))) { atcmd->at_groups[idx] = 1; } - if (config_setting_get_bool_elem(cmd, AtCommandType2idx(COMMAND_CHARCOMMAND))) { + if (config_setting_get_bool_elem(cmd, atcommand_command_type2idx(COMMAND_CHARCOMMAND))) { atcmd->char_groups[idx] = 1; } } @@ -10193,6 +10180,8 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command bool atcommand_can_use(struct map_session_data *sd, const char *command) { AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command + 1)); + nullpo_retr(false, sd); + nullpo_retr(false, command); if (info == NULL) return false; @@ -10206,6 +10195,8 @@ bool atcommand_can_use(struct map_session_data *sd, const char *command) { bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type) { AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command)); + nullpo_retr(false, sd); + nullpo_retr(false, command); if (info == NULL) return false; @@ -10219,7 +10210,7 @@ bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtComm bool atcommand_hp_add(char *name, AtCommandFunc func) { /* if commands are added after group permissions are thrown in, they end up with no permissions */ /* so we restrict commands to be linked in during boot */ - if( runflag == MAPSERVER_ST_RUNNING ) { + if( core->runflag == MAPSERVER_ST_RUNNING ) { ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name); return false; } @@ -10251,7 +10242,7 @@ void atcommand_db_clear(void) { } void atcommand_doload(void) { - if( runflag >= MAPSERVER_ST_RUNNING ) + if( core->runflag >= MAPSERVER_ST_RUNNING ) atcommand->cmd_db_clear(); if( atcommand->db == NULL ) atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); @@ -10312,6 +10303,8 @@ void atcommand_defaults(void) { atcommand->cleanfloor_sub = atcommand_cleanfloor_sub; atcommand->mutearea_sub = atcommand_mutearea_sub; atcommand->commands_sub = atcommand_commands_sub; + atcommand->getring = atcommand_getring; + atcommand->channel_help = atcommand_channel_help; atcommand->cmd_db_clear = atcommand_db_clear; atcommand->cmd_db_clear_sub = atcommand_db_clear_sub; atcommand->doload = atcommand_doload; diff --git a/src/map/atcommand.h b/src/map/atcommand.h index c1f451ad3..6c8dbf9ef 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -5,9 +5,12 @@ #ifndef MAP_ATCOMMAND_H #define MAP_ATCOMMAND_H -#include "pc_groups.h" -#include "../common/conf.h" -#include "../common/db.h" +#include "map/pc_groups.h" +#include "common/hercules.h" +#include "common/conf.h" +#include "common/db.h" + +#include <stdarg.h> /** * Declarations @@ -111,6 +114,8 @@ struct atcommand_interface { void (*get_jail_time) (int jailtime, int* year, int* month, int* day, int* hour, int* minute); int (*cleanfloor_sub) (struct block_list *bl, va_list ap); int (*mutearea_sub) (struct block_list *bl,va_list ap); + void (*getring) (struct map_session_data* sd); + void (*channel_help) (int fd, const char *command, bool can_create); /* */ void (*commands_sub) (struct map_session_data* sd, const int fd, AtCommandType type); void (*cmd_db_clear) (void); @@ -124,13 +129,14 @@ struct atcommand_interface { const char* (*msgsd) (struct map_session_data *sd, int msg_number); }; -struct atcommand_interface *atcommand; - #ifdef HERCULES_CORE void atcommand_defaults(void); #endif // HERCULES_CORE +HPShared struct atcommand_interface *atcommand; + /* stay here */ -#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) +#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) __attribute__((nonnull (2, 3, 4, 5))); \ + static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) #endif /* MAP_ATCOMMAND_H */ diff --git a/src/map/battle.c b/src/map/battle.c index 4e56b47ce..e2f85e988 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4,50 +4,52 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT #include "battle.h" +#include "map/battleground.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battleground.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "itemdb.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct Battle_Config battle_config; struct battle_interface battle_s; +struct battle_interface *battle; 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 ) { + nullpo_ret(bl); + if (bl->type == BL_SKILL) { struct skill_unit * su = (struct skill_unit*)bl; return su->group?su->group->skill_id:0; } @@ -66,6 +68,7 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) { int target_id; int *c; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); c = va_arg(ap, int *); target_id = va_arg(ap, int); @@ -76,7 +79,7 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) { if (*c >= 24) return 0; - if ( !(ud = unit->bl2ud(bl)) ) + if (!(ud = unit->bl2ud(bl))) return 0; if (ud->target == target_id || ud->skilltarget == target_id) { @@ -101,10 +104,10 @@ struct block_list* battle_gettargeted(struct block_list *target) { return bl_list[rnd()%c]; } - //Returns the id of the current targeted character of the passed bl. [Skotlex] int battle_gettarget(struct block_list* bl) { + nullpo_ret(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; @@ -122,6 +125,7 @@ int battle_getenemy_sub(struct block_list *bl, va_list ap) { struct block_list *target; int *c; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); c = va_arg(ap, int *); target = va_arg(ap, struct block_list *); @@ -148,6 +152,7 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang struct block_list *bl_list[24]; int c = 0; + nullpo_retr(NULL, target); memset(bl_list, 0, sizeof(bl_list)); map->foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target); @@ -163,8 +168,11 @@ int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list, *src; int *c, ignore_id; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); + nullpo_ret(bl_list); c = va_arg(ap, int *); + nullpo_ret(c); src = va_arg(ap, struct block_list *); ignore_id = va_arg(ap, int); @@ -190,6 +198,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int struct block_list *bl_list[24]; int c = 0; + nullpo_retr(NULL, src); memset(bl_list, 0, sizeof(bl_list)); map->foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); @@ -209,7 +218,7 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list* target = map->id2bl(dat->target_id); if( !target || status->isdead(target) ) {/* nothing we can do */ - if( dat->src_type == BL_PC && ( src = map->id2bl(dat->src_id) ) && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { + if( dat->src_type == BL_PC && (src = map->id2bl(dat->src_id)) != NULL && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { ((TBL_PC*)src)->state.hold_recalc = 0; status_calc_pc(((TBL_PC*)src),SCO_FORCE); } @@ -263,7 +272,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct if (d_tbl && sc && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && 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 separate here between reflect damage and others [icescope] @@ -299,11 +308,10 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct } int battle_attr_ratio(int atk_elem,int def_type, int def_lv) { - - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) return 100; - if (def_type < 0 || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) + if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) return 100; return battle->attr_fix_table[def_lv-1][atk_elem][def_type]; @@ -322,10 +330,10 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d if (src) sc = status->get_sc(src); if (target) tsc = status->get_sc(target); - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) atk_elem = rnd()%ELE_MAX; - if (def_type < 0 || def_type >= ELE_MAX || + if (def_type < ELE_NEUTRAL || 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; @@ -407,6 +415,8 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d else return damage + (damage * (ratio - 100) / 100); } + +//FIXME: Missing documentation for flag, flag2 int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett] #ifdef RENEWAL int64 damage, eatk = 0; @@ -449,7 +459,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) eatk += 200; } - + #ifdef RENEWAL_EDP if ( sc && sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ) { struct status_data *tstatus; @@ -459,9 +469,8 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u } else /* fall through */ #endif damage += eatk; - damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag); - + /** * In RE Shield Boomerang takes weapon element only for damage calculation, * - resist calculation is always against neutral @@ -485,7 +494,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex] *------------------------------------------ * Pass damage2 as NULL to not calc it. - * Flag values: + * Flag values: // TODO: Check whether these values are correct (the flag parameter seems to be passed through to other functions), and replace them with an enum. * &1: Critical hit * &2: Arrow attack * &4: Skill is Magic Crasher @@ -493,11 +502,13 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) */ /* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */ +// FIXME: Missing documentation for flag2 int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) { int64 damage; struct status_data *st = status->get_status_data(src); struct status_change *sc = status->get_sc(src); - + + nullpo_retr(0, src); if ( !skill_id ) { s_ele = st->rhw.ele; s_ele_ = st->lhw.ele; @@ -532,6 +543,8 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st short type = 0; int64 damage = 0; + nullpo_retr(damage, st); + nullpo_retr(damage, wa); if (!sd) { //Mobs/Pets if(flag&4) { atkmin = st->matk_min; @@ -608,6 +621,7 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore){ //SizeFix only for players + nullpo_retr(damage, sd); if (!(sd->special_state.no_sizefix || (ignore))) damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[size] : sd->right_weapon.atkmods[size] ) / 100; return damage; @@ -616,14 +630,15 @@ int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, i /*========================================== * Passive skill damages increases *------------------------------------------*/ +// FIXME: type is undocumented int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) { int64 damage; struct status_data *st = status->get_status_data(target); int weapon, skill_lv; damage = dmg; - nullpo_ret(sd); - + nullpo_retr(damage, sd); + nullpo_retr(damage, target); if((skill_lv = pc->checkskill(sd,AL_DEMONBANE)) > 0 && target->type == BL_MOB && //This bonus doesn't work against players. (battle->check_undead(st->race,st->def_ele) || st->race==RC_DEMON) ) @@ -843,7 +858,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, i = 2; //Star anger else ARR_FIND(0, MAX_PC_FEELHATE, i, status->get_class(target) == sd->hate_mob[i]); - if ( i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) && weapon ) { + if (i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) > 0 && weapon) { int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src); if ( i == 2 ) ratio += status_get_str(src); //Star Anger if (skill2_lv < 4 ) @@ -866,6 +881,7 @@ void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *t /*========================================== * Elemental attribute fix. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){ struct status_data *tstatus; @@ -930,8 +946,6 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 // RaceAddTolerance damage -= damage * tsd->race_tolerance[sstatus->race] / 100; damage -= damage * tsd->race_tolerance[is_boss(src) ? RC_BOSS : RC_NONBOSS] / 100; - if ( sstatus->race != RC_DEMIHUMAN ) - damage -= damage *tsd->race_tolerance[RC_NONDEMIHUMAN] / 100; if ( flag&BF_SHORT ) damage -= damage * tsd->bonus.near_attack_def_rate / 100; else // SubRangeAttackDamage or bLongAtkDef @@ -950,13 +964,13 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 * &1 - calc for left hand. * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON). *------------------------------------------*/ +// FIXME: wflag is undocumented int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){ struct map_session_data *sd, *tsd; - short cardfix = #ifdef RENEWAL - 100; + short cardfix = 100; #else - 1000; + short cardfix = 1000; #endif short t_class, s_class, s_race2, t_race2; struct status_data *sstatus, *tstatus; @@ -1013,8 +1027,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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) { @@ -1070,8 +1082,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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; @@ -1090,8 +1100,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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( cflag&1 ){ cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; @@ -1110,8 +1118,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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]; @@ -1137,8 +1143,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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; } } @@ -1203,8 +1207,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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 ) @@ -1251,8 +1253,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ } 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( wflag&BF_SHORT ) cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; else // BF_LONG (there's no other choice) @@ -1282,6 +1282,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ * &2 - pdef(Pierce defense) * &4 - tdef(Total defense reduction) *------------------------------------------*/ +// TODO: Add an enum for flag int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){ struct status_data *sstatus, *tstatus; struct map_session_data *sd, *tsd; @@ -1485,6 +1486,7 @@ int battle_calc_chorusbonus(struct map_session_data *sd) { return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible } +// FIXME: flag is undocumented int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){ int i; struct status_change *sc, *tsc; @@ -2695,9 +2697,12 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam struct map_session_data *sd = NULL; struct status_change *sc, *tsc; struct status_change_entry *sce; - int div_ = d->div_, flag = d->flag; + int div_, flag; nullpo_ret(bl); + nullpo_ret(d); + div_ = d->div_; + flag = d->flag; // need check src for null pointer? @@ -2788,6 +2793,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX); } else skill->del_unitgroup(group,ALC_MARK); + if (--group->val3<=0) + skill->del_unitgroup(group,ALC_MARK); #else if (--group->val2<=0) skill->del_unitgroup(group,ALC_MARK); @@ -2874,7 +2881,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam return 0; } - if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) { // attack blocked by Parrying clif->skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); @@ -2907,7 +2913,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam return 0; } - if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { + if (flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) != NULL && rnd()%100 < sce->val2) { clif->specialeffect(bl, 462, AREA); // Still need confirm it. return 0; } @@ -3126,7 +3132,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC_MEIKYOUSISUI] && rnd()%100 < 40 ) // custom value damage = 0; - if (!damage) return 0; if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { @@ -3159,28 +3164,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(bl, src); // Deadly infect attacked side + + if (sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + if ( rnd() % 100 < sce->val2 ) + pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(sd, 0)); + } } //SC effects from caster side. - sc = status->get_sc(src); - - if (sc && sc->count) { - if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + if (tsc && tsc->count) { + if( tsc->data[SC_INVINCIBLE] && !tsc->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)) + if ( ((sce=tsc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->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)) + if ( ((sce=tsc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) ) for (i=0;ARRAYLENGTH(mob->splendide)>i;i++) if (((TBL_MOB*)bl)->class_==mob->splendide[i]) { @@ -3197,14 +3205,19 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); } } - if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) + if( tsc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * tsc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(src, bl); - if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) + if (tsc->data[SC_SHIELDSPELL_REF] && tsc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY ); - if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { + if (tsc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); if (hd) homun->addspiritball(hd, 10); } + if (src->type == BL_PC && damage > 0 && (sce = tsc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + struct map_session_data *tsd = (struct map_session_data *)src; + if ( tsd && rnd() % 100 < sce->val2 ) + pc->addspiritball(tsd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(tsd, 0)); + } } /* no data claims these settings affect anything other than players */ if( damage && sd && bl->type == BL_PC ) { @@ -3248,24 +3261,27 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if (skill_id) mob->skill_event((TBL_MOB*)bl,src,timer->gettick(),MSC_SKILLUSED|(skill_id<<16)); } - if( sd ) { - if( pc_ismadogear(sd) && rnd()%100 < 50 ) { - short element = skill->get_ele(skill_id, skill_lv); - if( !skill_id || 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; - } + if (sd && pc_ismadogear(sd) && rnd()%100 < 50) { + int element = -1; + if (!skill_id || (element = skill->get_ele(skill_id, skill_lv)) == -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)) != NULL) { + 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); - } + } 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) + pc->overheat(sd, 1); + else if (element == ELE_WATER) + pc->overheat(sd, -1); } return damage; @@ -3274,11 +3290,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam /*========================================== * Calculates BG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) { if( !damage ) return 0; + nullpo_retr(damage, bl); if( bl->type == BL_MOB ) { struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -3292,12 +3310,15 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 /*========================================== * Calculates GVG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) { struct mob_data* md = BL_CAST(BL_MOB, bl); int class_ = status->get_class(bl); if (!damage) //No reductions to make. return 0; + nullpo_retr(damage, src); + nullpo_retr(damage, bl); if(md && md->guardian_data) { if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { @@ -3365,21 +3386,27 @@ int battle_calc_drain(int64 damage, int rate, int per) { *------------------------------------------*/ void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { int qty=1; + + nullpo_retv(sd); if (!battle_config.arrow_decrement) return; - if (skill_id) { + if (skill_id && lv) { qty = skill->get_ammo_qty(skill_id, 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); + pc->delitem(sd, sd->equip_index[EQI_AMMO], qty, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sd->state.arrow_atk = 0; } + //Skill Range Criteria int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { + nullpo_retr(BF_SHORT, src); + nullpo_retr(BF_SHORT, target); + if (battle_config.skillrange_by_distance && (src->type&battle_config.skillrange_by_distance) ) { //based on distance between src/target [Skotlex] @@ -3412,8 +3439,10 @@ int battle_adjust_skill_damage(int m, unsigned short skill_id) { return 0; } + int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { int i; + nullpo_ret(sd); if (!sd->skillblown[0].id) return 0; //Apply the bonus blow count. [Skotlex] @@ -3428,6 +3457,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { /*========================================== * battle_calc_magic_attack [DracoRPG] *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int nk; short s_ele = 0; @@ -3606,7 +3636,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 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; + ad.type = BDT_NORMAL; } /* Fall through */ default: @@ -3622,7 +3652,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -3754,6 +3784,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list /*========================================== * Calculate Misc damage for skill_id *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int temp; short i, nk; @@ -4095,7 +4126,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -4124,7 +4155,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * default: rskill = skill_id; } - if (sd && (i = pc->skillatk_bonus(sd, rskill))) + if (sd && (i = pc->skillatk_bonus(sd, rskill)) != 0) md.damage += md.damage*i/100; } if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) @@ -4185,6 +4216,7 @@ void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list * /*========================================== * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ +// FIXME: wflag is undocumented struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) { unsigned int skillratio = 100; //Skill dmg modifiers. @@ -4235,7 +4267,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.infdef = 1; // Reverberation takes 1 damage //Initial Values - wd.type=0; //Normal attack + wd.type = BDT_NORMAL; wd.div_ = skill_id ? skill->get_num(skill_id,skill_lv) : 1; wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. if(skill_id == KN_AUTOCOUNTER) @@ -4302,7 +4334,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case TF_DOUBLE: //For NPC used skill. case GS_CHAINACTION: - wd.type = 0x08; + wd.type = BDT_MULTIHIT; break; case GS_GROUNDDRIFT: @@ -4341,6 +4373,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( tsc && (tsc->data[SC_WUGBITE] || tsc->data[SC_ANKLESNARE] || tsc->data[SC_ELECTRICSHOCKER]) ) wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); break; + + case NPC_EARTHQUAKE: + wd.flag = (wd.flag&~(BF_WEAPON)) | BF_MAGIC; + break; #ifdef RENEWAL case MO_EXTREMITYFIST: case GS_PIERCINGSHOT: @@ -4367,7 +4403,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list wd.flag |= flag.arrow?BF_LONG:BF_SHORT; if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { //Check for Lucky Dodge - wd.type=0x0b; + wd.type = BDT_PDODGE; wd.dmg_lv=ATK_LUCKY; if (wd.div_ < 0) wd.div_*=-1; return wd; @@ -4435,13 +4471,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list 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; + wd.type = BDT_MULTIHIT; } } 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; + wd.type = BDT_MULTIHIT; } 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){ @@ -4472,13 +4508,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if ( wd.div_ > 1 ) { wd.div_ = min(wd.div_, sd->status.inventory[i].amount); sc->data[SC_FEARBREEZE]->val4 = wd.div_ - 1; - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } } } //Check for critical - if( !flag.cri && !(wd.type&0x08) && sstatus->cri && + if( !flag.cri && wd.type != BDT_MULTIHIT && sstatus->cri && (!skill_id || skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || @@ -4536,7 +4572,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.cri = 1; } if (flag.cri) { - wd.type = 0x0a; + wd.type = BDT_CRIT; #ifndef RENEWAL flag.idef = flag.idef2 = #endif @@ -4869,7 +4905,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list else wd.dmg_lv = ATK_DEF; break; - + case KO_BAKURETSU: { #ifdef RENEWAL @@ -5309,7 +5345,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) return wd; //Enough, rest is not needed. #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -5507,7 +5543,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list #endif } - if( src != target ) { // Don't reflect your own damage (Grand Cross) if( wd.dmg_lv == ATK_MISS || wd.dmg_lv == ATK_BLOCK ) { int64 prev1 = wd.damage, prev2 = wd.damage2; @@ -5534,7 +5569,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list rnd()%100 < tsc->data[SC_SWORDREJECT]->val2 ) { ATK_RATER(50); - status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,0,0)); + status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,BDT_NORMAL,0)); clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_SWORDREJECT]->val1,1); if( --(tsc->data[SC_SWORDREJECT]->val3) <= 0 ) status_change_end(target, SC_SWORDREJECT, INVALID_TIMER); @@ -5567,6 +5602,7 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl break; } + nullpo_retr(d, target); #ifdef HMAP_ZONE_DAMAGE_CAP_TYPE if( target && skill_id ) { int i; @@ -5604,9 +5640,10 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl } return d; } + //Performs reflect damage (magic (maya) is performed over skill.c). void battle_reflect_damage(struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id) { - int64 damage = wd->damage + wd->damage2, rdamage = 0, trdamage = 0; + int64 damage, rdamage = 0, trdamage = 0; struct map_session_data *sd, *tsd; struct status_change *sc; int64 tick = timer->gettick(); @@ -5617,6 +5654,10 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st max_reflect_damage = max(status_get_max_hp(target), status_get_max_hp(target) * status->get_lv(target) / 100); #endif + damage = wd->damage + wd->damage2; + + nullpo_retv(wd); + sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); @@ -5640,8 +5681,8 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st rdamage = ratio + (damage)* (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; skill->blown(target, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit->getdir(src), 0); clif->skill_damage(target, src, tick, status_get_amotion(src), 0, rdamage, - 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, 0); + 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, BDT_SKILL); // This is how official does + clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, BDT_NORMAL); status->damage(src, target, status->damage(target, src, rdamage, 0, 0, 1)/10, 0, 0, 1); status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER); /* shouldn't this trigger skill->additional_effect? */ @@ -5659,7 +5700,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended. - rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6); + rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, BDT_SKILL); skill->blown(target, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit->getdir(src), 0); if( tsd ) /* is this right? rdamage as both left and right? */ @@ -5686,7 +5727,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.short_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.short_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5711,9 +5752,9 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100); #ifndef RENEWAL - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); #else - rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4); + rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, BDT_ENDURE); #endif /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5747,7 +5788,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){ NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5761,7 +5802,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( ssc->data[SC_INSPIRATION] ) { NORMALIZE_RDAMAGE(damage / 100); - rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( sd ) @@ -5776,7 +5817,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.long_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.long_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5797,11 +5838,14 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st return; #undef NORMALIZE_RDAMAGE } + void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss) { struct weapon_data *wd; int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i; int64 *damage; + + nullpo_retv(sd); for (i = 0; i < 4; i++) { //First two iterations: Right hand if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; } @@ -5864,6 +5908,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM ) return 0; if( bl != src && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { + nullpo_ret(src); map->freeblock_lock(); if( src->type == BL_PC ) battle->drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); @@ -5871,7 +5916,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true); else status_fix_damage(src,bl,damage,0); - clif->damage(bl,bl,amotion,dmotion,damage,1,ATK_BLOCK,0); + clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0); if( !(src->type == BL_PC && ((TBL_PC*)src)->state.autocast) ) skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); map->freeblock_unlock(); @@ -5882,6 +5927,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ +// FIXME: flag is undocumented enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; @@ -5963,7 +6009,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; clif->skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); skill->attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; @@ -5976,7 +6022,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(target, src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. clif->bladestop(target, src->id, 1); sc_start4(target, target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; @@ -6020,18 +6066,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ATK_DEF; return ATK_MISS; } - if( sc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(sd, - skill->get_time(MO_CALLSPIRITS, sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } - if( tsc && tsc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(tsd, - skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 ) clif->skill_nodamage(target, target, SM_ENDURE, 5, @@ -6054,7 +6088,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } 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); + pc->delitem(sd, sd->equip_index[EQI_AMMO], sc->data[SC_FEARBREEZE]->val4, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sc->data[SC_FEARBREEZE]->val4 = 0; } } @@ -6102,7 +6136,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t (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, 0, 0, damage, 0, 0, 0); + clif->damage(d_bl, d_bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(NULL, d_bl, damage, 0); } else @@ -6110,7 +6144,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } 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); + 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, BDT_SKILL); 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 ) { @@ -6275,6 +6309,7 @@ bool battle_check_undead(int race,int element) //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?) + nullpo_retr(NULL, src); do { prev = src; switch (src->type) { @@ -6329,7 +6364,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f m = target->m; - if (flag&BCT_ENEMY && ( map->getcell(m,src->x,src->y,CELL_CHKBASILICA) || map->getcell(m,target->x,target->y,CELL_CHKBASILICA) ) ) { + if (flag & BCT_ENEMY && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) || map->getcell(m, src, target->x, target->y, CELL_CHKBASILICA))) { return -1; } @@ -6359,7 +6394,6 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f 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 ) { switch( battle->get_current_skill(src) ) { /* TODO a proper distinction should be established bugreport:8397 */ @@ -6379,21 +6413,26 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } 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 && t_bl->id != s_bl->id)) //Zanzoe - { + { + TBL_MOB *md = BL_CAST(BL_MOB, target); + if(( + (md->special_state.ai == AI_SPHERE || (md->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) + && s_bl->type == BL_PC && src->type != BL_MOB + ) + || (md->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id) + ) { //Targetable 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 && + if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS && su->group->unit_id != UNT_NETHERWORLD ) { //Only a few skills can target traps... switch( battle->get_current_skill(src) ) { @@ -6533,7 +6572,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f ) { 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 if ( src->type != BL_SKILL || (flag&BCT_ENEMY) ) + else if (src->type != BL_SKILL || (flag&BCT_ALL) != BCT_ALL) return 0; } } @@ -6550,19 +6589,16 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->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 ) - ) + if (md->special_state.ai == AI_NONE) { + //Normal mobs + struct mob_data *target_md = BL_CAST(BL_MOB, target); + if( (target_md && t_bl->type == BL_PC && target_md->special_state.ai != AI_ZANZOU && target_md->special_state.ai != AI_ATTACK) + || (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 ) + } else { + if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->special_state.ai == AI_NONE) state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. } break; @@ -6689,7 +6725,7 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range if( d > AREA_SIZE ) return false; // Avoid targeting 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,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); } static const struct battle_data { @@ -7048,7 +7084,6 @@ static const struct battle_data { { "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, }, { "client_emblem_max_blank_percent", &battle_config.client_emblem_max_blank_percent, 100, 0, 100, }, - // BattleGround Settings { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, @@ -7084,7 +7119,6 @@ static const struct battle_data { { "feature.banking", &battle_config.feature_banking, 1, 0, 1, }, { "feature.auction", &battle_config.feature_auction, 0, 0, 2, }, { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, }, - { "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, }, { "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, }, { "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, }, @@ -7096,6 +7130,7 @@ static const struct battle_data { { "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, }, { "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, }, { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, }, + { "show_monster_hp_bar", &battle_config.show_monster_hp_bar, 1, 0, 1, }, }; #ifndef STATS_OPT_OUT /** @@ -7270,8 +7305,10 @@ static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) { int battle_set_value(const char* w1, const char* w2) { int val = config_switch(w2); - int i; + + nullpo_retr(1, w1); + nullpo_retr(1, w2); ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); if (i == ARRAYLENGTH(battle_data)) { if( HPM->parseConf(w1,w2,HPCT_BATTLE) ) /* if plugin-owned, succeed */ @@ -7292,6 +7329,7 @@ int battle_set_value(const char* w1, const char* w2) int battle_get_value(const char* w1) { int i; + nullpo_retr(1, w1); ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); if (i == ARRAYLENGTH(battle_data)) return 0; // not found @@ -7362,7 +7400,6 @@ void battle_adjust_conf(void) { } #endif - #ifndef CELL_NOSTACK if (battle_config.custom_cell_stack_limit != 1) ShowWarning("Battle setting 'custom_cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); @@ -7374,6 +7411,8 @@ int battle_config_read(const char* cfgName) FILE* fp; static int count = 0; + nullpo_ret(cfgName); + if (count == 0) battle->config_set_defaults(); diff --git a/src/map/battle.h b/src/map/battle.h index b3437dbc3..0ebc0aeb9 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -5,8 +5,8 @@ #ifndef MAP_BATTLE_H #define MAP_BATTLE_H -#include "map.h" //ELE_MAX -#include "../common/cbasetypes.h" +#include "map/map.h" //ELE_MAX +#include "common/hercules.h" /** * Declarations @@ -77,6 +77,27 @@ enum e_battle_check_target { //New definitions [Skotlex] }; /** + * Values used by (struct Damage).type, as well as clif->damage(type) and clif->skill_damage(type) + * + * Note: some values may not apply in some contexts. + */ +enum battle_dmg_type { + BDT_NORMAL = 0, // Normal attack + //BDT_PICKUP = 1, // Pick up item + //BDT_SITDOWN = 2, // Sit down + //BDT_STANDUP = 3, // Stand up + BDT_ENDURE = 4, // Damage (endure) + BDT_SPLASH = 5, // Splash + BDT_SKILL = 6, // Skill + //BDT_REPEAT = 7, // (repeat damage?) + BDT_MULTIHIT = 8, // Multi-hit damage + BDT_MULTIENDURE = 9, // Multi-hit damage (endure) + BDT_CRIT = 10, // Critical hit + BDT_PDODGE = 11, // Lucky dodge + //BDT_TOUCH = 12, // (touch skill?) +}; + +/** * Structures **/ @@ -486,11 +507,9 @@ struct Battle_Config { int stormgust_knockback; int feature_roulette; -}; -#ifdef HERCULES_CORE -extern struct Battle_Config battle_config; -#endif // HERCULES_CORE + int show_monster_hp_bar; // [Frost] +}; /* criteria for battle_config.idletime_critera */ enum e_battle_config_idletime { @@ -622,10 +641,12 @@ struct battle_interface { void (*calc_misc_attack_unknown) (struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *mflag, struct Damage *md); }; -struct battle_interface *battle; - #ifdef HERCULES_CORE +extern struct Battle_Config battle_config; + void battle_defaults(void); #endif // HERCULES_CORE +HPShared struct battle_interface *battle; + #endif /* MAP_BATTLE_H */ diff --git a/src/map/battleground.c b/src/map/battleground.c index f0bad2b3d..5df05d301 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -6,31 +6,33 @@ #include "battleground.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" // struct mob_data +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/HPM.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <string.h> -#include "battle.h" -#include "clif.h" -#include "homunculus.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" // struct mob_data -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/HPM.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct battleground_interface bg_s; +struct battleground_interface *bg; /// Search a BG Team using bg_id struct battleground_data* bg_team_search(int bg_id) { @@ -211,7 +213,7 @@ int bg_team_get_id(struct block_list *bl) { { struct map_session_data *msd; struct mob_data *md = (TBL_MOB*)bl; - if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL ) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->bg_id; return md->bg_id; } @@ -234,6 +236,7 @@ bool bg_send_message(struct map_session_data *sd, const char *mes, int len) { struct battleground_data *bgd; nullpo_ret(sd); + nullpo_ret(mes); if( sd->bg_id == 0 || (bgd = bg->team_search(sd->bg_id)) == NULL ) return false; // Couldn't send message clif->bg_message(bgd, sd->bl.id, sd->status.name, mes, len); @@ -269,6 +272,7 @@ enum bg_queue_types bg_str2teamtype (const char *str) { char temp[200], *parse; enum bg_queue_types type = BGQT_INVALID; + nullpo_retr(type, str); safestrncpy(temp, str, 200); parse = strtok(temp,"|"); @@ -455,11 +459,12 @@ void bg_config_read(void) { } bg->arenas = arena_count; } - libconfig->destroy(&bg_conf); } + libconfig->destroy(&bg_conf); } struct bg_arena *bg_name2arena (char *name) { int i; + nullpo_retr(NULL, name); for(i = 0; i < bg->arenas; i++) { if( strcmpi(bg->arena[i]->name,name) == 0 ) return bg->arena[i]; @@ -482,6 +487,8 @@ int bg_id2pos ( int queue_id, int account_id ) { return 0; } void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bool response) { + nullpo_retv(arena); + nullpo_retv(sd); if( arena->begin_timer == INVALID_TIMER || !sd->bg_queue.arena || sd->bg_queue.arena != arena ) { bg->queue_pc_cleanup(sd); return; @@ -494,7 +501,7 @@ void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bo sd->bg_queue.ready = 1; for( i = 0; i < queue->size; i++ ) { - if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (sd = map->id2sd(queue->item[i])) != NULL) { if( sd->bg_queue.ready == 1 ) count++; } @@ -509,6 +516,7 @@ void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bo } void bg_queue_player_cleanup(struct map_session_data *sd) { + nullpo_retv(sd); if ( sd->bg_queue.client_has_bg_data ) { if( sd->bg_queue.arena ) clif->bgqueue_notice_delete(sd,BGQND_CLOSEWINDOW,sd->bg_queue.arena->name); @@ -526,6 +534,7 @@ void bg_match_over(struct bg_arena *arena, bool canceled) { struct hQueue *queue = &script->hq[arena->queue_id]; int i; + nullpo_retv(arena); if( !arena->ongoing ) return; arena->ongoing = false; @@ -533,16 +542,15 @@ void bg_match_over(struct bg_arena *arena, bool canceled) { for( i = 0; i < queue->size; i++ ) { struct map_session_data * sd = NULL; - if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (sd = map->id2sd(queue->item[i])) != NULL) { if( sd->bg_queue.arena ) { bg->team_leave(sd, 0); bg->queue_pc_cleanup(sd); } - if( canceled ) - clif->colormes(sd->fd,COLOR_RED,"BG Match Canceled: not enough players"); - else { + if (canceled) + clif->messagecolor_self(sd->fd, COLOR_RED, "BG Match Canceled: not enough players"); + else pc_setglobalreg(sd, script->add_str(arena->delay_var), (unsigned int)time(NULL)); - } } } @@ -555,10 +563,11 @@ void bg_begin(struct bg_arena *arena) { struct hQueue *queue = &script->hq[arena->queue_id]; int i, count = 0; + nullpo_retv(arena); for( i = 0; i < queue->size; i++ ) { struct map_session_data * sd = NULL; - if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (sd = map->id2sd(queue->item[i])) != NULL) { if( sd->bg_queue.ready == 1 ) count++; else @@ -585,7 +594,7 @@ void bg_begin(struct bg_arena *arena) { for( i = 0; i < queue->size; i++ ) { struct map_session_data * sd = NULL; - if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (sd = map->id2sd(queue->item[i])) != NULL) { if( sd->bg_queue.ready == 1 ) { mapreg->setreg(reference_uid(script->add_str("$@bg_member"), count), sd->status.account_id); mapreg->setreg(reference_uid(script->add_str("$@bg_member_group"), count), @@ -636,13 +645,15 @@ int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) { } void bg_queue_pregame(struct bg_arena *arena) { - struct hQueue *queue = &script->hq[arena->queue_id]; + struct hQueue *queue; int i; + nullpo_retv(arena); + queue = &script->hq[arena->queue_id]; for( i = 0; i < queue->size; i++ ) { struct map_session_data * sd = NULL; - if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (sd = map->id2sd(queue->item[i])) != NULL) { clif->bgqueue_battlebegins(sd,arena->id,SELF); } } @@ -655,7 +666,10 @@ int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data) { } void bg_queue_check(struct bg_arena *arena) { - int count = script->hq[arena->queue_id].items; + int count; + + nullpo_retv(arena); + count = script->hq[arena->queue_id].items; if( count == arena->max_players ) { if( arena->fillup_timer != INVALID_TIMER ) { timer->delete(arena->fillup_timer,bg->fillup_timer); @@ -671,6 +685,8 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q struct hQueue *queue; int i, count = 0; + nullpo_retv(sd); + nullpo_retv(arena); if( arena->begin_timer != INVALID_TIMER || arena->ongoing ) { clif->bgqueue_ack(sd,BGQA_FAIL_QUEUING_FINISHED,arena->id); return; @@ -749,6 +765,8 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ int tick; unsigned int tsec; + nullpo_retr(BGQA_FAIL_TYPE_INVALID, sd); + nullpo_retr(BGQA_FAIL_TYPE_INVALID, arena); if( !(arena->allowed_types & type) ) return BGQA_FAIL_TYPE_INVALID; @@ -766,7 +784,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "You are a deserter! Wait %d minute(s) before you can apply again",(tick-tsec)/60); else sprintf(response, "You are a deserter! Wait %d seconds before you can apply again",(tick-tsec)); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_DESERTER; } @@ -776,7 +794,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d minute(s)",(tick-tsec)/60); else sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d seconds",(tick-tsec)); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_COOLDOWN; } @@ -800,7 +818,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "Can't apply: not enough members in your team/guild that have not entered the queue in individual mode, minimum is %d",arena->min_team_players); else sprintf(response, "Can't apply: not enough members in your team/guild, minimum is %d",arena->min_team_players); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_TEAM_COUNT; } } @@ -832,7 +850,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "Can't apply: not enough members in your team/party that have not entered the queue in individual mode, minimum is %d",arena->min_team_players); else sprintf(response, "Can't apply: not enough members in your team/party, minimum is %d",arena->min_team_players); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_TEAM_COUNT; } } else @@ -863,6 +881,7 @@ void do_init_battleground(bool minimal) { int bg_team_db_final(DBKey key, DBData *data, va_list ap) { struct battleground_data* bgd = DB->data2ptr(data); int i; + nullpo_ret(bgd); for(i = 0; i < bgd->hdatac; i++ ) { if( bgd->hdata[i]->flag.free ) { aFree(bgd->hdata[i]->data); @@ -887,7 +906,6 @@ void do_final_battleground(void) } aFree(bg->arena); } - } void battleground_defaults(void) { bg = &bg_s; diff --git a/src/map/battleground.h b/src/map/battleground.h index 87d56516a..094037f43 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -5,9 +5,14 @@ #ifndef MAP_BATTLEGROUND_H #define MAP_BATTLEGROUND_H -#include "clif.h" -#include "guild.h" -#include "../common/mmo.h" // struct party +#include "map/map.h" // EVENT_NAME_LENGTH +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" // struct party + +struct HPluginData; +struct block_list; +struct map_session_data; /** * Defines @@ -122,10 +127,10 @@ struct battleground_interface { void (*config_read) (void); }; -struct battleground_interface *bg; - #ifdef HERCULES_CORE void battleground_defaults(void); #endif // HERCULES_CORE +HPShared struct battleground_interface *bg; + #endif /* MAP_BATTLEGROUND_H */ diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 85fef98aa..67018ec1f 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -4,21 +4,23 @@ #define HERCULES_CORE -#include "buyingstore.h" // struct s_buyingstore - -#include "atcommand.h" // msg_txt -#include "battle.h" // battle_config.* -#include "chrif.h" -#include "clif.h" // clif->buyingstore_* -#include "log.h" // log_pick_pc, log_zeny -#include "pc.h" // struct map_session_data -#include "../common/cbasetypes.h" -#include "../common/db.h" // ARR_FIND -#include "../common/showmsg.h" // ShowWarning -#include "../common/socket.h" // RBUF* -#include "../common/strlib.h" // safestrncpy +#include "buyingstore.h" // struct s_buyingstore + +#include "map/atcommand.h" // msg_txt +#include "map/battle.h" // battle_config.* +#include "map/chrif.h" +#include "map/clif.h" // clif-"buyingstore_* +#include "map/log.h" // log_pick_pc, log_zeny +#include "map/pc.h" // struct map_session_data +#include "common/cbasetypes.h" +#include "common/db.h" // ARR_FIND +#include "common/nullpo.h" // nullpo_* +#include "common/showmsg.h" // ShowWarning +#include "common/socket.h" // RBUF* +#include "common/strlib.h" // safestrncpy struct buyingstore_interface buyingstore_s; +struct buyingstore_interface *buyingstore; /// Returns unique buying store id unsigned int buyingstore_getuid(void) { @@ -27,6 +29,7 @@ unsigned int buyingstore_getuid(void) { bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) { + nullpo_retr(false, sd); if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 ) { return false; @@ -43,7 +46,7 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) return false; } - if( map->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) { + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) { // custom: no vending cells clif->message(sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell." return false; @@ -61,11 +64,11 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) return true; } - 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; + nullpo_retv(sd); if (!result || count == 0) { // canceled, or no items return; @@ -97,7 +100,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha return; } - if( map->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) { + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) { // custom: no vending cells clif->message(sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell." return; @@ -177,10 +180,10 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha clif->buyingstore_entry(sd); } - void buyingstore_close(struct map_session_data* sd) { - if( sd->state.buyingstore ) + nullpo_retv(sd); + if (sd->state.buyingstore) { // invalidate data sd->state.buyingstore = false; @@ -191,11 +194,11 @@ void buyingstore_close(struct map_session_data* sd) } } - void buyingstore_open(struct map_session_data* sd, int account_id) { struct map_session_data* pl_sd; + nullpo_retv(sd); if( !battle_config.feature_buying_store || pc_istrading(sd) ) {// not allowed to sell return; @@ -228,6 +231,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int unsigned int i, weight, listidx, k; struct map_session_data* pl_sd; + nullpo_retv(sd); if( count == 0 ) {// nothing to do return; @@ -353,7 +357,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int // 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); + pc->delitem(sd, index, amount, 1, DELITEM_NORMAL, LOG_TYPE_BUYING_STORE); pl_sd->buyingstore.items[listidx].amount-= amount; // pay up @@ -401,7 +405,8 @@ bool buyingstore_search(struct map_session_data* sd, unsigned short nameid) { unsigned int i; - if( !sd->state.buyingstore ) + nullpo_retr(false, sd); + if (!sd->state.buyingstore) {// not buying return false; } @@ -423,6 +428,8 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st unsigned int i, idx; struct s_buyingstore_item* it; + nullpo_retr(true, sd); + if( !sd->state.buyingstore ) {// not buying return true; diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index 7b8e369d2..74f61239f 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -5,8 +5,8 @@ #ifndef MAP_BUYINGSTORE_H #define MAP_BUYINGSTORE_H -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // MAX_SLOTS +#include "common/hercules.h" +#include "common/mmo.h" // MAX_SLOTS struct map_session_data; @@ -71,10 +71,10 @@ struct buyingstore_interface { unsigned int (*getuid) (void); }; -struct buyingstore_interface *buyingstore; - #ifdef HERCULES_CORE void buyingstore_defaults (void); #endif // HERCULES_CORE +HPShared struct buyingstore_interface *buyingstore; + #endif // MAP_BUYINGSTORE_H diff --git a/src/map/channel.c b/src/map/channel.c index 58ff98c2b..196e5f770 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -5,29 +5,30 @@ #include "channel.h" +#include "map/atcommand.h" +#include "map/guild.h" +#include "map/instance.h" +#include "map/irc-bot.h" +#include "map/map.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "guild.h" -#include "instance.h" -#include "irc-bot.h" -#include "map.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct channel_interface channel_s; +struct channel_interface *channel; static struct Channel_Config channel_config; @@ -254,21 +255,22 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const { char message[150]; nullpo_retv(chan); + nullpo_retv(msg); if (sd && chan->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + chan->msg_delay*1000, timer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1455)); + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1455)); return; } else if (sd) { - snprintf(message, 150, "[ #%s ] %s : %s",chan->name,sd->status.name, msg); + safesnprintf(message, 150, "[ #%s ] %s : %s", chan->name, sd->status.name, msg); clif->channel_msg(chan,sd,message); if (chan->type == HCS_TYPE_IRC) ircbot->relay(sd->status.name,msg); if (chan->msg_delay != 0) sd->hchsysch_tick = timer->gettick(); } else { - snprintf(message, 150, "[ #%s ] %s",chan->name, msg); + safesnprintf(message, 150, "[ #%s ] %s", chan->name, msg); clif->channel_msg2(chan, message); if (chan->type == HCS_TYPE_IRC) ircbot->relay(NULL, msg); @@ -301,7 +303,7 @@ void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bo /* someone is cheating, we kindly disconnect the bastard */ if (sd->channel_count > 200) { - set_eof(sd->fd); + sockt->eof(sd->fd); } } @@ -328,6 +330,7 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map nullpo_retr(HCS_STATUS_FAIL, chan); nullpo_retr(HCS_STATUS_FAIL, sd); + nullpo_retr(HCS_STATUS_FAIL, password); if (idb_exists(chan->users, sd->status.char_id)) { return HCS_STATUS_ALREADY; @@ -352,7 +355,7 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map } else { sprintf(output, msg_sd(sd,1403), chan->name); // You're now in the '%s' channel } - clif->colormes(sd->fd, COLOR_DEFAULT, output); + clif->messagecolor_self(sd->fd, COLOR_DEFAULT, output); } if (chan->type == HCS_TYPE_ALLY) { @@ -360,7 +363,7 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map int i; for (i = 0; i < MAX_GUILDALLIANCE; i++) { struct guild *sg = NULL; - if (g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id))) { + if (g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id)) != NULL) { if (!(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) { channel->join_sub(sg->channel, sd, stealth); } @@ -444,6 +447,7 @@ void channel_leave(struct channel_data *chan, struct map_session_data *sd) */ void channel_quit(struct map_session_data *sd) { + nullpo_retv(sd); while (sd->channel_count > 0) { // Loop downward to avoid unnecessary array compactions by channel_leave struct channel_data *chan = sd->channels[sd->channel_count-1]; @@ -460,10 +464,11 @@ void channel_quit(struct map_session_data *sd) /** * Joins the local map channel. * - * @param sd The target character + * @param sd The target character (sd must be non null) */ void channel_map_join(struct map_session_data *sd) { + nullpo_retv(sd); if (sd->state.autotrade || sd->state.standalone) return; if (!map->list[sd->bl.m].channel) { @@ -474,18 +479,20 @@ void channel_map_join(struct map_session_data *sd) map->list[sd->bl.m].channel->m = sd->bl.m; } - channel->join(map->list[sd->bl.m].channel, sd, NULL, false); + channel->join(map->list[sd->bl.m].channel, sd, "", false); } void channel_irc_join(struct map_session_data *sd) { struct channel_data *chan = ircbot->channel; + + nullpo_retv(sd); if (sd->state.autotrade || sd->state.standalone) return; if (channel->config->irc_name[0] == '\0') return; if (chan) - channel->join(chan, sd, NULL, false); + channel->join(chan, sd, "", false); } /** @@ -547,12 +554,13 @@ void channel_guild_leave_alliance(const struct guild *g_source, const struct gui /** * Makes a character quit all guild-related channels. * - * @param sd The character + * @param sd The character (must be non null) */ void channel_quit_guild(struct map_session_data *sd) { unsigned char i; + nullpo_retv(sd); for (i = 0; i < sd->channel_count; i++) { struct channel_data *chan = sd->channels[i]; @@ -693,7 +701,6 @@ void read_channels_config(void) safestrncpy(channel->config->colors_name[i], config_setting_name(color), HCS_NAME_LENGTH); channel->config->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0); - channel->config->colors[i] = (channel->config->colors[i] & 0x0000FF) << 16 | (channel->config->colors[i] & 0x00FF00) | (channel->config->colors[i] & 0xFF0000) >> 16;//RGB to BGR } channel->config->colors_count = color_count; } @@ -770,8 +777,8 @@ void read_channels_config(void) } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename); - libconfig->destroy(&channels_conf); } + libconfig->destroy(&channels_conf); } /*========================================== diff --git a/src/map/channel.h b/src/map/channel.h index 8fbf08d42..391045c59 100644 --- a/src/map/channel.h +++ b/src/map/channel.h @@ -4,11 +4,9 @@ #ifndef MAP_CHANNEL_H #define MAP_CHANNEL_H -#include <stdarg.h> - -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" /** * Declarations @@ -111,10 +109,10 @@ struct channel_interface { void (*config_read) (void); }; -struct channel_interface *channel; - #ifdef HERCULES_CORE void channel_defaults(void); #endif // HERCULES_CORE +HPShared struct channel_interface *channel; + #endif /* MAP_CHANNEL_H */ diff --git a/src/map/chat.c b/src/map/chat.c index a232781ca..976b1ce8e 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -6,24 +6,25 @@ #include "chat.h" +#include "map/atcommand.h" // msg_sd(sd,) +#include "map/battle.h" // struct battle_config +#include "map/clif.h" +#include "map/map.h" +#include "map/npc.h" // npc_event_do() +#include "map/pc.h" +#include "map/skill.h" // ext_skill_unit_onplace() +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" // msg_sd(sd,) -#include "battle.h" // struct battle_config -#include "clif.h" -#include "map.h" -#include "npc.h" // npc_event_do() -#include "pc.h" -#include "skill.h" // ext_skill_unit_onplace() -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" - struct chat_interface chat_s; +struct chat_interface *chat; /// Initializes a chatroom object (common functionality for both pc and npc chatrooms). /// Returns a chatroom object on success, or NULL on failure. @@ -31,6 +32,9 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons { struct chat_data* cd; nullpo_retr(NULL, bl); + nullpo_retr(NULL, title); + nullpo_retr(NULL, pass); + nullpo_retr(NULL, ev); /* Given the overhead and the numerous instances (npc allocated or otherwise) wouldn't it be beneficial to have it use ERS? [Ind] */ cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); @@ -74,6 +78,8 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons bool chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) { struct chat_data* cd; nullpo_ret(sd); + nullpo_ret(title); + nullpo_ret(pass); if( sd->chatID ) return false; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] @@ -88,12 +94,12 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha return false; //Can't create chatrooms on this map. } - if( map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) { + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOCHAT) ) { clif->message (sd->fd, msg_sd(sd,865)); // "Can't create chat rooms in this area." return false; } - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); cd = chat->create(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); if( cd ) { @@ -101,7 +107,7 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha cd->usersd[0] = sd; pc_setchatid(sd,cd->bl.id); pc_stop_attack(sd); - clif->createchat(sd,0); + clif->createchat(sd,0); // 0 = success clif->dispchat(cd,0); return true; } @@ -117,6 +123,7 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { struct chat_data* cd; nullpo_ret(sd); + nullpo_ret(pass); 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 ) @@ -150,7 +157,7 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { return false; } - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); cd->usersd[cd->users] = sd; cd->users++; @@ -254,6 +261,7 @@ bool chat_changechatowner(struct map_session_data* sd, const char* nextownername int i; nullpo_ret(sd); + nullpo_ret(nextownername); cd = (struct chat_data*)map->id2bl(sd->chatID); if( cd == NULL || (struct block_list*) sd != cd->owner ) @@ -297,6 +305,8 @@ bool chat_changechatstatus(struct map_session_data* sd, const char* title, const struct chat_data* cd; nullpo_ret(sd); + nullpo_ret(title); + nullpo_ret(pass); cd = (struct chat_data*)map->id2bl(sd->chatID); if( cd==NULL || (struct block_list *)sd != cd->owner ) @@ -324,6 +334,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) { int i; nullpo_ret(sd); + nullpo_ret(kickusername); cd = (struct chat_data *)map->id2bl(sd->chatID); @@ -339,7 +350,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) { idb_iput(cd->kick_list,cd->usersd[i]->status.char_id,1); - chat->leave(cd->usersd[i],1); + chat->leave(cd->usersd[i], true); return true; } @@ -440,7 +451,7 @@ bool chat_npckickall(struct chat_data* cd) nullpo_ret(cd); while( cd->users > 0 ) - chat->leave(cd->usersd[cd->users-1],0); + chat->leave(cd->usersd[cd->users-1], false); return true; } diff --git a/src/map/chat.h b/src/map/chat.h index ced216b41..68f9107f3 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -5,9 +5,9 @@ #ifndef MAP_CHAT_H #define MAP_CHAT_H -#include "map.h" // struct block_list, CHATROOM_TITLE_SIZE -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" // struct block_list, CHATROOM_TITLE_SIZE +#include "common/hercules.h" +#include "common/db.h" struct chat_data; struct map_session_data; @@ -55,10 +55,10 @@ struct chat_interface { struct chat_data* (*create) (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_interface *chat; - #ifdef HERCULES_CORE void chat_defaults(void); #endif // HERCULES_CORE +HPShared struct chat_interface *chat; + #endif /* MAP_CHAT_H */ diff --git a/src/map/chrif.c b/src/map/chrif.c index 6ac7d5695..1e376e3bc 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -4,41 +4,41 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT +#include "config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT #include "chrif.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/npc.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/types.h> -#include <time.h> - -#include "map.h" -#include "battle.h" -#include "clif.h" -#include "intif.h" -#include "npc.h" -#include "pc.h" -#include "pet.h" -#include "skill.h" -#include "status.h" -#include "homunculus.h" -#include "instance.h" -#include "mercenary.h" -#include "elemental.h" -#include "quest.h" -#include "storage.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" struct chrif_interface chrif_s; +struct chrif_interface *chrif; //Used Packets: //2af8: Outgoing, chrif_connect -> 'connect to charserver / auth @ charserver' @@ -103,11 +103,11 @@ void chrif_reset(void) { /// 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 ) + if( core->runflag != MAPSERVER_ST_SHUTDOWN ) return; if( db_size(chrif->auth_db) > 0 ) return; - runflag = CORE_ST_STOP; + core->runflag = CORE_ST_STOP; } struct auth_node* chrif_search(int account_id) { @@ -125,8 +125,8 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) { 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 ( sockt->session[fd] && sockt->session[fd]->session_data == node->sd ) + sockt->session[fd]->session_data = NULL; if ( node->sd ) { if( node->sd->regs.vars ) @@ -150,6 +150,7 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) { bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) { struct auth_node *node; + nullpo_retr(false, sd); if ( chrif->search(sd->status.account_id) ) return false; //Already exists? @@ -176,10 +177,11 @@ bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) { bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) { + nullpo_retr(false, sd); 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; + if ( sockt->session[sd->fd] ) + sockt->session[sd->fd]->session_data = NULL; sd->fd = 0; } @@ -187,8 +189,10 @@ bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) } bool chrif_auth_finished(TBL_PC* sd) { - struct auth_node *node= chrif->search(sd->status.account_id); + struct auth_node *node; + nullpo_retr(false, sd); + node = chrif->search(sd->status.account_id); if ( node && node->sd == sd && node->state == ST_LOGIN ) { node->sd = NULL; @@ -197,13 +201,16 @@ bool chrif_auth_finished(TBL_PC* sd) { return false; } + // sets char-server's user id void chrif_setuserid(char *id) { + nullpo_retv(id); memcpy(chrif->userid, id, NAME_LENGTH); } // sets char-server's password void chrif_setpasswd(char *pwd) { + nullpo_retv(pwd); memcpy(chrif->passwd, pwd, NAME_LENGTH); } @@ -220,14 +227,15 @@ void chrif_checkdefaultlogin(void) { bool chrif_setip(const char* ip) { char ip_str[16]; - if ( !( chrif->ip = host2ip(ip) ) ) { + nullpo_retr(false, ip); + if (!(chrif->ip = sockt->host2ip(ip))) { ShowWarning("Failed to Resolve Char Server Address! (%s)\n", ip); return false; } safestrncpy(chrif->ip_str, ip, sizeof(chrif->ip_str)); - ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(chrif->ip, ip_str)); + ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, sockt->ip2str(chrif->ip, ip_str)); return true; } @@ -239,7 +247,7 @@ void chrif_setport(uint16 port) { // says whether the char-server is connected or not int chrif_isconnected(void) { - return (chrif->fd > 0 && session[chrif->fd] != NULL && chrif->state == 2); + return (chrif->fd > 0 && sockt->session[chrif->fd] != NULL && chrif->state == 2); } /*========================================== @@ -247,6 +255,7 @@ int chrif_isconnected(void) { * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ +// TODO: Flag enum bool chrif_save(struct map_session_data *sd, int flag) { nullpo_ret(sd); @@ -263,11 +272,11 @@ bool chrif_save(struct map_session_data *sd, int flag) { chrif_check(false); //Character is saved on reconnect. //For data sync - if (sd->state.storage_flag == 2) + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->save(sd->status.account_id, sd->status.guild_id, flag); if (flag) - sd->state.storage_flag = 0; //Force close it. + sd->state.storage_flag = STORAGE_FLAG_CLOSED; //Force close it. //Saving of registry values. if (sd->vars_dirty) @@ -384,7 +393,7 @@ bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) WFIFOL(chrif->fd,24) = htonl(ip); WFIFOW(chrif->fd,28) = htons(port); WFIFOB(chrif->fd,30) = sd->status.sex; - WFIFOL(chrif->fd,31) = htonl(session[sd->fd]->client_addr); + WFIFOL(chrif->fd,31) = htonl(sockt->session[sd->fd]->client_addr); WFIFOL(chrif->fd,35) = sd->group_id; WFIFOSET(chrif->fd,39); @@ -401,7 +410,7 @@ bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int if ( !login_id1 ) { ShowError("chrif_changemapserverack: map server change failed.\n"); - clif->authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); // Disconnected from server } else clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); @@ -445,6 +454,7 @@ void chrif_connectack(int fd) { int chrif_reconnect(DBKey key, DBData *data, va_list ap) { struct auth_node *node = DB->data2ptr(data); + nullpo_ret(node); switch (node->state) { case ST_LOGIN: if ( node->sd ) {//Since there is no way to request the char auth, make it fail. @@ -465,14 +475,13 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) { 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); + clif->authfail_fd(sd->fd, 3); // timeout break; } } return 0; } - /// Called when all the connection steps are completed. void chrif_on_ready(void) { static bool once = false; @@ -502,7 +511,6 @@ void chrif_on_ready(void) { } } - /*========================================== * *------------------------------------------*/ @@ -541,8 +549,9 @@ bool chrif_scdata_request(int account_id, int char_id) void chrif_authreq(struct map_session_data *sd, bool hstandalone) { struct auth_node *node= chrif->search(sd->bl.id); + nullpo_retv(sd); if( node != NULL || !chrif->isconnected() ) { - set_eof(sd->fd); + sockt->eof(sd->fd); return; } @@ -552,7 +561,7 @@ void chrif_authreq(struct map_session_data *sd, bool hstandalone) { WFIFOL(chrif->fd,6) = sd->status.char_id; WFIFOL(chrif->fd,10) = sd->login_id1; WFIFOB(chrif->fd,14) = sd->status.sex; - WFIFOL(chrif->fd,15) = htonl(session[sd->fd]->client_addr); + WFIFOL(chrif->fd,15) = htonl(sockt->session[sd->fd]->client_addr); WFIFOB(chrif->fd,19) = hstandalone ? 1 : 0; WFIFOSET(chrif->fd,20); chrif->sd_to_auth(sd, ST_LOGIN); @@ -607,7 +616,7 @@ void chrif_authok(int fd) { sd = node->sd; - if( runflag == MAPSERVER_ST_RUNNING && + if( core->runflag == MAPSERVER_ST_RUNNING && node->account_id == account_id && node->char_id == char_id && node->login_id1 == login_id1 ) @@ -643,12 +652,11 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used ( node->sex == sex && node->state == ST_LOGIN ) {// found a match - clif->authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); // Disconnected from server chrif->auth_delete(account_id, char_id, ST_LOGIN); } } - /** * This can still happen (client times out while waiting for char to confirm auth data) * @see DBApply @@ -656,6 +664,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used ( int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) { struct auth_node *node = DB->data2ptr(data); + nullpo_retr(1, node); if(DIFF_TICK(timer->gettick(),node->node_created)>60000) { const char* states[] = { "Login", "Logout", "Map change" }; switch (node->state) { @@ -731,6 +740,8 @@ bool 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); + nullpo_retr(false, actual_email); + nullpo_retr(false, new_email); chrif_check(false); WFIFOHEAD(chrif->fd,86); @@ -747,18 +758,19 @@ bool chrif_changeemail(int id, const char *actual_email, const char *new_email) * S 2b0e <accid>.l <name>.24B <type>.w { <additional fields>.12B } * { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } * Send an account modification request to the login server (via char server). - * type of operation {additional fields}: - * 1: block { n/a } - * 2: ban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } - * 3: unblock { n/a } - * 4: unban { n/a } - * 5: changesex { n/a } -- use chrif_changesex - * 6: charban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } - * 7: charunban { n/a } - * 8: changecharsex { <sex>.b } -- use chrif_changesex + * type of operation: @see enum zh_char_ask_name + * block { n/a } + * ban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * unblock { n/a } + * unban { n/a } + * changesex { n/a } -- use chrif_changesex + * charban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * charunban { n/a } + * changecharsex { <sex>.b } -- use chrif_changesex *------------------------------------------*/ bool 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) { + nullpo_retr(false, character_name); chrif_check(false); WFIFOHEAD(chrif->fd,44); @@ -767,7 +779,7 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope safestrncpy((char*)WFIFOP(chrif->fd,6), character_name, NAME_LENGTH); WFIFOW(chrif->fd,30) = operation_type; - if ( operation_type == 2 || operation_type == 6 ) { + if (operation_type == CHAR_ASK_NAME_BAN || operation_type == CHAR_ASK_NAME_CHARBAN) { WFIFOW(chrif->fd,32) = year; WFIFOW(chrif->fd,34) = month; WFIFOW(chrif->fd,36) = day; @@ -782,20 +794,21 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope /** * Requests a sex change (either per character or per account). - * + * * @param sd The character's data. * @param change_account Whether to change the per-account sex. * @retval true. */ bool chrif_changesex(struct map_session_data *sd, bool change_account) { + nullpo_retr(false, sd); chrif_check(false); WFIFOHEAD(chrif->fd,44); WFIFOW(chrif->fd,0) = 0x2b0e; WFIFOL(chrif->fd,2) = sd->status.account_id; safestrncpy((char*)WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH); - WFIFOW(chrif->fd,30) = change_account ? 5 : 8; + WFIFOW(chrif->fd,30) = change_account ? CHAR_ASK_NAME_CHANGESEX : CHAR_ASK_NAME_CHANGECHARSEX; if (!change_account) WFIFOB(chrif->fd,32) = sd->status.sex == SEX_MALE ? SEX_FEMALE : SEX_MALE; WFIFOSET(chrif->fd,44); @@ -812,20 +825,16 @@ bool chrif_changesex(struct map_session_data *sd, bool change_account) /*========================================== * R 2b0f <accid>.l <name>.24B <type>.w <answer>.w * Processing a reply to chrif->char_ask_name() (request to modify an account). - * type of operation: - * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban, 8: changecharsex - * type of answer: - * 0: login-server request done - * 1: player not found - * 2: gm level too low - * 3: login-server offline + * type of operation: @see chrif_char_ask_name + * type of answer: @see hz_char_ask_name_answer *------------------------------------------*/ bool 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]; - bool charsrv = ( type == 6 || type == 7 ) ? true : false; + bool charsrv = ( type == CHAR_ASK_NAME_CHARBAN || type == CHAR_ASK_NAME_CHARUNBAN ) ? true : false; + nullpo_retr(false, player_name); sd = map->id2sd(acc); if( acc < 0 || sd == NULL ) { @@ -834,19 +843,19 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u } /* re-use previous msg_number */ - if( type == 6 ) type = 2; - if( type == 7 ) type = 4; + if( type == CHAR_ASK_NAME_CHARBAN ) type = CHAR_ASK_NAME_BAN; + if( type == CHAR_ASK_NAME_CHARUNBAN ) type = CHAR_ASK_NAME_UNBAN; - if( type > 0 && type <= 5 ) + if( type >= CHAR_ASK_NAME_BLOCK && type <= CHAR_ASK_NAME_CHANGESEX ) snprintf(action,25,"%s",msg_sd(sd,427+type)); //block|ban|unblock|unban|change the sex of else snprintf(action,25,"???"); switch( answer ) { - case 0 : sprintf(output, msg_sd(sd,charsrv?434:424), action, NAME_LENGTH, player_name); break; - case 1 : sprintf(output, msg_sd(sd,425), NAME_LENGTH, player_name); break; - case 2 : sprintf(output, msg_sd(sd,426), action, NAME_LENGTH, player_name); break; - case 3 : sprintf(output, msg_sd(sd,427), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_DONE: sprintf(output, msg_sd(sd,charsrv?434:424), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_NOTFOUND: sprintf(output, msg_sd(sd,425), NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_GMLOW: sprintf(output, msg_sd(sd,426), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_OFFLINE: sprintf(output, msg_sd(sd,427), action, NAME_LENGTH, player_name); break; default: output[0] = '\0'; break; } @@ -904,14 +913,14 @@ bool chrif_divorceack(int char_id, int 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); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, 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); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } return true; @@ -985,7 +994,7 @@ void chrif_idbanned(int fd) { clif->message(sd->fd, tmpstr); } - set_eof(sd->fd); // forced to disconnect for the change + sockt->eof(sd->fd); // forced to disconnect for the change map->quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] } @@ -1029,6 +1038,7 @@ int chrif_disconnectplayer(int fd) { int chrif_updatefamelist(struct map_session_data* sd) { char type; + nullpo_retr(0, sd); chrif_check(-1); switch(sd->class_ & MAPID_UPPERMASK) { @@ -1119,9 +1129,11 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th int i, count=0; int64 tick; struct status_change_data data; - struct status_change *sc = &sd->sc; + struct status_change *sc; const struct TimerData *td; + nullpo_retr(false, sd); + sc = &sd->sc; chrif_check(false); tick = timer->gettick(); @@ -1215,7 +1227,6 @@ bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) { return true; } - /*========================================= * Tell char-server character disconnected [Wizputer] *-----------------------------------------*/ @@ -1237,9 +1248,9 @@ bool chrif_char_offline_nsd(int account_id, int char_id) { bool chrif_flush(void) { chrif_check(false); - set_nonblocking(chrif->fd, 0); - flush_fifos(); - set_nonblocking(chrif->fd, 1); + sockt->set_nonblocking(chrif->fd, 0); + sockt->flush_fifos(); + sockt->set_nonblocking(chrif->fd, 1); return true; } @@ -1258,11 +1269,12 @@ bool chrif_char_reset_offline(void) { } /*========================================= - * Tell char-server character is online [Wizputer] + * Tell char-server character is online [Wizputer]. Look like unused. *-----------------------------------------*/ bool chrif_char_online(struct map_session_data *sd) { chrif_check(false); + nullpo_retr(false, sd); WFIFOHEAD(chrif->fd,10); WFIFOW(chrif->fd,0) = 0x2b19; WFIFOL(chrif->fd,2) = sd->status.char_id; @@ -1285,13 +1297,12 @@ void chrif_on_disconnect(void) { timer->add(timer->gettick() + 1000, chrif->check_connect_char_server, 0, 0); } - void chrif_update_ip(int fd) { uint32 new_ip; WFIFOHEAD(fd,6); - new_ip = host2ip(chrif->ip_str); + new_ip = sockt->host2ip(chrif->ip_str); if (new_ip && new_ip != chrif->ip) chrif->ip = new_ip; //Update chrif->ip @@ -1313,21 +1324,21 @@ void chrif_keepalive(int fd) { WFIFOSET(fd,2); } void chrif_keepalive_ack(int fd) { - session[fd]->flag.ping = 0;/* reset ping state, we received a packet */ + sockt->session[fd]->flag.ping = 0;/* reset ping state, we received a packet */ } void chrif_skillid2idx(int fd) { int i, count = 0; if( fd == 0 ) fd = chrif->fd; - if( !session_isValid(fd) ) + if (!sockt->session_is_valid(fd)) return; WFIFOHEAD(fd,4 + (MAX_SKILL * 4)); WFIFOW(fd,0) = 0x2b0b; for(i = 0; i < MAX_SKILL; i++) { - if( skill->db[i].nameid ) { - WFIFOW(fd, 4 + (count*4)) = skill->db[i].nameid; + if( skill->dbs->db[i].nameid ) { + WFIFOW(fd, 4 + (count*4)) = skill->dbs->db[i].nameid; WFIFOW(fd, 6 + (count*4)) = i; count++; } @@ -1345,22 +1356,22 @@ int chrif_parse(int fd) { // only process data from the char-server if ( fd != chrif->fd ) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); - do_close(fd); + sockt->close(fd); return 0; } - if ( session[fd]->flag.eof ) { - do_close(fd); + if ( sockt->session[fd]->flag.eof ) { + sockt->close(fd); chrif->fd = -1; chrif->on_disconnect(); return 0; - } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ - if( DIFF_TICK(sockt->last_tick, session[fd]->rdata_tick) > (sockt->stall_time * 2) ) {/* we can't wait any longer */ - set_eof(fd); + } else if ( sockt->session[fd]->flag.ping ) {/* we've reached stall time */ + if( DIFF_TICK(sockt->last_tick, sockt->session[fd]->rdata_tick) > (sockt->stall_time * 2) ) {/* we can't wait any longer */ + sockt->eof(fd); return 0; - } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ + } else if( sockt->session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ chrif->keepalive(fd); - session[fd]->flag.ping = 2; + sockt->session[fd]->flag.ping = 2; } } @@ -1382,7 +1393,7 @@ int chrif_parse(int fd) { 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); + sockt->eof(fd); return 0; } @@ -1423,7 +1434,7 @@ int chrif_parse(int fd) { case 0x2b27: chrif->authfail(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); - set_eof(fd); + sockt->eof(fd); return 0; } if ( fd == chrif->fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] @@ -1480,7 +1491,7 @@ bool send_users_tochar(void) { *------------------------------------------*/ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) { static int displayed = 0; - if ( chrif->fd <= 0 || session[chrif->fd] == NULL ) { + if ( chrif->fd <= 0 || sockt->session[chrif->fd] == NULL ) { if ( !displayed ) { ShowStatus("Attempting to connect to Char Server. Please wait.\n"); displayed = 1; @@ -1488,12 +1499,12 @@ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) { chrif->state = 0; - if ( ( chrif->fd = make_connection(chrif->ip, chrif->port,NULL) ) == -1) //Attempt to connect later. [Skotlex] + if ((chrif->fd = sockt->make_connection(chrif->ip, chrif->port,NULL)) == -1) //Attempt to connect later. [Skotlex] return 0; - session[chrif->fd]->func_parse = chrif->parse; - session[chrif->fd]->flag.server = 1; - realloc_fifo(chrif->fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + sockt->session[chrif->fd]->func_parse = chrif->parse; + sockt->session[chrif->fd]->flag.server = 1; + sockt->realloc_fifo(chrif->fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); chrif->connect(chrif->fd); chrif->connected = (chrif->state == 2); @@ -1527,6 +1538,7 @@ bool chrif_removefriend(int char_id, int friend_id) void chrif_send_report(char* buf, int len) { #ifndef STATS_OPT_OUT if( chrif->fd > 0 ) { + nullpo_retv(buf); WFIFOHEAD(chrif->fd,len + 2); WFIFOW(chrif->fd,0) = 0x3008; @@ -1534,7 +1546,7 @@ void chrif_send_report(char* buf, int len) { WFIFOSET(chrif->fd,len + 2); - flush_fifo(chrif->fd); /* ensure it's sent now. */ + sockt->flush(chrif->fd); /* ensure it's sent now. */ } #endif } @@ -1547,6 +1559,7 @@ void chrif_save_scdata_single(int account_id, int char_id, short type, struct st if( !chrif->isconnected() ) return; + nullpo_retv(sce); WFIFOHEAD(chrif->fd, 28); WFIFOW(chrif->fd, 0) = 0x2740; @@ -1586,6 +1599,7 @@ void chrif_del_scdata_single(int account_id, int char_id, short type) int auth_db_final(DBKey key, DBData *data, va_list ap) { struct auth_node *node = DB->data2ptr(data); + nullpo_ret(node); if (node->sd) { if( node->sd->regs.vars ) node->sd->regs.vars->destroy(node->sd->regs.vars, script->reg_destroy); @@ -1606,7 +1620,7 @@ int auth_db_final(DBKey key, DBData *data, va_list ap) { void do_final_chrif(void) { if( chrif->fd != -1 ) { - do_close(chrif->fd); + sockt->close(chrif->fd); chrif->fd = -1; } @@ -1639,7 +1653,6 @@ void do_init_chrif(bool minimal) { timer->add_interval(timer->gettick() + 1000, chrif->send_usercount_tochar, 0, 0, UPDATE_INTERVAL); } - /*===================================== * Default Functions : chrif.h * Generated by HerculesInterfaceMaker @@ -1710,7 +1723,7 @@ void chrif_defaults(void) { chrif->char_offline_nsd = chrif_char_offline_nsd; chrif->char_reset_offline = chrif_char_reset_offline; chrif->send_users_tochar = send_users_tochar; - chrif->char_online = chrif_char_online; + chrif->char_online = chrif_char_online; // look like unused chrif->changesex = chrif_changesex; //chrif->chardisconnect = chrif_chardisconnect; chrif->divorce = chrif_divorce; diff --git a/src/map/chrif.h b/src/map/chrif.h index c90d00ef5..25f69a309 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -5,12 +5,12 @@ #ifndef MAP_CHRIF_H #define MAP_CHRIF_H -#include <time.h> - -#include "map.h" //TBL_stuff -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" //TBL_PC +#include "common/hercules.h" +#include "common/db.h" +struct eri; +struct map_session_data; struct status_change_entry; /** @@ -150,10 +150,10 @@ struct chrif_interface { void (*del_scdata_single) (int account_id, int char_id, short type); }; -struct chrif_interface *chrif; - #ifdef HERCULES_CORE void chrif_defaults(void); #endif // HERCULES_CORE +HPShared struct chrif_interface *chrif; + #endif /* MAP_CHRIF_H */ diff --git a/src/map/clif.c b/src/map/clif.c index efad7b5e1..0d25be0a6 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4,61 +4,64 @@ #define HERCULES_CORE -#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT +#include "config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT #include "clif.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "map/vending.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/ers.h" +#include "common/grfio.h" +#include "common/malloc.h" +#include "common/mmo.h" // NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <time.h> -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/ers.h" -#include "../common/grfio.h" -#include "../common/malloc.h" -#include "../common/mmo.h" // NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct clif_interface clif_s; +struct clif_interface *clif; + +struct s_packet_db packet_db[MAX_PACKET_DB + 1]; /* re-usable */ static struct packet_itemlist_normal itemlist_normal; @@ -89,7 +92,6 @@ static inline int itemtype(int type) { } } - static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) { p += pos; p[0] = (uint8)(x>>2); @@ -97,7 +99,6 @@ static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsig 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) { p += pos; @@ -177,9 +178,14 @@ static inline bool disguised(struct block_list* bl) { return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1 ); } - //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) { + nullpo_retr(0, mes); + if (len <= 0) + { + mes[0] = '\0'; + Assert_retr(0, len > 0); + } if( len > max ) len = max; @@ -193,22 +199,24 @@ static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned i *------------------------------------------*/ bool clif_setip(const char* ip) { char ip_str[16]; - clif->map_ip = host2ip(ip); + nullpo_retr(false, ip); + clif->map_ip = sockt->host2ip(ip); if ( !clif->map_ip ) { ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); return false; } safestrncpy(clif->map_ip_str, ip, sizeof(clif->map_ip_str)); - ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->map_ip, ip_str)); + ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, sockt->ip2str(clif->map_ip, ip_str)); return true; } bool clif_setbindip(const char* ip) { - clif->bind_ip = host2ip(ip); + nullpo_retr(false, ip); + clif->bind_ip = sockt->host2ip(ip); if ( clif->bind_ip ) { char ip_str[16]; - ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->bind_ip, ip_str)); + ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, sockt->ip2str(clif->bind_ip, ip_str)); return true; } ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); @@ -242,10 +250,9 @@ uint16 clif_getport(void) /*========================================== * Updates server ip resolution and returns it *------------------------------------------*/ -uint32 clif_refresh_ip(void) { - uint32 new_ip; - - new_ip = host2ip(clif->map_ip_str); +uint32 clif_refresh_ip(void) +{ + uint32 new_ip = sockt->host2ip(clif->map_ip_str); if ( new_ip && new_ip != clif->map_ip ) { clif->map_ip = new_ip; ShowInfo("Updating IP resolution of [%s].\n", clif->map_ip_str); @@ -256,6 +263,7 @@ uint32 clif_refresh_ip(void) { #if PACKETVER >= 20071106 static inline unsigned char clif_bl_type(struct block_list *bl) { + nullpo_retr(0x1, bl); switch (bl->type) { case BL_PC: return (disguised(bl) && !pc->db_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE case BL_ITEM: return 0x2; //ITEM_TYPE @@ -292,7 +300,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) { nullpo_ret(sd = (struct map_session_data *)bl); fd = sd->fd; - if (!fd || session[fd] == NULL) //Don't send to disconnected clients. + if (!fd || sockt->session[fd] == NULL) //Don't send to disconnected clients. return 0; buf = va_arg(ap,void*); @@ -340,6 +348,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) { int clif_send_actual(int fd, void *buf, int len) { + nullpo_retr(0, buf); WFIFOHEAD(fd, len); if (WFIFOP(fd,0) == buf) { ShowError("WARNING: Invalid use of clif->send function\n"); @@ -389,8 +398,8 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target 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 ) { + while ((tsd = (TBL_PC*)mapit->next(iter)) != NULL) { + if (bl && bl->m == tsd->bl.m) { WFIFOHEAD(tsd->fd, len); memcpy(WFIFOP(tsd->fd,0), buf, len); WFIFOSET(tsd->fd,len); @@ -406,16 +415,19 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target /* Fall through */ case AREA_WOC: case AREA_WOS: + nullpo_retr(true, bl); 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: + nullpo_retr(true, bl); 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: + nullpo_retr(true, bl); { struct chat_data *cd; if (sd) { @@ -428,7 +440,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target for(i = 0; i < cd->users; i++) { if (type == CHAT_WOS && cd->usersd[i] == sd) continue; - if ((fd=cd->usersd[i]->fd) >0 && session[fd]) { // Added check to see if session exists [PoW] + if ((fd=cd->usersd[i]->fd) >0 && sockt->session[fd]) { // Added check to see if session exists [PoW] WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -439,6 +451,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target case PARTY_AREA: case PARTY_AREA_WOS: + nullpo_retr(true, bl); x0 = bl->x - AREA_SIZE; y0 = bl->y - AREA_SIZE; x1 = bl->x + AREA_SIZE; @@ -505,7 +518,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target break; case SELF: - if (sd && (fd=sd->fd) ) { + if (sd && (fd=sd->fd) != 0) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -515,6 +528,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target // New definitions for guilds [Valaris] - Cleaned up and reorganized by [Skotlex] case GUILD_AREA: case GUILD_AREA_WOS: + nullpo_retr(true, bl); x0 = bl->x - AREA_SIZE; y0 = bl->y - AREA_SIZE; x1 = bl->x + AREA_SIZE; @@ -567,6 +581,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target case BG_AREA: case BG_AREA_WOS: + nullpo_retr(true, bl); x0 = bl->x - AREA_SIZE; y0 = bl->y - AREA_SIZE; x1 = bl->x + AREA_SIZE; @@ -600,7 +615,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target for( i = 0; i < queue->size; i++ ) { struct map_session_data *qsd = NULL; - if( queue->item[i] > 0 && ( qsd = map->id2sd(queue->item[i]) ) ) { + if (queue->item[i] > 0 && (qsd = map->id2sd(queue->item[i])) != NULL) { WFIFOHEAD(qsd->fd,len); memcpy(WFIFOP(qsd->fd,0), buf, len); WFIFOSET(qsd->fd,len); @@ -624,11 +639,11 @@ void clif_authok(struct map_session_data *sd) { struct packet_authok p; + nullpo_retv(sd); p.PacketType = authokType; p.startTime = (unsigned int)timer->gettick(); WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */ p.xSize = p.ySize = 5; /* not-used */ - #if PACKETVER >= 20080102 p.font = sd->status.font; #endif @@ -638,7 +653,6 @@ void clif_authok(struct map_session_data *sd) clif->send(&p,sizeof(p),&sd->bl,SELF); } - /// Notifies the client, that it's connection attempt was refused (ZC_REFUSE_ENTER). /// 0074 <error code>.B /// error code: @@ -655,7 +669,6 @@ void clif_authrefuse(int fd, uint8 error_code) WFIFOSET(fd,packet_len(0x74)); } - /// Notifies the client of a ban or forced disconnect (SC_NOTIFY_BAN). /// 0081 <error code>.B /// error code: @@ -688,20 +701,20 @@ void clif_authrefuse(int fd, uint8 error_code) /// 109 = BAN_INVALID_PWD_CNT /// 110 = BAN_NOT_ALLOWED_JOBCLASS /// ? = disconnected -> MsgStringTable[3] +// TODO: type enum 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! + if (!fd || !sockt->session[fd] || sockt->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); + sockt->eof(fd); } - /// Notifies the client, whether it can disconnect and change servers (ZC_RESTART_ACK). /// 00b3 <type>.B /// type: @@ -749,8 +762,6 @@ void clif_dropflooritem(struct flooritem_data* fitem) { clif->send(&p, sizeof(p), &fitem->bl, AREA); } - - /// Makes an item disappear from the ground. /// 00a1 <id>.L (ZC_ITEM_DISAPPEAR) void clif_clearflooritem(struct flooritem_data *fitem, int fd) @@ -771,7 +782,6 @@ void clif_clearflooritem(struct flooritem_data *fitem, int fd) } } - /// Makes a unit (char, npc, mob, homun) disappear to one client (ZC_NOTIFY_VANISH). /// 0080 <id>.L <type>.B /// type: @@ -815,7 +825,6 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) } } - /// Used to make monsters with player-sprites disappear after dying /// like normal monsters, because the client does not remove those /// automatically. @@ -827,7 +836,10 @@ int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) { } void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) { - struct block_list *tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); + struct block_list *tbl; + + nullpo_retv(bl); + tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); memcpy (tbl, bl, sizeof (struct block_list)); timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl); } @@ -835,6 +847,9 @@ void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) { /// Gets weapon view info from sd's inventory_data and points (*rhand,*lhand) void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand) { + nullpo_retv(sd); + nullpo_retv(rhand); + nullpo_retv(lhand); if(sd->sc.option&OPTION_COSTUME) { *rhand = *lhand = 0; return; @@ -884,6 +899,7 @@ static int clif_setlevel_sub(int lv) { static int clif_setlevel(struct block_list* bl) { int lv = status->get_lv(bl); + nullpo_retr(0, bl); if( battle_config.client_limit_unit_lv&bl->type ) return clif_setlevel_sub(lv); switch( bl->type ) { @@ -903,6 +919,7 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en struct packet_idle_unit2 p; int g_id = status->get_guild_id(bl); + nullpo_retv(bl); sd = BL_CAST(BL_PC, bl); p.PacketType = idle_unit2Type; @@ -956,7 +973,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu int g_id = status->get_guild_id(bl); nullpo_retv(bl); - + #if PACKETVER < 20091103 if( !pc->db_checkid(vd->class_) ) { clif->set_unit_idle2(bl,tsd,target); @@ -1043,6 +1060,7 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) { struct packet_spawn_unit2 p; int g_id = status->get_guild_id(bl); + nullpo_retv(bl); sd = BL_CAST(BL_PC, bl); p.PacketType = spawn_unit2Type; @@ -1177,6 +1195,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, int g_id = status->get_guild_id(bl); nullpo_retv(bl); + nullpo_retv(ud); sd = BL_CAST(BL_PC, bl); @@ -1249,7 +1268,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, /// 01b0 <id>.L <type>.B <value>.L /// type: /// unused -void clif_class_change(struct block_list *bl,int class_,int type) +void clif_class_change(struct block_list *bl, int class_, int type) { nullpo_retv(bl); @@ -1264,11 +1283,11 @@ void clif_class_change(struct block_list *bl,int class_,int type) } } - /// Notifies the client of an object's spirits. /// 01d0 <id>.L <amount>.W (ZC_SPIRITS) /// 01e1 <id>.L <amount>.W (ZC_SPIRITS2) void clif_spiritball_single(int fd, struct map_session_data *sd) { + nullpo_retv(sd); WFIFOHEAD(fd, packet_len(0x1e1)); WFIFOW(fd,0)=0x1e1; WFIFOL(fd,2)=sd->bl.id; @@ -1281,6 +1300,7 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) { *------------------------------------------*/ void clif_charm_single(int fd, struct map_session_data *sd) { + nullpo_retv(sd); WFIFOHEAD(fd, packet_len(0x08cf)); WFIFOW(fd,0) = 0x08cf; WFIFOL(fd,2) = sd->bl.id; @@ -1294,9 +1314,12 @@ void clif_charm_single(int fd, struct map_session_data *sd) * Tells its client to display all weather settings being used by this map *------------------------------------------*/ void clif_weather_check(struct map_session_data *sd) { - int16 m = sd->bl.m; - int fd = sd->fd; + int16 m; + int fd; + nullpo_retv(sd); + m = sd->bl.m; + fd = sd->fd; if (map->list[m].flag.snow) clif->specialeffect_single(&sd->bl, 162, fd); if (map->list[m].flag.clouds) @@ -1338,6 +1361,7 @@ bool clif_spawn(struct block_list *bl) { struct view_data *vd; + nullpo_retr(false, bl); vd = status->get_viewdata(bl); if( !vd ) return false; @@ -1354,7 +1378,6 @@ bool clif_spawn(struct block_list *bl) if (vd->cloth_color) clif->refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - switch (bl->type) { case BL_PC: { @@ -1369,7 +1392,7 @@ bool clif_spawn(struct block_list *bl) if( sd->bg_id && map->list[sd->bl.m].flag.battleground ) clif->sendbgemblem_area(sd); for( i = 0; i < sd->sc_display_count; i++ ) { - clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); + clif->sc_load(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) clif->spiritcharm(sd); @@ -1410,6 +1433,7 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) unsigned char buf[128]; enum homun_type htype; + nullpo_retv(sd); nullpo_retv(hd); hstatus = &hd->battle_status; @@ -1476,7 +1500,6 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) clif->send(buf,packet_len(0x22e),&sd->bl,SELF); } - /// Notification about a change in homunuculus' state (ZC_CHANGESTATE_MER). /// 0230 <type>.B <state>.B <id>.L <data>.L /// type: @@ -1489,8 +1512,12 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) /// ? = ignored void clif_send_homdata(struct map_session_data *sd, int state, int param) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + nullpo_retv(sd->hd); + fd = sd->fd; if ( (state == SP_INTIMATE) && (param >= 910) && (sd->hd->homunculus.class_ == sd->hd->homunculusDB->evo_class) ) homun->calc_skilltree(sd->hd, 0); @@ -1520,19 +1547,24 @@ void clif_homskillinfoblock(struct map_session_data *sd) { WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL); WFIFOW(fd,0)=0x235; - for ( i = 0; i < MAX_HOMUNSKILL; i++){ + for ( i = 0; i < MAX_HOMUNSKILL; i++ ) { int id = hd->homunculus.hskill[i].id; - if (id != 0) { + if ( 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 < homun->skill_tree_get_max(id, hd->homunculus.class_))?1:0; - len+=37; + 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; + if ( 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); + } else { + WFIFOW(fd, len + 8) = 0; + WFIFOW(fd, len + 10) = 0; + } + safestrncpy((char*)WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); + WFIFOB(fd, len + 36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_)) ? 1 : 0; + len += 37; } } WFIFOW(fd,2)=len; @@ -1545,6 +1577,7 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn] struct homun_data *hd; int fd, idx; nullpo_retv(sd); + nullpo_retv(sd->hd); idx = skill_id - HM_SKILLBASE; fd=sd->fd; @@ -1575,13 +1608,14 @@ void clif_hom_food(struct map_session_data *sd,int foodid,int fail) return; } - /// Notifies the client, that it is walking (ZC_NOTIFY_PLAYERMOVE). /// 0087 <walk start time>.L <walk data>.6B void clif_walkok(struct map_session_data *sd) { - int fd=sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x87)); WFIFOW(fd,0)=0x87; WFIFOL(fd,2)=(unsigned int)timer->gettick(); @@ -1589,14 +1623,20 @@ void clif_walkok(struct map_session_data *sd) WFIFOSET(fd,packet_len(0x87)); } - void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) { #ifdef ANTI_MAYAP_CHEAT struct status_change *sc = NULL; +#endif + nullpo_retv(bl); + nullpo_retv(vd); + nullpo_retv(ud); + +#ifdef ANTI_MAYAP_CHEAT if( (sc = status->get_sc(bl)) && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK) ) clif->ally_only = true; #endif + clif->set_unit_walking(bl,NULL,ud,AREA_WOS); if(vd->cloth_color) @@ -1632,7 +1672,6 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u #endif } - /// Notifies clients in an area, that an other visible object is walking (ZC_NOTIFY_PLAYERMOVE). /// 0086 <id>.L <walk data>.6B <walk start time>.L /// Note: unit must not be self @@ -1640,10 +1679,14 @@ void clif_move(struct unit_data *ud) { unsigned char buf[16]; struct view_data *vd; - struct block_list *bl = ud->bl; + struct block_list *bl; #ifdef ANTI_MAYAP_CHEAT struct status_change *sc = NULL; #endif + + nullpo_retv(ud); + bl = ud->bl; + nullpo_retv(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. @@ -1682,7 +1725,6 @@ void clif_move(struct unit_data *ud) #endif } - /*========================================== * Delays the map->quit of a player after they are disconnected. [Skotlex] *------------------------------------------*/ @@ -1698,14 +1740,15 @@ int clif_delayquit(int tid, int64 tick, int id, intptr_t data) { /*========================================== * *------------------------------------------*/ -void clif_quitsave(int fd,struct map_session_data *sd) { +void clif_quitsave(int fd, struct map_session_data *sd) { + nullpo_retv(sd); if (!battle_config.prevent_logout || DIFF_TICK(timer->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; + sockt->session[sd->fd]->session_data = NULL; sd->fd = 0; timer->add(timer->gettick() + 10000, clif->delayquit, sd->bl.id, 0); } @@ -1726,7 +1769,6 @@ void clif_changemap(struct map_session_data *sd, short m, int x, int 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) { @@ -1740,19 +1782,18 @@ void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, WFIFOW(fd,18) = x; WFIFOW(fd,20) = y; WFIFOL(fd,22) = htonl(ip); - WFIFOW(fd,26) = ntows(htons(port)); // [!] LE byte order here [!] + WFIFOW(fd,26) = sockt->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. + nullpo_retv(bl); clif->fixpos(bl); clif->slide(bl, bl->x, bl->y); } - /// Visually moves(slides) a character to x,y. If the target cell /// isn't walkable, the char doesn't move at all. If the char is /// sitting it will stand up (ZC_STOPMOVE). @@ -1774,7 +1815,6 @@ void clif_fixpos(struct block_list *bl) { } } - /// 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) @@ -1790,7 +1830,6 @@ void clif_npcbuysell(struct map_session_data* sd, int id) WFIFOSET(fd,packet_len(0xc4)); } - /// Presents list of items, that can be bought in an NPC shop (ZC_PC_PURCHASE_ITEMLIST). /// 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) { @@ -1853,7 +1892,7 @@ void clif_selllist(struct map_session_data *sd) if( sd->status.inventory[i].expire_time ) continue; // Cannot Sell Rental Items - + if( sd->status.inventory[i].bound && !pc_can_give_bound_items(sd)) continue; // Don't allow sale of bound items @@ -1870,7 +1909,6 @@ void clif_selllist(struct map_session_data *sd) WFIFOSET(fd,WFIFOW(fd,2)); } - /// Displays an NPC dialog message (ZC_SAY_DIALOG). /// 00b4 <packet len>.W <npc id>.L <message>.?B /// Client behavior (dialog window): @@ -1881,7 +1919,11 @@ 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; - size_t slen = strlen(mes) + 9; + size_t slen; + + nullpo_retv(sd); + nullpo_retv(mes); + slen = strlen(mes) + 9; sd->state.dialog = 1; @@ -1893,7 +1935,6 @@ void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Adds a 'next' button to an NPC dialog (ZC_WAIT_DIALOG). /// 00b5 <npc id>.L /// Client behavior (dialog window): @@ -1904,7 +1945,7 @@ void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) { /// - 00B9 <npcid of dialog window>.L /// - set to clear on next mes /// - remove 'next' button -void clif_scriptnext(struct map_session_data *sd,int npcid) +void clif_scriptnext(struct map_session_data *sd, int npcid) { int fd; @@ -1917,7 +1958,6 @@ void clif_scriptnext(struct map_session_data *sd,int npcid) WFIFOSET(fd,packet_len(0xb5)); } - /// Adds a 'close' button to an NPC dialog (ZC_CLOSE_DIALOG). /// 00b6 <npc id>.L /// Client behavior: @@ -1951,9 +1991,11 @@ 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; + int fd; + nullpo_retv(sd); + 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)); @@ -1970,7 +2012,6 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) { WFIFOSET(fd, packet_len(0x78)); } - /// Displays an NPC dialog menu (ZC_MENU_LIST). /// 00b7 <packet len>.W <npc id>.L <menu items>.?B /// Client behavior: @@ -1992,11 +2033,15 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) { /// 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) { - int fd = sd->fd; - size_t slen = strlen(mes) + 9; + int fd; + size_t slen; struct block_list *bl = NULL; - if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m || + nullpo_retv(sd); + nullpo_retv(mes); + fd = sd->fd; + slen = strlen(mes) + 9; + if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (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); @@ -2009,7 +2054,6 @@ void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Displays an NPC dialog input box for numbers (ZC_OPEN_EDITDLG). /// 0142 <npc id>.L /// Client behavior (inputnum window): @@ -2027,7 +2071,7 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) { nullpo_retv(sd); - if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m || + if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (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); @@ -2039,7 +2083,6 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) { WFIFOSET(fd,packet_len(0x142)); } - /// Displays an NPC dialog input box for numbers (ZC_OPEN_EDITDLGSTR). /// 01d4 <npc id>.L /// Client behavior (inputstr window): @@ -2057,7 +2100,7 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) { nullpo_retv(sd); - if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m || + if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (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); @@ -2069,7 +2112,6 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) { WFIFOSET(fd,packet_len(0x1d4)); } - /// Marks a position on client's minimap (ZC_COMPASS). /// 0144 <npc id>.L <type>.L <x>.L <y>.L <id>.B <color>.L /// npc id: @@ -2121,12 +2163,12 @@ void clif_cutin(struct map_session_data* sd, const char* image, int type) WFIFOSET(fd,packet_len(0x1b3)); } - /*========================================== * Fills in card data from the given item and into the buffer. [Skotlex] *------------------------------------------*/ void clif_addcards(unsigned char* buf, struct item* item) { int i=0,j; + nullpo_retv(buf); if( item == NULL ) { //Blank data WBUFW(buf,0) = 0; WBUFW(buf,2) = 0; @@ -2176,6 +2218,7 @@ void clif_addcards(unsigned char* buf, struct item* item) { void clif_addcards2(unsigned short *cards, struct item* item) { int i=0,j; + nullpo_retv(cards); if( item == NULL ) { //Blank data cards[0] = 0; cards[1] = 0; @@ -2223,16 +2266,37 @@ void clif_addcards2(unsigned short *cards, struct item* item) { cards[3] = item->card[i]; } +/** + * Fills in RandomOptions(Bonuses) of items into the buffer + * + * Dummy datais used since this feature isn't supported yet (ITEM_RDM_OPT). + * A maximum of 5 random options can be supported. + * + * @param buf[in,out] The buffer to write to. The pointer must be valid and initialized. + * @param item[in] The source item. + */ +void clif_add_random_options(unsigned char* buf, struct item* item) +{ + int i; + nullpo_retv(buf); + for (i = 0; i < 5; i++){ + WBUFW(buf,i*5+0) = 0; // OptIndex + WBUFW(buf,i*5+2) = 0; // Value + WBUFB(buf,i*5+4) = 0; // Param1 + } +} /// Notifies the client, about a received inventory item or the result of a pick-up request. /// 00a0 <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 (ZC_ITEM_PICKUP_ACK) /// 029a <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 (ZC_ITEM_PICKUP_ACK2) /// 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) +/// 0990 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V5) +/// 0a0c <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V6) void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { struct packet_additem p; nullpo_retv(sd); - if( !session_isActive(sd->fd) ) //Sasuke- + if (!sockt->session_is_active(sd->fd)) //Sasuke- return; if( fail ) @@ -2243,6 +2307,9 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { p.count = amount; if( !fail ) { +#if PACKETVER >= 20150226 + int i; +#endif if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; @@ -2266,13 +2333,19 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { */ p.bindOnEquipType = sd->status.inventory[n].bound && !itemdb->isstackable2(sd->inventory_data[n]) ? 2 : sd->inventory_data[n]->flag.bindonequip ? 1 : 0; #endif +#if PACKETVER >= 20150226 + for (i=0; i<5; i++){ + p.option_data[i].index = 0; + p.option_data[i].value = 0; + p.option_data[i].param = 0; + } +#endif } p.result = (unsigned char)fail; clif->send(&p,sizeof(p),&sd->bl,SELF); } - /// Notifies the client, that an inventory item was deleted or dropped (ZC_ITEM_THROW_ACK). /// 00af <index>.W <amount>.W void clif_dropitem(struct map_session_data *sd,int n,int amount) @@ -2289,18 +2362,9 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount) WFIFOSET(fd,packet_len(0xaf)); } - /// Notifies the client, that an inventory item was deleted (ZC_DELETE_ITEM_FROM_BODY). /// 07fa <delete type>.W <index>.W <amount>.W -/// delete type: -/// 0 = Normal -/// 1 = Item used for a skill -/// 2 = Refine failed -/// 3 = Material changed -/// 4 = Moved to storage -/// 5 = Moved to cart -/// 6 = Item sold -/// 7 = Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill +/// delete type: @see enum delitem_reason void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) { #if PACKETVER < 20091117 @@ -2321,10 +2385,10 @@ void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) #endif } - // Simplifies inventory/cart/storage packets by handling the packet section relevant to items. [Skotlex] // Equip is >= 0 for equippable items (holds the equip-point, is 0 for pet // armor/egg) -1 for stackable items, -2 for stackable items where arrows must send in the equip-point. +// look like unused, not adding checks 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; @@ -2346,8 +2410,14 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data * } } -void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) { +void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) { +#if PACKETVER >= 20150226 + int j; +#endif + nullpo_retv(p); + nullpo_retv(i); + nullpo_retv(id); p->index = idx; if (id->view_id > 0) @@ -2363,7 +2433,6 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct p->location = eqp_pos; p->WearState = i->equip; - #if PACKETVER < 20120925 p->IsDamaged = i->attribute ? 1 : 0; #endif @@ -2374,7 +2443,7 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct #if PACKETVER >= 20071002 p->HireExpireDate = i->expire_time; #endif - + #if PACKETVER >= 20080102 p->bindOnEquipType = i->bound ? 2 : id->flag.bindonequip ? 1 : 0; #endif @@ -2389,8 +2458,22 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct p->Flag.PlaceETCTab = i->favorite ? 1 : 0; p->Flag.SpareBits = 0; #endif + +#if PACKETVER >= 20150226 + p->option_count = 0; + for (j=0; j<5; j++){ + p->option_data[j].index = 0; + p->option_data[j].value = 0; + p->option_data[j].param = 0; + } +#endif } + void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id) { + nullpo_retv(p); + nullpo_retv(i); + nullpo_retv(id); + p->index = idx; if (id->view_id > 0) @@ -2399,18 +2482,18 @@ void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, stru p->ITID = i->nameid; p->type = itemtype(id->type); - + #if PACKETVER < 20120925 p->IsIdentified = i->identify ? 1 : 0; #endif p->count = i->amount; p->WearState = id->equip; - + #if PACKETVER >= 5 clif->addcards2(&p->slot.card[0], i); #endif - + #if PACKETVER >= 20080102 p->HireExpireDate = i->expire_time; #endif @@ -2421,17 +2504,19 @@ void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, stru p->Flag.SpareBits = 0; #endif } + void clif_inventorylist(struct map_session_data *sd) { int i, normal = 0, equip = 0; + nullpo_retv(sd); for( i = 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) - clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); + clif->item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); else //Stackable (Normal) - clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.inventory[i],sd->inventory_data[i]); + clif->item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.inventory[i],sd->inventory_data[i]); } if( normal ) { @@ -2466,12 +2551,13 @@ void clif_inventorylist(struct map_session_data *sd) { void clif_equiplist(struct map_session_data *sd) { int i, equip = 0; + nullpo_retv(sd); for( i = 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) - clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); + clif->item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i)); } if( equip ) { @@ -2497,6 +2583,8 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items int i = 0; struct item_data *id; + nullpo_retv(sd); + nullpo_retv(items); do { int normal = 0, equip = 0, k = 0; @@ -2508,9 +2596,9 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items id = itemdb->search(items[i].nameid); if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable) - clif_item_equip(i+1,&storelist_equip.list[equip++],&items[i],id,id->equip); + clif->item_equip(i+1,&storelist_equip.list[equip++],&items[i],id,id->equip); else //Stackable (Normal) - clif_item_normal(i+1,&storelist_normal.list[normal++],&items[i],id); + clif->item_normal(i+1,&storelist_normal.list[normal++],&items[i],id); } if( normal ) { @@ -2543,17 +2631,17 @@ void clif_cartlist(struct map_session_data *sd) { int i, normal = 0, equip = 0; struct item_data *id; + nullpo_retv(sd); for( i = 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) ) //Non-stackable (Equippable) - clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.cart[i],id,id->equip); + clif->item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.cart[i],id,id->equip); else //Stackable (Normal) - clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.cart[i],id); + clif->item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.cart[i],id); } if( normal ) { @@ -2571,7 +2659,6 @@ void clif_cartlist(struct map_session_data *sd) { } } - /// Removes cart (ZC_CARTOFF). /// 012b /// Client behavior: @@ -2585,7 +2672,6 @@ void clif_clearcart(int fd) } - /// Guild XY locators (ZC_NOTIFY_POSITION_TO_GUILDM) [Valaris] /// 01eb <account id>.L <x>.W <y>.W void clif_guild_xy(struct map_session_data *sd) @@ -2609,6 +2695,7 @@ void clif_guild_xy_single(int fd, struct map_session_data *sd) if( sd->bg_id ) return; + nullpo_retv(sd); WFIFOHEAD(fd,packet_len(0x1eb)); WFIFOW(fd,0)=0x1eb; WFIFOL(fd,2)=sd->status.account_id; @@ -2699,7 +2786,7 @@ void clif_updatestatus(struct map_session_data *sd,int type) fd=sd->fd; - if ( !session_isActive(fd) ) // Invalid pointer fix, by sasuke [Kevin] + if (!sockt->session_is_active(fd)) // Invalid pointer fix, by sasuke [Kevin] return; WFIFOHEAD(fd, 14); @@ -2801,13 +2888,11 @@ void clif_updatestatus(struct map_session_data *sd,int type) WFIFOL(fd,4)=sd->battle_status.cri/10; break; case SP_MATK1: - WFIFOL(fd,4)=pc_rightside_matk(sd); + WFIFOL(fd,4)=pc_rightside_matk(sd); break; case SP_MATK2: - WFIFOL(fd,4)=pc_leftside_matk(sd); + WFIFOL(fd,4)=pc_leftside_matk(sd); break; - - case SP_ZENY: WFIFOW(fd,0)=0xb1; WFIFOL(fd,4)=sd->status.zeny; @@ -3107,7 +3192,6 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta clif->sendlook(bl, id, type, val, 0, target); } - /// Character status (ZC_STATUS). /// 00bd <stpoint>.W <str>.B <need str>.B <agi>.B <need agi>.B <vit>.B <need vit>.B /// <int>.B <need int>.B <dex>.B <need dex>.B <luk>.B <need luk>.B <atk>.W <atk2>.W @@ -3171,7 +3255,6 @@ void clif_initialstatus(struct map_session_data *sd) { clif->updatestatus(sd,SP_ASPD); } - /// Marks an ammunition item in inventory as equipped (ZC_EQUIP_ARROW). /// 013c <index>.W void clif_arrowequip(struct map_session_data *sd,int val) @@ -3190,7 +3273,6 @@ void clif_arrowequip(struct map_session_data *sd,int val) WFIFOSET(fd,packet_len(0x013c)); } - /// Ammunition action message (ZC_ACTION_FAILURE). /// 013b <type>.W /// type: @@ -3213,7 +3295,6 @@ void clif_arrow_fail(struct map_session_data *sd,int type) WFIFOSET(fd,packet_len(0x013b)); } - /// Presents a list of items, that can be processed by Arrow Crafting (ZC_MAKINGARROW_LIST). /// 01ad <packet len>.W { <name id>.W }* void clif_arrow_create_list(struct map_session_data *sd) @@ -3229,14 +3310,14 @@ void clif_arrow_create_list(struct map_session_data *sd) for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) { int j; - if (skill->arrow_db[i].nameid > 0 - && (j = pc->search_inventory(sd, skill->arrow_db[i].nameid)) != INDEX_NOT_FOUND + if (skill->dbs->arrow_db[i].nameid > 0 + && (j = pc->search_inventory(sd, skill->dbs->arrow_db[i].nameid)) != INDEX_NOT_FOUND && !sd->status.inventory[j].equip && sd->status.inventory[j].identify ) { - if ((j = itemdb_viewid(skill->arrow_db[i].nameid)) > 0) + if ((j = itemdb_viewid(skill->dbs->arrow_db[i].nameid)) > 0) WFIFOW(fd,c*2+4) = j; else - WFIFOW(fd,c*2+4) = skill->arrow_db[i].nameid; + WFIFOW(fd,c*2+4) = skill->dbs->arrow_db[i].nameid; c++; } } @@ -3248,7 +3329,6 @@ void clif_arrow_create_list(struct map_session_data *sd) } } - /// Notifies the client, about the result of an status change request (ZC_STATUS_CHANGE_ACK). /// 00bc <status id>.W <result>.B <value>.B /// status id: @@ -3271,7 +3351,6 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val) WFIFOSET(fd,packet_len(0xbc)); } - /// Notifies the client about the result of a request to equip an item (ZC_REQ_WEAR_EQUIP_ACK). /// 00aa <index>.W <equip location>.W <result>.B /// 00aa <index>.W <equip location>.W <view id>.W <result>.B (PACKETVER >= 20100629) @@ -3294,7 +3373,6 @@ void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_IT clif->send(&p, sizeof(p), &sd->bl, SELF); } - /// Notifies the client about the result of a request to take off an item (ZC_REQ_TAKEOFF_EQUIP_ACK). /// 00ac <index>.W <equip location>.W <result>.B void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result) { @@ -3310,7 +3388,6 @@ void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUI clif->send(&p, sizeof(p), &sd->bl, SELF); } - /// Notifies clients in the area about an special/visual effect (ZC_NOTIFY_EFFECT). /// 019b <id>.L <effect id>.L /// effect id: @@ -3337,7 +3414,6 @@ void clif_misceffect(struct block_list* bl,int type) 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) @@ -3388,13 +3464,13 @@ void clif_changeoption(struct block_list* bl) #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) { unsigned char buf[20]; struct status_change *sc; + nullpo_retv(bl); if ( !(sc = status->get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc? WBUFW(buf,0) = 0x28a; @@ -3413,7 +3489,6 @@ void clif_changeoption2(struct block_list* bl) { clif->send(buf,packet_len(0x28a),bl,AREA); } - /// Notifies the client about the result of an item use request. /// 00a8 <index>.W <amount>.W <result>.B (ZC_USE_ITEM_ACK) /// 01c8 <index>.W <name id>.W <id>.L <amount>.W <result>.B (ZC_USE_ITEM_ACK2) @@ -3462,6 +3537,7 @@ 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 +// TODO: Flag enum void clif_createchat(struct map_session_data* sd, int flag) { int fd; @@ -3475,7 +3551,6 @@ void clif_createchat(struct map_session_data* sd, int flag) WFIFOSET(fd,packet_len(0xd6)); } - /// Display a chat above the owner (ZC_ROOM_NEWENTRY). /// 00d7 <packet len>.W <owner id>.L <char id>.L <limit>.W <users>.W <type>.B <title>.?B /// type: @@ -3513,7 +3588,6 @@ void clif_dispchat(struct chat_data* cd, int fd) } } - /// Chatroom properties adjustment (ZC_CHANGE_CHATROOM). /// 00df <packet len>.W <owner id>.L <chat id>.L <limit>.W <users>.W <type>.B <title>.?B /// type: @@ -3545,7 +3619,6 @@ void clif_changechatstatus(struct chat_data* cd) clif->send(buf,WBUFW(buf,2),cd->owner,CHAT); } - /// Removes the chatroom (ZC_DESTROY_ROOM). /// 00d8 <chat id>.L void clif_clearchat(struct chat_data *cd,int fd) @@ -3565,7 +3638,6 @@ void clif_clearchat(struct chat_data *cd,int fd) } } - /// Displays messages regarding join chat failures (ZC_REFUSE_ENTER_ROOM). /// 00da <result>.B /// result: @@ -3591,7 +3663,6 @@ void clif_joinchatfail(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0xda)); } - /// Notifies the client about entering a chatroom (ZC_ENTER_ROOM). /// 00db <packet len>.W <chat id>.L { <role>.L <name>.24B }* /// role: @@ -3606,7 +3677,7 @@ void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd) nullpo_retv(cd); fd = sd->fd; - if (!session_isActive(fd)) + if (!sockt->session_is_active(fd)) return; t = (int)(cd->owner->type == BL_NPC); WFIFOHEAD(fd, 8 + (28*(cd->users+t))); @@ -3630,7 +3701,6 @@ void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd) 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) @@ -3646,7 +3716,6 @@ void clif_addchat(struct chat_data* cd,struct map_session_data *sd) clif->send(buf,packet_len(0xdc),&sd->bl,CHAT_WOS); } - /// Announce the new owner (ZC_ROLE_CHANGE). /// 00e1 <role>.L <nick>.24B /// role: @@ -3670,7 +3739,6 @@ void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd) clif->send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); } - /// Notify about user leaving the chatroom (ZC_MEMBER_EXIT). /// 00dd <users>.W <nick>.24B <flag>.B /// flag: @@ -3691,21 +3759,28 @@ void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag 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) { - int fd = sd->fd; +void clif_traderequest(struct map_session_data *sd, const char *name) +{ + int fd; +#if PACKETVER >= 6 + struct map_session_data* tsd = NULL; +#endif // PACKETVER >= 6 + nullpo_retv(sd); + nullpo_retv(name); + 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)); #else // PACKETVER >= 6 - struct map_session_data* tsd = map->id2sd(sd->trade_partner); - if( !tsd ) return; + tsd = map->id2sd(sd->trade_partner); + if (!tsd) + return; WFIFOHEAD(fd,packet_len(0x1f4)); WFIFOW(fd,0) = 0x1f4; @@ -3716,7 +3791,6 @@ void clif_traderequest(struct map_session_data* sd, const char* name) { #endif // PACKETVER < 6 } - /// Reply to a trade-request. /// 00e7 <result>.B (ZC_ACK_EXCHANGE_ITEM) /// 01f5 <result>.B <charid>.L <baselvl>.W (ZC_ACK_EXCHANGE_ITEM2) @@ -3727,11 +3801,18 @@ 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; +void clif_tradestart(struct map_session_data *sd, uint8 type) +{ + int fd; #if PACKETVER >= 6 - struct map_session_data* tsd = map->id2sd(sd->trade_partner); - if( tsd ) { + struct map_session_data *tsd = NULL; +#endif // PACKETVER >= 6 + nullpo_retv(sd); + + fd = sd->fd; +#if PACKETVER >= 6 + tsd = map->id2sd(sd->trade_partner); + if (tsd) { WFIFOHEAD(fd,packet_len(0x1f5)); WFIFOW(fd,0) = 0x1f5; WFIFOB(fd,2) = type; @@ -3747,7 +3828,6 @@ void clif_tradestart(struct map_session_data* sd, uint8 type) { WFIFOSET(fd,packet_len(0xe7)); } - /// 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) @@ -3755,18 +3835,13 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd { int fd; unsigned char *buf; -#if PACKETVER < 20100223 - const int cmd = 0xe9; -#else - 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; + WFIFOHEAD(fd,packet_len(tradeaddType)); + WBUFW(buf,0) = tradeaddType; if( index == 0 ) { #if PACKETVER < 20100223 @@ -3785,6 +3860,9 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFW(buf,13)= 0; //card (4w) WBUFW(buf,15)= 0; //card (4w) WBUFW(buf,17)= 0; //card (4w) +#if PACKETVER >= 20150226 + clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); +#endif } else { @@ -3808,11 +3886,13 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd 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]); +#if PACKETVER >= 20150226 + clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); +#endif } - WFIFOSET(fd,packet_len(cmd)); + WFIFOSET(fd,packet_len(tradeaddType)); } - /// Notifies the client about the result of request to add an item to the current trade (ZC_ACK_ADD_EXCHANGE_ITEM). /// 00ea <index>.W <result>.B /// result: @@ -3832,7 +3912,6 @@ void clif_tradeitemok(struct map_session_data* sd, int index, int fail) WFIFOSET(fd,packet_len(0xea)); } - /// Notifies the client about finishing one side of the current trade (ZC_CONCLUDE_EXCHANGE_ITEM). /// 00ec <who>.B /// who: @@ -3850,7 +3929,6 @@ void clif_tradedeal_lock(struct map_session_data* sd, int 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) @@ -3864,7 +3942,6 @@ void clif_tradecancelled(struct map_session_data* sd) WFIFOSET(fd,packet_len(0xee)); } - /// Result of a trade (ZC_EXEC_EXCHANGE_ITEM). /// 00f0 <result>.B /// result: @@ -3882,21 +3959,22 @@ void clif_tradecompleted(struct map_session_data* sd, int fail) WFIFOSET(fd,packet_len(0xf0)); } - /// Resets the trade window on the send side (ZC_EXCHANGEITEM_UNDO). /// 00f1 /// NOTE: Unknown purpose. Items are not removed until the window is /// refreshed (ex. by putting another item in there). +/// unused void clif_tradeundo(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; 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) @@ -3913,46 +3991,38 @@ void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_a 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) { int view,fd; + int offset = 0; 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)); -#else - WFIFOHEAD(fd,packet_len(0x1c4)); - WFIFOW(fd, 0) = 0x1c4; // Storage item added + WFIFOHEAD(fd,packet_len(storageaddType)); + WFIFOW(fd, 0) = storageaddType; // Storage item added WFIFOW(fd, 2) = index+1; // index WFIFOL(fd, 4) = amount; // amount WFIFOW(fd, 8) = ( view > 0 ) ? view : i->nameid; // id +#if PACKETVER >= 5 WFIFOB(fd,10) = itemtype(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)); + offset += 1; #endif + WFIFOB(fd,10+offset) = i->identify; //identify flag + WFIFOB(fd,11+offset) = i->attribute; // attribute + WFIFOB(fd,12+offset) = i->refine; //refine + clif->addcards(WFIFOP(fd,13+offset), i); +#if PACKETVER >= 20150226 + clif->add_random_options(WFIFOP(fd,21+offset), i); +#endif + WFIFOSET(fd,packet_len(storageaddType)); } - /// 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) @@ -3969,7 +4039,6 @@ void clif_storageitemremoved(struct map_session_data* sd, int index, int amount) WFIFOSET(fd,packet_len(0xf6)); } - /// Closes storage (ZC_CLOSE_STORE). /// 00f8 void clif_storageclose(struct map_session_data* sd) @@ -3991,6 +4060,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds struct block_list *d_bl; int i; + nullpo_retv(sd); + nullpo_retv(dstsd); if( dstsd->chatID ) { struct chat_data *cd = NULL; if( (cd = (struct chat_data*)map->id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd) @@ -4006,7 +4077,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds clif->charm_single(sd->fd, dstsd); for( i = 0; i < dstsd->sc_display_count; i++ ) { - clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); + clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } 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 @@ -4015,11 +4086,11 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds 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); + ARR_FIND( 0, MAX_PC_DEVOTION, i, sd->devotion[i] == dstsd->bl.id ); + if( i < MAX_PC_DEVOTION ) 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); + ARR_FIND( 0, MAX_PC_DEVOTION, i, dstsd->devotion[i] > 0 ); + if( i < MAX_PC_DEVOTION ) 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); @@ -4029,6 +4100,9 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { struct unit_data *ud; struct view_data *vd; + nullpo_retv(sd); + nullpo_retv(bl); + vd = status->get_viewdata(bl); if (!vd || vd->class_ == INVISIBLE_CLASS) return; @@ -4084,10 +4158,10 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { else if(md->special_state.size==SZ_MEDIUM) clif->specialeffect_single(bl,421,sd->fd); #if PACKETVER >= 20120404 - if( !(md->status.mode&MD_BOSS) ){ + if (battle_config.show_monster_hp_bar && !(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 ) { + if (md->dmglog[i].id == sd->status.char_id) { clif->monster_hp_bar(md, sd); break; } @@ -4117,6 +4191,7 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i if (type == 4 || type == 9 || damage <=0) return 0; + nullpo_retr(delay, bl); if (bl->type == BL_PC) { if (battle_config.pc_walk_delay_rate != 100) delay = delay*battle_config.pc_walk_delay_rate/100; @@ -4130,24 +4205,11 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i return delay>0?delay:1; //Return 1 to specify there should be no noticeable delay, but you should stop walking. } - /// Sends a 'damage' packet (src performs action on dst) /// 008a <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.W <div>.W <type>.B <damage2>.W (ZC_NOTIFY_ACT) /// 02e1 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <div>.W <type>.B <damage2>.L (ZC_NOTIFY_ACT2) -/// type: -/// 0 = damage [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ] -/// 1 = pick up item -/// 2 = sit down -/// 3 = stand up -/// 4 = damage (endure) -/// 5 = (splash?) -/// 6 = (skill?) -/// 7 = (repeat damage?) -/// 8 = multi-hit damage -/// 9 = multi-hit damage (endure) -/// 10 = critical hit -/// 11 = lucky dodge -/// 12 = (touch skill?) +/// type: @see enum battle_dmg_type +/// for BDT_NORMAL: [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ] int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type, int64 in_damage2) { struct packet_damage p; struct status_change *sc; @@ -4166,7 +4228,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int if(in_damage) in_damage = in_damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; if(in_damage2) in_damage2 = in_damage2*(sc->data[SC_ILLUSION]->val2) + rnd()%100; } - + #if PACKETVER < 20071113 damage = (short)min(in_damage,INT16_MAX); damage2 = (short)min(in_damage2,INT16_MAX); @@ -4225,7 +4287,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int *------------------------------------------*/ void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif->damage(src,dst,0,0,0,0,1,0); + //clif->damage(src,dst,0,0,0,0,BDT_PICKUP,0); unsigned char buf[32]; nullpo_retv(src); @@ -4277,7 +4339,6 @@ void clif_standing(struct block_list* bl) } } - /// Inform client(s) about a map-cell change (ZC_UPDATE_MAPINFO). /// 0192 <x>.W <y>.W <type>.W <map name>.16B void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target) { @@ -4303,11 +4364,13 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe } } - /// 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) { int view,fd; + + nullpo_retv(sd); + nullpo_retv(fitem); fd=sd->fd; WFIFOHEAD(fd,packet_len(0x9d)); @@ -4329,6 +4392,9 @@ void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fi void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send_target target) { struct packet_graffiti_entry p; + nullpo_retv(bl); + nullpo_retv(su); + nullpo_retv(su->group); p.PacketType = graffiti_entryType; p.AID = su->bl.id; p.creatorAID = su->group->src_id; @@ -4351,6 +4417,7 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en struct packet_skill_entry p; nullpo_retv(bl); nullpo_retv(su); + nullpo_retv(su->group); if( su->group->state.guildaura ) return; @@ -4363,7 +4430,6 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en #endif p.PacketType = skill_entryType; - #if PACKETVER >= 20110718 p.PacketLength = sizeof(p); #endif @@ -4379,7 +4445,7 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en p.job = UNT_DUMMYSKILL; else p.job = su->group->unit_id; - + #if PACKETVER >= 20110718 p.RadiusRange = (unsigned char)su->range; #endif @@ -4396,7 +4462,6 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en clif->changemapcell(bl->type == BL_PC ? ((TBL_PC*)bl)->fd : 0,su->bl.m,su->bl.x,su->bl.y,5,SELF); } - /*========================================== * Server tells client to remove unit of id 'unit->bl.id' *------------------------------------------*/ @@ -4412,7 +4477,6 @@ void clif_clearchar_skillunit(struct skill_unit *su, int fd) { clif->changemapcell(fd,su->bl.m,su->bl.x,su->bl.y,su->val2,SELF); } - /// Removes a skill unit (ZC_SKILL_DISAPPEAR). /// 0120 <id>.L void clif_skill_delunit(struct skill_unit *su) { @@ -4425,7 +4489,6 @@ void clif_skill_delunit(struct skill_unit *su) { clif->send(buf,packet_len(0x120),&su->bl,AREA); } - /// Sent when an object gets ankle-snared (ZC_SKILL_UPDATE). /// 01ac <id>.L /// Only affects units with class [139,153] client-side. @@ -4440,7 +4503,6 @@ void clif_skillunit_update(struct block_list* bl) clif->send(buf,packet_len(0x1ac),bl,AREA); } - /*========================================== * *------------------------------------------*/ @@ -4562,7 +4624,6 @@ int clif_insight(struct block_list *bl,va_list ap) return 0; } - /// Updates whole skill tree (ZC_SKILLINFO_LIST). /// 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) @@ -4623,32 +4684,38 @@ 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, idx = skill->get_index(id); + int fd, skill_lv, idx = skill->get_index(id); nullpo_retv(sd); fd = sd->fd; if (!fd) return; - if( sd->status.skill[idx].id <= 0 ) + if (sd->status.skill[idx].id <= 0) return; + skill_lv = sd->status.skill[idx].lv; + 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[idx].lv; - WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[idx].lv); - WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[idx].lv); + WFIFOW(fd,8) = skill_lv; + if (skill_lv > 0) { + WFIFOW(fd,10) = skill->get_sp(id, skill_lv); + WFIFOW(fd,12) = skill->get_range2(&sd->bl, id, skill_lv); + } else { + WFIFOW(fd,10) = 0; + WFIFOW(fd,12) = 0; + } safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,38) = (sd->status.skill[idx].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; + if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) + WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len(0x111)); } - /// Deletes a skill from the skill tree (ZC_SKILLINFO_DELETE). /// 0441 <skill id>.W void clif_deleteskill(struct map_session_data *sd, int id) @@ -4695,29 +4762,38 @@ void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, in WFIFOSET(fd, packet_len(0x10e)); } - /// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE2). /// 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_id, int inf) { const int fd = sd->fd; int idx = skill->get_index(skill_id); + int skill_lv; + + nullpo_retv(sd); + Assert_retv(idx >= 0 && idx < MAX_SKILL); + + skill_lv = sd->status.skill[idx].lv; WFIFOHEAD(fd,packet_len(0x7e1)); WFIFOW(fd,0) = 0x7e1; WFIFOW(fd,2) = skill_id; WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id); - WFIFOW(fd,8) = sd->status.skill[idx].lv; - WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[idx].lv); - WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; + WFIFOW(fd,8) = skill_lv; + if (skill_lv > 0) { + WFIFOW(fd,10) = skill->get_sp(skill_id, skill_lv); + WFIFOW(fd,12) = skill->get_range2(&sd->bl, skill_id, skill_lv); + } else { + WFIFOW(fd,10) = 0; + WFIFOW(fd,12) = 0; + } + if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) + WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; else WFIFOB(fd,14) = 0; WFIFOSET(fd,packet_len(0x7e1)); } - /// Notifies clients in area, that an object is about to use a skill. /// 013e <src id>.L <dst id>.L <x>.W <y>.W <skill id>.W <property>.L <delaytime>.L (ZC_USESKILL_ACK) /// 07fb <src id>.L <dst id>.L <x>.W <y>.W <skill id>.W <property>.L <delaytime>.L <is disposable>.B (ZC_USESKILL_ACK2) @@ -4762,7 +4838,6 @@ void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, 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) @@ -4776,7 +4851,6 @@ void clif_skillcastcancel(struct block_list* bl) clif->send(buf,packet_len(0x1b9), bl, AREA); } - /// Notifies the client about the result of a skill use request (ZC_ACK_TOUSESKILL). /// 0110 <skill id>.W <num>.L <result>.B <cause>.B /// num (only used when skill id = NV_BASIC and cause = 0): @@ -4834,7 +4908,6 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f WFIFOSET(fd,packet_len(0x110)); } - /// Skill cooldown display icon (ZC_SKILL_POSTDELAY). /// 043d <skill ID>.W <tick>.L void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration) @@ -4853,7 +4926,6 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned #endif } - /// Skill attack effect and damage. /// 0114 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.W <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL) /// 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) @@ -4867,11 +4939,11 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick damage = (int)cap_value(in_damage,INT_MIN,INT_MAX); type = clif_calc_delay(type,div,damage,ddelay); - + #if PACKETVER >= 20131223 if( type == 6 ) type = 8; //bugreport:8263 #endif - + if( ( sc = status->get_sc(dst) ) && sc->count ) { if(sc->data[SC_ILLUSION] && damage) damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; @@ -4945,7 +5017,6 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick return clif->calc_walkdelay(dst,ddelay,type,damage,div); } - /// Ground skill attack effect and damage (ZC_NOTIFY_SKILL_POSITION). /// 0115 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <x>.W <y>.W <damage>.W <level>.W <div>.W <type>.B #if 0 @@ -5003,7 +5074,6 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic } #endif // 0 - /// Non-damaging skill effect (ZC_USE_SKILL). /// 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,uint16 skill_id,int heal,int fail) @@ -5036,7 +5106,6 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski return fail; } - /// Non-damaging ground skill effect (ZC_NOTIFY_GROUNDSKILL). /// 0117 <skill id>.W <src id>.L <level>.W <x>.W <y>.W <tick>.L void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick) { @@ -5064,6 +5133,7 @@ void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4) { int fd; + nullpo_retv(sd); fd = sd->fd; @@ -5087,7 +5157,6 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s sd->menuskill_val = skill_lv; } - /// Memo message (ZC_ACK_REMEMBER_WARPPOINT). /// 011e <type>.B /// type: @@ -5110,7 +5179,6 @@ void clif_skill_memomessage(struct map_session_data* sd, int type) WFIFOSET(fd,packet_len(0x11e)); } - /// Teleport message (ZC_NOTIFY_MAPINFO). /// 0189 <type>.W /// type: @@ -5133,7 +5201,6 @@ void clif_skill_mapinfomessage(struct map_session_data *sd, int type) WFIFOSET(fd,packet_len(0x189)); } - /// Displays Sense (WZ_ESTIMATION) information window (ZC_MONSTER_INFO). /// 018c <class>.W <level>.W <size>.W <hp>.L <def>.W <race>.W <mdef>.W <element>.W /// <water%>.B <earth%>.B <fire%>.B <wind%>.B <poison%>.B <holy%>.B <shadow%>.B <ghost%>.B <undead%>.B @@ -5170,7 +5237,6 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) { clif->send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF); } - /// Presents a textual list of producible items (ZC_MAKABLEITEMLIST). /// 018d <packet len>.W { <name id>.W { <material id>.W }*3 }* /// material id: @@ -5190,13 +5256,13 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int 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) && - ( ( skill_id > 0 && skill->produce_db[i].req_skill == skill_id ) || skill_id < 0 ) + if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid, trigger, 1) && + ( ( skill_id > 0 && skill->dbs->produce_db[i].req_skill == skill_id ) || skill_id < 0 ) ){ - if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0) + if((view = itemdb_viewid(skill->dbs->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+ 4)= skill->dbs->produce_db[i].nameid; WFIFOW(fd,c*8+ 6)= 0; WFIFOW(fd,c*8+ 8)= 0; WFIFOW(fd,c*8+10)= 0; @@ -5212,7 +5278,6 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int } } - /// Present a list of producible items (ZC_MAKINGITEM_LIST). /// 025a <packet len>.W <mk type>.W { <name id>.W }* /// mk type: @@ -5237,13 +5302,13 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id c = 0; for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { - if( !skill->can_produce_mix(sd,skill->produce_db[i].nameid,trigger, qty) ) + if( !skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,trigger, qty) ) continue; - if( (view = itemdb_viewid(skill->produce_db[i].nameid)) > 0 ) + if( (view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0 ) WFIFOW(fd, 6 + 2 * c) = view; else - WFIFOW(fd, 6 + 2 * c) = skill->produce_db[i].nameid; + WFIFOW(fd, 6 + 2 * c) = skill->dbs->produce_db[i].nameid; c++; } @@ -5267,7 +5332,7 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking. // It fails. #if PACKETVER >= 20090922 - clif->msg_skill(sd,skill_id,0x625); + clif->msgtable_skill(sd, skill_id, MSG_COOKING_LIST_FAIL); #else WFIFOW(fd,2) = 6 + 2 * c; WFIFOSET(fd,WFIFOW(fd,2)); @@ -5325,7 +5390,7 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val p.index = type; p.AID = bl->id; p.state = (unsigned char)flag; - + #if PACKETVER >= 20120618 p.Total = tick; /* at this stage remain and total are the same value I believe */ #endif @@ -5349,7 +5414,7 @@ void clif_displaymessage(const int fd, const char* mes) { #if PACKETVER == 20141022 /** for some reason game client crashes depending on message pattern (only for this packet) **/ /** so we redirect to ZC_NPC_CHAT **/ - clif->colormes(fd,COLOR_DEFAULT,mes); + clif->messagecolor_self(fd, COLOR_DEFAULT, mes); #else size_t len; @@ -5363,8 +5428,8 @@ void clif_displaymessage(const int fd, const char* mes) { #endif } } + void clif_displaymessage2(const int fd, const char* mes) { - // invalid pointer? nullpo_retv(mes); //Scrapped, as these are shared by disconnected players =X [Skotlex] @@ -5401,10 +5466,11 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) __attribute void clif_displaymessage_sprintf(const int fd, const char *mes, ...) { va_list ap; + nullpo_retv(mes); if (map->cpsd_active && fd == 0) { ShowInfo("HCP: "); va_start(ap,mes); - vShowMessage_(MSG_NONE,mes,ap); + vShowMessage(mes,ap); va_end(ap); ShowMessage("\n"); } else if (fd > 0) { @@ -5431,10 +5497,13 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) { } /// 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, size_t len, int type, enum send_target target) +void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type, enum send_target target) { int lp = (type&BC_COLOR_MASK) ? 4 : 0; - unsigned char *buf = (unsigned char*)aMalloc((4 + lp + len)*sizeof(unsigned char)); + unsigned char *buf = NULL; + nullpo_retv(mes); + + buf = aMalloc((4 + lp + len)*sizeof(unsigned char)); WBUFW(buf,0) = 0x9a; WBUFW(buf,2) = 4 + lp + len; @@ -5479,8 +5548,11 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) { /// 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, size_t len, unsigned int 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; + + nullpo_retv(mes); + buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char)); WBUFW(buf,0) = 0x1c3; WBUFW(buf,2) = len + 16; WBUFL(buf,4) = fontColor; @@ -5494,7 +5566,6 @@ void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigne aFree(buf); } - /// Displays heal effect (ZC_RECOVERY). /// 013d <var id>.W <amount>.W /// var id: @@ -5510,7 +5581,6 @@ void clif_heal(int fd,int type,int val) WFIFOSET(fd,packet_len(0x13d)); } - /// Displays resurrection effect (ZC_RESURRECTION). /// 0148 <id>.L <type>.W /// type: @@ -5535,7 +5605,6 @@ void clif_resurrection(struct block_list *bl,int type) } } - /// Sets the map property (ZC_NOTIFY_MAPPROPERTY). /// 0199 <type>.W void clif_map_property(struct map_session_data* sd, enum map_property property) @@ -5551,7 +5620,6 @@ void clif_map_property(struct map_session_data* sd, enum map_property 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) { @@ -5566,11 +5634,13 @@ void clif_map_type(struct map_session_data* sd, enum map_type type) { WFIFOSET(fd,packet_len(0x1D6)); } - /// Updates PvP ranking (ZC_NOTIFY_RANKING). /// 019a <id>.L <ranking>.L <total>.L +// FIXME: missing documentation for the 'type' parameter void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) { + nullpo_retv(sd); + if(type == 2) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x19a)); @@ -5597,7 +5667,6 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) } } - /*========================================== * *------------------------------------------*/ @@ -5614,7 +5683,6 @@ void clif_map_property_mapall(int mapid, enum map_property property) clif->send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); } - /// Notifies the client about the result of a refine attempt (ZC_ACK_ITEMREFINING). /// 0188 <result>.W <index>.W <refine>.W /// result: @@ -5631,7 +5699,6 @@ void clif_refine(int fd, int fail, int index, int val) WFIFOSET(fd,packet_len(0x188)); } - /// Notifies the client about the result of a weapon refine attempt (ZC_ACK_WEAPONREFINE). /// 0223 <result>.L <nameid>.W /// result: @@ -5648,11 +5715,17 @@ void clif_upgrademessage(int fd, int result, int 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, size_t mes_len) { +void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len) +{ +#if PACKETVER >= 20091104 + struct map_session_data *ssd = NULL; +#endif // PACKETVER >= 20091104 + nullpo_retv(nick); + nullpo_retv(mes); + #if PACKETVER < 20091104 WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4); WFIFOW(fd,0) = 0x97; @@ -5661,7 +5734,7 @@ void clif_wis_message(int fd, const char* nick, const char* mes, size_t mes_len) safestrncpy((char*)WFIFOP(fd,28), mes, mes_len); WFIFOSET(fd,WFIFOW(fd,2)); #else - struct map_session_data *ssd = map->nick2sd(nick); + ssd = map->nick2sd(nick); WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8); WFIFOW(fd,0) = 0x97; @@ -5673,7 +5746,6 @@ void clif_wis_message(int fd, const char* nick, const char* mes, size_t mes_len) #endif } - /// Inform the player about the result of his whisper action (ZC_ACK_WHISPER). /// 0098 <result>.B /// result: @@ -5682,7 +5754,7 @@ void clif_wis_message(int fd, const char* nick, const char* mes, size_t mes_len) /// 2 = ignored by target /// 3 = everyone ignored by target void clif_wis_end(int fd, int flag) { - struct map_session_data *sd = session_isValid(fd) ? session[fd]->session_data : NULL; + struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL; struct packet_wis_end p; if( !sd ) @@ -5693,15 +5765,15 @@ void clif_wis_end(int fd, int flag) { #if PACKETVER >= 20131223 p.unknown = 0; #endif - + clif->send(&p, sizeof(p), &sd->bl, SELF); } - /// 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) { + nullpo_retv(name); WFIFOHEAD(fd,packet_len(0x194)); WFIFOW(fd,0)=0x194; WFIFOL(fd,2)=charid; @@ -5709,62 +5781,36 @@ void clif_solved_charname(int fd, int charid, const char* name) WFIFOSET(fd,packet_len(0x194)); } - /// Presents a list of items that can be carded/composed (ZC_ITEMCOMPOSITION_LIST). /// 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; + int fd; nullpo_retv(sd); - if (idx < 0 || idx >= MAX_INVENTORY) //Crash-fix from bad packets. + fd = sd->fd; + if (sd->state.trading != 0) + return; + if (!pc->can_insert_card(sd, idx)) return; - 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; - - 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->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]->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; + WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); + WFIFOW(fd, 0) = 0x17b; - if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped + for (i = c = 0; i < MAX_INVENTORY; i++) { + if (!pc->can_insert_card_into(sd, idx, i)) continue; - - WFIFOW(fd,4+c*2)=i+2; + WFIFOW(fd, 4 + c * 2) = i + 2; c++; } - if( !c ) return; // no item is available for card insertion + if (!c) return; // no item is available for card insertion - WFIFOW(fd,2)=4+c*2; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd, 2) = 4 + c * 2; + WFIFOSET(fd, WFIFOW(fd, 2)); } - /// Notifies the client about the result of item carding/composition (ZC_ACK_ITEMCOMPOSITION). /// 017d <equip index>.W <card index>.W <result>.B /// result: @@ -5785,7 +5831,6 @@ void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int WFIFOSET(fd,packet_len(0x17d)); } - /// Presents a list of items that can be identified (ZC_ITEMIDENTIFY_LIST). /// 0177 <packet len>.W { <name id>.W }* void clif_item_identify_list(struct map_session_data *sd) @@ -5814,7 +5859,6 @@ void clif_item_identify_list(struct map_session_data *sd) } } - /// Notifies the client about the result of a item identify request (ZC_ACK_ITEMIDENTIFY). /// 0179 <index>.W <result>.B void clif_item_identified(struct map_session_data *sd,int idx,int flag) @@ -5831,7 +5875,6 @@ void clif_item_identified(struct map_session_data *sd,int idx,int flag) WFIFOSET(fd,packet_len(0x179)); } - /// Presents a list of items that can be repaired (ZC_REPAIRITEMLIST). /// 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) @@ -5866,7 +5909,6 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); } - /// Notifies the client about the result of a item repair request (ZC_ACK_ITEMREPAIR). /// 01fe <index>.W <result>.B /// index: @@ -5890,12 +5932,14 @@ void clif_item_repaireffect(struct map_session_data *sd,int idx,int flag) } - /// 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) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x2bb)); WFIFOW(fd,0) = 0x2bb; @@ -5904,7 +5948,6 @@ void clif_item_damaged(struct map_session_data* sd, unsigned short position) WFIFOSET(fd,packet_len(0x2bb)); } - /// Presents a list of weapon items that can be refined [Taken from jAthena] (ZC_NOTIFY_WEAPONITEMLIST). /// 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) @@ -5941,7 +5984,6 @@ void clif_item_refine_list(struct map_session_data *sd) } } - /// Notification of an auto-casted skill (ZC_AUTORUN_SKILL). /// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv) @@ -5964,7 +6006,6 @@ void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv WFIFOSET(fd,packet_len(0x147)); } - /// Adds an item to character's cart. /// 0124 <index>.W <amount>.L <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_CART) /// 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) @@ -5972,6 +6013,7 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) { int view,fd; unsigned char *buf; + int offset = 0; nullpo_retv(sd); @@ -5979,41 +6021,29 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) 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)); -#else - WFIFOHEAD(fd,packet_len(0x1c5)); + WFIFOHEAD(fd,packet_len(cartaddType)); buf=WFIFOP(fd,0); - WBUFW(buf,0)=0x1c5; + WBUFW(buf,0)=cartaddType; 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; +#if PACKETVER >= 5 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)); + offset = 1; +#endif + WBUFB(buf,10+offset)=sd->status.cart[n].identify; + WBUFB(buf,11+offset)=sd->status.cart[n].attribute; + WBUFB(buf,12+offset)=sd->status.cart[n].refine; + clif->addcards(WBUFP(buf,13+offset), &sd->status.cart[n]); +#if PACKETVER >= 20150226 + clif->add_random_options(WBUFP(buf,21+offset), &sd->status.cart[n]); #endif + WFIFOSET(fd,packet_len(cartaddType)); } - /// Deletes an item from character's cart (ZC_DELETE_ITEM_FROM_CART). /// 0125 <index>.W <amount>.L void clif_cart_delitem(struct map_session_data *sd,int n,int amount) @@ -6031,7 +6061,6 @@ void clif_cart_delitem(struct map_session_data *sd,int n,int amount) WFIFOSET(fd,packet_len(0x125)); } - /// Opens the shop creation menu (ZC_OPENSTORE). /// 012d <num>.W /// num: @@ -6049,7 +6078,6 @@ void clif_openvendingreq(struct map_session_data* sd, int 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) @@ -6071,7 +6099,6 @@ void clif_showvendingboard(struct block_list* bl, const char* message, int fd) } } - /// Removes a vending board from screen (ZC_DISAPPEAR_ENTRY). /// 0132 <owner id>.L void clif_closevendingboard(struct block_list* bl, int fd) @@ -6091,7 +6118,6 @@ void clif_closevendingboard(struct block_list* bl, int fd) } } - /// 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) @@ -6107,6 +6133,12 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven const int offset = 12; #endif +#if PACKETVER >= 20150226 + const int item_length = 47; +#else + const int item_length = 22; +#endif + nullpo_retv(sd); nullpo_retv(vending_items); nullpo_retv(vsd=map->id2sd(id)); @@ -6114,9 +6146,9 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven fd = sd->fd; count = vsd->vend_num; - WFIFOHEAD(fd, offset+count*22); + WFIFOHEAD(fd, offset+count*item_length); WFIFOW(fd,0) = cmd; - WFIFOW(fd,2) = offset+count*22; + WFIFOW(fd,2) = offset+count*item_length; WFIFOL(fd,4) = id; #if PACKETVER >= 20100105 WFIFOL(fd,8) = vsd->vender_id; @@ -6125,20 +6157,22 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven for( i = 0; i < count; i++ ) { int index = vending_items[i].index; struct item_data* data = itemdb->search(vsd->status.cart[index].nameid); - WFIFOL(fd,offset+ 0+i*22) = vending_items[i].value; - WFIFOW(fd,offset+ 4+i*22) = vending_items[i].amount; - WFIFOW(fd,offset+ 6+i*22) = vending_items[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]); + WFIFOL(fd,offset+ 0+i*item_length) = vending_items[i].value; + WFIFOW(fd,offset+ 4+i*item_length) = vending_items[i].amount; + WFIFOW(fd,offset+ 6+i*item_length) = vending_items[i].index + 2; + WFIFOB(fd,offset+ 8+i*item_length) = itemtype(data->type); + WFIFOW(fd,offset+ 9+i*item_length) = ( data->view_id > 0 ) ? data->view_id : vsd->status.cart[index].nameid; + WFIFOB(fd,offset+11+i*item_length) = vsd->status.cart[index].identify; + WFIFOB(fd,offset+12+i*item_length) = vsd->status.cart[index].attribute; + WFIFOB(fd,offset+13+i*item_length) = vsd->status.cart[index].refine; + clif->addcards(WFIFOP(fd,offset+14+i*item_length), &vsd->status.cart[index]); +#if PACKETVER >= 20150226 + clif->add_random_options(WFIFOP(fd,offset+22+i*item_length), &vsd->status.cart[index]); +#endif } WFIFOSET(fd,WFIFOW(fd,2)); } - /// Shop purchase failure (ZC_PC_PURCHASE_RESULT_FROMMC). /// 0135 <index>.W <amount>.W <result>.B /// result: @@ -6164,37 +6198,46 @@ void clif_buyvending(struct map_session_data* sd, int index, int amount, int fai 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_items) { int i,fd; int count; +#if PACKETVER >= 20150226 + const int item_length = 47; +#else + const int item_length = 22; +#endif + nullpo_retv(sd); + nullpo_retv(vending_items); fd = sd->fd; count = sd->vend_num; - WFIFOHEAD(fd, 8+count*22); + WFIFOHEAD(fd, 8+count*item_length); WFIFOW(fd,0) = 0x136; - WFIFOW(fd,2) = 8+count*22; + WFIFOW(fd,2) = 8+count*item_length; WFIFOL(fd,4) = id; for( i = 0; i < count; i++ ) { int index = vending_items[i].index; struct item_data* data = itemdb->search(sd->status.cart[index].nameid); - WFIFOL(fd, 8+i*22) = vending_items[i].value; - WFIFOW(fd,12+i*22) = vending_items[i].index + 2; - WFIFOW(fd,14+i*22) = vending_items[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]); + WFIFOL(fd, 8+i*item_length) = vending_items[i].value; + WFIFOW(fd,12+i*item_length) = vending_items[i].index + 2; + WFIFOW(fd,14+i*item_length) = vending_items[i].amount; + WFIFOB(fd,16+i*item_length) = itemtype(data->type); + WFIFOW(fd,17+i*item_length) = ( data->view_id > 0 ) ? data->view_id : sd->status.cart[index].nameid; + WFIFOB(fd,19+i*item_length) = sd->status.cart[index].identify; + WFIFOB(fd,20+i*item_length) = sd->status.cart[index].attribute; + WFIFOB(fd,21+i*item_length) = sd->status.cart[index].refine; + clif->addcards(WFIFOP(fd,22+i*item_length), &sd->status.cart[index]); +#if PACKETVER >= 20150226 + clif->add_random_options(WFIFOP(fd,30+22+i*item_length), &sd->status.cart[index]); +#endif } WFIFOSET(fd,WFIFOW(fd,2)); - + #if PACKETVER >= 20141022 /** should go elsewhere perhaps? it has to be bundled with this however. **/ WFIFOHEAD(fd, 3); @@ -6204,7 +6247,6 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven #endif } - /// 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) @@ -6221,7 +6263,6 @@ void clif_vendingreport(struct map_session_data* sd, int index, int amount) WFIFOSET(fd,packet_len(0x137)); } - /// Result of organizing a party (ZC_ACK_MAKE_GROUP). /// 00fa <result>.B /// result: @@ -6243,7 +6284,6 @@ void clif_party_created(struct map_session_data *sd,int result) WFIFOSET(fd,packet_len(0xfa)); } - /// Adds new member to a party. /// 0104 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B (ZC_ADD_MEMBER_TO_GROUP) /// 01e9 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B <item pickup rule>.B <item share rule>.B (ZC_ADD_MEMBER_TO_GROUP2) @@ -6258,6 +6298,8 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) unsigned char buf[81]; int i; + nullpo_retv(p); + nullpo_retv(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 { @@ -6280,7 +6322,6 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY); } - /// Sends party information (ZC_GROUP_LIST). /// 00fb <packet len>.W <party name>.24B { <account id>.L <nick>.24B <map name>.16B <role>.B <state>.B }* /// role: @@ -6322,7 +6363,6 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd) } } - /// The player's 'party invite' state, sent during login (ZC_PARTY_CONFIG). /// 02c9 <flag>.B /// flag: @@ -6340,7 +6380,6 @@ void clif_partyinvitationstate(struct map_session_data* sd) WFIFOSET(fd, packet_len(0x2c9)); } - /// Party invitation request. /// 00fe <party id>.L <party name>.24B (ZC_REQ_JOIN_GROUP) /// 02c6 <party id>.L <party name>.24B (ZC_PARTY_JOIN_REQ) @@ -6369,7 +6408,6 @@ void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd) WFIFOSET(fd,packet_len(cmd)); } - /// Party invite result. /// 00fd <nick>.24S <result>.B (ZC_ACK_REQ_JOIN_GROUP) /// 02c5 <nick>.24S <result>.L (ZC_PARTY_JOIN_REQ_ACK) @@ -6386,6 +6424,7 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res { int fd; nullpo_retv(sd); + nullpo_retv(nick); fd=sd->fd; #if PACKETVER < 20070904 @@ -6410,7 +6449,6 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res #endif } - /// Updates party settings. /// 0101 <exp option>.L (ZC_GROUPINFO_CHANGE) /// 07d8 <exp option>.L <item pick rule>.B <item share rule>.B (ZC_REQ_GROUPINFO_CHANGE_V2) @@ -6453,7 +6491,6 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag clif->send(buf,packet_len(cmd),&sd->bl,SELF); } - /// 0105 <account id>.L <char name>.24B <result>.B (ZC_DELETE_MEMBER_FROM_GROUP). /// result: /// 0 = leave @@ -6465,17 +6502,18 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int unsigned char buf[64]; nullpo_retv(p); + nullpo_retv(name); - if(!sd && (flag&0xf0)==0) - { + if(!sd && (flag&0xf0)==0) { // TODO: Document this flag int i; - for(i=0;i<MAX_PARTY && !p->data[i].sd;i++) - ; - if (i < MAX_PARTY) - sd = p->data[i].sd; + // Search for any online party member + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL); + if (i != MAX_PARTY) + sd = p->data[i].sd; } - if(!sd) return; + if (!sd) + return; WBUFW(buf,0)=0x105; WBUFL(buf,2)=account_id; @@ -6487,7 +6525,6 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int 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) @@ -6496,6 +6533,7 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i int i; nullpo_retv(p); + nullpo_retv(mes); for(i=0; i < MAX_PARTY && !p->data[i].sd;i++); if(i < MAX_PARTY){ @@ -6516,7 +6554,6 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i } } - /// Updates the position of a party member on the minimap (ZC_NOTIFY_POSITION_TO_GROUPM). /// 0107 <account id>.L <x>.W <y>.W void clif_party_xy(struct map_session_data *sd) @@ -6532,12 +6569,12 @@ void clif_party_xy(struct map_session_data *sd) clif->send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } - /*========================================== * Sends x/y dot to a single fd. [Skotlex] *------------------------------------------*/ void clif_party_xy_single(int fd, struct map_session_data *sd) { + nullpo_retv(sd); WFIFOHEAD(fd,packet_len(0x107)); WFIFOW(fd,0)=0x107; WFIFOL(fd,2)=sd->status.account_id; @@ -6546,7 +6583,6 @@ void clif_party_xy_single(int fd, struct map_session_data *sd) WFIFOSET(fd,packet_len(0x107)); } - /// Updates HP bar of a party member. /// 0106 <account id>.L <hp>.W <max hp>.W (ZC_NOTIFY_HP_TO_GROUPM) /// 080e <account id>.L <hp>.L <max hp>.L (ZC_NOTIFY_HP_TO_GROUPM_R2) @@ -6578,7 +6614,6 @@ void clif_party_hp(struct map_session_data *sd) clif->send(buf,packet_len(cmd),&sd->bl,PARTY_AREA_WOS); } - /*========================================== * Sends HP bar to a single fd. [Skotlex] *------------------------------------------*/ @@ -6629,7 +6664,6 @@ void clif_movetoattack(struct map_session_data *sd,struct block_list *bl) WFIFOSET(fd,packet_len(0x139)); } - /// Notifies the client about the result of an item produce request (ZC_ACK_REQMAKINGITEM). /// 018f <result>.W <name id>.W /// result: @@ -6655,7 +6689,6 @@ void clif_produceeffect(struct map_session_data* sd,int flag,int nameid) WFIFOSET(fd,packet_len(0x18f)); } - /// Initiates the pet taming process (ZC_START_CAPTURE). /// 019e void clif_catch_process(struct map_session_data *sd) @@ -6670,7 +6703,6 @@ void clif_catch_process(struct map_session_data *sd) WFIFOSET(fd,packet_len(0x19e)); } - /// Displays the result of a pet taming attempt (ZC_TRYCAPTURE_MONSTER). /// 01a0 <result>.B /// 0 = failure @@ -6688,7 +6720,6 @@ void clif_pet_roulette(struct map_session_data *sd,int data) WFIFOSET(fd,packet_len(0x1a0)); } - /// Presents a list of pet eggs that can be hatched (ZC_PETEGG_LIST). /// 01a6 <packet len>.W { <index>.W }* void clif_sendegg(struct map_session_data *sd) @@ -6719,7 +6750,6 @@ void clif_sendegg(struct map_session_data *sd) sd->menuskill_val = -1; } - /// Sends a specific pet data update (ZC_CHANGESTATE_PET). /// 01a4 <type>.B <id>.L <data>.L /// type: @@ -6746,7 +6776,6 @@ void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int typ clif->send(buf, packet_len(0x1a4), &pd->bl, AREA); } - /// Pet's base data (ZC_PROPERTY_PET). /// 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) @@ -6773,7 +6802,6 @@ void clif_send_petstatus(struct map_session_data *sd) WFIFOSET(fd,packet_len(0x1a2)); } - /// Notification about a pet's emotion/talk (ZC_PET_ACT). /// 01aa <id>.L <data>.L /// data: @@ -6802,7 +6830,6 @@ void clif_pet_emotion(struct pet_data *pd,int param) clif->send(buf,packet_len(0x1aa),&pd->bl,AREA); } - /// Result of request to feed a pet (ZC_FEED_PET). /// 01a3 <result>.B <name id>.W /// result: @@ -6822,7 +6849,6 @@ void clif_pet_food(struct map_session_data *sd,int foodid,int fail) WFIFOSET(fd,packet_len(0x1a3)); } - /// Presents a list of skills that can be auto-spelled (ZC_AUTOSPELLLIST). /// 01cd { <skill id>.L }*7 void clif_autospell(struct map_session_data *sd,uint16 skill_lv) @@ -6869,7 +6895,6 @@ void clif_autospell(struct map_session_data *sd,uint16 skill_lv) sd->menuskill_val = skill_lv; } - /// Devotion's visual effect (ZC_DEVOTIONLIST). /// 01cf <devoter id>.L { <devotee id>.L }*5 <max distance>.W void clif_devotion(struct block_list *src, struct map_session_data *tsd) @@ -6896,7 +6921,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) if( sd == NULL ) return; - for( i = 0; i < 5; i++ ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) WBUFL(buf,6+4*i) = sd->devotion[i]; WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc->checkskill(sd, CR_DEVOTION)); } @@ -6930,7 +6955,6 @@ void clif_spiritball(struct block_list *bl) { clif->send(buf, packet_len(0x1d0), bl, AREA); } - /// Notifies clients in area of a character's combo delay (ZC_COMBODELAY). /// 01d2 <account id>.L <delay>.L void clif_combo_delay(struct block_list *bl,int wait) @@ -6945,7 +6969,6 @@ void clif_combo_delay(struct block_list *bl,int wait) clif->send(buf,packet_len(0x1d2),bl,AREA); } - /// Notifies clients in area that a character has blade-stopped another (ZC_BLADESTOP). /// 01d1 <src id>.L <dst id>.L <flag>.L /// flag: @@ -6965,7 +6988,6 @@ void clif_bladestop(struct block_list *src, int dst_id, int active) clif->send(buf,packet_len(0x1d1),src,AREA); } - /// MVP effect (ZC_MVP). /// 010c <account id>.L void clif_mvp_effect(struct map_session_data *sd) @@ -6979,7 +7001,6 @@ void clif_mvp_effect(struct map_session_data *sd) clif->send(buf,packet_len(0x10c),&sd->bl,AREA); } - /// MVP item reward message (ZC_MVP_GETTING_ITEM). /// 010a <name id>.W void clif_mvp_item(struct map_session_data *sd,int nameid) @@ -6998,7 +7019,6 @@ void clif_mvp_item(struct map_session_data *sd,int nameid) WFIFOSET(fd,packet_len(0x10a)); } - /// MVP EXP reward message (ZC_MVP_GETTING_SPECIAL_EXP). /// 010b <exp>.L void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) @@ -7014,7 +7034,6 @@ void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) WFIFOSET(fd,packet_len(0x10b)); } - /// Dropped MVP item reward message (ZC_THROW_MVPITEM). /// 010d /// @@ -7029,7 +7048,6 @@ void clif_mvp_noitem(struct map_session_data* sd) WFIFOSET(fd,packet_len(0x10d)); } - /// Guild creation result (ZC_RESULT_MAKE_GUILD). /// 0167 <result>.B /// result: @@ -7050,12 +7068,9 @@ void clif_guild_created(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x167)); } - /// Notifies the client that it is belonging to a guild (ZC_UPDATE_GDID). /// 016c <guild id>.L <emblem id>.L <mode>.L <ismaster>.B <inter sid>.L <guild name>.24B -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) { int ps,fd; @@ -7075,7 +7090,6 @@ void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) WFIFOSET(fd,packet_len(0x16c)); } - /// Guild member login notice. /// 016d <account id>.L <char id>.L <status>.L (ZC_UPDATE_CHARSTAT) /// 01f2 <account id>.L <char id>.L <status>.L <gender>.W <hair style>.W <hair color>.W (ZC_UPDATE_CHARSTAT2) @@ -7148,7 +7162,6 @@ void clif_guild_send_onlineinfo(struct map_session_data *sd) clif->send(buf, p_len*count, &sd->bl, SELF); } - /// Bitmask of enabled guild window tabs (ZC_ACK_GUILD_MENUINTERFACE). /// 014e <menu flag>.L /// menu flag: @@ -7172,7 +7185,6 @@ void clif_guild_masterormember(struct map_session_data *sd) 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) @@ -7208,7 +7220,6 @@ void clif_guild_basicinfo(struct map_session_data *sd) { WFIFOSET(fd,packet_len(0x1b6)); } - /// Guild alliance and opposition list (ZC_MYGUILD_BASIC_INFO). /// 014c <packet len>.W { <relation>.L <guild id>.L <guild name>.24B }* void clif_guild_allianceinfo(struct map_session_data *sd) @@ -7236,7 +7247,6 @@ void clif_guild_allianceinfo(struct map_session_data *sd) WFIFOSET(fd,WFIFOW(fd,2)); } - /// Guild member manager information (ZC_MEMBERMGR_INFO). /// 0154 <packet len>.W { <account>.L <char id>.L <hair style>.W <hair color>.W <gender>.W <class>.W <level>.W <contrib exp>.L <state>.L <position>.L <memo>.50B <name>.24B }* /// state: @@ -7280,7 +7290,6 @@ void clif_guild_memberlist(struct map_session_data *sd) WFIFOSET(fd,WFIFOW(fd,2)); } - /// Guild position name information (ZC_POSITION_ID_NAME_INFO). /// 0166 <packet len>.W { <position id>.L <position name>.24B }* void clif_guild_positionnamelist(struct map_session_data *sd) { @@ -7302,12 +7311,9 @@ void clif_guild_positionnamelist(struct map_session_data *sd) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Guild position information (ZC_POSITION_INFO). /// 0160 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L }* -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission /// ranking: /// TODO void clif_guild_positioninfolist(struct map_session_data *sd) { @@ -7332,12 +7338,9 @@ void clif_guild_positioninfolist(struct map_session_data *sd) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Notifies clients in a guild about updated position information (ZC_ACK_CHANGE_GUILD_POSITIONINFO). /// 0174 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L <position name>.24B }* -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission /// ranking: /// TODO void clif_guild_positionchanged(struct guild *g,int idx) @@ -7363,7 +7366,6 @@ void clif_guild_positionchanged(struct guild *g,int idx) clif->send(buf,WBUFW(buf,2),&sd->bl,GUILD); } - /// Notifies clients in a guild about updated member position assignments (ZC_ACK_REQ_CHANGE_MEMBERS). /// 0156 <packet len>.W { <account id>.L <char id>.L <position id>.L }* void clif_guild_memberpositionchanged(struct guild *g,int idx) @@ -7387,7 +7389,6 @@ void clif_guild_memberpositionchanged(struct guild *g,int idx) clif->send(buf,WBUFW(buf,2),&sd->bl,GUILD); } - /// Sends emblems bitmap data to the client that requested it (ZC_GUILD_EMBLEM_IMG). /// 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) @@ -7409,7 +7410,6 @@ void clif_guild_emblem(struct map_session_data *sd,struct guild *g) 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) @@ -7427,7 +7427,6 @@ void clif_guild_emblem_area(struct block_list* 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 <upgradeable>.B }* void clif_guild_skillinfo(struct map_session_data* sd) @@ -7451,8 +7450,13 @@ void clif_guild_skillinfo(struct map_session_data* sd) 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); + if ( 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); + } else { + WFIFOW(fd, p + 8) = 0; + WFIFOW(fd, p + 10) = 0; + } 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++; @@ -7462,7 +7466,6 @@ void clif_guild_skillinfo(struct map_session_data* sd) 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) @@ -7474,7 +7477,7 @@ void clif_guild_notice(struct map_session_data* sd, struct guild* g) fd = sd->fd; - if ( !session_isActive(fd) ) + if (!sockt->session_is_active(fd)) return; if(g->mes1[0] == '\0' && g->mes2[0] == '\0') @@ -7487,7 +7490,6 @@ void clif_guild_notice(struct map_session_data* sd, struct guild* g) WFIFOSET(fd,packet_len(0x16f)); } - /// Guild invite (ZC_REQ_JOIN_GUILD). /// 016a <guild id>.L <guild name>.24B void clif_guild_invite(struct map_session_data *sd,struct guild *g) @@ -7505,7 +7507,6 @@ void clif_guild_invite(struct map_session_data *sd,struct guild *g) WFIFOSET(fd,packet_len(0x16a)); } - /// Reply to invite request (ZC_ACK_REQ_JOIN_GUILD). /// 0169 <answer>.B /// answer: @@ -7526,7 +7527,6 @@ void clif_guild_inviteack(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x169)); } - /// Notifies clients of a guild of a leaving member (ZC_ACK_LEAVE_GUILD). /// 015a <char name>.24B <reason>.40B void clif_guild_leave(struct map_session_data *sd,const char *name,const char *mes) @@ -7541,7 +7541,6 @@ void clif_guild_leave(struct map_session_data *sd,const char *name,const char *m 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) @@ -7555,6 +7554,8 @@ void clif_guild_expulsion(struct map_session_data* sd, const char* name, const c #endif nullpo_retv(sd); + nullpo_retv(name); + nullpo_retv(mes); WBUFW(buf,0) = cmd; safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); @@ -7565,7 +7566,6 @@ void clif_guild_expulsion(struct map_session_data* sd, const char* name, const c 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) @@ -7608,7 +7608,6 @@ void clif_guild_expulsionlist(struct map_session_data* sd) { 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) @@ -7616,6 +7615,7 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) struct map_session_data *sd; uint8 buf[256]; + nullpo_retv(mes); if (len == 0) return; @@ -7639,6 +7639,7 @@ void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const cha int fd; nullpo_retv(sd); + nullpo_retv(name); fd=sd->fd; WFIFOHEAD(fd,packet_len(0x171)); @@ -7648,7 +7649,6 @@ void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const cha WFIFOSET(fd,packet_len(0x171)); } - /// Notifies the client about the result of a alliance request (ZC_ACK_REQ_ALLY_GUILD). /// 0173 <answer>.B /// answer: @@ -7671,7 +7671,6 @@ void clif_guild_allianceack(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x173)); } - /// Notifies the client that a alliance or opposition has been removed (ZC_DELETE_RELATED_GUILD). /// 0184 <other guild id>.L <relation>.L /// relation: @@ -7693,7 +7692,6 @@ void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag) WFIFOSET(fd,packet_len(0x184)); } - /// Notifies the client about the result of a opposition request (ZC_ACK_REQ_HOSTILE_GUILD). /// 0181 <result>.B /// result: @@ -7714,7 +7712,6 @@ void clif_guild_oppositionack(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x181)); } - /// Adds alliance or opposition (ZC_ADD_RELATED_GUILD). /// 0185 <relation>.L <guild id>.L <guild name>.24B /* @@ -7729,7 +7726,6 @@ void clif_guild_allianceadded(struct guild *g,int idx) } */ - /// Notifies the client about the result of a guild break (ZC_ACK_DISORGANIZE_GUILD_RESULT). /// 015e <reason>.L /// 0 = success @@ -7748,7 +7744,6 @@ void clif_guild_broken(struct map_session_data *sd,int flag) WFIFOSET(fd,packet_len(0x15e)); } - /// Displays emotion on an object (ZC_EMOTION). /// 00c0 <id>.L <type>.B /// type: @@ -7765,13 +7760,13 @@ void clif_emotion(struct block_list *bl,int 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) { unsigned char buf[MESSAGE_SIZE+6]; nullpo_retv(bl); + nullpo_retv(talkie); WBUFW(buf,0) = 0x191; WBUFL(buf,2) = bl->id; @@ -7779,7 +7774,6 @@ void clif_talkiebox(struct block_list* bl, const char* talkie) clif->send(buf,packet_len(0x191),bl,AREA); } - /// Displays wedding effect centered on an object (ZC_CONGRATULATION). /// 01ea <id>.L void clif_wedding_effect(struct block_list *bl) @@ -7793,7 +7787,6 @@ void clif_wedding_effect(struct block_list *bl) clif->send(buf, packet_len(0x1ea), bl, AREA); } - /// Notifies the client of the name of the partner character (ZC_COUPLENAME). /// 01e6 <partner name>.24B void clif_callpartner(struct map_session_data *sd) { @@ -7818,7 +7811,6 @@ void clif_callpartner(struct map_session_data *sd) { clif->send(buf, packet_len(0x1e6), &sd->bl, AREA); } - /// Initiates the partner "taming" process [DracoRPG] (ZC_START_COUPLE). /// 01e4 /// This packet while still implemented by the client is no longer being officially used. @@ -7835,7 +7827,6 @@ void clif_marriage_process(struct map_session_data *sd) } */ - /// Notice of divorce (ZC_DIVORCE). /// 0205 <partner name>.24B void clif_divorced(struct map_session_data* sd, const char* name) @@ -7850,7 +7841,6 @@ void clif_divorced(struct map_session_data* sd, const char* name) WFIFOSET(fd, packet_len(0x205)); } - /// Marriage proposal (ZC_REQ_COUPLE). /// 01e2 <account id>.L <char id>.L <char name>.24B /// This packet while still implemented by the client is no longer being officially used. @@ -7878,6 +7868,9 @@ void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum if (len == 0) return; + nullpo_retv(src); + nullpo_retv(mes); + if (len > sizeof(buf)-5) { ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id); len = sizeof(buf)-5; @@ -7889,7 +7882,6 @@ void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum clif->send(buf, WBUFW(buf,2), src, target); } - /// Notifies the client about the result of a request to disconnect another player (ZC_ACK_DISCONNECT_CHARACTER). /// 00cd <result>.L (unknown packet version or invalid information at packet_len_table) /// 00cd <result>.B @@ -7909,20 +7901,21 @@ void clif_GM_kickack(struct map_session_data *sd, int result) 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; + + nullpo_retv(tsd); + fd = tsd->fd; - if( fd > 0 ) + if (fd > 0) clif->authfail_fd(fd, 15); else map->quit(tsd); - if( sd ) + if (sd) clif->GM_kickack(sd, 1); } - /// Displays various manner-related status messages (ZC_ACK_GIVE_MANNER_POINT). /// 014a <result>.L /// result: @@ -7944,7 +7937,6 @@ void clif_manner_message(struct map_session_data* sd, uint32 type) WFIFOSET(fd, packet_len(0x14a)); } - /// Follow-up to 0x14a type 3/5, informs who did the manner adjustment action (ZC_NOTIFY_MANNER_POINT_GIVEN). /// 014b <type>.B <GM name>.24B /// type: @@ -7964,7 +7956,6 @@ void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, WFIFOSET(fd, packet_len(0x14b)); } - /// Notifies the client about the result of a request to allow/deny whispers from a player (ZC_SETTING_WHISPER_PC). /// 00d1 <type>.B <result>.B /// type: @@ -8008,7 +7999,6 @@ void clif_wisall(struct map_session_data *sd,int type,int 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) @@ -8024,7 +8014,6 @@ void clif_playBGM(struct map_session_data* sd, const char* name) WFIFOSET(fd,packet_len(0x7fe)); } - /// Plays/stops a wave sound (ZC_SOUND). /// 01d3 <file name>.24B <act>.B <term>.L <npc id>.L /// file name: @@ -8044,6 +8033,7 @@ void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const nullpo_retv(sd); nullpo_retv(bl); + nullpo_retv(name); fd = sd->fd; WFIFOHEAD(fd,packet_len(0x1d3)); @@ -8060,6 +8050,7 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum unsigned char buf[40]; nullpo_retv(bl); + nullpo_retv(name); WBUFW(buf,0) = 0x1d3; safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); @@ -8069,7 +8060,6 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum clif->send(buf, packet_len(0x1d3), bl, coverage); } - /// Displays special effects (npcs, weather, etc) [Valaris] (ZC_NOTIFY_EFFECT2). /// 01f3 <id>.L <effect id>.L /// effect id: @@ -8095,6 +8085,7 @@ void clif_specialeffect(struct block_list* bl, int type, enum send_target target } void clif_specialeffect_single(struct block_list* bl, int type, int fd) { + nullpo_retv(bl); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x1f3; WFIFOL(fd,2) = bl->id; @@ -8102,7 +8093,6 @@ void clif_specialeffect_single(struct block_list* bl, int type, int fd) { WFIFOSET(fd,10); } - /// Notifies clients of an special/visual effect that accepts an value (ZC_NOTIFY_EFFECT3). /// 0284 <id>.L <effect id>.L <num data>.L /// effect id: @@ -8126,30 +8116,47 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen 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(int fd, enum clif_colors color, const char* msg) { - size_t msg_len = strlen(msg) + 1; +/** + * 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 + * + * @param fd Target fd to send the message to + * @param color Message color (RGB format: 0xRRGGBB) + * @param msg Message text + */ +void clif_messagecolor_self(int fd, uint32 color, const char *msg) +{ + size_t msg_len; + + nullpo_retv(msg); + msg_len = strlen(msg) + 1; WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = color_table[color]; + WFIFOL(fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); WFIFOSET(fd, msg_len + 12); - - 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 int color, const char* msg) { +/** + * Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT). + * + * 02c1 <packet len>.W <id>.L <color>.L <message>.?B + * + * @param bl Source block list. + * @param color Message color (RGB format: 0xRRGGBB) + * @param msg Message text + */ +void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg) +{ size_t 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(msg); if (msg_len > sizeof(buf)-12) { ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len); @@ -8159,48 +8166,30 @@ void clif_messagecolor(struct block_list* bl, unsigned int color, const char* ms WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = bl->id; - WBUFL(buf,8) = color; + WBUFL(buf,8) = RGB2BGR(color); memcpy(WBUFP(buf,12), msg, msg_len); 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); - - 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); - - clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); -} - /** * Notifies the client that the storage window is still open * * Should only be used in cases where the client closed the * storage window without server's consent **/ -void clif_refresh_storagewindow( struct map_session_data *sd ) { +void clif_refresh_storagewindow(struct map_session_data *sd) +{ + nullpo_retv(sd); // Notify the client that the storage is open - if( sd->state.storage_flag == 1 ) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { 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); } // Notify the client that the gstorage is open otherwise it will // remain locked forever and nobody will be able to access it - if( sd->state.storage_flag == 2 ) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { struct guild_storage *gstor; if( (gstor = idb_get(gstorage->db,sd->status.guild_id)) == NULL) { // Shouldn't happen... The information should already be at the map-server @@ -8250,7 +8239,7 @@ void clif_refresh(struct map_session_data *sd) map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); clif->weather_check(sd); if( sd->chatID ) - chat->leave(sd,0); + chat->leave(sd, false); if( sd->state.vending ) clif->openvending(sd, sd->bl.id, sd->vending); if( pc_issit(sd) ) @@ -8274,7 +8263,6 @@ void clif_refresh(struct map_session_data *sd) clif->refresh_storagewindow(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) @@ -8414,7 +8402,6 @@ void clif_charnameack (int fd, struct block_list *bl) } } - //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) @@ -8469,7 +8456,6 @@ void clif_charnameupdate (struct map_session_data *ssd) clif->send(buf, packet_len(cmd), &ssd->bl, AREA); } - /// Taekwon Jump (TK_HIGHJUMP) effect (ZC_HIGHJUMP). /// 01ff <id>.L <x>.W <y>.W /// @@ -8494,13 +8480,16 @@ void clif_slide(struct block_list *bl, int x, int y) } } - /// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well /// 008d <packet len>.W <id>.L <message>.?B void clif_disp_overhead(struct block_list *bl, const char* mes) { unsigned char buf[256]; //This should be more than sufficient, the theoretical max is CHAT_SIZE + 8 (pads and extra inserted crap) - size_t len_mes = strlen(mes)+1; //Account for \0 + size_t len_mes; + + nullpo_retv(bl); + nullpo_retv(mes); + len_mes = strlen(mes)+1; //Account for \0 if (len_mes > sizeof(buf)-8) { ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes); @@ -8538,7 +8527,6 @@ void clif_party_xy_remove(struct map_session_data *sd) clif->send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } - /// Displays a skill message (thanks to Rayce) (ZC_SKILLMSG). /// 0215 <msg id>.L /// msg id: @@ -8556,7 +8544,10 @@ 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; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x215)); WFIFOW(fd,0)=0x215; WFIFOL(fd,2)=type; @@ -8564,7 +8555,6 @@ void clif_gospel_info(struct map_session_data *sd, int type) } - /// Multi-purpose mission information packet (ZC_STARSKILL). /// 020e <mapname>.24B <monster_id>.L <star>.B <result>.B /// result: @@ -8595,7 +8585,11 @@ void clif_gospel_info(struct map_session_data *sd, int type) /// 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) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + nullpo_retv(mapname); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x20e)); WFIFOW(fd,0) = 0x20e; @@ -8614,6 +8608,8 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig { char mapname[MAP_NAME_LENGTH_EXT]; + nullpo_retv(sd); + Assert_retv(feel_level < MAX_PC_FEELHATE); mapindex->getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname); clif->starskill(sd, mapname, 0, feel_level, type ? 1 : 0); } @@ -8649,7 +8645,6 @@ void clif_feel_hate_reset(struct map_session_data *sd) clif->starskill(sd, "", 0, 0, 30); } - /// Equip window (un)tick ack (ZC_CONFIG). /// 02d9 <type>.L <value>.L /// type: @@ -8670,7 +8665,6 @@ void clif_equiptickack(struct map_session_data* sd, int flag) WFIFOSET(fd, packet_len(0x2d9)); } - /// The player's 'view equip' state, sent during login (ZC_CONFIG_NOTIFY). /// 02da <open equip window>.B /// open equip window: @@ -8688,7 +8682,6 @@ void clif_equpcheckbox(struct map_session_data* sd) WFIFOSET(fd, packet_len(0x2da)); } - /// Sends info about a player's equipped items. /// 02d7 <packet len>.W <name>.24B <class>.W <hairstyle>.W <up-viewid>.W <mid-viewid>.W <low-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.26B* (ZC_EQUIPWIN_MICROSCOPE) /// 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) @@ -8706,7 +8699,7 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts if (tsd->status.inventory[k].nameid <= 0 || tsd->inventory_data[k] == NULL) // Item doesn't exist continue; - clif_item_equip(k+2,&viewequip_list.list[equip++],&tsd->status.inventory[k],tsd->inventory_data[k],pc->equippoint(tsd,k)); + clif->item_equip(k+2,&viewequip_list.list[equip++],&tsd->status.inventory[k],tsd->inventory_data[k],pc->equippoint(tsd,k)); } } @@ -8730,10 +8723,15 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts clif->send(&viewequip_list, viewequip_list.PacketLength, &sd->bl, SELF); } - -/// Display msgstringtable.txt string (ZC_MSG). -/// 0291 <message>.W -void clif_msg(struct map_session_data* sd, unsigned short id) +/** + * Displays a string from msgstringtable.txt (ZC_MSG). + * + * 0291 <msg id>.W + * + * @param sd The target character. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + */ +void clif_msgtable(struct map_session_data* sd, unsigned short msg_id) { int fd; nullpo_retv(sd); @@ -8741,33 +8739,52 @@ void clif_msg(struct map_session_data* sd, unsigned short id) WFIFOHEAD(fd, packet_len(0x291)); WFIFOW(fd, 0) = 0x291; - WFIFOW(fd, 2) = id; // zero-based msgstringtable.txt index + WFIFOW(fd, 2) = msg_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) +/** + * Displays a format string from msgstringtable.txt with a %d value (ZC_MSG_VALUE). + * + * 0x7e2 <msg id>.W <value>.L + * + * @param sd The target character. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + * @param value The value to fill %d. + */ +void clif_msgtable_num(struct map_session_data *sd, unsigned short msg_id, int value) { - int fd = sd->fd; +#if PACKETVER >= 20090805 + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x7e2)); - WFIFOW(fd,0) = 0x7e2; - WFIFOW(fd,2) = id; - WFIFOL(fd,4) = value; + WFIFOW(fd, 0) = 0x7e2; + WFIFOW(fd, 2) = msg_id; + WFIFOL(fd, 4) = value; WFIFOSET(fd, packet_len(0x7e2)); +#endif } - -/// Displays msgstringtable.txt string, prefixed with a skill name. (ZC_MSG_SKILL). -/// 07e6 <skill id>.W <msg id>.L -/// -/// NOTE: Message has following format and is printed in color 0xCDCDFF (purple): -/// "[SkillName] Message" -void clif_msg_skill(struct map_session_data* sd, uint16 skill_id, int msg_id) +/** + * Displays a string from msgstringtable.txt, prefixed with a skill name (ZC_MSG_SKILL). + * + * 07e6 <skill id>.W <msg id>.L + * + * NOTE: Message has following format and is printed in color 0xCDCDFF (purple): + * "[SkillName] Message" + * + * @param sd The target character. + * @param skill_id ID of the skill to display. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + */ +void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_id) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x7e6)); WFIFOW(fd,0) = 0x7e6; @@ -8786,6 +8803,12 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, size_t namelen, messagelen; int fd = sd->fd; + nullpo_retr(false, sd); + nullpo_retr(false, name_); + nullpo_retr(false, namelen_); + nullpo_retr(false, message_); + nullpo_retr(false, messagelen_); + *name_ = NULL; *namelen_ = 0; *message_ = NULL; @@ -8814,7 +8837,7 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, { //Hacked message, or infamous "client desynchronize" 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. + sockt->eof(fd); // Just kick them out to correct it. return false; } @@ -8873,15 +8896,23 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg) { - DBIterator *iter = db_iterator(chan->users); + DBIterator *iter; struct map_session_data *user; - unsigned short msg_len = strlen(msg) + 1; + unsigned short msg_len; + uint32 color; + + nullpo_retv(chan); + nullpo_retv(sd); + nullpo_retv(msg); + iter = db_iterator(chan->users); + msg_len = strlen(msg) + 1; + color = channel->config->colors[chan->color]; 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) = channel->config->colors[chan->color]; + WFIFOL(sd->fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { @@ -8899,15 +8930,22 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch void clif_channel_msg2(struct channel_data *chan, char *msg) { - DBIterator *iter = db_iterator(chan->users); + DBIterator *iter; struct map_session_data *user; unsigned char buf[210]; - unsigned short msg_len = strlen(msg) + 1; + unsigned short msg_len; + uint32 color; + + nullpo_retv(chan); + nullpo_retv(msg); + iter = db_iterator(chan->users); + msg_len = strlen(msg) + 1; + color = channel->config->colors[chan->color]; WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = 0; - WBUFL(buf,8) = channel->config->colors[chan->color]; + WBUFL(buf,8) = RGB2BGR(color); safestrncpy((char*)WBUFP(buf,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { @@ -8924,7 +8962,6 @@ void clif_channel_msg2(struct channel_data *chan, char *msg) // ------------ // Parses incoming (player) connection - /// Request to connect to map-server. /// 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) @@ -8949,7 +8986,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { client_tick = RFIFOL(fd, packet_db[cmd].pos[3]); sex = RFIFOB(fd, packet_db[cmd].pos[4]); - if( runflag != MAPSERVER_ST_RUNNING ) { // not allowed + if( core->runflag != MAPSERVER_ST_RUNNING ) { // not allowed clif->authfail_fd(fd,1);// server closed return; } @@ -8962,7 +8999,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = 3; // Rejected by server WFIFOSET(fd,packet_len(0x6a)); - set_eof(fd); + sockt->eof(fd); return; } @@ -8982,7 +9019,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF; sd->parse_cmd_func = clif->parse_cmd; - session[fd]->session_data = sd; + sockt->session[fd]->session_data = sd; pc->setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd); @@ -9000,12 +9037,10 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { chrif->authreq(sd,false); } +void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT). /// 007d -void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { -#if PACKETVER >= 20090218 - int i; -#endif +void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { bool first_time = false; if(sd->bl.prev != NULL) @@ -9190,10 +9225,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { //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(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); + int i; + for (i = 0; i < MAX_PC_FEELHATE; i++) { + if (sd->bl.m == sd->feel_map[i].m) { + sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); + break; + } + } } if(sd->pd && sd->pd->pet.intimate > 900) @@ -9221,14 +9259,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { 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.warp_clean) { + // 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); + } else { + sd->state.warp_clean = 1; + } if( sd->guild && ( battle_config.guild_notice_changemap == 2 || ( battle_config.guild_notice_changemap == 1 && sd->state.changemap ) ) ) clif->guild_notice(sd,sd->guild); } @@ -9316,7 +9356,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->guild_notice(sd, sd->guild); // 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)) + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC)) npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y); @@ -9339,25 +9379,30 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { // NPC Quest / Event Icon Check [Kisuka] #if PACKETVER >= 20090218 - for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { - struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; - if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started - if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. - if( sd->class_ == qi->job ) + { + int i; + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started + if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. + if( sd->class_ == qi->job ) + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } else { clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); - } else { - clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } } } } #endif } - /// Server's tick (ZC_NOTIFY_TIME). /// 007f <time>.L void clif_notify_time(struct map_session_data* sd, int64 time) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x7f)); WFIFOW(fd,0) = 0x7f; @@ -9365,7 +9410,7 @@ void clif_notify_time(struct map_session_data* sd, int64 time) { WFIFOSET(fd,packet_len(0x7f)); } - +void clif_parse_TickSend(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request for server's tick. /// 007e <client tick>.L (CZ_REQUEST_TIME) /// 0360 <client tick>.L (CZ_REQUEST_TIME2) @@ -9377,37 +9422,37 @@ void clif_parse_TickSend(int fd, struct map_session_data *sd) clif->notify_time(sd, timer->gettick()); } - /// Sends hotkey bar. /// 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) +/// 0a00 <rotate>.B { <is skill>.B <id>.L <count>.W }*38 (ZC_SHORTCUT_KEY_LIST_V3, PACKETVER >= 20141022) void clif_hotkeys_send(struct map_session_data *sd) { #ifdef HOTKEY_SAVING - const int fd = sd->fd; + struct packet_hotkey p; int i; - int offset = 2; -#if PACKETVER < 20090603 - const int cmd = 0x2b9; -#elif PACKETVER < 20141022 - const int cmd = 0x7d9; -#else - const int cmd = 0xa00; - offset = 3; + nullpo_retv(sd); + p.PacketType = hotkeyType; +#if PACKETVER >= 20141022 + p.Rotate = sd->status.hotkey_rowshift; #endif - if (!fd) return; - WFIFOHEAD(fd, offset+MAX_HOTKEYS*7); - WFIFOW(fd, 0) = cmd; - for(i = 0; i < MAX_HOTKEYS; i++) { - WFIFOB(fd, offset + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill - WFIFOL(fd, offset + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID - WFIFOW(fd, offset + 5 + i * 7) = sd->status.hotkeys[i].lv; // item qty or skill level + for(i = 0; i < ARRAYLENGTH(p.hotkey); i++) { + p.hotkey[i].isSkill = sd->status.hotkeys[i].type; + p.hotkey[i].ID = sd->status.hotkeys[i].id; + p.hotkey[i].count = sd->status.hotkeys[i].lv; } - WFIFOSET(fd, packet_len(cmd)); + clif->send(&p, sizeof(p), &sd->bl, SELF); #endif } +void clif_parse_HotkeyRowShift(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_HotkeyRowShift(int fd, struct map_session_data *sd) +{ + int cmd = RFIFOW(fd, 0); + sd->status.hotkey_rowshift = RFIFOB(fd, packet_db[cmd].pos[0]); +} +void clif_parse_Hotkey(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 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) { @@ -9425,13 +9470,15 @@ void clif_parse_Hotkey(int fd, struct map_session_data *sd) { #endif } - /// Displays cast-like progress bar (ZC_PROGRESS). /// 02f0 <color>.L <time>.L /* TODO ZC_PROGRESS_ACTOR <account_id>.L */ void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned int second) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x2f0)); WFIFOW(fd,0) = 0x2f0; @@ -9440,19 +9487,21 @@ void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned WFIFOSET(fd,packet_len(0x2f0)); } - /// Removes an ongoing progress bar (ZC_PROGRESS_CANCEL). /// 02f2 void clif_progressbar_abort(struct map_session_data * sd) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x2f2)); WFIFOW(fd,0) = 0x2f2; WFIFOSET(fd,packet_len(0x2f2)); } - +void clif_parse_progressbar(int fd, struct map_session_data * sd) __attribute__((nonnull (2))); /// 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) @@ -9466,7 +9515,7 @@ void clif_parse_progressbar(int fd, struct map_session_data * sd) npc->scriptcont(sd, npc_id, false); } - +void clif_parse_WalkToXY(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to walk to a certain position on the current map. /// 0085 <dest>.3B (CZ_REQUEST_MOVE) /// 035f <dest>.3B (CZ_REQUEST_MOVE2) @@ -9501,7 +9550,6 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) unit->walktoxy(&sd->bl, x, y, 4); } - /// Notification about the result of a disconnect request (ZC_ACK_REQ_DISCONNECT). /// 018b <result>.W /// result: @@ -9510,7 +9558,10 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) /// ? = ignored void clif_disconnect_ack(struct map_session_data* sd, short result) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x18b)); WFIFOW(fd,0) = 0x18b; @@ -9518,7 +9569,7 @@ void clif_disconnect_ack(struct map_session_data* sd, short result) WFIFOSET(fd,packet_len(0x18b)); } - +void clif_parse_QuitGame(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to disconnect from server (CZ_REQ_DISCONNECT). /// 018a <type>.W /// type: @@ -9529,7 +9580,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) { - set_eof(fd); + sockt->eof(fd); clif->disconnect_ack(sd, 0); } else { @@ -9537,7 +9588,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) } } - +void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Requesting unit's name. /// 0094 <id>.L (CZ_REQNAME) /// 0368 <id>.L (CZ_REQNAME2) @@ -9585,6 +9636,7 @@ int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } +void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (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. @@ -9655,6 +9707,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) } else if ( sd->fontcolor && !sd->chatID ) { char mout[200]; unsigned char mylen = 1; + uint32 color = 0; if( sd->disguise == -1 ) { sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0); @@ -9672,11 +9725,12 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message); + color = channel->config->colors[sd->fontcolor - 1]; WFIFOHEAD(fd,mylen + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = mylen + 12; WFIFOL(fd,4) = sd->bl.id; - WFIFOL(fd,8) = channel->config->colors[sd->fontcolor - 1]; + WFIFOL(fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(fd,12), mout, mylen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); WFIFOL(fd,4) = -sd->bl.id; @@ -9714,17 +9768,17 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOW(fd,0) = 0x8e; } WFIFOSET(fd, WFIFOW(fd,2)); - + // Chat logging type 'O' / Global Chat logs->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); - + #ifdef PCRE_SUPPORT // trigger listening npcs map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); #endif } - +void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /mm /mapmove (as @rura GM command) (CZ_MOVETO_MAP). /// Request to warp to a map on given coordinates. /// 0140 <map name>.16B <x>.W <y>.W @@ -9739,7 +9793,6 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) atcommand->exec(fd, sd, command, true); } - /// Updates body and head direction of an object (ZC_CHANGE_DIRECTION). /// 009c <id>.L <head dir>.W <dir>.B /// head dir: @@ -9759,6 +9812,7 @@ void clif_changed_dir(struct block_list *bl, enum send_target target) { unsigned char buf[64]; + nullpo_retv(bl); WBUFW(buf,0) = 0x9c; WBUFL(buf,2) = bl->id; WBUFW(buf,6) = bl->type==BL_PC?((TBL_PC*)bl)->head_dir:0; @@ -9773,7 +9827,7 @@ void clif_changed_dir(struct block_list *bl, enum send_target target) } } - +void clif_parse_ChangeDir(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change own body and head direction. /// 009b <head dir>.W <dir>.B (CZ_CHANGE_DIRECTION) /// 0361 <head dir>.W <dir>.B (CZ_CHANGE_DIRECTION2) @@ -9789,7 +9843,7 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd) clif->changed_dir(&sd->bl, AREA_WOS); } - +void clif_parse_Emotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to show an emotion (CZ_REQ_EMOTION). /// 00bf <type>.B /// type: @@ -9823,11 +9877,13 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) 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) { - int fd = sd->fd; + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0xc2)); WFIFOW(fd,0) = 0xc2; @@ -9835,7 +9891,7 @@ void clif_user_count(struct map_session_data* sd, int count) { WFIFOSET(fd,packet_len(0xc2)); } - +void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /w /who (CZ_REQ_USER_COUNT). /// Request to display amount of currently connected players. /// 00c1 @@ -9843,10 +9899,10 @@ void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) { clif->user_count(sd, map->getusers()); } - void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, int64 tick) { struct block_list *target = NULL; - + + nullpo_retv(sd); if (pc_isdead(sd)) { clif->clearunit_area(&sd->bl, CLR_DEAD); return; @@ -9863,7 +9919,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, return; if(action_type != 0x00 && action_type != 0x07) - pc_stop_walking(sd, 1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); pc_stop_attack(sd); if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] @@ -9872,12 +9928,11 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, switch(action_type) { case 0x00: // once attack case 0x07: // continuous attack - if( (target = map->id2bl(target_id)) && target->type == BL_NPC ) { npc->click(sd,(TBL_NPC*)target); return; } - + if( pc_cant_act(sd) || pc_issit(sd) || sd->sc.option&OPTION_HIDE ) return; @@ -9942,6 +9997,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, } } +void clif_parse_ActionRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request for an action. /// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT) /// 0437 <target id>.L <action>.B (CZ_REQUEST_ACT2) @@ -9962,7 +10018,7 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) ); } - +void clif_parse_Restart(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Response to the death/system menu (CZ_RESTART). /// 00b2 <type>.B /// type: @@ -9980,7 +10036,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) { && (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) { //Send to char-server for character selection. - chrif->charselectreq(sd, session[fd]->client_addr); + chrif->charselectreq(sd, sockt->session[fd]->client_addr); } else { clif->disconnect_ack(sd, 1); } @@ -9988,7 +10044,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) { } } - +void clif_parse_WisMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -10068,7 +10124,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if (chan) { int k; ARR_FIND(0, sd->channel_count, k, sd->channels[k] == chan); - if (k < sd->channel_count || channel->join(chan, sd, NULL, true) == HCS_STATUS_OK) { + if (k < sd->channel_count || channel->join(chan, sd, "", true) == HCS_STATUS_OK) { channel->send(chan,sd,message); } else { clif->message(fd, msg_fd(fd,1402)); @@ -10123,7 +10179,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) clif->wis_message(dstsd->fd, sd->status.name, message, messagelen); } - +void clif_parse_Broadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /b /nb (CZ_BROADCAST). /// Request to broadcast a message on whole server. /// 0099 <packet len>.W <text>.?B 00 @@ -10139,7 +10195,7 @@ void clif_parse_Broadcast(int fd, struct map_session_data* sd) { atcommand->exec(fd, sd, command, true); } - +void clif_parse_TakeItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to pick up an item. /// 009f <id>.L (CZ_ITEM_PICKUP) /// 0362 <id>.L (CZ_ITEM_PICKUP2) @@ -10183,7 +10239,7 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) { clif->additem(sd,0,0,6); } - +void clif_parse_DropItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to drop an item. /// 00a2 <index>.W <amount>.W (CZ_ITEM_THROW) /// 0363 <index>.W <amount>.W (CZ_ITEM_THROW2) @@ -10217,10 +10273,10 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) } //Because the client does not like being ignored. - clif->dropitem(sd, item_index,0); + clif->dropitem(sd, item_index, 0); } - +void clif_parse_UseItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to use an item. /// 00a7 <index>.W <account id>.L (CZ_USE_ITEM) /// 0439 <index>.W <account id>.L (CZ_USE_ITEM2) @@ -10242,13 +10298,13 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) sd->idletime = sockt->last_tick; n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2; - if(n <0 || n >= MAX_INVENTORY) + 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. } - +void clif_parse_EquipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to equip an item (CZ_REQ_WEAR_EQUIP). /// 00a9 <index>.W <position>.W /// 0998 <index>.W <position>.L @@ -10267,7 +10323,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { if( sd->npc_id ) { if ( !sd->npc_item_flag ) return; - } else if ( sd->state.storage_flag || sd->sc.opt1 ) + } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; @@ -10295,6 +10351,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { pc->equipitem(sd,p->index,p->wearLocation); } +void clif_parse_UnequipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to take off an equip (CZ_REQ_TAKEOFF_EQUIP). /// 00ab <index>.W void clif_parse_UnequipItem(int fd,struct map_session_data *sd) @@ -10309,7 +10366,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) if( sd->npc_id ) { if ( !sd->npc_item_flag ) return; - } else if ( sd->state.storage_flag || sd->sc.opt1 ) + } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; @@ -10319,10 +10376,10 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) if( battle_config.idletime_criteria & BCIDLE_USEITEM ) sd->idletime = sockt->last_tick; - pc->unequipitem(sd,index,1); + pc->unequipitem(sd,index, PCUNEQUIPITEM_RECALC); } - +void clif_parse_NpcClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to start a conversation with an NPC (CZ_CONTACTNPC). /// 0090 <id>.L <type>.B /// type: @@ -10337,7 +10394,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) } if( sd->npc_id || sd->state.workinprogress&2 ){ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return; } @@ -10352,7 +10409,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) case BL_NPC: if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills #ifdef RENEWAL - clif->msg(sd, 0x783); + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); #endif break; } @@ -10362,20 +10419,19 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) } } - +void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Selection between buy/sell was made (CZ_ACK_SELECT_DEALTYPE). /// 00c5 <id>.L <type>.B /// type: /// 0 = buy /// 1 = sell -void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd) +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)); + npc->buysellsel(sd, RFIFOL(fd,2), RFIFOB(fd,6)); } - /// Notification about the result of a purchase attempt from an NPC shop (ZC_PC_PURCHASE_RESULT). /// 00ca <result>.B /// result: @@ -10384,15 +10440,17 @@ void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd) /// 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0xca)); WFIFOW(fd,0) = 0xca; WFIFOB(fd,2) = result; WFIFOSET(fd,packet_len(0xca)); } - +void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -10411,22 +10469,23 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) clif->npc_buy_result(sd, result); } - /// Notification about the result of a sell attempt to an NPC shop (ZC_PC_SELL_RESULT). /// 00cb <result>.B /// 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0xcb)); WFIFOW(fd,0) = 0xcb; WFIFOB(fd,2) = result; WFIFOSET(fd,packet_len(0xcb)); } - +void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to sell chosen items to npc shop (CZ_PC_SELL_ITEMLIST). /// 00c9 <packet len>.W { <index>.W <amount>.W }* void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) @@ -10447,7 +10506,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) clif->npc_sell_result(sd, fail); } - +void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Chatroom creation request (CZ_CREATE_CHATROOM). /// 00d5 <packet len>.W <limit>.W <type>.B <passwd>.8B <title>.?B /// type: @@ -10487,7 +10546,7 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) chat->create_pc_chat(sd, s_title, s_password, limit, pub); } - +void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Chatroom join request (CZ_REQ_ENTER_ROOM). /// 00d9 <chat ID>.L <passwd>.8B void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) @@ -10498,7 +10557,7 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) chat->join(sd,chatid,password); } - +void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Chatroom properties adjustment request (CZ_CHANGE_CHATROOM). /// 00de <packet len>.W <limit>.W <type>.B <passwd>.8B <title>.?B /// type: @@ -10523,7 +10582,7 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) chat->change_status(sd, s_title, s_password, limit, pub); } - +void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to change the chat room ownership (CZ_REQ_ROLE_CHANGE). /// 00e0 <role>.L <nick>.24B /// role: @@ -10534,7 +10593,7 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) chat->change_owner(sd,(char*)RFIFOP(fd,6)); } - +void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to expel a player from chat room (CZ_REQ_EXPEL_MEMBER). /// 00e2 <name>.24B void clif_parse_KickFromChat(int fd,struct map_session_data *sd) @@ -10542,21 +10601,21 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) chat->kick(sd,(char*)RFIFOP(fd,2)); } - +void clif_parse_ChatLeave(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to leave the current chatroom (CZ_EXIT_ROOM). /// 00e3 void clif_parse_ChatLeave(int fd, struct map_session_data* sd) { - chat->leave(sd,0); + chat->leave(sd, false); } - //Handles notifying asker and rejecter of what has just occurred. //Type is used to determine the correct msg_txt to use: //0: void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) { const char* msg; char output[256]; + nullpo_retv(src); // Your request has been rejected by autoreject option. msg = msg_sd(src,392); clif_disp_onlyself(src, msg, strlen(msg)); @@ -10565,7 +10624,7 @@ void clif_noask_sub(struct map_session_data *src, struct map_session_data *targe clif_disp_onlyself(target, output, strlen(output)); } - +void clif_parse_TradeRequest(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to begin a trade (CZ_REQ_EXCHANGE_ITEM). /// 00e4 <account id>.L void clif_parse_TradeRequest(int fd,struct map_session_data *sd) { @@ -10590,7 +10649,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) { trade->request(sd,t_sd); } - +void clif_parse_TradeAck(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to a trade request (CZ_ACK_EXCHANGE_ITEM). /// 00e6 <result>.B /// result: @@ -10601,7 +10660,7 @@ void clif_parse_TradeAck(int fd,struct map_session_data *sd) trade->ack(sd,RFIFOB(fd,2)); } - +void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add an item to current trade (CZ_ADD_EXCHANGE_ITEM). /// 00e8 <index>.W <amount>.L void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) @@ -10615,7 +10674,7 @@ void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) trade->additem(sd, index, (short)amount); } - +void clif_parse_TradeOk(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to lock items in current trade (CZ_CONCLUDE_EXCHANGE_ITEM). /// 00eb void clif_parse_TradeOk(int fd,struct map_session_data *sd) @@ -10623,7 +10682,7 @@ void clif_parse_TradeOk(int fd,struct map_session_data *sd) trade->ok(sd); } - +void clif_parse_TradeCancel(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to cancel current trade (CZ_CANCEL_EXCHANGE_ITEM). /// 00ed void clif_parse_TradeCancel(int fd,struct map_session_data *sd) @@ -10631,7 +10690,7 @@ void clif_parse_TradeCancel(int fd,struct map_session_data *sd) trade->cancel(sd); } - +void clif_parse_TradeCommit(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to commit current trade (CZ_EXEC_EXCHANGE_ITEM). /// 00ef void clif_parse_TradeCommit(int fd,struct map_session_data *sd) @@ -10639,7 +10698,7 @@ void clif_parse_TradeCommit(int fd,struct map_session_data *sd) trade->commit(sd); } - +void clif_parse_StopAttack(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to stop chasing/attacking an unit (CZ_CANCEL_LOCKON). /// 0118 void clif_parse_StopAttack(int fd,struct map_session_data *sd) @@ -10647,7 +10706,7 @@ void clif_parse_StopAttack(int fd,struct map_session_data *sd) pc_stop_attack(sd); } - +void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from inventory to cart (CZ_MOVE_ITEM_FROM_BODY_TO_CART). /// 0126 <index>.W <amount>.L void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) { @@ -10662,7 +10721,7 @@ void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) { } } - +void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from cart to inventory (CZ_MOVE_ITEM_FROM_CART_TO_BODY). /// 0127 <index>.W <amount>.L void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) @@ -10672,7 +10731,7 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) pc->getitemfromcart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4)); } - +void clif_parse_RemoveOption(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to remove cart/falcon/peco/dragon (CZ_REQ_CARTOFF). /// 012a void clif_parse_RemoveOption(int fd,struct map_session_data *sd) @@ -10690,21 +10749,19 @@ void clif_parse_RemoveOption(int fd,struct map_session_data *sd) } } - +void clif_parse_ChangeCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// 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; - nullpo_retv(sd); - if( pc->checkskill(sd, MC_CHANGECART) < 1 ) return; #ifdef RENEWAL if( sd->npc_id || sd->state.workinprogress&1 ){ - clif->msg(sd, 0x783); + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); return; } #endif @@ -10730,7 +10787,7 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) pc->setcart(sd,type); } - +void clif_parse_StatusUp(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to increase status (CZ_STATUS_CHANGE). /// 00bb <status id>.W <amount>.B /// status id: @@ -10750,7 +10807,7 @@ void clif_parse_StatusUp(int fd,struct map_session_data *sd) { pc->statusup(sd, RFIFOW(fd,2), increase_amount); } - +void clif_parse_SkillUp(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to increase level of a skill (CZ_UPGRADE_SKILLLEVEL). /// 0112 <skill id>.W void clif_parse_SkillUp(int fd,struct map_session_data *sd) @@ -10761,6 +10818,7 @@ void clif_parse_SkillUp(int fd,struct map_session_data *sd) void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; + nullpo_retv(sd); if( !hd ) return; if (skill->not_ok_hom(skill_id, hd)){ @@ -10789,6 +10847,7 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; + nullpo_retv(sd); if( !hd ) return; if (skill->not_ok_hom(skill_id, hd)){ @@ -10817,6 +10876,7 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; + nullpo_retv(sd); if( !md ) return; if( skill->not_ok_mercenary(skill_id, md) ) @@ -10837,6 +10897,7 @@ void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_ses void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; + nullpo_retv(sd); if( !md ) return; if( skill->not_ok_mercenary(skill_id, md) ) @@ -10857,7 +10918,7 @@ void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_se unit->skilluse_pos(&md->bl, x, y, skill_id, skill_lv); } - +void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to use a targeted skill. /// 0113 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL) /// 0438 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL2) @@ -10894,7 +10955,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( sd->npc_id || sd->state.workinprogress&1 ){ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return; } @@ -10902,7 +10963,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( pc_cant_act(sd) && skill_id != RK_REFRESH && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) - && ( sd->state.storage_flag && !(tmp&INF_SELF_SKILL) ) // SELF skills can be used with the storage open, issue: 8027 + && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027 ) return; @@ -10975,6 +11036,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski { int64 tick = timer->gettick(); + nullpo_retv(sd); if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) ) return; //Using a target skill on the ground? WRONG. @@ -10987,10 +11049,10 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski clif->pUseSkillToPos_mercenary(sd->md, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); return; } - + #ifdef RENEWAL if( sd->state.workinprogress&1 ){ - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. return; } #endif @@ -11050,7 +11112,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski } } - +void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to use a ground skill. /// 0116 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND) /// 0366 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND2) @@ -11071,7 +11133,7 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) ); } - +void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to use a ground skill with text. /// 0190 <skill lv>.W <skill id>.W <x>.W <y>.W <contents>.80B (CZ_USE_SKILL_TOGROUND_WITHTALKBOX) /// 0367 <skill lv>.W <skill id>.W <x>.W <y>.W <contents>.80B (CZ_USE_SKILL_TOGROUND_WITHTALKBOX2) @@ -11092,7 +11154,7 @@ void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) ); } - +void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -11107,7 +11169,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) return; // It is possible to use teleport with the storage window open issue:8027 - if( pc_cant_act(sd) && (!sd->state.storage_flag && skill_id != AL_TELEPORT) ) { + if (pc_cant_act(sd) && (sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)) { clif_menuskill_clear(sd); return; } @@ -11116,7 +11178,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) skill->castend_map(sd,skill_id,map_name); } - +void clif_parse_RequestMemo(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to set a memo on current map (CZ_REMEMBER_WARPPOINT). /// 011d void clif_parse_RequestMemo(int fd,struct map_session_data *sd) @@ -11125,7 +11187,7 @@ void clif_parse_RequestMemo(int fd,struct map_session_data *sd) pc->memo(sd,-1); } - +void clif_parse_ProduceMix(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to pharmacy item selection dialog (CZ_REQMAKINGITEM). /// 018e <name id>.W { <material id>.W }*3 void clif_parse_ProduceMix(int fd,struct map_session_data *sd) @@ -11150,7 +11212,7 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_Cooking(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to mixing item selection dialog (CZ_REQ_MAKINGITEM). /// 025b <mk type>.W <name id>.W /// mk type: @@ -11178,7 +11240,7 @@ void clif_parse_Cooking(int fd,struct map_session_data *sd) { clif_menuskill_clear(sd); } - +void clif_parse_RepairItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to repair weapon item selection dialog (CZ_REQ_ITEMREPAIR). /// 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) @@ -11195,7 +11257,7 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to refine weapon item selection dialog (CZ_REQ_WEAPONREFINE). /// 0222 <index>.L void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) @@ -11217,7 +11279,7 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to script menu dialog (CZ_CHOOSE_MENU). /// 00b8 <npc id>.L <choice>.B /// choice: @@ -11247,7 +11309,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) npc->scriptcont(sd,npc_id, false); } - +void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// NPC dialog 'next' click (CZ_REQ_NEXT_SCRIPT). /// 00b9 <npc id>.L void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) @@ -11255,7 +11317,7 @@ void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) npc->scriptcont(sd,RFIFOL(fd,2), false); } - +void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// NPC numeric input dialog value (CZ_INPUT_EDITDLG). /// 0143 <npc id>.L <value>.L void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) @@ -11263,11 +11325,14 @@ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) int npcid = RFIFOL(fd,2); int amount = (int)RFIFOL(fd,6); - sd->npc_amount = amount; + if (amount >= 0) + sd->npc_amount = amount; + else + sd->npc_amount = 0; npc->scriptcont(sd, npcid, false); } - +void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -11283,7 +11348,7 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) npc->scriptcont(sd, npcid, false); } - +void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// NPC dialog 'close' click (CZ_CLOSE_DIALOG). /// 0146 <npc id>.L void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) @@ -11294,7 +11359,7 @@ void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) npc->scriptcont(sd, RFIFOL(fd,2), true); } - +void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to identify item selection dialog (CZ_REQ_ITEMIDENTIFY). /// 0178 <index>.W /// index: @@ -11315,7 +11380,7 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_SelectArrow(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to arrow crafting item selection dialog (CZ_REQ_MAKINGARROW). /// 01ae <name id>.W void clif_parse_SelectArrow(int fd,struct map_session_data *sd) @@ -11347,7 +11412,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_AutoSpell(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to SA_AUTOSPELL skill selection dialog (CZ_SELECTAUTOSPELL). /// 01ce <skill id>.L void clif_parse_AutoSpell(int fd,struct map_session_data *sd) @@ -11366,27 +11431,23 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_UseCard(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to display item carding/composition list (CZ_REQ_ITEMCOMPOSITION_LIST). /// 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); } - +void clif_parse_InsertCard(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to carding/composing item selection dialog (CZ_REQ_ITEMCOMPOSITION). /// 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); } - +void clif_parse_SolveCharName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request of character's name by char ID. /// 0193 <char id>.L (CZ_REQNAME_BYGID) /// 0369 <char id>.L (CZ_REQNAME_BYGID2) @@ -11398,7 +11459,7 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { map->reqnickdb(sd, charid); } - +void clif_parse_ResetChar(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /resetskill /resetstate (CZ_RESET). /// Request to reset stats or skills. /// 0197 <type>.W @@ -11416,7 +11477,7 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { atcommand->exec(fd, sd, cmd, true); } - +void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /lb /nlb (CZ_LOCALBROADCAST). /// Request to broadcast a message on current map. /// 019c <packet len>.W <text>.?B @@ -11433,7 +11494,7 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) atcommand->exec(fd, sd, command, true); } - +void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from inventory to storage. /// 00f3 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_BODY_TO_STORE) /// 0364 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_BODY_TO_STORE2) @@ -11450,13 +11511,13 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->add(sd, item_index, item_amount); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->add(sd, item_index, item_amount); } - +void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from storage to inventory. /// 00f5 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_STORE_TO_BODY) /// 0365 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_STORE_TO_BODY2) @@ -11468,13 +11529,13 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1; item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]); - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->get(sd, item_index, item_amount); - else if(sd->state.storage_flag == 2) + else if(sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->get(sd, item_index, item_amount); } - +void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from cart to storage (CZ_MOVE_ITEM_FROM_CART_TO_STORE). /// 0129 <index>.W <amount>.L void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) @@ -11484,13 +11545,13 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); } - +void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move an item from storage to cart (CZ_MOVE_ITEM_FROM_STORE_TO_CART). /// 0128 <index>.W <amount>.L void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) @@ -11500,24 +11561,23 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); } - +void clif_parse_CloseKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to close storage (CZ_CLOSE_STORE). /// 00f7 void clif_parse_CloseKafra(int fd, struct map_session_data *sd) { - if( sd->state.storage_flag == 1 ) + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) storage->close(sd); - else if( sd->state.storage_flag == 2 ) + else if( sd->state.storage_flag == STORAGE_FLAG_GUILD ) gstorage->close(sd); } - /// Displays kafra storage password dialog (ZC_REQ_STORE_PASSWORD). /// 023a <info>.W /// info: @@ -11528,15 +11588,17 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) /// NOTE: This packet is only available on certain non-kRO clients. void clif_storagepassword(struct map_session_data* sd, short info) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x23a)); WFIFOW(fd,0) = 0x23a; WFIFOW(fd,2) = info; WFIFOSET(fd,packet_len(0x23a)); } - +void clif_parse_StoragePassword(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to the kafra storage password dialog (CZ_ACK_STORE_PASSWORD). /// 023b <type>.W <password>.16B <new password>.16B /// type: @@ -11548,7 +11610,6 @@ void clif_parse_StoragePassword(int fd, struct map_session_data *sd) //TODO } - /// Result of kafra storage password validation (ZC_RESULT_STORE_PASSWORD). /// 023c <result>.W <error count>.W /// result: @@ -11561,8 +11622,10 @@ void clif_parse_StoragePassword(int fd, struct map_session_data *sd) /// 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x23c)); WFIFOW(fd,0) = 0x23c; WFIFOW(fd,2) = result; @@ -11570,7 +11633,7 @@ void clif_storagepassword_result(struct map_session_data* sd, short result, shor WFIFOSET(fd,packet_len(0x23c)); } - +void clif_parse_CreateParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Party creation request /// 00f9 <party name>.24B (CZ_MAKE_GROUP) /// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2) @@ -11591,6 +11654,7 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) { party->create(sd,name,0,0); } +void clif_parse_CreateParty2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { char* name = (char*)RFIFOP(fd,2); int item1 = RFIFOB(fd,26); @@ -11610,7 +11674,7 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { party->create(sd,name,item1,item2); } - +void clif_parse_PartyInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Party invitation request /// 00fc <account id>.L (CZ_REQ_JOIN_GROUP) /// 02c4 <char name>.24B (CZ_PARTY_JOIN_REQ) @@ -11633,6 +11697,7 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { party->invite(sd, t_sd); } +void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) { struct map_session_data *t_sd; char *name = (char*)RFIFOP(fd,2); @@ -11654,7 +11719,7 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) { party->invite(sd, t_sd); } - +void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Party invitation reply /// 00ff <party id>.L <flag>.L (CZ_JOIN_GROUP) /// 02c7 <party id>.L <flag>.B (CZ_PARTY_JOIN_REQ_ACK) @@ -11666,12 +11731,13 @@ void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) party->reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } +void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) { party->reply_invite(sd,RFIFOL(fd,2),RFIFOB(fd,6)); } - +void clif_parse_LeaveParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to leave party (CZ_REQ_LEAVE_GROUP). /// 0100 void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { @@ -11683,7 +11749,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { party->leave(sd); } - +void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to expel a party member (CZ_REQ_EXPEL_GROUP_MEMBER). /// 0103 <account id>.L <char name>.24B void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { @@ -11695,7 +11761,7 @@ void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { party->removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); } - +void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change party options. /// 0102 <exp share rule>.L (CZ_CHANGE_GROUPEXPOPTION) /// 07d7 <exp share rule>.L <item pickup rule>.B <item share rule>.B (CZ_GROUPINFO_CHANGE_V2) @@ -11726,7 +11792,7 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) #endif } - +void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -11759,13 +11825,14 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) party->send_message(sd, text, textlen); } - +void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Changes Party Leader (CZ_CHANGE_GROUP_MASTER). /// 07da <account id>.L void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) { party->changeleader(sd, map->id2sd(RFIFOL(fd,2))); } - + +void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Party Booking in KRO [Spiria] /// @@ -11788,7 +11855,6 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) #endif } - /// Result of request to register a party booking advertisement (ZC_PARTY_BOOKING_ACK_REGISTER). /// 0803 <result>.W /// result: @@ -11798,8 +11864,10 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag) { #ifndef PARTY_RECRUIT - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x803)); WFIFOW(fd,0) = 0x803; WFIFOW(fd,2) = flag; @@ -11809,7 +11877,7 @@ void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag) #endif } - +void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to search for party booking advertisement (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) @@ -11827,7 +11895,6 @@ void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd) #endif } - /// Party booking search results (ZC_PARTY_BOOKING_ACK_SEARCH). /// 0805 <packet len>.W <more results>.B { <index>.L <char name>.24B <expire time>.L <level>.W <map id>.W { <job>.W }*6 }* /// more results: @@ -11839,6 +11906,7 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int i, j; int size = sizeof(struct party_booking_ad_info); // structure size (48) struct party_booking_ad_info *pb_ad; + nullpo_retv(results); WFIFOHEAD(fd,size*count + 5); WFIFOW(fd,0) = 0x805; WFIFOW(fd,2) = size*count + 5; @@ -11860,7 +11928,7 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, #endif } - +void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to delete own party booking advertisement (CZ_PARTY_BOOKING_REQ_DELETE). /// 0806 void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) @@ -11873,7 +11941,6 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) #endif } - /// Result of request to delete own party booking advertisement (ZC_PARTY_BOOKING_ACK_DELETE). /// 0807 <result>.W /// result: @@ -11884,8 +11951,10 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag) { #ifndef PARTY_RECRUIT - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x807)); WFIFOW(fd,0) = 0x807; WFIFOW(fd,2) = flag; @@ -11895,7 +11964,7 @@ void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag) #endif } - +void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to update party booking advertisement (CZ_PARTY_BOOKING_REQ_UPDATE). /// 0808 { <job>.W }*6 void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) @@ -11913,7 +11982,6 @@ void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) #endif } - /// Notification about new party booking advertisement (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) @@ -11922,6 +11990,7 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo int i; uint8 buf[38+PARTY_BOOKING_JOBS*2]; + nullpo_retv(sd); if(pb_ad == NULL) return; WBUFW(buf,0) = 0x809; @@ -11939,7 +12008,6 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo #endif } - /// Notification about updated party booking advertisement (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) @@ -11948,6 +12016,7 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo int i; uint8 buf[6+PARTY_BOOKING_JOBS*2]; + nullpo_retv(sd); if(pb_ad == NULL) return; WBUFW(buf,0) = 0x80a; @@ -11960,7 +12029,6 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo #endif } - /// Notification about deleted party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_DELETE). /// 080b <index>.L void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) @@ -11968,6 +12036,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) #ifndef PARTY_RECRUIT uint8 buf[6]; + nullpo_retv(sd); WBUFW(buf,0) = 0x80b; WBUFL(buf,2) = index; @@ -11977,6 +12046,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) #endif } +void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Modified version of Party Booking System for 2012-04-10 or 2012-04-18 (RagexeRE). /// Code written by mkbu95, Spiria, Yommy and Ind @@ -12006,6 +12076,7 @@ void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results, int size = sizeof(struct party_booking_ad_info); struct party_booking_ad_info *pb_ad; + nullpo_retv(results); WFIFOHEAD(fd, (size * count) + 5); WFIFOW(fd, 0) = 0x8e8; WFIFOW(fd, 2) = (size * count) + 5; @@ -12036,8 +12107,10 @@ void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results, void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag) { #ifdef PARTY_RECRUIT - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x8e6)); WFIFOW(fd, 0) = 0x8e6; WFIFOW(fd, 2) = flag; @@ -12047,6 +12120,7 @@ void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag) #endif } +void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to search for party booking advertisement (CZ_PARTY_RECRUIT_REQ_SEARCH). /// 08e7 <level>.W <map id>.W <last index>.L <result count>.W void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd) @@ -12063,6 +12137,7 @@ void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd) #endif } +void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to delete own party booking advertisement (CZ_PARTY_RECRUIT_REQ_DELETE). /// 08e9 void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) @@ -12085,8 +12160,10 @@ void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag) { #ifdef PARTY_RECRUIT - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x8ea)); WFIFOW(fd, 0) = 0x8ea; WFIFOW(fd, 2) = flag; @@ -12096,6 +12173,7 @@ void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag) #endif } +void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to update party booking advertisement (CZ_PARTY_RECRUIT_REQ_UPDATE). /// 08eb <notice>.37B void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) @@ -12118,6 +12196,7 @@ void clif_PartyRecruitInsertNotify(struct map_session_data* sd, struct party_boo #ifdef PARTY_RECRUIT unsigned char buf[2+6+6+24+4+37+1]; + nullpo_retv(sd); if (pb_ad == NULL) return; @@ -12140,6 +12219,8 @@ void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_boo #ifdef PARTY_RECRUIT unsigned char buf[2+6+37+1]; + nullpo_retv(sd); + nullpo_retv(pb_ad); WBUFW(buf, 0) = 0x8ed; WBUFL(buf, 2) = pb_ad->index; memcpy(WBUFP(buf, 6), pb_ad->p_detail.notice, PB_NOTICE_LENGTH); @@ -12157,6 +12238,7 @@ void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index) #ifdef PARTY_RECRUIT unsigned char buf[2+6+1]; + nullpo_retv(sd); WBUFW(buf, 0) = 0x8ee; WBUFL(buf, 2) = index; @@ -12166,6 +12248,7 @@ void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index) #endif } +void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add to filtering list (PARTY_RECRUIT_ADD_FILTERLINGLIST). /// 08ef <index>.L void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd) @@ -12179,6 +12262,7 @@ void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd #endif } +void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to remove from filtering list (PARTY_RECRUIT_SUB_FILTERLINGLIST). /// 08f0 <GID>.L void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd) @@ -12192,6 +12276,7 @@ void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd #endif } +void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to recruit volunteer (PARTY_RECRUIT_REQ_VOLUNTEER). /// 08f1 <index>.L void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd) @@ -12212,6 +12297,7 @@ void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd) #ifdef PARTY_RECRUIT unsigned char buf[2+4+4+2+24+1]; + nullpo_retv(sd); WBUFW(buf, 0) = 0x8f2; WBUFL(buf, 2) = sd->status.account_id; WBUFL(buf, 6) = sd->status.class_; @@ -12230,21 +12316,25 @@ void clif_PartyBookingPersonalSetting(int fd, struct map_session_data *sd) { } +void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08f4 <target GID>.L void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd) { } +void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08f5 <packet len>.W void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd) { } +void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08f6 <money>.L <map name>.16B void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd) { } +void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08f7 <result>.B void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd) { @@ -12257,11 +12347,13 @@ void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd) /// REASON_REFUSE = 0x2 /// REASON_NOT_PARTY_MEMBER = 0x3 /// REASON_ETC = 0x4 +void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd) { } #endif //if 0 +void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08f9 <refuse AID>.L void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd) { @@ -12274,6 +12366,7 @@ void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd) #endif } +void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08fa <index>.L void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd) { @@ -12289,6 +12382,7 @@ void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data #endif } +void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 08fb <index>.L void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd) { @@ -12307,6 +12401,7 @@ void clif_PartyBookingCancelVolunteer(int index, struct map_session_data *sd) #ifdef PARTY_RECRUIT unsigned char buf[2+6+1]; + nullpo_retv(sd); WBUFW(buf, 0) = 0x909; WBUFL(buf, 2) = index; @@ -12322,6 +12417,7 @@ void clif_PartyBookingAddFilteringList(int index, struct map_session_data *sd) #ifdef PARTY_RECRUIT unsigned char buf[2+6+24+1]; + nullpo_retv(sd); WBUFW(buf, 0) = 0x90b; WBUFL(buf, 2) = sd->bl.id; memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH); @@ -12338,6 +12434,7 @@ void clif_PartyBookingSubFilteringList(int gid, struct map_session_data *sd) #ifdef PARTY_RECRUIT unsigned char buf[2+6+24+1]; + nullpo_retv(sd); WBUFW(buf, 0) = 0x90c; WBUFL(buf, 2) = gid; memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH); @@ -12360,6 +12457,7 @@ void clif_PartyBookingRefuseVolunteerToPM(struct map_session_data *sd) } #endif //if 0 +void clif_parse_CloseVending(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to close own vending (CZ_REQ_CLOSESTORE). /// 012e void clif_parse_CloseVending(int fd, struct map_session_data* sd) @@ -12367,7 +12465,7 @@ void clif_parse_CloseVending(int fd, struct map_session_data* sd) vending->close(sd); } - +void clif_parse_VendingListReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -12378,7 +12476,7 @@ void clif_parse_VendingListReq(int fd, struct map_session_data* sd) vending->list(sd,RFIFOL(fd,2)); } - +void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) __attribute__((nonnull (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) @@ -12393,7 +12491,7 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) sd->vended_id = 0; } - +void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -12409,7 +12507,7 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) sd->vended_id = 0; } - +void clif_parse_OpenVending(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Confirm or cancel the shop preparation window. /// 012f <packet len>.W <shop name>.80B { <index>.W <amount>.W <price>.L }* (CZ_REQ_OPENSTORE) /// 01b2 <packet len>.W <shop name>.80B <result>.B { <index>.W <amount>.W <price>.L }* (CZ_REQ_OPENSTORE2) @@ -12431,7 +12529,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) { clif->message (sd->fd, msg_sd(sd,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) ) { + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) { clif->message (sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell." return; } @@ -12442,6 +12540,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) { vending->open(sd, message, data, len/8); } +void clif_parse_CreateGuild(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild creation request (CZ_REQ_MAKE_GUILD). /// 0165 <char id>.L <guild name>.24B void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { @@ -12457,7 +12556,7 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { guild->create(sd, name); } - +void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request for guild window interface permissions (CZ_REQ_GUILD_MENUINTERFACE). /// 014d void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) @@ -12465,7 +12564,7 @@ void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) clif->guild_masterormember(sd); } - +void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request for guild window information (CZ_REQ_GUILD_MENU). /// 014f <type>.L /// type: @@ -12506,7 +12605,7 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) } } - +void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to update guild positions (CZ_REG_CHANGE_GUILD_POSITIONINFO). /// 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) @@ -12521,7 +12620,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) } } - +void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to update the position of guild members (CZ_REQ_CHANGE_MEMBERPOS). /// 0155 <packet len>.W { <account id>.L <char id>.L <position id>.L }* void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) @@ -12537,7 +12636,7 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) } } - +void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request for guild emblem data (CZ_REQ_GUILD_EMBLEM_IMG). /// 0151 <guild id>.L void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) @@ -12575,6 +12674,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { unsigned long buf_len = sizeof(buf); int header = 0, bitmap = 0, offbits = 0, palettesize = 0; + nullpo_retr(false, emblem); if( decode_zip(buf, &buf_len, emblem, emblem_len) != 0 || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE || RBUFW(buf,0) != 0x4d42 // BITMAPFILEHEADER.bfType (signature) || RBUFL(buf,2) != buf_len // BITMAPFILEHEADER.bfSize (file size) @@ -12672,7 +12772,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { return true; } - +void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to update the guild emblem (CZ_REGISTER_GUILD_EMBLEM_IMG). /// 0153 <packet len>.W <emblem data>.?B void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) @@ -12692,7 +12792,7 @@ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) guild->change_emblem(sd, emblem_len, (const char*)emblem); } - +void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -12717,13 +12817,15 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi if ( t_sd == NULL )// not online or does not exist return false; + nullpo_retr(false, sd); + nullpo_retr(false, t_sd); if ( map->list[sd->bl.m].flag.guildlock ) { //Guild locked. clif->message(fd, msg_fd(fd,228)); return false; } - if ( t_sd && t_sd->state.noask ) {// @noask [LuzZza] + if (t_sd->state.noask) {// @noask [LuzZza] clif->noask_sub(sd, t_sd, 2); return false; } @@ -12732,6 +12834,7 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi return true; } +void clif_parse_GuildInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild invite request (CZ_REQ_JOIN_GUILD). /// 0168 <account id>.L <inviter account id>.L <inviter char id>.L void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { @@ -12741,15 +12844,20 @@ void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { return; } +void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2). /// 0916 <char name>.24B void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) { - struct map_session_data *t_sd = map->nick2sd((char *)RFIFOP(fd, 2)); + char *nick = (char*)RFIFOP(fd, 2); + struct map_session_data *t_sd = map->nick2sd(nick); + + nick[NAME_LENGTH - 1] = '\0'; if (!clif_sub_guild_invite(fd, sd, t_sd)) return; } +void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to guild invitation (CZ_JOIN_GUILD). /// 016b <guild id>.L <answer>.L /// answer: @@ -12760,7 +12868,7 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) guild->reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } - +void clif_parse_GuildLeave(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to leave guild (CZ_REQ_LEAVE_GUILD). /// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { @@ -12777,7 +12885,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { guild->leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } - +void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to expel a member of a guild (CZ_REQ_BAN_GUILD). /// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { @@ -12789,7 +12897,7 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { guild->expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } - +void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -12825,7 +12933,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) guild->send_message(sd, text, textlen); } - +void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild alliance request (CZ_REQ_ALLY_GUILD). /// 0170 <account id>.L <inviter account id>.L <inviter char id>.L void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) { @@ -12851,7 +12959,7 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) { guild->reqalliance(sd,t_sd); } - +void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to a guild alliance request (CZ_ALLY_GUILD). /// 0172 <inviter account id>.L <answer>.L /// answer: @@ -12862,7 +12970,7 @@ void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) guild->reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } - +void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to delete a guild alliance or opposition (CZ_REQ_DELETE_RELATED_GUILD). /// 0183 <opponent guild id>.L <relation>.L /// relation: @@ -12880,7 +12988,7 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) { guild->delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } - +void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to set a guild as opposition (CZ_REQ_HOSTILE_GUILD). /// 0180 <account id>.L void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) { @@ -12906,7 +13014,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) { guild->opposition(sd,t_sd); } - +void clif_parse_GuildBreak(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to delete own guild (CZ_REQ_DISORGANIZE_GUILD). /// 015d <key>.40B /// key: @@ -12921,10 +13029,10 @@ void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { guild->dobreak(sd,(char*)RFIFOP(fd,2)); } - /// Pet /// +void clif_parse_PetMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to invoke a pet menu action (CZ_COMMAND_PET). /// 01a1 <type>.B /// type: @@ -12938,7 +13046,7 @@ void clif_parse_PetMenu(int fd, struct map_session_data *sd) pet->menu(sd,RFIFOB(fd,2)); } - +void clif_parse_CatchPet(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Attempt to tame a monster (CZ_TRYCAPTURE_MONSTER). /// 019f <id>.L void clif_parse_CatchPet(int fd, struct map_session_data *sd) @@ -12946,7 +13054,7 @@ void clif_parse_CatchPet(int fd, struct map_session_data *sd) pet->catch_process2(sd,RFIFOL(fd,2)); } - +void clif_parse_SelectEgg(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to pet incubator egg selection dialog (CZ_SELECT_PETEGG). /// 01a7 <index>.W void clif_parse_SelectEgg(int fd, struct map_session_data *sd) @@ -12958,7 +13066,7 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd) clif_menuskill_clear(sd); } - +void clif_parse_SendEmotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to display pet's emotion/talk (CZ_PET_ACT). /// 01a9 <data>.L /// data: @@ -12989,7 +13097,7 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd) clif->pet_emotion(sd->pd,RFIFOL(fd,2)); } - +void clif_parse_ChangePetName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change pet's name (CZ_RENAME_PET). /// 01a5 <name>.24B void clif_parse_ChangePetName(int fd, struct map_session_data *sd) @@ -12997,7 +13105,7 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) pet->change_name(sd,(char*)RFIFOP(fd,2)); } - +void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /kill (CZ_DISCONNECT_CHARACTER). /// Request to disconnect a character. /// 00cc <account id>.L @@ -13056,7 +13164,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) { } } - +void clif_parse_GMKickAll(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /killall (CZ_DISCONNECT_ALL_CHARACTER). /// Request to disconnect all characters. /// 00ce @@ -13066,7 +13174,7 @@ void clif_parse_GMKickAll(int fd, struct map_session_data* sd) { atcommand->exec(fd, sd, cmd, true); } - +void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /remove (CZ_REMOVE_AID). /// Request to warp to a character with given login ID. /// 01ba <account name>.24B @@ -13086,7 +13194,7 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) atcommand->exec(fd, sd, command, true); } - +void clif_parse_GMRemove2(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /remove (CZ_REMOVE_AID_SSO). /// Request to warp to a character with given account ID. /// 0843 <account id>.L @@ -13102,7 +13210,7 @@ void clif_parse_GMRemove2(int fd, struct map_session_data* sd) { } } - +void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /recall (CZ_RECALL). /// Request to summon a player with given login ID to own position. /// 01bc <account name>.24B @@ -13122,7 +13230,7 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) atcommand->exec(fd, sd, command, true); } - +void clif_parse_GMRecall2(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /recall (CZ_RECALL_SSO). /// Request to summon a player with given account ID to own position. /// 0842 <account id>.L @@ -13138,7 +13246,7 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) { } } - +void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /item /monster (CZ_ITEM_CREATE). /// Request to execute GM commands. /// usage: @@ -13208,7 +13316,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { } } - +void clif_parse_GMHide(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /hide (CZ_CHANGE_EFFECTSTATE). /// 019d <effect state>.L /// effect state: @@ -13221,7 +13329,7 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) { atcommand->exec(fd, sd, cmd, true); } - +void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to adjust player's manner points (CZ_REQ_GIVE_MANNER_POINT). /// 0149 <account id>.L <type>.B <value>.W /// type: @@ -13275,7 +13383,7 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) { atcommand->exec(fd, sd, command, true); } - +void clif_parse_GMRc(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /rc (CZ_REQ_GIVE_MANNER_BYNAME). /// GM adjustment of a player's manner value by -60. /// 0212 <char name>.24B @@ -13289,12 +13397,13 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd) atcommand->exec(fd, sd, command, true); } - /// 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x1e0)); WFIFOW(fd,0) = 0x1e0; WFIFOL(fd,2) = account_id; @@ -13302,7 +13411,7 @@ void clif_account_name(struct map_session_data* sd, int account_id, const char* WFIFOSET(fd,packet_len(0x1e0)); } - +void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// GM requesting account name (for right-click gm menu) (CZ_REQ_ACCOUNTNAME). /// 01df <account id>.L void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) @@ -13313,7 +13422,7 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) clif->account_name(sd, account_id, ""); // insert account name here >_< } - +void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /changemaptype <x> <y> <type> (CZ_CHANGE_MAPTYPE). /// GM single cell type change request. /// 0198 <x>.W <y>.W <type>.W @@ -13335,7 +13444,7 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) { //FIXME: once players leave the map, the client 'forgets' this information. } - +void clif_parse_PMIgnore(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// /in /ex (CZ_SETTING_WHISPER_PC). /// Request to allow/deny whispers from a nick. /// 00cf <nick>.24B <type>.B @@ -13388,7 +13497,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) { clif->wisexin(sd, type, 0); // success } - +void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /inall /exall (CZ_SETTING_WHISPER_STATE). /// Request to allow/deny all whispers. /// 00d0 <type>.B @@ -13424,12 +13533,13 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) 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) { - int i, fd = sd->fd; + int i, fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,4+ARRAYLENGTH(sd->ignore)*NAME_LENGTH); WFIFOW(fd,0) = 0xd4; @@ -13441,7 +13551,7 @@ void clif_PMIgnoreList(struct map_session_data* sd) { WFIFOSET(fd,WFIFOW(fd,2)); } - +void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Whisper ignore list request (CZ_REQ_WHISPER_LIST). /// 00d3 void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) @@ -13449,7 +13559,7 @@ void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) clif->PMIgnoreList(sd); } - +void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to invoke the /doridori recovery bonus (CZ_DORIDORI). /// 01e7 void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) @@ -13468,7 +13578,7 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) } } - +void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to invoke the effect of super novice's guardian angel prayer (CZ_CHOPOKGI). /// 01ed /// Note: This packet is caused by 7 lines of any text, followed by @@ -13497,7 +13607,6 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) } } - /// Friends List /// @@ -13507,8 +13616,10 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) /// 0 = online /// 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; + nullpo_retv(sd); + 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++); @@ -13524,7 +13635,6 @@ void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int cha WFIFOSET(fd, packet_len(0x206)); } - //Sub-function called from clif_foreachclient to toggle friends on/off [Skotlex] int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap) { @@ -13536,13 +13646,13 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap) return 0; } - /// Sends the whole friends list (ZC_FRIENDS_LIST). /// 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; + nullpo_retv(sd); // Send friends list WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4); WFIFOW(fd, 0) = 0x201; @@ -13563,7 +13673,6 @@ void clif_friendslist_send(struct map_session_data *sd) } } - /// Notification about the result of a friend add request (ZC_ADD_FRIENDS_LIST). /// 0209 <result>.W <account id>.L <char id>.L <name>.24B /// result: @@ -13588,12 +13697,13 @@ void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_dat 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x207)); WFIFOW(fd,0) = 0x207; WFIFOL(fd,2) = account_id; @@ -13602,14 +13712,16 @@ void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_i WFIFOSET(fd,packet_len(0x207)); } - +void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add a player as friend (CZ_ADD_FRIENDS). /// 0202 <name>.24B void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { struct map_session_data *f_sd; int i; + char *nick = (char*)RFIFOP(fd,2); - f_sd = map->nick2sd((char*)RFIFOP(fd,2)); + nick[NAME_LENGTH - 1] = '\0'; + f_sd = map->nick2sd(nick); // ensure that the request player's friend list is not full ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0); @@ -13649,7 +13761,7 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { clif->friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name); } - +void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to a friend add request (CZ_ACK_REQ_ADD_FRIENDS). /// 0208 <inviter account id>.L <inviter char id>.L <result>.B /// 0208 <inviter account id>.L <inviter char id>.L <result>.L (PACKETVER >= 6) @@ -13717,7 +13829,7 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) } } - +void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to delete a friend (CZ_DELETE_FRIENDS). /// 0203 <account id>.L <char id>.L void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) @@ -13781,12 +13893,13 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x210)); WFIFOW(fd,0) = 0x210; WFIFOL(fd,2) = sd->status.char_id; @@ -13797,7 +13910,7 @@ void clif_PVPInfo(struct map_session_data* sd) { WFIFOSET(fd, packet_len(0x210)); } - +void clif_parse_PVPInfo(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// /pvpinfo (CZ_REQ_PVPPOINT). /// 020f <char id>.L <account id>.L void clif_parse_PVPInfo(int fd,struct map_session_data *sd) @@ -13814,6 +13927,7 @@ void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) { struct fame_list* list; int i; + nullpo_retv(buf); switch( type ) { case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break; case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break; @@ -13842,10 +13956,13 @@ void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) { /// 097d <RankingType>.W {<CharName>.24B <point>L}*10 <mypoint>L (ZC_ACK_RANKING) void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) { - int fd = sd->fd; + int fd; int mypoint = 0; - int upperMask = sd->class_&MAPID_UPPERMASK; + int upperMask; + nullpo_retv(sd); + fd = sd->fd; + upperMask = sd->class_&MAPID_UPPERMASK; WFIFOHEAD(fd, 288); WFIFOW(fd, 0) = 0x97d; WFIFOW(fd, 2) = type; @@ -13864,6 +13981,7 @@ void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) { WFIFOSET(fd, 288); } +void clif_parse_ranklist(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /* * 097c <type> (CZ_REQ_RANKING) * */ @@ -13888,7 +14006,11 @@ void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type t case RANKTYPE_TAEKWON: clif->fame_taekwon(sd,points); break; } #else - int fd = sd->fd; + + int fd; + + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, 12); WFIFOW(fd, 0) = 0x97e; WFIFOW(fd, 2) = type; @@ -13901,14 +14023,17 @@ void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type t /// /blacksmith list (ZC_BLACKSMITH_RANK). /// 0219 { <name>.24B }*10 { <point>.L }*10 void clif_blacksmith(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x219)); WFIFOW(fd,0) = 0x219; clif_ranklist_sub(WFIFOP(fd, 2), RANKTYPE_BLACKSMITH); WFIFOSET(fd, packet_len(0x219)); } +void clif_parse_Blacksmith(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// /blacksmith (CZ_BLACKSMITH_RANK). /// 0217 void clif_parse_Blacksmith(int fd,struct map_session_data *sd) { @@ -13918,8 +14043,10 @@ void clif_parse_Blacksmith(int fd,struct map_session_data *sd) { /// Notification about backsmith points (ZC_BLACKSMITH_POINT). /// 021b <points>.L <total points>.L void clif_fame_blacksmith(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x21b)); WFIFOW(fd,0) = 0x21b; WFIFOL(fd,2) = points; @@ -13930,14 +14057,17 @@ void clif_fame_blacksmith(struct map_session_data *sd, int points) { /// /alchemist list (ZC_ALCHEMIST_RANK). /// 021a { <name>.24B }*10 { <point>.L }*10 void clif_alchemist(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x21a)); WFIFOW(fd,0) = 0x21a; clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_ALCHEMIST); WFIFOSET(fd, packet_len(0x21a)); } +void clif_parse_Alchemist(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// /alchemist (CZ_ALCHEMIST_RANK). /// 0218 void clif_parse_Alchemist(int fd,struct map_session_data *sd) { @@ -13947,8 +14077,10 @@ void clif_parse_Alchemist(int fd,struct map_session_data *sd) { /// Notification about alchemist points (ZC_ALCHEMIST_POINT). /// 021c <points>.L <total points>.L void clif_fame_alchemist(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x21c)); WFIFOW(fd,0) = 0x21c; WFIFOL(fd,2) = points; @@ -13959,14 +14091,17 @@ void clif_fame_alchemist(struct map_session_data *sd, int points) { /// /taekwon list (ZC_TAEKWON_RANK). /// 0226 { <name>.24B }*10 { <point>.L }*10 void clif_taekwon(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x226)); WFIFOW(fd,0) = 0x226; clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_TAEKWON); WFIFOSET(fd, packet_len(0x226)); } +void clif_parse_Taekwon(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// /taekwon (CZ_TAEKWON_RANK). /// 0225 void clif_parse_Taekwon(int fd,struct map_session_data *sd) { @@ -13976,8 +14111,10 @@ void clif_parse_Taekwon(int fd,struct map_session_data *sd) { /// Notification about taekwon points (ZC_TAEKWON_POINT). /// 0224 <points>.L <total points>.L void clif_fame_taekwon(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x224)); WFIFOW(fd,0) = 0x224; WFIFOL(fd,2) = points; @@ -13988,8 +14125,10 @@ void clif_fame_taekwon(struct map_session_data *sd, int points) { /// /pk list (ZC_KILLER_RANK). /// 0238 { <name>.24B }*10 { <point>.L }*10 void clif_ranking_pk(struct map_session_data* sd) { - int i, fd = sd->fd; + int i, fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x238)); WFIFOW(fd,0) = 0x238; for (i = 0; i < 10;i ++) { @@ -13999,14 +14138,14 @@ void clif_ranking_pk(struct map_session_data* sd) { WFIFOSET(fd, packet_len(0x238)); } - +void clif_parse_RankingPk(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// /pk (CZ_KILLER_RANK). /// 0237 void clif_parse_RankingPk(int fd,struct map_session_data *sd) { clif->ranking_pk(sd); } - +void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// SG Feel save OK [Komurka] (CZ_AGREE_STARPLACE). /// 0254 <which>.B /// which: @@ -14033,7 +14172,6 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } - /// Star Gladiator's Feeling map confirmation prompt (ZC_STARPLACE). /// 0253 <which>.B /// which: @@ -14042,6 +14180,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) /// 2 = star void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv) { + nullpo_retv(sd); WFIFOHEAD(fd,packet_len(0x253)); WFIFOW(fd,0)=0x253; WFIFOB(fd,2)=TOB(skill_lv-1); @@ -14050,14 +14189,14 @@ void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv) sd->menuskill_val = skill_lv; } - +void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change homunculus' name (CZ_RENAME_MER). /// 0231 <name>.24B void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { homun->change_name(sd,(char*)RFIFOP(fd,2)); } - +void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to warp/move homunculus/mercenary to it's owner (CZ_REQUEST_MOVETOOWNER). /// 0234 <id>.L void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) @@ -14066,9 +14205,9 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) struct block_list *bl = NULL; struct unit_data *ud = NULL; - if( sd->md && sd->md->bl.id == id ) + if (sd->md && sd->md->bl.id == id) bl = &sd->md->bl; - else if( homun_alive(sd->hd) && sd->hd->bl.id == id ) + else if (homun_alive(sd->hd) && sd->hd->bl.id == id) bl = &sd->hd->bl; // Moving Homunculus else return; @@ -14078,7 +14217,7 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) unit->walktoxy(bl, ud->to_x, ud->to_y, 4); } - +void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to move homunculus/mercenary (CZ_REQUEST_MOVENPC). /// 0232 <id>.L <position data>.3B void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) @@ -14099,7 +14238,7 @@ void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) unit->walktoxy(bl, x, y, 4); } - +void clif_parse_HomAttack(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to do an action with homunculus/mercenary (CZ_REQUEST_ACTNPC). /// 0233 <id>.L <target id>.L <action>.B /// action: @@ -14121,7 +14260,7 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd) unit->attack(bl, target_id, action_type != 0); } - +void clif_parse_HomMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to invoke a homunculus menu action (CZ_COMMAND_MER). /// 022d <type>.W <command>.B /// type: @@ -14141,7 +14280,7 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn] homun->menu(sd,RFIFOB(fd,packet_db[cmd].pos[1])); } - +void clif_parse_AutoRevive(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to resurrect oneself using Token of Siegfried (CZ_STANDING_RESURRECTION). /// 0292 void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { @@ -14164,12 +14303,11 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { if (item_position == INDEX_NOT_FOUND) status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); else - pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); + pc->delitem(sd, item_position, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); } - /// Information about character's status values (ZC_ACK_STATUS_GM). /// 0214 <str>.B <standardStr>.B <agi>.B <standardAgi>.B <vit>.B <standardVit>.B /// <int>.B <standardInt>.B <dex>.B <standardDex>.B <luk>.B <standardLuk>.B @@ -14178,6 +14316,7 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { /// <hitSuccessValue>.W <avoidSuccessValue>.W <plusAvoidSuccessValue>.W /// <criticalSuccessValue>.W <ASPD>.W <plusASPD>.W void clif_check(int fd, struct map_session_data* pl_sd) { + nullpo_retv(pl_sd); WFIFOHEAD(fd,packet_len(0x214)); WFIFOW(fd, 0) = 0x214; WFIFOB(fd, 2) = min(pl_sd->status.str, UINT8_MAX); @@ -14209,7 +14348,7 @@ void clif_check(int fd, struct map_session_data* pl_sd) { WFIFOSET(fd,packet_len(0x214)); } - +void clif_parse_Check(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /check (CZ_REQ_STATUS_GM). /// Request character's status values. /// 0213 <char name>.24B @@ -14230,8 +14369,6 @@ void clif_parse_Check(int fd, struct map_session_data *sd) clif->check(fd, pl_sd); } - - /// MAIL SYSTEM /// By Zephyrus /// @@ -14250,7 +14387,6 @@ void clif_Mail_setattachment(int fd, int index, uint8 flag) WFIFOSET(fd,packet_len(0x255)); } - /// Notification about the result of retrieving a mail attachment (ZC_MAIL_REQ_GET_ITEM). /// 0245 <result>.B /// result: @@ -14265,7 +14401,6 @@ void clif_Mail_getattachment(int fd, uint8 flag) WFIFOSET(fd,packet_len(0x245)); } - /// Notification about the result of sending a mail (ZC_MAIL_REQ_SEND). /// 0249 <result>.B /// result: @@ -14279,7 +14414,6 @@ void clif_Mail_send(int fd, bool fail) WFIFOSET(fd,packet_len(0x249)); } - /// Notification about the result of deleting a mail (ZC_ACK_MAIL_DELETE). /// 0257 <mail id>.L <result>.W /// result: @@ -14294,7 +14428,6 @@ void clif_Mail_delete(int fd, int mail_id, short fail) WFIFOSET(fd, packet_len(0x257)); } - /// Notification about the result of returning a mail (ZC_ACK_MAIL_RETURN). /// 0274 <mail id>.L <result>.W /// result: @@ -14309,11 +14442,12 @@ void clif_Mail_return(int fd, int mail_id, short fail) WFIFOSET(fd,packet_len(0x274)); } - /// Notification about new mail (ZC_MAIL_RECEIVE). /// 024a <mail id>.L <title>.40B <sender>.24B void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) { + nullpo_retv(sender); + nullpo_retv(title); WFIFOHEAD(fd,packet_len(0x24a)); WFIFOW(fd,0) = 0x24a; WFIFOL(fd,2) = mail_id; @@ -14322,7 +14456,6 @@ void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) WFIFOSET(fd,packet_len(0x24a)); } - /// Opens/closes the mail window (ZC_MAIL_WINDOWS). /// 0260 <type>.L /// type: @@ -14336,7 +14469,6 @@ void clif_Mail_window(int fd, int flag) WFIFOSET(fd,packet_len(0x260)); } - /// Lists mails stored in inbox (ZC_MAIL_REQ_GET_LIST). /// 0240 <packet len>.W <amount>.L { <mail id>.L <title>.40B <read>.B <sender>.24B <time>.L }*amount /// read: @@ -14345,10 +14477,12 @@ void clif_Mail_window(int fd, int flag) void clif_Mail_refreshinbox(struct map_session_data *sd) { int fd = sd->fd; - struct mail_data *md = &sd->mail.inbox; + struct mail_data *md; struct mail_message *msg; int len, i, j; + nullpo_retv(sd); + md = &sd->mail.inbox; len = 8 + (73 * md->amount); WFIFOHEAD(fd,len); @@ -14377,7 +14511,7 @@ void clif_Mail_refreshinbox(struct map_session_data *sd) } } - +void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Mail inbox list request (CZ_MAIL_GET_LIST). /// 023f void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) @@ -14393,7 +14527,6 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) mail->removezeny(sd, 0); } - /// Opens a mail (ZC_MAIL_REQ_OPEN). /// 0242 <packet len>.W <mail id>.L <title>.40B <sender>.24B <time>.L <zeny>.L /// <amount>.L <name id>.W <item type>.W <identified>.B <damaged>.B <refine>.B @@ -14402,6 +14535,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) { int i, fd = sd->fd; + nullpo_retv(sd); 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 @@ -14455,7 +14589,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) } } - +void clif_parse_Mail_read(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to open a mail (CZ_MAIL_OPEN). /// 0241 <mail id>.L void clif_parse_Mail_read(int fd, struct map_session_data *sd) @@ -14470,7 +14604,7 @@ void clif_parse_Mail_read(int fd, struct map_session_data *sd) clif->mail_read(sd, RFIFOL(fd,2)); } - +void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to receive mail's attachment (CZ_MAIL_GET_ITEM). /// 0244 <mail id>.L void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) @@ -14532,12 +14666,13 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) sd->mail.inbox.msg[i].zeny = 0; memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); - clif->mail_read(sd, mail_id); + mail->clear(sd); + clif->mail_read(sd, mail_id); intif->Mail_getattach(sd->status.char_id, mail_id); } - +void clif_parse_Mail_delete(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to delete a mail (CZ_MAIL_DELETE). /// 0243 <mail id>.L void clif_parse_Mail_delete(int fd, struct map_session_data *sd) @@ -14561,11 +14696,14 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd) return; } + sd->mail.inbox.msg[i].zeny = 0; + memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); + mail->clear(sd); intif->Mail_delete(sd->status.char_id, mail_id); } } - +void clif_parse_Mail_return(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to return a mail (CZ_REQ_MAIL_RETURN). /// 0273 <mail id>.L <receive name>.24B void clif_parse_Mail_return(int fd, struct map_session_data *sd) @@ -14579,13 +14717,17 @@ void clif_parse_Mail_return(int fd, struct map_session_data *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 ) + if (i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0) { + sd->mail.inbox.msg[i].zeny = 0; + memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); + mail->clear(sd); intif->Mail_return(sd->status.char_id, mail_id); - else + } else { clif->mail_return(sd->fd, mail_id, 1); + } } - +void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add an item or Zeny to mail (CZ_MAIL_ADD_ITEM). /// 0247 <index>.W <amount>.L void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) @@ -14603,7 +14745,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) clif->mail_setattachment(fd,idx,flag); } - +void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to reset mail item and/or Zeny (CZ_MAIL_RESET_ITEM). /// 0246 <type>.W /// type: @@ -14620,7 +14762,7 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) mail->removezeny(sd, 0); } - +void clif_parse_Mail_send(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to send mail (CZ_MAIL_SEND). /// 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) @@ -14680,7 +14822,6 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) sd->cansendmail_tick = timer->gettick() + 1000; // 1 Second flood Protection } - /// AUCTION SYSTEM /// By Zephyrus /// @@ -14692,9 +14833,11 @@ 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; - if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + nullpo_retv(sd); + fd = sd->fd; + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading) return; if( !battle_config.feature_auction ) @@ -14706,15 +14849,16 @@ void clif_Auction_openwindow(struct map_session_data *sd) WFIFOSET(fd,packet_len(0x25f)); } - /// Returns auction item search results (ZC_AUCTION_ITEM_REQ_SEARCH). /// 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); + int i, fd, len = sizeof(struct auction_data); struct auction_data auction; struct item_data *item; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,12 + (count * 83)); WFIFOW(fd,0) = 0x252; WFIFOW(fd,2) = 12 + (count * 83); @@ -14750,7 +14894,6 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, WFIFOSET(fd,WFIFOW(fd,2)); } - /// Result from request to add an item (ZC_ACK_AUCTION_ADD_ITEM). /// 0256 <index>.W <result>.B /// result: @@ -14764,7 +14907,7 @@ void clif_Auction_setitem(int fd, int index, bool fail) { WFIFOSET(fd,packet_len(0x256)); } - +void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to initialize 'new auction' data (CZ_AUCTION_CREATE). /// 024b <type>.W /// type: @@ -14779,7 +14922,7 @@ void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) sd->auction.amount = 0; } - +void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add an item to the action (CZ_AUCTION_ADD_ITEM). /// 024c <index>.W <count>.L void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) @@ -14844,7 +14987,6 @@ void clif_Auction_message(int fd, unsigned char flag) WFIFOSET(fd,packet_len(0x250)); } - /// Result of the auction close request (ZC_AUCTION_ACK_MY_SELL_STOP). /// 025e <result>.W /// result: @@ -14859,7 +15001,7 @@ void clif_Auction_close(int fd, unsigned char flag) WFIFOSET(fd,packet_len(0x25e)); } - +void clif_parse_Auction_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add an auction (CZ_AUCTION_ADD). /// 024d <now money>.L <max money>.L <delete hour>.W void clif_parse_Auction_register(int fd, struct map_session_data *sd) @@ -14870,12 +15012,19 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) if (!battle_config.feature_auction) return; + Assert_retv(sd->auction.index >= 0 && sd->auction.index < MAX_INVENTORY); + memset(&auction, 0, sizeof(auction)); auction.price = RFIFOL(fd,2); auction.buynow = RFIFOL(fd,6); auction.hours = RFIFOW(fd,10); // Invalid Situations... + if (auction.price <= 0 || auction.buynow <= 0) { + ShowWarning("Character %s trying to register auction wit wrong price.\n", sd->status.name); + return; + } + if( sd->auction.amount < 1 ) { ShowWarning("Character %s trying to register auction without item.\n", sd->status.name); return; @@ -14940,14 +15089,14 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) { int zeny = auction.hours*battle_config.auction_feeperhour; - pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION); + pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, DELITEM_SOLD, LOG_TYPE_AUCTION); sd->auction.amount = 0; pc->payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); } } - +void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Cancels an auction (CZ_AUCTION_ADD_CANCEL). /// 024e <auction id>.L void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) @@ -14957,7 +15106,7 @@ void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) intif->Auction_cancel(sd->status.char_id, auction_id); } - +void clif_parse_Auction_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Closes an auction (CZ_AUCTION_REQ_MY_SELL_STOP). /// 025d <auction id>.L void clif_parse_Auction_close(int fd, struct map_session_data *sd) @@ -14967,7 +15116,7 @@ void clif_parse_Auction_close(int fd, struct map_session_data *sd) intif->Auction_close(sd->status.char_id, auction_id); } - +void clif_parse_Auction_bid(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Places a bid on an auction (CZ_AUCTION_BUY). /// 024f <auction id>.L <money>.L void clif_parse_Auction_bid(int fd, struct map_session_data *sd) @@ -14992,7 +15141,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) } } - +void clif_parse_Auction_search(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Auction Search (CZ_AUCTION_ITEM_SEARCH). /// 0251 <search type>.W <auction id>.L <search text>.24B <page number>.W /// search type: @@ -15017,7 +15166,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page); } - +void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Requests list of own currently active bids or auctions (CZ_AUCTION_REQ_MY_INFO). /// 025c <type>.W /// type: @@ -15035,7 +15184,6 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) intif->Auction_requestlist(sd->status.char_id, type, 0, "", 1); } - /// CASH/POINT SHOP /// @@ -15102,9 +15250,11 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { /// For error return codes see enum cashshop_error@clif.h void clif_cashshop_ack(struct map_session_data* sd, int error) { struct npc_data *nd; - int fd = sd->fd; + int fd; int currency[2] = { 0,0 }; + nullpo_retv(sd); + fd = sd->fd; if( (nd = map->id2nd(sd->npc_shopid)) && nd->subtype == SCRIPT ) { npc->trader_count_funds(nd,sd); currency[0] = npc->trader_funds[0]; @@ -15126,7 +15276,7 @@ void clif_cashshop_ack(struct map_session_data* sd, int error) { WFIFOSET(fd, packet_len(0x289)); } - +void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to buy item(s) from cash shop (CZ_PC_BUY_CASH_POINT_ITEM). /// 0288 <name id>.W <amount>.W /// 0288 <name id>.W <amount>.W <kafra points>.L (PACKETVER >= 20070711) @@ -15134,7 +15284,6 @@ void clif_cashshop_ack(struct map_session_data* sd, int error) { 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 || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) fail = 1; @@ -15162,7 +15311,6 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) clif->cashshop_ack(sd,fail); } - /// Adoption System /// @@ -15174,20 +15322,24 @@ 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; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,6); WFIFOW(fd,0) = 0x216; WFIFOL(fd,2) = type; WFIFOSET(fd,6); } - /// Adoption confirmation (ZC_REQ_BABY). /// 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; + nullpo_retv(sd); + nullpo_retv(src); + fd = sd->fd; WFIFOHEAD(fd,34); WFIFOW(fd,0) = 0x1f6; WFIFOL(fd,2) = src->status.account_id; @@ -15196,7 +15348,7 @@ void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *sr WFIFOSET(fd,34); } - +void clif_parse_Adopt_request(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to adopt a player (CZ_REQ_JOIN_BABY). /// 01f9 <account id>.L void clif_parse_Adopt_request(int fd, struct map_session_data *sd) { @@ -15208,7 +15360,7 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd) { } } - +void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to adopt confirmation (CZ_JOIN_BABY). /// 01f7 <account id>.L <char id>.L <answer>.L /// answer: @@ -15236,7 +15388,6 @@ void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) { pc->adoption(p1_sd, p2_sd, sd); } - /// Convex Mirror (ZC_BOSS_INFO). /// 0293 <infoType>.B <x>.L <y>.L <minHours>.W <minMinutes>.W <maxHours>.W <maxMinutes>.W <monster name>.51B /// infoType: @@ -15278,7 +15429,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag) WFIFOSET(fd,70); } - +void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Requesting equip of a player (CZ_EQUIPWIN_MICROSCOPE). /// 02d6 <account id>.L void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) { @@ -15291,10 +15442,10 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) { if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) ) clif->viewequip_ack(sd, tsd); else - clif_viewequip_fail(sd); + clif->msgtable(sd, MSG_EQUIP_NOT_PUBLIC); } - +void clif_parse_EquipTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to change equip window tick (CZ_CONFIG). /// 02d8 <type>.L <value>.L /// type: @@ -15309,6 +15460,7 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) clif->equiptickack(sd, flag); } +void clif_parse_PartyTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to change party invitation tick. /// value: /// 0 = disabled @@ -15331,12 +15483,16 @@ void clif_quest_send_list(struct map_session_data *sd) int i; #if PACKETVER >= 20141022 int info_len = 15; - int len = sd->avail_quests*info_len+8; + int len; + nullpo_retv(sd); + len = sd->avail_quests*info_len+8; WFIFOHEAD(fd,len); WFIFOW(fd, 0) = 0x97a; #else int info_len = 5; - int len = sd->avail_quests*info_len+8; + int len; + nullpo_retv(sd); + len = sd->avail_quests*info_len+8; WFIFOHEAD(fd,len); WFIFOW(fd, 0) = 0x2b1; #endif @@ -15355,20 +15511,20 @@ void clif_quest_send_list(struct map_session_data *sd) WFIFOW(fd, i*info_len+21) = qi->objectives_count; #endif } - 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; + int len; struct mob_db *monster; + nullpo_retv(sd); + len = sd->avail_quests*104+8; WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x2b2; WFIFOW(fd, 2) = len; @@ -15392,15 +15548,18 @@ void clif_quest_send_mission(struct map_session_data *sd) 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 fd = sd->fd; + int fd; int i; - struct quest_db *qi = quest->db(qd->quest_id); + struct quest_db *qi; + nullpo_retv(sd); + nullpo_retv(qd); + fd = sd->fd; + qi = quest->db(qd->quest_id); WFIFOHEAD(fd, packet_len(0x2b3)); WFIFOW(fd, 0) = 0x2b3; WFIFOL(fd, 2) = qd->quest_id; @@ -15420,27 +15579,33 @@ void clif_quest_add(struct map_session_data *sd, struct quest *qd) 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; 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 fd = sd->fd; + int fd; int i; - struct quest_db *qi = quest->db(qd->quest_id); - int len = qi->objectives_count*12+6; + struct quest_db *qi; + int len; + + nullpo_retv(sd); + nullpo_retv(qd); + fd = sd->fd; + qi = quest->db(qd->quest_id); + len = qi->objectives_count * 12 + 6; WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x2b5; @@ -15457,19 +15622,20 @@ void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd) WFIFOSET(fd, len); } - +void clif_parse_questStateAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// 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) { 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x2b7)); WFIFOW(fd, 0) = 0x2b7; WFIFOL(fd, 2) = quest_id; @@ -15477,7 +15643,6 @@ void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool ac WFIFOSET(fd, packet_len(0x2b7)); } - /// Notification about an NPC's quest state (ZC_QUEST_NOTIFY_EFFECT). /// 0446 <npc id>.L <x>.W <y>.W <effect>.W <type>.W /// effect: @@ -15492,8 +15657,11 @@ 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; + int fd; + nullpo_retv(sd); + nullpo_retv(bl); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x446)); WFIFOW(fd, 0) = 0x446; WFIFOL(fd, 2) = bl->id; @@ -15505,7 +15673,6 @@ void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, s #endif } - /// Mercenary System /// @@ -15573,7 +15740,6 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) { WFIFOSET(fd,packet_len(0x2a2)); } - /// Mercenary base status data (ZC_MER_INIT). /// 029b <id>.L <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W /// <name>.24B <level>.W <hp>.L <maxhp>.L <sp>.L <maxsp>.L <expire time>.L <faith>.W @@ -15632,7 +15798,6 @@ void clif_mercenary_info(struct map_session_data *sd) { WFIFOSET(fd,packet_len(0x29b)); } - /// Mercenary skill tree (ZC_MER_SKILLINFO_LIST). /// 029d <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradeable>.B }* void clif_mercenary_skillblock(struct map_session_data *sd) @@ -15654,8 +15819,13 @@ void clif_mercenary_skillblock(struct map_session_data *sd) 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); + if ( 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); + } else { + WFIFOW(fd, len + 8) = 0; + WFIFOW(fd, len + 10) = 0; + } safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; @@ -15665,7 +15835,7 @@ void clif_mercenary_skillblock(struct map_session_data *sd) WFIFOSET(fd,len); } - +void clif_parse_mercenary_action(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to invoke a mercenary menu action (CZ_MER_COMMAND). /// 029f <command>.B /// 1 = mercenary information @@ -15680,7 +15850,6 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd) mercenary->delete(sd->md, 2); } - /// Mercenary Message /// message: /// 0 = Mercenary soldier's duty hour is over. @@ -15689,10 +15858,9 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd) /// 3 = Your mercenary soldier has ran away. void clif_mercenary_message(struct map_session_data* sd, int message) { - clif->msg(sd, 1266 + message); + clif->msgtable(sd, MSG_MERCENARY_EXPIRED + 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) @@ -15704,7 +15872,6 @@ void clif_rental_time(int fd, int nameid, int 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) @@ -15716,7 +15883,6 @@ void clif_rental_expired(int fd, int index, int nameid) WFIFOSET(fd,packet_len(0x299)); } - /// Book Reading (ZC_READ_BOOK). /// 0294 <book id>.L <page>.L void clif_readbook(int fd, int book_id, int page) @@ -15728,7 +15894,6 @@ void clif_readbook(int fd, int book_id, int page) WFIFOSET(fd,packet_len(0x294)); } - /// Battlegrounds /// @@ -15758,7 +15923,6 @@ void clif_bg_hp(struct map_session_data *sd) clif->send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); } - /// Updates the position of a camp member on the minimap (ZC_BATTLEFIELD_NOTIFY_POSITION). /// 02df <account id>.L <name>.24B <class>.W <x>.W <y>.W void clif_bg_xy(struct map_session_data *sd) @@ -15791,14 +15955,16 @@ void clif_bg_xy_remove(struct map_session_data *sd) clif->send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); } - /// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT). /// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len) { struct map_session_data *sd; unsigned char *buf; - + + nullpo_retv(bgd); + nullpo_retv(name); + nullpo_retv(mes); if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL ) return; @@ -15814,7 +15980,7 @@ void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name aFree(buf); } - +void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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) @@ -15846,7 +16012,6 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) bg->send_message(sd, text, textlen); } - /// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT). /// 02de <camp A points>.W <camp B points>.W void clif_bg_updatescore(int16 m) { @@ -15875,7 +16040,6 @@ void clif_bg_updatescore_single(struct map_session_data *sd) { WFIFOSET(fd,packet_len(0x2de)); } - /// Battleground camp belong-information (ZC_BATTLEFIELD_NOTIFY_CAMPINFO). /// 02dd <account id>.L <name>.24B <camp>.W void clif_sendbgemblem_area(struct map_session_data *sd) @@ -15901,7 +16065,6 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd) WFIFOSET(fd,packet_len(0x2dd)); } - /// Custom Fonts (ZC_NOTIFY_FONT). /// 02ef <account_id>.L <font id>.W void clif_font(struct map_session_data *sd) @@ -15916,7 +16079,6 @@ void clif_font(struct map_session_data *sd) #endif } - /*========================================== * Instancing Window *------------------------------------------*/ @@ -16025,15 +16187,17 @@ void clif_instance_leave(int fd) 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) { #if PACKETVER >= 20071002 unsigned char buf[22]; - struct item_data* id = itemdb->search(item_data->nameid); + struct item_data* id; + nullpo_retv(sd); + nullpo_retv(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; @@ -16047,7 +16211,6 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat #endif } - /// Display gained exp (ZC_NOTIFY_EXP). /// 07f6 <account id>.L <amount>.L <var id>.W <exp type>.W /// var id: @@ -16071,7 +16234,6 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b WFIFOSET(fd,packet_len(0x7f6)); } - /// Displays digital clock digits on top of the screen (ZC_SHOWDIGIT). /// type: /// 0 = Displays 'value' for 5 seconds. @@ -16082,6 +16244,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b /// 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) { + nullpo_retv(sd); WFIFOHEAD(sd->fd, packet_len(0x1b1)); WFIFOW(sd->fd,0) = 0x1b1; WFIFOB(sd->fd,2) = type; @@ -16089,7 +16252,7 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value) WFIFOSET(sd->fd, packet_len(0x1b1)); } - +void clif_parse_LessEffect(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Notification of the state of client command /effect (CZ_LESSEFFECT). /// 021d <state>.L /// state: @@ -16109,6 +16272,7 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd) sd->state.lesseffect = ( isLess != 0 ); } +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// 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; @@ -16197,7 +16361,6 @@ void clif_elemental_info(struct map_session_data *sd) { WFIFOSET(fd,22); } - /// Buying Store System /// @@ -16205,15 +16368,17 @@ void clif_elemental_info(struct map_session_data *sd) { /// 0810 <slots>.B void clif_buyingstore_open(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x810)); WFIFOW(fd,0) = 0x810; WFIFOB(fd,2) = sd->buyingstore.slots; WFIFOSET(fd,packet_len(0x810)); } - +void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to create a buying store (CZ_REQ_OPEN_BUYING_STORE). /// 0811 <packet len>.W <limit zeny>.L <result>.B <store name>.80B { <name id>.W <amount>.W <price>.L }* /// result: @@ -16255,7 +16420,6 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { buyingstore->create(sd, zenylimit, result, storename, itemlist, count); } - /// Notification, that the requested buying store could not be created (ZC_FAILED_OPEN_BUYING_STORE_TO_BUYER). /// 0812 <result>.W <total weight>.L /// result: @@ -16265,8 +16429,10 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { /// ? = nothing void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x812)); WFIFOW(fd,0) = 0x812; WFIFOW(fd,2) = result; @@ -16274,14 +16440,15 @@ void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short re 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; + int fd; unsigned int i; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,12+sd->buyingstore.slots*9); WFIFOW(fd,0) = 0x813; WFIFOW(fd,2) = 12+sd->buyingstore.slots*9; @@ -16299,13 +16466,13 @@ void clif_buyingstore_myitemlist(struct map_session_data* sd) 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) { uint8 buf[86]; + nullpo_retv(sd); WBUFW(buf,0) = 0x814; WBUFL(buf,2) = sd->bl.id; memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); @@ -16314,8 +16481,10 @@ 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x814)); WFIFOW(fd,0) = 0x814; WFIFOL(fd,2) = pl_sd->bl.id; @@ -16323,20 +16492,20 @@ void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_sessi WFIFOSET(fd,packet_len(0x814)); } - +void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE). /// 0815 void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* 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) { uint8 buf[6]; + nullpo_retv(sd); WBUFW(buf,0) = 0x816; WBUFL(buf,2) = sd->bl.id; @@ -16344,15 +16513,17 @@ 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + nullpo_retv(pl_sd); + fd = sd->fd; 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 void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) @@ -16364,14 +16535,16 @@ void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) 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; + int fd; unsigned int i; + nullpo_retv(sd); + nullpo_retv(pl_sd); + fd = sd->fd; WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9); WFIFOW(fd,0) = 0x818; WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9; @@ -16390,7 +16563,7 @@ void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_d WFIFOSET(fd,WFIFOW(fd,2)); } - +void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (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 }* void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { @@ -16425,7 +16598,6 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { buyingstore->trade(sd, account_id, buyer_id, itemlist, count); } - /// Notifies the buyer, that the buying store has been closed due to a post-trade condition (ZC_FAILED_TRADE_BUYING_STORE_TO_BUYER). /// 081a <result>.W /// result: @@ -16434,21 +16606,24 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { /// ? = nothing void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x81b)); WFIFOW(fd,0) = 0x81b; WFIFOW(fd,2) = nameid; @@ -16457,7 +16632,6 @@ void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short na WFIFOSET(fd,packet_len(0x81b)); } - /// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE). /// 081c <index>.W <amount>.W <price>.L /// message: @@ -16466,8 +16640,10 @@ void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short na /// 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x81c)); WFIFOW(fd,0) = 0x81c; WFIFOW(fd,2) = index+2; @@ -16476,7 +16652,6 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi WFIFOSET(fd,packet_len(0x81c)); } - /// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER). /// 0824 <result>.W <name id>.W /// result: @@ -16486,8 +16661,10 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi /// ? = nothing void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x824)); WFIFOW(fd,0) = 0x824; WFIFOW(fd,2) = result; @@ -16495,7 +16672,7 @@ void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short res WFIFOSET(fd,packet_len(0x824)); } - +void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Search Store Info System /// @@ -16551,7 +16728,6 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { searchstore->query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); } - /// Results for a store search request (ZC_SEARCH_STORE_INFO_ACK). /// 0836 <packet len>.W <is first page>.B <is next page>.B <remaining uses>.B { <store id>.L <account id>.L <shop name>.80B <nameid>.W <item type>.B <price>.L <amount>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* /// is first page: @@ -16563,9 +16739,11 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { void clif_search_store_info_ack(struct map_session_data* sd) { const unsigned int blocksize = MESSAGE_SIZE+26; - int fd = sd->fd; + int fd; unsigned int i, start, end; + nullpo_retv(sd); + fd = sd->fd; start = sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE; end = min(sd->searchstore.count, start+SEARCHSTORE_RESULTS_PER_PAGE); @@ -16601,7 +16779,6 @@ void clif_search_store_info_ack(struct map_session_data* sd) WFIFOSET(fd,WFIFOW(fd,2)); } - /// Notification of failure when searching for stores (ZC_SEARCH_STORE_INFO_FAILED). /// 0837 <reason>.B /// reason: @@ -16612,15 +16789,17 @@ void clif_search_store_info_ack(struct map_session_data* sd) /// 4 = "No sale (purchase) information available." (0x705) void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x837)); WFIFOW(fd,0) = 0x837; WFIFOB(fd,2) = reason; WFIFOSET(fd,packet_len(0x837)); } - +void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to display next page of results (CZ_SEARCH_STORE_INFO_NEXT_PAGE). /// 0838 void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) @@ -16628,7 +16807,6 @@ void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) searchstore->next(sd); } - /// Opens the search store window (ZC_OPEN_SEARCH_STORE_INFO). /// 083a <type>.W <remaining uses>.B /// type: @@ -16636,8 +16814,10 @@ void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) /// 1 = Search Stores (Cash), asks for confirmation, when clicking a store void clif_open_search_store_info(struct map_session_data* sd) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x83a)); WFIFOW(fd,0) = 0x83a; WFIFOW(fd,2) = sd->searchstore.effect; @@ -16647,7 +16827,7 @@ void clif_open_search_store_info(struct map_session_data* sd) WFIFOSET(fd,packet_len(0x83a)); } - +void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to close the store search window (CZ_CLOSE_SEARCH_STORE_INFO). /// 083b void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) @@ -16655,7 +16835,7 @@ void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) searchstore->close(sd); } - +void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /// Request to invoke catalog effect on a store from search results (CZ_SSILIST_ITEM_CLICK). /// 083c <account id>.L <store id>.L <nameid>.W void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) @@ -16671,13 +16851,14 @@ void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd 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) { - int fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x83d)); WFIFOW(fd,0) = 0x83d; WFIFOW(fd,2) = x; @@ -16685,7 +16866,6 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor 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; @@ -16716,18 +16896,17 @@ int clif_elementalconverter_list(struct map_session_data *sd) { 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) + if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,23, 1) ){ + if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0) WFIFOW(fd,c*2+ 4)= view; else - WFIFOW(fd,c*2+ 4)= skill->produce_db[i].nameid; + WFIFOW(fd,c*2+ 4)= skill->dbs->produce_db[i].nameid; c++; } } @@ -16747,6 +16926,7 @@ void clif_millenniumshield(struct block_list *bl, short shields ) { #if PACKETVER >= 20081217 unsigned char buf[10]; + nullpo_retv(bl); WBUFW(buf,0) = 0x440; WBUFL(buf,2) = bl->id; WBUFW(buf,6) = shields; @@ -16925,26 +17105,8 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin return 1; } -// 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)); -} -// msgstringtable.txt -// 0x7e2 <line>.W <value>.L -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)); -#endif -} +void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /*========================================== * used by SC_AUTOSHADOWSPELL * RFIFOL(fd,2) - flag (currently not used) @@ -16964,6 +17126,7 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { clif_menuskill_clear(sd); } + /*========================================== * Kagerou/Oboro amulet spirit *------------------------------------------*/ @@ -16979,6 +17142,8 @@ void clif_charm(struct map_session_data *sd) WBUFW(buf,8) = sd->charm_count; clif->send(buf,packet_len(0x08cf),&sd->bl,AREA); } + +void clif_parse_MoveItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] /// 0907 <index>.W /// @@ -17010,6 +17175,7 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { clif->favorite_item(sd, index); #endif } + /* [Ind/Hercules] */ void clif_cashshop_db(void) { config_t cashshop_conf; @@ -17061,7 +17227,6 @@ void clif_cashshop_db(void) { } } - RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); @@ -17072,15 +17237,17 @@ void clif_cashshop_db(void) { } } - libconfig->destroy(&cashshop_conf); } + libconfig->destroy(&cashshop_conf); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); } /// 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; + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd,packet_len(0x908)); WFIFOW(fd,0) = 0x908; WFIFOW(fd,2) = index+2; @@ -17091,6 +17258,7 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) { void clif_snap( struct block_list *bl, short x, short y ) { unsigned char buf[10]; + nullpo_retv(bl); WBUFW(buf,0) = 0x8d2; WBUFL(buf,2) = bl->id; WBUFW(buf,6) = x; @@ -17102,21 +17270,26 @@ void clif_snap( struct block_list *bl, short x, short y ) { void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) { struct packet_monster_hp p; + nullpo_retv(md); + nullpo_retv(sd); p.PacketType = monsterhpType; p.GID = md->bl.id; p.HP = md->status.hp; p.MaxHP = md->status.max_hp; - clif->send(&p,sizeof(p),&sd->bl,SELF); + clif->send(&p, sizeof(p), &sd->bl, SELF); } + /* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd) { return; } + +void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { - if( map->list[sd->bl.m].flag.nocashshop ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map + if (map->list[sd->bl.m].flag.nocashshop) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map return; } @@ -17127,10 +17300,12 @@ void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { WFIFOSET(fd, 10); } +void clif_parse_CashShopClose(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_CashShopClose(int fd, struct map_session_data *sd) { /* TODO apply some state tracking */ } +void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { int i, j = 0; @@ -17152,12 +17327,14 @@ void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { WFIFOSET(fd, 8 + ( clif->cs.item_count[i] * 6 )); } } + +void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { unsigned short limit = RFIFOW(fd, 4), i, j; unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing) - if( map->list[sd->bl.m].flag.nocashshop ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map + if (map->list[sd->bl.m].flag.nocashshop) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map return; } @@ -17239,6 +17416,8 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { } } + +void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /* [Ind/Hercules] */ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { short tab = RFIFOW(fd, 2); @@ -17304,6 +17483,7 @@ void clif_status_change2(struct block_list *bl, int tid, enum send_target target } void clif_partytickack(struct map_session_data* sd, bool flag) { + nullpo_retv(sd); WFIFOHEAD(sd->fd, packet_len(0x2c9)); WFIFOW(sd->fd, 0) = 0x2c9; @@ -17336,6 +17516,8 @@ void clif_ShowScript(struct block_list* bl, const char* message) { void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) { struct packet_status_change_end p; + nullpo_retv(bl); + if( bl->type == BL_PC && !((TBL_PC*)bl)->state.active ) return; @@ -17356,6 +17538,7 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK default: { struct packet_bgqueue_ack p; + nullpo_retv(sd); p.PacketType = bgqueue_ackType; p.type = response; safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name)); @@ -17366,10 +17549,10 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK } } - void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name) { struct packet_bgqueue_notice_delete p; + nullpo_retv(sd); p.PacketType = bgqueue_notice_deleteType; p.type = response; safestrncpy(p.bg_name, name, sizeof(p.bg_name)); @@ -17377,6 +17560,7 @@ void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_ clif->send(&p,sizeof(p), &sd->bl, SELF); } +void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) { struct packet_bgqueue_register *p = P2PTR(fd); struct bg_arena *arena = NULL; @@ -17403,6 +17587,8 @@ void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) { void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_id, int position) { struct packet_bgqueue_update_info p; + nullpo_retv(sd); + Assert_retv(arena_id < bg->arenas); p.PacketType = bgqueue_updateinfoType; safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name)); p.position = position; @@ -17412,15 +17598,18 @@ void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_i clif->send(&p,sizeof(p), &sd->bl, SELF); } +void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) { struct packet_bgqueue_checkstate *p = P2PTR(fd); + nullpo_retv(sd); if ( sd->bg_queue.arena && sd->bg_queue.type ) { clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id)); } else clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name); } +void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { struct packet_bgqueue_revoke_req *p = P2PTR(fd); @@ -17430,6 +17619,7 @@ void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name); } +void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) { struct packet_bgqueue_battlebegin_ack *p = P2PTR(fd); struct bg_arena *arena; @@ -17446,6 +17636,7 @@ void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) { void clif_bgqueue_joined(struct map_session_data *sd, int pos) { struct packet_bgqueue_notify_entry p; + nullpo_retv(sd); p.PacketType = bgqueue_notify_entryType; safestrncpy(p.name,sd->status.name,sizeof(p.name)); p.position = pos; @@ -17462,6 +17653,8 @@ void clif_bgqueue_pcleft(struct map_session_data *sd) { void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_id, enum send_target target) { struct packet_bgqueue_battlebegins p; + nullpo_retv(sd); + Assert_retv(arena_id < bg->arenas); p.PacketType = bgqueue_battlebeginsType; safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name)); safestrncpy(p.game_name, bg->arena[arena_id]->name, sizeof(p.game_name)); @@ -17472,15 +17665,18 @@ void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_ void clif_scriptclear(struct map_session_data *sd, int npcid) { struct packet_script_clear p; + nullpo_retv(sd); p.PacketType = script_clearType; p.NpcID = npcid; clif->send(&p,sizeof(p), &sd->bl, SELF); } + /* Made Possible Thanks to Yommy! */ void clif_package_item_announce(struct map_session_data *sd, unsigned short nameid, unsigned short containerid) { struct packet_package_item_announce p; + nullpo_retv(sd); p.PacketType = package_item_announceType; p.PacketLength = 11+NAME_LENGTH; p.type = 0x0; @@ -17492,10 +17688,12 @@ void clif_package_item_announce(struct map_session_data *sd, unsigned short name clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT); } + /* Made Possible Thanks to Yommy! */ void clif_item_drop_announce(struct map_session_data *sd, unsigned short nameid, char *monsterName) { struct packet_item_drop_announce p; + nullpo_retv(sd); p.PacketType = item_drop_announceType; p.PacketLength = sizeof(p); p.type = 0x1; @@ -17507,6 +17705,7 @@ void clif_item_drop_announce(struct map_session_data *sd, unsigned short nameid, clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT); } + /* [Ind/Hercules] special thanks to Yommy~! */ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) { #if PACKETVER >= 20120604 @@ -17516,6 +17715,8 @@ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) { #endif int i, count = 0; + nullpo_retv(cd); + WFIFOHEAD(fd,4+(offset*cd->cursor)); #if PACKETVER >= 20120604 @@ -17541,6 +17742,7 @@ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) { WFIFOSET(fd,4+(offset*count)); } + /* [Ind/Hercules] - Data Thanks to Yommy * - ADDITEM_TO_CART_FAIL_WEIGHT = 0x0 * - ADDITEM_TO_CART_FAIL_COUNT = 0x1 @@ -17548,18 +17750,21 @@ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) { void clif_cart_additem_ack(struct map_session_data *sd, int flag) { struct packet_cart_additem_ack p; + nullpo_retv(sd); p.PacketType = cart_additem_ackType; p.result = (char)flag; clif->send(&p,sizeof(p), &sd->bl, SELF); } + +void clif_parse_BankDeposit(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /* Bank System [Yommy/Hercules] */ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { struct packet_banking_deposit_req *p = P2PTR(fd); int money; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17568,12 +17773,13 @@ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { pc->bank_deposit(sd,money); } +void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { struct packet_banking_withdraw_req *p = P2PTR(fd); int money; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17582,11 +17788,12 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { pc->bank_withdraw(sd,money); } +void clif_parse_BankCheck(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_BankCheck(int fd, struct map_session_data* sd) { struct packet_banking_check p; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17597,10 +17804,12 @@ void clif_parse_BankCheck(int fd, struct map_session_data* sd) { clif->send(&p,sizeof(p), &sd->bl, SELF); } +void clif_parse_BankOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_BankOpen(int fd, struct map_session_data* sd) { return; } +void clif_parse_BankClose(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_BankClose(int fd, struct map_session_data* sd) { return; } @@ -17608,6 +17817,7 @@ void clif_parse_BankClose(int fd, struct map_session_data* sd) { void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) { struct packet_banking_deposit_ack p; + nullpo_retv(sd); p.PacketType = banking_deposit_ackType; p.Balance = sd->status.zeny;/* how much zeny char has after operation */ p.Money = (int64)sd->status.bank_vault;/* money in the bank */ @@ -17615,9 +17825,11 @@ void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK r clif->send(&p,sizeof(p), &sd->bl, SELF); } + void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) { struct packet_banking_withdraw_ack p; + nullpo_retv(sd); p.PacketType = banking_withdraw_ackType; p.Balance = sd->status.zeny;/* how much zeny char has after operation */ p.Money = (int64)sd->status.bank_vault;/* money in the bank */ @@ -17625,9 +17837,11 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK clif->send(&p,sizeof(p), &sd->bl, SELF); } + /* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */ /* currently mimicing */ void clif_show_modifiers (struct map_session_data *sd) { + nullpo_retv(sd); if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) { char output[128]; @@ -17642,12 +17856,14 @@ void clif_show_modifiers (struct map_session_data *sd) { void clif_notify_bounditem(struct map_session_data *sd, unsigned short index) { struct packet_notify_bounditem p; + nullpo_retv(sd); p.PacketType = notify_bounditemType; p.index = index+2; clif->send(&p,sizeof(p), &sd->bl, SELF); } +void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /** * Parses the (GM) right click option 'remove all equipment' **/ @@ -17661,9 +17877,10 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) { for( i = 0; i < EQI_MAX; i++ ) { if( tsd->equip_index[ i ] >= 0 ) - pc->unequipitem( tsd , tsd->equip_index[ i ] , 2 ); + pc->unequipitem(tsd, tsd->equip_index[i], PCUNEQUIPITEM_FORCE); } } + /** * clif_delay_damage timer, sends the stored data and clears the memory afterwards **/ @@ -17676,6 +17893,7 @@ int clif_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) { return 0; } + /** * Delays sending a damage packet in order to avoid the visual display to overlap * @@ -17707,7 +17925,7 @@ int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst if(sc && sc->count && sc->data[SC_ILLUSION]) { if(in_damage) in_damage = in_damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; } - + #if PACKETVER < 20071113 damage = (short)min(in_damage,INT16_MAX); #else @@ -17748,22 +17966,29 @@ int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst return clif->calc_walkdelay(dst,ddelay,type,damage,div); } + +void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /* Thanks to Yommy */ void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) { /* TODO track the state <3~ */ sd->npc_shopid = 0; } + /* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) { #if PACKETVER >= 20131223 - struct npc_item_list *shop = nd->u.scr.shop->item; - unsigned short shop_size = nd->u.scr.shop->items, i, c; + struct npc_item_list *shop; + unsigned short shop_size, i, c; + nullpo_retv(sd); + nullpo_retv(nd); + shop = nd->u.scr.shop->item; + shop_size = nd->u.scr.shop->items; npcmarket_open.PacketType = npcmarketopenType; for(i = 0, c = 0; i < shop_size; i++) { struct item_data *id = NULL; - if( shop[i].nameid && (id = itemdb->exists(shop[i].nameid)) ) { + if (shop[i].nameid && (id = itemdb->exists(shop[i].nameid)) != NULL) { npcmarket_open.list[c].nameid = shop[i].nameid; npcmarket_open.list[c].price = shop[i].value; npcmarket_open.list[c].qty = shop[i].qty; @@ -17778,14 +18003,19 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) { clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF); #endif } + +void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) { /* TODO track the state <3~ */ sd->npc_shopid = 0; } + void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) { #if PACKETVER >= 20131223 unsigned short c = 0; + nullpo_retv(sd); + nullpo_retv(req); npcmarket_result.PacketType = npcmarketresultackType; npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */ @@ -17818,6 +18048,8 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF); #endif } + +void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { #if PACKETVER >= 20131223 struct packet_npc_market_purchase *p = P2PTR(fd); @@ -17825,27 +18057,29 @@ void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p)); #endif } - + void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid) { struct packet_party_leader_changed p; - + + nullpo_retv(sd); p.PacketType = partyleaderchangedType; - + p.prev_leader_aid = prev_leader_aid; p.new_leader_aid = new_leader_aid; - + clif->send(&p,sizeof(p),&sd->bl,PARTY); } +void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /* Roulette System [Yommy/Hercules] */ void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) { struct packet_roulette_open_ack p; - + if( !battle_config.feature_roulette ) { clif->message(fd,"Roulette is disabled"); return; } - + p.PacketType = 0xa1a; p.Result = 0; p.Serial = 0; @@ -17858,6 +18092,8 @@ void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) { clif->send(&p,sizeof(p), &sd->bl, SELF); } + +void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) { struct packet_roulette_info_ack p; unsigned short i, j, count = 0; @@ -17866,11 +18102,11 @@ void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) { clif->message(fd,"Roulette is disabled"); return; } - + p.PacketType = rouletteinfoackType; p.PacketLength = 8 + (42 * 8); p.RouletteSerial = 1; - + for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { for(j = 0; j < MAX_ROULETTE_COLUMNS-i; j++) { p.ItemInfo[count].Row = i; @@ -17880,45 +18116,44 @@ void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) { count++; } } - clif->send(&p,sizeof(p), &sd->bl, SELF); return; } + +void clif_parse_RouletteClose(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_RouletteClose(int fd, struct map_session_data* sd) { - if( !battle_config.feature_roulette ) { clif->message(fd,"Roulette is disabled"); return; } - - + /** What do we need this for? (other than state tracking), game client closes the window without our response. **/ - //ShowDebug("clif_parse_RouletteClose\n"); - + return; } + +void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { unsigned char result = GENERATE_ROULETTE_SUCCESS; short stage = sd->roulette.stage; - + if( !battle_config.feature_roulette ) { clif->message(fd,"Roulette is disabled"); return; } - + if( sd->roulette.stage >= MAX_ROULETTE_LEVEL ) stage = sd->roulette.stage = 0; - + if( stage == 0 ) { if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) <= 0 && pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) < 10 && pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) < 10 ) result = GENERATE_ROULETTE_NO_ENOUGH_POINT; } - + if( result == GENERATE_ROULETTE_SUCCESS ) { - if( stage == 0 ) { if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) > 0 ) { pc_setglobalreg(sd, script->add_str("TmpRouletteBronze"), pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) - 1); @@ -17930,7 +18165,6 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { stage = sd->roulette.stage = 4; } } - sd->roulette.prizeStage = stage; sd->roulette.prizeIdx = rnd()%clif->rd.items[stage]; if( sd->roulette.prizeIdx == 0 ) { @@ -17939,37 +18173,39 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { it.nameid = clif->rd.nameid[stage][0]; it.identify = 1; - + pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_OTHER);/** TODO maybe a new log type for roulette items? **/ - + sd->roulette.stage = 0; result = GENERATE_ROULETTE_LOSING; } else sd->roulette.claimPrize = true; } - + clif->roulette_generate_ack(sd,result,stage,sd->roulette.prizeIdx,0); if( result == GENERATE_ROULETTE_SUCCESS ) sd->roulette.stage++; } + +void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /** * Request to cash in! **/ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { struct packet_roulette_itemrecv_ack p; - + if( !battle_config.feature_roulette ) { clif->message(fd,"Roulette is disabled"); return; } - + p.PacketType = roulettercvitemackType; p.AdditionItemID = 0;/** TODO **/ - + if( sd->roulette.claimPrize ) { struct item it; memset(&it, 0, sizeof(it)); - + it.nameid = clif->rd.nameid[sd->roulette.prizeStage][sd->roulette.prizeIdx]; it.identify = 1; @@ -17996,7 +18232,7 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { } } else p.Result = RECV_ITEM_FAILED; - + clif->send(&p,sizeof(p), &sd->bl, SELF); return; } @@ -18006,39 +18242,38 @@ bool clif_parse_roulette_db(void) { config_setting_t *roulette = NULL, *levels = NULL; const char *config_filename = "db/roulette_db.conf"; // FIXME hardcoded name int i, j, item_count_t = 0; - + for( i = 0; i < MAX_ROULETTE_LEVEL; i++ ) { clif->rd.items[i] = 0; } - + if (libconfig->read_file(&roulette_conf, config_filename)) { ShowError("can't read %s\n", config_filename); return false; } - roulette = libconfig->lookup(&roulette_conf, "roulette"); - + if( roulette != NULL && (levels = libconfig->setting_get_elem(roulette, 0)) != NULL ) { for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { config_setting_t *level; char entry_name[10]; - + sprintf(entry_name,"level_%d",i+1); - + if( (level = libconfig->setting_get_member(levels, entry_name)) != NULL ) { int k, item_count = libconfig->setting_length(level); - + for(k = 0; k < item_count; k++) { config_setting_t *entry = libconfig->setting_get_elem(level,k); const char *name = config_setting_name(entry); int qty = libconfig->setting_get_int(entry); struct item_data * data = NULL; - + if( qty < 1 ) { ShowWarning("roulette_db: unsupported qty '%d' for entry named '%s' in category '%s'\n", qty, name, entry_name); continue; } - + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { if( !( data = itemdb->exists(atoi(name+2))) ) { ShowWarning("roulette_db: unknown item id '%s' in category '%s'\n", name+2, entry_name); @@ -18050,26 +18285,25 @@ bool clif_parse_roulette_db(void) { continue; } } - + j = clif->rd.items[i]; RECREATE(clif->rd.nameid[i],int,++clif->rd.items[i]); RECREATE(clif->rd.qty[i],int,clif->rd.items[i]); - + clif->rd.nameid[i][j] = data->nameid; clif->rd.qty[i][j] = qty; - + item_count_t++; } } } - - libconfig->destroy(&roulette_conf); } - + libconfig->destroy(&roulette_conf); + for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { int limit = MAX_ROULETTE_COLUMNS-i; if( clif->rd.items[i] == limit ) continue; - + if( clif->rd.items[i] > limit ) { ShowWarning("roulette_db: level %d has %d items, only %d supported, capping...\n",i+1,clif->rd.items[i],limit); clif->rd.items[i] = limit; @@ -18077,23 +18311,20 @@ bool clif_parse_roulette_db(void) { } /** this scenario = clif->rd.items[i] < limit **/ ShowWarning("roulette_db: level %d has %d items, %d are required. filling with apples\n",i+1,clif->rd.items[i],limit); - + clif->rd.items[i] = limit; RECREATE(clif->rd.nameid[i],int,clif->rd.items[i]); RECREATE(clif->rd.qty[i],int,clif->rd.items[i]); - for(j = 0; j < MAX_ROULETTE_COLUMNS-i; j++) { - if( clif->rd.qty[i][j] ) continue; - + if (clif->rd.qty[i][j]) + continue; clif->rd.nameid[i][j] = ITEMID_APPLE; clif->rd.qty[i][j] = 1; } } - - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); - + return true; } @@ -18103,6 +18334,7 @@ bool clif_parse_roulette_db(void) { void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) { struct packet_roulette_generate_ack p; + nullpo_retv(sd); p.PacketType = roulettgenerateackType; p.Result = result; p.Step = stage; @@ -18111,10 +18343,160 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul p.RemainBronze = pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")); p.RemainGold = pc_readglobalreg(sd, script->add_str("TmpRouletteGold")); p.RemainSilver = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")); - + clif->send(&p,sizeof(p), &sd->bl, SELF); } +/** + * Stackable items merger + */ +void clif_openmergeitem(int fd, struct map_session_data *sd) +{ + int i = 0, n = 0, j = 0; + struct merge_item merge_items[MAX_INVENTORY]; + struct merge_item *merge_items_[MAX_INVENTORY] = {0}; + + nullpo_retv(sd); + memset(&merge_items,'\0',sizeof(merge_items)); + + for (i = 0; i < MAX_INVENTORY; i++) { + struct item *item_data = &sd->status.inventory[i]; + + if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid)) + continue; + + merge_items[n].nameid = item_data->nameid; + merge_items[n].position = i + 2; + n++; + } + + qsort(merge_items,n,sizeof(struct merge_item),clif->comparemergeitem); + + for (i = 0, j = 0; i < n; i++) { + if (i > 0 && merge_items[i].nameid == merge_items[i-1].nameid) + { + merge_items_[j] = &merge_items[i]; + j++; + continue; + } + + if (i < n - 1 && merge_items[i].nameid == merge_items[i+1].nameid) + { + merge_items_[j] = &merge_items[i]; + j++; + continue; + } + } + + WFIFOHEAD(fd,2*j+4); + WFIFOW(fd,0) = 0x96d; + WFIFOW(fd,2) = 2*j+4; + for ( i = 0; i < j; i++ ) + WFIFOW(fd,i*2+4) = merge_items_[i]->position; + WFIFOSET(fd,2*j+4); +} + +int clif_comparemergeitem(const void *a, const void *b) +{ + const struct merge_item *a_ = a; + const struct merge_item *b_ = b; + + nullpo_ret(a); + nullpo_ret(b); + if (a_->nameid == b_->nameid) + return 0; + return a_->nameid > b_->nameid ? -1 : 1; +} + +void clif_ackmergeitems(int fd, struct map_session_data *sd) +{ + int i = 0, n = 0, length = 0, count = 0; + int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0}; + struct item item_data; + + nullpo_retv(sd); + length = (RFIFOW(fd,2) - 4)/2; + + if (length >= MAX_INVENTORY || length < 2) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_FAILD; + WFIFOSET(fd,7); + return; + } + + for (i = 0, n = 0; i < length; i++) { + int16 idx = RFIFOW(fd,i*2+4) - 2; + struct item *it = NULL; + + if (idx < 0 || idx >= MAX_INVENTORY) + continue; + + it = &sd->status.inventory[idx]; + + if (it->nameid == 0 || !itemdb->isstackable(it->nameid)) + continue; + + if (nameid == 0) + nameid = it->nameid; + + if (nameid != it->nameid) + continue; + + count += it->amount; + indexes[n] = idx; + amounts[n] = it->amount; + n++; + } + + if (n < 2 || count == 0) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_FAILD; + WFIFOSET(fd,7); + return; + } + + if (count > MAX_AMOUNT) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_MAXCOUNTFAILD; + WFIFOSET(fd,7); + return; + } + + for (i = 0; i < n; i++) + pc->delitem(sd,indexes[i],amounts[i],0,DELITEM_NORMAL,LOG_TYPE_NPC); + + memset(&item_data,'\0',sizeof(item_data)); + + item_data.nameid = nameid; + item_data.identify = 1; + item_data.unique_id = itemdb->unique_id(sd); + pc->additem(sd,&item_data,count,LOG_TYPE_NPC); + + ARR_FIND(0,MAX_INVENTORY,i,item_data.unique_id == sd->status.inventory[i].unique_id); + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = i+2; + WFIFOW(fd,4) = count; + WFIFOB(fd,6) = MERGEITEM_SUCCESS; + WFIFOSET(fd,7); +} + +void clif_cancelmergeitem (int fd, struct map_session_data *sd) +{ + //Track The merge item cancelation ? + return; +} + /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { if( sd ) { @@ -18122,11 +18504,13 @@ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { } return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF)); } + unsigned short clif_parse_cmd_normal( int fd, struct map_session_data *sd ) { unsigned short cmd = RFIFOW(fd,0); return cmd; } + unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) { unsigned short cmd = RFIFOW(fd,0); @@ -18134,6 +18518,7 @@ unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) { return cmd; } + unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) { unsigned short cmd = RFIFOW(fd,0); @@ -18164,13 +18549,13 @@ int clif_parse(int fd) { unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); // begin main client packet processing loop - sd = (TBL_PC *)session[fd]->session_data; + sd = (TBL_PC *)sockt->session[fd]->session_data; - if (session[fd]->flag.eof) { + if (sockt->session[fd]->flag.eof) { if (sd) { if (sd->state.autotrade) { //Disassociate character from the socket connection. - session[fd]->session_data = NULL; + sockt->session[fd]->session_data = NULL; sd->fd = 0; ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); } else @@ -18184,9 +18569,9 @@ int clif_parse(int fd) { map->quit(sd); } } else { - ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL)); + ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", sockt->ip2str(sockt->session[fd]->client_addr, NULL)); } - do_close(fd); + sockt->close(fd); return 0; } @@ -18215,7 +18600,7 @@ int clif_parse(int fd) { #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - set_eof(fd); + sockt->eof(fd); return 0; } @@ -18231,7 +18616,7 @@ int clif_parse(int fd) { #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - set_eof(fd); + sockt->eof(fd); return 0; } @@ -18335,14 +18720,13 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) va_end(va); } void packetdb_loaddb(void) { - memset(packet_db,0,sizeof(packet_db)); - - #define packet(id, size, ...) packetdb_addpacket((id), (size), ##__VA_ARGS__, 0xFFFF) - #define packetKeys(a,b,c) do { clif->cryptKey[0] = (a); clif->cryptKey[1] = (b); clif->cryptKey[2] = (c); } while(0) - #include "packets.h" /* load structure data */ - #undef packet - #undef packetKeys + +#define packet(id, size, ...) packetdb_addpacket((id), (size), ##__VA_ARGS__, 0xFFFF) +#define packetKeys(a,b,c) do { clif->cryptKey[0] = (a); clif->cryptKey[1] = (b); clif->cryptKey[2] = (c); } while(0) +#include "packets.h" /* load structure data */ +#undef packet +#undef packetKeys } void clif_bc_ready(void) { if( battle_config.display_status_timers ) @@ -18366,25 +18750,15 @@ void clif_bc_ready(void) { /*========================================== * *------------------------------------------*/ -int do_init_clif(bool minimal) { - const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" }; - int i; - +int do_init_clif(bool minimal) +{ if (minimal) return 0; - /** - * Setup Color Table (saves unnecessary load of strtoul on every call) - **/ - for(i = 0; i < COLOR_MAX; i++) { - color_table[i] = (unsigned int)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 - } - packetdb_loaddb(); - set_defaultparse(clif->parse); - if( make_listen_bind(clif->bind_ip,clif->map_port) == -1 ) { + sockt->set_defaultparse(clif->parse); + if (sockt->make_listen_bind(clif->bind_ip,clif->map_port) == -1) { ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",clif->map_port); exit(EXIT_FAILURE); } @@ -18412,7 +18786,7 @@ void do_final_clif(void) } aFree(clif->cs.data[i]); } - + for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { if( clif->rd.nameid[i] ) aFree(clif->rd.nameid[i]); @@ -18453,6 +18827,8 @@ void clif_defaults(void) { clif->dropitem = clif_dropitem; clif->delitem = clif_delitem; clif->takeitem = clif_takeitem; + clif->item_equip = clif_item_equip; + clif->item_normal = clif_item_normal; clif->arrowequip = clif_arrowequip; clif->arrow_fail = clif_arrow_fail; clif->use_card = clif_use_card; @@ -18463,7 +18839,7 @@ void clif_defaults(void) { clif->useitemack = clif_useitemack; clif->addcards = clif_addcards; clif->addcards2 = clif_addcards2; - clif->item_sub = clif_item_sub; + clif->item_sub = clif_item_sub; // look like unused clif->getareachar_item = clif_getareachar_item; clif->cart_additem_ack = clif_cart_additem_ack; clif->cashshop_load = clif_cashshop_db; @@ -18675,17 +19051,15 @@ void clif_defaults(void) { clif->disp_message = clif_disp_message; clif->broadcast = clif_broadcast; clif->broadcast2 = clif_broadcast2; + clif->messagecolor_self = clif_messagecolor_self; clif->messagecolor = clif_messagecolor; clif->disp_overhead = clif_disp_overhead; - clif->msg = clif_msg; - clif->msg_value = clif_msg_value; - clif->msg_skill = clif_msg_skill; + clif->msgtable_skill = clif_msgtable_skill; clif->msgtable = clif_msgtable; clif->msgtable_num = clif_msgtable_num; clif->message = clif_displaymessage; clif->messageln = clif_displaymessage2; clif->messages = clif_displaymessage_sprintf; - clif->colormes = clif_colormes; clif->process_message = clif_process_message; clif->wisexin = clif_wisexin; clif->wisall = clif_wisall; @@ -18699,7 +19073,7 @@ void clif_defaults(void) { clif->tradedeal_lock = clif_tradedeal_lock; clif->tradecancelled = clif_tradecancelled; clif->tradecompleted = clif_tradecompleted; - clif->tradeundo = clif_tradeundo; + clif->tradeundo = clif_tradeundo; // unused /* vending handling */ clif->openvendingreq = clif_openvendingreq; clif->showvendingboard = clif_showvendingboard; @@ -18916,6 +19290,12 @@ void clif_defaults(void) { /* */ clif->parse_roulette_db = clif_parse_roulette_db; clif->roulette_generate_ack = clif_roulette_generate_ack; + /* Merge Items */ + clif->openmergeitem = clif_openmergeitem; + clif->cancelmergeitem = clif_cancelmergeitem; + clif->comparemergeitem = clif_comparemergeitem; + clif->ackmergeitems = clif_ackmergeitems; + /*------------------------ *- Parse Incoming Packet *------------------------*/ @@ -19155,4 +19535,7 @@ void clif_defaults(void) { /* NPC Market */ clif->pNPCMarketClosed = clif_parse_NPCMarketClosed; clif->pNPCMarketPurchase = clif_parse_NPCMarketPurchase; + /* */ + clif->add_random_options = clif_add_random_options; + clif->pHotkeyRowShift = clif_parse_HotkeyRowShift; } diff --git a/src/map/clif.h b/src/map/clif.h index 5f1a2a899..f6f0d4fe7 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -5,40 +5,38 @@ #ifndef MAP_CLIF_H #define MAP_CLIF_H -#include <stdarg.h> +#include "map/map.h" +#include "map/packets_struct.h" +#include "common/hercules.h" +#include "common/mmo.h" -#include "map.h" -#include "packets_struct.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" +#include <stdarg.h> /** * Declarations **/ +struct battleground_data; +struct channel_data; +struct chat_data; +struct eri; +struct flooritem_data; +struct guild; +struct homun_data; struct item; struct item_data; -struct unit_data; struct map_session_data; -struct homun_data; struct mercenary_data; -struct pet_data; struct mob_data; struct npc_data; -struct chat_data; -struct flooritem_data; -struct skill_unit; -struct s_vending; -struct party; +struct party_booking_ad_info; struct party_data; -struct guild; -struct battleground_data; +struct pet_data; struct quest; -struct party_booking_ad_info; -struct view_data; -struct eri; +struct s_vending; struct skill_cd; -struct channel_data; +struct skill_unit; +struct unit_data; +struct view_data; /** * Defines @@ -47,9 +45,14 @@ struct channel_data; #define P2PTR(fd) RFIFO2PTR(fd) #define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0) #define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF ) -#define clif_viewequip_fail( sd ) clif->msg( (sd), 0x54d ); #define MAX_ROULETTE_LEVEL 7 /** client-defined value **/ #define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/ +#define RGB2BGR(c) ((c & 0x0000FF) << 16 | (c & 0x00FF00) | (c & 0xFF0000) >> 16) + +#define COLOR_RED 0xff0000U +#define COLOR_GREEN 0x00ff00U +#define COLOR_WHITE 0xffffffU +#define COLOR_DEFAULT COLOR_GREEN /** * Enumerations @@ -344,9 +347,30 @@ typedef enum useskill_fail_cause { // clif_skill_fail }useskill_fail_cause; enum clif_messages { - ITEM_CANT_OBTAIN_WEIGHT = 0x34, /* you cannot carry more items because you are overweight. */ - SKILL_CANT_USE_AREA = 0x536, - ITEM_CANT_USE_AREA = 0x537, + MSG_ITEM_CANT_OBTAIN_WEIGHT = 0x034, ///< You cannot carry more items because you are overweight. + MSG_ITEM_NEED_STANDING = 0x297, ///< You cannot use this item while sitting. + MSG_MERCENARY_EXPIRED = 0x4f2, ///< The mercenary contract has expired. + MSG_MERCENARY_DIED = 0x4f3, ///< The mercenary has died. + MSG_MERCENARY_RELEASED = 0x4f4, ///< You have released the mercenary. + MSG_MERCENARY_ESCAPED = 0x4f5, ///< The mercenary has run away. + MSG_SKILL_CANT_USE_AREA = 0x536, ///< This skill cannot be used within this area + MSG_ITEM_CANT_USE_AREA = 0x537, ///< This item cannot be used within this area. + MSG_EQUIP_NOT_PUBLIC = 0x54d, ///< This character's equipment information is not open to the public. + MSG_ITEM_NEED_MADO = 0x59b, ///< Item can only be used when Mado Gear is mounted. + MSG_ITEM_NEED_CART = 0x5ef, ///< Usable only when cart is put on + MSG_RUNE_STONE_MAX_AMOUNT = 0x61b, ///< Cannot create Rune stone more than the maximum amount. + MSG_SKILL_POINTS_LEFT_JOB1 = 0x61e, ///< You must consume all '%d' remaining points in your 1st Job tab. + MSG_SKILL_POINTS_LEFT_JOB2 = 0x61f, ///< You must consume all '%d' remaining points in your 2nd Job tab. 1st Tab is already done. + MSG_SKILL_ITEM_NOT_FOUND = 0x623, // FIXME[Haru]: This seems to be 0x622 in the msgstringtable files I found. + MSG_SKILL_SUCCESS = 0x627, // FIXME[Haru]: This seems to be 0x626 in the msgstringtable files I found. + MSG_SKILL_FAILURE = 0x628, // FIXME[Haru]: This seems to be 0x627 in the msgstringtable files I found. + MSG_SKILL_ITEM_NEED_IDENTIFY = 0x62d, ///< Unable to use unchecked items as materials. + MSG_ITEM_CANT_EQUIP_LVL = 0x6ed, // FIXME[Haru]: This seems to be 0x6ee in the msgstringtable files I found. + MSG_ITEM_CANT_USE_LVL = 0x6ee, // FIXME[Haru]: This seems to be 0x6ef in the msgstringtable files I found. + MSG_COOKING_LIST_FAIL = 0x625, // FIXME[Haru]: This might be a wrong message ID. Not sure what it should be. + MSG_SECONDS_UNTIL_USE = 0x746, ///< %d seconds left until you can use + MSG_NPC_WORK_IN_PROGRESS = 0x783, // FIXME[Haru]: This seems to be 0x784 in the msgstringtable files I found. + MSG_REINS_CANT_USE_MOUNTED = 0x78b, // FIXME[Haru]: This seems to be 0x785 in the msgstringtalbe files I found. }; /** @@ -365,16 +389,6 @@ enum cashshop_error { ERROR_TYPE_NOT_ALL = 8, ///< Some items could not be purchased. (ERROR_TYPE_NOT_ALL) }; -/** - * Color Table - **/ -enum clif_colors { - COLOR_RED, - COLOR_DEFAULT, - COLOR_WHITE, - COLOR_MAX -}; - enum CASH_SHOP_TABS { CASHSHOP_TAB_NEW = 0, CASHSHOP_TAB_POPULAR = 1, @@ -495,6 +509,30 @@ enum CLOSE_ROULETTE_ACK { }; /** + * Reason for item deletion (clif->delitem) + */ +enum delitem_reason { + DELITEM_NORMAL = 0, /// Normal + DELITEM_SKILLUSE = 1, /// Item used for a skill + DELITEM_FAILREFINE = 2, /// Refine failed + DELITEM_MATERIALCHANGE = 3, /// Material changed + DELITEM_TOSTORAGE = 4, /// Moved to storage + DELITEM_TOCART = 5, /// Moved to cart + DELITEM_SOLD = 6, /// Item sold + DELITEM_ANALYSIS = 7, /// Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill +}; + +/* +* Merge items reasons +*/ + +enum mergeitem_reason { + MERGEITEM_SUCCESS = 0x0, + MERGEITEM_FAILD = 0x1, + MERGEITEM_MAXCOUNTFAILD = 0x2, +}; + +/** * Structures **/ typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first @@ -514,11 +552,10 @@ struct cdelayed_damage { struct block_list bl; }; -/** - * Vars - **/ -struct s_packet_db packet_db[MAX_PACKET_DB + 1]; -unsigned int color_table[COLOR_MAX]; +struct merge_item { + int16 position; + int16 nameid; +}; /** * Clif.c Interface @@ -574,6 +611,8 @@ struct clif_interface { void (*dropitem) (struct map_session_data *sd,int n,int amount); void (*delitem) (struct map_session_data *sd,int n,int amount, short reason); void (*takeitem) (struct block_list* src, struct block_list* dst); + void (*item_equip) (short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos); + void (*item_normal) (short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id); void (*arrowequip) (struct map_session_data *sd,int val); void (*arrow_fail) (struct map_session_data *sd,int type); void (*use_card) (struct map_session_data *sd,int idx); @@ -796,18 +835,16 @@ struct clif_interface { void (*disp_message) (struct block_list* src, const char* mes, size_t len, enum send_target target); void (*broadcast) (struct block_list* bl, const char* mes, size_t len, int type, enum send_target target); void (*broadcast2) (struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); - void (*messagecolor) (struct block_list* bl, unsigned int color, const char* msg); + void (*messagecolor_self) (int fd, uint32 color, const char *msg); + void (*messagecolor) (struct block_list* bl, uint32 color, const char* msg); void (*disp_overhead) (struct block_list *bl, const char* mes); - void (*msg) (struct map_session_data* sd, unsigned short id); - void (*msg_value) (struct map_session_data* sd, unsigned short id, int value); - void (*msg_skill) (struct map_session_data* sd, uint16 skill_id, int msg_id); - void (*msgtable) (int fd, int line); - void (*msgtable_num) (int fd, int line, int num); + void (*msgtable) (struct map_session_data* sd, unsigned short msg_id); + void (*msgtable_num) (struct map_session_data *sd, unsigned short msg_id, int value); + void (*msgtable_skill) (struct map_session_data *sd, uint16 skill_id, int msg_id); void (*message) (const int fd, const char* mes); void (*messageln) (const int fd, const char* mes); /* message+s(printf) */ void (*messages) (const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3))); - int (*colormes) (int fd, enum clif_colors color, const char* msg); bool (*process_message) (struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_); void (*wisexin) (struct map_session_data *sd,int type,int flag); void (*wisall) (struct map_session_data *sd,int type,int flag); @@ -1037,6 +1074,12 @@ struct clif_interface { /* */ bool (*parse_roulette_db) (void); void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID); + /* Merge Items */ + void (*openmergeitem) (int fd, struct map_session_data *sd); + void (*cancelmergeitem) (int fd, struct map_session_data *sd); + int (*comparemergeitem) (const void *a, const void *b); + void (*ackmergeitems) (int fd, struct map_session_data *sd); + /*------------------------ *- Parse Incoming Packet *------------------------*/ @@ -1274,12 +1317,20 @@ struct clif_interface { /* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */ void (*pNPCMarketClosed) (int fd, struct map_session_data *sd); void (*pNPCMarketPurchase) (int fd, struct map_session_data *sd); + /* */ + void (*add_random_options) (unsigned char* buf, struct item* item); + void (*pHotkeyRowShift) (int fd, struct map_session_data *sd); }; -struct clif_interface *clif; - #ifdef HERCULES_CORE +/** + * Vars + **/ +extern struct s_packet_db packet_db[MAX_PACKET_DB + 1]; + void clif_defaults(void); #endif // HERCULES_CORE +HPShared struct clif_interface *clif; + #endif /* MAP_CLIF_H */ diff --git a/src/map/date.c b/src/map/date.c index 975a00c50..e2ad2b179 100644 --- a/src/map/date.c +++ b/src/map/date.c @@ -5,9 +5,9 @@ #include "date.h" -#include <time.h> +#include "common/cbasetypes.h" -#include "../common/cbasetypes.h" +#include <time.h> int date_get_year(void) { diff --git a/src/map/date.h b/src/map/date.h index a57d8132c..e7d06f29d 100644 --- a/src/map/date.h +++ b/src/map/date.h @@ -4,7 +4,7 @@ #ifndef MAP_DATE_H #define MAP_DATE_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" #ifdef HERCULES_CORE // TODO: Interface diff --git a/src/map/duel.c b/src/map/duel.c index 2dae0ae0e..e18e2fc45 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -6,17 +6,19 @@ #include "duel.h" +#include "map/atcommand.h" // msg_txt +#include "map/clif.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/nullpo.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "atcommand.h" // msg_txt -#include "clif.h" -#include "pc.h" -#include "../common/cbasetypes.h" - struct duel_interface duel_s; +struct duel_interface *duel; /*========================================== * Duel organizing functions [LuzZza] @@ -24,10 +26,10 @@ struct duel_interface duel_s; void duel_savetime(struct map_session_data* sd) { time_t clock; struct tm *t; - + time(&clock); t = localtime(&clock); - + pc_setglobalreg(sd, script->add_str("PC_LAST_DUEL_TIME"), t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min); } @@ -35,22 +37,25 @@ int duel_checktime(struct map_session_data* sd) { int diff; time_t clock; struct tm *t; - + time(&clock); t = localtime(&clock); - + diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, script->add_str("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) { struct map_session_data *ssd = va_arg(va, struct map_session_data*); int *p = va_arg(va, int*); char output[256]; + nullpo_retr(1, sd); + nullpo_retr(1, ssd); 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; @@ -79,19 +84,21 @@ void duel_showinfo(const unsigned int did, struct map_session_data* sd) { int duel_create(struct map_session_data* sd, const unsigned int maxpl) { int i=1; char output[256]; - + + nullpo_ret(sd); + while(i < MAX_DUEL && duel->list[i].members_count > 0) 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; - + safestrncpy(output, msg_sd(sd,372), sizeof(output)); // " -- Duel has been created (@invite/@leave) --" clif_disp_onlyself(sd, output, strlen(output)); - + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); clif->maptypeproperty2(&sd->bl,SELF); return i; @@ -100,13 +107,15 @@ 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) { char output[256]; + nullpo_retv(sd); + nullpo_retv(target_sd); // " -- Player %s invites %s to duel --" sprintf(output, msg_sd(sd,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_sd(target_sd,374), sd->status.name); clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, BC_BLUE, SELF); @@ -115,6 +124,7 @@ void duel_invite(const unsigned int did, struct map_session_data* sd, struct map static int duel_leave_sub(struct map_session_data* sd, va_list va) { int did = va_arg(va, int); + nullpo_ret(sd); if (sd->duel_invite == did) sd->duel_invite = 0; return 0; @@ -122,18 +132,18 @@ static int duel_leave_sub(struct map_session_data* sd, va_list va) void duel_leave(const unsigned int did, struct map_session_data* sd) { char output[256]; - + + nullpo_retv(sd); // " <- Player %s has left duel --" sprintf(output, msg_sd(sd,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); @@ -142,12 +152,13 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) { void duel_accept(const unsigned int did, struct map_session_data* sd) { char output[256]; - + + nullpo_retv(sd); 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_sd(sd,376), sd->status.name); clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); @@ -158,11 +169,12 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) { void duel_reject(const unsigned int did, struct map_session_data* sd) { char output[256]; - + + nullpo_retv(sd); // " -- Player %s has rejected duel --" sprintf(output, msg_sd(sd,377), sd->status.name); clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - + duel->list[did].invites_count--; sd->duel_invite = 0; } diff --git a/src/map/duel.h b/src/map/duel.h index fa12a4032..c77f1c351 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -5,7 +5,7 @@ #ifndef MAP_DUEL_H #define MAP_DUEL_H -#include "../common/cbasetypes.h" +#include "common/hercules.h" struct map_session_data; @@ -42,10 +42,10 @@ struct duel_interface { void (*final) (void); }; -struct duel_interface *duel; - #ifdef HERCULES_CORE void duel_defaults(void); #endif // HERCULES_CORE +HPShared struct duel_interface *duel; + #endif /* MAP_DUEL_H */ diff --git a/src/map/elemental.c b/src/map/elemental.c index dd97e1970..b629275e5 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -6,42 +6,43 @@ #include "elemental.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct elemental_interface elemental_s; +struct elemental_interface *elemental; int elemental_search_index(int class_) { int i; @@ -560,7 +561,7 @@ int elemental_unlocktarget(struct elemental_data *ed) { ed->target_id = 0; elemental_stop_attack(ed); - elemental_stop_walking(ed,1); + elemental_stop_walking(ed, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -586,8 +587,8 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return req; - req.hp = skill->db[idx].hp[skill_lv-1]; - req.sp = skill->db[idx].sp[skill_lv-1]; + req.hp = skill->dbs->db[idx].hp[skill_lv-1]; + req.sp = skill->dbs->db[idx].sp[skill_lv-1]; return req; } @@ -784,8 +785,8 @@ int read_elementaldb(void) { struct status_data *estatus; sprintf(line, "%s/%s", map->db_path, "elemental_db.txt"); - - if( runflag == MAPSERVER_ST_RUNNING ) //only necessary after we're up + + if( core->runflag == MAPSERVER_ST_RUNNING ) //only necessary after we're up memset(elemental->db,0,sizeof(elemental->db)); fp = fopen(line, "r"); @@ -979,27 +980,26 @@ void elemental_defaults(void) { /* */ memset(elemental->db,0,sizeof(elemental->db)); - + /* funcs */ - elemental->class = elemental_class; elemental->get_viewdata = elemental_get_viewdata; - + elemental->create = elemental_create; elemental->data_received = elemental_data_received; elemental->save = elemental_save; - + elemental->change_mode_ack = elemental_change_mode_ack; elemental->change_mode = elemental_change_mode; - + elemental->heal = elemental_heal; elemental->dead = elemental_dead; - + elemental->delete = elemental_delete; elemental->summon_stop = elemental_summon_stop; - + elemental->get_lifetime = elemental_get_lifetime; - + elemental->unlocktarget = elemental_unlocktarget; elemental->skillnotok = elemental_skillnotok; elemental->set_target = elemental_set_target; @@ -1007,11 +1007,11 @@ void elemental_defaults(void) { elemental->clean_effect = elemental_clean_effect; elemental->action = elemental_action; elemental->skill_get_requirements = elemental_skill_get_requirements; - + elemental->read_skilldb = read_elemental_skilldb; elemental->reload_db = reload_elementaldb; elemental->reload_skilldb = reload_elemental_skilldb; - + elemental->search_index = elemental_search_index; elemental->summon_init = elemental_summon_init; elemental->summon_end_timer = elemental_summon_end_timer; diff --git a/src/map/elemental.h b/src/map/elemental.h index 8015f84c0..d040f8337 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -5,9 +5,12 @@ #ifndef MAP_ELEMENTAL_H #define MAP_ELEMENTAL_H -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/mmo.h" // NAME_LENGTH +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/hercules.h" +#include "common/mmo.h" // NAME_LENGTH + +#include <stdarg.h> /** * Defines @@ -117,10 +120,10 @@ struct elemental_interface { int (*read_db) (void); }; -struct elemental_interface *elemental; - #ifdef HERCULES_CORE void elemental_defaults(void); #endif // HERCULES_CORE +HPShared struct elemental_interface *elemental; + #endif /* MAP_ELEMENTAL_H */ diff --git a/src/map/guild.c b/src/map/guild.c index 936b4c900..7a187b625 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -4,38 +4,39 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS +#include "config/core.h" // GP_BOUND_ITEMS #include "guild.h" +#include "map/battle.h" +#include "map/channel.h" +#include "map/clif.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/pc.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/mapindex.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "channel.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "pc.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/mapindex.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct guild_interface guild_s; +struct guild_interface *guild; /*========================================== * Retrieves and validates the sd pointer for this guild member [Skotlex] @@ -226,7 +227,7 @@ int guild_getposition(struct guild* g, struct map_session_data* sd) if( g == NULL && (g=sd->guild) == 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; } @@ -262,7 +263,7 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { 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 @@ -343,14 +344,12 @@ int guild_create(struct map_session_data *sd, const char *name) if( !tname[0] ) return 0; // empty name - if( sd->status.guild_id ) - {// already in a guild - clif->guild_created(sd,1); + if( sd->status.guild_id ) { + clif->guild_created(sd,1); // You're already in a guild return 0; } if (battle_config.guild_emperium_check && pc->search_inventory(sd, ITEMID_EMPERIUM) == INDEX_NOT_FOUND) { - // item required - clif->guild_created(sd,3); + clif->guild_created(sd,3); // You need the necessary item to create a guild return 0; } @@ -367,14 +366,14 @@ int guild_created(int account_id,int guild_id) { if(sd==NULL) return 0; if(!guild_id) { - clif->guild_created(sd, 2); // Creation failure (presence of the same name Guild) + clif->guild_created(sd, 2); // Creation failure (The guild name already exists) return 0; } //struct guild *g; sd->status.guild_id=guild_id; - clif->guild_created(sd,0); + clif->guild_created(sd,0); // Success if(battle_config.guild_emperium_check) - pc->delitem(sd,pc->search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption + pc->delitem(sd, pc->search_inventory(sd, ITEMID_EMPERIUM), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption return 0; } @@ -476,7 +475,7 @@ int guild_recv_info(struct guild *sg) { if (channel->config->ally_autojoin) { struct s_mapiterator* iter = mapit_getallusers(); struct guild *tg[MAX_GUILDALLIANCE]; - + for (i = 0; i < MAX_GUILDALLIANCE; i++) { tg[i] = NULL; if( sg->alliance[i].opposition == 0 && sg->alliance[i].guild_id ) @@ -508,11 +507,8 @@ int guild_recv_info(struct guild *sg) { } } } - mapit->free(iter); - } - aChSysSave = chan; } @@ -541,16 +537,16 @@ int guild_recv_info(struct guild *sg) { instances_save = g->instances; } memcpy(g,sg,sizeof(struct guild)); - + g->channel = aChSysSave; g->instance = instance_save; g->instances = instances_save; - + 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); @@ -615,7 +611,7 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { if(tsd==NULL || g==NULL) return 0; - if( (i=guild->getposition(g,sd))<0 || !(g->position[i].mode&0x0001) ) + if( (i=guild->getposition(g,sd)) < 0 || !(g->position[i].mode&GPERM_INVITE) ) return 0; //Invite permission. if(!battle_config.invite_request_check) { @@ -624,7 +620,7 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { return 0; } } - + if (!tsd->fd) { //You can't invite someone who has already disconnected. clif->guild_inviteack(sd,1); return 0; @@ -736,12 +732,11 @@ void guild_member_joined(struct map_session_data *sd) if (i == -1) sd->status.guild_id = 0; else { - g->member[i].sd = sd; sd->guild = g; - + if (channel->config->ally && channel->config->ally_autojoin) { - channel->join(g->channel, sd, NULL, true); + channel->join(g->channel, sd, "", true); } } @@ -840,7 +835,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i if(sd->status.guild_id!=guild_id) return 0; - if( (ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) ) + if ((ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&GPERM_EXPEL)) return 0; //Expulsion permission //Can't leave inside guild castles. @@ -869,7 +864,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c 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!) @@ -877,7 +872,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c online_member_sd = guild->getavailablesd(g); if(online_member_sd == NULL) return 0; // no one online to inform - + #ifdef GP_BOUND_ITEMS //Guild bound item check guild->retrieveitembound(char_id,account_id,guild_id); @@ -895,7 +890,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c // 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. + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) //Close the guild storage. gstorage->close(sd); guild->send_dot_remove(sd); if (channel->config->ally) { @@ -926,7 +921,7 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id) { if(gstor && gstor->storage_status == 1) { //Someone is in guild storage, close them struct s_mapiterator* 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->state.storage_flag == 2) { + if(sd->status.guild_id == guild_id && sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->close(sd); break; } @@ -941,9 +936,9 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id) { 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; @@ -961,7 +956,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) 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); @@ -972,13 +967,12 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { // 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; @@ -994,7 +988,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin 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); @@ -1005,7 +999,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin 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; @@ -1014,14 +1008,14 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin 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; @@ -1080,7 +1074,7 @@ int guild_memberposition_changed(struct guild *g,int idx,int pos) 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); @@ -1095,9 +1089,7 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char 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.mode=mode&GPERM_BOTH; // Invite and Expel p.exp_mode=exp_mode; safestrncpy(p.name,name,NAME_LENGTH); return intif->guild_position(guild_id,idx,&p); @@ -1114,7 +1106,7 @@ int guild_position_changed(int guild_id,int idx,struct guild_position *p) 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) @@ -1254,29 +1246,27 @@ 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 = sd->guild) == 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), guild->create_expcache, sd)); if (c->exp > UINT64_MAX - exp) c->exp = UINT64_MAX; else c->exp += exp; - + return exp; } @@ -1364,7 +1354,7 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1 return; if( !skill_lv ) return; - if( sd->sc.data[type] && (group = skill->id2group(sd->sc.data[type]->val4)) ) { + if (sd->sc.data[type] && (group = skill->id2group(sd->sc.data[type]->val4)) != NULL) { skill->del_unitgroup(group,ALC_MARK); status_change_end(&sd->bl,type,INVALID_TIMER); } @@ -1436,7 +1426,6 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) return 0; } - nullpo_ret(sd); if(tsd==NULL || tsd->status.guild_id<=0) @@ -1502,7 +1491,7 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) struct guild *g, *tg; // Reconfirm the number of alliance g=sd->guild; tg=tsd->guild; - + if(g==NULL || guild->get_alliance_count(g,0) >= battle_config.max_guild_alliance){ clif->guild_allianceack(sd,4); clif->guild_allianceack(tsd,3); @@ -1642,7 +1631,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id channel->guild_leave_alliance(g[1],g[0]); } } - + if (!(flag & 0x08)) { // new relationship for(i=0;i<2-(flag&1);i++) { if(g[i]!=NULL) { @@ -1674,7 +1663,6 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id clif->guild_oppositionack(sd[0],0); } - for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members if (g[i] != NULL) { for (j = 0; j < g[i]->max_member; j++) { @@ -1750,7 +1738,7 @@ int guild_broken(int guild_id,int flag) for(i=0;i<g->max_member;i++){ // Destroy all relationships if((sd=g->member[i].sd)!=NULL){ - if(sd->state.storage_flag == 2) + if(sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->pc_quit(sd,1); sd->status.guild_id=0; sd->guild = NULL; @@ -1774,7 +1762,7 @@ int guild_broken(int guild_id,int flag) } if( g->instance ) aFree(g->instance); - + if( g->hdata ) { for( i = 0; i < g->hdatac; i++ ) { @@ -1785,7 +1773,7 @@ int guild_broken(int guild_id,int flag) } aFree(g->hdata); } - + idb_remove(guild->db,guild_id); return 0; } @@ -1798,7 +1786,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd) if (sd->status.guild_id != guild_id) return 0; - + g=guild->search(guild_id); nullpo_ret(g); @@ -1842,7 +1830,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) clif->message(g->member[pos].sd->fd, msg_sd(g->member[pos].sd,878)); //"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->message(g->member[0].sd->fd, msg_sd(g->member[0].sd,879)); //"You have become the Guild Master!" g->member[0].sd->state.gmaster_flag = 1; @@ -1870,7 +1858,7 @@ int guild_break(struct map_session_data *sd,char *name) { struct guild *g; struct unit_data *ud; int i; - + nullpo_ret(sd); if( (g=sd->guild)==NULL ) @@ -1891,7 +1879,7 @@ int guild_break(struct map_session_data *sd,char *name) { clif->guild_broken(sd,2); return 0; } - + /* regardless of char server allowing it, we clear the guild master's auras */ if( (ud = unit->bl2ud(&sd->bl)) ) { int count = 0; @@ -1908,9 +1896,8 @@ int guild_break(struct map_session_data *sd,char *name) { groups[count++] = ud->skillunit[i]; break; } - } - for(i = 0; i < count; i++) { + for(i = 0; i < count; i++) { // FIXME: Why is this not done in the above loop? skill->del_unitgroup(groups[i],ALC_MARK); } } @@ -1918,7 +1905,7 @@ int guild_break(struct map_session_data *sd,char *name) { #ifdef GP_BOUND_ITEMS pc->bound_clear(sd,IBT_GUILD); #endif - + intif->guild_break(g->guild_id); return 1; } @@ -2156,7 +2143,7 @@ bool guild_isallied(int guild_id, int guild_id2) 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 ) { @@ -2187,11 +2174,10 @@ void guild_flag_remove(struct npc_data *nd) { 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++; } @@ -2237,7 +2223,7 @@ void guild_flags_clear(void) { if( guild->flags[i] ) guild->flags[i] = NULL; } - + guild->flags_count = 0; } @@ -2250,7 +2236,7 @@ void do_init_guild(bool minimal) { guild->expcache_db = idb_alloc(DB_OPT_BASE); guild->infoevent_db = idb_alloc(DB_OPT_BASE); guild->expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE); - + sv->readdb(map->db_path, "castle_db.txt", ',', 4, 5, -1, guild->read_castledb); sv->readdb(map->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] @@ -2265,7 +2251,7 @@ void do_final_guild(void) { DBIterator *iter = db_iterator(guild->db); struct guild *g; int i; - + for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) { if( g->channel != NULL ) channel->delete(g->channel); @@ -2284,21 +2270,21 @@ void do_final_guild(void) { aFree(g->hdata); } } - + dbi_destroy(iter); - + db_destroy(guild->db); guild->castle_db->destroy(guild->castle_db,guild->castle_db_final); guild->expcache_db->destroy(guild->expcache_db,guild->expcache_db_final); guild->infoevent_db->destroy(guild->infoevent_db,guild->eventlist_db_final); ers_destroy(guild->expcache_ers); - + if( guild->flags ) aFree(guild->flags); } void guild_defaults(void) { guild = &guild_s; - + guild->init = do_init_guild; guild->final = do_final_guild; /* */ diff --git a/src/map/guild.h b/src/map/guild.h index a75b8a7a5..a11585fbc 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -5,10 +5,10 @@ #ifndef MAP_GUILD_H #define MAP_GUILD_H -#include "map.h" // EVENT_NAME_LENGTH, TBL_PC -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" +#include "map/map.h" // EVENT_NAME_LENGTH, TBL_PC +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" /** * Defines @@ -163,10 +163,10 @@ struct guild_interface { void (*castle_reconnect_sub) (void *key, void *data, va_list ap); }; -struct guild_interface *guild; - #ifdef HERCULES_CORE void guild_defaults(void); #endif // HERCULES_CORE +HPShared struct guild_interface *guild; + #endif /* MAP_GUILD_H */ diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 6bbe1eb20..d0a4f6679 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -4,50 +4,53 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH +#include "config/core.h" // DBPATH #include "homunculus.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct homunculus_interface homunculus_s; +struct homun_dbs homundbs; + +struct homunculus_interface *homun; //Returns the viewdata for homunculus struct view_data* homunculus_get_viewdata(int class_) { if (homdb_checkid(class_)) - return &homun->viewdb[class_-HM_CLASS_BASE]; + return &homun->dbs->viewdb[class_-HM_CLASS_BASE]; return NULL; } @@ -193,13 +196,13 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) { if( hd->homunculus.prev_class != 0 ) { c = hd->homunculus.prev_class - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->dbs->skill_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( homun->skill_tree[c][i].need[j].id && - homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { + if( homun->dbs->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->dbs->skill_tree[c][i].need[j].id) < homun->dbs->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -214,16 +217,16 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) { c = hd->homunculus.class_ - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->dbs->skill_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 < homun->skill_tree[c][i].intimacylv ) + if( j < homun->dbs->skill_tree[c][i].intimacylv ) continue; if(!battle_config.skillfree) { for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { - if( homun->skill_tree[c][i].need[j].id && - homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { + if( homun->dbs->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->dbs->skill_tree[c][i].need[j].id) < homun->dbs->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -252,9 +255,9 @@ int homunculus_checkskill(struct homun_data *hd,uint16 skill_id) { int homunculus_skill_tree_get_max(int id, int b_class) { int i, skill_id; b_class -= HM_CLASS_BASE; - for(i=0;(skill_id=homun->skill_tree[b_class][i].id)>0;i++) + for(i=0;(skill_id=homun->dbs->skill_tree[b_class][i].id)>0;i++) if (id == skill_id) - return homun->skill_tree[b_class][i].max; + return homun->dbs->skill_tree[b_class][i].max; return skill->get_max(id); } @@ -294,10 +297,10 @@ bool homunculus_levelup(struct homun_data *hd) { ShowError("homunculus_levelup: Invalid class %d. \n", hd->homunculus.class_); return false; } - + if( !hd->exp_next || hd->homunculus.exp < hd->exp_next ) return false; - + switch( htype ) { case HT_REG: case HT_EVO: @@ -309,14 +312,14 @@ bool homunculus_levelup(struct homun_data *hd) { return false; break; } - + 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 = homun->exptable[hom->level - 1]; + hd->exp_next = homun->dbs->exptable[hom->level - 1]; max = &hd->homunculusDB->gmax; min = &hd->homunculusDB->gmin; @@ -366,7 +369,7 @@ int homunculus_change_class(struct homun_data *hd, short class_) { i = homun->db_search(class_,HOMUNCULUS_CLASS); if(i < 0) return 0; - hd->homunculusDB = &homun->db[i]; + hd->homunculusDB = &homun->dbs->db[i]; hd->homunculus.class_ = class_; status->set_viewdata(&hd->bl, class_); homun->calc_skilltree(hd, 1); @@ -382,7 +385,7 @@ bool homunculus_evolve(struct homun_data *hd) { sd = hd->master; if (!sd) return false; - + if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) { clif->emotion(&hd->bl, E_SWT); return false; @@ -435,7 +438,7 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) { sd = hd->master; if (!sd) return false; - + m_class = homun->class2type(hd->homunculus.class_); m_id = homun->class2type(homun_id); @@ -458,7 +461,6 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) { 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; @@ -477,12 +479,12 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) { if(hd->homunculus.vaporize != HOM_ST_ACTIVE) return 1; - + if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) { ShowError("homunculus_gainexp: Invalid class %d. \n", hd->homunculus.class_); return 0; } - + switch( htype ) { case HT_REG: case HT_EVO: @@ -584,7 +586,7 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) { clif->hom_food(sd,foodID,0); return false; } - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); if ( hd->homunculus.hunger >= 91 ) { homun->consume_intimacy(hd, 50); @@ -703,16 +705,16 @@ int homunculus_db_search(int key,int type) { int i; for(i=0;i<MAX_HOMUNCULUS_CLASS;i++) { - if(homun->db[i].base_class <= 0) + if(homun->dbs->db[i].base_class <= 0) continue; switch(type) { case HOMUNCULUS_CLASS: - if(homun->db[i].base_class == key || - homun->db[i].evo_class == key) + if(homun->dbs->db[i].base_class == key || + homun->dbs->db[i].evo_class == key) return i; break; case HOMUNCULUS_FOOD: - if(homun->db[i].foodID == key) + if(homun->dbs->db[i].foodID == key) return i; break; default: @@ -743,9 +745,9 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { hd->bl.id = npc->get_new_npc_id(); hd->master = sd; - hd->homunculusDB = &homun->db[i]; + hd->homunculusDB = &homun->dbs->db[i]; memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); - hd->exp_next = homun->exptable[hd->homunculus.level - 1]; + hd->exp_next = homun->dbs->exptable[hd->homunculus.level - 1]; status->set_viewdata(&hd->bl, hd->homunculus.class_); status->change_init(&hd->bl); @@ -760,7 +762,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { hd->bl.x = hd->ud.to_x; hd->bl.y = hd->ud.to_y; hd->masterteleport_timer = 0; - + map->addiddb(&hd->bl); status_calc_homunculus(hd,SCO_FIRST); status_percent_heal(&hd->bl, 100, 100); @@ -832,7 +834,7 @@ bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) { 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 @@ -879,7 +881,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { memset(&hom, 0, sizeof(struct s_homunculus)); //Initial data - safestrncpy(hom.name, homun->db[i].name, NAME_LENGTH-1); + safestrncpy(hom.name, homun->dbs->db[i].name, NAME_LENGTH-1); hom.class_ = class_; hom.level = 1; hom.hunger = 32; //32% @@ -887,7 +889,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { hom.char_id = sd->status.char_id; hom.hp = 10 ; - base = &homun->db[i].base; + base = &homun->dbs->db[i].base; hom.max_hp = base->HP; hom.max_sp = base->SP; hom.str = base->str *10; @@ -963,7 +965,7 @@ void homunculus_stat_reset(struct homun_data *hd) { hom->dex = base->dex *10; hom->luk = base->luk *10; hom->exp = 0; - hd->exp_next = homun->exptable[0]; + hd->exp_next = homun->dbs->exptable[0]; memset(&hd->homunculus.hskill, 0, sizeof hd->homunculus.hskill); hd->homunculus.skillpts = 0; } @@ -982,10 +984,10 @@ bool homunculus_shuffle(struct homun_data *hd) { exp = hd->homunculus.exp; memcpy(&b_skill, &hd->homunculus.hskill, sizeof(b_skill)); skillpts = hd->homunculus.skillpts; - + //Reset values to level 1. homun->stat_reset(hd); - + //Level it back up do { hd->homunculus.exp += hd->exp_next; @@ -1026,7 +1028,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) { ShowError("homunculus_read_db_sub : Invalid class %d\n", classid); return false; } - db = &homun->db[current]; + db = &homun->dbs->db[current]; db->base_class = classid; classid = atoi(str[1]); if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { @@ -1129,8 +1131,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) { void homunculus_read_db(void) { int i; const char *filename[]={DBPATH"homunculus_db.txt","homunculus_db2.txt"}; - - memset(homun->db,0,sizeof(homun->db)); + memset(homun->dbs->db, 0, sizeof(homun->dbs->db)); for(i = 0; i<ARRAYLENGTH(filename); i++) { if( i > 0 ) { char filepath[256]; @@ -1157,7 +1158,7 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { // check for bounds [celest] classid = atoi(split[0]) - HM_CLASS_BASE; - + if ( classid >= MAX_HOMUNCULUS_CLASS ) { ShowWarning("homunculus_read_skill_db_sub: Invalid homunculus class %d.\n", atoi(split[0])); return false; @@ -1165,23 +1166,23 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { 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, !homun->skill_tree[classid][j].id || homun->skill_tree[classid][j].id == k ); + ARR_FIND( 0, MAX_SKILL_TREE, j, !homun->dbs->skill_tree[classid][j].id || homun->dbs->skill_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; } - homun->skill_tree[classid][j].id = k; - homun->skill_tree[classid][j].max = atoi(split[2]); + homun->dbs->skill_tree[classid][j].id = k; + homun->dbs->skill_tree[classid][j].max = atoi(split[2]); if (minJobLevelPresent) - homun->skill_tree[classid][j].joblv = atoi(split[3]); + homun->dbs->skill_tree[classid][j].joblv = atoi(split[3]); for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ ) { - homun->skill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); - homun->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); + homun->dbs->skill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); + homun->dbs->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); } - homun->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); + homun->dbs->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); return true; } @@ -1205,9 +1206,8 @@ int8 homunculus_get_intimacy_grade(struct homun_data *hd) { } void homunculus_skill_db_read(void) { - memset(homun->skill_tree,0,sizeof(homun->skill_tree)); + memset(homun->dbs->skill_tree, 0, sizeof(homun->dbs->skill_tree)); sv->readdb(map->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub); - } void homunculus_exp_db_read(void) { @@ -1217,7 +1217,7 @@ void homunculus_exp_db_read(void) { DBPATH"exp_homun.txt", "exp_homun2.txt"}; - memset(homun->exptable,0,sizeof(homun->exptable)); + memset(homun->dbs->exptable, 0, sizeof(homun->dbs->exptable)); for(i = 0; i < 2; i++) { FILE *fp; sprintf(line, "%s/%s", map->db_path, filename[i]); @@ -1231,13 +1231,13 @@ void homunculus_exp_db_read(void) { if(line[0] == '/' && line[1] == '/') continue; - if (!(homun->exptable[j++] = (unsigned int)strtoul(line, NULL, 10))) + if (!(homun->dbs->exptable[j++] = (unsigned int)strtoul(line, NULL, 10))) break; } // Last permitted level have to be 0! - if (homun->exptable[MAX_LEVEL - 1]) { + if (homun->dbs->exptable[MAX_LEVEL - 1]) { ShowWarning("homunculus_exp_db_read: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); - homun->exptable[MAX_LEVEL - 1] = 0; + homun->dbs->exptable[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]); @@ -1266,18 +1266,19 @@ void do_init_homunculus(bool minimal) { timer->add_func_list(homun->hunger_timer, "homunculus_hunger_timer"); //Stock view data for homuncs - memset(&homun->viewdb, 0, sizeof(homun->viewdb)); - for (class_ = 0; class_ < ARRAYLENGTH(homun->viewdb); class_++) - homun->viewdb[class_].class_ = HM_CLASS_BASE+class_; + memset(homun->dbs->viewdb, 0, sizeof(homun->dbs->viewdb)); + for (class_ = 0; class_ < MAX_HOMUNCULUS_CLASS; class_++) + homun->dbs->viewdb[class_].class_ = HM_CLASS_BASE+class_; } void do_final_homunculus(void) { - + } void homunculus_defaults(void) { homun = &homunculus_s; - + homun->dbs = &homundbs; + homun->init = do_init_homunculus; homun->final = do_final_homunculus; homun->reload = homunculus_reload; diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 18f8728d3..9d23fbe2c 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -5,10 +5,12 @@ #ifndef MAP_HOMUNCULUS_H #define MAP_HOMUNCULUS_H -#include "pc.h" -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/mmo.h" +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/hercules.h" +#include "common/mmo.h" + +struct map_session_data; #define MAX_HOM_SKILL_REQUIRE 5 #define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX) @@ -98,12 +100,16 @@ enum homun_type { HT_INVALID = -1, // Invalid Homunculus }; -/* homunculus.c interface */ -struct homunculus_interface { +struct homun_dbs { unsigned int exptable[MAX_LEVEL]; struct view_data viewdb[MAX_HOMUNCULUS_CLASS]; struct s_homunculus_db db[MAX_HOMUNCULUS_CLASS]; struct homun_skill_tree_entry skill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; +}; + +/* homunculus.c interface */ +struct homunculus_interface { + struct homun_dbs *dbs; /* */ void (*init) (bool minimal); void (*final) (void); @@ -155,10 +161,10 @@ struct homunculus_interface { int8 (*get_intimacy_grade) (struct homun_data *hd); }; -struct homunculus_interface *homun; - #ifdef HERCULES_CORE void homunculus_defaults(void); #endif // HERCULES_CORE +HPShared struct homunculus_interface *homun; + #endif /* MAP_HOMUNCULUS_H */ diff --git a/src/map/instance.c b/src/map/instance.c index dd5709452..300247fe7 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -4,33 +4,35 @@ #define HERCULES_CORE +#include "config/core.h" // CELL_NOSTACK #include "instance.h" +#include "map/channel.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "../config/core.h" // CELL_NOSTACK -#include "channel.h" -#include "clif.h" -#include "map.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct instance_interface instance_s; +struct instance_interface *instance; /// Checks whether given instance id is valid or not. bool instance_is_valid(int instance_id) { @@ -45,7 +47,6 @@ bool instance_is_valid(int instance_id) { return true; } - /*-------------------------------------- * name : instance name * Return value could be @@ -59,7 +60,7 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ struct guild *g = NULL; short *iptr = NULL; int i; - + switch ( type ) { case IOT_NONE: break; @@ -91,15 +92,15 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ ShowError("instance_create: unknown type %d for owner_id %d and name %s.\n", type,owner_id,name); return -1; } - + if( type != IOT_NONE && *icptr ) { ARR_FIND(0, *icptr, i, strcmp(instance->list[iptr[i]].name,name) == 0 ); if( i != *icptr ) return -4;/* already got this instance */ } - + ARR_FIND(0, instance->instances, i, instance->list[i].state == INSTANCE_FREE); - + if( i == instance->instances ) RECREATE(instance->list, struct instance_data, ++instance->instances); @@ -119,9 +120,9 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ instance->list[i].respawn.map = 0; instance->list[i].respawn.y = 0; instance->list[i].respawn.x = 0; - + safestrncpy( instance->list[i].name, name, sizeof(instance->list[i].name) ); - + if( type != IOT_NONE ) { int j; ARR_FIND(0, *icptr, j, iptr[j] == -1); @@ -144,7 +145,7 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ iptr[j] = i; } } - + clif->instance(i, 1, 0); // Start instancing window return i; } @@ -164,27 +165,27 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id); return -1; } - + if( map_name != NULL && strdb_iget(mapindex->db, map_name) ) { ShowError("instance_add_map: trying to create instanced map with existent name '%s'\n", map_name); return -2; } - + if( map->list[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_id, map->count, i, map->list[i].name[0] == 0 ); // Searching for a Free Map - + if( i < map->count ) im = i; // Unused map found (old instance) else { im = map->count; // Using next map index RECREATE(map->list,struct map_data,++map->count); } - + if( map->list[m].cell == (struct mapcell *)0xdeadbeaf ) map->cellfromcache(&map->list[m]); @@ -197,13 +198,13 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const map->list[im].index = mapindex->addmap(-1, map->list[im].name); // Add map index map->list[im].channel = NULL; - + if( !map->list[im].index ) { map->list[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->list[im].xs * map->list[im].ys; CREATE( map->list[im].cell, struct mapcell, num_cell ); @@ -219,7 +220,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const map->list[im].cell[j].npc = 0; map->list[im].cell[j].landprotector = 0; } - + size = map->list[im].bxs * map->list[im].bys * sizeof(struct block_list*); map->list[im].block = (struct block_list**)aCalloc(size, 1); map->list[im].block_mob = (struct block_list**)aCalloc(size, 1); @@ -244,7 +245,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const if( map->list[m].skill_count ) { map->list[im].skill_count = map->list[m].skill_count; CREATE( map->list[im].skills, struct mapflag_skill_adjust*, map->list[im].skill_count ); - + for(i = 0; i < map->list[im].skill_count; i++) { CREATE( map->list[im].skills[i], struct mapflag_skill_adjust, 1); memcpy( map->list[im].skills[i],map->list[m].skills[i],sizeof(struct mapflag_skill_adjust)); @@ -254,20 +255,20 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const if( map->list[m].zone_mf_count ) { map->list[im].zone_mf_count = map->list[m].zone_mf_count; CREATE( map->list[im].zone_mf, char *, map->list[im].zone_mf_count ); - + for(i = 0; i < map->list[im].zone_mf_count; i++) { CREATE(map->list[im].zone_mf[i], char, MAP_ZONE_MAPFLAG_LENGTH); safestrncpy(map->list[im].zone_mf[i],map->list[m].zone_mf[i],MAP_ZONE_MAPFLAG_LENGTH); } } - + //Mimic questinfo if( map->list[m].qi_count ) { map->list[im].qi_count = map->list[m].qi_count; CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count ); memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) ); } - + map->list[im].m = im; map->list[im].instance_id = instance_id; map->list[im].instance_src_map = m; @@ -278,7 +279,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const instance->list[instance_id].map[instance->list[instance_id].num_map - 1] = im; // Attach to actual instance map->addmap2db(&map->list[im]); - + return im; } @@ -303,11 +304,11 @@ int instance_map2imap(int16 m, int instance_id) { int instance_mapname2imap(const char *map_name, int instance_id) { int i; - + if( !instance->valid(instance_id) ) { return -1; } - + for( i = 0; i < instance->list[instance_id].num_map; i++ ) { if( instance->list[instance_id].map[i] && !strcmpi(map->list[map->list[instance->list[instance_id].map[i]].instance_src_map].name,map_name) ) return instance->list[instance_id].map[i]; @@ -315,7 +316,6 @@ int instance_mapname2imap(const char *map_name, int instance_id) { return -1; } - /*-------------------------------------- * m : source map * instance_id : where to search @@ -352,11 +352,11 @@ int instance_init_npc(struct block_list* bl, va_list args) { struct npc_data *nd = (struct npc_data*)bl; struct event_data *ev; char evname[EVENT_NAME_LENGTH]; - + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnInstanceInit", nd->exname); if( ( ev = strdb_get(npc->ev_db, evname) ) ) - script->run(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id); return 1; } @@ -375,7 +375,7 @@ void instance_init(int instance_id) { /* cant be together with the previous because it will rely on all of them being up */ map->foreachininstance(instance->init_npc, instance_id, BL_NPC); - + instance->list[instance_id].state = INSTANCE_BUSY; } @@ -385,7 +385,7 @@ void instance_init(int instance_id) { *--------------------------------------*/ int instance_del_load(struct map_session_data* sd, va_list args) { int16 m = va_arg(args,int); - + if( !sd || sd->bl.m != m ) return 0; @@ -426,7 +426,7 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) { *--------------------------------------*/ void instance_del_map(int16 m) { int i; - + if( m <= 0 || map->list[m].instance_id == -1 ) { ShowError("instance_del_map: tried to remove non-existing instance map (%d)\n", m); return; @@ -437,38 +437,38 @@ void instance_del_map(int16 m) { if( map->list[m].mob_delete_timer != INVALID_TIMER ) timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer); - + mapindex->removemap(map_id2index(m)); // Free memory aFree(map->list[m].cell); aFree(map->list[m].block); aFree(map->list[m].block_mob); - + if (map->list[m].unit_count && map->list[m].units) { for(i = 0; i < map->list[m].unit_count; i++) { aFree(map->list[m].units[i]); } aFree(map->list[m].units); } - + if (map->list[m].skill_count && map->list[m].skills) { for(i = 0; i < map->list[m].skill_count; i++) { aFree(map->list[m].skills[i]); } aFree(map->list[m].skills); } - + if (map->list[m].zone_mf_count && map->list[m].zone_mf) { for(i = 0; i < map->list[m].zone_mf_count; i++) { aFree(map->list[m].zone_mf[i]); } aFree(map->list[m].zone_mf); } - + if( map->list[m].qi_data ) aFree(map->list[m].qi_data); - + // Remove from instance for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) { if( instance->list[map->list[m].instance_id].map[i] == m ) { @@ -479,10 +479,10 @@ void instance_del_map(int16 m) { break; } } - + if( i == instance->list[map->list[m].instance_id].num_map ) ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map->list[m].name, instance->list[map->list[m].instance_id].name, m); - + if( map->list[m].channel ) channel->delete(map->list[m].channel); @@ -512,7 +512,7 @@ void instance_destroy(int instance_id) { short *iptr = NULL; int type, j; unsigned int now = (unsigned int)time(NULL); - + if( !instance->valid(instance_id) ) return; // nothing to do @@ -522,7 +522,7 @@ void instance_destroy(int instance_id) { type = 2; else type = 3; - + clif->instance(instance_id, 5, type); // Report users this instance has been destroyed switch ( instance->list[instance_id].owner_type ) { @@ -553,13 +553,13 @@ void instance_destroy(int instance_id) { ShowError("instance_destroy: unknown type %d for owner_id %d and name '%s'.\n", instance->list[instance_id].owner_type,instance->list[instance_id].owner_id,instance->list[instance_id].name); break; } - + if( iptr != NULL ) { ARR_FIND(0, *icptr, j, iptr[j] == instance_id); if( j != *icptr ) iptr[j] = -1; } - + if (instance->list[instance_id].map) { int last = 0; while (instance->list[instance_id].num_map && last != instance->list[instance_id].map[0]) { @@ -568,7 +568,7 @@ void instance_destroy(int instance_id) { instance->del_map( instance->list[instance_id].map[0] ); } } - + if( instance->list[instance_id].regs.vars ) db_destroy(instance->list[instance_id].regs.vars); if( instance->list[instance_id].regs.arrays ) @@ -583,11 +583,11 @@ void instance_destroy(int instance_id) { if( instance->list[instance_id].map ) aFree(instance->list[instance_id].map); - + instance->list[instance_id].map = NULL; instance->list[instance_id].state = INSTANCE_FREE; instance->list[instance_id].num_map = 0; - + if (instance->list[instance_id].hdata) { for( j = 0; j < instance->list[instance_id].hdatac; j++ ) { @@ -598,7 +598,7 @@ void instance_destroy(int instance_id) { } aFree(instance->list[instance_id].hdata); } - + instance->list[instance_id].hdata = NULL; instance->list[instance_id].hdatac = 0; } @@ -686,13 +686,13 @@ void do_reload_instance(void) { struct s_mapiterator *iter; struct map_session_data *sd; int i, k; - + for(i = 0; i < instance->instances; i++) { for(k = 0; k < instance->list[i].num_map; k++) { if( !map->list[map->list[instance->list[i].map[k]].instance_src_map].flag.src4instance ) break; } - + if( k != instance->list[i].num_map ) /* any (or all) of them were disabled, we destroy */ instance->destroy(i); else { @@ -702,7 +702,7 @@ void do_reload_instance(void) { instance->set_timeout(i,instance->list[i].original_progress_timeout,instance->list[i].idle_timeoutval); } } - + iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if(sd && map->list[sd->bl.m].instance_id >= 0) { @@ -712,14 +712,13 @@ void do_reload_instance(void) { mapit->free(iter); } - void do_final_instance(void) { int i; - + for(i = 0; i < instance->instances; i++) { instance->destroy(i); } - + if( instance->list ) aFree(instance->list); @@ -736,7 +735,7 @@ void do_init_instance(bool minimal) { void instance_defaults(void) { instance = &instance_s; - + instance->init = do_init_instance; instance->final = do_final_instance; instance->reload = do_reload_instance; diff --git a/src/map/instance.h b/src/map/instance.h index 80bd1f012..589e1a511 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -5,10 +5,11 @@ #ifndef MAP_INSTANCE_H #define MAP_INSTANCE_H -#include "script.h" // struct reg_db -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // struct point +#include "map/script.h" // struct reg_db +#include "common/hercules.h" +#include "common/mmo.h" // struct point +struct HPluginData; struct block_list; struct map_session_data; @@ -84,10 +85,10 @@ struct instance_interface { int (*destroy_timer) (int tid, int64 tick, int id, intptr_t data); }; -struct instance_interface *instance; - #ifdef HERCULES_CORE void instance_defaults(void); #endif // HERCULES_CORE +HPShared struct instance_interface *instance; + #endif /* MAP_INSTANCE_H */ diff --git a/src/map/intif.c b/src/map/intif.c index 7a860049a..1795055c4 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3,9 +3,32 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS +#include "config/core.h" // GP_BOUND_ITEMS #include "intif.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/storage.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <fcntl.h> #include <signal.h> #include <stdio.h> @@ -13,30 +36,8 @@ #include <string.h> #include <sys/types.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "storage.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct intif_interface intif_s; +struct intif_interface *intif; #define inter_fd (chrif->fd) // alias @@ -45,7 +46,7 @@ struct intif_interface intif_s; int CheckForCharServer(void) { - return ((chrif->fd <= 0) || session[chrif->fd] == NULL || session[chrif->fd]->wdata == NULL); + return ((chrif->fd <= 0) || sockt->session[chrif->fd] == NULL || sockt->session[chrif->fd]->wdata == NULL); } // pet @@ -278,7 +279,7 @@ int intif_saveregistry(struct map_session_data *sd) { if (intif->CheckForCharServer() || !sd->regs.vars) return -1; - + WFIFOHEAD(inter_fd, 60000 + 300); WFIFOW(inter_fd,0) = 0x3004; /* 0x2 = length (set later) */ @@ -287,78 +288,76 @@ int intif_saveregistry(struct map_session_data *sd) { WFIFOW(inter_fd,12) = 0;/* count */ plen = 14; - + iter = db_iterator(sd->regs.vars); for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) { const char *varname = NULL; struct script_reg_state *src = NULL; - + if( data->type != DB_DATA_PTR ) /* its a @number */ continue; - + varname = script->get_str(script_getvarid(key.i64)); - + if( varname[0] == '@' ) /* @string$ can get here, so we skip */ continue; - + src = DB->data2ptr(data); /* no need! */ if( !src->update ) continue; - + src->update = false; - + len = strlen(varname)+1; - + WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ plen += 1; - + safestrncpy((char*)WFIFOP(inter_fd,plen), varname, len); plen += len; - + WFIFOL(inter_fd, plen) = script_getvaridx(key.i64); plen += 4; - + if( src->type ) { struct script_reg_str *p = (struct script_reg_str *)src; - + WFIFOB(inter_fd, plen) = p->value ? 2 : 3; plen += 1; - + if( p->value ) { len = strlen(p->value)+1; - + WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */ plen += 1; - + safestrncpy((char*)WFIFOP(inter_fd,plen), p->value, len); plen += len; } else { script->reg_destroy_single(sd,key.i64,&p->flag); } - } else { struct script_reg_num *p = (struct script_reg_num *)src; WFIFOB(inter_fd, plen) = p->value ? 0 : 1; plen += 1; - + if( p->value ) { WFIFOL(inter_fd, plen) = p->value; plen += 4; } else { script->reg_destroy_single(sd,key.i64,&p->flag); } - } - + WFIFOW(inter_fd,12) += 1; - + if( plen > 60000 ) { WFIFOW(inter_fd, 2) = plen; WFIFOSET(inter_fd, plen); - + /* prepare follow up */ WFIFOHEAD(inter_fd, 60000 + 300); WFIFOW(inter_fd,0) = 0x3004; @@ -366,19 +365,18 @@ int intif_saveregistry(struct map_session_data *sd) { WFIFOL(inter_fd,4) = sd->status.account_id; WFIFOL(inter_fd,8) = sd->status.char_id; WFIFOW(inter_fd,12) = 0;/* count */ - + plen = 14; } - } dbi_destroy(iter); /* mark & go. */ WFIFOW(inter_fd, 2) = plen; WFIFOSET(inter_fd, plen); - + sd->vars_dirty = false; - + return 0; } @@ -825,7 +823,6 @@ int intif_guild_castle_dataload(int num, int *castle_ids) return 1; } - // Request change castle guild owner and save data int intif_guild_castle_datasave(int castle_id,int index, int value) { @@ -894,7 +891,6 @@ int intif_homunculus_requestdelete(int homun_id) } - //----------------------------------------------------------------- // Packets receive from inter server @@ -998,13 +994,13 @@ void intif_parse_Registers(int fd) else { //Normally registries should arrive for in log-in chars. sd = map->id2sd(account_id); } - + if (!sd || sd->status.char_id != char_id) { return; //Character registry from another character. } - + flag = ( sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR ) ? 0 : 1; - + switch (RFIFOB(fd,12)) { case 3: //Character Registry sd->vars_received |= PRL_CHAR; @@ -1023,14 +1019,14 @@ void intif_parse_Registers(int fd) } /* have it not complain about insertion of vars before loading, and not set those vars as new or modified */ pc->reg_load = true; - + if( RFIFOW(fd, 14) ) { char key[32]; unsigned int index; int max = RFIFOW(fd, 14), cursor = 16, i; - + script->parser_current_file = "loading char/acc variables";//for script_add_str to refer to here in case errors occur - + /** * Vessel!char_reg_num_db * @@ -1042,13 +1038,13 @@ void intif_parse_Registers(int fd) char sval[254]; safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor)); cursor += RFIFOB(fd, cursor) + 1; - + index = RFIFOL(fd, cursor); cursor += 4; - + safestrncpy(sval, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor)); cursor += RFIFOB(fd, cursor) + 1; - + script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)sval, NULL); } /** @@ -1062,23 +1058,22 @@ void intif_parse_Registers(int fd) int ival; safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor)); cursor += RFIFOB(fd, cursor) + 1; - + index = RFIFOL(fd, cursor); cursor += 4; - + ival = RFIFOL(fd, cursor); cursor += 4; - + script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)h64BPTRSIZE(ival), NULL); } } - script->parser_current_file = NULL;/* reset */ } - + /* flag it back */ pc->reg_load = false; - + if (flag && sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR) pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] } @@ -1661,7 +1656,7 @@ void intif_parse_MailDelete(int fd) { int char_id = RFIFOL(fd,2); int mail_id = RFIFOL(fd,6); bool failed = RFIFOB(fd,10); - + if ( (sd = map->charid2sd(char_id)) == NULL) { ShowError("intif_parse_MailDelete: char not found %d\n", char_id); return; @@ -1986,7 +1981,7 @@ int intif_mercenary_create(struct s_mercenary *merc) void intif_parse_MercenaryReceived(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 mismatch %d != %"PRIuS"\n", len, sizeof(struct s_mercenary)); @@ -2066,7 +2061,7 @@ int intif_elemental_create(struct s_elemental *ele) void intif_parse_ElementalReceived(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 mismatch %d != %"PRIuS"\n", len, sizeof(struct s_elemental)); @@ -2127,8 +2122,6 @@ void intif_parse_ElementalSaved(int fd) { } void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { - - WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); WFIFOW(inter_fd,0) = 0x3007; @@ -2145,14 +2138,14 @@ void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { void intif_parse_MessageToFD(int fd) { int u_fd = RFIFOL(fd,4); - if( session[u_fd] && session[u_fd]->session_data ) { + if( sockt->session[u_fd] && sockt->session[u_fd]->session_data ) { int aid = RFIFOL(fd,8); - struct map_session_data * sd = session[u_fd]->session_data; + struct map_session_data * sd = sockt->session[u_fd]->session_data; /* matching e.g. previous fd owner didn't dc during request or is still the same */ if( sd && sd->bl.id == aid ) { char msg[512]; safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif->message(u_fd,msg); + clif->messagecolor_self(u_fd, COLOR_DEFAULT ,msg); } } @@ -2175,7 +2168,7 @@ void intif_itembound_req(int char_id,int aid,int guild_id) { gstor->lock = 1; //Lock for retrieval process #endif } - + //3856 void intif_parse_Itembound_ack(int fd) { #ifdef GP_BOUND_ITEMS @@ -2251,11 +2244,11 @@ int intif_parse(int fd) case 0x383f: intif->pGuildEmblem(fd); break; case 0x3840: intif->pGuildCastleDataLoad(fd); break; case 0x3843: intif->pGuildMasterChanged(fd); break; - + //Quest system case 0x3860: intif->pQuestLog(fd); break; case 0x3861: intif->pQuestSave(fd); break; - + // Mail System case 0x3848: intif->pMailInboxReceived(fd); break; case 0x3849: intif->pMailNew(fd); break; @@ -2286,7 +2279,7 @@ int intif_parse(int fd) case 0x387c: intif->pElementalReceived(fd); break; case 0x387d: intif->pElementalDeleted(fd); break; case 0x387e: intif->pElementalSaved(fd); break; - + case 0x3880: intif->pCreatePet(fd); break; case 0x3881: intif->pRecvPetData(fd); break; case 0x3882: intif->pSavePetOk(fd); break; @@ -2327,7 +2320,7 @@ void intif_defaults(void) { /* */ memcpy(intif->packet_len_table,&packet_len_table,sizeof(intif->packet_len_table)); - + /* funcs */ intif->parse = intif_parse; intif->create_pet = intif_create_pet; diff --git a/src/map/intif.h b/src/map/intif.h index 52aa32259..369ac1d9b 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -5,7 +5,7 @@ #ifndef MAP_INTIF_H #define MAP_INTIF_H -#include "../common/cbasetypes.h" +#include "common/hercules.h" /** * Declarations @@ -182,10 +182,10 @@ struct intif_interface { void (*pDeleteHomunculusOk) (int fd); }; -struct intif_interface *intif; - #ifdef HERCULES_CORE void intif_defaults(void); #endif // HERCULES_CORE +HPShared struct intif_interface *intif; + #endif /* MAP_INTIF_H */ diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index d492ad9ca..f89bd2f1c 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -1,29 +1,30 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -// Base Author: shennetsind @ http://hercules.ws +// Base Author: shennetsind @ http://herc.ws #define HERCULES_CORE #include "irc-bot.h" +#include "map/channel.h" +#include "map/map.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "channel.h" -#include "map.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - //#define IRCBOT_DEBUG struct irc_bot_interface irc_bot_s; +struct irc_bot_interface *ircbot; char send_string[IRC_MESSAGE_LENGTH]; @@ -35,15 +36,15 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) { struct hSockOpt opt; if( ircbot->isOn || ++ircbot->fails >= 3 ) return 0; - + opt.silent = 1; opt.setTimeo = 0; - + ircbot->last_try = timer->gettick(); - if ((ircbot->fd = make_connection(ircbot->ip, channel->config->irc_server_port, &opt)) > 0) { - session[ircbot->fd]->func_parse = ircbot->parse; - session[ircbot->fd]->flag.server = 1; + if ((ircbot->fd = sockt->make_connection(ircbot->ip, channel->config->irc_server_port, &opt)) > 0) { + sockt->session[ircbot->fd]->func_parse = ircbot->parse; + sockt->session[ircbot->fd]->flag.server = 1; timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0); ircbot->isOn = true; } @@ -57,14 +58,14 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) { int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) { if( !ircbot->isOn ) return 0; - + sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rnd()%777); ircbot->send(send_string); sprintf(send_string, "NICK %s", channel->config->irc_nick); ircbot->send(send_string); timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0); - + return 0; } @@ -75,7 +76,7 @@ int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) { int irc_join_timer(int tid, int64 tick, int id, intptr_t data) { if( !ircbot->isOn ) return 0; - + if (channel->config->irc_nick_pw[0] != '\0') { sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", channel->config->irc_nick_pw); ircbot->send(send_string); @@ -83,7 +84,7 @@ int irc_join_timer(int tid, int64 tick, int id, intptr_t data) { sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", channel->config->irc_nick, channel->config->irc_nick_pw); } } - + sprintf(send_string, "JOIN %s", channel->config->irc_channel); ircbot->send(send_string); ircbot->isIn = true; @@ -114,30 +115,30 @@ struct irc_func* irc_func_search(char* function_name) { int irc_parse(int fd) { char *parse_string = NULL, *str_safe = NULL; - if (session[fd]->flag.eof) { - do_close(fd); + if (sockt->session[fd]->flag.eof) { + sockt->close(fd); ircbot->fd = 0; ircbot->isOn = false; ircbot->isIn = false; ircbot->fails = 0; - ircbot->ip = host2ip(channel->config->irc_server); + ircbot->ip = sockt->host2ip(channel->config->irc_server); timer->add(timer->gettick() + 120000, ircbot->connect_timer, 0, 0); return 0; } - + if( !RFIFOREST(fd) ) return 0; - + parse_string = (char*)RFIFOP(fd,0); parse_string[ RFIFOREST(fd) - 1 ] = '\0'; - + parse_string = strtok_r(parse_string,"\r\n",&str_safe); - + while (parse_string != NULL) { ircbot->parse_sub(fd,parse_string); parse_string = strtok_r(NULL,"\r\n",&str_safe); } - + RFIFOSKIP(fd, RFIFOREST(fd)); RFIFOFLUSH(fd); return 0; @@ -157,7 +158,7 @@ void irc_parse_source(char *source, char *nick, char *ident, char *host) { int i, pos = 0; size_t len = strlen(source); unsigned char stage = 0; - + for(i = 0; i < len; i++) { if( stage == 0 && source[i] == '!' ) { safestrncpy(nick, &source[0], min(i + 1, IRC_NICK_LENGTH)); @@ -181,29 +182,28 @@ void irc_parse_sub(int fd, char *str) { char source[180], command[60], buf1[IRC_MESSAGE_LENGTH], buf2[IRC_MESSAGE_LENGTH]; char *target = buf1, *message = buf2; struct irc_func *func; - + source[0] = command[0] = buf1[0] = buf2[0] = '\0'; - + if( str[0] == ':' ) str++; - + if (sscanf(str, "%179s %59s %499s :%499[^\r\n]", source, command, buf1, buf2) == 3 && buf1[0] == ':') { // source command :message (i.e. QUIT) message = buf1+1; target = buf2; } - + if( command[0] == '\0' ) return; - - if( !(func = ircbot->func_search(command)) && !(func = ircbot->func_search(source)) ) { + + if ((func = ircbot->func_search(command)) == NULL && (func = ircbot->func_search(source)) == NULL) { #ifdef IRCBOT_DEBUG ShowWarning("Unknown command received %s from %s\n",command,source); #endif // IRCBOT_DEBUG return; } func->func(fd,command,source,target,message); - } /** @@ -300,7 +300,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) { if( source[0] != '\0' ) ircbot->parse_source(source,source_nick,source_ident,source_host); - + if( ircbot->channel ) { size_t padding_len = strlen(ircbot->channel->name) + strlen(source_nick) + 13; while (1) { @@ -415,31 +415,31 @@ void irc_bot_init(bool minimal) { if (!channel->config->irc) return; - if (!(ircbot->ip = host2ip(channel->config->irc_server))) { + if (!(ircbot->ip = sockt->host2ip(channel->config->irc_server))) { ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", channel->config->irc_server); channel->config->irc = false; return; } - + ircbot->funcs.size = ARRAYLENGTH(irc_func_base); CREATE(ircbot->funcs.list,struct irc_func*,ircbot->funcs.size); - + for( i = 0; i < ircbot->funcs.size; i++ ) { - + CREATE(function, struct irc_func, 1); - + safestrncpy(function->name, irc_func_base[i].name, sizeof(function->name)); function->func = irc_func_base[i].func; - + ircbot->funcs.list[i] = function; } - + ircbot->fails = 0; ircbot->fd = 0; ircbot->isIn = false; ircbot->isOn = false; - + timer->add_func_list(ircbot->connect_timer, "irc_connect_timer"); timer->add(timer->gettick() + 7000, ircbot->connect_timer, 0, 0); } @@ -449,14 +449,14 @@ void irc_bot_init(bool minimal) { */ void irc_bot_final(void) { int i; - + if (!channel->config->irc) return; if( ircbot->isOn ) { ircbot->send("QUIT :Hercules is shutting down"); - do_close(ircbot->fd); + sockt->close(ircbot->fd); } - + for( i = 0; i < ircbot->funcs.size; i++ ) { aFree(ircbot->funcs.list[i]); } @@ -468,25 +468,25 @@ void irc_bot_final(void) { */ void ircbot_defaults(void) { ircbot = &irc_bot_s; - + ircbot->channel = NULL; - + ircbot->init = irc_bot_init; ircbot->final = irc_bot_final; - + ircbot->parse = irc_parse; ircbot->parse_sub = irc_parse_sub; ircbot->parse_source = irc_parse_source; - + ircbot->func_search = irc_func_search; - + ircbot->connect_timer = irc_connect_timer; ircbot->identify_timer = irc_identify_timer; ircbot->join_timer = irc_join_timer; - + ircbot->send = irc_send; ircbot->relay = irc_relay; - + ircbot->pong = irc_pong; ircbot->privmsg = irc_privmsg; diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index 8dcfea5bd..a85fc46e8 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -1,12 +1,12 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -// Base Author: shennetsind @ http://hercules.ws +// Base Author: shennetsind @ http://herc.ws #ifndef MAP_IRC_BOT_H #define MAP_IRC_BOT_H -#include "../common/cbasetypes.h" +#include "common/hercules.h" #define IRC_NICK_LENGTH 40 #define IRC_IDENT_LENGTH 40 @@ -59,10 +59,10 @@ struct irc_bot_interface { void (*usernick) (int fd, char *cmd, char *source, char *target, char *msg); }; -struct irc_bot_interface *ircbot; - #ifdef HERCULES_CORE void ircbot_defaults(void); #endif // HERCULES_CORE +HPShared struct irc_bot_interface *ircbot; + #endif /* MAP_IRC_BOT_H */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index fb6bcc730..ccedee72a 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -4,28 +4,29 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, RENEWAL +#include "config/core.h" // DBPATH, RENEWAL #include "itemdb.h" +#include "map/battle.h" // struct battle_config +#include "map/map.h" +#include "map/mob.h" // MAX_MOB_DB +#include "map/pc.h" // W_MUSICAL, W_WHIP +#include "map/script.h" // item script processing +#include "common/HPM.h" +#include "common/conf.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" // struct battle_config -#include "map.h" -#include "mob.h" // MAX_MOB_DB -#include "pc.h" // W_MUSICAL, W_WHIP -#include "script.h" // item script processing -#include "../common/HPM.h" -#include "../common/conf.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" - struct itemdb_interface itemdb_s; +struct itemdb_interface *itemdb; /** * Search for item name @@ -75,7 +76,7 @@ struct item_data* itemdb_searchname(const char *str) { return item; //Second priority to Client displayed name. - if( strcasecmp(item->jname,str) == 0 ) + if (!item2 && strcasecmp(item->jname,str) == 0) item2 = item; } @@ -159,14 +160,14 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str, /* [Ind/Hercules] */ int itemdb_chain_item(unsigned short chain_id, int *rate) { struct item_chain_entry *entry; - + if( chain_id >= itemdb->chain_count ) { ShowError("itemdb_chain_item: unknown chain id %d\n", chain_id); return UNKNOWN_ITEM_ID; } - + entry = &itemdb->chains[chain_id].items[ rnd()%itemdb->chains[chain_id].qty ]; - + if( rnd()%10000 >= entry->rate ) return 0; @@ -177,44 +178,47 @@ int itemdb_chain_item(unsigned short chain_id, int *rate) { /* [Ind/Hercules] */ void itemdb_package_item(struct map_session_data *sd, struct item_package *package) { int i = 0, get_count, j, flag; - + for( i = 0; i < package->must_qty; i++ ) { struct item it; memset(&it, 0, sizeof(it)); it.nameid = package->must_items[i].id; it.identify = 1; - + if( package->must_items[i].hours ) { it.expire_time = (unsigned int)(time(NULL) + ((package->must_items[i].hours*60)*60)); } - + if( package->must_items[i].named ) { it.card[0] = CARD0_FORGE; it.card[1] = 0; it.card[2] = GetWord(sd->status.char_id, 0); it.card[3] = GetWord(sd->status.char_id, 1); } - + if( package->must_items[i].announce ) clif->package_announce(sd,package->must_items[i].id,package->id); - + + if ( package->must_items[i].force_serial ) + it.unique_id = itemdb->unique_id(sd); + get_count = itemdb->isstackable(package->must_items[i].id) ? package->must_items[i].qty : 1; - + it.amount = get_count == 1 ? 1 : get_count; - + for( j = 0; j < package->must_items[i].qty; j += get_count ) { if ( ( flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT) ) ) clif->additem(sd, 0, 0, flag); } } - + if( package->random_qty ) { for( i = 0; i < package->random_qty; i++ ) { struct item_package_rand_entry *entry; - + entry = &package->random_groups[i].random_list[rnd()%package->random_groups[i].random_qty]; - + while( 1 ) { if( rnd()%10000 >= entry->rate ) { entry = entry->next; @@ -222,28 +226,28 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa } else { struct item it; memset(&it, 0, sizeof(it)); - + it.nameid = entry->id; it.identify = 1; - + if( entry->hours ) { it.expire_time = (unsigned int)(time(NULL) + ((entry->hours*60)*60)); } - + if( entry->named ) { it.card[0] = CARD0_FORGE; it.card[1] = 0; it.card[2] = GetWord(sd->status.char_id, 0); it.card[3] = GetWord(sd->status.char_id, 1); } - + if( entry->announce ) clif->package_announce(sd,entry->id,package->id); - + get_count = itemdb->isstackable(entry->id) ? entry->qty : 1; - + it.amount = get_count == 1 ? 1 : get_count; - + for( j = 0; j < entry->qty; j += get_count ) { if ( ( flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT) ) ) clif->additem(sd, 0, 0, flag); @@ -253,9 +257,8 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa } } } - - return; } + /*========================================== * Return a random item id from group. (takes into account % chance giving/tot group) *------------------------------------------*/ @@ -263,17 +266,17 @@ int itemdb_searchrandomid(struct item_group *group) { if (group->qty) return group->nameid[rnd()%group->qty]; - + ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group->id); return UNKNOWN_ITEM_ID; } bool itemdb_in_group(struct item_group *group, int nameid) { int i; - + for( i = 0; i < group->qty; i++ ) if( group->nameid[i] == nameid ) return true; - + return false; } @@ -518,7 +521,6 @@ int itemdb_isstackable2(struct item_data *data) } } - /*========================================== * Trade Restriction functions [Skotlex] *------------------------------------------*/ @@ -565,10 +567,10 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru 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)) @@ -619,12 +621,12 @@ void itemdb_read_groups(void) { ShowError("can't read %s\n", config_filename); return; } - + gsize = aMalloc( libconfig->setting_length(item_group_conf.root) * sizeof(unsigned int) ); - + for(i = 0; i < libconfig->setting_length(item_group_conf.root); i++) gsize[i] = 0; - + i = 0; while( (itg = libconfig->setting_get_elem(item_group_conf.root,i++)) ) { const char *name = config_setting_name(itg); @@ -635,7 +637,7 @@ void itemdb_read_groups(void) { --i; continue; } - + c = 0; while( (it = libconfig->setting_get_elem(itg,c++)) ) { if( config_setting_is_list(it) ) @@ -643,19 +645,18 @@ void itemdb_read_groups(void) { else gsize[ i - 1 ] += 1; } - } - + i = 0; CREATE(itemdb->groups, struct item_group, libconfig->setting_length(item_group_conf.root)); itemdb->group_count = (unsigned short)libconfig->setting_length(item_group_conf.root); - + while( (itg = libconfig->setting_get_elem(item_group_conf.root,i++)) ) { struct item_data *data = itemdb->name2id(config_setting_name(itg)); int ecount = 0; - + data->group = &itemdb->groups[count]; - + itemdb->groups[count].id = data->nameid; itemdb->groups[count].qty = gsize[ count ]; @@ -668,13 +669,13 @@ void itemdb_read_groups(void) { repeat = libconfig->setting_get_int_elem(it,1); } else itname = libconfig->setting_get_string_elem(itg,c - 1); - + if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) { if( !( data = itemdb->exists(atoi(itname+2)) ) ) ShowWarning("itemdb_read_groups: unknown item ID '%d' in group '%s'!\n",atoi(itname+2),config_setting_name(itg)); } else if( !( data = itemdb->name2id(itname) ) ) ShowWarning("itemdb_read_groups: unknown item '%s' in group '%s'!\n",itname,config_setting_name(itg)); - + itemdb->groups[count].nameid[ecount] = data ? data->nameid : 0; if( repeat > 1 ) { //memset would be better? I failed to get the following to work though hu @@ -685,25 +686,24 @@ void itemdb_read_groups(void) { } ecount += repeat; } - count++; } - + libconfig->destroy(&item_group_conf); aFree(gsize); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename); } + /* [Ind/Hercules] - HCache for Packages */ void itemdb_write_cached_packages(const char *config_filename) { FILE *file; unsigned short pcount = itemdb->package_count; unsigned short i; - + if( !(file = HCache->open(config_filename,"wb")) ) { return; } - + // first 2 bytes = package count hwrite(&pcount,sizeof(pcount),1,file); @@ -719,7 +719,7 @@ void itemdb_write_cached_packages(const char *config_filename) { //now we loop into must for(c = 0; c < must_qty; c++) { struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c]; - unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0; + unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0; //first 2 byte = item id hwrite(&entry->id,sizeof(entry->id),1,file); //next 2 byte = qty @@ -729,19 +729,21 @@ void itemdb_write_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hwrite(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hwrite(&named,sizeof(announce),1,file); + hwrite(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hwrite(&force_serial,sizeof(force_serial),1,file); } //now we loop into random groups for(c = 0; c < random_qty; c++) { struct item_package_rand_group *group = &itemdb->packages[i].random_groups[c]; unsigned short group_qty = group->random_qty, h; - + //next 2 bytes = how many entries in this group hwrite(&group_qty,sizeof(group_qty),1,file); //now we loop into the group's list for(h = 0; h < group_qty; h++) { struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h]; - unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0; + unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0; //first 2 byte = item id hwrite(&entry->id,sizeof(entry->id),1,file); //next 2 byte = qty @@ -753,13 +755,14 @@ void itemdb_write_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hwrite(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hwrite(&named,sizeof(announce),1,file); + hwrite(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hwrite(&force_serial,sizeof(force_serial),1,file); } } } - fclose(file); - + return; } bool itemdb_read_cached_packages(const char *config_filename) { @@ -770,7 +773,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { if( !(file = HCache->open(config_filename,"rb")) ) { return false; } - + // first 2 bytes = package count hread(&pcount,sizeof(pcount),1,file); @@ -782,32 +785,32 @@ bool itemdb_read_cached_packages(const char *config_filename) { struct item_data *pdata; struct item_package *package = &itemdb->packages[i]; unsigned short c; - + //into a package, first 2 bytes = id. hread(&id,sizeof(id),1,file); //next 2 bytes = must count hread(&must_qty,sizeof(must_qty),1,file); //next 2 bytes = random count hread(&random_qty,sizeof(random_qty),1,file); - + if( !(pdata = itemdb->exists(id)) ) ShowWarning("itemdb_read_cached_packages: unknown package item '%d', skipping..\n",id); else pdata->package = &itemdb->packages[i]; - + package->id = id; package->random_qty = random_qty; package->must_qty = must_qty; package->must_items = NULL; package->random_groups = NULL; - + if( package->must_qty ) { CREATE(package->must_items, struct item_package_must_entry, package->must_qty); //now we loop into must for(c = 0; c < package->must_qty; c++) { struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c]; unsigned short mid = 0, qty = 0, hours = 0; - unsigned char announce = 0, named = 0; + unsigned char announce = 0, named = 0, force_serial = 0; struct item_data *data; //first 2 byte = item id hread(&mid,sizeof(mid),1,file); @@ -818,8 +821,10 @@ bool itemdb_read_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hread(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hread(&named,sizeof(announce),1,file); - + hread(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hread(&force_serial,sizeof(force_serial),1,file); + if( !(data = itemdb->exists(mid)) ) ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); @@ -828,6 +833,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { entry->qty = qty; entry->announce = announce ? 1 : 0; entry->named = named ? 1 : 0; + entry->force_serial = force_serial ? 1 : 0; } } if( package->random_qty ) { @@ -836,22 +842,22 @@ bool itemdb_read_cached_packages(const char *config_filename) { for(c = 0; c < package->random_qty; c++) { unsigned short group_qty = 0, h; struct item_package_rand_entry *prev = NULL; - + //next 2 bytes = how many entries in this group hread(&group_qty,sizeof(group_qty),1,file); - + package->random_groups[c].random_qty = group_qty; CREATE(package->random_groups[c].random_list, struct item_package_rand_entry, package->random_groups[c].random_qty); - + //now we loop into the group's list for(h = 0; h < group_qty; h++) { struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h]; unsigned short mid = 0, qty = 0, hours = 0, rate = 0; - unsigned char announce = 0, named = 0; + unsigned char announce = 0, named = 0, force_serial = 0; struct item_data *data; if( prev ) prev->next = entry; - + //first 2 byte = item id hread(&mid,sizeof(mid),1,file); //next 2 byte = qty @@ -863,18 +869,20 @@ bool itemdb_read_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hread(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hread(&named,sizeof(announce),1,file); - + hread(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hread(&force_serial,sizeof(force_serial),1,file); + if( !(data = itemdb->exists(mid)) ) ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); - + entry->id = data ? data->nameid : 0; entry->rate = rate; entry->hours = hours; entry->qty = qty; entry->announce = announce ? 1 : 0; entry->named = named ? 1 : 0; - + entry->force_serial = force_serial ? 1 : 0; prev = entry; } if( prev ) @@ -882,9 +890,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { } } } - fclose(file); - ShowStatus("Done reading '"CL_WHITE"%hu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"' ("CL_GREEN"C"CL_RESET").\n", pcount, config_filename); return true; @@ -901,42 +907,41 @@ void itemdb_read_packages(void) { int i = 0, count = 0, c = 0, highest_gcount = 0; unsigned int *must = NULL, *random = NULL, *rgroup = NULL, **rgroups = NULL; struct item_package_rand_entry **prev = NULL; - + if( HCache->check(config_filename) ) { if( itemdb->read_cached_packages(config_filename) ) return; } - + if (libconfig->read_file(&item_packages_conf, config_filename)) { ShowError("can't read %s\n", config_filename); return; } - + must = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); random = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); rgroup = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); rgroups = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int *) ); - for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++) { must[i] = 0; random[i] = 0; rgroup[i] = 0; rgroups[i] = NULL; } - + /* validate tree, drop poisonous fruits! */ i = 0; while( (itg = libconfig->setting_get_elem(item_packages_conf.root,i++)) ) { const char *name = config_setting_name(itg); - + if( !itemdb->name2id(name) ) { ShowWarning("itemdb_read_packages: unknown package item '%s', skipping..\n",name); libconfig->setting_remove(item_packages_conf.root, name); --i; continue; } - + c = 0; while( (it = libconfig->setting_get_elem(itg,c++)) ) { int rval = 0; @@ -946,7 +951,7 @@ void itemdb_read_packages(void) { --c; continue; } - + if( rval == 0 ) must[ i - 1 ] += 1; else { @@ -963,7 +968,7 @@ void itemdb_read_packages(void) { for(i = 0; i < highest_gcount; i++) { prev[i] = NULL; } - + for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++ ) { rgroups[i] = aMalloc( rgroup[i] * sizeof(unsigned int) ); for( c = 0; c < rgroup[i]; c++ ) { @@ -977,33 +982,33 @@ void itemdb_read_packages(void) { c = 0; while( (it = libconfig->setting_get_elem(itg,c++)) ) { int rval = 0; - if( ( t = libconfig->setting_get_member(it, "Random")) && ( rval = libconfig->setting_get_int(t) ) > 0 ) { + if ((t = libconfig->setting_get_member(it, "Random")) != NULL && (rval = libconfig->setting_get_int(t)) > 0) { rgroups[i - 1][rval - 1] += 1; } } } - + CREATE(itemdb->packages, struct item_package, libconfig->setting_length(item_packages_conf.root)); itemdb->package_count = (unsigned short)libconfig->setting_length(item_packages_conf.root); - + /* write */ i = 0; while( (itg = libconfig->setting_get_elem(item_packages_conf.root,i++)) ) { struct item_data *data = itemdb->name2id(config_setting_name(itg)); int r = 0, m = 0; - + for(r = 0; r < highest_gcount; r++) { prev[r] = NULL; } - + data->package = &itemdb->packages[count]; - + itemdb->packages[count].id = data->nameid; itemdb->packages[count].random_groups = NULL; itemdb->packages[count].must_items = NULL; itemdb->packages[count].random_qty = rgroup[ i - 1 ]; itemdb->packages[count].must_qty = must[ i - 1 ]; - + if( itemdb->packages[count].random_qty ) { CREATE(itemdb->packages[count].random_groups, struct item_package_rand_group, itemdb->packages[count].random_qty); for( c = 0; c < itemdb->packages[count].random_qty; c++ ) { @@ -1016,14 +1021,14 @@ void itemdb_read_packages(void) { } if( itemdb->packages[count].must_qty ) CREATE(itemdb->packages[count].must_items, struct item_package_must_entry, itemdb->packages[count].must_qty); - + c = 0; while( (it = libconfig->setting_get_elem(itg,c++)) ) { int icount = 1, expire = 0, rate = 10000, gid = 0; - bool announce = false, named = false; - + bool announce = false, named = false, force_serial = false; + itname = config_setting_name(it); - + if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) { if( !( data = itemdb->exists(atoi(itname+2)) ) ) ShowWarning("itemdb_read_packages: unknown item ID '%d' in package '%s'!\n",atoi(itname+2),config_setting_name(itg)); @@ -1032,10 +1037,10 @@ void itemdb_read_packages(void) { if( ( t = libconfig->setting_get_member(it, "Count")) ) icount = libconfig->setting_get_int(t); - + if( ( t = libconfig->setting_get_member(it, "Expire")) ) expire = libconfig->setting_get_int(t); - + if( ( t = libconfig->setting_get_member(it, "Rate")) ) { if( (rate = (unsigned short)libconfig->setting_get_int(t)) > 10000 ) { ShowWarning("itemdb_read_packages: invalid rate (%d) for item '%s' in package '%s'!\n",rate,itname,config_setting_name(itg)); @@ -1048,7 +1053,10 @@ void itemdb_read_packages(void) { if( ( t = libconfig->setting_get_member(it, "Named")) && libconfig->setting_get_bool(t) ) named = true; - + + if( ( t = libconfig->setting_get_member(it, "ForceSerial")) && libconfig->setting_get_bool(t) ) + force_serial = true; + if( !( t = libconfig->setting_get_member(it, "Random") ) ) { ShowWarning("itemdb_read_packages: missing 'Random' field for item '%s' in package '%s', defaulting to must!\n",itname,config_setting_name(itg)); gid = 0; @@ -1061,15 +1069,16 @@ void itemdb_read_packages(void) { itemdb->packages[count].must_items[m].hours = expire; itemdb->packages[count].must_items[m].announce = announce == true ? 1 : 0; itemdb->packages[count].must_items[m].named = named == true ? 1 : 0; + itemdb->packages[count].must_items[m].force_serial = force_serial == true ? 1 : 0; m++; } else { int gidx = gid - 1; - + r = itemdb->packages[count].random_groups[gidx].random_qty; - + if( prev[gidx] ) prev[gidx]->next = &itemdb->packages[count].random_groups[gidx].random_list[r]; - + itemdb->packages[count].random_groups[gidx].random_list[r].id = data ? data->nameid : 0; itemdb->packages[count].random_groups[gidx].random_list[r].qty = icount; if( (itemdb->packages[count].random_groups[gidx].random_list[r].rate = rate) == 10000 ) { @@ -1078,18 +1087,18 @@ void itemdb_read_packages(void) { itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire; itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0; itemdb->packages[count].random_groups[gidx].random_list[r].named = named == true ? 1 : 0; + itemdb->packages[count].random_groups[gidx].random_list[r].force_serial = force_serial == true ? 1 : 0; itemdb->packages[count].random_groups[gidx].random_qty += 1; - + prev[gidx] = &itemdb->packages[count].random_groups[gidx].random_list[r]; } - } - + for(r = 0; r < highest_gcount; r++) { if( prev[r] ) prev[r]->next = &itemdb->packages[count].random_groups[r].random_list[0]; } - + for( r = 0; r < itemdb->packages[count].random_qty; r++ ) { if( itemdb->packages[count].random_groups[r].random_qty == 1 ) { //item packages don't stop looping until something comes out of them, so if you have only one item in it the drop is guaranteed. @@ -1098,11 +1107,9 @@ void itemdb_read_packages(void) { itemdb->packages[count].random_groups[r].random_list[0].rate = 10000; } } - count++; } - - + aFree(must); aFree(random); for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++ ) { @@ -1111,12 +1118,12 @@ void itemdb_read_packages(void) { aFree(rgroups); aFree(rgroup); aFree(prev); - + libconfig->destroy(&item_packages_conf); if( HCache->enabled ) itemdb->write_cached_packages(config_filename); - + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename); } @@ -1129,7 +1136,7 @@ void itemdb_read_chains(void) { const char *config_filename = "db/pre-re/item_chain.conf"; // FIXME hardcoded name #endif int i = 0, count = 0; - + if (libconfig->read_file(&item_chain_conf, config_filename)) { ShowError("can't read %s\n", config_filename); return; @@ -1137,7 +1144,7 @@ void itemdb_read_chains(void) { CREATE(itemdb->chains, struct item_chain, libconfig->setting_length(item_chain_conf.root)); itemdb->chain_count = (unsigned short)libconfig->setting_length(item_chain_conf.root); - + #ifdef ENABLE_CASE_CHECK script->parser_current_file = config_filename; #endif // ENABLE_CASE_CHECK @@ -1147,12 +1154,12 @@ void itemdb_read_chains(void) { const char *name = config_setting_name(itc); int c = 0; config_setting_t *entry = NULL; - + script->set_constant2(name,i-1,0); itemdb->chains[count].qty = (unsigned short)libconfig->setting_length(itc); - + CREATE(itemdb->chains[count].items, struct item_chain_entry, libconfig->setting_length(itc)); - + while( (entry = libconfig->setting_get_elem(itc,c++)) ) { const char *itname = config_setting_name(entry); if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) { @@ -1160,32 +1167,32 @@ void itemdb_read_chains(void) { ShowWarning("itemdb_read_chains: unknown item ID '%d' in chain '%s'!\n",atoi(itname+2),name); } else if( !( data = itemdb->name2id(itname) ) ) ShowWarning("itemdb_read_chains: unknown item '%s' in chain '%s'!\n",itname,name); - + if( prev ) prev->next = &itemdb->chains[count].items[c - 1]; - + itemdb->chains[count].items[c - 1].id = data ? data->nameid : 0; itemdb->chains[count].items[c - 1].rate = data ? libconfig->setting_get_int(entry) : 0; - + prev = &itemdb->chains[count].items[c - 1]; } - + if( prev ) prev->next = &itemdb->chains[count].items[0]; - + count++; } #ifdef ENABLE_CASE_CHECK script->parser_current_file = NULL; #endif // ENABLE_CASE_CHECK - + libconfig->destroy(&item_chain_conf); - + if( !script->get_constant("ITMCHAIN_ORE",&i) ) ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_ORE' chain to link to cache!\n"); else itemdb->chain_cache[ECC_ORE] = i; - + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename); } @@ -1194,21 +1201,19 @@ void itemdb_read_chains(void) { **/ 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; } /** @@ -1217,41 +1222,38 @@ int itemdb_combo_split_atoi (char *str, int *val) { void itemdb_read_combos() { uint32 lines = 0, count = 0; char line[1024]; - char filepath[256]; FILE* fp; - + sprintf(filepath, "%s/%s", map->db_path, DBPATH"item_combo_db.txt"); - + if ((fp = fopen(filepath, "r")) == NULL) { ShowError("itemdb_read_combos: File not found \"%s\".\n", filepath); 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, filepath); continue; } - + str[0] = p; p = strchr(p,','); *p = '\0'; @@ -1260,12 +1262,12 @@ void itemdb_read_combos() { 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, filepath); 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, filepath); @@ -1274,12 +1276,12 @@ void itemdb_read_combos() { int items[MAX_ITEMS_PER_COMBO]; int v = 0, retcount = 0; struct item_combo *combo = NULL; - + 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, filepath); continue; } - + /* validate */ for(v = 0; v < retcount; v++) { if( !itemdb->exists(items[v]) ) { @@ -1290,11 +1292,11 @@ void itemdb_read_combos() { /* failed at some item */ if( v < retcount ) continue; - + RECREATE(itemdb->combos, struct item_combo*, ++itemdb->combo_count); - + CREATE(combo, struct item_combo, 1); - + combo->count = retcount; combo->script = script->parse(str[1], filepath, lines, 0, NULL); combo->id = itemdb->combo_count - 1; @@ -1302,37 +1304,28 @@ void itemdb_read_combos() { for( v = 0; v < retcount; v++ ) { combo->nameid[v] = items[v]; } - + itemdb->combos[itemdb->combo_count - 1] = combo; - + /* populate the items to refer to this combo */ for( v = 0; v < retcount; v++ ) { struct item_data * it; int index; - + it = itemdb->exists(items[v]); - index = it->combos_count; - RECREATE(it->combos, struct item_combo*, ++it->combos_count); - it->combos[index] = combo; } - } - count++; } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count); - + return; } - - /*====================================== * Applies gender restrictions according to settings. [Skotlex] *======================================*/ @@ -1480,7 +1473,7 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { entry->flag.available = 1; entry->view_id = 0; } - + entry->sex = itemdb->gendercheck(entry); //Apply gender filtering. // Validated. Finally insert it @@ -1583,14 +1576,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1; SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0; SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 22, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 23, &data, NULL); id.delay = data ? atoi(data) : 0; - SQL->GetData(handle, 24, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE; - SQL->GetData(handle, 25, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0; - SQL->GetData(handle, 26, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE; - SQL->GetData(handle, 27, &data, NULL); id.item_usage.override = data ? atoi(data) : 0; - SQL->GetData(handle, 28, &data, NULL); id.stack.amount = data ? atoi(data) : 0; - SQL->GetData(handle, 29, &data, NULL); + SQL->GetData(handle, 22, &data, NULL); id.flag.force_serial = data && atoi(data) ? 1 : 0; + SQL->GetData(handle, 23, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0; + SQL->GetData(handle, 24, &data, NULL); id.delay = data ? atoi(data) : 0; + SQL->GetData(handle, 25, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE; + SQL->GetData(handle, 26, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0; + SQL->GetData(handle, 27, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE; + SQL->GetData(handle, 28, &data, NULL); id.item_usage.override = data ? atoi(data) : 0; + SQL->GetData(handle, 29, &data, NULL); id.stack.amount = data ? atoi(data) : 0; + SQL->GetData(handle, 30, &data, NULL); if (data) { int stack_flag = atoi(data); id.stack.inventory = (stack_flag&1)!=0; @@ -1598,15 +1592,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { id.stack.storage = (stack_flag&4)!=0; id.stack.guildstorage = (stack_flag&8)!=0; } - SQL->GetData(handle, 30, &data, NULL); + SQL->GetData(handle, 31, &data, NULL); if (data) { id.view_id = atoi(data); if (id.view_id) id.flag.available = 1; } - SQL->GetData(handle, 31, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 32, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 33, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 32, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 33, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 34, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; return itemdb->validate_entry(&id, n, source); } @@ -1657,6 +1651,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) * BindOnEquip: (true or false) * BuyingStore: (true or false) * Delay: Delay to use item + * ForceSerial: (true or false) * Trade: { * override: Group to override * nodrop: (true or false) @@ -1790,7 +1785,10 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if( (t = libconfig->setting_get_member(it, "BindOnEquip")) ) id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0; - + + if( (t = libconfig->setting_get_member(it, "ForceSerial")) ) + id.flag.force_serial = libconfig->setting_get_bool(t) ? 1 : 0; + if ( (t = libconfig->setting_get_member(it, "BuyingStore")) ) id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0; @@ -1903,7 +1901,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) id.flag.available = 1; id.view_id = i32; } - + if( libconfig->setting_lookup_string(it, "Script", &str) ) id.script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; @@ -1947,7 +1945,7 @@ int itemdb_readdb_libconfig(const char *filename) { config_setting_t *itdb, *it; char filepath[256]; int i = 0, count = 0; - + sprintf(filepath, "%s/%s", map->db_path, filename); memset(&duplicate,0,sizeof(duplicate)); if( libconfig->read_file(&item_db_conf, filepath) || !(itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) ) { @@ -1972,7 +1970,7 @@ int itemdb_readdb_libconfig(const char *filename) { } libconfig->destroy(&item_db_conf); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); - + return count; } @@ -1985,14 +1983,14 @@ int itemdb_readdb_libconfig(const char *filename) { */ int itemdb_readdb_sql(const char *tablename) { int i = 0, count = 0; - + // retrieve all rows from the item database if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `id`, `name_english`, `name_japanese`, `type`," " `price_buy`, `price_sell`, `weight`, `atk`," " `matk`, `defence`, `range`, `slots`," " `equip_jobs`, `equip_upper`, `equip_genders`, `equip_locations`," " `weapon_level`, `equip_level_min`, `equip_level_max`, `refineable`," - " `view`, `bindonequip`, `buyingstore`, `delay`," + " `view`, `bindonequip`, `forceserial`, `buyingstore`, `delay`," " `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`," " `stack_amount`, `stack_flag`, `sprite`, `script`," " `equip_script`, `unequip_script`" @@ -2030,7 +2028,7 @@ uint64 itemdb_unique_id(struct map_session_data *sd) { void itemdb_read(bool minimal) { int i; DBData prev; - + if (map->db_use_sql_item_db) { const char* item_db_name[] = { map->item_db_db, @@ -2047,7 +2045,7 @@ void itemdb_read(bool minimal) { for(i = 0; i < ARRAYLENGTH(filename); i++) itemdb->readdb_libconfig(filename[i]); } - + for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) { if( itemdb->array[i] ) { if( itemdb->names->put(itemdb->names,DB->str2key(itemdb->array[i]->name),DB->ptr2data(itemdb->array[i]),&prev) ) { @@ -2056,7 +2054,7 @@ void itemdb_read(bool minimal) { } } } - + if (minimal) return; @@ -2141,7 +2139,7 @@ void itemdb_clear(bool total) { if( itemdb->array[i] ) itemdb->destroy_item_data(itemdb->array[i], 1); } - + if( itemdb->groups ) { for( i = 0; i < itemdb->group_count; i++ ) { @@ -2153,7 +2151,7 @@ void itemdb_clear(bool total) { itemdb->groups = NULL; itemdb->group_count = 0; - + if (itemdb->chains) { for (i = 0; i < itemdb->chain_count; i++) { if (itemdb->chains[i].items) @@ -2164,7 +2162,7 @@ void itemdb_clear(bool total) { itemdb->chains = NULL; itemdb->chain_count = 0; - + if (itemdb->packages) { for (i = 0; i < itemdb->package_count; i++) { if (itemdb->packages[i].random_groups) { @@ -2180,7 +2178,7 @@ void itemdb_clear(bool total) { itemdb->packages = NULL; } itemdb->package_count = 0; - + if (itemdb->combos) { for (i = 0; i < itemdb->combo_count; i++) { if (itemdb->combos[i]->script) // Check if script was loaded @@ -2192,28 +2190,28 @@ void itemdb_clear(bool total) { itemdb->combos = NULL; itemdb->combo_count = 0; - + if (total) return; - + itemdb->other->clear(itemdb->other, itemdb->final_sub); - + memset(itemdb->array, 0, sizeof(itemdb->array)); - - db_clear(itemdb->names); + db_clear(itemdb->names); } + void itemdb_reload(void) { struct s_mapiterator* iter; struct map_session_data* sd; int i,d,k; - + itemdb->clear(false); // read new data itemdb->read(false); - + //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++ ) { @@ -2234,7 +2232,7 @@ void itemdb_reload(void) { if (k == MAX_SEARCH) continue; - + if (id->mob[k].id != i && k != MAX_SEARCH - 1) memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); id->mob[k].chance = entry->dropitem[d].p; @@ -2264,7 +2262,7 @@ void itemdb_reload(void) { void itemdb_name_constants(void) { DBIterator *iter = db_iterator(itemdb->names); struct item_data *data; - + #ifdef ENABLE_CASE_CHECK script->parser_current_file = "Item Database (Likely an invalid or conflicting AegisName)"; #endif // ENABLE_CASE_CHECK @@ -2278,7 +2276,7 @@ void itemdb_name_constants(void) { } void do_final_itemdb(void) { itemdb->clear(true); - + itemdb->other->destroy(itemdb->other, itemdb->final_sub); itemdb->destroy_item_data(&itemdb->dummy, 0); db_destroy(itemdb->names); @@ -2295,14 +2293,14 @@ void do_init_itemdb(bool minimal) { return; clif->cashshop_load(); - + /** it failed? we disable it **/ if( !clif->parse_roulette_db() ) battle_config.feature_roulette = 0; } void itemdb_defaults(void) { itemdb = &itemdb_s; - + itemdb->init = do_init_itemdb; itemdb->final = do_final_itemdb; itemdb->reload = itemdb_reload; diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 1d811e3cb..a3edd451e 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -5,18 +5,14 @@ #ifndef MAP_ITEMDB_H #define MAP_ITEMDB_H -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/mmo.h" // ITEM_NAME_LENGTH -#include "../common/sql.h" +/* #include "map/map.h" */ +#include "common/hercules.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/mmo.h" // ITEM_NAME_LENGTH +#include "common/sql.h" -/** - * Declarations - **/ -struct item_group; -struct item_package; +struct script_code; /** * Defines @@ -371,6 +367,63 @@ enum ItemNouseRestrictions { INR_ALL = 0x1 ///< Sum of all the above values }; +struct item_combo { + struct script_code *script; + unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ + unsigned char count; + unsigned short id;/* id of this combo */ +}; + +struct item_group { + unsigned short id; + unsigned short *nameid; + unsigned short qty; +}; + +struct item_chain_entry { + unsigned short id; + unsigned short rate; + struct item_chain_entry *next; +}; + +struct item_chain { + struct item_chain_entry *items; + unsigned short qty; +}; + +struct item_package_rand_entry { + unsigned short id; + unsigned short qty; + unsigned short rate; + unsigned short hours; + unsigned int announce : 1; + unsigned int named : 1; + unsigned int force_serial: 1; + struct item_package_rand_entry *next; +}; + +struct item_package_must_entry { + unsigned short id; + unsigned short qty; + unsigned short hours; + unsigned int announce : 1; + unsigned int named : 1; + unsigned int force_serial : 1; +}; + +struct item_package_rand_group { + struct item_package_rand_entry *random_list; + unsigned short random_qty; +}; + +struct item_package { + unsigned short id; + struct item_package_rand_group *random_groups; + struct item_package_must_entry *must_items; + unsigned short random_qty; + unsigned short must_qty; +}; + struct item_data { uint16 nameid; char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; @@ -415,6 +468,7 @@ struct item_data { unsigned buyingstore : 1; unsigned bindonequip : 1; unsigned keepafteruse : 1; + unsigned force_serial : 1; } flag; struct {// item stacking limitation unsigned short amount; @@ -440,61 +494,6 @@ struct item_data { unsigned int hdatac; }; -struct item_combo { - struct script_code *script; - unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ - unsigned char count; - unsigned short id;/* id of this combo */ -}; - -struct item_group { - unsigned short id; - unsigned short *nameid; - unsigned short qty; -}; - -struct item_chain_entry { - unsigned short id; - unsigned short rate; - struct item_chain_entry *next; -}; - -struct item_chain { - struct item_chain_entry *items; - unsigned short qty; -}; - -struct item_package_rand_entry { - unsigned short id; - unsigned short qty; - unsigned short rate; - unsigned short hours; - unsigned int announce : 1; - unsigned int named : 1; - struct item_package_rand_entry *next; -}; - -struct item_package_must_entry { - unsigned short id; - unsigned short qty; - unsigned short hours; - unsigned int announce : 1; - unsigned int named : 1; -}; - -struct item_package_rand_group { - struct item_package_rand_entry *random_list; - unsigned short random_qty; -}; - -struct item_package { - unsigned short id; - struct item_package_rand_group *random_groups; - struct item_package_must_entry *must_items; - unsigned short random_qty; - unsigned short must_qty; -}; - #define itemdb_name(n) (itemdb->search(n)->name) #define itemdb_jname(n) (itemdb->search(n)->jname) #define itemdb_type(n) (itemdb->search(n)->type) @@ -619,10 +618,10 @@ struct itemdb_interface { bool (*lookup_const) (const config_setting_t *it, const char *name, int *value); }; -struct itemdb_interface *itemdb; - #ifdef HERCULES_CORE void itemdb_defaults(void); #endif // HERCULES_CORE +HPShared struct itemdb_interface *itemdb; + #endif /* MAP_ITEMDB_H */ diff --git a/src/map/log.c b/src/map/log.c index f18efbfb7..a74cb27c5 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -6,23 +6,24 @@ #include "log.h" +#include "map/battle.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/sql.h" // SQL_INNODB +#include "common/strlib.h" +#include "common/HPM.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "itemdb.h" -#include "map.h" -#include "mob.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/sql.h" // SQL_INNODB -#include "../common/strlib.h" -#include "../common/HPM.h" - struct log_interface log_s; +struct log_interface *logs; /// obtain log type character for item/zeny logs char log_picktype2char(e_log_pick_type type) { @@ -53,7 +54,6 @@ char log_picktype2char(e_log_pick_type type) { return 'X'; } - /// obtain log type character for chat logs char log_chattype2char(e_log_chat_type type) { switch( type ) { @@ -69,7 +69,6 @@ char log_chattype2char(e_log_chat_type type) { return 'O'; } - /// check if this item should be logged according the settings bool should_log_item(int nameid, int amount, int refine, struct item_data *id) { int filter = logs->config.filter; @@ -111,7 +110,7 @@ void log_branch_sub_txt(struct map_session_data* sd) { char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_branch, "a") ) == NULL ) return; time(&curtime); @@ -144,7 +143,7 @@ void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_pick, "a") ) == NULL ) return; time(&curtime); @@ -173,7 +172,6 @@ void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid)); } - /// logs item transactions (monsters) void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { nullpo_retv(md); @@ -191,7 +189,7 @@ void log_zeny_sub_txt(struct map_session_data* sd, e_log_pick_type type, struct char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_zeny, "a") ) == NULL ) return; time(&curtime); @@ -221,7 +219,7 @@ void log_mvpdrop_sub_txt(struct map_session_data* sd, int monster_id, int* log_m char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_mvpdrop,"a") ) == NULL ) return; time(&curtime); @@ -242,7 +240,7 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp) void log_atcommand_sub_sql(struct map_session_data* sd, const char* message) { SqlStmt* stmt; - + stmt = SQL->StmtMalloc(logs->mysql_handle); if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) @@ -259,7 +257,7 @@ void log_atcommand_sub_txt(struct map_session_data* sd, const char* message) { char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_gm, "a") ) == NULL ) return; time(&curtime); @@ -297,7 +295,7 @@ void log_npc_sub_txt(struct map_session_data *sd, const char *message) { char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_npc, "a") ) == NULL ) return; time(&curtime); @@ -318,7 +316,7 @@ void log_npc(struct map_session_data* sd, const char* message) void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message) { SqlStmt* stmt; - + stmt = SQL->StmtMalloc(logs->mysql_handle); if( SQL_SUCCESS != SQL->StmtPrepare(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', ?, ?)", logs->config.log_chat, logs->chattype2char(type), type_id, src_charid, src_accid, mapname, x, y) || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) @@ -335,7 +333,7 @@ void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src char timestring[255]; time_t curtime; FILE* logfp; - + if( ( logfp = fopen(logs->config.log_chat, "a") ) == NULL ) return; time(&curtime); @@ -362,12 +360,12 @@ void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, void log_sql_init(void) { // log db connection logs->mysql_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",logs->db_name,logs->db_ip); if ( SQL_ERROR == SQL->Connect(logs->mysql_handle, logs->db_id, logs->db_pw, logs->db_ip, logs->db_port, logs->db_name) ) exit(EXIT_FAILURE); ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", logs->db_name); - + if (map->default_codepage[0] != '\0') if ( SQL_ERROR == SQL->SetEncoding(logs->mysql_handle, map->default_codepage) ) Sql_ShowDebug(logs->mysql_handle); @@ -388,7 +386,6 @@ void log_set_defaults(void) { logs->config.amount_items_log = 100; } - int log_config_read(const char* cfgName) { static int count = 0; char line[1024], w1[1024], w2[1024]; @@ -505,7 +502,7 @@ void log_config_complete(void) { } void log_defaults(void) { logs = &log_s; - + sprintf(logs->db_ip,"127.0.0.1"); sprintf(logs->db_id,"ragnarok"); sprintf(logs->db_pw,"ragnarok"); @@ -514,7 +511,7 @@ void log_defaults(void) { logs->db_port = 3306; logs->mysql_handle = NULL; /* */ - + logs->pick_pc = log_pick_pc; logs->pick_mob = log_pick_mob; logs->zeny = log_zeny; @@ -523,7 +520,7 @@ void log_defaults(void) { logs->atcommand = log_atcommand; logs->branch = log_branch; logs->mvpdrop = log_mvpdrop; - + /* will be modified in a few seconds once loading is complete. */ logs->pick_sub = log_pick_sub_txt; logs->zeny_sub = log_zeny_sub_txt; diff --git a/src/map/log.h b/src/map/log.h index b4b8b84f4..4b2b5d4d6 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -5,8 +5,8 @@ #ifndef MAP_LOG_H #define MAP_LOG_H -#include "../common/cbasetypes.h" -#include "../common/sql.h" +#include "common/hercules.h" +#include "common/sql.h" /** * Declarations @@ -129,10 +129,10 @@ struct log_interface { bool (*should_log_item) (int nameid, int amount, int refine, struct item_data *id); }; -struct log_interface *logs; - #ifdef HERCULES_CORE void log_defaults(void); #endif // HERCULES_CORE +HPShared struct log_interface *logs; + #endif /* MAP_LOG_H */ diff --git a/src/map/mail.c b/src/map/mail.c index 7ba7d7470..e952d9b63 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -6,18 +6,20 @@ #include "mail.h" +#include "map/atcommand.h" +#include "map/clif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/pc.h" +#include "map/storage.h" +#include "common/nullpo.h" +#include "common/showmsg.h" + #include <time.h> #include <string.h> -#include "atcommand.h" -#include "clif.h" -#include "itemdb.h" -#include "log.h" -#include "pc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" - struct mail_interface mail_s; +struct mail_interface *mail; void mail_clear(struct map_session_data *sd) { @@ -36,7 +38,7 @@ int mail_removeitem(struct map_session_data *sd, short flag) if( sd->mail.amount ) { if (flag) // Item send - pc->delitem(sd, sd->mail.index, sd->mail.amount, 1, 0, LOG_TYPE_MAIL); + pc->delitem(sd, sd->mail.index, sd->mail.amount, 1, DELITEM_NORMAL, LOG_TYPE_MAIL); else clif->additem(sd, sd->mail.index, sd->mail.amount, 0); } @@ -81,7 +83,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { if( idx < 0 || idx >= MAX_INVENTORY ) return 1; - if( amount < 0 || amount > sd->status.inventory[idx].amount ) + 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)) || @@ -120,6 +122,8 @@ bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg) memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); msg->item.amount = sd->mail.amount; + if (msg->item.amount != sd->mail.amount) // check for amount overflow + return false; } else memset(&msg->item, 0x00, sizeof(struct item)); @@ -151,7 +155,7 @@ int mail_openmail(struct map_session_data *sd) { nullpo_ret(sd); - if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading) return 0; clif->mail_window(sd->fd, 0); @@ -191,7 +195,7 @@ bool mail_invalid_operation(struct map_session_data *sd) { void mail_defaults(void) { mail = &mail_s; - + mail->clear = mail_clear; mail->removeitem = mail_removeitem; mail->removezeny = mail_removezeny; diff --git a/src/map/mail.h b/src/map/mail.h index db49ca39e..128b1fbaa 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -5,7 +5,7 @@ #ifndef MAP_MAIL_H #define MAP_MAIL_H -#include "../common/cbasetypes.h" +#include "common/hercules.h" struct item; struct mail_message; @@ -23,10 +23,10 @@ struct mail_interface { bool (*invalid_operation) (struct map_session_data *sd); }; -struct mail_interface *mail; - #ifdef HERCULES_CORE void mail_defaults(void); #endif // HERCULES_CORE +HPShared struct mail_interface *mail; + #endif /* MAP_MAIL_H */ diff --git a/src/map/map.c b/src/map/map.c index c79d49c3e..fe0922063 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -4,65 +4,64 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL #include "map.h" +#include "map/HPMmap.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/npc.h" // npc_setcells(), npc_unsetcells() +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/console.h" +#include "common/core.h" +#include "common/ers.h" +#include "common/grfio.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // WFIFO*() +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> - -#include "HPMmap.h" -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "npc.h" // npc_setcells(), npc_unsetcells() -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/console.h" -#include "../common/core.h" -#include "../common/ers.h" -#include "../common/grfio.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // WFIFO*() -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - #ifndef _WIN32 #include <unistd.h> #endif @@ -70,6 +69,9 @@ struct map_interface map_s; struct mapit_interface mapit_s; +struct map_interface *map; +struct mapit_interface *mapit; + /*========================================== * server player count (of all mapservers) *------------------------------------------*/ @@ -109,7 +111,7 @@ int map_usercount(void) { *------------------------------------------*/ int map_freeblock (struct block_list *bl) { nullpo_retr(map->block_free_lock, bl); - + if (map->block_free_lock == 0) { if( bl->type == BL_ITEM ) ers_free(map->flooritem_ers, bl); @@ -117,10 +119,9 @@ int map_freeblock (struct block_list *bl) { aFree(bl); bl = NULL; } else { - if( map->block_free_count >= map->block_free_list_size ) map_block_free_expand(); - + map->block_free[map->block_free_count++] = bl; } @@ -137,7 +138,6 @@ int map_freeblock_lock (void) { * Remove the lock on map_bl *------------------------------------------*/ int map_freeblock_unlock (void) { - if ((--map->block_free_lock) == 0) { int i; for (i = 0; i < map->block_free_count; i++) { @@ -373,8 +373,6 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) { ) { sc->data[SC_PROPERTYWALK]->val3++; } - - } /* Guild Aura Moving */ if( bl->type == BL_PC && ((TBL_PC*)bl)->state.gmaster_flag ) { @@ -838,7 +836,7 @@ static int bl_vgetall_inshootrange(struct block_list *bl, va_list args) if (!check_distance_bl(center, bl, range)) return 0; #endif - if (!path->search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL)) + if (!path->search_long(NULL, center, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL)) return 0; return 1; } @@ -1193,7 +1191,7 @@ static int bl_vgetall_inpath(struct block_list *bl, va_list args) if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well. return 0; - if ( k > magnitude2 && !path->search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) ) + if ( k > magnitude2 && !path->search_long(NULL, NULL, m, x0, y0, xi, yi, CELL_CHKWALL) ) return 0; //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 @@ -1364,7 +1362,6 @@ int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data) { return 1; } - if (pet->search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0) intif->delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); @@ -1395,7 +1392,7 @@ 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(int16 m,int16 *x,int16 *y,int stack) { +int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int stack) { int free_cell,i,j; int free_cells[9][2]; @@ -1405,7 +1402,7 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) { for(j=-1;j<=1;j++){ if(j+*x<0 || j+*x>=map->list[m].xs) continue; - if(map->getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map->getcell(m,j+*x,i+*y,CELL_CHKICEWALL)) + if (map->getcell(m, bl, j + *x, i + *y, CELL_CHKNOPASS) && !map->getcell(m, bl, 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, 0) > stack) @@ -1422,7 +1419,6 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) { return 1; } - int map_count_sub(struct block_list *bl,va_list ap) { return 1; } @@ -1464,7 +1460,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 //No range? Return the target cell then.... *x = bx; *y = by; - return map->getcell(m,*x,*y,CELL_CHKREACH); + return map->getcell(m, src, *x, *y, CELL_CHKREACH); } if (rx >= 0 && ry >= 0) { @@ -1482,7 +1478,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 if (*x == bx && *y == by) continue; //Avoid picking the same target tile. - if (map->getcell(m,*x,*y,CELL_CHKREACH)) { + if (map->getcell(m, src, *x, *y, CELL_CHKREACH)) { if(flag&2 && !unit->can_reach_pos(src, *x, *y, 1)) continue; if(flag&4) { @@ -1509,7 +1505,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1 * flag: * 0x1 - only count standing units *------------------------------------------*/ -bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) +bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag) { uint8 dir = 6; int16 tx = *x; @@ -1528,7 +1524,7 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) if(dir%2 == 0 && costrange%MOVE_COST == 0) { tx = *x+dx*(costrange/MOVE_COST); ty = *y+dy*(costrange/MOVE_COST); - if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) { + if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) { *x = tx; *y = ty; return true; @@ -1538,7 +1534,7 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) else if(dir%2 == 1 && costrange%MOVE_DIAGONAL_COST == 0) { tx = *x+dx*(costrange/MOVE_DIAGONAL_COST); ty = *y+dy*(costrange/MOVE_DIAGONAL_COST); - if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) { + if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) { *x = tx; *y = ty; return true; @@ -1548,14 +1544,14 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) else if(dir%2 == 1 && costrange%MOVE_COST == 4) { tx = *x+dx*((dir%4==3)?(costrange/MOVE_COST):1); ty = *y+dy*((dir%4==1)?(costrange/MOVE_COST):1); - if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) { + if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) { *x = tx; *y = ty; return true; } tx = *x+dx*((dir%4==1)?(costrange/MOVE_COST):1); ty = *y+dy*((dir%4==3)?(costrange/MOVE_COST):1); - if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) { + if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) { *x = tx; *y = ty; return true; @@ -1589,19 +1585,19 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) * @first_charid, @second_charid, @third_charid, looting priority * @flag: &1 MVP item. &2 do stacking check. *------------------------------------------*/ -int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags) +int map_addflooritem(const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags) { int r; struct flooritem_data *fitem=NULL; nullpo_ret(item_data); - if (!map->searchrandfreecell(m, &x, &y, (flags&2)?1:0)) + if (!map->searchrandfreecell(m, bl, &x, &y, (flags&2)?1:0)) return 0; r=rnd(); fitem = ers_alloc(map->flooritem_ers, struct flooritem_data); - + fitem->bl.type = BL_ITEM; fitem->bl.prev = fitem->bl.next = NULL; fitem->bl.m = m; @@ -1787,7 +1783,7 @@ int map_quit(struct map_session_data *sd) { //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->expiration_tid != INVALID_TIMER ) timer->delete(sd->expiration_tid,pc->expiration_timer); @@ -1800,7 +1796,7 @@ int map_quit(struct map_session_data *sd) { if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */ bg->team_leave(sd,BGTL_QUIT); - if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !channel->config->closing) + if (sd->state.autotrade && core->runflag != MAPSERVER_ST_SHUTDOWN && !channel->config->closing) pc->autotrade_update(sd,PAUC_REMOVE); skill->cooldown_save(sd); @@ -1844,13 +1840,13 @@ int map_quit(struct map_session_data *sd) { 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 ); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } // 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->state.storage_flag == STORAGE_FLAG_NORMAL ) sd->state.storage_flag = STORAGE_FLAG_CLOSED; // No need to Double Save Storage on Quit. if( sd->ed ) { elemental->clean_effect(sd->ed); @@ -1880,7 +1876,7 @@ int map_quit(struct map_session_data *sd) { if( sd->state.vending ) { idb_remove(vending->db, sd->status.char_id); } - + party->booking_delete(sd); // Party Booking [Spiria] pc->makesavestatus(sd); pc->clean_skilltree(sd); @@ -2565,8 +2561,8 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y) 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 ); + } while ((map->getcell(bl->m, bl, xi, yi, CELL_CHKNOPASS) || !path->search(NULL, bl, bl->m, bl->x, bl->y, xi, yi, 1, CELL_CHKNOREACH)) + && (++i)<100); if (i < 100) { *x = xi; @@ -2638,11 +2634,11 @@ void map_cellfromcache(struct map_data *m) { /*========================================== * Confirm if celltype in (m,x,y) match the one given in cellchk *------------------------------------------*/ -int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk) { - return (m < 0 || m >= map->count) ? 0 : map->list[m].getcellp(&map->list[m],x,y,cellchk); +int map_getcell(int16 m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) { + return (m < 0 || m >= map->count) ? 0 : map->list[m].getcellp(&map->list[m], bl, x, y, cellchk); } -int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) { +int map_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) { struct mapcell cell; nullpo_ret(m); @@ -2661,14 +2657,11 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) { // base gat type checks case CELL_CHKWALL: return (!cell.walkable && !cell.shootable); - case CELL_CHKWATER: return (cell.water); - case CELL_CHKCLIFF: return (!cell.walkable && cell.shootable); - // base cell type checks case CELL_CHKNPC: return (cell.npc); @@ -2713,12 +2706,13 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) { } /* [Ind/Hercules] */ -int map_sub_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) { +int map_sub_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) { map->cellfromcache(m); m->getcellp = map->getcellp; m->setcell = map->setcell; - return m->getcellp(m,x,y,cellchk); + return m->getcellp(m, bl, x, y, cellchk); } + /*========================================== * Change the type/flags of a map cell * 'cell' - which flag to modify @@ -2806,7 +2800,7 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable if( (iwall = (struct iwall_data *)strdb_get(map->iwall_db, wall_name)) != NULL ) return false; // Already Exists - if( map->getcell(m, x, y, CELL_CHKNOREACH) ) + if (map->getcell(m, NULL, x, y, CELL_CHKNOREACH)) return false; // Starting cell problem CREATE(iwall, struct iwall_data, 1); @@ -2821,13 +2815,13 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable for( i = 0; i < size; i++ ) { map->iwall_nextxy(x, y, dir, i, &x1, &y1); - if( map->getcell(m, x1, y1, CELL_CHKNOREACH) ) + if (map->getcell(m, NULL, x1, y1, CELL_CHKNOREACH)) break; // Collision map->list[m].setcell(m, x1, y1, CELL_WALKABLE, false); map->list[m].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, NULL, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); } iwall->size = i; @@ -2854,7 +2848,7 @@ void map_iwall_get(struct map_session_data *sd) { 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); + clif->changemapcell(sd->fd, iwall->m, x1, y1, map->getcell(iwall->m, &sd->bl, x1, y1, CELL_GETTYPE), SELF); } } dbi_destroy(iter); @@ -2874,7 +2868,7 @@ void map_iwall_remove(const char *wall_name) map->list[iwall->m].setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true); map->list[iwall->m].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, NULL, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); } map->list[iwall->m].iwall_num--; @@ -3042,7 +3036,6 @@ int map_readfromcache(struct map_data *m, char *buffer) { return 0; // Not found } - int map_addmap(const char* mapname) { map->list[map->count].instance_id = -1; mapindex->getmapname(mapname, map->list[map->count++].name); @@ -3079,38 +3072,38 @@ int map_delmap(char* mapname) { **/ void map_zone_clear_single(struct map_zone_data *zone) { int i; - + for(i = 0; i < zone->disabled_skills_count; i++) { aFree(zone->disabled_skills[i]); } - + if( zone->disabled_skills ) aFree(zone->disabled_skills); - + if( zone->disabled_items ) aFree(zone->disabled_items); - + if( zone->cant_disable_items ) aFree(zone->cant_disable_items); - + for(i = 0; i < zone->mapflags_count; i++) { aFree(zone->mapflags[i]); } - + if( zone->mapflags ) aFree(zone->mapflags); - + for(i = 0; i < zone->disabled_commands_count; i++) { aFree(zone->disabled_commands[i]); } - + if( zone->disabled_commands ) aFree(zone->disabled_commands); - + for(i = 0; i < zone->capped_skills_count; i++) { aFree(zone->capped_skills[i]); } - + if( zone->capped_skills ) aFree(zone->capped_skills); } @@ -3120,11 +3113,11 @@ void map_zone_clear_single(struct map_zone_data *zone) { void map_zone_db_clear(void) { struct map_zone_data *zone; DBIterator *iter = db_iterator(map->zone_db); - + for(zone = dbi_first(iter); dbi_exists(iter); zone = dbi_next(iter)) { map->zone_clear_single(zone); } - + dbi_destroy(iter); db_destroy(map->zone_db);/* will aFree(zone) */ @@ -3242,10 +3235,10 @@ void do_final_maps(void) { if( map->list[i].channel ) channel->delete(map->list[i].channel); - + if( map->list[i].qi_data ) aFree(map->list[i].qi_data); - + if( map->list[i].hdata ) { for( v = 0; v < map->list[i].hdatac; v++ ) { @@ -3321,10 +3314,10 @@ void map_flags_init(void) { map->list[i].misc_damage_rate = 100; map->list[i].short_damage_rate = 100; map->list[i].long_damage_rate = 100; - + if( map->list[i].qi_data ) aFree(map->list[i].qi_data); - + map->list[i].qi_data = NULL; map->list[i].qi_count = 0; } @@ -3539,12 +3532,12 @@ int map_config_read(char *cfgName) { *ptr = '\0'; if(strcmpi(w1,"timestamp_format")==0) - safestrncpy(timestamp_format, w2, 20); + safestrncpy(showmsg->timestamp_format, w2, 20); else if(strcmpi(w1,"stdout_with_ansisequence")==0) - stdout_with_ansisequence = config_switch(w2); + showmsg->stdout_with_ansisequence = config_switch(w2) ? true : false; else if(strcmpi(w1,"console_silent")==0) { - msg_silent = atoi(w2); - if( msg_silent ) // only bother if its actually enabled + showmsg->silent = atoi(w2); + if (showmsg->silent) // only bother if its actually enabled ShowInfo("Console Silent Setting: %d\n", atoi(w2)); } else if (strcmpi(w1, "userid")==0) chrif->setuserid(w2); @@ -3594,7 +3587,7 @@ int map_config_read(char *cfgName) { else if (strcmpi(w1, "use_grf") == 0) map->enable_grf = config_switch(w2); else if (strcmpi(w1, "console_msg_log") == 0) - console_msg_log = atoi(w2);//[Ind] + showmsg->console_log = atoi(w2);//[Ind] else if (strcmpi(w1, "default_language") == 0) safestrncpy(map->default_lang_str, w2, sizeof(map->default_lang_str)); else if (strcmpi(w1, "import") == 0) @@ -3715,7 +3708,7 @@ int inter_config_read(char *cfgName) { while (fgets(line, sizeof(line), fp)) { if (line[0] == '/' && line[1] == '/') continue; - + if (sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2) < 2) continue; /* table names */ @@ -3731,8 +3724,6 @@ int inter_config_read(char *cfgName) { safestrncpy(map->mob_skill_db_db, w2, sizeof(map->mob_skill_db_db)); else if(strcmpi(w1,"mob_skill_db2_db")==0) safestrncpy(map->mob_skill_db2_db, w2, sizeof(map->mob_skill_db2_db)); - else if(strcmpi(w1,"interreg_db")==0) - safestrncpy(map->interreg_db, w2, sizeof(map->interreg_db)); /* map sql stuff */ else if(strcmpi(w1,"map_server_ip")==0) safestrncpy(map->server_ip, w2, sizeof(map->server_ip)); @@ -3749,14 +3740,38 @@ int inter_config_read(char *cfgName) { else if(strcmpi(w1,"use_sql_item_db")==0) { map->db_use_sql_item_db = config_switch(w2); ShowStatus ("Using item database as SQL: '%s'\n", w2); + if (map->db_use_sql_item_db) { + // Deprecated 2015-08-09 [Haru] + ShowWarning("Support for the SQL item database is deprecated and it will removed in future versions. " + "Please upgrade to the non-sql version as soon as possible. " + "Bug reports or pull requests concerning the SQL item database are no longer accepted.\n"); + ShowInfo("Resuming in 10 seconds...\n"); + HSleep(10); + } } else if(strcmpi(w1,"use_sql_mob_db")==0) { map->db_use_sql_mob_db = config_switch(w2); ShowStatus ("Using monster database as SQL: '%s'\n", w2); + if (map->db_use_sql_mob_db) { + // Deprecated 2015-08-09 [Haru] + ShowWarning("Support for the SQL monster database is deprecated and it will removed in future versions. " + "Please upgrade to the non-sql version as soon as possible. " + "Bug reports or pull requests concerning the SQL monster database are no longer accepted.\n"); + ShowInfo("Resuming in 10 seconds...\n"); + HSleep(10); + } } else if(strcmpi(w1,"use_sql_mob_skill_db")==0) { map->db_use_sql_mob_skill_db = config_switch(w2); ShowStatus ("Using monster skill database as SQL: '%s'\n", w2); + if (map->db_use_sql_mob_skill_db) { + // Deprecated 2015-08-09 [Haru] + ShowWarning("Support for the SQL monster skill database is deprecated and it will removed in future versions. " + "Please upgrade to the non-sql version as soon as possible. " + "Bug reports or pull requests concerning the SQL monster skill database are no longer accepted.\n"); + ShowInfo("Resuming in 10 seconds...\n"); + HSleep(10); + } } else if(strcmpi(w1,"autotrade_merchants_db")==0) safestrncpy(map->autotrade_merchants_db, w2, sizeof(map->autotrade_merchants_db)); @@ -3831,34 +3846,31 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone char newzone[MAP_ZONE_NAME_LENGTH]; struct map_zone_data *zone = NULL; int cursor, i, j; - + sprintf(newzone, "%s+%s",main->name,other->name); - + if( (zone = strdb_get(map->zone_db, newzone)) ) return zone;/* this zone has already been merged */ - + CREATE(zone, struct map_zone_data, 1); - safestrncpy(zone->name, newzone, MAP_ZONE_NAME_LENGTH); - zone->disabled_skills_count = main->disabled_skills_count + other->disabled_skills_count; zone->disabled_items_count = main->disabled_items_count + other->disabled_items_count; zone->mapflags_count = main->mapflags_count + other->mapflags_count; zone->disabled_commands_count = main->disabled_commands_count + other->disabled_commands_count; zone->capped_skills_count = main->capped_skills_count + other->capped_skills_count; - + CREATE(zone->disabled_skills, struct map_zone_disabled_skill_entry *, zone->disabled_skills_count ); - for(i = 0, cursor = 0; i < main->disabled_skills_count; i++, cursor++ ) { CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); memcpy(zone->disabled_skills[cursor], main->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); } - + for(i = 0; i < other->disabled_skills_count; i++, cursor++ ) { CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); memcpy(zone->disabled_skills[cursor], other->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); } - + for(j = 0; j < main->cant_disable_items_count; j++) { for(i = 0; i < other->disabled_items_count; i++) { if( other->disabled_items[i] == main->cant_disable_items[j] ) { @@ -3869,11 +3881,10 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone } CREATE(zone->disabled_items, int, zone->disabled_items_count ); - for(i = 0, cursor = 0; i < main->disabled_items_count; i++, cursor++ ) { zone->disabled_items[cursor] = main->disabled_items[i]; } - + for(i = 0; i < other->disabled_items_count; i++) { for(j = 0; j < main->cant_disable_items_count; j++) { if( other->disabled_items[i] == main->cant_disable_items[j] ) { @@ -3887,45 +3898,40 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone } CREATE(zone->mapflags, char *, zone->mapflags_count ); - for(i = 0, cursor = 0; i < main->mapflags_count; i++, cursor++ ) { CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); safestrncpy(zone->mapflags[cursor], main->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); } - + for(i = 0; i < other->mapflags_count; i++, cursor++ ) { CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); safestrncpy(zone->mapflags[cursor], other->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); } - + CREATE(zone->disabled_commands, struct map_zone_disabled_command_entry *, zone->disabled_commands_count); - for(i = 0, cursor = 0; i < main->disabled_commands_count; i++, cursor++ ) { CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); memcpy(zone->disabled_commands[cursor], main->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); } - + for(i = 0; i < other->disabled_commands_count; i++, cursor++ ) { CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); memcpy(zone->disabled_commands[cursor], other->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); } - + CREATE(zone->capped_skills, struct map_zone_skill_damage_cap_entry *, zone->capped_skills_count); - for(i = 0, cursor = 0; i < main->capped_skills_count; i++, cursor++ ) { CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); memcpy(zone->capped_skills[cursor], main->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry)); } - + for(i = 0; i < other->capped_skills_count; i++, cursor++ ) { CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); memcpy(zone->capped_skills[cursor], other->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry)); } - + zone->info.special = 2; - strdb_put(map->zone_db, newzone, zone); - return zone; } @@ -3934,17 +3940,17 @@ void map_zone_change2(int m, struct map_zone_data *zone) { if( map->list[m].zone == zone ) return; - + if( map->list[m].zone->info.special != 2 ) /* we don't update it for merged zones! */ map->list[m].prev_zone = map->list[m].zone; - + if( map->list[m].zone_mf_count ) map->zone_remove(m); if( zone->info.special ) { zone = map->merge_zone(zone,map->list[m].prev_zone); } - + map->zone_apply(m,zone,empty,empty,empty); } /* when changing from a mapflag to another during runtime */ @@ -4963,7 +4969,6 @@ void read_map_zone_db(void) { if( (libconfig->setting_length(items) - disabled_items_count) > 0 ) { //Some are forcefully enabled zone->cant_disable_items_count = libconfig->setting_length(items) - disabled_items_count; CREATE(zone->cant_disable_items, int, zone->cant_disable_items_count); - } for(h = 0, v = 0, j = 0; h < libconfig->setting_length(items); h++) { config_setting_t *item = libconfig->setting_get_elem(items, h); @@ -5249,9 +5254,7 @@ void read_map_zone_db(void) { } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' zones in '"CL_WHITE"%s"CL_RESET"'.\n", zone_count, config_filename); - /* not supposed to go in here but in skill_final whatever */ - libconfig->destroy(&map_zone_db); - + /* post-load processing */ if( (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) ) zone->info.special = 1; @@ -5260,6 +5263,8 @@ void read_map_zone_db(void) { if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) ) zone->info.special = 1; } + /* not supposed to go in here but in skill_final whatever */ + libconfig->destroy(&map_zone_db); } int map_get_new_bonus_id (void) { @@ -5268,22 +5273,22 @@ int map_get_new_bonus_id (void) { void map_add_questinfo(int m, struct questinfo *qi) { unsigned short i; - + /* duplicate, override */ for(i = 0; i < map->list[m].qi_count; i++) { if( map->list[m].qi_data[i].nd == qi->nd ) break; } - + if( i == map->list[m].qi_count ) RECREATE(map->list[m].qi_data, struct questinfo, ++map->list[m].qi_count); - + memcpy(&map->list[m].qi_data[i], qi, sizeof(struct questinfo)); } bool map_remove_questinfo(int m, struct npc_data *nd) { unsigned short i; - + for(i = 0; i < map->list[m].qi_count; i++) { struct questinfo *qi = &map->list[m].qi_data[i]; if( qi->nd == nd ) { @@ -5294,7 +5299,6 @@ bool map_remove_questinfo(int m, struct npc_data *nd) { return true; } } - return false; } @@ -5373,10 +5377,10 @@ int do_final(void) { struct s_mapiterator* iter; ShowStatus("Terminating...\n"); - + channel->config->closing = true; HPM->event(HPET_FINAL); - + if (map->cpsd) aFree(map->cpsd); //Ladies and babies first. @@ -5437,7 +5441,7 @@ int do_final(void) { vending->final(); HPM_map_do_final(); - + map->map_db->destroy(map->map_db, map->db_final); mapindex->final(); @@ -5463,8 +5467,7 @@ int do_final(void) { aFree(map->block_free); if( map->bl_list ) aFree(map->bl_list); - - + if( !map->enable_grf ) aFree(map->cache_buffer); @@ -5476,7 +5479,7 @@ int do_final(void) { aFree(map->GRF_PATH_FILENAME); aFree(map->INTER_CONF_NAME); aFree(map->LOG_CONF_NAME); - + HPM->event(HPET_POST_FINAL); ShowStatus("Finished.\n"); @@ -5488,7 +5491,6 @@ int map_abort_sub(struct map_session_data* sd, va_list ap) { return 1; } - //------------------------------ // Function called when the server // has received a crash signal. @@ -5517,13 +5519,12 @@ void set_server_type(void) { SERVER_TYPE = SERVER_TYPE_MAP; } - /// Called when a terminate signal is received. void do_shutdown(void) { - if( runflag != MAPSERVER_ST_SHUTDOWN ) + if( core->runflag != MAPSERVER_ST_SHUTDOWN ) { - runflag = MAPSERVER_ST_SHUTDOWN; + core->runflag = MAPSERVER_ST_SHUTDOWN; ShowStatus("Shutting down...\n"); { struct map_session_data* sd; @@ -5531,7 +5532,7 @@ void do_shutdown(void) 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(); + sockt->flush_fifos(); } chrif->check_shutdown(); } @@ -5569,12 +5570,12 @@ CPCMD(gm_use) { } map->cpsd_active = true; - + if( !atcommand->exec(map->cpsd->fd, map->cpsd, line, false) ) ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' failed\n",line); else ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' was used\n",line); - + map->cpsd_active = false; } /* Hercules Console Parser */ @@ -5591,60 +5592,6 @@ void map_cp_defaults(void) { console->input->addCommand("gm:use",CPCMD_A(gm_use)); #endif } -/* Hercules Plugin Mananger */ -void map_hp_symbols(void) { - /* full interfaces */ - HPM->share(atcommand,"atcommand"); - HPM->share(battle,"battle"); - HPM->share(bg,"battlegrounds"); - HPM->share(buyingstore,"buyingstore"); - HPM->share(channel,"channel"); - HPM->share(clif,"clif"); - HPM->share(chrif,"chrif"); - HPM->share(guild,"guild"); - HPM->share(gstorage,"gstorage"); - HPM->share(homun,"homun"); - HPM->share(map,"map"); - HPM->share(ircbot,"ircbot"); - HPM->share(itemdb,"itemdb"); - HPM->share(logs,"logs"); - HPM->share(mail,"mail"); - HPM->share(instance,"instance"); - HPM->share(script,"script"); - HPM->share(searchstore,"searchstore"); - HPM->share(skill,"skill"); - HPM->share(vending,"vending"); - HPM->share(pc,"pc"); - HPM->share(pcg,"pc_groups"); - HPM->share(party,"party"); - HPM->share(storage,"storage"); - HPM->share(trade,"trade"); - HPM->share(status,"status"); - HPM->share(chat, "chat"); - HPM->share(duel,"duel"); - HPM->share(elemental,"elemental"); - HPM->share(intif,"intif"); - HPM->share(mercenary,"mercenary"); - HPM->share(mob,"mob"); - HPM->share(unit,"unit"); - HPM->share(npc,"npc"); - HPM->share(mapreg,"mapreg"); - HPM->share(pet,"pet"); - HPM->share(path,"path"); - HPM->share(quest,"quest"); -#ifdef PCRE_SUPPORT - HPM->share(npc_chat,"npc_chat"); - HPM->share(libpcre,"libpcre"); -#endif - HPM->share(mapit,"mapit"); - HPM->share(mapindex,"mapindex"); - /* sql link */ - HPM->share(map->mysql_handle,"sql_handle"); - /* specific */ - HPM->share(atcommand->create,"addCommand"); - HPM->share(script->addScript,"addScript"); - HPM->share(HPM_map_add_group_permission,"addGroupPermission"); -} void map_load_defaults(void) { mapindex_defaults(); @@ -5699,7 +5646,7 @@ void map_load_defaults(void) { */ static CMDLINEARG(runonce) { - runflag = CORE_ST_STOP; + core->runflag = CORE_ST_STOP; return true; } /** @@ -5807,7 +5754,7 @@ static CMDLINEARG(logconfig) static CMDLINEARG(scriptcheck) { map->minimal = true; - runflag = CORE_ST_STOP; + core->runflag = CORE_ST_STOP; map->scriptcheck = true; return true; } @@ -5832,12 +5779,11 @@ static CMDLINEARG(loadscript) **/ static CMDLINEARG(generatetranslations) { script->lang_export_file = aStrdup("./generated_translations.pot"); - + if( !(script->lang_export_fp = fopen(script->lang_export_file,"wb")) ) { ShowError("export-dialog: failed to open '%s' for writing\n",script->lang_export_file); } - - runflag = CORE_ST_STOP; + core->runflag = CORE_ST_STOP; return true; } @@ -5868,7 +5814,7 @@ int do_init(int argc, char *argv[]) #ifdef GCOLLECT GC_enable_incremental(); #endif - + map_load_defaults(); map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf"); @@ -5881,12 +5827,11 @@ int do_init(int argc, char *argv[]) map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt"); HPM_map_do_init(); - HPM->symbol_defaults_sub = map_hp_symbols; cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); HPM->config_read(); - + HPM->event(HPET_PRE_INIT); - + cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */ if (!minimal) { @@ -5902,7 +5847,7 @@ int do_init(int argc, char *argv[]) if (!map->ip_set || !map->char_ip_set) { char ip_str[16]; - ip2str(sockt->addr_[0], ip_str); + sockt->ip2str(sockt->addr_[0], ip_str); ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n"); @@ -5967,7 +5912,6 @@ int do_init(int argc, char *argv[]) map->readallmaps(); - if (!minimal) { timer->add_func_list(map->freeblock_timer, "map_freeblock_timer"); timer->add_func_list(map->clearflooritem_timer, "map_clearflooritem_timer"); @@ -6021,24 +5965,24 @@ int do_init(int argc, char *argv[]) HPM->event(HPET_READY); exit(EXIT_SUCCESS); } - + npc->event_do_oninit( false ); // Init npcs (OnInit) npc->market_fromsql(); /* after OnInit */ - + if (battle_config.pk_mode) ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); Sql_HerculesUpdateCheck(map->mysql_handle); - + #ifdef CONSOLE_INPUT console->input->setSQL(map->mysql_handle); #endif - + 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 = map->do_shutdown; - runflag = MAPSERVER_ST_RUNNING; + if( core->runflag != CORE_ST_STOP ) { + core->shutdown_callback = map->do_shutdown; + core->runflag = MAPSERVER_ST_RUNNING; } map_cp_defaults(); @@ -6064,14 +6008,14 @@ void map_defaults(void) { map->extra_scripts = NULL; map->extra_scripts_count = 0; - + sprintf(map->db_path ,"db"); sprintf(map->help_txt ,"conf/help.txt"); sprintf(map->help2_txt ,"conf/help2.txt"); sprintf(map->charhelp_txt ,"conf/charhelp.txt"); - + sprintf(map->wisp_server_name ,"Server"); // can be modified in char-server configuration file - + map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; map->minsave_interval = 100; map->save_settings = 0xFFFF; @@ -6079,19 +6023,18 @@ void map_defaults(void) { map->agit2_flag = 0; map->night_flag = 0; // 0=day, 1=night [Yor] map->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] - + map->db_use_sql_item_db = 0; map->db_use_sql_mob_db = 0; map->db_use_sql_mob_skill_db = 0; - + sprintf(map->item_db_db, "item_db"); sprintf(map->item_db2_db, "item_db2"); sprintf(map->mob_db_db, "mob_db"); sprintf(map->mob_db2_db, "mob_db2"); sprintf(map->mob_skill_db_db, "mob_skill_db"); sprintf(map->mob_skill_db2_db, "mob_skill_db2"); - sprintf(map->interreg_db, "interreg"); - + map->INTER_CONF_NAME="conf/inter-server.conf"; map->LOG_CONF_NAME="conf/logs.conf"; map->MAP_CONF_NAME = "conf/map-server.conf"; @@ -6100,7 +6043,7 @@ void map_defaults(void) { map->SCRIPT_CONF_NAME = "conf/script.conf"; map->MSG_CONF_NAME = "conf/messages.conf"; map->GRF_PATH_FILENAME = "conf/grf-files.txt"; - + map->default_codepage[0] = '\0'; map->server_port = 3306; sprintf(map->server_ip,"127.0.0.1"); @@ -6111,15 +6054,15 @@ void map_defaults(void) { map->default_lang_str[0] = '\0'; map->cpsd_active = false; - + map->port = 0; map->users = 0; map->ip_set = 0; map->char_ip_set = 0; map->enable_grf = 0; - + memset(&map->index2mapid, -1, sizeof(map->index2mapid)); - + map->id_db = NULL; map->pc_db = NULL; map->mobid_db = NULL; @@ -6138,19 +6081,16 @@ void map_defaults(void) { map->bl_list = NULL; map->bl_list_count = 0; map->bl_list_size = 0; - + //all in a big chunk, respects order - memset(&map->bl_head,0,sizeof(map->bl_head) - + sizeof(map->zone_all) - + sizeof(map->zone_pk) - ); - + memset(ZEROED_BLOCK_POS(map), 0, ZEROED_BLOCK_SIZE(map)); + map->cpsd = NULL; map->list = NULL; - + map->iterator_ers = NULL; map->cache_buffer = NULL; - + map->flooritem_ers = NULL; /* */ map->bonus_id = SP_LAST_KNOWN; @@ -6317,19 +6257,17 @@ void map_defaults(void) { map->abort_sub = map_abort_sub; map->update_cell_bl = map_update_cell_bl; - map->get_new_bonus_id = map_get_new_bonus_id; - + map->add_questinfo = map_add_questinfo; map->remove_questinfo = map_remove_questinfo; - + map->merge_zone = map_merge_zone; map->zone_clear_single = map_zone_clear_single; - + /** * mapit interface **/ - mapit = &mapit_s; mapit->alloc = mapit_alloc; @@ -6339,5 +6277,4 @@ void map_defaults(void) { mapit->next = mapit_next; mapit->prev = mapit_prev; mapit->exists = mapit_exists; - } diff --git a/src/map/map.h b/src/map/map.h index 3960a64b4..39af13de8 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -5,18 +5,17 @@ #ifndef MAP_MAP_H #define MAP_MAP_H -#include "../config/core.h" - +#include "map/atcommand.h" +#include "common/hercules.h" +#include "common/core.h" // CORE_ST_LAST +#include "common/db.h" +#include "common/mapindex.h" +#include "common/mmo.h" +#include "common/sql.h" + +#include <stdio.h> #include <stdarg.h> -#include "atcommand.h" -#include "../common/cbasetypes.h" -#include "../common/core.h" // CORE_ST_LAST -#include "../common/db.h" -#include "../common/mapindex.h" -#include "../common/mmo.h" -#include "../common/sql.h" - struct mob_data; struct npc_data; struct channel_data; @@ -65,16 +64,6 @@ enum MOBID { MOBID_MAGICDECOY_WIND = 2046, }; -// The following system marks a different job ID system used by the map server, -// which makes a lot more sense than the normal one. [Skotlex] -// These marks the "level" of the job. -#define JOBL_2_1 0x100 //256 -#define JOBL_2_2 0x200 //512 -#define JOBL_2 0x300 -#define JOBL_UPPER 0x1000 //4096 -#define JOBL_BABY 0x2000 //8192 -#define JOBL_THIRD 0x4000 //16384 - // For filtering and quick checking. #define MAPID_BASEMASK 0x00ff #define MAPID_UPPERMASK 0x0fff @@ -224,7 +213,13 @@ enum { #define EVENT_NAME_LENGTH ( NAME_LENGTH * 2 + 3 ) #define DEFAULT_AUTOSAVE_INTERVAL (5*60*1000) // Specifies maps where players may hit each other -#define map_flag_vs(m) (map->list[m].flag.pvp || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) || map->list[m].flag.battleground) +#define map_flag_vs(m) ( \ + map->list[m].flag.pvp \ + || map->list[m].flag.gvg_dungeon \ + || map->list[m].flag.gvg \ + || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) \ + || map->list[m].flag.battleground \ + ) // Specifies maps that have special GvG/WoE restrictions #define map_flag_gvg(m) (map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle)) // Specifies if the map is tagged as GvG/WoE (regardless of map->agit_flag status) @@ -266,10 +261,15 @@ enum { RC_DEMIHUMAN, RC_ANGEL, RC_DRAGON, + RC_PLAYER, RC_BOSS, RC_NONBOSS, + RC_MAX, RC_NONDEMIHUMAN, - RC_MAX + RC_NONPLAYER, + RC_DEMIPLAYER, + RC_NONDEMIPLAYER, + RC_ALL = 0xFF }; enum { @@ -280,6 +280,8 @@ enum { RC2_GOLEM, RC2_GUARDIAN, RC2_NINJA, + RC2_SCARABA, + RC2_TURTLE, RC2_MAX }; @@ -294,7 +296,8 @@ enum elements { ELE_DARK, ELE_GHOST, ELE_UNDEAD, - ELE_MAX + ELE_MAX, + ELE_ALL = 0xFF }; /** @@ -716,7 +719,7 @@ struct map_data { bool custom_name; ///< Whether the instanced map is using a custom name /* */ - int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk); + int (*getcellp)(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk); void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag); char *cellPos; @@ -763,8 +766,6 @@ struct mapit_interface { bool (*exists) (struct s_mapiterator* iter); }; -struct mapit_interface *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)) @@ -862,7 +863,6 @@ struct map_interface { char mob_db2_db[32]; char mob_skill_db_db[32]; char mob_skill_db2_db[32]; - char interreg_db[32]; char autotrade_merchants_db[32]; char autotrade_data_db[32]; char npc_market_data_db[32]; @@ -896,15 +896,15 @@ struct map_interface { DBMap* regen_db; // int id -> struct block_list* (status_natural_heal processing) DBMap* zone_db; // string => struct map_zone_data DBMap* iwall_db; - /* order respected by map_defaults() in order to zero */ - /* from block_free until zone_pk */ struct block_list **block_free; int block_free_count, block_free_lock, block_free_list_size; struct block_list **bl_list; int bl_list_count, bl_list_size; +BEGIN_ZEROED_BLOCK; // This block is zeroed in map_defaults() struct block_list bl_head; struct map_zone_data zone_all;/* used as a base on all maps */ struct map_zone_data zone_pk;/* used for (pk_mode) */ +END_ZEROED_BLOCK; /* */ struct map_session_data *cpsd; struct map_data *list; @@ -924,7 +924,7 @@ struct map_interface { void (*zone_change) (int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath); void (*zone_change2) (int m, struct map_zone_data *zone); - int (*getcell) (int16 m,int16 x,int16 y,cell_chk cellchk); + int (*getcell) (int16 m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk); void (*setgatcell) (int16 m, int16 x, int16 y, int gat); void (*cellfromcache) (struct map_data *m); @@ -946,7 +946,7 @@ struct map_interface { // search and creation int (*get_new_object_id) (void); int (*search_freecell) (struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag); - bool (*closest_freecell) (int16 m, int16 *x, int16 *y, int type, int flag); + bool (*closest_freecell) (int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag); // int (*quit) (struct map_session_data *sd); // npc @@ -955,7 +955,7 @@ struct map_interface { int (*clearflooritem_timer) (int tid, int64 tick, int id, intptr_t data); int (*removemobs_timer) (int tid, int64 tick, int id, intptr_t data); void (*clearflooritem) (struct block_list* bl); - int (*addflooritem) (struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags); + int (*addflooritem) (const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags); // player to map session void (*addnickdb) (int charid, const char* nick); void (*delnickdb) (int charid, const char* nick); @@ -1042,15 +1042,15 @@ struct map_interface { void (*do_shutdown) (void); int (*freeblock_timer) (int tid, int64 tick, int id, intptr_t data); - int (*searchrandfreecell) (int16 m, int16 *x, int16 *y, int stack); + int (*searchrandfreecell) (int16 m, const struct block_list *bl, int16 *x, int16 *y, int stack); int (*count_sub) (struct block_list *bl, va_list ap); DBData (*create_charid2nick) (DBKey key, va_list args); int (*removemobs_sub) (struct block_list *bl, va_list ap); struct mapcell (*gat2cell) (int gat); int (*cell2gat) (struct mapcell cell); - int (*getcellp) (struct map_data *m, int16 x, int16 y, cell_chk cellchk); + int (*getcellp) (struct map_data *m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk); void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag); - int (*sub_getcellp) (struct map_data *m, int16 x, int16 y, cell_chk cellchk); + int (*sub_getcellp) (struct map_data *m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk); void (*sub_setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag); void (*iwall_nextxy) (int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1); DBData (*create_map_data_other_server) (DBKey key, va_list args); @@ -1087,10 +1087,11 @@ struct map_interface { void (*zone_clear_single) (struct map_zone_data *zone); }; -struct map_interface *map; - #ifdef HERCULES_CORE void map_defaults(void); #endif // HERCULES_CORE +HPShared struct mapit_interface *mapit; +HPShared struct map_interface *map; + #endif /* MAP_MAP_H */ diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 9c9a1acee..09d051bab 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -5,9 +5,11 @@ #ifndef MAP_MAPREG_H #define MAP_MAPREG_H -#include "script.h" // struct reg_db -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/script.h" // struct reg_db +#include "common/hercules.h" +#include "common/db.h" + +struct eri; /** Container for a mapreg value */ struct mapreg_save { @@ -46,10 +48,10 @@ struct mapreg_interface { bool (*config_read) (const char *w1, const char *w2); }; -struct mapreg_interface *mapreg; - #ifdef HERCULES_CORE void mapreg_defaults(void); #endif // HERCULES_CORE +HPShared struct mapreg_interface *mapreg; + #endif /* MAP_MAPREG_H */ diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 0092a6c61..37c830e2e 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -6,21 +6,22 @@ #include "mapreg.h" +#include "map/map.h" // map-"mysql_handle +#include "map/script.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/showmsg.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdlib.h> #include <string.h> -#include "map.h" // map->mysql_handle -#include "script.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/sql.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct mapreg_interface mapreg_s; +struct mapreg_interface *mapreg; #define MAPREG_AUTOSAVE_INTERVAL (300*1000) diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 84f6a3c41..b26876d39 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -6,42 +6,45 @@ #include "mercenary.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct mercenary_interface mercenary_s; +struct s_mercenary_db mercdb[MAX_MERCENARY_CLASS]; + +struct mercenary_interface *mercenary; int merc_search_index(int class_) { @@ -449,7 +452,7 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) { } int read_mercenarydb(void) { - memset(mercenary->db,0,sizeof(mercenary->db)); + memset(mercenary->db, 0, sizeof(struct s_mercenary_db) * MAX_MERCENARY_CLASS); sv->readdb(map->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, mercenary->read_db_sub); return 0; @@ -468,7 +471,7 @@ bool read_mercenary_skilldb_sub(char* str[], int columns, int current) ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); return false; } - + skill_id = atoi(str[1]); if( skill_id < MC_SKILLBASE || skill_id >= MC_SKILLBASE + MAX_MERCSKILL ) { @@ -498,7 +501,7 @@ void do_init_mercenary(bool minimal) { mercenary->read_db(); mercenary->read_skilldb(); - + timer->add_func_list(mercenary->contract_end_timer, "merc_contract_end_timer"); } @@ -511,25 +514,25 @@ void mercenary_defaults(void) { mercenary = &mercenary_s; /* vars */ - memset(mercenary->db,0,sizeof(mercenary->db)); + mercenary->db = mercdb; + memset(mercenary->db, 0, sizeof(struct s_mercenary_db) * MAX_MERCENARY_CLASS); /* funcs */ - mercenary->init = do_init_mercenary; - + mercenary->class = merc_class; mercenary->get_viewdata = merc_get_viewdata; - + mercenary->create = merc_create; mercenary->data_received = merc_data_received; mercenary->save = mercenary_save; - + mercenary->heal = mercenary_heal; mercenary->dead = mercenary_dead; - + mercenary->delete = merc_delete; mercenary->contract_stop = merc_contract_stop; - + mercenary->get_lifetime = mercenary_get_lifetime; mercenary->get_guild = mercenary_get_guild; mercenary->get_faith = mercenary_get_faith; @@ -537,14 +540,14 @@ void mercenary_defaults(void) { mercenary->get_calls = mercenary_get_calls; mercenary->set_calls = mercenary_set_calls; mercenary->kills = mercenary_kills; - + mercenary->checkskill = mercenary_checkskill; mercenary->read_db = read_mercenarydb; mercenary->read_skilldb = read_mercenary_skilldb; - + mercenary->killbonus = mercenary_killbonus; mercenary->search_index = merc_search_index; - + mercenary->contract_end_timer = merc_contract_end_timer; mercenary->read_db_sub = read_mercenarydb_sub; mercenary->read_skill_db_sub = read_mercenary_skilldb_sub; diff --git a/src/map/mercenary.h b/src/map/mercenary.h index fbf3603f6..9e0c59428 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -4,9 +4,11 @@ #ifndef MAP_MERCENARY_H #define MAP_MERCENARY_H -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/hercules.h" + +struct map_session_data; // number of cells that a mercenary can walk to from it's master before being warped #define MAX_MER_DISTANCE 15 @@ -56,7 +58,7 @@ struct mercenary_interface { /* vars */ - struct s_mercenary_db db[MAX_MERCENARY_CLASS]; + struct s_mercenary_db *db; /* funcs */ @@ -95,10 +97,10 @@ struct mercenary_interface { bool (*read_skill_db_sub) (char* str[], int columns, int current); }; -struct mercenary_interface *mercenary; - #ifdef HERCULES_CORE void mercenary_defaults(void); #endif // HERCULES_CORE +HPShared struct mercenary_interface *mercenary; + #endif /* MAP_MERCENARY_H */ diff --git a/src/map/mob.c b/src/map/mob.c index 8a8e96508..2fe9fe8fb 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -4,50 +4,51 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP +#include "config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP #include "mob.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "clif.h" -#include "date.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mercenary.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct mob_interface mob_s; +struct mob_interface *mob; #define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode. @@ -290,7 +291,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) { status->set_viewdata(&md->bl, md->class_); status->change_init(&md->bl); unit->dataset(&md->bl); - + map->addiddb(&md->bl); return md; } @@ -378,14 +379,14 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) { 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 + (sce->val2 == KSPROTECT_PARTY && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed + (sce->val2 == KSPROTECT_GUILD && 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)) ) + (sce->val2 == KSPROTECT_SELF && sce->val1 != t_sd->bl.id) || + (sce->val2 == KSPROTECT_PARTY && sce->val3 && sce->val3 != t_sd->status.party_id) || + (sce->val2 == KSPROTECT_GUILD && 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 ) @@ -467,7 +468,7 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const struct mob_data* md = NULL; int count, lv; bool no_guardian_data = false; - + if( ai && ai&0x200 ) { no_guardian_data = true; ai &=~ 0x200; @@ -544,7 +545,7 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0 x = rnd()%(x1-x0+1)+x0; y = rnd()%(y1-y0+1)+y0; j++; - } while (map->getcell(m,x,y,CELL_CHKNOPASS) && j < max); + } while (map->getcell(m, NULL, x, y, CELL_CHKNOPASS) && j < max); if (j == max) {// attempt to find an available cell failed @@ -1078,7 +1079,7 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) ) { //Pick closest target? #ifdef ACTIVEPATHSEARCH struct walkpath_data wpd; - if (!path->search(&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells + if (!path->search(&wpd, &md->bl, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells return 0; //Standing monsters use range2, walking monsters use range3 if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2) @@ -1298,7 +1299,7 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) { break; default: mob_stop_attack(md); - mob_stop_walking(md,1); //Stop chasing. + mob_stop_walking(md, STOPWALKING_FLAG_FIXPOS); //Stop chasing. md->state.skillstate = MSS_IDLE; if(battle_config.mob_ai&0x8) //Walk instantly after dropping target md->next_walktime = tick+rnd()%1000; @@ -1343,7 +1344,7 @@ int mob_randomwalk(struct mob_data *md, int64 tick) { x+=md->bl.x; y+=md->bl.y; - if(((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m,x,y,CELL_CHKPASS) && unit->walktoxy(&md->bl,x,y,8)){ + if (((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&md->bl, x, y, 8)) { break; } } @@ -1381,7 +1382,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) 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)) + map->getcell(md->bl.m, &md->bl, 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. @@ -1818,7 +1819,7 @@ int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) { ditem = list->item; while (ditem) { struct item_drop *ditem_prev; - map->addflooritem(&ditem->item_data,ditem->item_data.amount, + map->addflooritem(NULL, &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; @@ -1975,7 +1976,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) case BL_MOB: { struct mob_data* md2 = (TBL_MOB*)src; - if( md2->special_state.ai && md2->master_id ) { + if (md2->special_state.ai != AI_NONE && md2->master_id) { struct map_session_data* msd = map->id2sd(md2->master_id); if( msd ) char_id = msd->status.char_id; @@ -2063,13 +2064,13 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) { return; #if PACKETVER >= 20120404 - if( !(md->status.mode&MD_BOSS) ){ + if (battle_config.show_monster_hp_bar && !(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 ) { + if (md->dmglog[i].id) { 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); + if (sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE)) // check if in range + clif->monster_hp_bar(md, sd); } } } @@ -2170,7 +2171,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { if( !(type&2) //No exp && (!map->list[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] + && (!md->master_id || md->special_state.ai == AI_NONE) //Only player-summoned mobs do not give exp. [Skotlex] && (!map->list[m].flag.nobaseexp || !map->list[m].flag.nojobexp) //Gives Exp ) { //Experience calculation. int bonus = 100; //Bonus on top of your share (common to all attackers). @@ -2183,7 +2184,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { else ARR_FIND(0, MAX_PC_FEELHATE, i, temp == sd->hate_mob[i] && (battle_config.allow_skill_without_day || pc->sg_info[i].day_func())); - if(i<MAX_PC_FEELHATE && (temp=pc->checkskill(sd,pc->sg_info[i].bless_id))) + if(i<MAX_PC_FEELHATE && (temp=pc->checkskill(sd,pc->sg_info[i].bless_id)) > 0) bonus += (i==2?20:10)*temp; } if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] @@ -2298,9 +2299,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { } //End EXP giving. if( !(type&1) && !map->list[m].flag.nomobloot && !md->state.rebirth && ( - !md->special_state.ai || //Non special mob + md->special_state.ai == AI_NONE || //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. + (md->special_state.ai == AI_SPHERE && 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); @@ -2370,7 +2371,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { if( drop_rate < 1 ) drop_rate = 1; } - + // attempt to drop the item if (rnd() % 10000 >= drop_rate) continue; @@ -2389,14 +2390,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { //MSG: "'%s' won %s's %s (chance: %0.02f%%)" intif->broadcast(message, strlen(message)+1, BC_DEFAULT); } - + /* heres the thing we got the feature set up however we're still discussing how to best define the ids, * so while we discuss, for a small period of time, the list is hardcoded (yes officially only those 2 use it, * thus why we're unsure on how to best place the setting) */ /* temp, will not be hardcoded for long thudu. */ if( it->nameid == 7782 || it->nameid == 7783 ) /* for when not hardcoded: add a check on mvp bonus drop as well */ clif->item_drop_announce(mvp_sd, it->nameid, md->name); - + // 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); @@ -2473,7 +2474,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { timer->add(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) { + if(mvp_sd && md->db->mexp > 0 && md->special_state.ai == AI_NONE) { int log_mvp[2] = {0}; unsigned int mexp; double exp; @@ -2542,7 +2543,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { 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); + map->addflooritem(&md->bl, &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] @@ -2573,7 +2574,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { 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)) ) { + if (++sd->mission_count >= 100 && (temp = mob->get_random_id(0, 0xE, sd->status.base_level)) != 0) { pc->addfame(sd, 1); sd->mission_mobid = temp; pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), temp); @@ -2746,7 +2747,7 @@ int mob_class_change (struct mob_data *md, int class_) if( mob_is_treasure(md) ) return 0; //Treasure Boxes - if( md->special_state.ai > 1 ) + if( md->special_state.ai > AI_ATTACK ) return 0; //Marine Spheres and Floras. if( mob->is_clone(md->class_) ) @@ -2764,7 +2765,7 @@ int mob_class_change (struct mob_data *md, int class_) memcpy(md->name,md->db->jname,NAME_LENGTH); mob_stop_attack(md); - mob_stop_walking(md, 0); + mob_stop_walking(md, STOPWALKING_FLAG_NONE); unit->skillcastcancel(&md->bl, 0); status->set_viewdata(&md->bl, class_); clif->class_change(&md->bl, md->vd->class_, 1); @@ -2797,19 +2798,19 @@ int mob_class_change (struct mob_data *md, int class_) /*========================================== * mob heal, update display hp info of mob for players *------------------------------------------*/ -void mob_heal(struct mob_data *md,unsigned int heal) +void mob_heal(struct mob_data *md, unsigned int heal) { if (battle_config.show_mob_info&3) clif->charnameack (0, &md->bl); - + #if PACKETVER >= 20120404 - if( !(md->status.mode&MD_BOSS) ){ + if (battle_config.show_monster_hp_bar && !(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 ) { + if (md->dmglog[i].id) { 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); + if (sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE)) // check if in range + clif->monster_hp_bar(md, sd); } } } @@ -3016,7 +3017,7 @@ struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_ nullpo_retr(NULL, md); - if (md->special_state.ai) //Summoned creatures. [Skotlex] + if (md->special_state.ai != AI_NONE) //Summoned creatures. [Skotlex] type = BL_PC; map->foreachinrange(mob->getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr); @@ -3174,7 +3175,8 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { 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; + flag = (md->master_id > 0 && (fbl=map->id2bl(md->master_id)) != NULL && unit->counttargeted(fbl) > 0); + break; case MSC_ALCHEMIST: flag = (md->state.alchemist); break; @@ -3302,11 +3304,11 @@ int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int if(md->bl.prev == NULL || md->status.hp <= 0) return 0; - if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] + if (md->special_state.ai == AI_SPHERE) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] md->state.alchemist = 1; return mob->skill_use(md, timer->gettick(), MSC_ALCHEMIST); } - + target_id = md->target_id; if (!target_id || battle_config.mob_changetarget_byskill) md->target_id = src->id; @@ -3402,7 +3404,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][j].idx; int skill_id = pc->skill_tree[pc->class2idx(sd->status.class_)][j].id; if (!skill_id || sd->status.skill[idx].lv < 1 || - (skill->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) + (skill->dbs->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) ) continue; for(h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) { @@ -3435,7 +3437,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv); ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv); - inf = skill->db[idx].inf; + inf = skill->dbs->db[idx].inf; if (inf&INF_ATTACK_SKILL) { ms[i].target = MST_TARGET; ms[i].cond1 = MSC_ALWAYS; @@ -3702,13 +3704,13 @@ bool mob_parse_dbrow(char** str) { db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); mstatus->rhw.range = atoi(str[9]); - + mstatus->rhw.atk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[10])); mstatus->rhw.atk2 = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[11])); - + mstatus->def = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[12])); mstatus->mdef = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[13])); - + mstatus->str = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[14])); mstatus->agi = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[15])); mstatus->vit = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[16])); @@ -3943,7 +3945,7 @@ void mob_readdb(void) { * mob_db table reading *------------------------------------------*/ int mob_read_sqldb(void) { - const char* mob_db_name[] = { + const char* mob_db_name[] = { map->mob_db_db, map->mob_db2_db }; @@ -4399,13 +4401,13 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current) if ( skill->get_casttype2(sidx) == 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->db[sidx].name, + ms->skill_id, skill->dbs->db[sidx].name, 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->db[sidx].name, + ms->skill_id, skill->dbs->db[sidx].name, mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite); ms->target = MST_TARGET; } @@ -4519,7 +4521,7 @@ void mob_readskilldb(void) { * seems to work though... */ int mob_read_sqlskilldb(void) { - const char* mob_skill_db_name[] = { + const char* mob_skill_db_name[] = { map->mob_skill_db_db, map->mob_skill_db2_db }; @@ -4530,7 +4532,6 @@ int mob_read_sqlskilldb(void) { return 0; } - for( fi = 0; fi < ARRAYLENGTH(mob_skill_db_name); ++fi ) { uint32 lines = 0, count = 0; @@ -4645,7 +4646,7 @@ void mob_load(bool minimal) { 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] && !mob->is_clone(i)) { @@ -4764,13 +4765,13 @@ void mob_defaults(void) { //Defines the Manuk/Splendide mob groups for the status reductions [Epoque] const int mob_manuk[8] = { 1986, 1987, 1988, 1989, 1990, 1997, 1998, 1999 }; const int mob_splendide[5] = { 1991, 1992, 1993, 1994, 1995 }; - + mob = &mob_s; - + memset(mob->db_data, 0, sizeof(mob->db_data)); mob->dummy = NULL; memset(mob->chat_db, 0, sizeof(mob->chat_db)); - + memcpy(mob->manuk, mob_manuk, sizeof(mob->manuk)); memcpy(mob->splendide, mob_splendide, sizeof(mob->splendide)); /* */ diff --git a/src/map/mob.h b/src/map/mob.h index 02ae1630a..4b8a054b5 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -5,11 +5,11 @@ #ifndef MAP_MOB_H #define MAP_MOB_H -#include "map.h" // struct status_data, struct view_data, struct mob_skill -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // struct item +#include "map/map.h" // struct block_list +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data, view_data +#include "common/hercules.h" +#include "common/mmo.h" // struct item #define MAX_RANDOMMONSTER 5 @@ -38,7 +38,7 @@ #define MOB_CLONE_END MAX_MOB_DB //Used to determine default enemy type of mobs (for use in each in range calls) -#define DEFAULT_ENEMY_TYPE(md) ((md)->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER) +#define DEFAULT_ENEMY_TYPE(md) ((md)->special_state.ai != AI_NONE ?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER) #define MAX_MOB_CHAT 250 //Max Skill's messages @@ -79,11 +79,23 @@ enum size { }; enum ai { - AI_NONE = 0, - AI_ATTACK, - AI_SPHERE, - AI_FLORA, - AI_ZANZOU, + AI_NONE = 0, //0: Normal mob. + AI_ATTACK, //1: Standard summon, attacks mobs. + AI_SPHERE, //2: Alchemist Marine Sphere + AI_FLORA, //3: Alchemist Summon Flora + AI_ZANZOU, //4: Summon Zanzou + + AI_MAX +}; + +/** + * Acceptable values for map_session_data.state.noks + */ +enum ksprotection_mode { + KSPROTECT_NONE = 0, + KSPROTECT_SELF = 1, + KSPROTECT_PARTY = 2, + KSPROTECT_GUILD = 3, }; struct mob_skill { @@ -141,13 +153,8 @@ struct mob_data { 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 size : 2; //Small/Big monsters. @see enum size + unsigned int ai : 4; //Special AI for summoned monsters. @see enum ai 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 { @@ -265,8 +272,8 @@ struct item_drop_list { #define mob_stop_walking(md, type) (unit->stop_walking(&(md)->bl, (type))) #define mob_stop_attack(md) (unit->stop_attack(&(md)->bl)) -#define mob_is_battleground(md) ( map->list[(md)->bl.m].flag.battleground && ((md)->class_ == MOBID_BARRICADE2 || ((md)->class_ >= MOBID_FOOD_STOR && (md)->class_ <= MOBID_PINK_CRYST)) ) -#define mob_is_gvg(md) (map->list[(md)->bl.m].flag.gvg_castle && ( (md)->class_ == MOBID_EMPERIUM || (md)->class_ == MOBID_BARRICADE1 || (md)->class_ == MOBID_GUARIDAN_STONE1 || (md)->class_ == MOBID_GUARIDAN_STONE2) ) +#define mob_is_battleground(md) (map->list[(md)->bl.m].flag.battleground && ((md)->class_ == MOBID_BARRICADE2 || ((md)->class_ >= MOBID_FOOD_STOR && (md)->class_ <= MOBID_PINK_CRYST))) +#define mob_is_gvg(md) (map->list[(md)->bl.m].flag.gvg_castle && ( (md)->class_ == MOBID_EMPERIUM || (md)->class_ == MOBID_BARRICADE1 || (md)->class_ == MOBID_GUARIDAN_STONE1 || (md)->class_ == MOBID_GUARIDAN_STONE2)) #define mob_is_treasure(md) (((md)->class_ >= MOBID_TREAS01 && (md)->class_ <= MOBID_TREAS40) || ((md)->class_ >= MOBID_TREAS41 && (md)->class_ <= MOBID_TREAS49)) struct mob_interface { @@ -380,10 +387,10 @@ struct mob_interface { void (*destroy_mob_db) (int index); }; -struct mob_interface *mob; - #ifdef HERCULES_CORE void mob_defaults(void); #endif // HERCULES_CORE +HPShared struct mob_interface *mob; + #endif /* MAP_MOB_H */ diff --git a/src/map/npc.c b/src/map/npc.c index 1721e3db3..a0c14a058 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -4,9 +4,37 @@ #define HERCULES_CORE -#include "../config/core.h" // NPC_SECURE_TIMEOUT_INPUT, NPC_SECURE_TIMEOUT_MENU, NPC_SECURE_TIMEOUT_NEXT, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL +#include "config/core.h" // NPC_SECURE_TIMEOUT_INPUT, NPC_SECURE_TIMEOUT_MENU, NPC_SECURE_TIMEOUT_NEXT, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL #include "npc.h" +#include "map/battle.h" +#include "map/chat.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <errno.h> #include <math.h> #include <stdio.h> @@ -14,34 +42,8 @@ #include <string.h> #include <time.h> -#include "battle.h" -#include "chat.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "unit.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct npc_interface npc_s; +struct npc_interface *npc; static int npc_id=START_NPC_NUM; static int npc_warp=0; @@ -74,25 +76,40 @@ static struct script_event_s { * @param class_ The NPC class ID. * @return The viewdata, or NULL if the ID is invalid. */ -struct view_data* npc_get_viewdata(int class_) +struct view_data *npc_get_viewdata(int class_) { if (class_ == INVISIBLE_CLASS) return &npc_viewdb[0]; - if (npc->db_checkid(class_) || class_ == WARP_CLASS) { - if (class_ < MAX_NPC_CLASS2_START) { + if (npc->db_checkid(class_)) { + if (class_ < MAX_NPC_CLASS) { return &npc_viewdb[class_]; - } else { + } else if (class_ >= MAX_NPC_CLASS2_START && class_ < MAX_NPC_CLASS2_END) { return &npc_viewdb2[class_-MAX_NPC_CLASS2_START]; } } return NULL; } -//Checks if a given id is a valid npc id. [Skotlex] -//Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) +/** + * Checks if a given id is a valid npc id. + * + * Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) + * + * @param id The NPC ID to validate. + * @return Whether the value is a valid ID. + */ bool npc_db_checkid(int id) { - return ((id >= 46 && id <= 125) || id == HIDDEN_WARP_CLASS || (id > 400 && id < MAX_NPC_CLASS) || id == INVISIBLE_CLASS || (id > MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END)); + if (id >= WARP_CLASS && id <= 125) // First subrange + return true; + if (id == HIDDEN_WARP_CLASS || id == INVISIBLE_CLASS) // Special IDs not included in the valid ranges + return true; + if (id > 400 && id < MAX_NPC_CLASS) // Second subrange + return true; + if (id >= MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END) // Second range + return true; + // Anything else is invalid + return false; } /// Returns a new npc id that isn't being used in id_db. @@ -188,7 +205,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap) if (sd->npc_id != 0) return 0; - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); npc->click(sd,nd); } } @@ -254,7 +271,7 @@ int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) { if( sd ) sd->npc_idle_timer = INVALID_TIMER; return 0;//Not logged in anymore OR no longer attached to a npc } - + switch( sd->npc_idle_type ) { case NPCT_INPUT: timeout = NPC_SECURE_TIMEOUT_INPUT; @@ -264,7 +281,7 @@ int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) { break; //case NPCT_WAIT: var starts with this value } - + if( DIFF_TICK(tick,sd->npc_idle_tick) > (timeout*1000) ) { /** * If we still have the NPC script attached, tell it to stop. @@ -380,7 +397,7 @@ void npc_event_doall_sub(void *key, void *data, va_list ap) npc->event_sub(map->id2sd(rid), ev, buf); } else { - script->run(ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id); } (*c)++; } @@ -395,7 +412,7 @@ int npc_event_do(const char* name) else { struct event_data *ev = strdb_get(npc->ev_db, name); if (ev) { - script->run(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id); return 1; } } @@ -539,7 +556,7 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data) { return 0; } - if( ted->rid && !(sd = map->id2sd(ted->rid)) ) { + if (ted->rid && (sd = map->id2sd(ted->rid)) == NULL) { ShowError("npc_timerevent: Attached player not found.\n"); ers_free(npc->timer_event_ers, ted); return 0; @@ -580,7 +597,7 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data) { } // Run the script - script->run(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id); + script->run_npc(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 ) @@ -604,7 +621,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid) { // 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)) ) { + if (nd->u.scr.rid > 0 && (sd = map->id2sd(nd->u.scr.rid)) == NULL) { // Failed to attach timer to this player. ShowError("npc_timerevent_start: Attached player not found!\n"); return 1; @@ -653,7 +670,7 @@ int npc_timerevent_stop(struct npc_data* nd) nullpo_ret(nd); - if (nd->u.scr.rid && !(sd = map->id2sd(nd->u.scr.rid))) { + if (nd->u.scr.rid && (sd = map->id2sd(nd->u.scr.rid)) == NULL) { ShowError("npc_timerevent_stop: Attached player not found!\n"); return 1; } @@ -729,7 +746,7 @@ void npc_timerevent_quit(struct map_session_data* sd) nd->u.scr.timer = ted->time; //Execute label - script->run(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id); + script->run_npc(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id); //Restore previous data. nd->u.scr.rid = old_rid; @@ -806,7 +823,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char npc->event_dequeue(sd); return 2; } - script->run(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); return 0; } @@ -1051,7 +1068,7 @@ int npc_touch_areanpc2(struct mob_data *md) break; // No OnTouchNPC Event md->areanpc_id = map->list[m].npc[i]->bl.id; id = md->bl.id; // Stores Unique ID - script->run(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id); + script->run_npc(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; } @@ -1082,7 +1099,7 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { i = 0; for (ys = y0; ys <= y1 && !i; ys++) { for(xs = x0; xs <= x1 && !i; xs++) { - if (map->getcell(m,xs,ys,CELL_CHKNPC)) + if (map->getcell(m, NULL, xs, ys, CELL_CHKNPC)) i = 1; } } @@ -1222,7 +1239,7 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) if ((nd = npc->checknear(sd,&nd->bl)) == NULL) return 1; - + //Hidden/Disabled npc. if (nd->class_ < 0 || nd->option&(OPTION_INVISIBLE|OPTION_HIDE)) return 1; @@ -1239,7 +1256,7 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) if( !npc->trader_open(sd,nd) ) return 1; } else - script->run(nd->u.scr.script,0,sd->bl.id,nd->bl.id); + script->run_npc(nd->u.scr.script,0,sd->bl.id,nd->bl.id); break; case TOMB: npc->run_tomb(sd,nd); @@ -1264,7 +1281,7 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) { nd?(char*)nd->name:"'Unknown NPC'", (int)id); return 1; } - + if(id != npc->fake_nd->bl.id) { // Not item script if ((npc->checknear(sd,target)) == NULL){ ShowWarning("npc_scriptcont: failed npc->checknear test.\n"); @@ -1286,10 +1303,10 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) { **/ if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,timer->gettick()) > 0 ) return 1; - + if( !sd->st ) return 1; - + if( closing && sd->st->state == CLOSE ) sd->st->state = END; @@ -1310,12 +1327,11 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { return 1; if ( nd->subtype != SHOP && !(nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->items) ) { - if( nd->subtype == SCRIPT ) ShowError("npc_buysellsel: trader '%s' has no shop list!\n",nd->exname); else ShowError("npc_buysellsel: no such shop npc %d (%s)\n",id,nd->exname); - + if (sd->npc_id == id) sd->npc_id = 0; return 1; @@ -1323,7 +1339,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { if (nd->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; } @@ -1337,7 +1353,6 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { } else { clif->selllist(sd); } - return 0; } @@ -1355,13 +1370,13 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns if( count <= 0 ) return ERROR_TYPE_ITEM_ID; - + if( points < 0 ) return ERROR_TYPE_MONEY; - + if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) return ERROR_TYPE_NPC; - + if( nd->subtype != CASHSHOP ) { if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) { shop = nd->u.scr.shop->item; @@ -1372,7 +1387,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; } - + new_ = 0; w = 0; vt = 0; // Global Value @@ -1409,10 +1424,10 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns if( w + sd->weight > sd->max_weight ) return ERROR_TYPE_INVENTORY_WEIGHT; - + if( pc->inventoryblank(sd) < new_ ) return ERROR_TYPE_INVENTORY_WEIGHT; - + if( points > vt ) points = vt; // Payment Process ---------------------------------------------------- @@ -1475,7 +1490,7 @@ void npc_market_fromsql(void) { char name[NAME_LENGTH+1]; int itemid; int amount; - + if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `%s`", map->npc_market_data_db) || SQL_ERROR == SQL->StmtExecute(stmt) ) { @@ -1483,15 +1498,15 @@ void npc_market_fromsql(void) { SQL->StmtFree(stmt); return; } - + SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name[0], sizeof(name), NULL, NULL); SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, 0, NULL, NULL); SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, 0, NULL, NULL); - + while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) { struct npc_data *nd = NULL; unsigned short i; - + if( !(nd = npc->name2id(name)) ) { ShowError("npc_market_fromsql: NPC '%s' not found! skipping...\n",name); npc->market_delfromsql_sub(name, USHRT_MAX); @@ -1501,22 +1516,20 @@ void npc_market_fromsql(void) { npc->market_delfromsql_sub(name, USHRT_MAX); continue; } - + for(i = 0; i < nd->u.scr.shop->items; i++) { if( nd->u.scr.shop->item[i].nameid == itemid ) { nd->u.scr.shop->item[i].qty = amount; break; } } - + if( i == nd->u.scr.shop->items ) { ShowError("npc_market_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n",name,itemid,amount); npc->market_delfromsql_sub(name, itemid); continue; } - } - SQL->StmtFree(stmt); } /** @@ -1550,10 +1563,9 @@ void npc_market_delfromsql(struct npc_data *nd, unsigned short index) { * Judges whether to allow and spawn a trader's window. **/ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { - if( !nd->u.scr.shop || !nd->u.scr.shop->items ) return false; - + switch( nd->u.scr.shop->type ) { case NST_ZENY: sd->state.callshop = 1; @@ -1561,15 +1573,15 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { return true;/* we skip sd->npc_shopid, npc->buysell will set it then when the player selects */ case NST_MARKET: { unsigned short i; - + for(i = 0; i < nd->u.scr.shop->items; i++) { if( nd->u.scr.shop->item[i].qty ) break; } - + /* nothing to display, no items available */ - if( i == nd->u.scr.shop->items ) { - clif->colormes(sd->fd,COLOR_RED, msg_sd(sd,881)); + if (i == nd->u.scr.shop->items) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,881)); return false; } @@ -1580,9 +1592,7 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { clif->cashshop_show(sd,nd); break; } - sd->npc_shopid = nd->bl.id; - return true; } /** @@ -1594,21 +1604,19 @@ void npc_trader_update(int master) { DBIterator* iter; struct block_list* bl; struct npc_data *master_nd = map->id2nd(master); - + CREATE(master_nd->u.scr.shop,struct npc_shop_data,1); - + iter = db_iterator(map->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; - + if( nd->src_id == master ) { nd->u.scr.shop = master_nd->u.scr.shop; } } } - dbi_destroy(iter); } /** @@ -1620,9 +1628,9 @@ void npc_trader_update(int master) { void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; - + npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */ - + switch( nd->u.scr.shop->type ) { case NST_CASH: npc->trader_funds[0] = sd->cashPoints; @@ -1634,14 +1642,14 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { ShowError("npc_trader_count_funds: unsupported shop type %d\n",nd->u.scr.shop->type); return; } - + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnCountFunds",nd->exname); - + if ( (ev = strdb_get(npc->ev_db, evname)) ) - script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); else ShowError("npc_trader_count_funds: '%s' event '%s' not found, operation failed\n",nd->exname,evname); - + /* the callee will rely on npc->trader_funds, upon success script->run updates them */ } /** @@ -1657,19 +1665,17 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, int points) { char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; - + npc->trader_ok = false;/* clear */ - + snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname); - if ( (ev = strdb_get(npc->ev_db, evname)) ) { pc->setreg(sd,script->add_str("@price"),price); pc->setreg(sd,script->add_str("@points"),points); - - script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); + script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); } else ShowError("npc_trader_pay: '%s' event '%s' not found, operation failed\n",nd->exname,evname); - + return npc->trader_ok;/* run script will deal with it */ } /*========================================== @@ -1681,7 +1687,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po struct npc_item_list *shop = NULL; int i, price, w; unsigned short shop_size = 0; - + if( amount <= 0 ) return ERROR_TYPE_ITEM_ID; @@ -1690,7 +1696,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po if( sd->state.trading ) return ERROR_TYPE_EXCHANGE; - + if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) return ERROR_TYPE_NPC; @@ -1707,12 +1713,12 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; } - + ARR_FIND(0, shop_size, i, shop[i].nameid == nameid); - + if( i == shop_size ) return ERROR_TYPE_ITEM_ID; - + if( shop[i].value <= 0 ) return ERROR_TYPE_ITEM_ID; @@ -1745,7 +1751,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po } price = shop[i].value * amount; - + if( points > price ) points = price; @@ -1755,7 +1761,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po } else { if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) return ERROR_TYPE_MONEY; - + pc->paycash(sd, price, points); } @@ -1781,14 +1787,14 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { double z; int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT); unsigned short shop_size = 0; - + 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 ) { if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type == NST_ZENY ) { shop = nd->u.scr.shop->item; @@ -1799,76 +1805,76 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; } - + 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, shop_size, j, item_list[i*2+1] == shop[j].nameid || //Normal items item_list[i*2+1] == itemdb_viewid(shop[j].nameid) //item_avail replacement ); - + if( j == shop_size ) return 3; // no such item in shop - + amount = item_list[i*2+0]; nameid = item_list[i*2+1] = shop[j].nameid; //item_avail replacement value = shop[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 non-stackable 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]; - + if (itemdb_type(nameid) == IT_PETEGG) { pet->create_egg(sd, nameid); } else { @@ -1876,16 +1882,16 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { 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_t = pc->checkskill2(sd,idx)) > 0 ) { if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0; - + if( skill_t > 0 ) { z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; if( z < 1 ) @@ -1893,7 +1899,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { pc->gainexp(sd,NULL,0,(int)z, false); } } - + return 0; } @@ -1906,7 +1912,7 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st double z; int i,j,w,new_; unsigned short shop_size = 0; - + nullpo_retr(1, sd); nullpo_retr(1, p); @@ -1917,21 +1923,21 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st shop = nd->u.scr.shop->item; shop_size = nd->u.scr.shop->items; - + z = 0; w = 0; new_ = 0; - + // process entries in buy list, one by one for( i = 0; i < list_size; ++i ) { int nameid, amount, value; - + // find this entry in the shop's sell list ARR_FIND( 0, shop_size, j, p->list[i].ITID == shop[j].nameid || //Normal items p->list[i].ITID == itemdb_viewid(shop[j].nameid) //item_avail replacement ); - + if( j == shop_size ) /* TODO find official response for this */ return 1; // no such item in shop @@ -1945,26 +1951,24 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st if( !itemdb->exists(nameid) ) /* TODO find official response for this */ return 1; // 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 non-stackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = p->list[i].qty = 1; } - + switch( pc->checkadditem(sd,nameid,amount) ) { case ADDITEM_EXIST: break; - case ADDITEM_NEW: new_++; break; - case ADDITEM_OVERAMOUNT: /* TODO find official response for this */ return 1; } - + z += (double)value * amount; w += itemdb_weight(nameid) * amount; } @@ -1979,20 +1983,20 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st return 1; // Not enough space to store items pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - + for( i = 0; i < list_size; ++i ) { int nameid = p->list[i].ITID; int amount = p->list[i].qty; - + j = npc_market_qty[i]; - + if( p->list[i].qty > shop[j].qty ) /* wohoo someone tampered with the packet. */ return 1; - + shop[j].qty -= amount; - + npc->market_tosql(nd,j); - + if (itemdb_type(nameid) == IT_PETEGG) { pet->create_egg(sd, nameid); } else { @@ -2000,7 +2004,7 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; - + pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); } } @@ -2042,18 +2046,17 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li 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); + // process item 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]); - } + for (j = 0; j < MAX_SLOTS; j++) { + // store each of the cards/special info from the item 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 @@ -2062,7 +2065,6 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li return 0; } - /// Player item selling to npc shop. /// /// @param item_list 'n' pairs <index,amount> @@ -2084,7 +2086,6 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) return 1; } - z = 0; // verify the sell list @@ -2130,7 +2131,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) } } - pc->delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC); + pc->delitem(sd, idx, amount, 0, DELITEM_SOLD, LOG_TYPE_NPC); } if( z > MAX_ZENY ) @@ -2230,7 +2231,7 @@ int npc_unload(struct npc_data* nd, bool single) if( nd->ud && nd->ud != &npc->base_ud ) { skill->clear_unitgroup(&nd->bl); } - + npc->remove_map(nd); map->deliddb(&nd->bl); if( single ) @@ -2254,7 +2255,7 @@ int npc_unload(struct npc_data* nd, bool single) aFree(nd->path);/* remove now that no other instances exist */ } } - + if( single && nd->bl.m != -1 ) map->remove_questinfo(nd->bl.m,nd); @@ -2268,7 +2269,7 @@ int npc_unload(struct npc_data* nd, bool single) npc->ev_db->foreach(npc->ev_db,npc->unload_ev,nd->exname); //Clean up all events related npc->ev_label_db->foreach(npc->ev_label_db,npc->unload_ev_label,nd); } - + 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); @@ -2520,6 +2521,8 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c } else { // NPC has an ID specified for view id. val = atoi(w4); + if (val != -1) + ShowWarning("npc_parseview: Use of numeric NPC view IDs is deprecated and may be removed in a future update. Please use NPC view constants instead. ID '%d' specified in file '%s', line '%d'.\n", val, filepath, strline(buffer, start-buffer)); } return val; @@ -2628,7 +2631,7 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');;//try next } - + nd = npc->create_npc(m, x, y); map->addnpc(m, nd); npc->parsename(nd, w3, start, buffer, filepath); @@ -2690,6 +2693,12 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s return strchr(start,'\n');// skip and continue } + if (dir < 0 || dir > 7) { + ShowError("npc_parse_ship: Invalid NPC facing direction '%d' in file '%s', line '%d'.\n", dir, filepath, strline(buffer, start-buffer)); + if (retval) *retval = EXIT_FAILURE; + return strchr(start,'\n');//continue + } + m = map->mapname2mapid(mapname); } @@ -2698,7 +2707,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');//try next } - + if( strcmp(w2,"cashshop") == 0 ) type = CASHSHOP; else @@ -2796,14 +2805,14 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) { int i; - + for( i = 0; i < script->label_count; i++ ) { const char* lname = script->get_str(script->labels[i].key); int lpos = script->labels[i].pos; struct npc_label_list* label; const char *p; size_t len; - + // In case of labels not terminated with ':', for user defined function support p = lname; @@ -2816,9 +2825,9 @@ void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath ShowError("npc_parse_script: label name longer than 23 chars! (%s) in file '%s'.\n", lname, filepath); return; } - + label = &label_list[i]; - + safestrncpy(label->name, lname, sizeof(label->name)); label->pos = lpos; } @@ -2915,6 +2924,13 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* script_start = strstr(start,",{"); end = strchr(start,'\n'); + + if (dir < 0 || dir > 7) { + ShowError("npc_parse_script: Invalid NPC facing direction '%d' in file '%s', line '%d'.\n", dir, filepath, strline(buffer, start-buffer)); + if (retval) *retval = EXIT_FAILURE; + return npc->skip_script(script_start, buffer, filepath, retval); // continue + } + 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); @@ -2927,13 +2943,10 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* if( end == NULL ) return NULL;// (simple) parse error, don't continue - script->parser_current_npc_name = w3; - scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB, retval); - script->parser_current_npc_name = NULL; - + label_list = NULL; label_list_num = 0; if( script->label_count ) { @@ -2963,7 +2976,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* if( options&NPO_TRADER ) nd->u.scr.trader = true; nd->u.scr.shop = NULL; - + ++npc_script; nd->bl.type = BL_NPC; nd->subtype = SCRIPT; @@ -3007,7 +3020,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) { //Execute OnInit - script->run(nd->u.scr.script,ev->pos,0,nd->bl.id); + script->run_npc(nd->u.scr.script,ev->pos,0,nd->bl.id); } } @@ -3072,6 +3085,11 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } + if (dir < 0 || dir > 7) { + ShowError("npc_parse_duplicate: Invalid NPC facing direction '%d' in file '%s', line '%d'.\n", dir, filepath, strline(buffer, start-buffer)); + if (retval) *retval = EXIT_FAILURE; + return end; // try next + } m = map->mapname2mapid(mapname); } @@ -3080,7 +3098,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if (retval) *retval = EXIT_FAILURE; return end;//try next } - + if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany> else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY> else if( type == WARP ) { @@ -3173,7 +3191,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) { //Execute OnInit - script->run(nd->u.scr.script,ev->pos,0,nd->bl.id); + script->run_npc(nd->u.scr.script,ev->pos,0,nd->bl.id); } } @@ -3264,7 +3282,7 @@ void npc_setcells(struct npc_data* nd) { for (i = y-ys; i <= y+ys; i++) { for (j = x-xs; j <= x+xs; j++) { - if (map->getcell(m, j, i, CELL_CHKNOPASS)) + if (map->getcell(m, &nd->bl, j, i, CELL_CHKNOPASS)) continue; map->list[m].setcell(m, j, i, CELL_NPC, true); } @@ -3301,10 +3319,10 @@ void npc_unsetcells(struct npc_data* nd) { //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->list[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->list[m].ys-1 && map->getcell(m, x, y1, CELL_CHKNPC); y1++); + for(x0 = x-xs; x0 > 0 && map->getcell(m, &nd->bl, x0, y, CELL_CHKNPC); x0--); + for(x1 = x+xs; x1 < map->list[m].xs-1 && map->getcell(m, &nd->bl, x1, y, CELL_CHKNPC); x1++); + for(y0 = y-ys; y0 > 0 && map->getcell(m, &nd->bl, x, y0, CELL_CHKNPC); y0--); + for(y1 = y+ys; y1 < map->list[m].ys-1 && map->getcell(m, &nd->bl, x, y1, CELL_CHKNPC); y1++); //Erase this npc's cells for (i = y-ys; i <= y+ys; i++) @@ -3449,7 +3467,7 @@ const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const cha scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT, retval); script->parser_current_npc_name = NULL; - + if( scriptroot == NULL )// parse error, continue return end; @@ -3465,7 +3483,6 @@ const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const cha return end; } - /*========================================== * Parse Mob 1 - Parse mob list into each map * Parse Mob 2 - Actually Spawns Mob @@ -3496,10 +3513,10 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st // 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 + // w4=<mob id>,<amount>,<delay1>,<delay2>{,<event>,<mob size>,<mob ai>} + if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 5 || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1 - || sscanf(w4, "%d,%d,%u,%u,%50[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2 + || sscanf(w4, "%d,%d,%u,%u,%50[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 4 ) { 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); if (retval) *retval = EXIT_FAILURE; @@ -3540,7 +3557,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st return strchr(start, '\n'); } - if (mobspawn.state.ai > 4 && ai != -1) { + if (mobspawn.state.ai >= AI_MAX && ai != -1) { ShowError("npc_parse_mob: Invalid ai %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer)); if (retval) *retval = EXIT_FAILURE; return strchr(start, '\n'); @@ -3563,7 +3580,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st mobspawn.level = mob_lv; if (size > 0 && size <= 2) mobspawn.state.size = size; - if (ai > 0 && ai <= 4) + if (ai > AI_NONE && ai < AI_MAX) mobspawn.state.ai = ai; if (mobspawn.num > 1 && battle_config.mob_count_rate != 100) { @@ -3747,7 +3764,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; } - if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) && map->list[m].zone != zone ) { + if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) != NULL && map->list[m].zone != zone ) { map->zone_change(m,zone,start,buffer,filepath); } else if ( !state ) { map->list[m].zone = &map->zone_all; @@ -3787,7 +3804,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].flag.pvp_nocalcrank=state; else if (!strcmpi(w3,"gvg")) { struct map_zone_data *zone; - + map->list[m].flag.gvg = state; if( state && map->list[m].flag.pvp ) { map->list[m].flag.pvp = 0; @@ -3799,7 +3816,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; } - if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) && map->list[m].zone != zone ) { + if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) != NULL && map->list[m].zone != zone ) { map->zone_change(m,zone,start,buffer,filepath); } } @@ -3815,13 +3832,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char } else if (!strcmpi(w3,"battleground")) { struct map_zone_data *zone; - if( state ) { - if( sscanf(w4, "%d", &state) == 1 ) + if (state) { + if (w4 && sscanf(w4, "%d", &state) == 1) map->list[m].flag.battleground = state; else map->list[m].flag.battleground = 1; // Default value - } else + } else { map->list[m].flag.battleground = 0; + } if( map->list[m].flag.battleground && map->list[m].flag.pvp ) { map->list[m].flag.pvp = 0; @@ -3835,8 +3853,8 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; } - - if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) && map->list[m].zone != zone ) { + + if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) != NULL && map->list[m].zone != zone ) { map->zone_change(m,zone,start,buffer,filepath); } } @@ -3921,11 +3939,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char int skill_id, k; char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; size_t len = w4 ? strlen(w4) : 0; - + modifier[0] = '\0'; if( w4 ) memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH); - + for(k = 0; k < len; k++) { if( skill_name[k] == '\t' ) { memcpy(modifier, &skill_name[k+1], len - k); @@ -3933,7 +3951,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char break; } } - + if( modifier[0] == '\0' ) { ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; @@ -3945,9 +3963,9 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char if (retval) *retval = EXIT_FAILURE; } else { int idx = map->list[m].unit_count; - + ARR_FIND(0, idx, k, map->list[m].units[k]->skill_id == skill_id); - + if( k < idx ) { if( atoi(modifier) != 100 ) map->list[m].units[k]->modifier = (unsigned short)atoi(modifier); @@ -3958,9 +3976,9 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char for( k = 0; k < idx; k++ ) { if( map->list[m].units[k] == NULL ) continue; - + map->list[m].units[cursor] = map->list[m].units[k]; - + cursor++; } if( !( map->list[m].unit_count = cursor ) ) { @@ -3979,12 +3997,12 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char int skill_id, k; char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; size_t len = w4 ? strlen(w4) : 0; - + modifier[0] = '\0'; - + if( w4 ) memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH); - + for(k = 0; k < len; k++) { if( skill_name[k] == '\t' ) { memcpy(modifier, &skill_name[k+1], len - k); @@ -3992,7 +4010,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char break; } } - + if( modifier[0] == '\0' ) { ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; @@ -4004,9 +4022,9 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char if (retval) *retval = EXIT_FAILURE; } else { int idx = map->list[m].skill_count; - + ARR_FIND(0, idx, k, map->list[m].skills[k]->skill_id == skill_id); - + if( k < idx ) { if( atoi(modifier) != 100 ) map->list[m].skills[k]->modifier = (unsigned short)atoi(modifier); @@ -4017,9 +4035,9 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char for( k = 0; k < idx; k++ ) { if( map->list[m].skills[k] == NULL ) continue; - + map->list[m].skills[cursor] = map->list[m].skills[k]; - + cursor++; } if( !( map->list[m].skill_count = cursor ) ) { @@ -4033,11 +4051,10 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].skills[idx]->skill_id = (unsigned short)skill_id; map->list[m].skills[idx]->modifier = (unsigned short)atoi(modifier); } - } } else if (!strcmpi(w3,"zone")) { struct map_zone_data *zone; - + if( !(zone = strdb_get(map->zone_db, w4)) ) { ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s in file '%s', line '%d'.\n", w4, map->list[m].name, filepath, strline(buffer,start-buffer)); if (retval) *retval = EXIT_FAILURE; @@ -4414,9 +4431,8 @@ int npc_reload(void) { npc_last_npd = NULL; npc_last_path = NULL; npc_last_ref = NULL; - - //Remove all npcs/mobs. [Skotlex] + //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) { @@ -4543,14 +4559,14 @@ void npc_debug_warps_sub(struct npc_data* nd) { 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)) { + if (map->getcell(m, &nd->bl, 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->list[nd->bl.m].name, nd->bl.x, nd->bl.y, map->list[m].name, nd->u.warp.x, nd->u.warp.y ); } - if (map->getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) { + if (map->getcell(m, &nd->bl, 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->list[nd->bl.m].name, nd->bl.x, nd->bl.y, @@ -4580,7 +4596,7 @@ int do_init_npc(bool minimal) { npc->base_ud.attackabletime = npc->base_ud.canact_tick = npc->base_ud.canmove_tick = timer->gettick(); - + //Stock view data for normal npcs. memset(&npc_viewdb, 0, sizeof(npc_viewdb)); @@ -4608,12 +4624,12 @@ int do_init_npc(bool minimal) { npc_process_files(START_NPC_NUM); } - + if (!minimal) { map->zone_init(); - + npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */ - + // set up the events cache memset(script_event, 0, sizeof(script_event)); npc->read_event_script(); @@ -4625,7 +4641,7 @@ int do_init_npc(bool minimal) { timer->add_func_list(npc->event_do_clock,"npc_event_do_clock"); timer->add_func_list(npc->timerevent,"npc_timerevent"); } - + if( script->lang_export_fp ) { ShowInfo("Lang exported to '%s'\n",script->lang_export_file); fclose(script->lang_export_fp); diff --git a/src/map/npc.h b/src/map/npc.h index 68d683847..14b89d128 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -5,11 +5,11 @@ #ifndef MAP_NPC_H #define MAP_NPC_H -#include "map.h" // struct block_list -#include "status.h" // struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" // struct block_list +#include "map/status.h" // struct status_change +#include "map/unit.h" // struct unit_data +#include "common/hercules.h" +#include "common/db.h" struct HPluginData; struct view_data; @@ -121,7 +121,7 @@ enum actor_classes { // Old NPC range #define MAX_NPC_CLASS 1000 // New NPC range -#define MAX_NPC_CLASS2_START 10000 +#define MAX_NPC_CLASS2_START 10001 #define MAX_NPC_CLASS2_END 10110 //Script NPC events. @@ -279,16 +279,15 @@ struct npc_interface { int (*secure_timeout_timer) (int tid, int64 tick, int id, intptr_t data); }; -struct npc_interface *npc; - #ifdef HERCULES_CORE void npc_defaults(void); #endif // HERCULES_CORE +HPShared struct npc_interface *npc; /* comes from npc_chat.c */ #ifdef PCRE_SUPPORT -#include "../../3rdparty/pcre/include/pcre.h" +#include <pcre/include/pcre.h> /* Structure containing all info associated with a single pattern block */ struct pcrematch_entry { struct pcrematch_entry* next; @@ -326,8 +325,6 @@ struct npc_chat_interface { void (*finalize_pcrematch_entry) (struct pcrematch_entry* e); }; -struct npc_chat_interface *npc_chat; - /** * pcre interface (libpcre) * so that plugins may share and take advantage of the core's pcre @@ -344,14 +341,16 @@ struct pcre_interface { int (*get_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr); }; -struct pcre_interface *libpcre; - /** * Also defaults libpcre **/ #ifdef HERCULES_CORE void npc_chat_defaults(void); #endif // HERCULES_CORE + +HPShared struct npc_chat_interface *npc_chat; +HPShared struct pcre_interface *libpcre; + #endif // PCRE_SUPPORT #endif /* MAP_NPC_H */ diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 8bc246819..503dbd845 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -8,28 +8,30 @@ #include "npc.h" // struct npc_data +#include "map/mob.h" // struct mob_data +#include "map/pc.h" // struct map_session_data +#include "map/script.h" // set_var() +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" + +#include <pcre/include/pcre.h> + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "../../3rdparty/pcre/include/pcre.h" - -#include "mob.h" // struct mob_data -#include "pc.h" // struct map_session_data -#include "script.h" // set_var() -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" - /** * interface sources **/ struct npc_chat_interface npc_chat_s; struct pcre_interface libpcre_s; +struct npc_chat_interface *npc_chat; +struct pcre_interface *libpcre; /** * Written by MouseJstr in a vision... (2/21/2005) @@ -78,7 +80,6 @@ struct pcre_interface libpcre_s; * deletes a pset */ - /** * delete everything associated with a entry * @@ -100,9 +101,9 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) { struct npc_parse *npcParse = 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; @@ -110,13 +111,13 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) { } 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; @@ -126,7 +127,6 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) { npcParse->inactive = pcreset; pcreset->setid = setid; } - return pcreset; } @@ -155,7 +155,7 @@ void activate_pcreset(struct npc_data* nd, int setid) pcreset->prev->next = pcreset->next; else npcParse->inactive = pcreset->next; - + pcreset->prev = NULL; pcreset->next = npcParse->active; if (pcreset->next != NULL) @@ -193,7 +193,7 @@ void deactivate_pcreset(struct npc_data* nd, int setid) pcreset->prev->next = pcreset->next; else npcParse->active = pcreset->next; - + pcreset->prev = NULL; pcreset->next = npcParse->inactive; if (pcreset->next != NULL) @@ -228,27 +228,26 @@ void delete_pcreset(struct npc_data* nd, int setid) } 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; npc_chat->finalize_pcrematch_entry(pcreset->head); aFree(pcreset->head); // Cleaning the last ones.. [Lance] pcreset->head = n; } - aFree(pcreset); } @@ -259,25 +258,25 @@ 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; } @@ -288,7 +287,7 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c { const char *err; int erroff; - + struct pcrematch_set * s = npc_chat->lookup_pcreset(nd, setid); struct pcrematch_entry *e = npc_chat->create_pcrematch_entry(s); e->pattern = aStrdup(pattern); @@ -308,13 +307,13 @@ void npc_chat_finalize(struct npc_data* nd) struct npc_parse *npcParse = nd->chatdb; if (npcParse == NULL) return; - + while(npcParse->active) npc_chat->delete_pcreset(nd, npcParse->active->setid); - + while(npcParse->inactive) npc_chat->delete_pcreset(nd, npcParse->inactive->setid); - + // Additional cleaning up [Lance] aFree(npcParse); } @@ -332,15 +331,15 @@ int npc_chat_sub(struct block_list* bl, va_list ap) 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) { @@ -348,7 +347,7 @@ int npc_chat_sub(struct block_list* bl, va_list ap) for (e = pcreset->head; e != NULL; e = e->next) { int offsets[2*10 + 10]; // 1/3 reserved for temp space required by pcre_exec - + // perform pattern match int r = libpcre->exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets)); if (r > 0) @@ -361,7 +360,7 @@ int npc_chat_sub(struct block_list* bl, va_list ap) libpcre->copy_substring(msg, offsets, r, i, val, sizeof(val)); script->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); @@ -369,14 +368,13 @@ int npc_chat_sub(struct block_list* bl, va_list ap) ShowWarning("npc_chat_sub: Unable to find label: %s\n", e->label); return 0; } - + // run the npc script - script->run(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id); + script->run_npc(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id); return 0; } } } - return 0; } @@ -386,7 +384,7 @@ BUILDIN(defpattern) { const char* pattern = script_getstr(st,3); const char* label = script_getstr(st,4); struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid); - + npc_chat->def_pattern(nd, setid, pattern, label); return true; @@ -395,7 +393,7 @@ BUILDIN(defpattern) { BUILDIN(activatepset) { int setid = script_getnum(st,2); struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid); - + npc_chat->activate_pcreset(nd, setid); return true; @@ -404,16 +402,16 @@ BUILDIN(activatepset) { BUILDIN(deactivatepset) { int setid = script_getnum(st,2); struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid); - + npc_chat->deactivate_pcreset(nd, setid); - + return true; } BUILDIN(deletepset) { int setid = script_getnum(st,2); struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid); - + npc_chat->delete_pcreset(nd, setid); return true; @@ -421,7 +419,7 @@ BUILDIN(deletepset) { void npc_chat_defaults(void) { npc_chat = &npc_chat_s; - + npc_chat->sub = npc_chat_sub; npc_chat->finalize = npc_chat_finalize; npc_chat->def_pattern = npc_chat_def_pattern; @@ -431,9 +429,9 @@ void npc_chat_defaults(void) { npc_chat->activate_pcreset = activate_pcreset; npc_chat->lookup_pcreset = lookup_pcreset; npc_chat->finalize_pcrematch_entry = finalize_pcrematch_entry; - + libpcre = &libpcre_s; - + libpcre->compile = pcre_compile; libpcre->study = pcre_study; libpcre->exec = pcre_exec; diff --git a/src/map/packets.h b/src/map/packets.h index db332c033..ffa40ff7c 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -448,6 +448,8 @@ packet(0x020a,10); //packet(0x020b,-1); //packet(0x020c,-1); packet(0x020d,-1); +packet(0x974,2,clif->cancelmergeitem); +packet(0x96e,-1,clif->ackmergeitems); //2004-07-05aSakexe #if PACKETVER >= 20040705 @@ -2816,7 +2818,6 @@ packet(0x020d,-1); packet(0x0A22,5); // HEADER_ZC_RECV_ROULETTE_ITEM #endif - // 2014-10-22bRagexe - YomRawr #if PACKETVER >= 20141022 packet(0x0369,7,clif->pActionRequest,2,6); @@ -2848,6 +2849,17 @@ packet(0x020d,-1); packet(0x091A,26,clif->pFriendsListAdd,2); packet(0x0899,5,clif->pHomMenu,2,4); packet(0x0438,36,clif->pStoragePassword,0); + packet(0x0A01,3,clif->pHotkeyRowShift,2); +#endif + +#if PACKETVER >= 20150226 + packet(0x0A09,45); + packet(0x0A0A,47); + packet(0x0A0B,47); + packet(0x0A0C,56); + packet(0x0A0D,-1); + packet(0x0A0F,-1); + packet(0x0A10,-1); #endif // 2015-05-13aRagexe @@ -2883,9 +2895,9 @@ packet(0x020d,-1); packet(0x0923,36,clif->pStoragePassword,0); packet(0x09e8,11,clif->pDull); //CZ_OPEN_MAILBOX packet(0x0a2e,6,clif->pDull); //TITLE -#endif +#endif -/* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ +/* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ #if PACKETVER >= 20110817 packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */ #endif diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 71471e5c6..8f9747747 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -1,13 +1,13 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -/* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */ +/* Hercules Renewal: Phase Two http://herc.ws/board/topic/383-hercules-renewal-phase-two/ */ #ifndef MAP_PACKETS_STRUCT_H #define MAP_PACKETS_STRUCT_H -#include "../common/cbasetypes.h" -#include "../common/mmo.h" +#include "common/cbasetypes.h" +#include "common/mmo.h" /** * @@ -18,14 +18,44 @@ enum packet_headers { banking_checkType = 0x9a6, cart_additem_ackType = 0x12c, sc_notickType = 0x196, +#if PACKETVER >= 20141022 + hotkeyType = 0xa00, +#elif PACKETVER >= 20090603 + hotkeyType = 0x7d9, +#else + hotkeyType = 0x2b9, +#endif +#if PACKETVER >= 20150226 + cartaddType = 0xa0b, +#elif PACKETVER >= 5 + cartaddType = 0x1c5, +#else + cartaddType = 0x124, +#endif +#if PACKETVER >= 20150226 + storageaddType = 0xa0a, +#elif PACKETVER >= 5 + storageaddType = 0x1c4, +#else + storageaddType = 0xf4, +#endif +#if PACKETVER >= 20150226 + tradeaddType = 0xa09, +#elif PACKETVER >= 20100223 + tradeaddType = 0x80f, +#else + tradeaddType = 0x0e9, +#endif #if PACKETVER < 20061218 - additemType = 0xa0, + additemType = 0x0a0, #elif PACKETVER < 20071002 additemType = 0x29a, #elif PACKETVER < 20120925 additemType = 0x2d4, -#else +#elif PACKETVER < 20150226 additemType = 0x990, +#else + additemType = 0xa0c, #endif #if PACKETVER < 4 idle_unitType = 0x78, @@ -134,7 +164,9 @@ enum packet_headers { #else inventorylistnormalType = 0xa3, #endif -#if PACKETVER >= 20120925 +#if PACKETVER >= 20150226 + inventorylistequipType = 0xa0d, +#elif PACKETVER >= 20120925 inventorylistequipType = 0x992, #elif PACKETVER >= 20080102 inventorylistequipType = 0x2d0, @@ -152,7 +184,9 @@ enum packet_headers { #else storagelistnormalType = 0xa5, #endif -#if PACKETVER >= 20120925 +#if PACKETVER >= 20150226 + storagelistequipType = 0xa10, +#elif PACKETVER >= 20120925 storagelistequipType = 0x996, #elif PACKETVER >= 20080102 storagelistequipType = 0x2d1, @@ -170,7 +204,9 @@ enum packet_headers { #else cartlistnormalType = 0x123, #endif -#if PACKETVER >= 20120925 +#if PACKETVER >= 20150226 + cartlistequipType = 0xa0f, +#elif PACKETVER >= 20120925 cartlistequipType = 0x994, #elif PACKETVER >= 20080102 cartlistequipType = 0x2d2, @@ -179,6 +215,12 @@ enum packet_headers { #else cartlistequipType = 0x122, #endif +#if PACKETVER < 20100105 + vendinglistType = 0x133, +#else + vendinglistType = 0x800, +#endif + openvendingType = 0x136, #if PACKETVER >= 20120925 equipitemType = 0x998, #else @@ -213,8 +255,8 @@ enum packet_headers { #endif partyleaderchangedType = 0x7fc, rouletteinfoackType = 0xa1c, - roulettgenerateackType = 0xA20, - roulettercvitemackType = 0xA22, + roulettgenerateackType = 0xa20, + roulettercvitemackType = 0xa22, }; #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute @@ -256,6 +298,12 @@ struct NORMALITEM_INFO { #endif } __attribute__((packed)); +struct RndOptions { + short index; + short value; + unsigned char param; +} __attribute__((packed)); + struct EQUIPITEM_INFO { short index; unsigned short ITID; @@ -284,6 +332,10 @@ struct EQUIPITEM_INFO { #if PACKETVER >= 20100629 unsigned short wItemSpriteNumber; #endif +#if PACKETVER >= 20150226 + unsigned char option_count; + struct RndOptions option_data[5]; +#endif #if PACKETVER >= 20120925 struct { unsigned char IsIdentified : 1; @@ -344,6 +396,9 @@ struct packet_additem { #if PACKETVER >= 20071002 unsigned short bindOnEquipType; #endif +#if PACKETVER >= 20150226 + struct RndOptions option_data[5]; +#endif } __attribute__((packed)); struct packet_dropflooritem { @@ -360,8 +415,8 @@ struct packet_dropflooritem { unsigned char subY; short count; } __attribute__((packed)); -#if PACKETVER < 20091103 struct packet_idle_unit2 { +#if PACKETVER < 20091103 short PacketType; #if PACKETVER >= 20071106 unsigned char objecttype; @@ -392,8 +447,13 @@ struct packet_idle_unit2 { unsigned char ySize; unsigned char state; short clevel; +#else // ! PACKETVER < 20091103 + char UNUSED; +#endif // PACKETVER < 20091103 } __attribute__((packed)); + struct packet_spawn_unit2 { +#if PACKETVER < 20091103 short PacketType; #if PACKETVER >= 20071106 unsigned char objecttype; @@ -418,8 +478,11 @@ struct packet_spawn_unit2 { unsigned char PosDir[3]; unsigned char xSize; unsigned char ySize; +#else // ! PACKETVER < 20091103 + char UNUSED; +#endif // PACKETVER < 20091103 } __attribute__((packed)); -#endif + struct packet_spawn_unit { short PacketType; #if PACKETVER >= 20091103 @@ -1026,6 +1089,17 @@ struct packet_party_leader_changed { unsigned int new_leader_aid; } __attribute__((packed)); +struct packet_hotkey { + short PacketType; +#if PACKETVER >= 20141022 + char Rotate; +#endif + struct { + char isSkill; // 0: Item, 1:Skill + unsigned int ID; // Item/Skill ID + short count; // Item Quantity/Skill Level + } hotkey[MAX_HOTKEYS]; +} __attribute__((packed)); #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) diff --git a/src/map/party.c b/src/map/party.c index fb738a12b..db285a4b4 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -4,37 +4,38 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP +#include "config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP #include "party.h" +#include "map/atcommand.h" //msg_txt() +#include "map/battle.h" +#include "map/clif.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" // struct mob_data +#include "map/pc.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // last_tick +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" //msg_txt() -#include "battle.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" // struct mob_data -#include "pc.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // last_tick -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct party_interface party_s; +struct party_interface *party; /*========================================== * Fills the given party_member structure according to the sd provided. @@ -97,7 +98,7 @@ TBL_PC* party_sd_check(int party_id, int account_id, int char_id) { } int party_db_final(DBKey key, DBData *data, va_list ap) { struct party_data *p; - + if ((p = DB->data2ptr(data))) { if (p->instance) aFree(p->instance); @@ -113,7 +114,6 @@ int party_db_final(DBKey key, DBData *data, va_list ap) { aFree(p->hdata); } } - return 0; } /// Party data lookup using party id. @@ -167,7 +167,6 @@ int party_create(struct map_session_data *sd,char *name,int item,int 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); @@ -499,7 +498,6 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) { break; } } - return 0; } @@ -599,7 +597,7 @@ int party_broken(int party_id) instance->list[p->instance[j]].owner_id = 0; } } - + 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); @@ -640,7 +638,7 @@ int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) { if( (p=party->search(party_id))==NULL) return 0; - //Flag&1: Exp change denied. Flag&2: Item change denied. + //Flag&0x1: Exp change denied. Flag&0x10: Item change denied. if(!(flag&0x01) && p->party.exp != exp) p->party.exp=exp; if(!(flag&0x10) && p->party.item != item) { @@ -689,7 +687,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts //Change leadership. p->party.member[mi].leader = 0; p->party.member[tmi].leader = 1; - + /** update members **/ clif->PartyLeaderChanged(p->data[mi].sd, p->data[mi].sd->status.account_id, p->data[tmi].sd->status.account_id); @@ -954,13 +952,13 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b base_exp_bonus = base_exp; job_exp_bonus = job_exp; #endif - + for (i = 0; i < c; i++) { #ifdef RENEWAL_EXP if( !(src && src->type == BL_MOB && ((TBL_MOB*)src)->db->mexp) ){ struct mob_data *md = (TBL_MOB*)src; int rate = pc->level_penalty_mod(md->level - (sd[i])->status.base_level, md->status.race, md->status.mode, 1); - + base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX); job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX); } @@ -1117,7 +1115,7 @@ int party_sub_count_chorus(struct block_list *bl, va_list ap) { if (sd->state.autotrade) return 0; - + if (battle_config.idle_no_share && pc_isidle(sd)) return 0; @@ -1188,9 +1186,8 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi #ifndef PARTY_RECRUIT 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 = party->create_booking_data(); @@ -1201,17 +1198,17 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi clif->PartyBookingRegisterAck(sd, 2); return; } - + memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH); pb_ad->expiretime = (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 #else @@ -1243,26 +1240,25 @@ void party_booking_update(struct map_session_data *sd, short* job) { #ifndef PARTY_RECRUIT 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); - + if( pb_ad == NULL ) return; - + pb_ad->expiretime = (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; - + clif->PartyBookingUpdateNotify(sd, pb_ad); #else return; #endif } - void party_recruit_search(struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount) { #ifdef PARTY_RECRUIT struct party_booking_ad_info *pb_ad; @@ -1301,9 +1297,9 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid, 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; @@ -1333,7 +1329,6 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid, #endif } - bool party_booking_delete(struct map_session_data *sd) { struct party_booking_ad_info* pb_ad; @@ -1383,7 +1378,7 @@ void party_defaults(void) { party->searchname = party_searchname; party->getmemberid = party_getmemberid; party->getavailablesd = party_getavailablesd; - + party->create = party_create; party->created = party_created; party->request_info = party_request_info; diff --git a/src/map/party.h b/src/map/party.h index a541d03cb..c7893add2 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -5,12 +5,12 @@ #ifndef MAP_PARTY_H #define MAP_PARTY_H -#include <stdarg.h> +#include "map/map.h" // TBL_PC +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" // struct party -#include "map.h" // TBL_PC -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // struct party +#include <stdarg.h> #define PARTY_BOOKING_JOBS 6 #define PARTY_BOOKING_RESULTS 10 @@ -139,10 +139,10 @@ struct party_interface { int (*db_final) (DBKey key, DBData *data, va_list ap); }; -struct party_interface *party; - #ifdef HERCULES_CORE void party_defaults(void); #endif // HERCULES_CORE +HPShared struct party_interface *party; + #endif /* MAP_PARTY_H */ diff --git a/src/map/path.c b/src/map/path.c index 600dfc082..a482fc473 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -4,21 +4,21 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA #include "path.h" +#include "map/map.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" + +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> - -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" #define SET_OPEN 0 #define SET_CLOSED 1 @@ -29,6 +29,7 @@ #define DIR_EAST 8 struct path_interface path_s; +struct path_interface *path; /// @name Structures and defines for A* pathfinding /// @{ @@ -68,7 +69,7 @@ static const unsigned char walk_choices [3][3] = * Find the closest reachable cell, 'count' cells away from (x0,y0) in direction (dx,dy). * Income after the coordinates of the blow *------------------------------------------*/ -int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count) +int path_blownpos(struct block_list *bl, int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count) { struct map_data *md; @@ -87,7 +88,7 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count) } while( count > 0 && (dx != 0 || dy != 0) ) { - if( !md->getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) ) + if (!md->getcellp(md, bl, x0 + dx, y0 + dy, CELL_CHKPASS)) break; x0 += dx; @@ -101,7 +102,7 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count) /*========================================== * is ranged attack from (x0,y0) to (x1,y1) possible? *------------------------------------------*/ -bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,cell_chk cell) +bool path_search_long(struct shootpath_data *spd,struct block_list *bl,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,cell_chk cell) { int dx, dy; int wx = 0, wy = 0; @@ -158,7 +159,7 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 spd->y[spd->len] = y0; spd->len++; } - if (md->getcellp(md,x0,y0,cell)) + if (md->getcellp(md, bl, x0, y0, cell)) return false; } @@ -235,7 +236,7 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16 * flag: &1 = easy path search only * cell: type of obstruction to check for *------------------------------------------*/ -bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell) +bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell) { register int i, j, x, y, dx, dy; struct map_data *md; @@ -249,13 +250,13 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x md = &map->list[m]; //Do not check starting cell as that would get you stuck. - if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/) + if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md, bl, x0, y0, cell)*/) return false; // Check destination cell - if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md,x1,y1,cell)) + if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md, bl, x1, y1, cell)) return false; - + if( x0 == x1 && y0 == y1 ) { wpd->path_len = 0; wpd->path_pos = 0; @@ -286,7 +287,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x if( dx == 0 && dy == 0 ) break; // success - if( md->getcellp(md,x,y,cell) ) + if (md->getcellp(md, bl, x, y, cell)) break; // obstacle = failure } @@ -359,26 +360,26 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x break; } - if (y < ys && !md->getcellp(md, x, y+1, cell)) allowed_dirs |= DIR_NORTH; - if (y > 0 && !md->getcellp(md, x, y-1, cell)) allowed_dirs |= DIR_SOUTH; - if (x < xs && !md->getcellp(md, x+1, y, cell)) allowed_dirs |= DIR_EAST; - if (x > 0 && !md->getcellp(md, x-1, y, cell)) allowed_dirs |= DIR_WEST; + if (y < ys && !md->getcellp(md, bl, x, y+1, cell)) allowed_dirs |= DIR_NORTH; + if (y > 0 && !md->getcellp(md, bl, x, y-1, cell)) allowed_dirs |= DIR_SOUTH; + if (x < xs && !md->getcellp(md, bl, x+1, y, cell)) allowed_dirs |= DIR_EAST; + if (x > 0 && !md->getcellp(md, bl, x-1, y, cell)) allowed_dirs |= DIR_WEST; #define chk_dir(d) ((allowed_dirs & (d)) == (d)) // Process neighbors of current node - if (chk_dir(DIR_SOUTH|DIR_EAST) && !md->getcellp(md, x+1, y-1, cell)) + if (chk_dir(DIR_SOUTH|DIR_EAST) && !md->getcellp(md, bl, x+1, y-1, cell)) e += add_path(&open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5 if (chk_dir(DIR_EAST)) e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6 - if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, x+1, y+1, cell)) + if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, bl, x+1, y+1, cell)) e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7 if (chk_dir(DIR_NORTH)) e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0 - if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, x-1, y+1, cell)) + if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, bl, x-1, y+1, cell)) e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1 if (chk_dir(DIR_WEST)) e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2 - if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, x-1, y-1, cell)) + if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, bl, x-1, y-1, cell)) e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3 if (chk_dir(DIR_SOUTH)) e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4 @@ -408,7 +409,6 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x return false; } - //Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml bool check_distance(int dx, int dy, int distance) { @@ -488,7 +488,7 @@ int distance_client(int dx, int dy) void path_defaults(void) { path = &path_s; - + path->blownpos = path_blownpos; path->search_long = path_search_long; path->search = path_search; diff --git a/src/map/path.h b/src/map/path.h index eb42df6d0..14885d566 100644 --- a/src/map/path.h +++ b/src/map/path.h @@ -5,8 +5,8 @@ #ifndef MAP_PATH_H #define MAP_PATH_H -#include "map.h" // enum cell_chk -#include "../common/cbasetypes.h" +#include "map/map.h" // enum cell_chk +#include "common/hercules.h" #define MOVE_COST 10 #define MOVE_DIAGONAL_COST 14 @@ -42,21 +42,21 @@ struct shootpath_data { struct path_interface { // calculates destination cell for knockback - int (*blownpos) (int16 m, int16 x0, int16 y0, int16 dx, int16 dy, int count); + int (*blownpos) (struct block_list *bl, int16 m, int16 x0, int16 y0, int16 dx, int16 dy, int count); // tries to find a walkable path - bool (*search) (struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell); + bool (*search) (struct walkpath_data *wpd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell); // tries to find a shootable path - bool (*search_long) (struct shootpath_data *spd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, cell_chk cell); + bool (*search_long) (struct shootpath_data *spd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, cell_chk cell); bool (*check_distance) (int dx, int dy, int distance); unsigned int (*distance) (int dx, int dy); bool (*check_distance_client) (int dx, int dy, int distance); int (*distance_client) (int dx, int dy); }; -struct path_interface *path; - #ifdef HERCULES_CORE void path_defaults(void); #endif // HERCULES_CORE +HPShared struct path_interface *path; + #endif /* MAP_PATH_H */ diff --git a/src/map/pc.c b/src/map/pc.c index 00c09b108..dc7014701 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4,59 +4,61 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT +#include "config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT #include "pc.h" +#include "map/atcommand.h" // get_atcommand_level() +#include "map/battle.h" // battle_config +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" // is_day_of_*() +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" // guild-"search(), guild_request_info() +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" // struct mob_data +#include "map/npc.h" // fake_nd +#include "map/party.h" // party-"search() +#include "map/path.h" +#include "map/pc_groups.h" +#include "map/pet.h" // pet_unlocktarget() +#include "map/quest.h" +#include "map/script.h" // script_config +#include "map/skill.h" +#include "map/status.h" // struct status_data +#include "map/storage.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/core.h" // get_svn_revision() +#include "common/HPM.h" +#include "common/malloc.h" +#include "common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" // safestrncpy() +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "atcommand.h" // get_atcommand_level() -#include "battle.h" // battle_config -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" // is_day_of_*() -#include "duel.h" -#include "elemental.h" -#include "guild.h" // guild->search(), guild_request_info() -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" // struct mob_data -#include "npc.h" // fake_nd -#include "party.h" // party->search() -#include "path.h" -#include "pc_groups.h" -#include "pet.h" // pet_unlocktarget() -#include "quest.h" -#include "script.h" // script_config -#include "skill.h" -#include "status.h" // struct status_data -#include "storage.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/core.h" // get_svn_revision() -#include "../common/malloc.h" -#include "../common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // session[] -#include "../common/strlib.h" // safestrncpy() -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct pc_interface pc_s; +struct pc_interface *pc; //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 @@ -125,7 +127,7 @@ void pc_setinvincibletimer(struct map_session_data* sd, int val) { nullpo_retv(sd); val += map->list[sd->bl.m].invincible_time_inc; - + if( sd->invincible_timer != INVALID_TIMER ) timer->delete(sd->invincible_timer,pc->invincible_timer); sd->invincible_timer = timer->add(timer->gettick()+val,pc->invincible_timer,sd->bl.id,0); @@ -174,6 +176,28 @@ int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } +/** +* Get the possible number of spiritball that a player can call. +* @param sd the affected player structure +* @param min the minimum number of spiritball regardless the level of MO_CALLSPIRITS +* @retval total number of spiritball +**/ +int pc_getmaxspiritball(struct map_session_data *sd, int min) { + int result; + + nullpo_ret(sd); + + result = pc->checkskill(sd, MO_CALLSPIRITS); + + if ( min && result < min ) + result = min; + else if ( sd->sc.data[SC_RAISINGDRAGON] ) + result += sd->sc.data[SC_RAISINGDRAGON]->val1; + if ( result > MAX_SPIRITBALL ) + result = MAX_SPIRITBALL; + return result; +} + int pc_addspiritball(struct map_session_data *sd,int interval,int max) { int tid, i; @@ -493,9 +517,9 @@ void pc_rental_expire(struct map_session_data *sd, int i) { } break; } - + clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } void pc_inventory_rentals(struct map_session_data *sd) { @@ -599,14 +623,12 @@ int pc_makesavestatus(struct map_session_data *sd) sd->status.last_point.x = 0; sd->status.last_point.y = 0; } - + if( sd->status.save_point.map == 0 ) { sd->status.save_point.map = 1; sd->status.save_point.x = 0; sd->status.save_point.y = 0; } - - return 0; } @@ -629,6 +651,7 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo sd->canlog_tick = timer->gettick(); //Required to prevent homunculus copuing a base speed of 0. sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; + sd->state.warp_clean = 1; return 0; } @@ -861,12 +884,12 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, clif->updatestatus(b_sd, SP_JOBEXP); // Baby Skills - pc->skill(b_sd, WE_BABY, 1, 0); - pc->skill(b_sd, WE_CALLPARENT, 1, 0); + pc->skill(b_sd, WE_BABY, 1, SKILL_GRANT_PERMANENT); + pc->skill(b_sd, WE_CALLPARENT, 1, SKILL_GRANT_PERMANENT); // Parents Skills - pc->skill(p1_sd, WE_CALLBABY, 1, 0); - pc->skill(p2_sd, WE_CALLBABY, 1, 0); + pc->skill(p1_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT); + pc->skill(p2_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT); return true; } @@ -891,13 +914,13 @@ int pc_isequip(struct map_session_data *sd,int n) if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT)) return 1; - - if(item->elv && sd->status.base_level < (unsigned int)item->elv){ - clif->msg(sd, 0x6ED); + + if (item->elv && sd->status.base_level < (unsigned int)item->elv) { + clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL); return 0; } - if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){ - clif->msg(sd, 0x6ED); + if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) { + clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL); return 0; } if(item->sex != 2 && sd->status.sex != item->sex) @@ -906,11 +929,11 @@ int pc_isequip(struct map_session_data *sd,int n) if ( item->equip & EQP_AMMO ) { if ( (sd->state.active && !pc_iscarton(sd)) // check if sc data is already loaded. && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) { - clif->msg(sd, 0x5EF); + clif->msgtable(sd, MSG_ITEM_NEED_CART); return 0; } if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) { - clif->msg(sd, 0x59B); + clif->msgtable(sd, MSG_ITEM_NEED_MADO); return 0; } } @@ -984,7 +1007,7 @@ 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; int64 tick = timer->gettick(); - uint32 ip = session[sd->fd]->client_addr; + uint32 ip = sockt->session[sd->fd]->client_addr; sd->login_id2 = login_id2; @@ -1023,7 +1046,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim 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; @@ -1055,7 +1078,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->hchsysch_tick = tick; sd->idletime = sockt->last_tick; - + for(i = 0; i < MAX_SPIRITBALL; i++) sd->spirit_timer[i] = INVALID_TIMER; for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++) @@ -1081,11 +1104,11 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim if( sd->status.option & OPTION_INVISIBLE && !pc->can_use_command(sd, "@hide") ) sd->status.option &=~ OPTION_INVISIBLE; - + status->change_init(&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); @@ -1094,32 +1117,32 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->guild_y = -1; sd->disguise = -1; - + sd->instance = NULL; sd->instances = 0; - + sd->bg_queue.arena = NULL; sd->bg_queue.ready = 0; sd->bg_queue.client_has_bg_data = 0; sd->bg_queue.type = 0; - + sd->queues = NULL; sd->queues_count = 0; - + sd->state.dialog = 0; - + sd->delayed_damage = 0; - + if( battle_config.item_check ) sd->state.itemcheck = 1; - + // 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++ ) + for( i = 0; i < MAX_PC_FEELHATE; i++ ) sd->hate_mob[i] = -1; sd->quest_log = NULL; @@ -1132,9 +1155,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->vars_dirty = false; sd->vars_ok = false; sd->vars_received = 0x0; - + sd->lang_id = map->default_lang_id; - + //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); @@ -1169,7 +1192,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sprintf(buf, msg_sd(sd,1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts) clif->message(sd->fd, buf); } - + if (expiration_time != 0) { sd->expiration_time = expiration_time; } @@ -1198,7 +1221,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim /* [Ind/Hercules] */ sd->sc_display = NULL; sd->sc_display_count = 0; - + // Request all registries (auth is considered completed whence they arrive) intif->request_registry(sd,7); return true; @@ -1217,7 +1240,7 @@ void pc_authfail(struct map_session_data *sd) 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) + if (!sd || !bl || pos < 0 || pos >= MAX_PC_FEELHATE) return 0; if (sd->hate_mob[pos] != -1) { //Can't change hate targets. @@ -1281,7 +1304,7 @@ int pc_reg_received(struct map_session_data *sd) if ((i = pc->checkskill(sd,RG_PLAGIARISM)) > 0) { sd->cloneskill_id = pc_readglobalreg(sd,script->add_str("CLONE_SKILL")); - if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id))) { + if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id)) > 0) { sd->status.skill[idx].id = sd->cloneskill_id; sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("CLONE_SKILL_LV")); if (sd->status.skill[idx].lv > i) @@ -1291,7 +1314,7 @@ int pc_reg_received(struct map_session_data *sd) } if ((i = pc->checkskill(sd,SC_REPRODUCE)) > 0) { sd->reproduceskill_id = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL")); - if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id))) { + if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id)) > 0) { sd->status.skill[idx].id = sd->reproduceskill_id; sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL_LV")); if( i < sd->status.skill[idx].lv) @@ -1299,7 +1322,7 @@ int pc_reg_received(struct map_session_data *sd) sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED; } } - + //Weird... maybe registries were reloaded? if (sd->state.active) return 0; @@ -1345,7 +1368,7 @@ int pc_reg_received(struct map_session_data *sd) clif->message(sd->fd, msg_sd(sd,11)); // Invisible: On // decrement the number of pvp players on the map map->list[sd->bl.m].users_pvp--; - + if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {// unregister the player for ranking timer->delete( sd->pvp_timer, pc->calc_pvprank_timer ); sd->pvp_timer = INVALID_TIMER; @@ -1355,7 +1378,7 @@ int pc_reg_received(struct map_session_data *sd) if( npc->motd ) /* [Ind/Hercules] */ script->run(npc->motd->u.scr.script, 0, sd->bl.id, npc->fake_nd->bl.id); - + return 1; } @@ -1367,7 +1390,7 @@ int pc_calc_skillpoint(struct map_session_data* sd) { for (i = 1; i < MAX_SKILL; i++) { int skill_lv = pc->checkskill2(sd,i); if (skill_lv > 0) { - inf2 = skill->db[i].inf2; + inf2 = skill->dbs->db[i].inf2; if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL|INF2_GUILD_SKILL)) //Do not count wedding/link skills. [Skotlex] ) { @@ -1382,7 +1405,6 @@ int pc_calc_skillpoint(struct map_session_data* sd) { return skill_point; } - /*========================================== * Calculation of skill level. *------------------------------------------*/ @@ -1400,13 +1422,13 @@ int pc_calc_skilltree(struct map_session_data *sd) return 1; } c = pc->class2idx(c); - + for( i = 0; i < MAX_SKILL; i++ ) { if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these sd->status.skill[i].id = 0; //First clear skills. /* permanent skills that must be re-checked */ if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) { - switch( skill->db[i].nameid ) { + switch( skill->dbs->db[i].nameid ) { case NV_TRICKDEAD: if( (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { sd->status.skill[i].id = 0; @@ -1425,21 +1447,21 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->db[i].nameid >= DC_HUMMING && skill->db[i].nameid <= DC_SERVICEFORYOU ) + if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU ) { //Enable Bard/Dancer spirit linked skills. if( sd->status.sex ) { //Link dancer skills to bard. // i can be < 8? if( sd->status.skill[i-8].lv < 10 ) continue; - sd->status.skill[i].id = skill->db[i].nameid; + sd->status.skill[i].id = skill->dbs->db[i].nameid; 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; // i can be < 8? - sd->status.skill[i-8].id = skill->db[i-8].nameid; + sd->status.skill[i-8].id = skill->dbs->db[i-8].nameid; 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 } @@ -1448,7 +1470,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { for( i = 0; i < MAX_SKILL; i++ ) { - switch(skill->db[i].nameid) { + switch(skill->dbs->db[i].nameid) { /** * 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 @@ -1471,10 +1493,10 @@ int pc_calc_skilltree(struct map_session_data *sd) default: break; } - if( skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) + if( skill->dbs->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) continue; //Only skills you can't have are npc/guild ones - if( skill->db[i].max > 0 ) - sd->status.skill[i].id = skill->db[i].nameid; + if( skill->dbs->db[i].max > 0 ) + sd->status.skill[i].id = skill->dbs->db[i].nameid; } return 0; } @@ -1517,8 +1539,8 @@ int pc_calc_skilltree(struct map_session_data *sd) } if( f ) { int inf2; - inf2 = skill->db[idx].inf2; - + inf2 = skill->dbs->db[idx].inf2; + if(!sd->status.skill[idx].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || inf2&INF2_WEDDING_SKILL || @@ -1527,7 +1549,7 @@ int pc_calc_skilltree(struct map_session_data *sd) continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. sd->status.skill[idx].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[idx].lv = 1; // need to manually specify a skill level sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. @@ -1548,7 +1570,7 @@ int pc_calc_skilltree(struct map_session_data *sd) for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) { int idx = pc->skill_tree[c][i].idx; - if( (skill->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) + if( (skill->dbs->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) continue; //Do not include Quest/Wedding skills. if( sd->status.skill[idx].id == 0 ) { @@ -1618,7 +1640,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id) continue; } - j = skill->db[idx].inf2; + j = skill->dbs->db[idx].inf2; if( !sd->status.skill[idx].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || @@ -1665,7 +1687,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) novice_skills = pc->max_level[pc->class2idx(JOB_NOVICE)][1] - 1; sd->sktree.second = sd->sktree.third = 0; - + // limit 1st class and above to novice job levels if(skill_point < novice_skills) { c = MAPID_NOVICE; @@ -1720,7 +1742,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) // restore non-limiting flags c |= sd->class_&(JOBL_UPPER|JOBL_BABY); - + return c; } @@ -1777,7 +1799,7 @@ int pc_disguise(struct map_session_data *sd, int class_) { if( class_ == -1 && sd->disguise == sd->status.class_ ) { clif->clearunit_single(-sd->bl.id,CLR_OUTSIGHT,sd->fd); } else if ( class_ != sd->status.class_ ) { - pc_stop_walking(sd, 0); + pc_stop_walking(sd, STOPWALKING_FLAG_NONE); clif->clearunit_area(&sd->bl, CLR_OUTSIGHT); } } @@ -2783,24 +2805,56 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) switch(type){ case SP_ADDELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { 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; + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) { + if ( !sd->state.lr_flag ) + sd->right_weapon.addele[i] += val; + else if ( sd->state.lr_flag == 1 ) + sd->left_weapon.addele[i] += val; + else if ( sd->state.lr_flag == 2 ) + sd->arrow_addele[i] += val; + } + } else { + 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; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if ( !sd->state.lr_flag ) + sd->right_weapon.addrace[i] += val; + else if ( sd->state.lr_flag == 1 ) + sd->left_weapon.addrace[i] += val; + else if ( sd->state.lr_flag == 2 ) + sd->arrow_addrace[i] += val; + } + } else { + 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) @@ -2811,16 +2865,40 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->arrow_addsize[type2]+=val; break; case SP_SUBELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->subele[type2]+=val; + if(sd->state.lr_flag != 2) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ){ + sd->subele[i] += val; + } + } else { + sd->subele[type2] += val; + } + } break; case SP_SUBRACE: - if(sd->state.lr_flag != 2) - sd->subrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SUBRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if (type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->subrace[i] += val; + } + } else { + sd->subrace[type2]+=val; + } + } break; case SP_ADDEFF: if (type2 > SC_MAX) { @@ -2849,24 +2927,57 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000); break; case SP_MAGIC_ADDELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->magic_addele[type2]+=val; + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->magic_addele[i] += val; + } else { + sd->magic_addele[type2] += val; + } + } break; case SP_MAGIC_ADDRACE: - if(sd->state.lr_flag != 2) - sd->magic_addrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_MAGIC_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2){ + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->magic_addrace[i] += val; + } + } else { + sd->magic_addrace[type2]+=val; + } + } break; case SP_MAGIC_ADDSIZE: if(sd->state.lr_flag != 2) sd->magic_addsize[type2]+=val; break; case SP_MAGIC_ATK_ELE: - if(sd->state.lr_flag != 2) - sd->magic_atk_ele[type2]+=val; + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus2: SP_MAGIC_ATK_ELE: Invalid element %d\n", type2); + break; + } + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->magic_atk_ele[i] += val; + } else { + sd->magic_atk_ele[type2] += val; + } + } break; case SP_ADD_DAMAGE_CLASS: switch (sd->state.lr_flag) { @@ -3015,19 +3126,40 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; case SP_WEAPON_COMA_ELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { 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; + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->weapon_coma_ele[i] += val; + } else { + sd->weapon_coma_ele[type2] += val; + } sd->special_state.bonus_coma = 1; break; case SP_WEAPON_COMA_RACE: + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_WEAPON_COMA_RACE: Invalid Race(%d)\n",type2); + break; + } if(sd->state.lr_flag == 2) break; - sd->weapon_coma_race[type2] += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->weapon_coma_race[i] += val; + } + } else { + sd->weapon_coma_race[type2] += val; + } sd->special_state.bonus_coma = 1; break; case SP_WEAPON_ATK: @@ -3039,8 +3171,25 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->weapon_atk_rate[type2]+=val; break; case SP_CRITICAL_ADDRACE: - if(sd->state.lr_flag != 2) - sd->critaddrace[type2] += val*10; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_CRITICAL_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2){ + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->critaddrace[i] += val*10; + } + } else { + sd->critaddrace[type2] += val*10; + } + } break; case SP_ADDEFF_WHENHIT: if (type2 > SC_MAX) { @@ -3118,23 +3267,17 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->skillblown[i].val = val; } break; - #ifndef RENEWAL_CAST +#ifndef RENEWAL_CAST case SP_VARCASTRATE: - #endif +#endif 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("script->run: bonus2 %s reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", - - #ifndef RENEWAL_CAST - "bCastRate", - #else - "bVariableCastrate", - #endif - + ShowDebug("script->run: bonus2 %s reached its limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n", + type == SP_CASTRATE ? "bCastRate" : "bVariableCastrate", ARRAYLENGTH(sd->skillcast), type2, val); break; } @@ -3211,12 +3354,46 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->itemhealrate[i].rate += val; break; case SP_EXP_ADDRACE: - if(sd->state.lr_flag != 2) - sd->expaddrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_EXP_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->expaddrace[i] += val; + } + } else { + sd->expaddrace[type2] += val; + } + } break; case SP_SP_GAIN_RACE: - if(sd->state.lr_flag != 2) - sd->sp_gain_race[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_GAIN_RACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->sp_gain_race[i] += val; + } + } else { + sd->sp_gain_race[type2] += val; + } + } break; case SP_ADD_MONSTER_DROP_ITEM: if (sd->state.lr_flag != 2) @@ -3235,19 +3412,61 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; case SP_HP_DRAIN_VALUE_RACE: - if(!sd->state.lr_flag) { - sd->right_weapon.hp_drain[type2].value += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_HP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].value += val; + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[i].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[i].value += val; + } + } + } else { + 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; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].value += val; + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[i].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[i].value += val; + } + } + } else { + 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: @@ -3259,12 +3478,46 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) 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); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->sp_gain_race_attack[i] = cap_value(sd->sp_gain_race_attack[i] + val, 0, INT16_MAX); + } + } else { + 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); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_HP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->hp_gain_race_attack[i] = cap_value(sd->hp_gain_race_attack[i] + val, 0, INT16_MAX); + } + } else { + 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) @@ -3370,8 +3623,25 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; #ifdef RENEWAL case SP_RACE_TOLERANCE: - if ( sd->state.lr_flag != 2 ) - sd->race_tolerance[type2] += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_RACE_TOLERANCE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->race_tolerance[i] += val; + } + } else { + sd->race_tolerance[type2] += val; + } + } break; #endif default: @@ -3383,6 +3653,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) { + int i; nullpo_ret(sd); switch(type){ @@ -3432,23 +3703,69 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int 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; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus3: SP_HP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].rate += type3; - sd->left_weapon.hp_drain[type2].per += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[i].rate += type3; + sd->right_weapon.hp_drain[i].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[i].rate += type3; + sd->left_weapon.hp_drain[i].per += val; + } + } + } else { + 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; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus3: SP_SP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].rate += type3; - sd->left_weapon.sp_drain[type2].per += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[i].rate += type3; + sd->right_weapon.sp_drain[i].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[i].rate += type3; + sd->left_weapon.sp_drain[i].per += val; + } + } + } else { + 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_ADDEFF: @@ -3479,21 +3796,33 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; case SP_ADDELE: - if (type2 > ELE_MAX) { - ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2); + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus3: SP_ADDELE: Invalid element %d\n", type2); break; } - if (sd->state.lr_flag != 2) - pc_bonus_addele(sd, (unsigned char)type2, type3, val); + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + pc_bonus_addele(sd, (unsigned char)i, type3, val); + } else { + 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); + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus3: SP_SUBELE: Invalid element %d\n", type2); break; } - if (sd->state.lr_flag != 2) - pc_bonus_subele(sd, (unsigned char)type2, type3, val); + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + pc_bonus_subele(sd, (unsigned char)i, type3, val); + } else { + pc_bonus_subele(sd, (unsigned char)type2, type3, val); + } + } break; case SP_SP_VANISH_RATE: if(sd->state.lr_flag != 2) { @@ -3512,6 +3841,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) } int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) { + int i; nullpo_ret(sd); switch(type) { @@ -3544,27 +3874,55 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 break; case SP_SET_DEF_RACE: //bonus4 bSetDefRace,n,x,r,y; - if( type2 >= RC_MAX ) { - ShowWarning("pc_bonus4 (DEF_SET): %d is not supported.\n", type2); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus4: SP_SET_DEF_RACE: Invalid Race(%d)\n",type2); break; } if(sd->state.lr_flag == 2) break; - sd->def_set_race[type2].rate = type3; - sd->def_set_race[type2].tick = type4; - sd->def_set_race[type2].value = val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->def_set_race[i].rate = type3; + sd->def_set_race[i].tick = type4; + sd->def_set_race[i].value = val; + } + } else { + sd->def_set_race[type2].rate = type3; + sd->def_set_race[type2].tick = type4; + sd->def_set_race[type2].value = val; + } break; case SP_SET_MDEF_RACE: //bonus4 bSetMDefRace,n,x,r,y; - if( type2 >= RC_MAX ) { - ShowWarning("pc_bonus4 (MDEF_SET): %d is not supported.\n", type2); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus4: SP_SET_MDEF_RACE: Invalid Race(%d)\n",type2); break; } if(sd->state.lr_flag == 2) break; - sd->mdef_set_race[type2].rate = type3; - sd->mdef_set_race[type2].tick = type4; - sd->mdef_set_race[type2].value = val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->mdef_set_race[i].rate = type3; + sd->mdef_set_race[i].tick = type4; + sd->mdef_set_race[i].value = val; + } + } else { + sd->mdef_set_race[type2].rate = type3; + sd->mdef_set_race[type2].tick = type4; + sd->mdef_set_race[type2].value = val; + } break; case SP_ADDEFF: @@ -3578,11 +3936,11 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 ShowWarning("pc_bonus4 (Add Effect): invalid duration %d. Valid range: [0:%d].\n", val, UINT16_MAX); duration = (val < 0 ? 0 : UINT16_MAX); } else { - duration = (uint16)type4; + duration = (uint16)val; } 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, duration); + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, type4, duration); } break; @@ -3622,13 +3980,11 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4 } /*========================================== - * Grants a player a given skill. Flag values are: - * 0 - Grant permanent skill to be bound to skill tree - * 1 - Grant an item skill (temporary) - * 2 - Like 1, except the level granted can stack with previously learned level. - * 3 - Grant skill unconditionally and forever (persistent to job changes and skill resets) + * Grants a player a given skill. + * Flag values: @see enum pc_skill_flag *------------------------------------------*/ -int pc_skill(TBL_PC* sd, int id, int level, int flag) { +int pc_skill(TBL_PC* sd, int id, int level, int flag) +{ uint16 index = 0; nullpo_ret(sd); @@ -3640,13 +3996,13 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { 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[index].lv + level > MAX_SKILL_LEVEL ) { + if( flag == SKILL_GRANT_TEMPSTACK && sd->status.skill[index].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[index].lv); return 0; } switch( flag ){ - case 0: //Set skill data overwriting whatever was there before. + case SKILL_GRANT_PERMANENT: //Set skill data overwriting whatever was there before. sd->status.skill[index].id = id; sd->status.skill[index].lv = level; sd->status.skill[index].flag = SKILL_FLAG_PERMANENT; @@ -3655,10 +4011,10 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { clif->deleteskill(sd,id); } else clif->addskill(sd,id); - if( !skill->db[index].inf ) //Only recalculate for passive skills. + if( !skill->dbs->db[index].inf ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - case 1: //Item bonus skill. + case SKILL_GRANT_TEMPORARY: //Item bonus skill. if( sd->status.skill[index].id == id ) { if( sd->status.skill[index].lv >= level ) return 0; @@ -3670,7 +4026,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { } sd->status.skill[index].lv = level; break; - case 2: //Add skill bonus on top of what you had. + case SKILL_GRANT_TEMPSTACK: //Add skill bonus on top of what you had. if( sd->status.skill[index].id == id ) { if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv; // Store previous level. @@ -3680,7 +4036,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { } sd->status.skill[index].lv += level; break; - case 3: + case SKILL_GRANT_UNCONDITIONAL: sd->status.skill[index].id = id; sd->status.skill[index].lv = level; sd->status.skill[index].flag = SKILL_FLAG_PERM_GRANTED; @@ -3689,60 +4045,100 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { clif->deleteskill(sd,id); } else clif->addskill(sd,id); - if( !skill->db[index].inf ) //Only recalculate for passive skills. + if( !skill->dbs->db[index].inf ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - default: //Unknown flag? - return 0; + default: //Unknown flag? + return 0; } return 1; } + +/** + * Checks if the given card can be inserted into the given equipment piece. + * + * @param sd The current character. + * @param idx_card The card's inventory index (note: it must be a valid index and can be checked by pc_can_insert_card) + * @param idx_equip The target equipment's inventory index. + * @retval true if the card can be inserted. + */ +bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_equip) +{ + int i; + + nullpo_ret(sd); + + if (idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL) + return false; //Invalid item index. + if (sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1) + return false; // target item missing + if (sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR) + return false; // only weapons and armor are allowed + if (sd->status.inventory[idx_equip].identify == 0) + return false; // target must be identified + if (itemdb_isspecial(sd->status.inventory[idx_equip].card[0])) + return false; // card slots reserved for other purposes + if (sd->status.inventory[idx_equip].equip != 0) + return false; // item must be unequipped + if ((sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0) + return false; // 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 false; // attempted to place shield card on left-hand weapon. + + 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 false; // no free slots + return true; +} + +/** + * Checks if the given item is card and it can be inserted into some equipment. + * + * @param sd The current character. + * @param idx_card The card's inventory index. + * @retval true if the card can be inserted. + */ +bool pc_can_insert_card(struct map_session_data* sd, int idx_card) +{ + nullpo_ret(sd); + + if (idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL) + return false; //Invalid card index. + if (sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1) + return false; // target card missing + if (sd->inventory_data[idx_card]->type != IT_CARD) + return false; // must be a card + return true; +} + /*========================================== * 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 + if (sd->state.trading != 0) + return 0; + + if (!pc->can_insert_card(sd, idx_card) || !pc->can_insert_card_into(sd, idx_card, idx_equip)) + return 0; // 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 ) + if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_OTHER) == 1 ) {// failed clif->insert_card(sd,idx_equip,idx_card,1); } else {// success + int i; + 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 logs->pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); sd->status.inventory[idx_equip].card[i] = nameid; logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); @@ -4077,7 +4473,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l break; } } - + i = MAX_INVENTORY; // Stackable | Non Rental @@ -4086,6 +4482,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && sd->status.inventory[i].expire_time == 0 && + sd->status.inventory[i].unique_id == item_data->unique_id && 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; @@ -4095,7 +4492,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l } } } - + if ( i >= MAX_INVENTORY ) { i = pc->search_inventory(sd,0); if (i == INDEX_NOT_FOUND) @@ -4113,8 +4510,8 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l clif->additem(sd,i,amount,0); } - if( !itemdb->isstackable2(data) && !item_data->unique_id ) - sd->status.inventory[i].unique_id = itemdb->unique_id(sd); + if( ( !itemdb->isstackable2(data) || data->flag.force_serial || data->type == IT_CASH) && !item_data->unique_id ) + sd->status.inventory[i].unique_id = itemdb->unique_id(sd); logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]); @@ -4144,6 +4541,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l * @type * 1 : don't notify deletion * 2 : don't notify weight change + * reason: @see enum delitem_reason * Return: * 0 = success * 1 = invalid itemid or negative amount @@ -4161,7 +4559,7 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas 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); + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); sd->inventory_data[n] = NULL; } @@ -4208,10 +4606,10 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) return 0; } - if (!map->addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2)) + if (!map->addflooritem(&sd->bl, &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); + pc->delitem(sd, n, amount, 1, DELITEM_NORMAL, LOG_TYPE_PICKDROP_PLAYER); clif->dropitem(sd, n, amount); return 1; } @@ -4306,14 +4704,14 @@ int pc_isUseitem(struct map_session_data *sd,int n) if( !item->script ) //if it has no script, you can't really consume it! return 0; - if( (item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) { - clif->msgtable(sd->fd,0x297); - //clif->colormes(sd->fd,COLOR_WHITE,msg_txt(1474)); + if ((item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override)) { + clif->msgtable(sd, MSG_ITEM_NEED_STANDING); + //clif->messagecolor_self(sd->fd, COLOR_WHITE, msg_txt(1474)); return 0; // You cannot use this item while sitting. } - if (sd->state.storage_flag && item->type != IT_CASH) { - clif->colormes(sd->fd, COLOR_RED, msg_sd(sd,1475)); + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED && item->type != IT_CASH) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1475)); return 0; // You cannot use this item while storage is open. } @@ -4412,27 +4810,27 @@ int pc_isUseitem(struct map_session_data *sd,int n) return 0; if( item->package || item->group ) { - if( pc_is90overweight(sd) ) { - clif->msgtable(sd->fd,ITEM_CANT_OBTAIN_WEIGHT); + if (pc_is90overweight(sd)) { + clif->msgtable(sd, MSG_ITEM_CANT_OBTAIN_WEIGHT); return 0; } - if( !pc->inventoryblank(sd) ) { - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1477)); + if (!pc->inventoryblank(sd)) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1477)); 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){ - clif->msg(sd, 0x6EE); + if (item->elv && sd->status.base_level < (unsigned int)item->elv) { + clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL); return 0; } - if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){ - clif->msg(sd, 0x6EE); + if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) { + clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL); return 0; } @@ -4442,7 +4840,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) (item->class_base[(sd->class_&JOBL_2_1) ? 1 : ((sd->class_&JOBL_2_2) ? 2 : 0)]) )) return 0; - + //Not usable by upper class. [Haru] while( 1 ) { // Normal classes (no upper, no baby, no third classes) @@ -4477,14 +4875,14 @@ int pc_isUseitem(struct map_session_data *sd,int n) int pc_useitem(struct map_session_data *sd,int n) { int64 tick = timer->gettick(); int amount, nameid, i; - struct script_code *item_script; + bool removeItem = false; nullpo_ret(sd); if( sd->npc_id || sd->state.workinprogress&1 ){ /* TODO: add to clif->messages enum */ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return 0; } @@ -4524,7 +4922,7 @@ int pc_useitem(struct map_session_data *sd,int n) { (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 && nameid != ITEMID_REINS_OF_MOUNT ) { if( sd->sc.data[SC_ALL_RIDING] ) @@ -4547,7 +4945,7 @@ int pc_useitem(struct map_session_data *sd,int n) { if( sd->item_delay[i].nameid ) {// found if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) { int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000); - clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use + clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, e_tick + 1); // [%d] seconds left until you can use return 0; // Delay has not expired yet } } else {// not yet used item (all slots are initially empty) @@ -4570,57 +4968,55 @@ int pc_useitem(struct map_session_data *sd,int n) { /* on restricted maps the item is consumed but the effect is not used */ for(i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++) { if( map->list[sd->bl.m].zone->disabled_items[i] == nameid ) { - clif->msg(sd, ITEM_CANT_USE_AREA); // This item cannot be used within this area + clif->msgtable(sd, MSG_ITEM_CANT_USE_AREA); // This item cannot be used within this area if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) { clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true); - pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); + pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); } return 0; } } - + //Dead Branch & Bloody Branch & Porings Box if( nameid == ITEMID_BRANCH_OF_DEAD_TREE || nameid == ITEMID_BLOODY_DEAD_BRANCH || nameid == ITEMID_PORING_BOX ) logs->branch(sd); - + 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; - item_script = sd->inventory_data[n]->script; //Check if the item is to be consumed immediately [Skotlex] if (sd->inventory_data[n]->flag.delay_consume || sd->inventory_data[n]->flag.keepafteruse) 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 + removeItem = true; } 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)) { - script->potion_flag = 2; // Famous player's potions have 50% more efficiency - if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE) - script->potion_flag = 3; //Even more effective potions. + script->potion_flag = 2; // Famous player's potions have 50% more efficiency + if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE) + script->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; - - script->current_item_id = nameid; - - script->run(item_script,0,sd->bl.id,npc->fake_nd->bl.id); - - script->current_item_id = 0; + + script->run_use_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id); script->potion_flag = 0; - + + if (removeItem) + pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); return 1; } @@ -4665,7 +5061,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] ); }; - if( i < MAX_CART ) + if( i < MAX_CART && item_data->unique_id == sd->status.cart[i].unique_id) {// 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 2; // no room @@ -4744,7 +5140,7 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) return 1; if( (flag = pc->cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 ) - return pc->delitem(sd,idx,amount,0,5,LOG_TYPE_NONE); + return pc->delitem(sd, idx, amount, 0, DELITEM_TOCART, LOG_TYPE_NONE); return flag; } @@ -4788,7 +5184,7 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) 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); @@ -4796,14 +5192,14 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) } void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) { int i; - + switch( type ) { /* both restricted to inventory */ case IBT_PARTY: case IBT_CHARACTER: for( i = 0; i < MAX_INVENTORY; i++ ){ if( sd->status.inventory[i].bound == type ) { - pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_SKILLUSE, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? } } break; @@ -4812,12 +5208,12 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) { break; case IBT_GUILD: { struct guild_storage *gstor = idb_get(gstorage->db,sd->status.guild_id); - + for( i = 0; i < MAX_INVENTORY; i++ ){ if(sd->status.inventory[i].bound == type) { if( gstor ) gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount); - pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,gstor?LOG_TYPE_GSTORAGE:LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_SKILLUSE, gstor ? LOG_TYPE_GSTORAGE : LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? } } if( gstor ) @@ -4825,7 +5221,6 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) { } break; } - } /*========================================== * Display item stolen msg to player sd @@ -4894,7 +5289,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil // 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 && (data = itemdb->exists(md->db->dropitem[i].nameid)) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. ) + if (md->db->dropitem[i].nameid > 0 && (data = itemdb->exists(md->db->dropitem[i].nameid)) != NULL && rnd() % 10000 < md->db->dropitem[i].p * rate/100.) break; if( i == MAX_STEAL_DROP ) return 0; @@ -5004,7 +5399,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int stop = true; } } - if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) { + if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances ) { for( i = 0; i < p->instances; i++ ) { if( p->instance[i] >= 0 ) { ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[p->instance[i]].map[j]].custom_name); @@ -5049,7 +5444,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int if( sd->state.changemap ) { // Misc map-changing settings int i; sd->state.pmap = sd->bl.m; - + for( i = 0; i < sd->queues_count; i++ ) { struct hQueue *queue; if( (queue = script->queue(sd->queues[i])) && queue->onMapChange[0] != '\0' ) { @@ -5057,7 +5452,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int npc->event(sd, queue->onMapChange, 0); } } - + if( map->list[m].cell == (struct mapcell *)0xdeadbeaf ) map->cellfromcache(&map->list[m]); if (sd->sc.count) { // Cancel some map related stuff. @@ -5086,7 +5481,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int 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 ); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } if (battle_config.clear_unit_onwarp&BL_PC) skill->clear_unitgroup(&sd->bl); @@ -5100,7 +5495,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int clif->message (sd->fd, msg_sd(sd,276)); // "You can't open a shop on this map" vending->close(sd); } - + if (map->list[sd->bl.m].channel) { channel->leave(map->list[sd->bl.m].channel,sd); } @@ -5140,10 +5535,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int do { x=rnd()%(map->list[m].xs-2)+1; y=rnd()%(map->list[m].ys-2)+1; - } while(map->getcell(m,x,y,CELL_CHKNOPASS)); + } while(map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS)); } - if (sd->state.vending && map->getcell(m,x,y,CELL_CHKNOVENDING)) { + if (sd->state.vending && map->getcell(m, &sd->bl, x, y, CELL_CHKNOVENDING)) { clif->message (sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell." vending->close(sd); } @@ -5186,7 +5581,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int sd->md->bl.y = sd->md->ud.to_y = y; sd->md->ud.dir = sd->ud.dir; } - + /* given autotrades have no clients you have to trigger this manually otherwise they get stuck in memory limbo bugreport:7495 */ if( sd->state.autotrade ) clif->pLoadEndAck(0,sd); @@ -5215,7 +5610,7 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type) { do { x=rnd()%(map->list[m].xs-2)+1; y=rnd()%(map->list[m].ys-2)+1; - } while( map->getcell(m,x,y,CELL_CHKNOPASS) && (i++) < 1000 ); + } while (map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS) && (i++) < 1000 ); if (i < 1000) return pc->setpos(sd,map_id2index(sd->bl.m),x,y,type); @@ -5302,16 +5697,16 @@ int pc_checkskill2(struct map_session_data *sd,uint16 index) { ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id); return 0; } - if( skill->db[index].nameid >= GD_SKILLBASE && skill->db[index].nameid < GD_MAX ) { + if( skill->dbs->db[index].nameid >= GD_SKILLBASE && skill->dbs->db[index].nameid < GD_MAX ) { struct guild *g; - + if( sd->status.guild_id>0 && (g=sd->guild)!=NULL) - return guild->checkskill(g,skill->db[index].nameid); + return guild->checkskill(g,skill->dbs->db[index].nameid); return 0; } - if(sd->status.skill[index].id == skill->db[index].nameid) + if(sd->status.skill[index].id == skill->dbs->db[index].nameid) return (sd->status.skill[index].lv); - + return 0; } @@ -6083,8 +6478,8 @@ int pc_stop_following (struct map_session_data *sd) sd->followtarget = -1; sd->ud.target_to = 0; - unit->stop_walking(&sd->bl, 1); - + unit->stop_walking(&sd->bl, STOPWALKING_FLAG_FIXPOS); + return 0; } @@ -6156,7 +6551,7 @@ void pc_baselevelchanged(struct map_session_data *sd) { 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); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } } } @@ -6223,8 +6618,6 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in *job_exp = (unsigned int) cap_value((double)*job_exp * sd->status.mod_exp/100., 1, UINT_MAX); } - - return; } /** @@ -6305,7 +6698,7 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in if(job_exp) clif->displayexp(sd, job_exp, SP_JOBEXP, is_quest); #endif - + if(sd->state.showexp) { char output[256]; sprintf(output, @@ -6353,7 +6746,6 @@ unsigned int pc_thisbaseexp(struct map_session_data *sd) return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-2]; } - /*========================================== * job level exp lookup * Return: @@ -6603,7 +6995,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { if( !(index = skill->get_index(skill_id)) ) return 0; - + if( sd->status.skill_point > 0 && sd->status.skill[index].id && sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] @@ -6611,7 +7003,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { { sd->status.skill[index].lv++; sd->status.skill_point--; - if( !skill->db[index].inf ) + if( !skill->dbs->db[index].inf ) status_calc_pc(sd,SCO_NONE); // 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. @@ -6625,14 +7017,12 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { 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); } else if( battle_config.skillup_limit ){ - if( sd->sktree.second ) - clif->msg_value(sd, 0x61E, sd->sktree.second); - else if( sd->sktree.third ) - clif->msg_value(sd, 0x61F, sd->sktree.third); - else if( pc->calc_skillpoint(sd) < 9 ) { - /* TODO: official response? */ - clif->colormes(sd->fd,COLOR_RED,"You need the basic skills"); - } + if (sd->sktree.second) + clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB1, sd->sktree.second); + else if (sd->sktree.third) + clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB2, sd->sktree.third); + else if (pc->calc_skillpoint(sd) < 9) /* TODO: official response? */ + clif->messagecolor_self(sd->fd, COLOR_RED, "You need the basic skills"); } return 0; } @@ -6658,22 +7048,22 @@ int pc_allskillup(struct map_session_data *sd) 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( skill->db[i].nameid ) { + switch( skill->dbs->db[i].nameid ) { case SG_DEVIL: case MO_TRIPLEATTACK: case RG_SNATCHER: continue; default: - if( !(skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) - if ( ( sd->status.skill[i].lv = skill->db[i].max ) )//Nonexistant skills should return a max of 0 anyway. - sd->status.skill[i].id = skill->db[i].nameid; + if( !(skill->dbs->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) + if ( ( sd->status.skill[i].lv = skill->dbs->db[i].max ) )//Nonexistant skills should return a max of 0 anyway. + sd->status.skill[i].id = skill->dbs->db[i].nameid; } } } else { int id; for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class_)][i].id) > 0; i++) { int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][i].idx; - int inf2 = skill->db[idx].inf2; + int inf2 = skill->dbs->db[idx].inf2; if ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || @@ -6702,9 +7092,9 @@ int pc_resetlvl(struct map_session_data* sd,int type) nullpo_ret(sd); if (type != 3) //Also reset skills - pc->resetskill(sd, 0); + pc->resetskill(sd, PCRESETSKILL_NONE); - if(type == 1){ + if(type == 1) { sd->status.skill_point=0; sd->status.base_level=1; sd->status.job_level=1; @@ -6722,8 +7112,8 @@ int pc_resetlvl(struct map_session_data* sd,int type) 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); + pc->skill(sd, NV_FIRSTAID, 1, SKILL_GRANT_PERMANENT); + pc->skill(sd, NV_TRICKDEAD, 1, SKILL_GRANT_PERMANENT); } } @@ -6769,7 +7159,7 @@ int pc_resetlvl(struct map_session_data* sd,int type) 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); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } if ((type == 1 || type == 2 || type == 3) && sd->status.party_id) @@ -6847,19 +7237,17 @@ int pc_resetstate(struct map_session_data* sd) /*========================================== * /resetskill - * if flag&1, perform block resync and status_calc call. - * 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.) + * @param flag: @see enum pc_resetskill_flag *------------------------------------------*/ int pc_resetskill(struct map_session_data* sd, int flag) { int i, inf2, skill_point=0; nullpo_ret(sd); - if( flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) + if( flag&PCRESETSKILL_CHSEX && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) return 0; - if( !(flag&2) ) { //Remove stuff lost when resetting skills. + if( !(flag&PCRESETSKILL_RECOUNT) ) { //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) @@ -6898,18 +7286,18 @@ int pc_resetskill(struct map_session_data* sd, int flag) for( i = 1; i < MAX_SKILL; i++ ) { // FIXME: We're looping on i = [1..MAX_SKILL-1] (which makes sense as index for sd->status.skill[]) but then we're using the - // same i to access skill->db[], and especially to check skill_ischangesex(). This is wrong. + // same i to access skill->dbs->db[], and especially to check skill_ischangesex(). This is wrong. uint16 skill_id = 0; int lv = sd->status.skill[i].lv; if (lv < 1) continue; - inf2 = skill->db[i].inf2; + inf2 = skill->dbs->db[i].inf2; if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills. continue; - - skill_id = skill->db[i].nameid; - + + skill_id = skill->dbs->db[i].nameid; + // Don't reset trick dead if not a novice/baby if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { sd->status.skill[i].lv = 0; @@ -6923,13 +7311,13 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) continue; - - if( flag&4 && !skill_ischangesex(i) ) + + if( flag&PCRESETSKILL_CHSEX && !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 + if( battle_config.quest_skill_reset && !(flag&PCRESETSKILL_RECOUNT) ) { //Wipe them sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } @@ -6940,18 +7328,17 @@ int pc_resetskill(struct map_session_data* sd, int flag) 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 + if( !(flag&PCRESETSKILL_RECOUNT) ) {// reset sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } } - if( flag&2 || !skill_point ) return skill_point; + if( flag&PCRESETSKILL_RECOUNT || !skill_point ) return skill_point; sd->status.skill_point += skill_point; - - if( !(flag&2) ) { + if (!(flag&PCRESETSKILL_RECOUNT)) { // Remove all SCs that can't be inactivated without a skill if( sd->sc.data[SC_STORMKICK_READY] ) status_change_end(&sd->bl, SC_STORMKICK_READY, INVALID_TIMER); @@ -6965,7 +7352,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) status_change_end(&sd->bl, SC_DODGE_READY, INVALID_TIMER); } - if( flag&1 ) { + if (flag&PCRESETSKILL_RESYNC) { clif->updatestatus(sd,SP_SKILLPOINT); clif->skillinfoblock(sd); status_calc_pc(sd,SCO_FORCE); @@ -6997,8 +7384,7 @@ int pc_resethate(struct map_session_data* sd) int i; nullpo_ret(sd); - for (i=0; i<3; i++) - { + for (i = 0; i < MAX_PC_FEELHATE; i++) { sd->hate_mob[i] = -1; pc_setglobalreg(sd,script->add_str(pc->sg_info[i].hate_var),0); } @@ -7115,8 +7501,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { nullpo_retr(0, sd); - for(j = 0; j < 5; j++) { - if (sd->devotion[j]){ + for (j = 0; j < MAX_PC_DEVOTION; j++) { + if (sd->devotion[j]) { struct map_session_data *devsd = map->id2sd(sd->devotion[j]); if (devsd) status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER); @@ -7157,7 +7543,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { if (sd->npc_id && sd->st && sd->st->state != RUN) npc->event_dequeue(sd); - + pc_setglobalreg(sd,script->add_str("PC_DIE_COUNTER"),sd->die_counter+1); pc->setparam(sd, SP_KILLERRID, src?src->id:0); @@ -7166,15 +7552,15 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { if( (bgd = bg->team_search(sd->bg_id)) != NULL && bgd->die_event[0] ) npc->event(sd, bgd->die_event, 0); } - + for( i = 0; i < sd->queues_count; i++ ) { struct hQueue *queue; if( (queue = script->queue(sd->queues[i])) && queue->onDeath[0] != '\0' ) npc->event(sd, queue->onDeath, 0); } - + npc->script_event(sd,NPCE_DIE); - + // Clear anything NPC-related when you die and was interacting with one. if ( (sd->npc_id || sd->npc_shopid) && sd->state.dialog) { if (sd->state.using_fake_npc) { @@ -7220,7 +7606,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { 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] + && !md->guardian_data && md->special_state.ai == AI_NONE// Guardians/summons should not level. [Skotlex] ) { // monster level up [Valaris] clif->misceffect(&md->bl,0); @@ -7272,7 +7658,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { else if (sd->status.karma < ssd->status.karma) // If player killed was more good ssd->status.karma++; - // or the PK System way... if (sd->status.karma > 0) // player killed is dishonourable? @@ -7295,7 +7680,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { 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); + map->addflooritem(&sd->bl, &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] @@ -7324,7 +7709,6 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { ) { 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); @@ -7333,7 +7717,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { 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; @@ -7343,10 +7727,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { 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); @@ -7355,7 +7739,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { 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; @@ -7365,7 +7749,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { clif->updatestatus(sd,SP_JOBEXP); } } - + if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) { base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.); if(base_penalty) @@ -7400,7 +7784,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { int n = eq_n[rnd()%eq_num]; if(rnd()%10000 < per){ if(sd->status.inventory[n].equip) - pc->unequipitem(sd,n,3); + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd,n,1); } } @@ -7413,7 +7797,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { || (type == 2 && sd->status.inventory[i].equip) || type == 3) ){ if(sd->status.inventory[i].equip) - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd,i,1); break; } @@ -7632,7 +8016,6 @@ int pc_readparam(struct map_session_data* sd,int type) case SP_VARCASTRATE: val = sd->bonus.varcastrate; break; case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break; #endif - } return val; @@ -8038,7 +8421,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) /* going off star glad lineage, reset feel to not store no-longer-used vars in the database */ pc->resetfeel(sd); } - + sd->status.class_ = job; fame_flag = pc->famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK); sd->class_ = (unsigned short)b_class; @@ -8062,7 +8445,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) 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 + pc->unequipitem(sd,sd->equip_index[i], PCUNEQUIPITEM_FORCE); // unequip invalid item for class } //Change look, if disguised, you need to undisguise @@ -8257,7 +8640,7 @@ int pc_setoption(struct map_session_data *sd,int type) if(pc->checkskill(sd, MC_PUSHCART) < 10) status_calc_pc(sd,SCO_NONE); //Remove speed penalty. if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); } #endif @@ -8294,14 +8677,14 @@ int pc_setoption(struct map_session_data *sd,int type) status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER); } if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); } 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 (sd->disguise != -1 || !new_look) return 0; //Disguises break sprite changes @@ -8348,7 +8731,7 @@ int pc_setcart(struct map_session_data *sd,int type) { clif->clearcart(sd->fd); clif->updatestatus(sd, SP_CARTINFO); if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); 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 */ @@ -8547,7 +8930,7 @@ int pc_readreg(struct map_session_data* sd, int64 reg) { **/ void pc_setreg(struct map_session_data* sd, int64 reg, int val) { unsigned int index = script_getvaridx(reg); - + if( val ) { i64db_iput(sd->regs.vars, reg, val); if( index ) @@ -8566,7 +8949,7 @@ char* pc_readregstr(struct map_session_data* sd, int64 reg) { struct script_reg_str *p = NULL; p = i64db_get(sd->regs.vars, reg); - + return p ? p->value : NULL; } /** @@ -8579,10 +8962,10 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) { if( str[0] ) { p = ers_alloc(pc->str_reg_ers, struct script_reg_str); - + p->value = aStrdup(str); p->flag.type = 1; - + if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) { p = DB->data2ptr(&prev); if( p->value ) @@ -8611,15 +8994,15 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) { **/ int pc_readregistry(struct map_session_data *sd, int64 reg) { struct script_reg_num *p = NULL; - + if (!sd->vars_ok) { ShowError("pc_readregistry: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg))); //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); - set_eof(sd->fd); + sockt->eof(sd->fd); return 0; } - + p = i64db_get(sd->regs.vars, reg); return p ? p->value : 0; @@ -8632,17 +9015,17 @@ int pc_readregistry(struct map_session_data *sd, int64 reg) { **/ char* pc_readregistry_str(struct map_session_data *sd, int64 reg) { struct script_reg_str *p = NULL; - + if (!sd->vars_ok) { ShowError("pc_readregistry_str: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg))); //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); - set_eof(sd->fd); + sockt->eof(sd->fd); return NULL; } p = i64db_get(sd->regs.vars, reg); - + return p ? p->value : NULL; } /** @@ -8679,12 +9062,12 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) { } break; } - + if ( !pc->reg_load && !sd->vars_ok ) { ShowError("pc_setregistry : refusing to set %s until vars are received.\n", regname); return 0; } - + if( (p = i64db_get(sd->regs.vars, reg) ) ) { if( val ) { if( !p->value && index ) /* its a entry that was deleted, so we reset array */ @@ -8699,22 +9082,22 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) { p->flag.update = 1;/* either way, it will require either delete or replace */ } else if( val ) { DBData prev; - + if( index ) script->array_update(&sd->regs, reg, false); - + p = ers_alloc(pc->num_reg_ers, struct script_reg_num); - + p->value = val; if( !pc->reg_load ) p->flag.update = 1; - + if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) { p = DB->data2ptr(&prev); ers_free(pc->num_reg_ers, p); } } - + if( !pc->reg_load && p ) sd->vars_dirty = true; @@ -8757,12 +9140,12 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val) script->array_update(&sd->regs, reg, false); p = ers_alloc(pc->str_reg_ers, struct script_reg_str); - + p->value = aStrdup(val); if( !pc->reg_load ) p->flag.update = 1; p->flag.type = 1; - + if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) { p = DB->data2ptr(&prev); if( p->value ) @@ -8770,10 +9153,10 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val) ers_free(pc->str_reg_ers, p); } } - + if( !pc->reg_load && p ) sd->vars_dirty = true; - + return 1; } @@ -8901,7 +9284,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { /* ensure this isn't a duplicate combo */ if( sd->combos != NULL ) { int x; - + ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id ); /* found a match, skip this combo */ @@ -8922,7 +9305,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { if(!sd->inventory_data[index]) continue; - + if ( itemdb_type(id) != IT_CARD ) { if ( sd->inventory_data[index]->nameid != id ) continue; @@ -8957,15 +9340,13 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { /* we got here, means all items in the combo are matching */ RECREATE(sd->combos, struct pc_combos, ++sd->combo_count); - combo = &sd->combos[sd->combo_count - 1]; - combo->bonus = data->combos[i]->script; combo->id = data->combos[i]->id; - + success++; } - + return success; } @@ -8975,11 +9356,11 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { if( !sd->combos ) 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->combo_count, x, sd->combos[x].id == data->combos[i]->id ); /* no match, skip this combo */ if( x == sd->combo_count ) @@ -8987,9 +9368,9 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { sd->combos[x].bonus = NULL; sd->combos[x].id = 0; - + retval++; - + for( j = 0, cursor = 0; j < sd->combo_count; j++ ) { if( sd->combos[j].bonus == NULL ) continue; @@ -9001,7 +9382,7 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { cursor++; } - + /* it's empty, we can clear all the memory */ if( (sd->combo_count = cursor) == 0 ) { aFree(sd->combos); @@ -9009,7 +9390,7 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { break; } } - + /* check if combo requirements still fit -- don't touch retval! */ pc->checkcombo( sd, data ); @@ -9040,7 +9421,14 @@ int pc_load_combo(struct map_session_data *sd) { return ret; } -void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int pos) +/** +* Equip item ad given position. +* @param sd the affected player structure. Must be checked before. +* @param id item structure for equip. Must be checked before. +* @param n inventory item position. Must be checked before. +* @param pos slot position. Must be checked before. +**/ +void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int n, int pos) { if (pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) { if(id) @@ -9168,7 +9556,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) sd->status.inventory[n].bound = (unsigned char)IBT_CHARACTER; clif->notify_bounditem(sd,n); } - + 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.. @@ -9199,7 +9587,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) for(i=0;i<EQI_MAX;i++) { if(pos & pc->equip_pos[i]) { if(sd->equip_index[i] >= 0) //Slot taken, remove item from there. - pc->unequipitem(sd,sd->equip_index[i],2); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); sd->equip_index[i] = n; } @@ -9214,7 +9602,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) sd->status.inventory[n].equip=pos; - pc->equipitem_pos(sd, id, pos); + pc->equipitem_pos(sd, id, n, pos); pc->checkallowskill(sd); //Check if status changes should be halted. iflag = sd->npc_item_flag; @@ -9239,10 +9627,11 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) status_calc_pc(sd,SCO_NONE); if (flag) //Update skill data clif->skillinfoblock(sd); - + //OnEquip script [Skotlex] if (id->equip_script) - script->run(id->equip_script,0,sd->bl.id,npc->fake_nd->bl.id); + script->run_item_equip_script(sd, id, npc->fake_nd->bl.id); + if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards else { @@ -9251,8 +9640,8 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) if (!sd->status.inventory[n].card[i]) continue; if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) { - if( data->equip_script ) - script->run(data->equip_script,0,sd->bl.id,npc->fake_nd->bl.id); + if (data->equip_script) + script->run_item_equip_script(sd, data, npc->fake_nd->bl.id); } } } @@ -9261,6 +9650,12 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) return 1; } +/** +* Unrquip item ad given position. +* @param sd the affected player structure. Must be checked before. +* @param n inventory item position. Must be checked before. +* @param pos slot position. Must be checked before. +**/ void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos) { if (pos & EQP_HAND_R) { @@ -9320,15 +9715,13 @@ void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos) /*========================================== * Called when attemting to unequip an item from player - * type: - * 0 - only unequip - * 1 - calculate status after unequipping - * 2 - force unequip + * type: @see enum pc_unequipitem_flag * Return: * 0 = fail * 1 = success *------------------------------------------*/ -int pc_unequipitem(struct map_session_data *sd,int n,int flag) { +int pc_unequipitem(struct map_session_data *sd,int n,int flag) +{ int i,iflag; bool status_cacl = false; int pos; @@ -9340,13 +9733,13 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } // if player is berserk then cannot unequip - if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) ) + if (!(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) ) { clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; } - if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) + if( !(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) { clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; @@ -9407,7 +9800,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } } - if(flag&1 || status_cacl) { + if(flag&PCUNEQUIPITEM_RECALC || status_cacl) { pc->checkallowskill(sd); status_calc_pc(sd,SCO_NONE); } @@ -9421,10 +9814,10 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { if ( battle_config.unequip_restricted_equipment & 1 ) { ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid); if ( i == map->list[sd->bl.m].zone->disabled_items_count ) - script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id); + script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id); } else - script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id); + script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id); } if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards @@ -9440,10 +9833,10 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { int j; ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]); if ( j == map->list[sd->bl.m].zone->disabled_items_count ) - script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id); + script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id); } else - script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id); + script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id); } } @@ -9478,7 +9871,7 @@ int pc_checkitem(struct map_session_data *sd) if (!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); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); continue; } @@ -9501,7 +9894,7 @@ int pc_checkitem(struct map_session_data *sd) if ( !sd->status.cart[i].unique_id && !itemdb->isstackable(id) ) sd->status.cart[i].unique_id = itemdb->unique_id(sd); } - + for( i = 0; i < MAX_STORAGE; i++ ) { id = sd->status.storage.items[i].nameid; @@ -9518,7 +9911,7 @@ int pc_checkitem(struct map_session_data *sd) if ( !sd->status.storage.items[i].unique_id && !itemdb->isstackable(id) ) sd->status.storage.items[i].unique_id = itemdb->unique_id(sd); } - + if (sd->guild) { struct guild_storage *guild_storage = idb_get(gstorage->db,sd->guild->guild_id); if (guild_storage) { @@ -9552,28 +9945,28 @@ int pc_checkitem(struct map_session_data *sd) continue; if( sd->status.inventory[i].equip&~pc->equippoint(sd,i) ) { - pc->unequipitem(sd, i, 2); + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; continue; } - if ( battle_config.unequip_restricted_equipment & 1 ) { + if (battle_config.unequip_restricted_equipment&1) { int j; - for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) { - if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid ) { - pc->unequipitem( sd, i, 2 ); + for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) { + if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid) { + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; } } } - if ( battle_config.unequip_restricted_equipment & 2 ) { - if ( !itemdb_isspecial( sd->status.inventory[i].card[0] ) ) { + if (battle_config.unequip_restricted_equipment&2) { + if (!itemdb_isspecial(sd->status.inventory[i].card[0])) { int j, slot; - for ( slot = 0; slot < MAX_SLOTS; slot++ ) { - for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) { - if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].card[slot] ) { - pc->unequipitem( sd, i, 2 ); + for (slot = 0; slot < MAX_SLOTS; slot++) { + for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) { + if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].card[slot]) { + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; } } @@ -9709,9 +10102,9 @@ int pc_divorce(struct map_session_data *sd) 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); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, 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); + pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } clif->divorced(sd, p_sd->status.name); @@ -9993,7 +10386,7 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) { /** * Spirit Charm expiration timer. - * + * * @see TimerFunc */ int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) @@ -10031,7 +10424,7 @@ int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) /** * Adds a spirit charm. - * + * * @param sd Target character. * @param interval Duration. * @param max Maximum amount of charms to add. @@ -10074,7 +10467,7 @@ void pc_add_charm(struct map_session_data *sd, int interval, int max, int type) /** * Removes one or more spirit charms. - * + * * @param sd The target character. * @param count Amount of charms to remove. * @param type Type of charm to remove. @@ -10216,32 +10609,32 @@ void pc_read_skill_tree(void) { int i = 0; struct s_mapiterator *iter; struct map_session_data *sd; - + if (libconfig->read_file(&skill_tree_conf, config_filename)) { ShowError("can't read %s\n", config_filename); return; } - + while ((skt = libconfig->setting_get_elem(skill_tree_conf.root,i++))) { int k; const char *name = config_setting_name(skt); - + if ( (k = pc->check_job_name(name)) == -1 ) { ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n", name); continue; } - + if( ( skills = libconfig->setting_get_member(skt,"skills") ) ) { int c = 0; int idx = pc->class2idx(k); - + while ((sk = libconfig->setting_get_elem(skills,c++))) { const char *sk_name = config_setting_name(sk); int skill_id; - + if( ( skill_id = skill->name2id(sk_name) ) ) { int skidx, offset = 0, h = 0, rlen = 0; - + ARR_FIND( 0, MAX_SKILL_TREE, skidx, pc->skill_tree[idx][skidx].id == 0 || pc->skill_tree[idx][skidx].id == skill_id ); if (skidx == MAX_SKILL_TREE) { ShowWarning("pc_read_skill_tree: Unable to load skill %d (%s) into '%s's tree. Maximum number of skills per class has been reached.\n", skill_id, sk_name, name); @@ -10249,10 +10642,10 @@ void pc_read_skill_tree(void) { } else if (pc->skill_tree[idx][skidx].id) { ShowNotice("pc_read_skill_tree: Overwriting %d for '%s' (%d)\n", skill_id, name, k); } - + pc->skill_tree[idx][skidx].id = skill_id; pc->skill_tree[idx][skidx].idx = skill->get_index(skill_id); - + if( config_setting_is_group(sk) ) { int max = 0, jlevel = 0; libconfig->setting_lookup_int(sk, "MaxLevel", &max); @@ -10265,11 +10658,11 @@ void pc_read_skill_tree(void) { pc->skill_tree[idx][skidx].max = (unsigned char)libconfig->setting_get_int(sk); pc->skill_tree[idx][skidx].joblv = 0; } - + for (h = offset; h < rlen && h < MAX_PC_SKILL_REQUIRE; h++) { config_setting_t *rsk = libconfig->setting_get_elem(sk,h); int rskid; - if (rsk && ( rskid = skill->name2id(config_setting_name(rsk)))) { + if (rsk && (rskid = skill->name2id(config_setting_name(rsk))) != 0) { pc->skill_tree[idx][skidx].need[h].id = rskid; pc->skill_tree[idx][skidx].need[h].idx = skill->get_index(rskid); pc->skill_tree[idx][skidx].need[h].lv = (unsigned char)libconfig->setting_get_int(rsk); @@ -10279,19 +10672,18 @@ void pc_read_skill_tree(void) { ShowWarning("pc_read_skill_tree: error for '%s' in '%s'\n",sk_name,name); } } - } else { ShowWarning("pc_read_skill_tree: unknown skill '%s' in '%s'\n",sk_name,name); } } } } - + i = 0; while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) { int k, idx; const char *name = config_setting_name(skt); - + if ( (k = pc->check_job_name(name)) == -1 ) { ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n", name); continue; @@ -10329,9 +10721,8 @@ void pc_read_skill_tree(void) { } } - } - + libconfig->destroy(&skill_tree_conf); /* lets update all players skill tree */ @@ -10477,8 +10868,8 @@ int pc_readdb(void) { // 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++) + for ( j = ELE_NEUTRAL; j<ELE_MAX; j++ ) + for ( k = ELE_NEUTRAL; k<ELE_MAX; k++ ) battle->attr_fix_table[i][j][k]=100; sprintf(line, "%s/"DBPATH"attr_fix.txt", map->db_path); @@ -10505,13 +10896,13 @@ int pc_readdb(void) { lv=atoi(split[0]); n=atoi(split[1]); count++; - for(i=0;i<n && i<ELE_MAX;){ + for ( i = ELE_NEUTRAL; 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++){ + for ( j = ELE_NEUTRAL, p = line; j<n && j<ELE_MAX && p; j++ ) { while(*p==32 && *p>0) p++; battle->attr_fix_table[lv-1][i][j]=atoi(p); @@ -10618,7 +11009,7 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) { void pc_bank_deposit(struct map_session_data *sd, int money) { unsigned int limit_check = money+sd->status.bank_vault; - + if( money <= 0 || limit_check > MAX_BANK_ZENY ) { clif->bank_deposit(sd,BDA_OVERFLOW); return; @@ -10638,19 +11029,19 @@ void pc_bank_deposit(struct map_session_data *sd, int money) { } void pc_bank_withdraw(struct map_session_data *sd, int money) { unsigned int limit_check = money+sd->status.zeny; - - if( money <= 0 ) { + + if (money <= 0) { clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR); return; - } else if ( money > sd->status.bank_vault ) { + } else if (money > sd->status.bank_vault) { clif->bank_withdraw(sd,BWA_NO_MONEY); return; - } else if ( limit_check > MAX_ZENY ) { + } else if (limit_check > MAX_ZENY) { /* no official response for this scenario exists. */ - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1482)); + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1482)); return; } - + if( pc->getzeny(sd,money, LOG_TYPE_BANK, NULL) ) clif->bank_withdraw(sd,BWA_NO_MONEY); else { @@ -10664,16 +11055,16 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) { void pc_scdata_received(struct map_session_data *sd) { pc->inventory_rentals(sd); clif->show_modifiers(sd); - + if (sd->expiration_time != 0) { // don't display if it's unlimited or unknow value time_t exp_time = sd->expiration_time; char tmpstr[1024]; strftime(tmpstr, sizeof(tmpstr) - 1, msg_sd(sd,501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1); - + pc->expire_check(sd); } - + if( sd->state.standalone ) { clif->pLoadEndAck(0,sd); pc->autotrade_populate(sd); @@ -10682,16 +11073,16 @@ void pc_scdata_received(struct map_session_data *sd) { } int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = map->id2sd(id); - + if( !sd ) return 0; - + sd->expiration_tid = INVALID_TIMER; - + if( sd->fd ) clif->authfail_fd(sd->fd,10); - + map->quit(sd); - + return 0; } /* This timer exists only when a character with an expire timer > 24h is online */ @@ -10701,30 +11092,26 @@ int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data* sd; iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if( sd->expiration_time ) pc->expire_check(sd); } - mapit->free(iter); - + return 0; } void pc_expire_check(struct map_session_data *sd) { /* ongoing timer */ if( sd->expiration_tid != INVALID_TIMER ) return; - + /* not within the next 24h, enable the global check */ if( sd->expiration_time > ( time(NULL) + ( ( 60 * 60 ) * 24 ) ) ) { - /* global check not running, enable */ if( pc->expiration_tid == INVALID_TIMER ) { /* starts in 1h, repeats every hour */ pc->expiration_tid = timer->add_interval(timer->gettick() + ((1000*60)*60), pc->global_expiration_timer, 0, 0, ((1000*60)*60)); } - return; } @@ -10736,33 +11123,31 @@ void pc_expire_check(struct map_session_data *sd) { void pc_autotrade_load(void) { char *data; - + if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `account_id`,`char_id`,`sex`,`title` FROM `%s`",map->autotrade_merchants_db)) Sql_ShowDebug(map->mysql_handle); - + while (SQL_SUCCESS == SQL->NextRow(map->mysql_handle)) { struct map_session_data *sd; int account_id, char_id; char title[MESSAGE_SIZE]; unsigned char sex; - + SQL->GetData(map->mysql_handle, 0, &data, NULL); account_id = atoi(data); SQL->GetData(map->mysql_handle, 1, &data, NULL); char_id = atoi(data); SQL->GetData(map->mysql_handle, 2, &data, NULL); sex = atoi(data); SQL->GetData(map->mysql_handle, 3, &data, NULL); safestrncpy(title, data, sizeof(title)); CREATE(sd, TBL_PC, 1); - + pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0); - + safestrncpy(sd->message, title, MESSAGE_SIZE); - sd->state.standalone = 1; sd->group = pcg->get_dummy_group(); - + chrif->authreq(sd,true); } - SQL->FreeResult(map->mysql_handle); } /** @@ -10778,17 +11163,16 @@ void pc_autotrade_start(struct map_session_data *sd) { while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) { int itemkey, amount, price; - + SQL->GetData(map->mysql_handle, 0, &data, NULL); itemkey = atoi(data); SQL->GetData(map->mysql_handle, 1, &data, NULL); amount = atoi(data); SQL->GetData(map->mysql_handle, 2, &data, NULL); price = atoi(data); ARR_FIND(0, MAX_CART, i, sd->status.cart[i].id == itemkey); - if( i != MAX_CART && itemdb_cantrade(&sd->status.cart[i], 0, 0) ) { if( amount > sd->status.cart[i].amount ) amount = sd->status.cart[i].amount; - + if( amount ) { sd->vending[count].index = i; sd->vending[count].amount = amount; @@ -10798,7 +11182,7 @@ void pc_autotrade_start(struct map_session_data *sd) { } } } - + if( !count ) { pc->autotrade_update(sd,PAUC_REMOVE); map->quit(sd); @@ -10817,13 +11201,13 @@ void pc_autotrade_start(struct map_session_data *sd) { **/ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) { int i; - + /* either way, this goes down */ if( action != PAUC_START ) { if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id)) Sql_ShowDebug(map->mysql_handle); } - + switch( action ) { case PAUC_REMOVE: if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' LIMIT 1",map->autotrade_merchants_db,sd->status.char_id)) @@ -10831,7 +11215,7 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update break; case PAUC_START: { char title[MESSAGE_SIZE*2+1]; - + SQL->EscapeStringLen(map->mysql_handle, title, sd->message, strnlen(sd->message, MESSAGE_SIZE)); if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`account_id`,`char_id`,`sex`,`title`) VALUES ('%d','%d','%d','%s')", @@ -10848,7 +11232,7 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update for( i = 0; i < sd->vend_num; i++ ) { if( sd->vending[i].amount == 0 ) continue; - + if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%d')", map->autotrade_data_db, sd->status.char_id, @@ -10872,25 +11256,25 @@ void pc_autotrade_prepare(struct map_session_data *sd) { unsigned char sex; CREATE(data, struct autotrade_vending, 1); - + memcpy(data->vending, sd->vending, sizeof(sd->vending)); - + for(i = 0; i < sd->vend_num; i++) { if( sd->vending[i].amount ) { memcpy(&data->list[cursor],&sd->status.cart[sd->vending[i].index],sizeof(struct item)); cursor++; } } - + data->vend_num = (unsigned char)cursor; - + idb_put(pc->at_db, sd->status.char_id, data); - + account_id = sd->status.account_id; char_id = sd->status.char_id; sex = sd->status.sex; safestrncpy(title, sd->message, sizeof(title)); - + sd->npc_id = 0; sd->npc_shopid = 0; if (sd->st) { @@ -10901,11 +11285,10 @@ void pc_autotrade_prepare(struct map_session_data *sd) { chrif->auth_delete(account_id, char_id, ST_LOGOUT); CREATE(sd, TBL_PC, 1); - + pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0); - + safestrncpy(sd->message, title, MESSAGE_SIZE); - sd->state.standalone = 1; sd->group = pcg->get_dummy_group(); @@ -10924,7 +11307,7 @@ void pc_autotrade_populate(struct map_session_data *sd) { for(i = 0; i < data->vend_num; i++) { if( !data->vending[i].amount ) continue; - + for(j = 0; j < MAX_CART; j++) { if( !memcmp((char*)(&data->list[i]) + sizeof(data->list[0].id), (char*)(&sd->status.cart[j]) + sizeof(data->list[0].id), sizeof(struct item) - sizeof(data->list[0].id)) ) { if( cursor ) { @@ -10935,23 +11318,50 @@ void pc_autotrade_populate(struct map_session_data *sd) { break; } } - + if( j != MAX_CART ) { sd->vending[cursor].index = j; sd->vending[cursor].amount = data->vending[i].amount; sd->vending[cursor].value = data->vending[i].value; - + cursor++; } } - + sd->vend_num = cursor; pc->autotrade_update(sd,PAUC_START); - + + for(i = 0; i < data->hdatac; i++ ) { + if( data->hdata[i]->flag.free ) { + aFree(data->hdata[i]->data); + } + aFree(data->hdata[i]); + } + if( data->hdata ) + aFree(data->hdata); + idb_remove(pc->at_db, sd->status.char_id); } +/** + * @see DBApply + */ +int pc_autotrade_final(DBKey key, DBData *data, va_list ap) { + struct autotrade_vending* at_v = DB->data2ptr(data); + int i; + for(i = 0; i < at_v->hdatac; i++ ) { + if( at_v->hdata[i]->flag.free ) { + aFree(at_v->hdata[i]->data); + } + aFree(at_v->hdata[i]); + } + if( at_v->hdata ) + aFree(at_v->hdata); + + return 0; +} + //Checks if the given class value corresponds to a player class. [Skotlex] //JOB_NOVICE isn't checked for class_ is supposed to be unsigned bool pc_db_checkid(unsigned int class_) @@ -10966,12 +11376,11 @@ bool pc_db_checkid(unsigned int class_) } void do_final_pc(void) { - db_destroy(pc->itemcd_db); - db_destroy(pc->at_db); - + pc->at_db->destroy(pc->at_db,pc->autotrade_final); + pcg->final(); - + ers_destroy(pc->sc_display_ers); ers_destroy(pc->num_reg_ers); ers_destroy(pc->str_reg_ers); @@ -10982,12 +11391,12 @@ void do_final_pc(void) { void do_init_pc(bool minimal) { if (minimal) return; - + pc->itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA); pc->at_db = idb_alloc(DB_OPT_RELEASE_DATA); - + pc->readdb(); - + timer->add_func_list(pc->invincible_timer, "pc_invincible_timer"); timer->add_func_list(pc->eventtimer, "pc_eventtimer"); timer->add_func_list(pc->inventory_rental_end, "pc_inventory_rental_end"); @@ -10999,25 +11408,25 @@ void do_init_pc(bool minimal) { timer->add_func_list(pc->charm_timer, "pc_charm_timer"); timer->add_func_list(pc->global_expiration_timer,"pc_global_expiration_timer"); timer->add_func_list(pc->expiration_timer,"pc_expiration_timer"); - + timer->add(timer->gettick() + map->autosave_interval, pc->autosave, 0, 0); - + // 0=day, 1=night [Yor] map->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] timer->add_func_list(pc->map_day_timer, "pc_map_day_timer"); timer->add_func_list(pc->map_night_timer, "pc_map_night_timer"); - + pc->day_timer_tid = timer->add_interval(timer->gettick() + (map->night_flag ? 0 : day_duration) + night_duration, pc->map_day_timer, 0, 0, day_duration + night_duration); pc->night_timer_tid = timer->add_interval(timer->gettick() + day_duration + (map->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration); } - + pcg->init(); - + pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_FLEX_CHUNK); pc->num_reg_ers = ers_new(sizeof(struct script_reg_num), "pc.c::num_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); pc->str_reg_ers = ers_new(sizeof(struct script_reg_str), "pc.c::str_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); @@ -11047,16 +11456,10 @@ void pc_defaults(void) { /* */ pc->day_timer_tid = INVALID_TIMER; pc->night_timer_tid = INVALID_TIMER; - /* respecting order */ - memset(pc->exp_table, 0, sizeof(pc->exp_table) - + sizeof(pc->max_level) - + sizeof(pc->statp) - + sizeof(pc->level_penalty) - + sizeof(pc->skill_tree) - + sizeof(pc->smith_fame_list) - + sizeof(pc->chemist_fame_list) - + sizeof(pc->taekwon_fame_list) - ); + + // These macros are used instead of a sum of sizeof(), to ensure that padding won't interfere with our size, and code won't rot when adding more fields + memset(ZEROED_BLOCK_POS(pc), 0, ZEROED_BLOCK_SIZE(pc)); + /* */ memcpy(pc->equip_pos, &equip_pos, sizeof(pc->equip_pos)); /* */ @@ -11076,7 +11479,7 @@ void pc_defaults(void) { pc->get_dummy_sd = pc_get_dummy_sd; pc->class2idx = pc_class2idx; - + pc->can_use_command = pc_can_use_command; pc->set_group = pc_set_group; pc->should_log_commands = pc_should_log_commands; @@ -11088,25 +11491,25 @@ void pc_defaults(void) { pc->authok = pc_authok; pc->authfail = pc_authfail; pc->reg_received = pc_reg_received; - + pc->isequip = pc_isequip; pc->equippoint = pc_equippoint; pc->setinventorydata = pc_setinventorydata; - + pc->checkskill = pc_checkskill; pc->checkskill2 = pc_checkskill2; pc->checkallowskill = pc_checkallowskill; pc->checkequip = pc_checkequip; - + pc->calc_skilltree = pc_calc_skilltree; pc->calc_skilltree_normalize_job = pc_calc_skilltree_normalize_job; pc->clean_skilltree = pc_clean_skilltree; - + pc->setpos = pc_setpos; pc->setsavepoint = pc_setsavepoint; pc->randomwarp = pc_randomwarp; pc->memo = pc_memo; - + pc->checkadditem = pc_checkadditem; pc->inventoryblank = pc_inventoryblank; pc->search_inventory = pc_search_inventory; @@ -11117,45 +11520,47 @@ void pc_defaults(void) { // Special Shop System pc->paycash = pc_paycash; pc->getcash = pc_getcash; - + pc->cart_additem = pc_cart_additem; pc->cart_delitem = pc_cart_delitem; pc->putitemtocart = pc_putitemtocart; pc->getitemfromcart = pc_getitemfromcart; pc->cartitem_amount = pc_cartitem_amount; - + pc->takeitem = pc_takeitem; pc->dropitem = pc_dropitem; - + pc->isequipped = pc_isequipped; pc->can_Adopt = pc_can_Adopt; pc->adoption = pc_adoption; - + pc->updateweightstatus = pc_updateweightstatus; - + pc->addautobonus = pc_addautobonus; pc->exeautobonus = pc_exeautobonus; pc->endautobonus = pc_endautobonus; pc->delautobonus = pc_delautobonus; - + pc->bonus = pc_bonus; pc->bonus2 = pc_bonus2; pc->bonus3 = pc_bonus3; pc->bonus4 = pc_bonus4; pc->bonus5 = pc_bonus5; pc->skill = pc_skill; - + pc->insert_card = pc_insert_card; - + pc->can_insert_card = pc_can_insert_card; + pc->can_insert_card_into = pc_can_insert_card_into; + pc->steal_item = pc_steal_item; pc->steal_coin = pc_steal_coin; - + pc->modifybuyvalue = pc_modifybuyvalue; pc->modifysellvalue = pc_modifysellvalue; - + pc->follow = pc_follow; // [MouseJstr] pc->stop_following = pc_stop_following; - + pc->maxbaselv = pc_maxbaselv; pc->maxjoblv = pc_maxjoblv; pc->checkbaselevelup = pc_checkbaselevelup; @@ -11183,11 +11588,11 @@ void pc_defaults(void) { pc->unequipitem_pos = pc_unequipitem_pos; pc->checkitem = pc_checkitem; pc->useitem = pc_useitem; - + pc->skillatk_bonus = pc_skillatk_bonus; pc->skillheal_bonus = pc_skillheal_bonus; pc->skillheal2_bonus = pc_skillheal2_bonus; - + pc->damage = pc_damage; pc->dead = pc_dead; pc->revive = pc_revive; @@ -11204,7 +11609,7 @@ void pc_defaults(void) { pc->setridingwug = pc_setridingwug; pc->changelook = pc_changelook; pc->equiplookall = pc_equiplookall; - + pc->readparam = pc_readparam; pc->setparam = pc_setparam; pc->readreg = pc_readreg; @@ -11215,15 +11620,15 @@ void pc_defaults(void) { pc->setregistry = pc_setregistry; pc->readregistry_str = pc_readregistry_str; pc->setregistry_str = pc_setregistry_str; - + pc->addeventtimer = pc_addeventtimer; pc->deleventtimer = pc_deleventtimer; pc->cleareventtimer = pc_cleareventtimer; pc->addeventtimercount = pc_addeventtimercount; - + pc->calc_pvprank = pc_calc_pvprank; pc->calc_pvprank_timer = pc_calc_pvprank_timer; - + pc->ismarried = pc_ismarried; pc->marriage = pc_marriage; pc->divorce = pc_divorce; @@ -11231,29 +11636,30 @@ void pc_defaults(void) { pc->get_father = pc_get_father; pc->get_mother = pc_get_mother; pc->get_child = pc_get_child; - + pc->bleeding = pc_bleeding; pc->regen = pc_regen; - + pc->setstand = pc_setstand; pc->candrop = pc_candrop; pc->can_talk = pc_can_talk; pc->can_attack = pc_can_attack; - + pc->jobid2mapid = pc_jobid2mapid; // Skotlex pc->mapid2jobid = pc_mapid2jobid; // Skotlex - + pc->job_name = job_name; - + pc->setinvincibletimer = pc_setinvincibletimer; pc->delinvincibletimer = pc_delinvincibletimer; - + pc->addspiritball = pc_addspiritball; pc->delspiritball = pc_delspiritball; pc->addfame = pc_addfame; pc->famerank = pc_famerank; pc->set_hate_mob = pc_set_hate_mob; - + pc->getmaxspiritball = pc_getmaxspiritball; + pc->readdb = pc_readdb; pc->map_day_timer = map_day_timer; // by [yor] pc->map_night_timer = map_night_timer; // by [yor] @@ -11261,26 +11667,24 @@ void pc_defaults(void) { pc->inventory_rentals = pc_inventory_rentals; pc->inventory_rental_clear = pc_inventory_rental_clear; pc->inventory_rental_add = pc_inventory_rental_add; - + pc->disguise = pc_disguise; pc->isautolooting = pc_isautolooting; - + pc->overheat = pc_overheat; - pc->banding = pc_banding; - + pc->itemcd_do = pc_itemcd_do; - pc->load_combo = pc_load_combo; - + pc->add_charm = pc_add_charm; pc->del_charm = pc_del_charm; - + pc->baselevelchanged = pc_baselevelchanged; pc->level_penalty_mod = pc_level_penalty_mod; - + pc->calc_skillpoint = pc_calc_skillpoint; - + pc->invincible_timer = pc_invincible_timer; pc->spiritball_timer = pc_spiritball_timer; pc->check_banding = pc_check_banding; @@ -11308,15 +11712,15 @@ void pc_defaults(void) { pc->checkcombo = pc_checkcombo; pc->calcweapontype = pc_calcweapontype; pc->removecombo = pc_removecombo; - + pc->bank_withdraw = pc_bank_withdraw; pc->bank_deposit = pc_bank_deposit; - + pc->rental_expire = pc_rental_expire; pc->scdata_received = pc_scdata_received; - + pc->bound_clear = pc_bound_clear; - + pc->expiration_timer = pc_expiration_timer; pc->global_expiration_timer = pc_global_expiration_timer; pc->expire_check = pc_expire_check; @@ -11331,6 +11735,7 @@ void pc_defaults(void) { pc->autotrade_start = pc_autotrade_start; pc->autotrade_prepare = pc_autotrade_prepare; pc->autotrade_populate = pc_autotrade_populate; + pc->autotrade_final = pc_autotrade_final; pc->check_job_name = pc_check_job_name; } diff --git a/src/map/pc.h b/src/map/pc.h index 867344d58..e6e95978d 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -5,23 +5,21 @@ #ifndef MAP_PC_H #define MAP_PC_H -#include "../config/core.h" // AUTOLOOTITEM_SIZE, RENEWAL, SECURE_NPCTIMEOUT - -#include "battle.h" // battle -#include "battleground.h" // enum bg_queue_types -#include "buyingstore.h" // struct s_buyingstore -#include "itemdb.h" // MAX_ITEMDELAYS -#include "log.h" // struct e_log_pick_type -#include "map.h" // RC_MAX, ELE_MAX -#include "pc_groups.h" // GroupSettings -#include "script.h" // struct reg_db -#include "searchstore.h" // struct s_search_store_info -#include "status.h" // enum sc_type, OPTION_* -#include "unit.h" // struct unit_data, struct view_data -#include "vending.h" // struct s_vending -#include "../common/cbasetypes.h" -#include "../common/ers.h" // struct eri -#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS +#include "map/battle.h" // battle +#include "map/battleground.h" // enum bg_queue_types +#include "map/buyingstore.h" // struct s_buyingstore +#include "map/itemdb.h" // MAX_ITEMDELAYS +#include "map/log.h" // struct e_log_pick_type +#include "map/map.h" // RC_MAX, ELE_MAX +#include "map/pc_groups.h" // GroupSettings +#include "map/script.h" // struct reg_db +#include "map/searchstore.h" // struct s_search_store_info +#include "map/status.h" // enum sc_type, OPTION_* +#include "map/unit.h" // struct unit_data, struct view_data +#include "map/vending.h" // struct s_vending +#include "common/hercules.h" +#include "common/ers.h" // struct eri +#include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS /** * Defines @@ -29,7 +27,8 @@ #define MAX_PC_BONUS 10 #define MAX_PC_SKILL_REQUIRE 5 #define MAX_PC_FEELHATE 3 -#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval +#define MAX_PC_DEVOTION 5 ///< Max amount of devotion targets +#define PVP_CALCRANK_INTERVAL 1000 ///< PVP calculation interval //Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index //where the arrows are equipped) @@ -57,11 +56,23 @@ enum equip_index { EQI_SHADOW_ACC_L, EQI_MAX }; + +enum pc_unequipitem_flag { + PCUNEQUIPITEM_NONE = 0x0, ///< Just unequip + PCUNEQUIPITEM_RECALC = 0x1, ///< Recalculate status after unequipping + PCUNEQUIPITEM_FORCE = 0x2, ///< Force unequip +}; + +enum pc_resetskill_flag { + PCRESETSKILL_NONE = 0x0, + PCRESETSKILL_RESYNC = 0x1, // perform block resync and status_calc call + PCRESETSKILL_RECOUNT = 0x2, // just count total amount of skill points used by player, do not really reset + PCRESETSKILL_CHSEX = 0x4, // just reset the skills if the player class is a bard/dancer type (for changesex.) +}; + 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] +BEGIN_ZEROED_BLOCK; // all the variables within this block get zero'ed in each call of status_calc_pc int overrefine; int star; int ignore_def_ele; @@ -85,6 +96,7 @@ struct weapon_data { short flag, rate; unsigned char ele; } addele2[MAX_PC_BONUS]; +END_ZEROED_BLOCK; }; struct s_autospell { short id, lv, rate, card_id, flag; @@ -145,7 +157,7 @@ struct map_session_data { 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 storage_flag : 2; // @see enum storage_flag 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] @@ -192,6 +204,7 @@ struct map_session_data { unsigned int itemcheck : 1; unsigned int standalone : 1;/* [Ind/Hercules <3] */ unsigned int loggingout : 1; + unsigned int warp_clean : 1; } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -264,7 +277,8 @@ struct map_session_data { 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() + +BEGIN_ZEROED_BLOCK; // this block will 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]; @@ -292,8 +306,6 @@ struct map_session_data { #ifdef RENEWAL int race_tolerance[RC_MAX]; #endif - // 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]; @@ -322,11 +334,6 @@ struct map_session_data { short value; int rate, tick; } def_set_race[RC_MAX], mdef_set_race[RC_MAX]; - // 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; @@ -363,7 +370,11 @@ struct map_session_data { int add_fixcast,add_varcast; int ematk; // matk bonus from equipment } bonus; - // zeroed vars end here. +END_ZEROED_BLOCK; + + // The following structures are zeroed manually in status_calc_pc_ + struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage + int castrate,delayrate,hprate,sprate,dsprate; int hprecov_rate,sprecov_rate; int matk_rate; @@ -380,7 +391,7 @@ struct map_session_data { 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 devotion[MAX_PC_DEVOTION]; //Stores the account IDs of chars devoted to. int trade_partner; struct { struct { @@ -412,11 +423,11 @@ struct map_session_data { struct mercenary_data *md; struct elemental_data *ed; - struct{ + 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]; + } feel_map[MAX_PC_FEELHATE];// 0 - Sun; 1 - Moon; 2 - Stars + short hate_mob[MAX_PC_FEELHATE]; int pvp_timer; short pvp_point; @@ -558,7 +569,7 @@ struct map_session_data { } roulette; uint8 lang_id; - + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; @@ -730,12 +741,25 @@ enum e_pc_autotrade_update_action { }; /** + * Flag values for pc->skill + */ +enum pc_skill_flag { + SKILL_GRANT_PERMANENT = 0, // Grant permanent skill to be bound to skill tree + SKILL_GRANT_TEMPORARY = 1, // Grant an item skill (temporary) + SKILL_GRANT_TEMPSTACK = 2, // Like 1, except the level granted can stack with previously learned level. + SKILL_GRANT_UNCONDITIONAL = 3, // Grant skill unconditionally and forever (persistent to job changes and skill resets) +}; + +/** * Used to temporarily remember vending data **/ struct autotrade_vending { struct item list[MAX_VENDING]; struct s_vending vending[MAX_VENDING]; unsigned char vend_num; + /* HPM Custom Struct */ + struct HPluginData **hdata; + unsigned int hdatac; }; /*===================================== @@ -753,17 +777,20 @@ struct pc_interface { int day_timer_tid; int night_timer_tid; /* */ + +BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */ unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL]; unsigned int max_level[CLASS_COUNT][2]; unsigned int statp[MAX_LEVEL+1]; unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1]; - - unsigned int equip_pos[EQI_MAX]; /* */ struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE]; 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]; +END_ZEROED_BLOCK; /* End */ + + unsigned int equip_pos[EQI_MAX]; struct sg_data sg_info[MAX_PC_FEELHATE]; /* */ struct eri *sc_display_ers; @@ -855,6 +882,8 @@ struct pc_interface { int (*skill) (struct map_session_data *sd, int id, int level, int flag); int (*insert_card) (struct map_session_data *sd,int idx_card,int idx_equip); + bool (*can_insert_card) (struct map_session_data* sd, int idx_card); + bool (*can_insert_card_into) (struct map_session_data* sd, int idx_card, int idx_equip); int (*steal_item) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv); int (*steal_coin) (struct map_session_data *sd,struct block_list *bl); @@ -887,7 +916,7 @@ struct pc_interface { int (*resetfeel) (struct map_session_data *sd); int (*resethate) (struct map_session_data *sd); int (*equipitem) (struct map_session_data *sd,int n,int req_pos); - void (*equipitem_pos) (struct map_session_data *sd, struct item_data *id, int pos); + void (*equipitem_pos) (struct map_session_data *sd, struct item_data *id, int n, int pos); int (*unequipitem) (struct map_session_data *sd,int n,int flag); void (*unequipitem_pos) (struct map_session_data *sd, int n, int pos); int (*checkitem) (struct map_session_data *sd); @@ -957,6 +986,7 @@ struct pc_interface { int (*addspiritball) (struct map_session_data *sd,int interval,int max); int (*delspiritball) (struct map_session_data *sd,int count,int type); + int (*getmaxspiritball) (struct map_session_data *sd, int min); void (*addfame) (struct map_session_data *sd,int count); unsigned char (*famerank) (int char_id, int job); int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl); @@ -1039,14 +1069,15 @@ struct pc_interface { void (*autotrade_start) (struct map_session_data *sd); void (*autotrade_prepare) (struct map_session_data *sd); void (*autotrade_populate) (struct map_session_data *sd); + int (*autotrade_final) (DBKey key, DBData *data, va_list ap); int (*check_job_name) (const char *name); }; -struct pc_interface *pc; - #ifdef HERCULES_CORE void pc_defaults(void); #endif // HERCULES_CORE +HPShared struct pc_interface *pc; + #endif /* MAP_PC_H */ diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 9cd478b3f..7efcd7e26 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -6,21 +6,22 @@ #include "pc_groups.h" -#include "atcommand.h" // atcommand->exists(), atcommand->load_groups() -#include "clif.h" // clif->GM_kick() -#include "map.h" // mapiterator -#include "pc.h" // pc->set_group() -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" // strcmp +#include "map/atcommand.h" // atcommand-"exists(), atcommand-"load_groups() +#include "map/clif.h" // clif-"GM_kick() +#include "map/map.h" // mapiterator +#include "map/pc.h" // pc-"set_group() +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" // strcmp static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd() struct pc_groups_interface pcg_s; +struct pc_groups_interface *pcg; /** * Returns dummy group. @@ -50,7 +51,7 @@ 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 (libconfig->read_file(&pc_group_config, config_filename)) return; @@ -124,11 +125,10 @@ static void read_config(void) { strdb_put(pcg->name_db, groupname, group_settings); idb_put(pcg->db, id, group_settings); - } group_count = libconfig->setting_length(groups); // Save number of groups assert(group_count == db_size(pcg->db)); - + // Check if all commands and permissions exist iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { @@ -181,7 +181,7 @@ static void read_config(void) { *commands = group_settings->commands, *permissions = group_settings->permissions; int j, inherit_count = 0, done = 0; - + if (group_settings->inheritance_done) // group already processed continue; @@ -191,7 +191,7 @@ static void read_config(void) { group_settings->inheritance_done = true; continue; } - + for (j = 0; j < inherit_count; ++j) { GroupSettings *inherited_group = NULL; const char *groupname = libconfig->setting_get_string_elem(inherit, j); @@ -224,7 +224,7 @@ static void read_config(void) { ++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 @@ -238,7 +238,7 @@ static void read_config(void) { break; } } // while(i < group_count) - + // Pack permissions into GroupSettings.e_permissions for faster checking iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { @@ -364,28 +364,28 @@ int pc_group_get_idx(GroupSettings *group) unsigned int pc_groups_add_permission(const char *name) { uint64 key = 0x1; unsigned char i; - + for(i = 0; i < pcg->permission_count; i++) { if( strcmpi(name,pcg->permissions[i].name) == 0 ) { ShowError("pc_groups_add_permission(%s): failed! duplicate permission name!\n",name); return 0; } } - + if( i != 0 ) key = (uint64)pcg->permissions[i - 1].permission << 1; - + if( key >= UINT_MAX ) { ShowError("pc_groups_add_permission(%s): failed! not enough room, too many permissions!\n",name); return 0; } - + i = pcg->permission_count; RECREATE(pcg->permissions, struct pc_groups_permission_table, ++pcg->permission_count); - + pcg->permissions[i].name = aStrdup(name); pcg->permissions[i].permission = (unsigned int)key; - + return (unsigned int)key; } /** @@ -426,23 +426,23 @@ void do_init_pc_groups(void) { { "disable_skill_usage", PC_PERM_DISABLE_SKILL_USAGE }, }; unsigned char i, len = ARRAYLENGTH(pc_g_defaults); - + for(i = 0; i < len; i++) { unsigned int p; if( ( p = pc_groups_add_permission(pc_g_defaults[i].name) ) != pc_g_defaults[i].permission ) ShowError("do_init_pc_groups: %s error : %d != %d\n",pc_g_defaults[i].name,p,pc_g_defaults[i].permission); } - + /** * Handle plugin-provided permissions **/ for(i = 0; i < pcg->HPMpermissions_count; i++) { *pcg->HPMpermissions[i].mask = pc_groups_add_permission(pcg->HPMpermissions[i].name); } - + pcg->db = idb_alloc(DB_OPT_RELEASE_DATA); pcg->name_db = stridb_alloc(DB_OPT_DUP_KEY, 0); - + read_config(); } @@ -467,7 +467,7 @@ void do_final_pc_groups(void) pcg->db->destroy(pcg->db, group_db_clear_sub); if (pcg->name_db != NULL) db_destroy(pcg->name_db); - + if(pcg->permissions != NULL) { unsigned char i; for(i = 0; i < pcg->permission_count; i++) @@ -489,7 +489,7 @@ void pc_groups_reload(void) { pcg->final(); pcg->init(); - + /* refresh online users permissions */ iter = mapit_getallusers(); for (sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter)) { @@ -507,7 +507,6 @@ void pc_groups_reload(void) { **/ void pc_groups_defaults(void) { pcg = &pcg_s; - /* */ pcg->db = NULL; pcg->name_db = NULL; diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 8dd95a177..6f92a7955 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -5,9 +5,9 @@ #ifndef MAP_PC_GROUPS_H #define MAP_PC_GROUPS_H -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" +#include "common/hercules.h" +#include "common/conf.h" +#include "common/db.h" /// PC permissions enum e_pc_permission { @@ -96,10 +96,10 @@ struct pc_groups_interface { int (*get_idx) (GroupSettings *group); }; -struct pc_groups_interface *pcg; - #ifdef HERCULES_CORE void pc_groups_defaults(void); #endif // HERCULES_CORE +HPShared struct pc_groups_interface *pcg; + #endif /* MAP_PC_GROUPS_H */ diff --git a/src/map/pet.c b/src/map/pet.c index 52a8017b4..2865cc901 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -4,39 +4,41 @@ #define HERCULES_CORE +#include "config/core.h" // DBPATH #include "pet.h" +#include "map/atcommand.h" // msg_txt() +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" // msg_txt() -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "unit.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct pet_interface pet_s; +struct pet_interface *pet; #define MIN_PETTHINKTIME 100 @@ -91,7 +93,7 @@ int pet_unlocktarget(struct pet_data *pd) pd->target_id=0; pet_stop_attack(pd); - pet_stop_walking(pd,1); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -105,7 +107,7 @@ int pet_attackskill(struct pet_data *pd, int target_id) { if (DIFF_TICK(pd->ud.canact_tick, timer->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; @@ -131,7 +133,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) int rate; pd = sd->pd; - + Assert_ret(pd->msd == 0 || pd->msd->pd == pd); if( bl == NULL || bl->type != BL_MOB || bl->prev == NULL @@ -184,7 +186,7 @@ int pet_sc_check(struct map_session_data *sd, int type) return 1; pd->recovery->timer = timer->add(timer->gettick()+pd->recovery->delay*1000,pet->recovery_timer,sd->bl.id,0); - + return 0; } @@ -209,7 +211,7 @@ int pet_hungry(int tid, int64 tick, int id, intptr_t data) { if (pd->pet.intimate <= 0) return 1; //You lost the pet already, the rest is irrelevant. - + pd->pet.hungry--; if( pd->pet.hungry < 0 ) { @@ -280,7 +282,7 @@ int pet_performance(struct map_session_data *sd, struct pet_data *pd) else val = 1; - pet_stop_walking(pd,2000<<8); + pet_stop_walking(pd,STOPWALKING_FLAG_NONE | (2000<<8)); // Stop walking for 2000ms clif->send_petdata(NULL, pd, 4, rnd()%val + 1); pet->lootitem_drop(pd,NULL); return 1; @@ -301,7 +303,7 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) 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); + map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } pd->pet.incubate = 1; unit->free(&pd->bl,CLR_OUTSIGHT); @@ -335,7 +337,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) //The pet_id value was lost? odd... restore it. sd->status.pet_id = petinfo->pet_id; } - + i = pet->search_petDB_index(petinfo->class_,PET_CLASS); if(i < 0) { sd->status.pet_id = 0; @@ -365,10 +367,10 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) pd->last_thinktime = timer->gettick(); pd->state.skillbonus = 0; - + if( battle_config.pet_status_support ) - script->run(pet->db[i].pet_script,0,sd->bl.id,0); - + script->run_pet(pet->db[i].pet_script,0,sd->bl.id,0); + if( pd->petDB ) { if( pd->petDB->equip_script ) status_calc_pc(sd,SCO_NONE); @@ -378,7 +380,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) else interval = pd->petDB->hungry_delay; } - + if( interval <= 0 ) interval = 1; pd->pet_hungry_timer = timer->add(timer->gettick() + interval, pet->hungry, sd->bl.id, 0); @@ -445,7 +447,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { return 1; } if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd,i,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -565,7 +567,7 @@ bool pet_get_egg(int account_id, short pet_class, int pet_id ) { // the first request. [Panikon] i = pet->search_petDB_index(pet_class,PET_CLASS); sd->catch_target_class = -1; - + if(i < 0) { intif->delete_petdata(pet_id); return false; @@ -580,7 +582,7 @@ bool pet_get_egg(int account_id, short pet_class, int pet_id ) { 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); + map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } return true; @@ -592,11 +594,11 @@ 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.incubate) return 1; - + egg_id = itemdb->exists(sd->pd->petDB->EggID); if (egg_id) { if ((egg_id->flag.trade_restriction&ITR_NODROP) && !pc->inventoryblank(sd)) { @@ -604,7 +606,7 @@ int pet_menu(struct map_session_data *sd,int menunum) return 1; } } - + switch(menunum) { case 0: clif->send_petstatus(sd); @@ -670,15 +672,15 @@ int pet_equipitem(struct map_session_data *sd,int index) { 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,EIA_FAIL); return 1; } - pc->delitem(sd,index,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, index, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); pd->pet.equip = nameid; status->set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); @@ -711,7 +713,7 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) { 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); + map->addflooritem(&sd->bl, &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 @@ -743,7 +745,7 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd) { clif->pet_food(sd, food_id, 0); return 1; } - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); if (pd->pet.hungry > 90) { pet->set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); @@ -793,7 +795,7 @@ int pet_randomwalk(struct pet_data *pd, int64 tick) int r=rnd(); int x=pd->bl.x+r%(d*2+1)-d; int 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)) { + if(map->getcell (pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&pd->bl, x, y, 0)) { pd->move_fail_count=0; break; } @@ -841,7 +843,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick 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) @@ -865,7 +867,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick 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) @@ -875,13 +877,13 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick pet->unlocktarget(pd); } } - + if(!target && pd->loot && pd->msd && pc_has_permission(pd->msd, PC_PERM_TRADE) && 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)) @@ -896,7 +898,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick return 0; } - + if(pd->ud.target == target->id && (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER)) return 0; //Target already locked. @@ -960,7 +962,7 @@ int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) 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)))) @@ -980,9 +982,9 @@ int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) { ditem = list->item; while (ditem) { struct item_drop *ditem_prev; - 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); + map->addflooritem(NULL, &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(pet->item_drop_ers, ditem_prev); @@ -1045,18 +1047,18 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { struct pet_data *pd; int bonus; int duration = 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; @@ -1068,7 +1070,7 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { pd->bonus->timer = INVALID_TIMER; return 0; } - + if (pd->state.skillbonus != bonus) { pd->state.skillbonus = bonus; status_calc_pc(sd, SCO_NONE); @@ -1084,10 +1086,10 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { int pet_recovery_timer(int tid, int64 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) { @@ -1104,7 +1106,7 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) { } pd->recovery->timer = INVALID_TIMER; - + return 0; } @@ -1118,14 +1120,14 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { 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; } - + st = status->get_status_data(&sd->bl); if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) { @@ -1133,7 +1135,7 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { pd->s_skill->timer=timer->add(pd->ud.canact_tick,pet->skill_support_timer,sd->bl.id,0); return 0; } - + if(pc_isdead(sd) || (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp || (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp || @@ -1142,9 +1144,9 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { pd->s_skill->timer=timer->add(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); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); pd->s_skill->timer=timer->add(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); @@ -1153,26 +1155,24 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -/*========================================== - * Pet read db data - * pet->db.txt - * pet->db2.txt - *------------------------------------------*/ +/** + * Loads (or reloads) the pet database. + */ int read_petdb() { - char* filename[] = {"pet_db.txt","pet_db2.txt"}; - int nameid,i,j,k; + const char *filename[] = { + DBPATH"pet_db.txt", + "pet_db2.txt", + }; + int i,j; // Remove any previous scripts in case reloaddb was invoked. - for( j = 0; j < MAX_PET_DB; j++ ) - { - if( pet->db[j].pet_script ) - { + 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 ) - { + if (pet->db[j].equip_script) { script->free_code(pet->db[j].equip_script); pet->db[j].equip_script = NULL; } @@ -1182,59 +1182,56 @@ int read_petdb() memset(pet->db,0,sizeof(pet->db)); j = 0; // entry counter - for( i = 0; i < ARRAYLENGTH(filename); i++ ) { + for (i = 0; i < ARRAYLENGTH(filename); i++) { char line[1024]; int lines, entries; FILE *fp; sprintf(line, "%s/%s", map->db_path, filename[i]); fp=fopen(line,"r"); - if( fp == NULL ) { - if( i == 0 ) + 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 ) { + while (fgets(line, sizeof(line), fp) && j < MAX_PET_DB) { char *str[22], *p; + int nameid, k; lines++; - if(line[0] == '/' && line[1] == '/') + if (line[0] == '/' && line[1] == '/') continue; memset(str, 0, sizeof(str)); p = line; - while( ISSPACE(*p) ) + while (ISSPACE(*p)) ++p; - if( *p == '\0' ) + if (*p == '\0') continue; // empty line - for( k = 0; k < 20; ++k ) - { + for (k = 0; k < 20; ++k) { str[k] = p; p = strchr(p,','); - if( p == NULL ) + if (p == NULL) break; // comma not found *p = '\0'; ++p; } - if( p == NULL ) - { + if (p == NULL) { ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines); continue; } // Pet Script - if( *p != '{' ) - { + 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 ) - { + if (p == NULL) { ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); continue; } @@ -1242,18 +1239,17 @@ int read_petdb() p += 2; // Equip Script - if( *p != '{' ) - { + 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 ) + nameid = atoi(str[0]); + if (nameid <= 0) continue; - if( !mob->db_checkid(nameid) ) - { + if (!mob->db_checkid(nameid)) { ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid); continue; } @@ -1268,7 +1264,7 @@ int read_petdb() 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 ) + 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]); @@ -1283,16 +1279,16 @@ int read_petdb() pet->db[j].pet_script = NULL; pet->db[j].equip_script = NULL; - if( *str[20] ) + if (*str[20]) pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL); - if( *str[21] ) + if (*str[21]) pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL); j++; entries++; } - if( j >= MAX_PET_DB ) + 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]); @@ -1311,7 +1307,7 @@ int do_init_pet(bool minimal) { pet->item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE); pet->item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE); - + timer->add_func_list(pet->hungry,"pet_hungry"); timer->add_func_list(pet->ai_hard,"pet_ai_hard"); timer->add_func_list(pet->skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris] @@ -1345,16 +1341,14 @@ int do_final_pet(void) } void pet_defaults(void) { pet = &pet_s; - + memset(pet->db,0,sizeof(pet->db)); pet->item_drop_ers = NULL; pet->item_drop_list_ers = NULL; - - /* */ + pet->init = do_init_pet; pet->final = do_final_pet; - - /* */ + pet->hungry_val = pet_hungry_val; pet->set_intimate = pet_set_intimate; pet->create_egg = pet_create_egg; diff --git a/src/map/pet.h b/src/map/pet.h index 0b51bcb16..84df856bf 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -5,11 +5,11 @@ #ifndef MAP_PET_H #define MAP_PET_H -#include "map.h" // struct block_list -#include "status.h" // enum sc_type -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // NAME_LENGTH, struct s_pet +#include "map/map.h" // struct block_list +#include "map/status.h" // enum sc_type +#include "map/unit.h" // struct unit_data +#include "common/hercules.h" +#include "common/mmo.h" // NAME_LENGTH, struct s_pet #define MAX_PET_DB 300 #define MAX_PETLOOT_SIZE 30 @@ -153,10 +153,10 @@ struct pet_interface { int (*read_db) (); }; -struct pet_interface *pet; - #ifdef HERCULES_CORE void pet_defaults(void); #endif // HERCULES_CORE +HPShared struct pet_interface *pet; + #endif /* MAP_PET_H */ diff --git a/src/map/quest.c b/src/map/quest.c index 93ec1b04c..fe4014ae5 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -6,37 +6,40 @@ #include "quest.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "script.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct quest_interface quest_s; +struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database + +struct quest_interface *quest; /** * Searches a quest by ID. @@ -526,6 +529,7 @@ int quest_read_db(void) count++; } + libconfig->destroy(&quest_db_conf); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); return count; } @@ -618,6 +622,7 @@ void do_reload_quest(void) { */ void quest_defaults(void) { quest = &quest_s; + quest->db_data = db_data; memset(&quest->db, 0, sizeof(quest->db)); memset(&quest->dummy, 0, sizeof(quest->dummy)); diff --git a/src/map/quest.h b/src/map/quest.h index 36ac69a53..ccb3e58f9 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -5,9 +5,9 @@ #ifndef MAP_QUEST_H #define MAP_QUEST_H -#include "map.h" // TBL_PC -#include "../common/cbasetypes.h" -#include "../common/conf.h" +#include "map/map.h" // TBL_PC +#include "common/hercules.h" +#include "common/conf.h" #define MAX_QUEST_DB (60355+1) // Highest quest ID + 1 @@ -40,7 +40,7 @@ enum quest_check_type { }; struct quest_interface { - struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database + struct quest_db **db_data; ///< Quest database struct quest_db dummy; ///< Dummy entry for invalid quest lookups /* */ void (*init) (bool minimal); @@ -61,10 +61,10 @@ struct quest_interface { struct quest_db *(*read_db_sub) (config_setting_t *cs, int n, const char *source); }; -struct quest_interface *quest; - #ifdef HERCULES_CORE void quest_defaults(void); #endif // HERCULES_CORE +HPShared struct quest_interface *quest; + #endif /* MAP_QUEST_H */ diff --git a/src/map/script.c b/src/map/script.c index bcc3fd710..30f0bad85 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -4,65 +4,65 @@ #define HERCULES_CORE -#include "../config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL +#include "config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL #include "script.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/md5calc.h" +#include "common/mmo.h" // NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // usage: getcharip +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" +#include "common/HPM.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> - -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "pet.h" -#include "quest.h" -#include "skill.h" -#include "status.h" -#include "status.h" -#include "storage.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/md5calc.h" -#include "../common/mmo.h" // NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // usage: getcharip -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" -#include "../common/HPM.h" - #ifndef WIN32 #include <sys/time.h> #endif struct script_interface script_s; +struct script_interface *script; static inline int GETVALUE(const unsigned char* buf, int i) { return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0)); @@ -87,7 +87,6 @@ static inline void script_string_buf_addb(struct script_string_buf *buf,uint8 b) buf->size += 512; RECREATE(buf->ptr, char, buf->size); } - buf->ptr[buf->pos++] = b; } @@ -267,7 +266,6 @@ void script_reportdata(struct script_data* data) } } - /// Reports on the console information about the current built-in function. void script_reportfunc(struct script_state* st) { @@ -301,7 +299,6 @@ void script_reportfunc(struct script_state* st) } } - /*========================================== * Output error message *------------------------------------------*/ @@ -398,7 +395,6 @@ unsigned int calc_hash_ci(const char* p) { return h % SCRIPT_HASH_SIZE; } - /*========================================== * script->str_data manipulation functions *------------------------------------------*/ @@ -590,7 +586,6 @@ int script_add_str(const char* p) return script->str_num++; } - /// Appends 1 byte to the script buffer. void add_scriptb(int a) { @@ -807,19 +802,19 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) else { //Nested function call script->syntax.nested_call++; nested_call = true; - + if( script->str_data[func].val == script->buildin_lang_macro_offset ) { script->syntax.lang_macro_active = true; macro = true; } } - + if( !macro ) { // buildin function script->addl(func); script->addc(C_ARG); } - + arg = script->buildin[script->str_data[func].val]; if (script->str_data[func].deprecated) DeprecationWarning(p); @@ -903,17 +898,17 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) if( *p != ')' ) disp_error_message("parse_callfunc: expected ')' to close argument list",p); ++p; - + if( script->str_data[func].val == script->buildin_lang_macro_offset ) script->syntax.lang_macro_active = false; } - + if( nested_call ) script->syntax.nested_call--; - + if( !script->syntax.nested_call ) script->syntax.last_func = -1; - + if( !macro ) script->addc(C_FUNC); return p; @@ -978,8 +973,8 @@ const char* parse_variable(const char* p) const char *p2 = NULL; const char *var = p; - if( ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PRE) ) // pre ++ - || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PRE) ) // pre -- + if( ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PRE, true) ) // pre ++ + || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PRE, true) ) // pre -- ) { var = p = script->skip_space(&p[2]); } @@ -1008,19 +1003,19 @@ const char* parse_variable(const char* 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_ADD_POST) ) // post ++ - || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_POST) ) // post -- - || ( p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT) ) // <<= - || ( p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT) ) // >>= + !( ( p[0] == '=' && p[1] != '=' && (type = C_EQ, true) ) // = + || ( p[0] == '+' && p[1] == '=' && (type = C_ADD, true) ) // += + || ( p[0] == '-' && p[1] == '=' && (type = C_SUB, true) ) // -= + || ( p[0] == '^' && p[1] == '=' && (type = C_XOR, true) ) // ^= + || ( p[0] == '|' && p[1] == '=' && (type = C_OR, true) ) // |= + || ( p[0] == '&' && p[1] == '=' && (type = C_AND, true) ) // &= + || ( p[0] == '*' && p[1] == '=' && (type = C_MUL, true) ) // *= + || ( p[0] == '/' && p[1] == '=' && (type = C_DIV, true) ) // /= + || ( p[0] == '%' && p[1] == '=' && (type = C_MOD, true) ) // %= + || ( p[0] == '+' && p[1] == '+' && (type = C_ADD_POST, true) ) // post ++ + || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_POST, true) ) // post -- + || ( p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT, true) ) // <<= + || ( p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT, true) ) // >>= ) ) {// failed to find a matching operator combination so invalid return NULL; @@ -1149,15 +1144,15 @@ bool is_number(const char *p) { int script_string_dup(char *str) { size_t len = strlen(str); int pos = script->string_list_pos; - + while( pos+len+1 >= script->string_list_size ) { script->string_list_size += (1024*1024)/2; RECREATE(script->string_list,char,script->string_list_size); } - + safestrncpy(script->string_list+pos, str, len+1); script->string_list_pos += len+1; - + return pos; } @@ -1208,7 +1203,7 @@ const char* parse_simpleexpr(const char *p) const char *start_point = p; bool duplicate = true; struct script_string_buf *sbuf = &script->parse_simpleexpr_str; - + do { p++; while( *p && *p != '"' ) { @@ -1231,19 +1226,19 @@ const char* parse_simpleexpr(const char *p) p++; //'"' p = script->skip_space(p); } while( *p && *p == '"' ); - + script_string_buf_addb(sbuf, 0); - - if( !(script->syntax.translation_db && (st = strdb_get(script->syntax.translation_db, sbuf->ptr))) ) { + + if (!(script->syntax.translation_db && (st = strdb_get(script->syntax.translation_db, sbuf->ptr)) != NULL)) { script->addc(C_STR); - + if( script->pos+sbuf->pos >= script->size ) { do { script->size += SCRIPT_BLOCK_SIZE; } while( script->pos+sbuf->pos >= script->size ); RECREATE(script->buf,unsigned char,script->size); } - + memcpy(script->buf+script->pos, sbuf->ptr, sbuf->pos); script->pos += sbuf->pos; @@ -1253,19 +1248,19 @@ const char* parse_simpleexpr(const char *p) unsigned int st_cursor = 0; script->addc(C_LSTR); - + expand += (sizeof(char*) + sizeof(uint8)) * st->translations; - + while( script->pos+expand >= script->size ) { script->size += SCRIPT_BLOCK_SIZE; RECREATE(script->buf,unsigned char,script->size); } - + *((int *)(&script->buf[script->pos])) = st->string_id; *((uint8 *)(&script->buf[script->pos + sizeof(int)])) = st->translations; script->pos += sizeof(int) + sizeof(uint8); - + for(j = 0; j < st->translations; j++) { *((uint8 *)(&script->buf[script->pos])) = RBUFB(st->buf, st_cursor); *((char **)(&script->buf[script->pos+sizeof(uint8)])) = &st->buf[st_cursor + sizeof(uint8)]; @@ -1275,19 +1270,19 @@ const char* parse_simpleexpr(const char *p) st_cursor += sizeof(uint8); } } - + /* When exporting we don't know what is a translation and what isn't */ if( script->lang_export_fp && sbuf->pos > 1 ) {//sbuf->pos will always be at least 1 because of the '\0' if( !script->syntax.strings ) { script->syntax.strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0); } - + if( !strdb_exists(script->syntax.strings,sbuf->ptr) ) { strdb_put(script->syntax.strings, sbuf->ptr, NULL); duplicate = false; } } - + if( script->lang_export_fp && !duplicate && ( ( ( script->syntax.last_func == script->buildin_mes_offset || script->syntax.last_func == script->buildin_select_offset ) && !script->syntax.nested_call @@ -1304,44 +1299,41 @@ const char* parse_simpleexpr(const char *p) else break; } - + while( *line_end != '\n' && *line_end != '\0' ) line_end++; - + line_length = (size_t)(line_end - line_start); - if( line_length > 0 ) { script_string_buf_ensure(lbuf,line_length + 1); - + memcpy(lbuf->ptr, line_start, line_length); lbuf->pos = line_length; script_string_buf_addb(lbuf, 0); - + normalize_name(lbuf->ptr, "\r\n\t "); } - + for(cursor = 0; cursor < sbuf->pos; cursor++) { if( sbuf->ptr[cursor] == '"' ) script_string_buf_addb(ubuf, '\\'); script_string_buf_addb(ubuf, sbuf->ptr[cursor]); } script_string_buf_addb(ubuf, 0); - + fprintf(script->lang_export_fp, "#: %s\n" - "# %s\n" - "msgctxt \"%s\"\n" - "msgid \"%s\"\n" - "msgstr \"\"\n", + "# %s\n" + "msgctxt \"%s\"\n" + "msgid \"%s\"\n" + "msgstr \"\"\n", script->parser_current_file ? script->parser_current_file : "Unknown File", lbuf->ptr, script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC", ubuf->ptr ); - lbuf->pos = 0; ubuf->pos = 0; } - sbuf->pos = 0; } else { int l; @@ -2423,10 +2415,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o if( script->parse_cleanup_timer_id == INVALID_TIMER ) { script->parse_cleanup_timer_id = timer->add(timer->gettick() + 10, script->parse_cleanup_timer, 0, 0); } - + if( script->syntax.strings ) /* used only when generating translation file */ db_destroy(script->syntax.strings); - + memset(&script->syntax,0,sizeof(script->syntax)); script->syntax.last_func = -1;/* as valid values are >= 0 */ if( script->parser_current_npc_name ) { @@ -2822,14 +2814,13 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data * struct script_array *sa = idb_get(src->arrays, script_getvarid(uid)); if (sa) { unsigned int i; - + ARR_FIND(0, sa->size, i, sa->members[i] == 0); if( i != sa->size ) { if( !insert ) script->array_remove_member(src,sa,i); return; } - script->array_add_member(sa,0); } else if (insert) { script->array_update(src,reference_uid(script_getvarid(uid), 0),false); @@ -2842,10 +2833,10 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data * unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) { struct script_array *sa = NULL; struct reg_db *src = script->array_src(st, sd, name, ref); - + if( src && src->arrays ) sa = idb_get(src->arrays, script->search_str(name)); - + return sa ? sa->size : 0; } /** @@ -2854,25 +2845,22 @@ unsigned int script_array_size(struct script_state *st, struct map_session_data unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) { struct script_array *sa = NULL; struct reg_db *src = script->array_src(st, sd, name, ref); - - + if( src && src->arrays ) { int key = script->add_word(name); - + script->array_ensure_zero(st,sd,reference_uid(key, 0),ref); - + if( ( sa = idb_get(src->arrays, key) ) ) { unsigned int i, highest_key = 0; - + for(i = 0; i < sa->size; i++) { if( sa->members[i] > highest_key ) highest_key = sa->members[i]; } - return sa->size ? highest_key + 1 : 0; } } - return 0; } int script_free_array_db(DBKey key, DBData *data, va_list ap) { @@ -2896,15 +2884,15 @@ void script_array_delete(struct reg_db *src, struct script_array *sa) { **/ void script_array_remove_member(struct reg_db *src, struct script_array *sa, unsigned int idx) { unsigned int i, cursor; - + /* its the only member left, no need to do anything other than delete the array data */ if( sa->size == 1 ) { script->array_delete(src,sa); return; } - + sa->members[idx] = UINT_MAX; - + for(i = 0, cursor = 0; i < sa->size; i++) { if( sa->members[i] == UINT_MAX ) continue; @@ -2912,7 +2900,7 @@ void script_array_remove_member(struct reg_db *src, struct script_array *sa, uns sa->members[cursor] = sa->members[i]; cursor++; } - + sa->size = cursor; } /** @@ -2921,11 +2909,9 @@ void script_array_remove_member(struct reg_db *src, struct script_array *sa, uns * @param idx the index of the array member being inserted **/ void script_array_add_member(struct script_array *sa, unsigned int idx) { - RECREATE(sa->members, unsigned int, ++sa->size); - - sa->members[sa->size - 1] = idx; + sa->members[sa->size - 1] = idx; } /** * Obtains the source of the array database for this type and scenario @@ -2933,7 +2919,7 @@ void script_array_add_member(struct script_array *sa, unsigned int idx) { **/ struct reg_db *script_array_src(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) { struct reg_db *src = NULL; - + switch( name[0] ) { /* from player */ default: /* char reg */ @@ -2956,13 +2942,12 @@ struct reg_db *script_array_src(struct script_state *st, struct map_session_data } break; } - + if( src ) { if( !src->arrays ) src->arrays = idb_alloc(DB_OPT_BASE); return src; } - return NULL; } @@ -2977,7 +2962,7 @@ void script_array_update(struct reg_db *src, int64 num, bool empty) { struct script_array *sa = NULL; int id = script_getvarid(num); unsigned int index = script_getvaridx(num); - + if (!src->arrays) { src->arrays = idb_alloc(DB_OPT_BASE); } else { @@ -2986,13 +2971,13 @@ void script_array_update(struct reg_db *src, int64 num, bool empty) { if( sa ) { unsigned int i; - + /* search */ for(i = 0; i < sa->size; i++) { if( sa->members[i] == index ) break; } - + /* if existent */ if( i != sa->size ) { /* if empty, we gotta remove it */ @@ -3029,7 +3014,7 @@ void script_array_update(struct reg_db *src, int64 num, bool empty) { *------------------------------------------*/ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, const void* value, struct reg_db *ref) { char prefix = name[0]; - + if( is_string_variable(name) ) {// string variable const char *str = (const char*)value; @@ -3432,7 +3417,7 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos, st->oid = oid; st->sleep.timer = INVALID_TIMER; st->npc_item_flag = battle_config.item_enabled_npc; - + if( st->script->instances != USHRT_MAX ) st->script->instances++; else { @@ -3457,11 +3442,11 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos, void script_free_state(struct script_state* st) { if( idb_exists(script->st_db,st->id) ) { struct map_session_data *sd = st->rid ? map->id2sd(st->rid) : NULL; - + 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(sd && sd->st == st) { //Current script is aborted. if(sd->state.using_fake_npc){ clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); @@ -3864,7 +3849,6 @@ void op_1(struct script_state* st, int op) script_pushint(st, i1); } - /// Checks the type of all arguments passed to a built-in function. /// /// @param st Script state whose stack arguments should be inspected. @@ -3945,7 +3929,6 @@ void script_check_buildin_argtype(struct script_state* st, int func) } } - /// Executes a buildin command. /// Stack: C_NAME(<command>) C_ARG <arg0> <arg1> ... <argN> int run_func(struct script_state *st) @@ -4036,7 +4019,7 @@ int run_func(struct script_state *st) /*========================================== * script execution *------------------------------------------*/ -void run_script(struct script_code *rootscript,int pos,int rid,int oid) { +void run_script(struct script_code *rootscript, int pos, int rid, int oid) { struct script_state *st; if( rootscript == NULL || pos < 0 ) @@ -4207,15 +4190,15 @@ void run_script_main(struct script_state *st) { int string_id = *((int *)(&st->script->script_buf[st->pos])); uint8 translations = *((uint8 *)(&st->script->script_buf[st->pos+sizeof(int)])); struct map_session_data *lsd = NULL; - + st->pos += sizeof(int) + sizeof(uint8); - + if( (!st->rid || !(lsd = map->id2sd(st->rid)) || !lsd->lang_id) && !map->default_lang_id ) script->push_str(stack,C_CONSTSTR,script->string_list+string_id); else { uint8 k, wlang_id = lsd ? lsd->lang_id : map->default_lang_id; int offset = st->pos; - + for(k = 0; k < translations; k++) { uint8 lang_id = *(uint8 *)(&st->script->script_buf[offset]); offset += sizeof(uint8); @@ -4223,12 +4206,9 @@ void run_script_main(struct script_state *st) { break; offset += sizeof(char*); } - script->push_str(stack,C_CONSTSTR, - ( k == translations ) ? script->string_list+string_id : *(char**)(&st->script->script_buf[offset]) ); - + ( k == translations ) ? script->string_list+string_id : *(char**)(&st->script->script_buf[offset]) ); } - st->pos += ( ( sizeof(char*) + sizeof(uint8) ) * translations ); } break; @@ -4342,7 +4322,6 @@ int script_config_read(char *cfgName) { char line[1024],w1[1024],w2[1024]; FILE *fp; - if( !( fp = fopen(cfgName,"r") ) ) { ShowError("File not found: %s\n", cfgName); return 1; @@ -4417,7 +4396,6 @@ void script_add_autobonus(const char *autobonus) } } - /// resets a temporary character array variable to given value void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value) { struct script_array *sa = NULL; @@ -4426,39 +4404,38 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void int key; key = script->add_str(varname); - + if( !(src = script->array_src(NULL,sd,varname,NULL) ) ) return; - + if( value ) script->array_ensure_zero(NULL,sd,reference_uid(key,0),NULL); - + if( !(sa = idb_get(src->arrays, key)) ) /* non-existent array, nothing to empty */ return; - + size = sa->size; list = script->array_cpy_list(sa); - + for(i = 0; i < size; i++) { script->set_reg(NULL,sd,reference_uid(key, list[i]),varname,value,NULL); } } - /// 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, uint32 idx, void* value, int* refcache) { int key; - + if( idx >= SCRIPT_MAX_ARRAYSIZE ) { ShowError("script_setarray_pc: Variable '%s' has invalid index '%u' (char_id=%d).\n", varname, idx, sd->status.char_id); return; } key = ( refcache && refcache[0] ) ? refcache[0] : script->add_str(varname); - + script->set_reg(NULL,sd,reference_uid(key, idx),varname,value,NULL); - + if( refcache ) {// save to avoid repeated script->add_str calls refcache[0] = key; @@ -4469,23 +4446,22 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint32 **/ int script_reg_destroy(DBKey key, DBData *data, va_list ap) { struct script_reg_state *src; - + if( data->type != DB_DATA_PTR )/* got no need for those! */ return 0; - + src = DB->data2ptr(data); - + if( src->type ) { struct script_reg_str *p = (struct script_reg_str *)src; - + if( p->value ) aFree(p->value); - + ers_free(pc->str_reg_ers,p); } else { ers_free(pc->num_reg_ers,(struct script_reg_num*)src); } - return 0; } /** @@ -4496,10 +4472,10 @@ void script_reg_destroy_single(struct map_session_data *sd, int64 reg, struct sc if( data->type ) { struct script_reg_str *p = (struct script_reg_str*)data; - + if( p->value ) aFree(p->value); - + ers_free(pc->str_reg_ers,p); } else { ers_free(pc->num_reg_ers,(struct script_reg_num*)data); @@ -4643,16 +4619,15 @@ void do_final_script(void) { if( script->labels != NULL ) aFree(script->labels); - + ers_destroy(script->array_ers); - + if( script->generic_ui_array ) aFree(script->generic_ui_array); - + script->clear_translations(false); - script->parser_clean_leftovers(); - + if( script->lang_export_file ) aFree(script->lang_export_file); } @@ -4662,11 +4637,10 @@ void do_final_script(void) { **/ uint8 script_add_language(const char *name) { uint8 lang_id = script->max_lang_id; - + RECREATE(script->languages, char *, ++script->max_lang_id); - script->languages[lang_id] = aStrdup(name); - + return lang_id; } /** @@ -4682,9 +4656,9 @@ void script_load_translations(void) { if (map->minimal) // No translations in minimal mode return; - + script->translation_db = strdb_alloc(DB_OPT_DUP_KEY, NAME_LENGTH*2+1); - + if( script->languages ) { for(i = 0; i < script->max_lang_id; i++) aFree(script->languages[i]); @@ -4692,33 +4666,33 @@ void script_load_translations(void) { } script->languages = NULL; script->max_lang_id = 0; - + script->add_language("English");/* 0 is default, which is whatever is in the npc files hardcoded (in our case, English) */ - + if (libconfig->read_file(&translations_conf, config_filename)) { ShowError("load_translations: can't read '%s'\n", config_filename); return; } - + if( !(translations = libconfig->lookup(&translations_conf, "translations")) ) { ShowError("load_translations: invalid format on '%s'\n",config_filename); return; } - + if( script->string_list ) aFree(script->string_list); - + script->string_list = NULL; script->string_list_pos = 0; script->string_list_size = 0; - + size = libconfig->setting_length(translations); - + for(i = 0; i < size; i++) { const char *translation_file = libconfig->setting_get_string_elem(translations, i); - script->load_translation(translation_file, ++lang_id, &total); } + libconfig->destroy(&translations_conf); if( total ) { DBIterator *main_iter; @@ -4726,32 +4700,27 @@ void script_load_translations(void) { DBMap *string_db; struct string_translation *st = NULL; uint32 j = 0; - - + CREATE(script->translation_buf, char *, total); script->translation_buf_size = total; - + main_iter = db_iterator(script->translation_db); - for( string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter) ) { sub_iter = db_iterator(string_db); - for( st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter) ) { script->translation_buf[j++] = st->buf; } - dbi_destroy(sub_iter); } - dbi_destroy(main_iter); } - + for(k = 0; k < script->max_lang_id; k++) { if( !strcmpi(script->languages[k],map->default_lang_str) ) { break; } } - + if( k == script->max_lang_id ) { ShowError("load_translations: map server default_language setting '%s' is not a loaded language\n",map->default_lang_str); map->default_lang_id = 0; @@ -4766,21 +4735,21 @@ void script_load_translations(void) { const char * script_get_translation_file_name(const char *file) { static char file_name[200]; int i, len = (int)strlen(file), last_bar = -1, last_dot = -1; - + for(i = 0; i < len; i++) { if( file[i] == '/' || file[i] == '\\' ) last_bar = i; else if ( file[i] == '.' ) last_dot = i; } - + if( last_bar != -1 || last_dot != -1 ) { if( last_bar != -1 && last_dot < last_bar ) last_dot = -1; safestrncpy(file_name, file+(last_bar >= 0 ? last_bar+1 : 0), ( last_dot >= 0 ? ( last_bar >= 0 ? last_dot - last_bar : last_dot ) : sizeof(file_name) )); return file_name; } - + return file; } @@ -4795,25 +4764,25 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { size_t i; FILE *fp; struct script_string_buf msgid = { 0 }, msgstr = { 0 }; - + if( !(fp = fopen(file,"rb")) ) { ShowError("load_translation: failed to open '%s' for reading\n",file); return; } - + script->add_language(script->get_translation_file_name(file)); if( lang_id >= atcommand->max_message_table ) atcommand->expand_message_table(); - + while(fgets(line, sizeof(line), fp)) { size_t len = strlen(line), cursor = 0; - + if( len <= 1 ) continue; - + if( line[0] == '#' ) continue; - + if( strncasecmp(line,"msgctxt \"", 9) == 0 ) { msgctxt[0] = '\0'; for(i = 9; i < len - 2; i++) { @@ -4847,14 +4816,14 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { } script_string_buf_addb(&msgstr,0); } - + if( msgctxt[0] && msgid.pos > 1 && msgstr.pos > 1 ) { size_t msgstr_len = msgstr.pos; unsigned int inner_len = 1 + (uint32)msgstr_len + 1; //uint8 lang_id + msgstr_len + '\0' - + if( strcasecmp(msgctxt, "messages.conf") == 0 ) { int k; - + for(k = 0; k < MAX_MSG; k++) { if( atcommand->msg_table[0][k] && strcmpi(atcommand->msg_table[0][k],msgid.ptr) == 0 ) { if( atcommand->msg_table[lang_id][k] ) @@ -4863,29 +4832,24 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { break; } } - } else { struct string_translation *st = NULL; if( !( string_db = strdb_get(script->translation_db, msgctxt) ) ) { string_db = strdb_alloc(DB_OPT_DUP_KEY, 0); - strdb_put(script->translation_db, msgctxt, string_db); } - + if( !(st = strdb_get(string_db, msgid.ptr) ) ) { CREATE(st, struct string_translation, 1); - st->string_id = script->string_dup(msgid.ptr); - strdb_put(string_db, msgid.ptr, st); } - RECREATE(st->buf, char, st->len + inner_len); - + WBUFB(st->buf, st->len) = lang_id; safestrncpy((char*)WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1); - + st->translations++; st->len += inner_len; } @@ -4894,11 +4858,11 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { translations++; } } - + *total += translations; - + fclose(fp); - + script_string_buf_destroy(&msgid); script_string_buf_destroy(&msgstr); @@ -4913,21 +4877,21 @@ void script_clear_translations(bool reload) { if( script->string_list ) aFree(script->string_list); - + script->string_list = NULL; script->string_list_pos = 0; script->string_list_size = 0; - + if( script->translation_buf ) { for(i = 0; i < script->translation_buf_size; i++) { aFree(script->translation_buf[i]); } aFree(script->translation_buf); } - + script->translation_buf = NULL; script->translation_buf_size = 0; - + if( script->languages ) { for(i = 0; i < script->max_lang_id; i++) aFree(script->languages[i]); @@ -4935,11 +4899,11 @@ void script_clear_translations(bool reload) { } script->languages = NULL; script->max_lang_id = 0; - + if( script->translation_db ) { script->translation_db->clear(script->translation_db,script->translation_db_destroyer); } - + if( reload ) script->load_translations(); } @@ -4949,18 +4913,17 @@ void script_clear_translations(bool reload) { **/ int script_translation_db_destroyer(DBKey key, DBData *data, va_list ap) { DBMap *string_db = DB->data2ptr(data); - + if( db_size(string_db) ) { - DBIterator *iter = db_iterator(string_db); struct string_translation *st = NULL; - + DBIterator *iter = db_iterator(string_db); + for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) { aFree(st); } - dbi_destroy(iter); } - + db_destroy(string_db); return 0; } @@ -4969,10 +4932,9 @@ int script_translation_db_destroyer(DBKey key, DBData *data, va_list ap) { * **/ void script_parser_clean_leftovers(void) { - if( script->buf ) aFree(script->buf); - + script->buf = NULL; script->size = 0; @@ -4980,7 +4942,7 @@ void script_parser_clean_leftovers(void) { script->translation_db->destroy(script->translation_db,script->translation_db_destroyer); script->translation_db = NULL; } - + if( script->syntax.strings ) { /* used only when generating translation file */ db_destroy(script->syntax.strings); script->syntax.strings = NULL; @@ -4995,21 +4957,19 @@ void script_parser_clean_leftovers(void) { * Performs cleanup after all parsing is processed **/ int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) { - script->parser_clean_leftovers(); script->parse_cleanup_timer_id = INVALID_TIMER; - + return 0; } - /*========================================== * Initialization *------------------------------------------*/ void do_init_script(bool minimal) { script->parse_cleanup_timer_id = INVALID_TIMER; - + script->st_db = idb_alloc(DB_OPT_BASE); script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0); script->autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); @@ -5029,7 +4989,6 @@ void do_init_script(bool minimal) { return; mapreg->init(); - script->load_translations(); } @@ -5063,9 +5022,9 @@ int script_reload(void) { atcommand->binding_count = 0; db_clear(script->st_db); - + script->clear_translations(true); - + if( script->parse_cleanup_timer_id != INVALID_TIMER ) { timer->delete(script->parse_cleanup_timer_id,script->parse_cleanup_timer); script->parse_cleanup_timer_id = INVALID_TIMER; @@ -5764,6 +5723,7 @@ BUILDIN(warp) { int ret; int x,y; + int warp_clean = 1; const char* str; TBL_PC* sd; @@ -5775,6 +5735,11 @@ BUILDIN(warp) x = script_getnum(st,3); y = script_getnum(st,4); + if (script_hasdata(st, 5)) { + warp_clean = script_getnum(st, 5); + } + + sd->state.warp_clean = warp_clean; if(strcmp(str,"Random")==0) ret = pc->randomwarp(sd,CLR_TELEPORT); else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0) @@ -5817,7 +5782,7 @@ int buildin_areawarp_sub(struct block_list *bl,va_list ap) tx = rnd()%(x3-x2+1)+x2; ty = rnd()%(y3-y2+1)+y2; j++; - } while( map->getcell(index,tx,ty,CELL_CHKNOPASS) && j < max ); + } while (map->getcell(index, bl, tx, ty, CELL_CHKNOPASS) && j < max); pc->setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT); } @@ -6284,7 +6249,7 @@ BUILDIN(__setr) { if (!not_array_variable(*namevalue)) { // array variable being copied into another array variable - if (sd == NULL && not_server_variable(*namevalue) && !(sd = script->rid2sd(st))) { + if (sd == NULL && not_server_variable(*namevalue) && (sd = script->rid2sd(st)) == NULL) { // player must be attached in order to copy a player variable ShowError("script:set: no player attached for player variable '%s'\n", namevalue); return true; @@ -6578,15 +6543,15 @@ BUILDIN(deletearray) st->state = END; return false;// not a variable } - + script->array_ensure_zero(st,NULL,data->u.num,reference_getref(data)); - + if ( !(sa = idb_get(src->arrays, id)) ) { /* non-existent array, nothing to empty */ return true;// not a variable } end = script->array_highest_key(st,sd,name,reference_getref(data)); - + if( start >= end ) return true;// nothing to free @@ -6594,7 +6559,7 @@ BUILDIN(deletearray) value = (void *)""; else value = (void *)0; - + if( script_hasdata(st,3) ) { unsigned int count = script_getnum(st, 3); if( count > end - start ) @@ -6620,14 +6585,14 @@ BUILDIN(deletearray) list = script->array_cpy_list(sa); size = sa->size; qsort(list, size, sizeof(unsigned int), script_array_index_cmp); - + ARR_FIND(0, size, i, list[i] >= start); - + for( ; i < size && list[i] < start + count; i++ ) { // Clear any entries between start and start+count, if they exist script->set_reg(st, sd, reference_uid(id, list[i]), name, value, reference_getref(data)); } - + for( ; i < size && list[i] < end; i++ ) { // Move back count positions any entries between start+count to fill the gaps void* v = script->get_val2(st, reference_uid(id, list[i]), reference_getref(data)); @@ -6641,7 +6606,7 @@ BUILDIN(deletearray) unsigned int *list = NULL, size = 0; list = script->array_cpy_list(sa); size = sa->size; - + for(i = 0; i < size; i++) { if( list[i] >= start ) // Less expensive than sorting it, most likely script->set_reg(st, sd, reference_uid(id, list[i]), name, value, reference_getref(data)); @@ -7120,7 +7085,7 @@ BUILDIN(getitem) { 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); + map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -7228,7 +7193,7 @@ BUILDIN(getitem2) 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); + map->addflooritem(&sd->bl, &item_tmp, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -7417,17 +7382,15 @@ BUILDIN(makeitem) return false; } - memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify=1; - - map->addflooritem(&item_tmp,amount,m,x,y,0,0,0,0); + + map->addflooritem(NULL, &item_tmp, amount, m, x, y, 0, 0, 0, 0); return true; } - /// Counts / deletes the current item given by idx. /// Used by buildin_delitem_search /// Relies on all input data being already fully valid. @@ -7444,13 +7407,12 @@ void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, b {// delete associated pet intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2])); } - pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); + pc->delitem(sd, idx, delamount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT); } amount[0]-= delamount; } - /// Searches for item(s) and checks, if there is enough of them. /// Used by delitem and delitem2 /// Relies on all input data being already fully valid. @@ -7558,7 +7520,6 @@ bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool e } } - /// Deletes items from the target/attached player. /// Prioritizes ordinary items. /// @@ -8478,7 +8439,7 @@ BUILDIN(successrefitem) if (script_hasdata(st, 3)) up = script_getnum(st, 3); - + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); if (i >= 0) { @@ -8492,10 +8453,10 @@ BUILDIN(successrefitem) sd->status.inventory[i].refine += up; sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); - pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // 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); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); @@ -8541,10 +8502,10 @@ BUILDIN(failedrefitem) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0) { sd->status.inventory[i].refine = 0; - pc->unequipitem(sd,i,3); //recalculate bonus + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //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, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); clif->misceffect(&sd->bl,2); // display failure effect } @@ -8575,12 +8536,12 @@ BUILDIN(downrefitem) //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]); - pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // status calc will happen in pc->equipitem() below sd->status.inventory[i].refine -= down; sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); clif->refine(sd->fd,2,i,sd->status.inventory[i].refine); - clif->delitem(sd,i,1,3); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); @@ -8609,11 +8570,11 @@ BUILDIN(delequip) if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0) { - pc->unequipitem(sd,i,3); //recalculate bonus - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //recalculate bonus + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); return true; } - + ShowError("script:delequip: no item found in position '%d' for player '%s' (AID:%d/CID:%d).\n", num, sd->status.name,sd->status.account_id, sd->status.char_id); st->state = END; clif->scriptclose(sd, st->oid); @@ -8866,7 +8827,7 @@ BUILDIN(autobonus3) { BUILDIN(skill) { int id; int level; - int flag = 1; + int flag = SKILL_GRANT_TEMPORARY; TBL_PC* sd; sd = script->rid2sd(st); @@ -8894,7 +8855,7 @@ BUILDIN(skill) { BUILDIN(addtoskill) { int id; int level; - int flag = 2; + int flag = SKILL_GRANT_TEMPSTACK; TBL_PC* sd; sd = script->rid2sd(st); @@ -9033,7 +8994,7 @@ BUILDIN(getgroupid) /// end BUILDIN(end) { st->state = END; - + /* are we stopping inside a function? */ if( st->stack->defsp >= 1 && st->stack->stack_data[st->stack->defsp-1].type == C_RETINFO ) { int i; @@ -9739,8 +9700,7 @@ BUILDIN(monster) if (script_hasdata(st, 10)) { ai = script_getnum(st, 10); - if (ai > 4) - { + if (ai > AI_FLORA) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); return false; } @@ -9844,7 +9804,7 @@ BUILDIN(areamonster) { if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); - if (ai > 4) { + if (ai > AI_FLORA) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); return false; } @@ -10449,7 +10409,7 @@ BUILDIN(itemeffect) { } } - script->run( item_data->script, 0, sd->bl.id, nd->bl.id ); + script->run_use_script(sd, item_data, nd->bl.id); return true; } @@ -11014,7 +10974,7 @@ BUILDIN(homunculus_mutate) if (m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 && i != INDEX_NOT_FOUND && - !pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_SCRIPT) ) { + !pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT) ) { sd->hd->homunculus.vaporize = HOM_ST_REST; // Remove morph state. homun->call(sd); // Respawn homunculus. homun->mutate(sd->hd, homun_id); @@ -11090,7 +11050,6 @@ BUILDIN(homunculus_checkcall) { return true; } - // [Zephyrus] BUILDIN(homunculus_shuffle) { TBL_PC *sd; @@ -11130,7 +11089,7 @@ BUILDIN(roclass) sex = script_getnum(st,3); else { TBL_PC *sd; - if (st->rid && (sd=script->rid2sd(st))) + if (st->rid && (sd=script->rid2sd(st)) != NULL) sex = sd->status.sex; else sex = 1; //Just use male when not found. @@ -11195,26 +11154,24 @@ BUILDIN(resetstatus) /*========================================== * script command resetskill *------------------------------------------*/ -BUILDIN(resetskill) -{ +BUILDIN(resetskill) { TBL_PC *sd; sd=script->rid2sd(st); if( sd == NULL ) return false; - pc->resetskill(sd,1); + pc->resetskill(sd, PCRESETSKILL_RESYNC); return true; } /*========================================== * Counts total amount of skill points. *------------------------------------------*/ -BUILDIN(skillpointcount) -{ +BUILDIN(skillpointcount) { TBL_PC *sd; sd=script->rid2sd(st); if( sd == NULL ) return false; - script_pushint(st,sd->status.skill_point + pc->resetskill(sd,2)); + script_pushint(st,sd->status.skill_point + pc->resetskill(sd, PCRESETSKILL_RECOUNT)); return true; } @@ -11256,10 +11213,10 @@ static TBL_PC *prepareChangeSex(struct script_state* st) if (sd == NULL) return NULL; - pc->resetskill(sd, 4); + pc->resetskill(sd, PCRESETSKILL_CHSEX); // 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); + if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); return sd; } @@ -11417,6 +11374,10 @@ BUILDIN(disablewaitingroomevent) { /// <type>=16 : the name of the waiting room event /// <type>=32 : if the waiting room is full /// <type>=33 : if there are enough users to trigger the event +/// -- Custom Added +/// <type>=34 : minimum player of waiting room +/// <type>=35 : maximum player of waiting room +/// <type>=36 : minimum zeny required /// /// getwaitingroomstate(<type>,"<npc_name>") -> <info> /// getwaitingroomstate(<type>) -> <info> @@ -11424,6 +11385,7 @@ BUILDIN(getwaitingroomstate) { struct npc_data *nd; struct chat_data *cd; int type; + int i; type = script_getnum(st,2); if( script_hasdata(st,3) ) @@ -11437,7 +11399,13 @@ BUILDIN(getwaitingroomstate) { } switch(type) { - case 0: script_pushint(st, cd->users); break; + case 0: + for (i = 0; i < cd->users; i++) { + struct map_session_data *sd = cd->usersd[i]; + mapreg->setreg(reference_uid(script->add_str("$@chatmembers"), i), sd->bl.id); + } + 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; @@ -11446,6 +11414,10 @@ BUILDIN(getwaitingroomstate) { 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; + + case 34: script_pushint(st, cd->minLvl); break; + case 35: script_pushint(st, cd->maxLvl); break; + case 36: script_pushint(st, cd->zeny); break; default: script_pushint(st, -1); break; } return true; @@ -11562,7 +11534,6 @@ BUILDIN(isloggedin) { return true; } - /*========================================== * *------------------------------------------*/ @@ -11882,7 +11853,6 @@ BUILDIN(pvpon) { bl.m = m; clif->maptypeproperty2(&bl,ALL_SAMEMAP); - if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] return true; @@ -12291,7 +12261,7 @@ BUILDIN(successremovecards) 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -12312,11 +12282,11 @@ BUILDIN(successremovecards) 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); + pc->delitem(sd, i, 1, 0, DELITEM_MATERIALCHANGE, 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } clif->misceffect(&sd->bl,3); @@ -12365,7 +12335,7 @@ BUILDIN(failedremovecards) 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -12374,7 +12344,7 @@ BUILDIN(failedremovecards) if (cardflag == 1) { if (typefail == 0 || typefail == 2) { // destroy the item - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); } else if (typefail == 1) { // destroy the card int flag, j; @@ -12392,11 +12362,11 @@ BUILDIN(failedremovecards) 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, DELITEM_FAILREFINE, 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } clif->misceffect(&sd->bl,2); @@ -13086,7 +13056,7 @@ BUILDIN(clearitem) if(sd==NULL) return true; 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); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT); } } return true; @@ -13515,7 +13485,7 @@ BUILDIN(nude) if( sd->equip_index[ i ] >= 0 ) { if( !calcflag ) calcflag = 1; - pc->unequipitem( sd , sd->equip_index[ i ] , 2); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } } @@ -13803,12 +13773,20 @@ BUILDIN(message) { /*========================================== * npctalk (sends message to surrounding area) + * usage: npctalk "<message>"{,"<npc name>"}; *------------------------------------------*/ BUILDIN(npctalk) { - struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid); + struct npc_data* nd; const char *str = script_getstr(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) { char name[NAME_LENGTH], message[256]; safestrncpy(name, nd->name, sizeof(name)); @@ -13862,7 +13840,7 @@ BUILDIN(npcstop) { if( nd ) { unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit - unit->stop_walking(&nd->bl,1|4); + unit->stop_walking(&nd->bl, STOPWALKING_FLAG_FIXPOS|STOPWALKING_FLAG_NEXTCELL); } return true; @@ -13974,7 +13952,6 @@ BUILDIN(getnpcclass) return true; } - /*========================================== * getlook char info. getlook(arg) *------------------------------------------*/ @@ -14079,13 +14056,13 @@ BUILDIN(getmapxy) script_pushint(st,-1); return false; } - + if( !is_string_variable(reference_getname(script_getdata(st, 2))) ) { ShowWarning("script: buildin_getmapxy: %s is not a string variable\n",reference_getname(script_getdata(st, 2))); script_pushint(st,-1); return false; } - + if( is_string_variable(reference_getname(script_getdata(st, 3))) ) { ShowWarning("script: buildin_getmapxy: %s is a string variable, should be int\n",reference_getname(script_getdata(st, 3))); script_pushint(st,-1); @@ -14177,7 +14154,7 @@ BUILDIN(getmapxy) num=st->stack->stack_data[st->start+2].u.num; name=script->get_str(script_getvarid(num)); prefix=*name; - + if(not_server_variable(prefix)) sd=script->rid2sd(st); else @@ -14487,7 +14464,7 @@ BUILDIN(unequip) if (sd != NULL && num >= 1 && num <= ARRAYLENGTH(script->equip)) { int i = pc->checkequip(sd,script->equip[num-1]); if (i >= 0) - pc->unequipitem(sd,i,1|2); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } return true; } @@ -14554,7 +14531,7 @@ BUILDIN(equip2) script_pushint(st,0); return true; } - + nameid = script_getnum(st,2); if( (item_data = itemdb->exists(nameid)) == NULL ) { @@ -14828,8 +14805,6 @@ BUILDIN(explode) size_t len = strlen(str); int i = 0, j = 0; int start; - - char *temp; const char* name; @@ -15400,7 +15375,6 @@ BUILDIN(countstr) return true; } - /// Changes the display name and/or display class of the npc. /// Returns 0 is successful, 1 if the npc does not exist. /// @@ -15493,6 +15467,14 @@ BUILDIN(compare) return true; } +BUILDIN(strcmp) +{ + const char *str1 = script_getstr(st,2); + const char *str2 = script_getstr(st,3); + script_pushint(st,strcmp(str1, str2)); + return true; +} + // List of mathematics commands ---> BUILDIN(log10) @@ -16142,7 +16124,6 @@ BUILDIN(checkvending) // check vending [Nab4] return true; } - // check chatting [Marka] BUILDIN(checkchatting) { TBL_PC *sd = NULL; @@ -16284,7 +16265,6 @@ BUILDIN(pcfollow) { int id, targetid; TBL_PC *sd = NULL; - id = script_getnum(st,2); targetid = script_getnum(st,3); @@ -16304,7 +16284,6 @@ BUILDIN(pcstopfollow) int id; TBL_PC *sd = NULL; - id = script_getnum(st,2); if(id) @@ -16469,7 +16448,7 @@ BUILDIN(unitstop) { if( bl != NULL ) { unit->bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit unit->stop_attack(bl); - unit->stop_walking(bl,4); + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); if( bl->type == BL_MOB ) ((TBL_MOB*)bl)->target_id = 0; } @@ -16722,7 +16701,7 @@ BUILDIN(getvariableofnpc) if( !nd->u.scr.script->local.vars ) nd->u.scr.script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA); - + script->push_val(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->local); return true; } @@ -16759,7 +16738,7 @@ BUILDIN(warpportal) { if( bl->type == BL_NPC ) unit->bl2ud2(bl); // ensure nd->ud is safe to edit - + group = skill->unitsetting(bl, AL_WARP, 4, spx, spy, 0); if( group == NULL ) return true;// failed @@ -16812,7 +16791,7 @@ BUILDIN(checkcell) { return true; } - script_pushint(st, map->getcell(m, x, y, type)); + script_pushint(st, map->getcell(m, NULL, x, y, type)); return true; } @@ -17173,18 +17152,27 @@ BUILDIN(changequest) { BUILDIN(questactive) { struct map_session_data *sd = script->rid2sd(st); - int quest_progress = 0; + int qid, i; - if (sd == NULL) + if (sd == NULL) { + ShowError("questactive: no player attached!"); return false; + } - if (quest->check(sd, script_getnum(st, 2), HAVEQUEST) == Q_ACTIVE) + qid = script_getnum(st, 2); + + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid ); + + if( i >= sd->avail_quests ) { + script_pushint(st, 0); + return true; + } + + if(sd->quest_log[i].state == Q_ACTIVE) script_pushint(st, 1); else script_pushint(st, 0); - script_pushint(st, quest_progress); - return true; } @@ -17288,7 +17276,9 @@ BUILDIN(waitingroom2bg) { return true; } + Assert_retr(false, cd->users < MAX_CHAT_USERS); n = cd->users; // This is always < MAX_CHAT_USERS + for (i = 0; i < n && i < MAX_BG_MEMBERS; i++) { struct map_session_data *sd = cd->usersd[i]; if (sd != NULL && bg->team_join(bg_id, sd)) @@ -17393,7 +17383,7 @@ BUILDIN(bg_monster_set_team) { md->bg_id = bg_id; mob_stop_attack(md); - mob_stop_walking(md, 0); + mob_stop_walking(md, STOPWALKING_FLAG_NONE); md->target_id = md->attacked_id = 0; clif->charnameack(0, &md->bl); @@ -17704,7 +17694,7 @@ BUILDIN(has_instance) { int16 m; int instance_id = -1; bool type = strcmp(script->getfuncname(st),"has_instance2") == 0 ? true : false; - + str = script_getstr(st, 2); if( (m = map->mapname2mapid(str)) < 0 ) { @@ -17733,7 +17723,7 @@ BUILDIN(has_instance) { if( i != sd->instances ) instance_id = sd->instance[i]; } - if( instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) { + if (instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances) { for( i = 0; i < p->instances; i++ ) { if( p->instance[i] >= 0 ) { ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m); @@ -17918,7 +17908,7 @@ BUILDIN(instance_check_guild) c++; } } - + if( c < amount ) script_pushint(st,0); else @@ -18017,7 +18007,6 @@ BUILDIN(areamobuseskill) { return true; } - BUILDIN(progressbar) { struct map_session_data * sd = script->rid2sd(st); @@ -18079,7 +18068,6 @@ BUILDIN(pushpc) return true; } - /// Invokes buying store preparation window /// buyingstore <slots>; BUILDIN(buyingstore) @@ -18094,7 +18082,6 @@ BUILDIN(buyingstore) return true; } - /// Invokes search store info window /// searchstores <uses>,<effect>; BUILDIN(searchstores) @@ -18195,7 +18182,7 @@ BUILDIN(setcashmount) if ((sd = script->rid2sd(st)) == NULL) return true; if (pc_hasmount(sd)) { - clif->msgtable(sd->fd, 0X78b); + clif->msgtable(sd, MSG_REINS_CANT_USE_MOUNTED); script_pushint(st,0);//can't mount with one of these } else { if (sd->sc.data[SC_ALL_RIDING]) @@ -18244,22 +18231,22 @@ BUILDIN(getcharip) { } /* check for sd and IP */ - if (!sd || !session[sd->fd]->client_addr) + if (!sd || !sockt->session[sd->fd]->client_addr) { script_pushconststr(st, ""); return true; } /* return the client ip_addr converted for output */ - if (sd && sd->fd && session[sd->fd]) + if (sd && sd->fd && sockt->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); + ip = sockt->session[sd->fd]->client_addr; + ip_addr = sockt->ip2str(ip, NULL); script_pushstrcopy(st, ip_addr); } @@ -18371,7 +18358,6 @@ BUILDIN(bindatcmd) { if( script_hasdata(st,5) ) group_lv_char = script_getnum(st,5); if( script_hasdata(st,6) ) log = script_getnum(st,6) ? true : false; - if( atcommand->binding_count == 0 ) { CREATE(atcommand->binding,struct atcmd_binding_data*,1); @@ -18586,7 +18572,7 @@ BUILDIN(getrandgroupitem) { 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); + map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -18646,11 +18632,11 @@ BUILDIN(npcskill) { skill_level = script_getnum(st, 3); stat_point = script_getnum(st, 4); npc_level = script_getnum(st, 5); - + if( !(sd = script->rid2sd(st)) ) return false; - - nd = (struct npc_data *)map->id2bl(sd->npc_id); + + nd = (struct npc_data *)map->id2bl(sd->npc_id); if (stat_point > battle_config.max_third_parameter) { ShowError("npcskill: stat point exceeded maximum of %d.\n",battle_config.max_third_parameter ); @@ -18756,7 +18742,7 @@ BUILDIN(montransform) { clif->ShowScript(&sd->bl, msg); status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick); - + if (script_hasdata(st, 4)) sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick); } @@ -18840,7 +18826,7 @@ bool script_hqueue_add(int idx, int var) script->hq[idx].item[i] = var; script->hq[idx].items++; - if (var >= START_ACCOUNT_NUM && (sd = map->id2sd(var))) { + if (var >= START_ACCOUNT_NUM && (sd = map->id2sd(var)) != NULL) { for (i = 0; i < sd->queues_count; i++) { if (sd->queues[i] == -1) { break; @@ -18886,7 +18872,7 @@ bool script_hqueue_remove(int idx, int var) { script->hq[idx].item[i] = -1; script->hq[idx].items--; - if( var >= START_ACCOUNT_NUM && (sd = map->id2sd(var)) ) { + if (var >= START_ACCOUNT_NUM && (sd = map->id2sd(var)) != NULL) { for(i = 0; i < sd->queues_count; i++) { if( sd->queues[i] == idx ) { break; @@ -18964,7 +18950,7 @@ bool script_hqueue_del(int idx) int i; for (i = 0; i < script->hq[idx].size; i++) { struct map_session_data *sd; - if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) ) { + if (script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) != NULL) { int j; for(j = 0; j < sd->queues_count; j++) { if( sd->queues[j] == script->hq[idx].item[i] ) { @@ -19003,7 +18989,7 @@ void script_hqueue_clear(int idx) { for(i = 0; i < script->hq[idx].size; i++) { if( script->hq[idx].item[i] > 0 ) { - if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) ) { + if (script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) != NULL) { for(j = 0; j < sd->queues_count; j++) { if( sd->queues[j] == idx ) { break; @@ -19069,7 +19055,7 @@ BUILDIN(qiget) { if( idx < 0 || idx >= script->hqis ) { ShowWarning("buildin_qiget: unknown queue iterator id %d\n",idx); script_pushint(st, 0); - } else if ( script->hqi[idx].pos -1 == script->hqi[idx].items ) { + } else if (script->hqi[idx].pos >= script->hqi[idx].items) { script_pushint(st, 0); } else { struct hQueueIterator *it = &script->hqi[idx]; @@ -19086,7 +19072,7 @@ BUILDIN(qicheck) { if( idx < 0 || idx >= script->hqis ) { ShowWarning("buildin_qicheck: unknown queue iterator id %d\n",idx); script_pushint(st, 0); - } else if ( script->hqi[idx].pos -1 == script->hqi[idx].items ) { + } else if (script->hqi[idx].pos >= script->hqi[idx].items) { script_pushint(st, 0); } else { script_pushint(st, 1); @@ -19270,7 +19256,7 @@ BUILDIN(checkbound) return true; } else script_pushint(st,0); - + return true; } @@ -19351,8 +19337,6 @@ BUILDIN(instance_set_respawn) { script_pushint(st, 0); } } - - return true; } /** @@ -19654,6 +19638,47 @@ BUILDIN(channelmes) return true; } +/** By Cydh +Display script message +showscript "<message>"{,<GID>}; +*/ +BUILDIN(showscript) { + struct block_list *bl = NULL; + const char *msg = script_getstr(st, 2); + int id = 0; + + if (script_hasdata(st, 3)) { + id = script_getnum(st, 3); + bl = map->id2bl(id); + } + else { + bl = st->rid ? map->id2bl(st->rid) : map->id2bl(st->oid); + } + + if (!bl) { + ShowError("buildin_showscript: Script not attached. (id=%d, rid=%d, oid=%d)\n", id, st->rid, st->oid); + script_pushint(st, 0); + return false; + } + + clif->ShowScript(bl, msg); + + script_pushint(st, 1); + + return true; +} + +BUILDIN(mergeitem) +{ + struct map_session_data *sd = script->rid2sd(st); + + if (sd == NULL) + return true; + + clif->openmergeitem(sd->fd, sd); + + return true; +} /** place holder for the translation macro **/ BUILDIN(_) { return true; @@ -19771,6 +19796,54 @@ bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st) return script->add_builtin(&buildin, true); } +void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1))); + +/** + * Run use script for item. + * + * @param sd player session data. Must be correct and checked before. + * @param n item index in inventory. Must be correct and checked before. + * @param oid npc id. Can be also 0 or fake npc id. + */ +void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid) +{ + script->current_item_id = data->nameid; + script->run(data->script, 0, sd->bl.id, oid); + script->current_item_id = 0; +} + +void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2))); + +/** + * Run item equip script for item. + * + * @param sd player session data. Must be correct and checked before. + * @param data equipped item data. Must be correct and checked before. + * @param oid npc id. Can be also 0 or fake npc id. + */ +void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid) +{ + script->current_item_id = data->nameid; + script->run(data->equip_script, 0, sd->bl.id, oid); + script->current_item_id = 0; +} + +void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2))); + +/** + * Run item unequip script for item. + * + * @param sd player session data. Must be correct and checked before. + * @param data unequipped item data. Must be correct and checked before. + * @param oid npc id. Can be also 0 or fake npc id. + */ +void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid) +{ + script->current_item_id = data->nameid; + script->run(data->unequip_script, 0, sd->bl.id, oid); + script->current_item_id = 0; +} + #define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args, false } #define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args, false } #define BUILDIN_DEF_DEPRECATED(x,args) { buildin_ ## x , #x , args, true } @@ -19798,7 +19871,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(jobchange,"i?"), BUILDIN_DEF(jobname,"i"), BUILDIN_DEF(input,"r??"), - BUILDIN_DEF(warp,"sii"), + BUILDIN_DEF(warp,"sii?"), BUILDIN_DEF(areawarp,"siiiisii??"), BUILDIN_DEF(warpchar,"siii"), // [LuzZza] BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] @@ -20016,7 +20089,7 @@ void script_parse_builtin(void) { BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] BUILDIN_DEF(message,"ss"), // [MouseJstr] - BUILDIN_DEF(npctalk,"s"), // [Valaris] + BUILDIN_DEF(npctalk,"s?"), // [Valaris] BUILDIN_DEF(mobcount,"ss"), BUILDIN_DEF(getlook,"i"), BUILDIN_DEF(getsavepoint,"i"), @@ -20077,6 +20150,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(countstr,"ss?"), BUILDIN_DEF(setnpcdisplay,"sv??"), BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. + BUILDIN_DEF(strcmp,"ss"), 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 @@ -20213,7 +20287,6 @@ void script_parse_builtin(void) { BUILDIN_DEF(makerune,"i"), BUILDIN_DEF(hascashmount,""),//[Ind] BUILDIN_DEF(setcashmount,""),//[Ind] - BUILDIN_DEF_DEPRECATED(checkre,"i"), // Deprecated 2015-05-08 [Haru] /** * rAthena and beyond! **/ @@ -20290,6 +20363,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(shopcount, "i"), BUILDIN_DEF(channelmes, "ss"), + BUILDIN_DEF(showscript, "s?"), + BUILDIN_DEF(mergeitem,""), BUILDIN_DEF(_,"s"), }; int i, len = ARRAYLENGTH(BUILDIN); @@ -20319,7 +20394,6 @@ void script_label_add(int key, int pos) { * Sets source-end constants for scripts to play with **/ void script_hardcoded_constants(void) { - /* server defines */ script->set_constant("PACKETVER",PACKETVER,false); script->set_constant("MAX_LEVEL",MAX_LEVEL,false); @@ -20439,7 +20513,7 @@ void script_hardcoded_constants(void) { **/ unsigned short script_mapindexname2id (struct script_state *st, const char* name) { unsigned short index; - + if( !(index=mapindex->name2id(name)) ) { script->reportsrc(st); return 0; @@ -20447,7 +20521,6 @@ unsigned short script_mapindexname2id (struct script_state *st, const char* name return index; } - void script_defaults(void) { // aegis->athena slot position conversion table unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L}; @@ -20460,7 +20533,7 @@ void script_defaults(void) { script->st_ers = NULL; script->stack_ers = NULL; script->array_ers = NULL; - + script->hq = NULL; script->hqi = NULL; script->hqs = script->hqis = 0; @@ -20548,6 +20621,8 @@ void script_defaults(void) { script->get_constant = script_get_constant; script->label_add = script_label_add; script->run = run_script; + script->run_npc = run_script; + script->run_pet = run_script; script->run_main = run_script_main; script->run_timer = run_script_timer; script->set_var = set_var; @@ -20682,7 +20757,7 @@ void script_defaults(void) { script->global_casecheck.str_pos = 0; memset(script->global_casecheck.str_hash, 0, sizeof(script->global_casecheck.str_hash)); // end ENABLE_CASE_CHECK - + /** * Array Handling **/ @@ -20713,5 +20788,8 @@ void script_defaults(void) { script->add_language = script_add_language; script->get_translation_file_name = script_get_translation_file_name; script->parser_clean_leftovers = script_parser_clean_leftovers; - + + script->run_use_script = script_run_use_script; + script->run_item_equip_script = script_run_item_equip_script; + script->run_item_unequip_script = script_run_item_unequip_script; } diff --git a/src/map/script.h b/src/map/script.h index 25c4283ca..ad8ae82cb 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -5,20 +5,21 @@ #ifndef MAP_SCRIPT_H #define MAP_SCRIPT_H +#include "map/map.h" //EVENT_NAME_LENGTH +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" // struct item +#include "common/sql.h" // Sql +#include "common/strlib.h" //StringBuf + #include <errno.h> #include <setjmp.h> -#include "map.h" //EVENT_NAME_LENGTH -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // struct item -#include "../common/sql.h" // Sql -#include "../common/strlib.h" //StringBuf - /** * Declarations **/ struct eri; +struct item_data; /** * Defines @@ -636,7 +637,9 @@ struct script_interface { void (*set_constant2) (const char *name, int value, bool isparameter); bool (*get_constant) (const char* name, int* value); void (*label_add)(int key, int pos); - void (*run) (struct script_code *rootscript,int pos,int rid,int oid); + void (*run) (struct script_code *rootscript, int pos, int rid, int oid); + void (*run_npc) (struct script_code *rootscript, int pos, int rid, int oid); + void (*run_pet) (struct script_code *rootscript, int pos, int rid, int oid); void (*run_main) (struct script_state *st); int (*run_timer) (int tid, int64 tick, int id, intptr_t data); int (*set_var) (struct map_session_data *sd, char *name, void *val); @@ -765,12 +768,15 @@ struct script_interface { uint8 (*add_language) (const char *name); const char *(*get_translation_file_name) (const char *file); void (*parser_clean_leftovers) (void); + void (*run_use_script) (struct map_session_data *sd, struct item_data *data, int oid); + void (*run_item_equip_script) (struct map_session_data *sd, struct item_data *data, int oid); + void (*run_item_unequip_script) (struct map_session_data *sd, struct item_data *data, int oid); }; -struct script_interface *script; - #ifdef HERCULES_CORE void script_defaults(void); #endif // HERCULES_CORE +HPShared struct script_interface *script; + #endif /* MAP_SCRIPT_H */ diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 782c14987..46b102ad5 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -4,17 +4,18 @@ #define HERCULES_CORE -#include "searchstore.h" // struct s_search_store_info +#include "searchstore.h" // struct s_search_store_info -#include "battle.h" // battle_config.* -#include "clif.h" // clif->open_search_store_info, clif->search_store_info_* -#include "pc.h" // struct map_session_data -#include "../common/cbasetypes.h" -#include "../common/malloc.h" // aMalloc, aRealloc, aFree -#include "../common/showmsg.h" // ShowError, ShowWarning -#include "../common/strlib.h" // safestrncpy +#include "map/battle.h" // battle_config.* +#include "map/clif.h" // clif-"open_search_store_info, clif-"search_store_info_* +#include "map/pc.h" // struct map_session_data +#include "common/cbasetypes.h" +#include "common/malloc.h" // aMalloc, aRealloc, aFree +#include "common/showmsg.h" // ShowError, ShowWarning +#include "common/strlib.h" // safestrncpy struct searchstore_interface searchstore_s; +struct searchstore_interface *searchstore; /// retrieves search function by type static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type) { diff --git a/src/map/searchstore.h b/src/map/searchstore.h index 6664eddfa..24d7665e0 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -5,11 +5,11 @@ #ifndef MAP_SEARCHSTORE_H #define MAP_SEARCHSTORE_H -#include <time.h> +#include "map/map.h" // MESSAGE_SIZE +#include "common/hercules.h" +#include "common/mmo.h" // MAX_SLOTS -#include "map.h" // MESSAGE_SIZE -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // MAX_SLOTS +#include <time.h> /** * Defines @@ -95,10 +95,10 @@ struct searchstore_interface { bool (*result) (struct map_session_data* sd, unsigned 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 searchstore_interface *searchstore; - #ifdef HERCULES_CORE void searchstore_defaults(void); #endif // HERCULES_CORE +HPShared struct searchstore_interface *searchstore; + #endif /* MAP_SEARCHSTORE_H */ diff --git a/src/map/skill.c b/src/map/skill.c index 64b0cebe8..a9ebf6998 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4,47 +4,47 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION() +#include "config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION() #include "skill.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "battle.h" -#include "battleground.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "status.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - #define SKILLUNITTIMER_INTERVAL 100 // ranges reserved for mapping skill ids to skilldb offsets @@ -62,6 +62,9 @@ #endif struct skill_interface skill_s; +struct s_skill_dbs skilldbs; + +struct skill_interface *skill; //Since only mob-casted splash skills can hit ice-walls static inline int splash_target(struct block_list* bl) { @@ -99,7 +102,7 @@ int skill_get_index( uint16 skill_id ) { skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE; else if( skill_id >= HM_SKILLBASE ) skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE; - //[Ind/Hercules] GO GO GO LESS! - http://hercules.ws/board/topic/512-skill-id-processing-overhaul/ + //[Ind/Hercules] GO GO GO LESS! - http://herc.ws/board/topic/512-skill-id-processing-overhaul/ else if( skill_id > 1019 && skill_id < 8001 ) { if( skill_id < 2058 ) // 1020 - 2000 are empty skill_id = 1020 + skill_id - 2001; @@ -112,7 +115,7 @@ int skill_get_index( uint16 skill_id ) { else ShowWarning("skill_get_index: skill id '%d' is not being handled!\n",skill_id); } - + // validate result if( !skill_id || skill_id >= MAX_SKILL_DB ) return 0; @@ -121,11 +124,11 @@ int skill_get_index( uint16 skill_id ) { } const char* skill_get_name( uint16 skill_id ) { - return skill->db[skill->get_index(skill_id)].name; + return skill->dbs->db[skill->get_index(skill_id)].name; } const char* skill_get_desc( uint16 skill_id ) { - return skill->db[skill->get_index(skill_id)].desc; + return skill->dbs->db[skill->get_index(skill_id)].desc; } // out of bounds error checking [celest] @@ -138,58 +141,58 @@ void skill_chk(uint16* skill_id) { skill->chk(&(id)); \ if(!(id)) return 0; \ if( (lv) > MAX_SKILL_LEVEL && (var) > 1 ) { \ - int lv2__ = (lv); (lv) = skill->db[(id)].max; \ + int lv2__ = (lv); (lv) = skill->dbs->db[(id)].max; \ return (var) + ((lv2__-(lv))/2);\ } \ return (var);\ } while(0) #define skill_glv(lv) min((lv),MAX_SKILL_LEVEL-1) // Skill DB -int skill_get_hit( uint16 skill_id ) { skill_get (skill->db[skill_id].hit, skill_id); } -int skill_get_inf( uint16 skill_id ) { skill_get (skill->db[skill_id].inf, skill_id); } -int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get (skill->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); } -int skill_get_nk( uint16 skill_id ) { skill_get (skill->db[skill_id].nk, skill_id); } -int skill_get_max( uint16 skill_id ) { skill_get (skill->db[skill_id].max, skill_id); } -int skill_get_range( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 ( (skill->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); } -int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_state(uint16 skill_id) { skill_get (skill->db[skill_id].state, skill_id); } -int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].itemid[idx], skill_id); } -int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].amount[idx], skill_id); } -int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_castdef( uint16 skill_id ) { skill_get (skill->db[skill_id].cast_def_rate, skill_id); } -int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->db[skill_id].weapon, skill_id); } -int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->db[skill_id].ammo, skill_id); } -int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_inf2( uint16 skill_id ) { skill_get (skill->db[skill_id].inf2, skill_id); } -int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->db[skill_id].castcancel, skill_id); } -int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_type( uint16 skill_id ) { skill_get (skill->db[skill_id].skill_type, skill_id); } -int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->db[skill_id].unit_id[flag], skill_id); } -int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_interval, skill_id); } -int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BCT_ALL, skill_id); } -int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BL_ALL, skill_id); } -int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_flag, skill_id); } -int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_hit( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].hit, skill_id); } +int skill_get_inf( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf, skill_id); } +int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get (skill->dbs->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); } +int skill_get_nk( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].nk, skill_id); } +int skill_get_max( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].max, skill_id); } +int skill_get_range( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 ( (skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); } +int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_state(uint16 skill_id) { skill_get (skill->dbs->db[skill_id].state, skill_id); } +int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].itemid[idx], skill_id); } +int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].amount[idx], skill_id); } +int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_castdef( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].cast_def_rate, skill_id); } +int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].weapon, skill_id); } +int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].ammo, skill_id); } +int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_inf2( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf2, skill_id); } +int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].castcancel, skill_id); } +int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_type( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].skill_type, skill_id); } +int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->dbs->db[skill_id].unit_id[flag], skill_id); } +int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_interval, skill_id); } +int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BCT_ALL, skill_id); } +int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BL_ALL, skill_id); } +int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_flag, skill_id); } +int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); } int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) { #ifdef RENEWAL_CAST - Assert_ret(skill_lv > 0); skill_get2 (skill->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv); + Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv); #else return 0; #endif @@ -223,17 +226,17 @@ int skill_get_casttype (uint16 skill_id) { } int skill_get_casttype2 (uint16 index) { - int inf = skill->db[index].inf; + int inf = skill->dbs->db[index].inf; if (inf&(INF_GROUND_SKILL)) return CAST_GROUND; if (inf&INF_SUPPORT_SKILL) return CAST_NODAMAGE; if (inf&INF_SELF_SKILL) { - if(skill->db[index].inf2&INF2_NO_TARGET_SELF) + if(skill->dbs->db[index].inf2&INF2_NO_TARGET_SELF) return CAST_DAMAGE; //Combo skill. return CAST_NODAMAGE; } - if (skill->db[index].nk&NK_NO_DAMAGE) + if (skill->dbs->db[index].nk&NK_NO_DAMAGE) return CAST_NODAMAGE; return CAST_DAMAGE; } @@ -362,7 +365,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk #else // not RENEWAL 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 // RENEWAL - if( sd && ((skill2_lv = pc->checkskill(sd, HP_MEDITATIO)) > 0) ) + if (sd && (skill2_lv = pc->checkskill(sd, HP_MEDITATIO)) > 0) hp += hp * skill2_lv * 2 / 100; else if( src->type == BL_HOM && (skill2_lv = homun->checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 ) hp += hp * skill2_lv * 2 / 100; @@ -372,10 +375,10 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk if( ( (target && target->type == BL_MER) || !heal ) && skill_id != NPC_EVILLAND ) hp >>= 1; - if( sd && (skill2_lv = pc->skillheal_bonus(sd, skill_id)) ) + if (sd && (skill2_lv = pc->skillheal_bonus(sd, skill_id)) != 0) hp += hp*skill2_lv/100; - if( tsd && (skill2_lv = pc->skillheal2_bonus(tsd, skill_id)) ) + if (tsd && (skill2_lv = pc->skillheal2_bonus(tsd, skill_id)) != 0) hp += hp*skill2_lv/100; sc = status->get_sc(src); @@ -438,7 +441,7 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE))) return 0; // Reproduce will only copy skills according on the list. [Jobbie] - else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] ) + else if( sd->sc.data[SC__REPRODUCE] && !skill->dbs->reproduce_db[skill->get_index(skill_id)] ) return 0; return 1; @@ -478,14 +481,14 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) clif->skill_fail(sd, skill_id, 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 below * 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 == skill_id ) return 0; - + if( sd->sc.data[SC_ALL_RIDING] ) return 1;//You can't use skills while in the new mounts (The client doesn't let you, this is to make cheat-safe) @@ -619,19 +622,19 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill } if (pos != -1) // simple single-definition layout - return &skill->unit_layout[pos]; + return &skill->dbs->unit_layout[pos]; dir = (src->x == x && src->y == y) ? 6 : map->calc_dir(src,x,y); // 6 - default aegis direction if (skill_id == MG_FIREWALL) - return &skill->unit_layout [skill->firewall_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->firewall_unit_pos + dir]; else if (skill_id == WZ_ICEWALL) - return &skill->unit_layout [skill->icewall_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->icewall_unit_pos + dir]; else if( skill_id == WL_EARTHSTRAIN ) //Warlock - return &skill->unit_layout [skill->earthstrain_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->earthstrain_unit_pos + dir]; ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skill_id, skill_lv); - return &skill->unit_layout[0]; // default 1x1 layout + return &skill->dbs->unit_layout[0]; // default 1x1 layout } /*========================================== @@ -699,7 +702,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if (sd->addeff[i].duration > 0) { // Fixed duration temp = sd->addeff[i].duration; - flag = SCFLAG_NOAVOID; + flag = SCFLAG_FIXEDRATE|SCFLAG_FIXEDTICK; } else { // Default duration temp = skill->get_time2(status->sc2skill(type),7); @@ -967,7 +970,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case DC_UGLYDANCE: rate = 5+5*skill_lv; - if(sd && (temp=pc->checkskill(sd,DC_DANCINGLESSON))) + if (sd && (temp=pc->checkskill(sd,DC_DANCINGLESSON)) > 0) rate += 5+temp; status_zap(bl, 0, rate); break; @@ -1367,7 +1370,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; } - if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) { + if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai != AI_NONE) { //Pass heritage to Master for status causing effects. [Skotlex] sd = map->id2sd(md->master_id); src = sd?&sd->bl:src; @@ -2013,7 +2016,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in } if (flag) { sd->status.inventory[j].attribute = 1; - pc->unequipitem(sd, j, 3); + pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } } clif->equiplist(sd); @@ -2102,7 +2105,6 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in 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 (targeted) @@ -2210,7 +2212,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if(csc && csc->data[SC_GRAVITATION] && csc->data[SC_GRAVITATION]->val3 == BCT_SELF ) return 0; } - + dmg = battle->calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF); //Skotlex: Adjusted to the new system @@ -2229,10 +2231,11 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } } - if( dmg.flag&BF_MAGIC + if( dmg.flag&BF_MAGIC && (skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag & 0xFFF) == 1)) ) { /* Need more info cause NPC_EARTHQUAKE is ground type */ // 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)) ) { + int reflecttype; + if ((dmg.damage || dmg.damage2) && (reflecttype = skill->magic_reflect(src, bl, src==dsrc)) != 0) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = true; @@ -2249,17 +2252,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr /* bugreport:7859 magical reflected zeroes blow count */ dmg.blewcount = 0; //Spirit of Wizard blocks Kaite's reflection - if (type == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD) { + if (reflecttype == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD) { //Consume one Fragment per hit of the casted skill? [Skotlex] - type = tsd ? pc->search_inventory(tsd, ITEMID_FRAGMENT_OF_CRYSTAL) : 0; - if (type != INDEX_NOT_FOUND) { - if ( tsd ) pc->delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); + int consumeitem = tsd ? pc->search_inventory(tsd, ITEMID_FRAGMENT_OF_CRYSTAL) : 0; + if (consumeitem != INDEX_NOT_FOUND) { + if ( tsd ) pc->delitem(tsd, consumeitem, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; sc->data[SC_SOULLINK]->val3 = skill_id; sc->data[SC_SOULLINK]->val4 = dsrc->id; } - } else if( type != 2 ) /* Kaite bypasses */ + } else if( reflecttype != 2 ) /* Kaite bypasses */ additional_effects = false; /** @@ -2272,7 +2275,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr #else // issue:6415 in pre-renewal Kaite reflected the entire damage received // regardless of caster's equipment (Aegis 11.1) - if( dmg.dmg_lv != ATK_MISS && type == 1 ) //Wiz SL canceled and consumed fragment + if( dmg.dmg_lv != ATK_MISS && reflecttype == 1 ) //Wiz SL canceled and consumed fragment #endif { short s_ele = skill->get_ele(skill_id, skill_lv); @@ -2320,14 +2323,13 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ struct block_list *nbl; nbl = battle->get_enemy_area(bl,bl->x,bl->y,2,BL_CHAR,bl->id); - if( nbl ){ // Only one target is chosen. - int temp = (int)(damage / (float)(10 / skill_lv)); - clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,temp,0), 1, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + if (nbl) { // Only one target is chosen. + clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage * skill_lv / 10,0), 1, OB_OBOROGENSOU_TRANSITION_ATK, -1, BDT_SKILL); } } //Skill hit type - type=(skill_id==0)?5:skill->get_hit(skill_id); + type=(skill_id==0)?BDT_SPLASH:skill->get_hit(skill_id); if(damage < dmg.div_ //Only skills that knockback even when they miss. [Skotlex] @@ -2336,7 +2338,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if(skill_id == CR_GRANDCROSS||skill_id == NPC_GRANDDARKNESS) { if(battle_config.gx_disptype) dsrc = src; - if(src == bl) type = 4; + if(src == bl) type = BDT_ENDURE; else flag|=SD_ANIMATION; } if(skill_id == NJ_TATAMIGAESHI) { @@ -2403,7 +2405,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr { //bonus from SG_FRIEND [Komurka] int level; - if(sd->status.party_id>0 && (level = pc->checkskill(sd,SG_FRIEND))) + if(sd->status.party_id>0 && (level = pc->checkskill(sd,SG_FRIEND)) > 0) party->skill_check(sd, sd->status.party_id, TK_COUNTER,level); } break; @@ -2442,7 +2444,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr //Display damage. switch( skill_id ) { 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); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, BDT_SPLASH); break; //Skills that need be passed as a normal attack for the client to display correctly. case HVAN_EXPLOSION: @@ -2460,13 +2462,13 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr 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_, skill_id, -1, 5); // needs -1 as skill level + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, BDT_SPLASH); // 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_, skill_id, -2, 5); // needs -2(!) as skill level + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, BDT_SPLASH); // 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,skill_id,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,BDT_SKILL); break; case KO_MUCHANAGE: if( dmg.dmg_lv == ATK_FLEE ) @@ -2474,17 +2476,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case WL_SOULEXPANSION: case WL_COMET: case NJ_HUUMA: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,BDT_MULTIHIT); break; case WL_CHAINLIGHTNING_ATK: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,BDT_SKILL); break; case LG_OVERBRAND_BRANDISH: case LG_OVERBRAND: /* Fall through */ dmg.amotion = status_get_amotion(src) * 2; case LG_OVERBRAND_PLUSATK: - dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,5); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH); break; case EL_FIRE_BOMB: case EL_FIRE_BOMB_ATK: @@ -2507,29 +2509,29 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case GN_CRAZYWEED_ATK: case KO_BAKURETSU: case NC_MAGMA_ERUPTION: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH); break; case GN_SLINGITEM_RANGEMELEEATK: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,BDT_SKILL); break; case SC_FEINTBOMB: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,BDT_SPLASH); break; case EL_STONE_RAIN: - dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?BDT_MULTIHIT:BDT_SPLASH); break; case WM_SEVERE_RAINSTORM_MELEE: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,BDT_SPLASH); 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); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,BDT_SKILL); break; case WL_TETRAVORTEX_FIRE: case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_, WL_TETRAVORTEX,-1,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_, WL_TETRAVORTEX,-1,BDT_SPLASH); break; case HT_CLAYMORETRAP: case HT_BLASTMINE: @@ -2538,17 +2540,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case RA_CLUSTERBOMB: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: - dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, 5); + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH); 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_, skill_id, -1, type); break; case HW_GRAVITATION: - dmg.dmotion = clif->damage(bl, bl, 0, 0, damage, 1, 4, 0); + dmg.dmotion = clif->damage(bl, bl, 0, 0, damage, 1, BDT_ENDURE, 0); break; case WZ_SIGHTBLASTER: - dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, 5); + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH); break; case AB_DUPLELIGHT_MELEE: case AB_DUPLELIGHT_MAGIC: @@ -2607,7 +2609,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru] { int lv, idx = 0; - if( sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) ) { + if (sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) > 0) { //Level dependent and limitation. lv = min(lv,skill->get_max(copy_skill)); @@ -2630,6 +2632,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED; clif->addskill(tsd,copy_skill); } else { + int plagiarismlvl; lv = skill_lv; if ( tsd->cloneskill_id ) { idx = skill->get_index(tsd->cloneskill_id); @@ -2641,8 +2644,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } } - if ((type = pc->checkskill(tsd,RG_PLAGIARISM)) < lv) - lv = type; + if ((plagiarismlvl = pc->checkskill(tsd,RG_PLAGIARISM)) < lv) + lv = plagiarismlvl; tsd->cloneskill_id = copy_skill; pc_setglobalreg(tsd, script->add_str("CLONE_SKILL"), copy_skill); @@ -2713,7 +2716,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } /* monsters with skill lv higher than MAX_SKILL_LEVEL may get this value beyond the max depending on conditions, we cap to the system's limit */ - if( dsrc && dsrc->type == BL_MOB && skill_lv > MAX_SKILL_LEVEL && dmg.blewcount > 25 ) + if (dsrc->type == BL_MOB && skill_lv > MAX_SKILL_LEVEL && dmg.blewcount > 25) dmg.blewcount = 25; //blown-specific handling @@ -2727,7 +2730,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr short dir_x, dir_y; dir_x = dirx[(dir+4)%8]; dir_y = diry[(dir+4)%8]; - if( map->getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 ) + if (map->getcell(bl->m, bl, bl->x + dir_x, bl->y + dir_y, CELL_CHKNOPASS) != 0) skill->addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4); } break; @@ -2758,12 +2761,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr ) && check_distance_bl(bl, d_bl, sce->val3) ) { if(!rmdamage){ - clif->damage(d_bl,d_bl, 0, 0, damage, 0, 0, 0); + clif->damage(d_bl,d_bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(NULL,d_bl, damage, 0); } else{ //Reflected magics are done directly on the target not on paladin //This check is only for magical skill. //For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage - clif->damage(bl,bl, 0, 0, damage, 0, 0, 0); + clif->damage(bl,bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(bl,bl, damage, 0); } } @@ -2796,7 +2799,6 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr battle->drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); } - if( damage > 0 ) { /** * Post-damage effects @@ -2831,7 +2833,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if (!(flag&2) && (skill_id == MG_COLDBOLT || skill_id == MG_FIREBOLT || skill_id == MG_LIGHTNINGBOLT) - && (sc = status->get_sc(src)) + && (sc = status->get_sc(src)) != NULL && sc->data[SC_DOUBLECASTING] && rnd() % 100 < sc->data[SC_DOUBLECASTING]->val2 ) { @@ -2857,11 +2859,11 @@ void skill_attack_combo2_unknown(int *attack_type, struct block_list* src, struc void skill_attack_display_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage) { if (*flag & SD_ANIMATION && dmg->div_ < 2) //Disabling skill animation doesn't works on multi-hit. - *type = 5; + *type = BDT_SPLASH; 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_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, 5); + clif->skill_damage(src, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, BDT_SPLASH); } dmg->dmotion = clif->skill_damage(dsrc, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, *type); } @@ -2910,7 +2912,7 @@ int skill_area_sub(struct block_list *bl, va_list ap) { 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); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if (flag&(SD_SPLASH|SD_PREAMBLE)) skill->area_temp[2]++; @@ -3085,15 +3087,15 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, // Requirements for( i = 0; i < ARRAYLENGTH(itemid); i++ ) { - itemid[i] = skill->db[idx].itemid[i]; - amount[i] = skill->db[idx].amount[i]; - } - hp = skill->db[idx].hp[lv-1]; - sp = skill->db[idx].sp[lv-1]; - hp_rate = skill->db[idx].hp_rate[lv-1]; - sp_rate = skill->db[idx].sp_rate[lv-1]; - state = skill->db[idx].state; - if( (mhp = skill->db[idx].mhp[lv-1]) > 0 ) + itemid[i] = skill->dbs->db[idx].itemid[i]; + amount[i] = skill->dbs->db[idx].amount[i]; + } + hp = skill->dbs->db[idx].hp[lv-1]; + sp = skill->dbs->db[idx].sp[lv-1]; + hp_rate = skill->dbs->db[idx].hp_rate[lv-1]; + sp_rate = skill->dbs->db[idx].sp_rate[lv-1]; + state = skill->dbs->db[idx].state; + if( (mhp = skill->dbs->db[idx].mhp[lv-1]) > 0 ) hp += (st->max_hp * mhp) / 100; if( hp_rate > 0 ) hp += (st->hp * hp_rate) / 100; @@ -3155,7 +3157,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, // Consume items for (i = 0; i < ARRAYLENGTH(itemid); i++) { if (index[i] != INDEX_NOT_FOUND) - pc->delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME); + pc->delitem(sd, index[i], amount[i], 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); } if( type&2 ) @@ -3335,7 +3337,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { break; case SC_ESCAPE: if( skl->type < 4+skl->skill_lv ){ - clif->skill_damage(src,src,tick,0,0,-30000,1,skl->skill_id,skl->skill_lv,5); + clif->skill_damage(src,src,tick,0,0,-30000,1,skl->skill_id,skl->skill_lv,BDT_SPLASH); skill->blown(src,src,1,unit->getdir(src),0); skill->addtimerskill(src,tick+80,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type+1,0); } @@ -3370,13 +3372,13 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { 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) ) + if( path->search_long(NULL, src, 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) - && !map->getcell(src->m, skl->x, skl->y, CELL_CHKLANDPROTECTOR) ) + if( path->search_long(NULL, src, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) + && !map->getcell(src->m, src, skl->x, skl->y, CELL_CHKLANDPROTECTOR) ) 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) ) + else if( path->search_long(NULL, src, 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: { @@ -3493,7 +3495,7 @@ int skill_activate_reverberation(struct block_list *bl, va_list ap) { struct skill_unit_group *sg; if( bl->type != BL_SKILL ) return 0; - if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) { + if( su->alive && (sg = su->group) != NULL && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) { int64 tick = timer->gettick(); clif->changetraplook(bl,UNT_USED_TRAPS); map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, tick); @@ -3720,7 +3722,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; case KN_CHARGEATK: { - bool path_exists = path->search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); + bool path_exists = path->search_long(NULL, src, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); unsigned int dist = distance_bl(src, bl); uint8 dir = map->calc_dir(bl, src->x, src->y); @@ -3834,9 +3836,16 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( dir > 2 && dir < 6 ) y = -i; else if( dir == 7 || dir < 2 ) y = i; else y = 0; - if( (mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground) ) // only NJ_ISSEN don't have slide effect in GVG - && unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1) - ) { + if ((mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground))) { // only NJ_ISSEN don't have slide effect in GVG + if (!(unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1))) { + // The cell is not reachable (wall, object, ...), move next to the target + if (x > 0) x = -1; + else if (x < 0) x = 1; + if (y > 0) y = -1; + else if (y < 0) y = 1; + + unit->movepos(src, bl->x+x, bl->y+y, 1, 1); + } clif->slide(src, src->x, src->y); clif->fixpos(src); clif->spiritball(src); @@ -3934,7 +3943,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 /* Fall through */ case LG_MOONSLASHER: case MH_XENO_SLASHER: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; default: break; @@ -4033,7 +4042,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 tx -= dirx[dir]; ty -= diry[dir]; // If target cell is a wall then break - if(map->getcell(bl->m,tx,ty,CELL_CHKWALL)) + if(map->getcell(bl->m, bl, tx, ty, CELL_CHKWALL)) break; skill->blown(src,bl,1,dir,0); // Splash around target cell, but only cells inside area; we first have to check the area is not negative @@ -4089,7 +4098,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] //clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/ - clif->damage(src,bl,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. + clif->damage(src,bl,status_get_amotion(src),0,-1,1,BDT_ENDURE,0); //Display an absorbed damage attack. skill->addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); break; @@ -4164,7 +4173,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 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 + if (src->type != BL_PC || map->getcell(src->m, src, x, y, CELL_CHKWATER)) // non-players bypass the water requirement count++; // natural water cell else if( (su = map->find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (su = map->find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) { @@ -4481,7 +4490,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; case WL_FROSTMISTY: // 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) ) + if( path->search(NULL,src,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) ) skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); break; case WL_HELLINFERNO: @@ -4503,7 +4512,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; } case RA_WUGBITE: - if( path->search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { + if( path->search(NULL,src,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); }else if( sd && skill_id == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message. clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); @@ -4521,14 +4530,14 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 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( su && (sg=su->group) != NULL && 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); + map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0); } skill->delunit(su); } @@ -4543,7 +4552,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. } else { map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( sd ) pc->overheat(sd,1); } break; @@ -4562,7 +4571,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->area_temp[5] = y; map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); } break; case LG_PINPOINTATTACK: @@ -4620,7 +4629,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); } else{ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); } break; @@ -4687,7 +4696,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 else { int i = skill->get_splash(skill_id,skill_lv); clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 30 ) map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); else @@ -4697,7 +4706,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case EL_ROCK_CRUSHER: clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 50 ) skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); else @@ -4710,7 +4719,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 else { int i = skill->get_splash(skill_id,skill_lv); clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 30 ) map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); else @@ -4723,7 +4732,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case EL_WIND_SLASH: case EL_STONE_HAMMER: clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); break; @@ -4736,7 +4745,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 type2 = type-1; clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( (esc && esc->data[type2]) || (tsc && tsc->data[type]) ) { elemental->clean_single_effect(ele, skill_id); } @@ -4934,7 +4943,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { } if( ud->skill_id == RA_WUGSTRIKE ){ - if( !path->search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) + if( !path->search(NULL,src,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) break; } @@ -4988,7 +4997,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { } if( inf&BCT_ENEMY - && (sc = status->get_sc(target)) && sc->data[SC_FOGWALL] + && (sc = status->get_sc(target)) != NULL && sc->data[SC_FOGWALL] && rnd() % 100 < 75 ) { // Fogwall makes all offensive-type targeted skills fail at 75% @@ -5026,7 +5035,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1); } #ifdef OFFICIAL_WALKPATH - if( !path->search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) + if( !path->search_long(NULL, src, 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->skill_id, ud->skill_lv, 1) ) @@ -5039,7 +5048,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { } if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); // Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] @@ -5530,10 +5539,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int abra_skill_id = 0, abra_skill_lv, abra_idx; do { abra_idx = rnd() % MAX_SKILL_ABRA_DB; - abra_skill_id = skill->abra_db[abra_idx].skill_id; + abra_skill_id = skill->dbs->abra_db[abra_idx].skill_id; } while (abra_skill_id == 0 || - skill->abra_db[abra_idx].req_lv > skill_lv || //Required lv for it to appear - rnd()%10000 >= skill->abra_db[abra_idx].per + skill->dbs->abra_db[abra_idx].req_lv > skill_lv || //Required lv for it to appear + rnd()%10000 >= skill->dbs->abra_db[abra_idx].per ); abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id)); clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); @@ -6099,7 +6108,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } i = 0; - count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner + count = (sd)? min(skill_lv,MAX_PC_DEVOTION) : 1; // Mercenary only can Devote owner if( sd ) { // Player Devoting Player ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); @@ -6127,22 +6136,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case MO_CALLSPIRITS: if(sd) { - int limit = skill_lv; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), pc->getmaxspiritball(sd, 0)); } break; case CH_SOULCOLLECT: if(sd) { - int limit = 5, i; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + int i, limit = pc->getmaxspiritball(sd, 5); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - for (i = 0; i < limit; i++) - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + for ( i = 0; i < limit; i++ ) + pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), limit); } break; @@ -6234,7 +6238,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); if( !count && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); } break; @@ -6286,7 +6290,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { //Self Destruction hits everyone in range (allies+enemies) //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - int targetmask = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? + int targetmask = ((!md || md->special_state.ai == AI_SPHERE) && !map_flag_vs(src->m))? BCT_ENEMY:BCT_ALL; clif->skill_nodamage(src, src, skill_id, -1, 1); map->delblock(src); //Required to prevent chain-self-destructions hitting back. @@ -6457,7 +6461,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // 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[skill_id].desc); + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill->dbs->db[skill_id].desc); clif->disp_overhead(&md->bl,temp); } break; @@ -6655,7 +6659,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 1; } if( sd->skillitem != skill_id ) - status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded + status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded } break; @@ -6738,7 +6742,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } break; @@ -6833,13 +6837,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { int x,bonus=100, potion = min(500+skill_lv,505); x = skill_lv%11 - 1; - i = pc->search_inventory(sd,skill->db[skill_id].itemid[x]); - if (i == INDEX_NOT_FOUND || skill->db[skill_id].itemid[x] <= 0) { + i = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[x]); + if (i == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[x] <= 0) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map->freeblock_unlock(); return 1; } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->db[skill_id].amount[x]) { + if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->dbs->db[skill_id].amount[x]) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map->freeblock_unlock(); return 1; @@ -6854,7 +6858,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin script->potion_flag = 1; script->potion_hp = script->potion_sp = script->potion_per_hp = script->potion_per_sp = 0; script->potion_target = bl->id; - script->run(sd->inventory_data[i]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[i], 0); script->potion_flag = script->potion_target = 0; if( sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ALCHEMIST ) bonus += sd->status.base_level; @@ -6905,7 +6909,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( dstsd ) hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; } - if( dstsd && (i = pc->skillheal2_bonus(dstsd, skill_id)) ) { + if (dstsd && (i = pc->skillheal2_bonus(dstsd, skill_id)) != 0) { hp += hp * i / 100; sp += sp * i / 100; } @@ -7077,7 +7081,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } clif->skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1); - if(!map->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB,0) && map->getcell(src->m,x,y,CELL_CHKREACH)) { + if (!map->count_oncell(src->m, x, y, BL_PC | BL_NPC | BL_MOB, 0) && map->getcell(src->m, src, x, y, CELL_CHKREACH)) { clif->slide(src,x,y); unit->movepos(src, x, y, 1, 0); } @@ -7381,14 +7385,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case WE_MALE: { - int hp_rate = (!skill_lv)? 0:skill->db[skill_id].hp_rate[skill_lv-1]; + int hp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].hp_rate[skill_lv-1]; int gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it cost the caster. [Skotlex] clif->skill_nodamage(src,bl,skill_id,status->heal(bl, gain_hp, 0, 0),1); } break; case WE_FEMALE: { - int sp_rate = (!skill_lv)? 0:skill->db[skill_id].sp_rate[skill_lv-1]; + int sp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].sp_rate[skill_lv-1]; int gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it cost the caster. [Skotlex] clif->skill_nodamage(src,bl,skill_id,status->heal(bl, 0, gain_sp, 0),1); } @@ -7443,7 +7447,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // 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) ) + if( su && (sg = su->group) != NULL && (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, skill_id, skill_lv, 1); if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) && sg->unit_id != UNT_THORNS_TRAP ) { @@ -7452,15 +7456,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int i; // 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 ) { + if( skill->dbs->db[su->group->skill_id].itemid[i] > 0 ) { int success; struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill->db[su->group->skill_id].itemid[i]; + item_tmp.nameid = skill->dbs->db[su->group->skill_id].itemid[i]; item_tmp.identify = 1; - if( item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) { + if (item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) != 0) { clif->additem(sd,0,0,success); - 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); + map->addflooritem(&sd->bl, &item_tmp, skill->dbs->db[su->group->skill_id].amount[i], sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -7470,9 +7474,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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)) ) { + if (item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) != 0) { clif->additem(sd,0,0,flag); - map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } @@ -7486,7 +7490,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->skill_nodamage(src,bl,skill_id,skill_lv,1); { struct skill_unit *su=NULL; - if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ + if (bl->type==BL_SKILL && (su=(struct skill_unit *)bl) != NULL && su->group != NULL) { switch(su->group->unit_id){ case UNT_ANKLESNARE: if (su->group->val2 != 0) @@ -7667,7 +7671,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case CG_LONGINGFREEDOM: { - if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 + if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) != NULL && tsce->val4 && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] { clif->skill_nodamage(src,bl,skill_id,skill_lv, @@ -7690,7 +7694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] + status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] do { int eff = rnd() % 14; if( eff == 5 ) @@ -7711,7 +7715,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case 3: // 1000 damage, random armor destroyed { status_fix_damage(src, bl, 1000, 0); - clif->damage(src,bl,0,0,1000,0,0,0); + clif->damage(src,bl,0,0,1000,0,BDT_NORMAL,0); if( !status->isdead(bl) ) { int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); @@ -7748,14 +7752,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case 10: // 6666 damage, atk matk halved, cursed status_fix_damage(src, bl, 6666, 0); - clif->damage(src,bl,0,0,6666,0,0,0); + clif->damage(src,bl,0,0,6666,0,BDT_NORMAL,0); sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); break; case 11: // 4444 damage status_fix_damage(src, bl, 4444, 0); - clif->damage(src,bl,0,0,4444,0,0,0); + clif->damage(src,bl,0,0,4444,0,BDT_NORMAL,0); break; case 12: // stun sc_start(src,bl,SC_STUN,100,skill_lv,5000); @@ -7896,7 +7900,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { if (map->list[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)) + if (map->getcell(src->m, src, 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); } @@ -8133,7 +8137,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case LG_EARTHDRIVE: { int splash; - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); splash = skill->get_splash(skill_id,skill_lv); if( skill_id == LG_EARTHDRIVE ) { int dummy = 1; @@ -8314,7 +8318,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case GC_PHANTOMMENACE: { int r; - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); r = skill->get_splash(skill_id, skill_lv); map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR, @@ -8610,7 +8614,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin * Ranger **/ case RA_FEARBREEZE: - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; @@ -8651,7 +8655,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RA_SENSITIVEKEEN: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); break; /** @@ -8678,7 +8682,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case NC_ANALYZE: - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src,bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); if( sd ) pc->overheat(sd,1); @@ -8690,7 +8694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) { map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);; - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); if (sd) pc->overheat(sd,1); } clif->skill_nodamage(src,src,skill_id,skill_lv,failure); @@ -8810,7 +8814,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case LG_TRAMPLE: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); break; @@ -8848,7 +8852,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin switch( opt ) { case 1: sc_start(src,bl,SC_SHIELDSPELL_DEF,100,opt,INVALID_TIMER); //Splash AoE ATK - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); break; @@ -8875,13 +8879,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin switch( opt ) { case 1: sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,INVALID_TIMER); //Splash AoE MATK - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); break; case 2: sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 2000); //Splash AoE Lex Divina - clif->skill_damage(src,bl,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); break; case 3: @@ -8994,7 +8998,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } else { int count = 0; - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); count = map->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-characters BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); if( sd ) pc->delspiritball(sd, count, 0); @@ -9004,13 +9008,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case SR_RAISINGDRAGON: - if( sd ) { - short max = 5 + skill_lv; - int i; + if ( sd ) { + int i, max; sc_start(src, bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - for( i = 0; i < max; i++ ) // Don't call more than max available spheres. - pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max); - clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + max = pc->getmaxspiritball(sd, 0); + for ( i = 0; i < max; i++ ) + pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, skill_lv), max); } break; @@ -9028,7 +9033,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0); } else { - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id); } break; @@ -9036,12 +9041,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SR_POWERVELOCITY: if( !dstsd ) break; - if( sd && dstsd->spiritball <= 5 ) { - int i; - 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); + if ( sd && (dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER ) { + int i, max = pc->getmaxspiritball(dstsd, 5); + for ( i = 0; i < max; i++ ) { + pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, 1), max); } + pc->delspiritball(sd, sd->spiritball, 0); } clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); break; @@ -9197,7 +9202,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin madnesscheck = map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count); sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)); if ( madnesscheck >= 8 )//The god of madness deals 9999 fixed unreduceable damage when 8 or more enemy players are affected. - status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, 0, 0)); + status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, BDT_NORMAL, 0)); //skill->attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);//To renable when I can confirm it deals damage like this. Data shows its dealt as reflected damage which I don't have it coded like that yet. [Rytech] } else if( sd ) { int rate = sstatus->int_ / 6 + (sd? sd->status.job_level:0) / 5 + skill_lv * 4; @@ -9228,8 +9233,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int improv_skill_id = 0, improv_skill_lv, improv_idx; do { improv_idx = rnd() % MAX_SKILL_IMPROVISE_DB; - improv_skill_id = skill->improvise_db[improv_idx].skill_id; - } while( improv_skill_id == 0 || rnd()%10000 >= skill->improvise_db[improv_idx].per ); + improv_skill_id = skill->dbs->improvise_db[improv_idx].skill_id; + } while( improv_skill_id == 0 || rnd()%10000 >= skill->dbs->improvise_db[improv_idx].per ); improv_skill_lv = 4 + skill_lv; clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); @@ -9333,7 +9338,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, BDT_SKILL); break; case GM_SANDMAN: @@ -9558,7 +9563,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin elemental->clean_single_effect(ele, skill_id); } else { clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0); sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); @@ -9573,7 +9578,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case EL_ZEPHYR: case EL_POWER_OF_GAIA: clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); break; @@ -9589,7 +9594,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin elemental->clean_single_effect(ele, skill_id); } else { // This not heals at the end. - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); sc_start(src, bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); } @@ -9666,8 +9671,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->skill_nodamage(src, src, skill_id, skill_lv, 1); clif->slide(src, bl->x, bl->y) ; sc_start(src, src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv)); - if ( !is_boss(bl) && unit->stop_walking(&sd->bl, 1) && unit->movepos(bl, x, y, 0, 0) ) - { + if ( !is_boss(bl) && unit->stop_walking(&sd->bl, STOPWALKING_FLAG_FIXPOS) && unit->movepos(bl, x, y, 0, 0) ) { if( dstsd && pc_issit(dstsd) ) pc->setstand(dstsd); clif->slide(bl, x, y) ; @@ -9690,7 +9694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case KG_KAGEMUSYA: clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; case KG_KAGEHUMI: @@ -9709,7 +9713,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); sc_start(src, src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); } } else { @@ -9963,7 +9967,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) src->type, src->id, ud->skill_id, ud->skill_lv, ud->skillx, ud->skilly); if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); @@ -10454,8 +10458,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui 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) - && !map->getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR)) + if (i == 0 && path->search_long(NULL, src, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) + && !map->getcell(src->m, src, tmpx, tmpy, CELL_CHKLANDPROTECTOR)) clif->skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick); if( i > 0 ) @@ -10525,9 +10529,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case CR_SLIMPITCHER: if (sd) { int i = skill_lv%11 - 1; - int j = pc->search_inventory(sd,skill->db[skill_id].itemid[i]); - if (j == INDEX_NOT_FOUND || skill->db[skill_id].itemid[i] <= 0 - || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->db[skill_id].amount[i] + int j = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[i]); + if (j == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[i] <= 0 + || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->dbs->db[skill_id].amount[i] ) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; @@ -10535,7 +10539,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui script->potion_flag = 1; script->potion_hp = 0; script->potion_sp = 0; - script->run(sd->inventory_data[j]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[j], 0); script->potion_flag = 0; //Apply skill bonuses i = pc->checkskill(sd,CR_SLIMPITCHER)*10 @@ -10556,7 +10560,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } else { int i = skill_lv%11 - 1; struct item_data *item; - i = skill->db[skill_id].itemid[i]; + i = skill->dbs->db[skill_id].itemid[i]; item = itemdb->search(i); script->potion_flag = 1; script->potion_hp = 0; @@ -10659,7 +10663,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui break; case RK_WINDCUTTER: - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); /* Fall through */ case NC_COLDSLOWER: case RK_DRAGONBREATH: @@ -10699,7 +10703,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_POISONINGWEAPON,0); return 0; } - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); skill->unitsetting(src, skill_id, skill_lv, 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; @@ -10708,7 +10712,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui **/ case AB_EPICLESIS: if( (sg = skill->unitsetting(src, skill_id, skill_lv, x, y, 0)) ) { - r = sg->unit->range; + r = skill->get_unit_range(skill_id, skill_lv); map->foreachinarea(skill->area_sub, src->m, x - r, y - r, x + r, y + r, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill->castend_nodamage_id); } break; @@ -10736,7 +10740,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case RA_DETONATOR: r = skill->get_splash(skill_id, skill_lv); map->foreachinarea(skill->detonator, src->m, x-r, y-r, x+r, y+r, BL_SKILL, src); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; /** * Mechanic @@ -10837,30 +10841,36 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui 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) < 3 ) { - switch( skill_lv ) { + r = skill->get_unit_range(GN_DEMONIC_FIRE, skill_lv); + + for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) { + if (ud->skillunit[i]->skill_id != GN_DEMONIC_FIRE) + continue; + // FIXME: Code after this point assumes that the group has one and only one unit, regardless of what the skill_unit_db says. + if (ud->skillunit[i]->unit.count != 1) + continue; + if (distance_xy(x, y, ud->skillunit[i]->unit.data[0].bl.x, ud->skillunit[i]->unit.data[0].bl.y) < r) { + switch (skill_lv) { case 3: ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER; - clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_SMOKE_POWDER); + clif->changetraplook(&ud->skillunit[i]->unit.data[0].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); + clif->changetraplook(&ud->skillunit[i]->unit.data[0].bl, UNT_FIRE_EXPANSION_TEAR_GAS); break; case 5:// If player knows a level of Acid Demonstration greater then 5, that level will be casted. if ( pc->checkskill(sd, CR_ACIDDEMONSTRATION) > 5 ) aciddemocast = pc->checkskill(sd, CR_ACIDDEMONSTRATION); map->foreachinarea(skill->area_sub, src->m, - ud->skillunit[i]->unit->bl.x - 2, ud->skillunit[i]->unit->bl.y - 2, - ud->skillunit[i]->unit->bl.x + 2, ud->skillunit[i]->unit->bl.y + 2, BL_CHAR, + ud->skillunit[i]->unit.data[0].bl.x - 2, ud->skillunit[i]->unit.data[0].bl.y - 2, + ud->skillunit[i]->unit.data[0].bl.x + 2, ud->skillunit[i]->unit.data[0].bl.y + 2, BL_CHAR, src, CR_ACIDDEMONSTRATION, aciddemocast, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id); - skill->delunit(ud->skillunit[i]->unit); + skill->delunit(&ud->skillunit[i]->unit.data[0]); break; default: - ud->skillunit[i]->unit->val2 = skill_lv; - ud->skillunit[i]->unit->group->val2 = skill_lv; + ud->skillunit[i]->unit.data[0].val2 = skill_lv; + ud->skillunit[i]->val2 = skill_lv; break; } } @@ -11072,6 +11082,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ * According to data provided in RE, SW life is equal to 3 times caster's health **/ val2 = status_get_max_hp(src) * 3; + val3 = skill_lv+1; #else val2 = skill_lv+1; #endif @@ -11106,7 +11117,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ break; case WZ_FIREPILLAR: - if( map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + if (map->getcell(src->m, src, x, y, CELL_CHKLANDPROTECTOR)) return NULL; if((flag&1)!=0) limit=1000; @@ -11115,7 +11126,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] case AM_DEMONSTRATION: case GN_HELLS_PLANT: - if( skill_id == GN_HELLS_PLANT && map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + if (skill_id == GN_HELLS_PLANT && map->getcell(src->m, src, x, y, CELL_CHKLANDPROTECTOR)) return NULL; if (map_flag_vs(src->m) && battle_config.vs_traps_bctall && (src->type&battle_config.vs_traps_bctall)) @@ -11357,7 +11368,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ case SO_FIRE_INSIGNIA: case SO_WIND_INSIGNIA: case SO_EARTH_INSIGNIA: - if( map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + if (map->getcell(src->m, src, x, y, CELL_CHKLANDPROTECTOR)) return NULL; break; case SO_CLOUD_KILL: @@ -11387,7 +11398,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ } break; case NPC_EARTHQUAKE: - clif->skill_damage(src, src, timer->gettick(), status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, timer->gettick(), status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; default: skill->unitsetting1_unknown(src, &skill_id, &skill_lv, &x, &y, &flag, &val1, &val2, &val3); @@ -11438,9 +11449,9 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ val1 = skill_lv; val2 = 0; - if( !group->state.song_dance && !map->getcell(src->m,ux,uy,CELL_CHKREACH) ) + if (!group->state.song_dance && !map->getcell(src->m, src, 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(skill_id)&UF_PATHCHECK && !path->search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) + if( battle_config.skill_wall_check && skill->get_unit_flag(skill_id)&UF_PATHCHECK && !path->search_long(NULL,src,src->m,ux,uy,x,y,CELL_CHKWALL) ) continue; // no path between cell and center of casting. switch( skill_id ) { @@ -11450,7 +11461,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ break; case WZ_ICEWALL: val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; - val2 = map->getcell(src->m, ux, uy, CELL_GETTYPE); + val2 = map->getcell(src->m, src, ux, uy, CELL_GETTYPE); break; case HT_LANDMINE: case MA_LANDMINE: @@ -11562,14 +11573,14 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick nullpo_ret(sg=src->group); nullpo_ret(ss=map->id2bl(sg->src_id)); - if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(src->bl.m, src->bl.x, src->bl.y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR ) + if (skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(src->bl.m, &src->bl, src->bl.x, src->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] - if (sc && sc->data[SC_VACUUM_EXTREME] && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR)) + if (sc && sc->data[SC_VACUUM_EXTREME] && map->getcell(bl->m, bl, bl->x, bl->y, CELL_CHKLANDPROTECTOR)) status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER); if ( sc && sc->data[SC_HOVERING] && ( sg->skill_id == SO_VACUUM_EXTREME || sg->skill_id == SO_ELECTRICWALK || sg->skill_id == SO_FIREWALK || sg->skill_id == WZ_QUAGMIRE ) ) @@ -11584,7 +11595,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick // 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 && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) { + } else if (sc && battle->check_target(&src->bl,bl,sg->target_flag) > 0) { int sec = skill->get_time2(sg->skill_id,sg->skill_lv); if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,SCFLAG_FIXEDRATE) ) { const struct TimerData* td = sce?timer->get(sce->timer):NULL; @@ -11593,9 +11604,9 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick map->moveblock(bl, src->bl.x, src->bl.y, tick); clif->fixpos(bl); sg->val2 = bl->id; - } - else + } else { sec = 3000; //Couldn't trap it? + } sg->limit = DIFF_TICK32(tick,sg->tick)+sec; } break; @@ -11650,7 +11661,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick break; case UNT_QUAGMIRE: - if( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) + if (!sce && battle->check_target(&src->bl,bl,sg->target_flag) > 0) sc_start4(ss,bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); break; @@ -11763,7 +11774,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_GD_GLORYWOUNDS: case UNT_GD_SOULCOLD: case UNT_GD_HAWKEYES: - if ( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) + if (!sce && battle->check_target(&src->bl,bl,sg->target_flag) > 0) sc_start4(ss,bl,type,100,sg->skill_lv,0,0,0,1000); break; default: @@ -11783,7 +11794,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 struct skill_unit_group *sg; struct block_list *ss; TBL_PC* tsd; - struct status_data *tstatus; + struct status_data *tstatus, *bst; struct status_change *tsc, *ssc; struct skill_unit_group_tickset *ts; enum sc_type type; @@ -11807,6 +11818,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 return 0; tstatus = status->get_status_data(bl); + bst = status->get_base_status(bl); type = status->skill2sc(sg->skill_id); skill_id = sg->skill_id; @@ -12043,7 +12055,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_NONE); break; - case UNT_MAGENTATRAP: case UNT_COBALTTRAP: case UNT_MAIZETRAP: @@ -12455,7 +12466,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) { return 0; } else { - sg->limit -= 100 * tstatus->str/20; + sg->limit -= 1000 * bst->str/20; sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit); if ( !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !is_boss(bl) ) { @@ -12922,7 +12933,8 @@ int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) { mob_class=va_arg(ap,int); skill_id=va_arg(ap,int); c=va_arg(ap,int *); - if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill_id == AM_SPHEREMINE?2:skill_id == KO_ZANZOU?4:skill_id == MH_SUMMON_LEGION?1:3) ) + if( md->master_id != src_id + || md->special_state.ai != (skill_id == AM_SPHEREMINE?AI_SPHERE:skill_id == KO_ZANZOU?AI_ZANZOU:skill_id == MH_SUMMON_LEGION?AI_ATTACK:AI_FLORA) ) return 0; //Non alchemist summoned mobs have nothing to do here. if(md->class_==mob_class) (*c)++; @@ -13036,8 +13048,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id sd->itemid = sd->itemindex = -1; if( skill_id == 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 + else if( sd->status.inventory[i].expire_time == 0 ) // Rental usable items are not consumed until expiration + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); } return 1; } @@ -13364,7 +13376,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id for (i=0;i<size*size;i++) { int x = sd->bl.x+(i%size-range); int y = sd->bl.y+(i/size-range); - if (map->getcell(sd->bl.m,x,y,CELL_CHKWALL)) { + if (map->getcell(sd->bl.m, &sd->bl, x, y, CELL_CHKWALL)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -13642,7 +13654,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id 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"); /* TODO official response? or message.conf it */ - clif->colormes(sd->fd, COLOR_RED, output); + clif->messagecolor_self(sd->fd, COLOR_RED, output); return 0; } } @@ -13816,7 +13828,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case ST_WATER: if (sc && (sc->data[SC_DELUGE] || sc->data[SC_NJ_SUITON])) break; - if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) + if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKWATER)) break; clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; @@ -13938,7 +13950,6 @@ int skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 *sk return -1; } - int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) { struct skill_condition require; struct status_data *st; @@ -14076,7 +14087,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, skill->get_desc(skill_id), require.ammo_qty, itemdb_jname(sd->status.inventory[i].nameid)); - clif->colormes(sd->fd,COLOR_RED,e_msg); + clif->messagecolor_self(sd->fd, COLOR_RED, e_msg); return 0; } if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message @@ -14212,7 +14223,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin } if ((n = pc->search_inventory(sd,req.itemid[i])) != INDEX_NOT_FOUND) - pc->delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, n, req.amount[i], 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); } } @@ -14278,17 +14289,17 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 st = &sd->battle_status; - req.hp = skill->db[idx].hp[skill_lv-1]; - hp_rate = skill->db[idx].hp_rate[skill_lv-1]; + req.hp = skill->dbs->db[idx].hp[skill_lv-1]; + hp_rate = skill->dbs->db[idx].hp_rate[skill_lv-1]; if(hp_rate > 0) req.hp += (st->hp * hp_rate)/100; else req.hp += (st->max_hp * (-hp_rate))/100; - req.sp = skill->db[idx].sp[skill_lv-1]; + req.sp = skill->dbs->db[idx].sp[skill_lv-1]; if((sd->skill_id_old == BD_ENCORE) && skill_id == sd->skill_id_dance) req.sp /= 2; - sp_rate = skill->db[idx].sp_rate[skill_lv-1]; + sp_rate = skill->dbs->db[idx].sp_rate[skill_lv-1]; if(sp_rate > 0) req.sp += (st->sp * sp_rate)/100; else @@ -14316,22 +14327,22 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.sp -= req.sp * sc->data[SC_TELEKINESIS_INTENSE]->val2 / 100; } - req.zeny = skill->db[idx].zeny[skill_lv-1]; + req.zeny = skill->dbs->db[idx].zeny[skill_lv-1]; if( sc && sc->data[SC__UNLUCKY] ) req.zeny += sc->data[SC__UNLUCKY]->val1 * 500; - req.spiritball = skill->db[idx].spiritball[skill_lv-1]; + req.spiritball = skill->dbs->db[idx].spiritball[skill_lv-1]; - req.state = skill->db[idx].state; + req.state = skill->dbs->db[idx].state; - req.mhp = skill->db[idx].mhp[skill_lv-1]; + req.mhp = skill->dbs->db[idx].mhp[skill_lv-1]; - req.weapon = skill->db[idx].weapon; + req.weapon = skill->dbs->db[idx].weapon; - req.ammo_qty = skill->db[idx].ammo_qty[skill_lv-1]; + req.ammo_qty = skill->dbs->db[idx].ammo_qty[skill_lv-1]; if (req.ammo_qty) - req.ammo = skill->db[idx].ammo; + req.ammo = skill->dbs->db[idx].ammo; if (!req.ammo && skill_id && skill->isammotype(sd, skill_id)) { //Assume this skill is using the weapon, therefore it requires arrows. @@ -14357,11 +14368,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 continue; break; case AB_ADORAMUS: - if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) + if( itemid_isgemstone(skill->dbs->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) continue; break; case WL_COMET: - if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) + if( itemid_isgemstone(skill->dbs->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) continue; break; case GN_FIRE_EXPANSION: @@ -14387,8 +14398,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 } } - req.itemid[i] = skill->db[idx].itemid[i]; - req.amount[i] = skill->db[idx].amount[i]; + req.itemid[i] = skill->dbs->db[idx].itemid[i]; + req.amount[i] = skill->dbs->db[idx].amount[i]; if (itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN) { if (sd->special_state.no_gemstone) { @@ -14430,8 +14441,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 case SO_FIRE_INSIGNIA: case SO_WIND_INSIGNIA: case SO_EARTH_INSIGNIA: - req.itemid[skill_lv-1] = skill->db[idx].itemid[skill_lv-1]; - req.amount[skill_lv-1] = skill->db[idx].amount[skill_lv-1]; + req.itemid[skill_lv-1] = skill->dbs->db[idx].itemid[skill_lv-1]; + req.amount[skill_lv-1] = skill->dbs->db[idx].amount[skill_lv-1]; break; } if (skill_id == NC_REPAIR) { @@ -14735,8 +14746,11 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 fixcast_r = max(fixcast_r, sc->data[SC_DANCE_WITH_WUG]->val4); 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, (status_get_int(bl) + status->get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] % + if (sd && skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) { + int radius_lv = pc->checkskill(sd, WL_RADIUS); + if (radius_lv) + fixcast_r = max(fixcast_r, (status_get_int(bl) + status->get_lv(bl)) / 15 + radius_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] % + } // Fixed cast non percentage bonuses if( sc->data[SC_MANDRAGORA] ) fixed += sc->data[SC_MANDRAGORA]->val1 * 500; @@ -15076,7 +15090,7 @@ void skill_repairweapon (struct map_session_data *sd, int idx) { 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, DELITEM_NORMAL, LOG_TYPE_CONSUME); // FIXME: is this the correct reason flag? clif->item_repaireffect(sd,idx,0); @@ -15145,7 +15159,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) else per += 5 * ((signed int)sd->status.job_level - 50); - pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? if (per > rnd() % 1000) { int ep = 0; logs->pick_pc(sd, LOG_TYPE_OTHER, -1, item, ditem); @@ -15153,9 +15167,9 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) logs->pick_pc(sd, LOG_TYPE_OTHER, 1, item, ditem); if(item->equip) { ep = item->equip; - pc->unequipitem(sd,idx,3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } - clif->delitem(sd,idx,1,0); + clif->delitem(sd, idx, 1, DELITEM_NORMAL); clif->upgrademessage(sd->fd, 0,item->nameid); clif->inventorylist(sd); clif->refine(sd->fd,0,idx,item->refine); @@ -15181,9 +15195,9 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) } else { item->refine = 0; if(item->equip) - pc->unequipitem(sd,idx,3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); clif->refine(sd->fd,1,idx,item->refine); - pc->delitem(sd,idx,1,0,0, LOG_TYPE_OTHER); + pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); clif->misceffect(&sd->bl,2); clif->emotion(&sd->bl, E_OMG); } @@ -15295,7 +15309,6 @@ int skill_sit (struct map_session_data *sd, int type) int range = 0, lv; nullpo_ret(sd); - if((lv = pc->checkskill(sd,RG_GANGSTER)) > 0) { flag|=1; range = skill->get_splash(RG_GANGSTER, lv); @@ -15391,7 +15404,6 @@ int skill_attack_area(struct block_list *bl, va_list ap) { 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,skill_id,skill_lv,tick,flag); @@ -15399,7 +15411,6 @@ int skill_attack_area(struct block_list *bl, va_list ap) { || !status->check_skilluse(NULL, bl, skill_id, 2)) return 0; - switch (skill_id) { case WZ_FROSTNOVA: //Skills that don't require the animation to be removed case NPC_ACIDBREATH: @@ -15486,7 +15497,6 @@ int skill_graffitiremover (struct block_list *bl, va_list ap) { struct skill_unit *su=NULL; nullpo_ret(bl); - nullpo_ret(ap); if(bl->type != BL_SKILL) return 0; @@ -15517,7 +15527,6 @@ int skill_detonator(struct block_list *bl, va_list ap) { int unit_id; nullpo_ret(bl); - nullpo_ret(ap); src = va_arg(ap,struct block_list *); if( bl->type != BL_SKILL ) @@ -15723,7 +15732,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap) { 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); + clif->skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,BDT_SPLASH); break; case UNT_MAGENTATRAP: case UNT_COBALTTRAP: @@ -15807,7 +15816,7 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce ) { //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 ); + ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 ); if( i == 8 ) wall = false; } @@ -15868,7 +15877,7 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s 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 ); + ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 ); if( i == 8 ) wall = false; } @@ -15910,7 +15919,7 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) return false; } - status->damage(bl, src, damage, 0, clif->damage(src, src, 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0); + status->damage(bl, src, damage, 0, clif->damage(src, src, 500, 500, damage, hit, (hit > 1 ? BDT_MULTIHIT : BDT_NORMAL), 0), 0); /* because damage can cancel it */ if( sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) { @@ -15929,8 +15938,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int struct skill_unit *su; nullpo_retr(NULL, group); - nullpo_retr(NULL, group->unit); // crash-protection against poor coding - nullpo_retr(NULL, su=&group->unit[idx]); + nullpo_retr(NULL, group->unit.data); // crash-protection against poor coding + nullpo_retr(NULL, su=&group->unit.data[idx]); if(!su->alive) group->alive_count++; @@ -15943,7 +15952,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int su->group=group; su->alive=1; su->val1=val1; - su->val2=val2; + su->val2 = val2; + su->prev = 0; idb_put(skill->unit_db, su->bl.id, su); map->addiddb(&su->bl); @@ -16112,8 +16122,8 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, 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->unit.data = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); + group->unit.count = count; group->alive_count = 0; group->val1 = 0; group->val2 = 0; @@ -16239,9 +16249,10 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin 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]); + if (group->unit.data != NULL) { + for (i = 0; i < group->unit.count; i++) + skill->delunit(&group->unit.data[i]); + } // clear Talkie-box string if( group->valstr != NULL ) { @@ -16250,10 +16261,10 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin } idb_remove(skill->group_db, group->group_id); - map->freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK) - group->unit=NULL; + map->freeblock(&group->unit.data[0].bl); // schedules deallocation of whole array (HACK) + group->unit.data=NULL; group->group_id=0; - group->unit_count=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 ); @@ -16337,7 +16348,7 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) { nullpo_ret(group); - if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(su->bl.m, su->bl.x, su->bl.y, CELL_CHKLANDPROTECTOR) ) + if (!(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(su->bl.m, &su->bl, su->bl.x, su->bl.y, CELL_CHKLANDPROTECTOR)) return 0; //AoE skills are ineffective. [Skotlex] if( battle->check_target(&su->bl,bl,group->target_flag) <= 0 ) @@ -16415,7 +16426,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { 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); + map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0); } skill->delunit(su); } @@ -16466,7 +16477,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { case UNT_FEINTBOMB: { struct block_list *src = map->id2bl(group->src_id); if( src ) { - map->foreachinrange(skill->area_sub, &group->unit->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id); + map->foreachinrange(skill->area_sub, &su->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id); status_change_end(src, SC__FEINTBOMB_MASTER, INVALID_TIMER); } skill->delunit(su); @@ -16537,7 +16548,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { dissonance = skill->dance_switch(su, 0); - if( su->range >= 0 && group->interval != -1 ) { + if( su->range >= 0 && group->interval != -1 && su->bl.id != su->prev) { if( battle_config.skill_wall_check ) map->foreachinshootrange(skill->unit_timer_sub_onplace, bl, su->range, group->bl_flag, bl,tick); else @@ -16553,6 +16564,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { group->bl_flag= BL_NUL; } } + if ( group->limit == group->interval ) + su->prev = su->bl.id; } if( dissonance ) skill->dance_switch(su, 1); @@ -16703,9 +16716,9 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx if (group == NULL) return 0; - if (group->unit_count<=0) + if (group->unit.count<=0) return 0; - if (group->unit==NULL) + if (group->unit.data==NULL) return 0; if (skill->get_unit_flag(group->skill_id)&UF_ENSEMBLE) @@ -16714,18 +16727,18 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx 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 = (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++) { - su1=&group->unit[i]; + for (i = 0; i < group->unit.count; i++) { + su1=&group->unit.data[i]; if (!su1->alive || su1->bl.m!=m) continue; - for(j=0;j<group->unit_count;j++) { - su2=&group->unit[j]; + for (j = 0; j < group->unit.count; j++) { + su2=&group->unit.data[j]; if (!su2->alive) continue; if (su1->bl.x+dx==su2->bl.x && su1->bl.y+dy==su2->bl.y) { @@ -16737,8 +16750,8 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx } } j = 0; - for (i=0;i<group->unit_count;i++) { - su1=&group->unit[i]; + for (i = 0; i < group->unit.count; i++) { + su1=&group->unit.data[i]; if (!su1->alive) continue; if (!(m_flag[i]&0x2)) { @@ -16755,11 +16768,11 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx 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) + for (; j < group->unit.count; j++) { + if (m_flag[j]!=2 || !group->unit.data[j].alive) continue; //Move to where this cell would had moved. - su2 = &group->unit[j]; + su2 = &group->unit.data[j]; map->moveblock(&su1->bl, su2->bl.x+dx, su2->bl.y+dy, tick); j++; //Skip this cell as we have used it. break; @@ -16793,9 +16806,9 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, 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) + if(skill->dbs->produce_db[i].nameid == nameid ){ + if((j=skill->dbs->produce_db[i].req_skill)>0 && + pc->checkskill(sd,j) < skill->dbs->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 @@ -16813,22 +16826,22 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, if(trigger>=0){ if(trigger>20) { // Non-weapon, non-food item (itemlv must match) - if(skill->produce_db[i].itemlv!=trigger) + if(skill->dbs->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) + if(skill->dbs->produce_db[i].itemlv<=10 || skill->dbs->produce_db[i].itemlv>20) return 0; } else { // Weapon (itemlv must be higher or equal) - if(skill->produce_db[i].itemlv>trigger) + if(skill->dbs->produce_db[i].itemlv>trigger) return 0; } } for (j = 0; j < MAX_PRODUCE_RESOURCE; j++) { - int id = skill->produce_db[i].mat_id[j]; + int id = skill->dbs->produce_db[i].mat_id[j]; if (id <= 0) continue; - if (skill->produce_db[i].mat_amount[j] <= 0) { + if (skill->dbs->produce_db[i].mat_amount[j] <= 0) { if (pc->search_inventory(sd,id) == INDEX_NOT_FOUND) return 0; } else { @@ -16836,7 +16849,7 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, 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]) + if(x<qty*skill->dbs->produce_db[i].mat_amount[j]) return 0; } } @@ -16867,7 +16880,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, qty = 1; if (!skill_id) //A skill can be specified for some override cases. - skill_id = skill->produce_db[idx].req_skill; + skill_id = skill->dbs->produce_db[idx].req_skill; if( skill_id == GC_RESEARCHNEWPOISON ) skill_id = GC_CREATENEWPOISON; @@ -16884,12 +16897,12 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, if (j == INDEX_NOT_FOUND) continue; if( slot[i]==ITEMID_STAR_CRUMB ) { - pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 1, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? sc++; } if( slot[i] >= ITEMID_FLAME_HEART && slot[i] <= ITEMID_GREAT_NATURE && ele == 0 ) { static const int ele_table[4]={3,1,4,2}; - pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 1, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? ele=ele_table[slot[i]-994]; } } @@ -16906,7 +16919,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, 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); + clif->msgtable(sd, MSG_RUNE_STONE_MAX_AMOUNT); return 0; } else { /** @@ -16924,10 +16937,10 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, for(i=0;i<MAX_PRODUCE_RESOURCE;i++){ int j,id,x; - if( (id=skill->produce_db[idx].mat_id[i]) <= 0 ) + if( (id=skill->dbs->produce_db[idx].mat_id[i]) <= 0 ) continue; num++; - x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill->produce_db[idx].mat_amount[i]; + x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill->dbs->produce_db[idx].mat_amount[i]; do{ int y=0; j = pc->search_inventory(sd,id); @@ -16935,7 +16948,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, if (j != INDEX_NOT_FOUND) { y = sd->status.inventory[j].amount; if(y>x)y=x; - pc->delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, y, 0, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? } else ShowError("skill_produce_mix: material item error\n"); @@ -17068,8 +17081,8 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, 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; + if( skill->dbs->changematerial_db[i].itemid == nameid ){ + make_per = skill->dbs->changematerial_db[i].rate * 10; break; } break; @@ -17181,7 +17194,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, + 20 * (sd->status.base_level + 1) + 20 * (st->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) + - 400 * (skill->dbs->produce_db[idx].itemlv - 11 + 1) - 10 * (100 - st->luk + 1) - 500 * (num - 1) - 100 * (rnd()%4 + 1); @@ -17212,7 +17225,6 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, 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)); @@ -17337,11 +17349,11 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int 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) + if( skill->dbs->produce_db[idx].itemlv > 10 && skill->dbs->produce_db[idx].itemlv <= 20) { //Cooking items. clif->specialeffect(&sd->bl, 608, AREA); if( sd->cook_mastery < 1999 ) - pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->produce_db[idx].itemlv - 11) / 2 ) ) * 5); + pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->dbs->produce_db[idx].itemlv - 11) / 2 ) ) * 5); } break; } @@ -17349,13 +17361,13 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, 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 ){ + if( skill->dbs->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( rnd()%1000 < skill->dbs->changematerial_db[i].qty_rate[j] ){ + tmp_item.amount = qty * skill->dbs->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); + map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } k++; } @@ -17363,16 +17375,16 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, break; } if( k ){ - clif->msg_skill(sd,skill_id,0x627); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS); 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); + map->addflooritem(&sd->bl, &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); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS); return 1; } } @@ -17429,22 +17441,22 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, 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); + map->addflooritem(&sd->bl, &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); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE); } break; case GN_MAKEBOMB: case GN_S_PHARMACY: case GN_CHANGEMATERIAL: - clif->msg_skill(sd,skill_id,0x628); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE); break; default: - if( skill->produce_db[idx].itemlv > 10 && skill->produce_db[idx].itemlv <= 20 ) + if( skill->dbs->produce_db[idx].itemlv > 10 && skill->dbs->produce_db[idx].itemlv <= 20 ) { //Cooking items. clif->specialeffect(&sd->bl, 609, AREA); if( sd->cook_mastery > 0 ) - pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); + pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); } } } @@ -17462,7 +17474,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) return 1; for(i=0;i<MAX_SKILL_ARROW_DB;i++) - if(nameid == skill->arrow_db[i].nameid) { + if(nameid == skill->dbs->arrow_db[i].nameid) { index = i; break; } @@ -17470,12 +17482,12 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) if(index < 0 || (j = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND) return 1; - pc->delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 0, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? 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]; + tmp_item.nameid = skill->dbs->arrow_db[index].cre_id[i]; + tmp_item.amount = skill->dbs->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; @@ -17486,7 +17498,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) 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); + map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } @@ -17496,7 +17508,7 @@ 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)) == INDEX_NOT_FOUND || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) { + if (nameid <= 0 || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND || pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME)) { clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); return 0; } @@ -17546,22 +17558,22 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) { } } - int skill_magicdecoy(struct map_session_data *sd, int nameid) { int x, y, i, class_, skill_id; struct mob_data *md; nullpo_ret(sd); skill_id = sd->menuskill_val; - if (nameid <= 0 || !itemdb_is_element(nameid) || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND - || !skill_id || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) + if (nameid <= 0 || !itemdb_is_element(nameid) || !skill_id + || (i = pc->search_inventory(sd, nameid)) == INDEX_NOT_FOUND + || pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) != 0 ) { clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); return 0; } // Spawn Position - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); // FIXME: is this intended to be there twice? x = sd->sc.comet_x; y = sd->sc.comet_y; sd->sc.comet_x = sd->sc.comet_y = 0; @@ -17569,7 +17581,6 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { class_ = (nameid == ITEMID_BOODY_RED || nameid == ITEMID_CRYSTAL_BLUE) ? 2043 + nameid - ITEMID_BOODY_RED : (nameid == ITEMID_WIND_OF_VERDURE) ? 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; @@ -17601,10 +17612,10 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { return 0; } - ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill->spellbook_db[i].nameid == nameid); // Search for information of this item + ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill->dbs->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].skill_id)) ) + if( !pc->checkskill(sd, (skill_id = skill->dbs->spellbook_db[i].skill_id)) ) { // User don't know the skill sc_start(&sd->bl, &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); @@ -17612,7 +17623,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { } max_preserve = 4 * pc->checkskill(sd, WL_FREEZE_SP) + (status_get_int(&sd->bl) + sd->status.base_level) / 10; - point = skill->spellbook_db[i].point; + point = skill->dbs->spellbook_db[i].point; if( sc && sc->data[SC_READING_SB] ) { if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) { @@ -17697,7 +17708,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, return 1; } - if( pc->delitem(sd,idx,del_amount,0,1,LOG_TYPE_CONSUME) ) { + if( pc->delitem(sd, idx, del_amount, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME) ) { clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -17708,7 +17719,6 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, return 1; } - memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = product; tmp_item.amount = add_amount; @@ -17718,7 +17728,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, int flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME); if (flag) { 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); + map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } @@ -17735,23 +17745,23 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite // Search for objects that can be created. for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { - if( skill->produce_db[i].itemlv == 26 ) { + if( skill->dbs->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 ) { + if( skill->dbs->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); + clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NEED_IDENTIFY); 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 + if( nameid == skill->dbs->produce_db[i].mat_id[j] && (amount-p*skill->dbs->produce_db[i].mat_amount[j]) >= skill->dbs->produce_db[i].mat_amount[j] + && (amount-p*skill->dbs->produce_db[i].mat_amount[j])%skill->dbs->produce_db[i].mat_amount[j] == 0 ) // must be in exact amount c++; // match } } @@ -17762,14 +17772,14 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite } while(n == j && c == n); p--; if ( p > 0 ) { - skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->produce_db[i].nameid,0,0,0,p); + skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->dbs->produce_db[i].nameid,0,0,0,p); return 1; } } } if( p == 0) - clif->msg_skill(sd,GN_CHANGEMATERIAL,0x623); + clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NOT_FOUND); return 0; } @@ -17784,7 +17794,7 @@ int skill_destroy_trap(struct block_list *bl, va_list ap) { nullpo_ret(su); tick = va_arg(ap, int64); - if (su->alive && (sg = su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP) { + if (su->alive && (sg = su->group) != NULL && skill->get_inf2(sg->skill_id)&INF2_TRAP) { switch( sg->unit_id ) { case UNT_CLAYMORETRAP: case UNT_FIRINGTRAP: @@ -17892,6 +17902,9 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) } if( i != cd->cursor ) {/* duplicate, update necessary */ + // Don't do anything if there's already a tick longer than the incoming one + if (DIFF_TICK32(cd->entry[i]->started + cd->entry[i]->duration, now) > tick) + return 0; cd->entry[i]->duration = tick; #if PACKETVER >= 20120604 cd->entry[i]->total = tick; @@ -17954,7 +17967,6 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { / uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, hd); - if (idx == 0) return -1; @@ -18074,26 +18086,26 @@ void skill_init_unit_layout (void) int i,j,pos = 0; //when != it was already cleared during skill_defaults() no need to repeat - if( runflag == MAPSERVER_ST_RUNNING ) - memset(skill->unit_layout,0,sizeof(skill->unit_layout)); + if( core->runflag == MAPSERVER_ST_RUNNING ) + memset(skill->dbs->unit_layout, 0, sizeof(skill->dbs->unit_layout)); // standard square layouts go first for (i=0; i<=MAX_SQUARE_LAYOUT; i++) { int size = i*2+1; - skill->unit_layout[i].count = size*size; + skill->dbs->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); + skill->dbs->unit_layout[i].dx[j] = (j%size-i); + skill->dbs->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) + if (!skill->dbs->db[i].unit_id[0] || skill->dbs->db[i].unit_layout_type[0] != -1) continue; - switch (skill->db[i].nameid) { + switch (skill->dbs->db[i].nameid) { case MG_FIREWALL: case WZ_ICEWALL: case WL_EARTHSTRAIN://Warlock @@ -18107,9 +18119,9 @@ void skill_init_unit_layout (void) 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)); + skill->dbs->unit_layout[pos].count = 21; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PR_MAGNUS: { @@ -18121,18 +18133,18 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 33; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + skill->dbs->unit_layout[pos].count = 5; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case CR_GRANDCROSS: @@ -18145,9 +18157,9 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 29; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PF_FOGWALL: { @@ -18155,9 +18167,9 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 15; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PA_GOSPEL: { @@ -18171,17 +18183,17 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 33; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + skill->dbs->unit_layout[pos].count = 24; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case NJ_TATAMIGAESHI: { @@ -18196,29 +18208,29 @@ void skill_init_unit_layout (void) 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; + skill->dbs->unit_layout[pos].count = 4; + memcpy(skill->dbs->unit_layout[pos].dx,dx1,sizeof(dx1)); + memcpy(skill->dbs->unit_layout[pos].dy,dy1,sizeof(dy1)); + skill->dbs->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; + skill->dbs->unit_layout[pos].count = 8; + memcpy(skill->dbs->unit_layout[pos].dx,dx2,sizeof(dx2)); + memcpy(skill->dbs->unit_layout[pos].dy,dy2,sizeof(dy2)); + skill->dbs->db[i].unit_layout_type[j] = pos; + skill->dbs->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; + skill->dbs->unit_layout[pos].count = 12; + memcpy(skill->dbs->unit_layout[pos].dx,dx3,sizeof(dx3)); + memcpy(skill->dbs->unit_layout[pos].dy,dy3,sizeof(dy3)); + skill->dbs->db[i].unit_layout_type[j] = pos; + skill->dbs->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; + skill->dbs->db[i].unit_layout_type[j] = pos; //Skip, this way the check below will fail and continue to the next skill. pos++; } @@ -18226,27 +18238,27 @@ void skill_init_unit_layout (void) 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)); + skill->dbs->unit_layout[pos].count = 16; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case 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)); + skill->dbs->unit_layout[pos].count = 8; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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) + if (!skill->dbs->unit_layout[pos].count) continue; for (j=0;j<MAX_SKILL_LEVEL;j++) - skill->db[i].unit_layout_type[j] = pos; + skill->dbs->db[i].unit_layout_type[j] = pos; pos++; } @@ -18254,60 +18266,60 @@ void skill_init_unit_layout (void) skill->firewall_unit_pos = pos; for (i=0;i<8;i++) { if (i&1) { - skill->unit_layout[pos].count = 5; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } else { - skill->unit_layout[pos].count = 3; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } pos++; } skill->icewall_unit_pos = pos; for (i=0;i<8;i++) { - skill->unit_layout[pos].count = 5; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } pos++; @@ -18315,15 +18327,15 @@ void skill_init_unit_layout (void) skill->earthstrain_unit_pos = pos; for( i = 0; i < 8; i++ ) { // For each Direction - skill->unit_layout[pos].count = 15; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case 2: @@ -18331,8 +18343,8 @@ void skill_init_unit_layout (void) { 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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; } @@ -18579,36 +18591,36 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->db[idx].nameid = skill_id; - skill->split_atoi(split[1],skill->db[idx].range); - skill->db[idx].hit = atoi(split[2]); - skill->db[idx].inf = atoi(split[3]); - skill->split_atoi(split[4],skill->db[idx].element); - skill->db[idx].nk = (int)strtol(split[5], NULL, 0); - skill->split_atoi(split[6],skill->db[idx].splash); - skill->db[idx].max = atoi(split[7]); - skill->split_atoi(split[8],skill->db[idx].num); + skill->dbs->db[idx].nameid = skill_id; + skill->split_atoi(split[1],skill->dbs->db[idx].range); + skill->dbs->db[idx].hit = atoi(split[2]); + skill->dbs->db[idx].inf = atoi(split[3]); + skill->split_atoi(split[4],skill->dbs->db[idx].element); + skill->dbs->db[idx].nk = (int)strtol(split[5], NULL, 0); + skill->split_atoi(split[6],skill->dbs->db[idx].splash); + skill->dbs->db[idx].max = atoi(split[7]); + skill->split_atoi(split[8],skill->dbs->db[idx].num); if( strcmpi(split[9],"yes") == 0 ) - skill->db[idx].castcancel = 1; + skill->dbs->db[idx].castcancel = 1; else - skill->db[idx].castcancel = 0; - skill->db[idx].cast_def_rate = atoi(split[10]); - skill->db[idx].inf2 = (int)strtol(split[11], NULL, 0); - skill->split_atoi(split[12],skill->db[idx].maxcount); + skill->dbs->db[idx].castcancel = 0; + skill->dbs->db[idx].cast_def_rate = atoi(split[10]); + skill->dbs->db[idx].inf2 = (int)strtol(split[11], NULL, 0); + skill->split_atoi(split[12],skill->dbs->db[idx].maxcount); if( strcmpi(split[13],"weapon") == 0 ) - skill->db[idx].skill_type = BF_WEAPON; + skill->dbs->db[idx].skill_type = BF_WEAPON; else if( strcmpi(split[13],"magic") == 0 ) - skill->db[idx].skill_type = BF_MAGIC; + skill->dbs->db[idx].skill_type = BF_MAGIC; else if( strcmpi(split[13],"misc") == 0 ) - skill->db[idx].skill_type = BF_MISC; + skill->dbs->db[idx].skill_type = BF_MISC; else - skill->db[idx].skill_type = 0; - skill->split_atoi(split[14],skill->db[idx].blewcount); - safestrncpy(skill->db[idx].name, trim(split[15]), sizeof(skill->db[idx].name)); - safestrncpy(skill->db[idx].desc, trim(split[16]), sizeof(skill->db[idx].desc)); - strdb_iput(skill->name2id_db, skill->db[idx].name, skill_id); - script->set_constant2(skill->db[idx].name,(int)skill_id,0); + skill->dbs->db[idx].skill_type = 0; + skill->split_atoi(split[14],skill->dbs->db[idx].blewcount); + safestrncpy(skill->dbs->db[idx].name, trim(split[15]), sizeof(skill->dbs->db[idx].name)); + safestrncpy(skill->dbs->db[idx].desc, trim(split[16]), sizeof(skill->dbs->db[idx].desc)); + strdb_iput(skill->name2id_db, skill->dbs->db[idx].name, skill_id); + script->set_constant2(skill->dbs->db[idx].name,(int)skill_id,0); return true; } @@ -18623,22 +18635,22 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].hp); - skill->split_atoi(split[2],skill->db[idx].mhp); - skill->split_atoi(split[3],skill->db[idx].sp); - skill->split_atoi(split[4],skill->db[idx].hp_rate); - skill->split_atoi(split[5],skill->db[idx].sp_rate); - skill->split_atoi(split[6],skill->db[idx].zeny); + skill->split_atoi(split[1],skill->dbs->db[idx].hp); + skill->split_atoi(split[2],skill->dbs->db[idx].mhp); + skill->split_atoi(split[3],skill->dbs->db[idx].sp); + skill->split_atoi(split[4],skill->dbs->db[idx].hp_rate); + skill->split_atoi(split[5],skill->dbs->db[idx].sp_rate); + skill->split_atoi(split[6],skill->dbs->db[idx].zeny); //Which 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[idx].weapon = 0; + skill->dbs->db[idx].weapon = 0; break; } else - skill->db[idx].weapon |= 1<<l; + skill->dbs->db[idx].weapon |= 1<<l; p = strchr(p,':'); if(!p) break; @@ -18650,49 +18662,49 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) { for( j = 0; j < 32; j++ ) { int l = atoi(p); if( l == 99 ) { // Any ammo type - skill->db[idx].ammo = 0xFFFFFFFF; + skill->dbs->db[idx].ammo = 0xFFFFFFFF; break; } else if( l ) // 0 stands for no requirement - skill->db[idx].ammo |= 1<<l; + skill->dbs->db[idx].ammo |= 1<<l; p = strchr(p,':'); if( !p ) break; p++; } - skill->split_atoi(split[9],skill->db[idx].ammo_qty); - - if( strcmpi(split[10],"hiding") == 0 ) skill->db[idx].state = ST_HIDING; - else if( strcmpi(split[10],"cloaking") == 0 ) skill->db[idx].state = ST_CLOAKING; - else if( strcmpi(split[10],"hidden") == 0 ) skill->db[idx].state = ST_HIDDEN; - else if( strcmpi(split[10],"riding") == 0 ) skill->db[idx].state = ST_RIDING; - else if( strcmpi(split[10],"falcon") == 0 ) skill->db[idx].state = ST_FALCON; - else if( strcmpi(split[10],"cart") == 0 ) skill->db[idx].state = ST_CART; - else if( strcmpi(split[10],"shield") == 0 ) skill->db[idx].state = ST_SHIELD; - else if( strcmpi(split[10],"sight") == 0 ) skill->db[idx].state = ST_SIGHT; - else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->db[idx].state = ST_EXPLOSIONSPIRITS; - else if( strcmpi(split[10],"cartboost") == 0 ) skill->db[idx].state = ST_CARTBOOST; - else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->db[idx].state = ST_RECOV_WEIGHT_RATE; - else if( strcmpi(split[10],"move_enable") == 0 ) skill->db[idx].state = ST_MOVE_ENABLE; - else if( strcmpi(split[10],"water") == 0 ) skill->db[idx].state = ST_WATER; - else if( strcmpi(split[10],"dragon") == 0 ) skill->db[idx].state = ST_RIDINGDRAGON; - else if( strcmpi(split[10],"warg") == 0 ) skill->db[idx].state = ST_WUG; - else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->db[idx].state = ST_RIDINGWUG; - else if( strcmpi(split[10],"mado") == 0 ) skill->db[idx].state = ST_MADO; - else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->db[idx].state = ST_ELEMENTALSPIRIT; - else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->db[idx].state = ST_POISONINGWEAPON; - else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->db[idx].state = ST_ROLLINGCUTTER; - else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->db[idx].state = ST_MH_FIGHTING; - else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->db[idx].state = ST_MH_GRAPPLING; - else if( strcmpi(split[10],"peco") == 0 ) skill->db[idx].state = ST_PECO; + skill->split_atoi(split[9],skill->dbs->db[idx].ammo_qty); + + if( strcmpi(split[10],"hiding") == 0 ) skill->dbs->db[idx].state = ST_HIDING; + else if( strcmpi(split[10],"cloaking") == 0 ) skill->dbs->db[idx].state = ST_CLOAKING; + else if( strcmpi(split[10],"hidden") == 0 ) skill->dbs->db[idx].state = ST_HIDDEN; + else if( strcmpi(split[10],"riding") == 0 ) skill->dbs->db[idx].state = ST_RIDING; + else if( strcmpi(split[10],"falcon") == 0 ) skill->dbs->db[idx].state = ST_FALCON; + else if( strcmpi(split[10],"cart") == 0 ) skill->dbs->db[idx].state = ST_CART; + else if( strcmpi(split[10],"shield") == 0 ) skill->dbs->db[idx].state = ST_SHIELD; + else if( strcmpi(split[10],"sight") == 0 ) skill->dbs->db[idx].state = ST_SIGHT; + else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->dbs->db[idx].state = ST_EXPLOSIONSPIRITS; + else if( strcmpi(split[10],"cartboost") == 0 ) skill->dbs->db[idx].state = ST_CARTBOOST; + else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->dbs->db[idx].state = ST_RECOV_WEIGHT_RATE; + else if( strcmpi(split[10],"move_enable") == 0 ) skill->dbs->db[idx].state = ST_MOVE_ENABLE; + else if( strcmpi(split[10],"water") == 0 ) skill->dbs->db[idx].state = ST_WATER; + else if( strcmpi(split[10],"dragon") == 0 ) skill->dbs->db[idx].state = ST_RIDINGDRAGON; + else if( strcmpi(split[10],"warg") == 0 ) skill->dbs->db[idx].state = ST_WUG; + else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->dbs->db[idx].state = ST_RIDINGWUG; + else if( strcmpi(split[10],"mado") == 0 ) skill->dbs->db[idx].state = ST_MADO; + else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->dbs->db[idx].state = ST_ELEMENTALSPIRIT; + else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->dbs->db[idx].state = ST_POISONINGWEAPON; + else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->dbs->db[idx].state = ST_ROLLINGCUTTER; + else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->dbs->db[idx].state = ST_MH_FIGHTING; + else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->dbs->db[idx].state = ST_MH_GRAPPLING; + else if( strcmpi(split[10],"peco") == 0 ) skill->dbs->db[idx].state = ST_PECO; /** * Unknown or no state **/ - else skill->db[idx].state = ST_NONE; + else skill->dbs->db[idx].state = ST_NONE; - skill->split_atoi(split[11],skill->db[idx].spiritball); + skill->split_atoi(split[11],skill->dbs->db[idx].spiritball); for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) { - skill->db[idx].itemid[j] = atoi(split[12+ 2*j]); - skill->db[idx].amount[j] = atoi(split[13+ 2*j]); + skill->dbs->db[idx].itemid[j] = atoi(split[12+ 2*j]); + skill->dbs->db[idx].amount[j] = atoi(split[13+ 2*j]); } return true; @@ -18705,14 +18717,14 @@ bool skill_parse_row_castdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].cast); - skill->split_atoi(split[2],skill->db[idx].delay); - skill->split_atoi(split[3],skill->db[idx].walkdelay); - skill->split_atoi(split[4],skill->db[idx].upkeep_time); - skill->split_atoi(split[5],skill->db[idx].upkeep_time2); - skill->split_atoi(split[6],skill->db[idx].cooldown); + skill->split_atoi(split[1],skill->dbs->db[idx].cast); + skill->split_atoi(split[2],skill->dbs->db[idx].delay); + skill->split_atoi(split[3],skill->dbs->db[idx].walkdelay); + skill->split_atoi(split[4],skill->dbs->db[idx].upkeep_time); + skill->split_atoi(split[5],skill->dbs->db[idx].upkeep_time2); + skill->split_atoi(split[6],skill->dbs->db[idx].cooldown); #ifdef RENEWAL_CAST - skill->split_atoi(split[7],skill->db[idx].fixed_cast); + skill->split_atoi(split[7],skill->dbs->db[idx].fixed_cast); #endif return true; } @@ -18724,9 +18736,9 @@ bool skill_parse_row_castnodexdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].castnodex); + skill->split_atoi(split[1],skill->dbs->db[idx].castnodex); if( split[2] ) // optional column - skill->split_atoi(split[2],skill->db[idx].delaynodex); + skill->split_atoi(split[2],skill->dbs->db[idx].delaynodex); return true; } @@ -18738,37 +18750,37 @@ bool skill_parse_row_unitdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16); - skill->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16); - skill->split_atoi(split[3],skill->db[idx].unit_layout_type); - skill->split_atoi(split[4],skill->db[idx].unit_range); - skill->db[idx].unit_interval = atoi(split[5]); - - if( strcmpi(split[6],"noenemy")==0 ) skill->db[idx].unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"friend")==0 ) skill->db[idx].unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"party")==0 ) skill->db[idx].unit_target = BCT_PARTY; - else if( strcmpi(split[6],"ally")==0 ) skill->db[idx].unit_target = BCT_PARTY|BCT_GUILD; - else if( strcmpi(split[6],"guild")==0 ) skill->db[idx].unit_target = BCT_GUILD; - else if( strcmpi(split[6],"all")==0 ) skill->db[idx].unit_target = BCT_ALL; - else if( strcmpi(split[6],"enemy")==0 ) skill->db[idx].unit_target = BCT_ENEMY; - else if( strcmpi(split[6],"self")==0 ) skill->db[idx].unit_target = BCT_SELF; - else if( strcmpi(split[6],"sameguild")==0 ) skill->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD; - else if( strcmpi(split[6],"noone")==0 ) skill->db[idx].unit_target = BCT_NOONE; - else skill->db[idx].unit_target = (int)strtol(split[6],NULL,16); - - skill->db[idx].unit_flag = (int)strtol(split[7],NULL,16); - - if (skill->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) - skill->db[idx].unit_target = BCT_NOENEMY; + skill->dbs->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16); + skill->dbs->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16); + skill->split_atoi(split[3],skill->dbs->db[idx].unit_layout_type); + skill->split_atoi(split[4],skill->dbs->db[idx].unit_range); + skill->dbs->db[idx].unit_interval = atoi(split[5]); + + if( strcmpi(split[6],"noenemy")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY; + else if( strcmpi(split[6],"ally")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY|BCT_GUILD; + else if( strcmpi(split[6],"guild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD; + else if( strcmpi(split[6],"all")==0 ) skill->dbs->db[idx].unit_target = BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill->dbs->db[idx].unit_target = BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill->dbs->db[idx].unit_target = BCT_SELF; + else if( strcmpi(split[6],"sameguild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD; + else if( strcmpi(split[6],"noone")==0 ) skill->dbs->db[idx].unit_target = BCT_NOONE; + else skill->dbs->db[idx].unit_target = (int)strtol(split[6],NULL,16); + + skill->dbs->db[idx].unit_flag = (int)strtol(split[7],NULL,16); + + if (skill->dbs->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + skill->dbs->db[idx].unit_target = BCT_NOENEMY; //By default, target just characters. - skill->db[idx].unit_target |= BL_CHAR; - if (skill->db[idx].unit_flag&UF_NOPC) - skill->db[idx].unit_target &= ~BL_PC; - if (skill->db[idx].unit_flag&UF_NOMOB) - skill->db[idx].unit_target &= ~BL_MOB; - if (skill->db[idx].unit_flag&UF_SKILL) - skill->db[idx].unit_target |= BL_SKILL; + skill->dbs->db[idx].unit_target |= BL_CHAR; + if (skill->dbs->db[idx].unit_flag&UF_NOPC) + skill->dbs->db[idx].unit_target &= ~BL_PC; + if (skill->dbs->db[idx].unit_flag&UF_NOMOB) + skill->dbs->db[idx].unit_target &= ~BL_MOB; + if (skill->dbs->db[idx].unit_flag&UF_SKILL) + skill->dbs->db[idx].unit_target |= BL_SKILL; return true; } @@ -18781,14 +18793,14 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) { 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->dbs->produce_db[current].nameid = i; + skill->dbs->produce_db[current].itemlv = atoi(split[1]); + skill->dbs->produce_db[current].req_skill = atoi(split[2]); + skill->dbs->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]); + skill->dbs->produce_db[current].mat_id[y] = atoi(split[x]); + skill->dbs->produce_db[current].mat_amount[y] = atoi(split[x+1]); } return true; @@ -18802,11 +18814,11 @@ bool skill_parse_row_createarrowdb(char* split[], int columns, int current) { if( !i ) return false; - skill->arrow_db[current].nameid = i; + skill->dbs->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]); + skill->dbs->arrow_db[current].cre_id[y] = atoi(split[x]); + skill->dbs->arrow_db[current].cre_amount[y] = atoi(split[x+1]); } return true; @@ -18825,9 +18837,9 @@ bool skill_parse_row_spellbookdb(char* split[], int columns, int current) { if( points < 1 ) ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill->get_name(skill_id)); else { - skill->spellbook_db[current].skill_id = skill_id; - skill->spellbook_db[current].point = points; - skill->spellbook_db[current].nameid = nameid; + skill->dbs->spellbook_db[current].skill_id = skill_id; + skill->dbs->spellbook_db[current].point = points; + skill->dbs->spellbook_db[current].nameid = nameid; return true; } @@ -18855,8 +18867,8 @@ bool skill_parse_row_improvisedb(char* split[], int columns, int current) { ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB); return false; } - skill->improvise_db[current].skill_id = skill_id; - skill->improvise_db[current].per = j; // Still need confirm it. + skill->dbs->improvise_db[current].skill_id = skill_id; + skill->dbs->improvise_db[current].per = j; // Still need confirm it. return true; } @@ -18873,7 +18885,7 @@ bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { return false; } - skill->magicmushroom_db[current].skill_id = skill_id; + skill->dbs->magicmushroom_db[current].skill_id = skill_id; return true; } @@ -18884,12 +18896,11 @@ bool skill_parse_row_reproducedb(char* split[], int column, int current) { if( !idx ) return false; - skill->reproduce_db[idx] = true; + skill->dbs->reproduce_db[idx] = true; return true; } - bool skill_parse_row_abradb(char* split[], int columns, int current) { // skill_id,DummyName,RequiredHocusPocusLevel,Rate uint16 skill_id = atoi(split[0]); @@ -18902,9 +18913,9 @@ bool skill_parse_row_abradb(char* split[], int columns, int current) { return false; } - skill->abra_db[current].skill_id = skill_id; - skill->abra_db[current].req_lv = atoi(split[2]); - skill->abra_db[current].per = atoi(split[3]); + skill->dbs->abra_db[current].skill_id = skill_id; + skill->dbs->abra_db[current].req_lv = atoi(split[2]); + skill->dbs->abra_db[current].per = atoi(split[3]); return true; } @@ -18916,8 +18927,8 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { int x,y; for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){ - if( skill->produce_db[x].nameid == skill_id ) - if( skill->produce_db[x].req_skill == GN_CHANGEMATERIAL ) + if( skill->dbs->produce_db[x].nameid == skill_id ) + if( skill->dbs->produce_db[x].req_skill == GN_CHANGEMATERIAL ) break; } @@ -18931,12 +18942,12 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { return false; } - skill->changematerial_db[current].itemid = skill_id; - skill->changematerial_db[current].rate = j; + skill->dbs->changematerial_db[current].itemid = skill_id; + skill->dbs->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]); + skill->dbs->changematerial_db[current].qty[y] = atoi(split[x]); + skill->dbs->changematerial_db[current].qty_rate[y] = atoi(split[x+1]); } return true; @@ -18959,22 +18970,13 @@ void skill_readdb(bool minimal) { db_clear(skill->name2id_db); /* when != it was called during init and this procedure was already performed by skill_defaults() */ - if( runflag == MAPSERVER_ST_RUNNING ) { - memset(skill->db,0,sizeof(skill->db) - + sizeof(skill->produce_db) - + sizeof(skill->arrow_db) - + sizeof(skill->abra_db) - + sizeof(skill->magicmushroom_db) - + sizeof(skill->improvise_db) - + sizeof(skill->changematerial_db) - + sizeof(skill->spellbook_db) - + sizeof(skill->reproduce_db) - ); + if( core->runflag == MAPSERVER_ST_RUNNING ) { + memset(ZEROED_BLOCK_POS(skill->dbs), 0, ZEROED_BLOCK_SIZE(skill->dbs)); } // 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)); + safestrncpy(skill->dbs->db[0].name, "UNKNOWN_SKILL", sizeof(skill->dbs->db[0].name)); + safestrncpy(skill->dbs->db[0].desc, "Unknown Skill", sizeof(skill->dbs->db[0].desc)); #ifdef ENABLE_CASE_CHECK script->parser_current_file = DBPATH"skill_db.txt"; @@ -19092,6 +19094,8 @@ void skill_defaults(void) { const int skill_deluge_eff[5] = { 5, 9, 12, 14, 15 }; skill = &skill_s; + skill->dbs = &skilldbs; + skill->init = do_init_skill; skill->final = do_final_skill; skill->reload = skill_reload; @@ -19108,18 +19112,10 @@ void skill_defaults(void) { skill->timer_ers = NULL; skill->cd_ers = NULL; skill->cd_entry_ers = NULL; - /* one huge 0, follows skill.h order */ - memset(skill->db,0,sizeof(skill->db) - + sizeof(skill->produce_db) - + sizeof(skill->arrow_db) - + sizeof(skill->abra_db) - + sizeof(skill->magicmushroom_db) - + sizeof(skill->improvise_db) - + sizeof(skill->changematerial_db) - + sizeof(skill->spellbook_db) - + sizeof(skill->reproduce_db) - + sizeof(skill->unit_layout) - ); + + memset(ZEROED_BLOCK_POS(skill->dbs), 0, ZEROED_BLOCK_SIZE(skill->dbs)); + memset(skill->dbs->unit_layout, 0, sizeof(skill->dbs->unit_layout)); + /* */ memcpy(skill->enchant_eff, skill_enchant_eff, sizeof(skill->enchant_eff)); memcpy(skill->deluge_eff, skill_deluge_eff, sizeof(skill->deluge_eff)); diff --git a/src/map/skill.h b/src/map/skill.h index b598b91c8..b8be9ac8f 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -5,13 +5,11 @@ #ifndef MAP_SKILL_H #define MAP_SKILL_H -#include "../config/core.h" // RENEWAL_CAST - -#include "map.h" // struct block_list -#include "status.h" // enum sc_type -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // MAX_SKILL, struct square +#include "map/map.h" // struct block_list +#include "map/status.h" // enum sc_type +#include "common/hercules.h" +#include "common/db.h" +#include "common/mmo.h" // MAX_SKILL, struct square /** * Declarations @@ -1714,9 +1712,12 @@ struct skill_unit_group { char *valstr; int unit_id; int group_id; - int unit_count,alive_count; + int alive_count; int item_id; //store item used. - struct skill_unit *unit; + struct { + int count; + struct skill_unit *data; + } unit; struct { unsigned ammo_consume : 1; unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble @@ -1732,6 +1733,7 @@ struct skill_unit { int limit; int val1,val2; short alive,range; + int prev; }; struct skill_unit_group_tickset { @@ -1813,6 +1815,21 @@ struct s_skill_spellbook_db { typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); +struct s_skill_dbs { +BEGIN_ZEROED_BLOCK; // This block will be zeroed in skill_defaults() as well as skill_readdb() + struct s_skill_db db[MAX_SKILL_DB]; + struct s_skill_produce_db produce_db[MAX_SKILL_PRODUCE_DB]; + struct s_skill_arrow_db arrow_db[MAX_SKILL_ARROW_DB]; + struct s_skill_abra_db abra_db[MAX_SKILL_ABRA_DB]; + struct s_skill_magicmushroom_db magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; + struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB]; + struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB]; + struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB]; + bool reproduce_db[MAX_SKILL_DB]; +END_ZEROED_BLOCK; + struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT]; +}; + /** * Skill.c Interface **/ @@ -1834,16 +1851,7 @@ struct skill_interface { struct eri *cd_ers; // ERS Storage for skill cool down managers [Ind/Hercules] struct eri *cd_entry_ers; // ERS Storage for skill cool down entries [Ind/Hercules] /* */ - struct s_skill_db db[MAX_SKILL_DB]; - struct s_skill_produce_db produce_db[MAX_SKILL_PRODUCE_DB]; - struct s_skill_arrow_db arrow_db[MAX_SKILL_ARROW_DB]; - struct s_skill_abra_db abra_db[MAX_SKILL_ABRA_DB]; - struct s_skill_magicmushroom_db magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; - struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB]; - struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB]; - struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB]; - bool reproduce_db[MAX_SKILL_DB]; - struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT]; + struct s_skill_dbs *dbs; /* */ int enchant_eff[5]; int deluge_eff[5]; @@ -2077,10 +2085,10 @@ struct skill_interface { void (*get_requirement_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req); }; -struct skill_interface *skill; - #ifdef HERCULES_CORE void skill_defaults(void); #endif // HERCULES_CORE +HPShared struct skill_interface *skill; + #endif /* MAP_SKILL_H */ diff --git a/src/map/status.c b/src/map/status.c index 685febcdb..3ba80e531 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4,9 +4,38 @@ #define HERCULES_CORE -#include "../config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP +#include "config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP #include "status.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/skill.h" +#include "map/unit.h" +#include "map/vending.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <memory.h> #include <stdio.h> @@ -14,36 +43,10 @@ #include <string.h> #include <time.h> -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "itemdb.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "skill.h" -#include "unit.h" -#include "vending.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct status_interface status_s; +struct s_status_dbs statusdbs; + +struct status_interface *status; /** * Returns the status change associated with a skill. @@ -56,7 +59,7 @@ sc_type status_skill2sc(int skill_id) { ShowError("status_skill2sc: Unsupported skill id %d\n", skill_id); return SC_NONE; } - return status->Skill2SCTable[idx]; + return status->dbs->Skill2SCTable[idx]; } /** @@ -72,7 +75,7 @@ int status_sc2skill(sc_type sc) return 0; } - return status->SkillChangeTable[sc]; + return status->dbs->SkillChangeTable[sc]; } /** @@ -87,7 +90,7 @@ unsigned int status_sc2scb_flag(sc_type sc) return SCB_NONE; } - return status->ChangeFlagTable[sc]; + return status->dbs->ChangeFlagTable[sc]; } /** @@ -102,7 +105,7 @@ int status_type2relevant_bl_types(int type) return BL_NUL; } - return status->RelevantBLTypes[type]; + return status->dbs->RelevantBLTypes[type]; } static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { @@ -116,35 +119,35 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { return; } - if( status->SkillChangeTable[sc] == 0 ) - status->SkillChangeTable[sc] = skill_id; - if( status->IconChangeTable[sc] == SI_BLANK ) - status->IconChangeTable[sc] = icon; - status->ChangeFlagTable[sc] |= flag; + if( status->dbs->SkillChangeTable[sc] == 0 ) + status->dbs->SkillChangeTable[sc] = skill_id; + if( status->dbs->IconChangeTable[sc] == SI_BLANK ) + status->dbs->IconChangeTable[sc] = icon; + status->dbs->ChangeFlagTable[sc] |= flag; - if( status->Skill2SCTable[idx] == SC_NONE ) - status->Skill2SCTable[idx] = sc; + if( status->dbs->Skill2SCTable[idx] == SC_NONE ) + status->dbs->Skill2SCTable[idx] = sc; } void initChangeTables(void) { #define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE) // indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units -#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0) +#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0) int i; for (i = 0; i < SC_MAX; i++) - status->IconChangeTable[i] = SI_BLANK; + status->dbs->IconChangeTable[i] = SI_BLANK; for (i = 0; i < MAX_SKILL; i++) - status->Skill2SCTable[i] = SC_NONE; + status->dbs->Skill2SCTable[i] = SC_NONE; for (i = 0; i < SI_MAX; i++) - status->RelevantBLTypes[i] = BL_PC; + status->dbs->RelevantBLTypes[i] = BL_PC; - memset(status->SkillChangeTable, 0, sizeof(status->SkillChangeTable)); - memset(status->ChangeFlagTable, 0, sizeof(status->ChangeFlagTable)); - memset(status->DisplayType, 0, sizeof(status->DisplayType)); + memset(status->dbs->SkillChangeTable, 0, sizeof(status->dbs->SkillChangeTable)); + memset(status->dbs->ChangeFlagTable, 0, sizeof(status->dbs->ChangeFlagTable)); + memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType)); //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 ); @@ -754,303 +757,303 @@ void initChangeTables(void) { set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT ); // Storing the target job rather than simply SC_SOULLINK simplifies code later on. - status->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, - status->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK, - status->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, - status->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE, - status->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, - status->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, - status->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, - status->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, - status->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, - status->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, - status->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, - status->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, - status->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, - status->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, - status->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, + status->dbs->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, + status->dbs->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK, + status->dbs->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, + status->dbs->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE, + status->dbs->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, + status->dbs->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, + status->dbs->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, + status->dbs->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, + status->dbs->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, + status->dbs->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, + status->dbs->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, + status->dbs->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, + status->dbs->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, + status->dbs->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, + status->dbs->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, //Status that don't have a skill associated. - status->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; - status->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; - status->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; - status->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; - status->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; - status->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; - status->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; - status->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; - status->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR; - status->IconChangeTable[SC_MIRACLE] = SI_SOULLINK; - status->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; - status->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; - status->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; - status->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; - status->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; - status->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; - status->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; - status->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; - status->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; - status->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; - status->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; - status->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; - status->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; - status->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; - status->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; - status->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; - status->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; + status->dbs->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; + status->dbs->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; + status->dbs->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; + status->dbs->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; + status->dbs->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; + status->dbs->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR; + status->dbs->IconChangeTable[SC_MIRACLE] = SI_SOULLINK; + status->dbs->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; + status->dbs->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; + status->dbs->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; + status->dbs->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; + status->dbs->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; + status->dbs->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; + status->dbs->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; + status->dbs->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; + status->dbs->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; + status->dbs->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; + status->dbs->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; + status->dbs->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; + status->dbs->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; + status->dbs->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; + status->dbs->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; + status->dbs->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; + status->dbs->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; //Cash Items - status->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; - status->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; - status->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; - status->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; - status->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; - status->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; - status->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; - status->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; - status->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; - status->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; - status->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; - status->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; - status->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; - status->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; - status->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; - status->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; - status->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; - status->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; - status->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; - status->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; + status->dbs->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; + status->dbs->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; + status->dbs->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; + status->dbs->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; + status->dbs->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; + status->dbs->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; + status->dbs->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; + status->dbs->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; + status->dbs->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; + status->dbs->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; + status->dbs->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; + status->dbs->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; + status->dbs->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; + status->dbs->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; + status->dbs->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; + status->dbs->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; + status->dbs->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; + status->dbs->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; + status->dbs->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; + status->dbs->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; // Mercenary Bonus Effects - status->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; - status->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; - status->IconChangeTable[SC_MER_HP] = SI_MER_HP; - status->IconChangeTable[SC_MER_SP] = SI_MER_SP; - status->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; + status->dbs->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; + status->dbs->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; + status->dbs->IconChangeTable[SC_MER_HP] = SI_MER_HP; + status->dbs->IconChangeTable[SC_MER_SP] = SI_MER_SP; + status->dbs->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; // Warlock Spheres - status->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; - status->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; - status->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; - status->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; - status->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; + status->dbs->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; + status->dbs->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; + status->dbs->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; + status->dbs->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; + status->dbs->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; // Warlock Preserved spells - status->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; - status->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; - status->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; - status->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; - status->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; - status->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; - status->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; - - status->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; - status->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; - status->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; - status->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; - - status->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; - status->IconChangeTable[SC_TOXIN] = SI_TOXIN; - status->IconChangeTable[SC_PARALYSE] = SI_PARALYSE; - status->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; - status->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; - status->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; - status->IconChangeTable[SC_PYREXIA] = SI_PYREXIA; - status->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; - status->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; - - status->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; - status->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; - status->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; - status->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; - - status->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; - - status->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; - status->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; - status->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; - status->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; - status->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; + status->dbs->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; + status->dbs->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; + status->dbs->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; + status->dbs->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; + status->dbs->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; + status->dbs->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; + status->dbs->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; + + status->dbs->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; + status->dbs->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; + status->dbs->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; + status->dbs->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; + + status->dbs->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; + status->dbs->IconChangeTable[SC_TOXIN] = SI_TOXIN; + status->dbs->IconChangeTable[SC_PARALYSE] = SI_PARALYSE; + status->dbs->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; + status->dbs->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; + status->dbs->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; + status->dbs->IconChangeTable[SC_PYREXIA] = SI_PYREXIA; + status->dbs->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; + status->dbs->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; + + status->dbs->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; + status->dbs->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; + status->dbs->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; + status->dbs->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; + + status->dbs->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; + + status->dbs->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; + status->dbs->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; + status->dbs->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; + status->dbs->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; + status->dbs->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; //Genetics New Food Items Status Icons - status->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; - status->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; - status->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; - status->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; - status->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; - status->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; - - status->IconChangeTable[SC_BOOST500] |= SI_BOOST500; - status->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; - status->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; - status->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; - status->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; - status->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; - status->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500; - status->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; + status->dbs->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; + status->dbs->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; + status->dbs->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; + status->dbs->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; + status->dbs->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; + status->dbs->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; + + status->dbs->IconChangeTable[SC_BOOST500] |= SI_BOOST500; + status->dbs->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; + status->dbs->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; + status->dbs->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; + status->dbs->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; + status->dbs->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; + status->dbs->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500; + status->dbs->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; // Elemental Spirit's 'side' status change icons. - status->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; - status->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; - status->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; - status->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; - status->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; - status->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; - status->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; - status->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; - status->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; - status->IconChangeTable[SC_HEATER] = SI_HEATER; - status->IconChangeTable[SC_TROPIC] = SI_TROPIC; - status->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; - status->IconChangeTable[SC_COOLER] = SI_COOLER; - status->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; - status->IconChangeTable[SC_GUST] = SI_GUST; - status->IconChangeTable[SC_BLAST] = SI_BLAST; - status->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; - status->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; - status->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; - status->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; - status->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; - status->IconChangeTable[SC_REBOUND] = SI_REBOUND; - status->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; - status->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; - status->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; - status->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; - status->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; - status->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC; + status->dbs->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; + status->dbs->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; + status->dbs->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; + status->dbs->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; + status->dbs->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; + status->dbs->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; + status->dbs->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; + status->dbs->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; + status->dbs->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; + status->dbs->IconChangeTable[SC_HEATER] = SI_HEATER; + status->dbs->IconChangeTable[SC_TROPIC] = SI_TROPIC; + status->dbs->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; + status->dbs->IconChangeTable[SC_COOLER] = SI_COOLER; + status->dbs->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; + status->dbs->IconChangeTable[SC_GUST] = SI_GUST; + status->dbs->IconChangeTable[SC_BLAST] = SI_BLAST; + status->dbs->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; + status->dbs->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; + status->dbs->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; + status->dbs->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; + status->dbs->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; + status->dbs->IconChangeTable[SC_REBOUND] = SI_REBOUND; + status->dbs->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; + status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; + status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; + status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; + status->dbs->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; + status->dbs->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC; //Other SC which are not necessarily associated to skills. - status->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD; - status->ChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED; - status->ChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; - status->ChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK; - status->ChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK; - status->ChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; - status->ChangeFlagTable[SC_CHASEWALK2] |= SCB_STR; - status->ChangeFlagTable[SC_INCAGI] |= SCB_AGI; - status->ChangeFlagTable[SC_INCVIT] |= SCB_VIT; - status->ChangeFlagTable[SC_INCINT] |= SCB_INT; - status->ChangeFlagTable[SC_INCDEX] |= SCB_DEX; - status->ChangeFlagTable[SC_INCLUK] |= SCB_LUK; - status->ChangeFlagTable[SC_INCHIT] |= SCB_HIT; - status->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; - status->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; - status->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; - status->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE; - status->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; - status->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; - status->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; - status->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; - status->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; - status->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; - status->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; - status->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; - status->ChangeFlagTable[SC_FOOD_STR] |= SCB_STR; - status->ChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI; - status->ChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT; - status->ChangeFlagTable[SC_FOOD_INT] |= SCB_INT; - status->ChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX; - status->ChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK; - status->ChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT; - status->ChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE; - status->ChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; - status->ChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; - status->ChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; - status->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; - status->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; - status->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; - status->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; - status->ChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK; + status->dbs->ChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK; + status->dbs->ChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; + status->dbs->ChangeFlagTable[SC_CHASEWALK2] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_INCAGI] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_INCVIT] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_INCINT] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_INCDEX] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_INCLUK] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_INCHIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE; + status->dbs->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; + status->dbs->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; + status->dbs->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; + status->dbs->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; + status->dbs->ChangeFlagTable[SC_FOOD_STR] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_FOOD_INT] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; + status->dbs->ChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; // Cash Items - status->ChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; - status->ChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; - status->ChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; - status->ChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; - status->ChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; - status->ChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; + status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; + status->dbs->ChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; + status->dbs->ChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; + status->dbs->ChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; + status->dbs->ChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; + status->dbs->ChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; // Mercenary Bonus Effects - status->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; - status->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK; - status->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT; // Guillotine Cross Poison Effects - status->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD; - status->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN; - status->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; - status->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE; - status->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD; + status->dbs->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE; + status->dbs->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; // RG status - status->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; - status->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; + status->dbs->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; // Meca status - status->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED; - - status->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; - status->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; - status->ChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; - status->ChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; - status->ChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; - status->ChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; - status->ChangeFlagTable[SC_BOOST500] |= SCB_ASPD; - status->ChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; - status->ChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; - status->ChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; - status->ChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; - status->ChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; - status->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; - status->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; - status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; - status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2; - status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2; - status->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP; - - status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; - status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED; - - status->ChangeFlagTable[SC_MTF_ASPD] = SCB_ASPD|SCB_HIT; - status->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK; - status->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL; - - status->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; - status->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; - status->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; - status->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE; - - /* status->DisplayType Table [Ind/Hercules] */ - status->DisplayType[SC_ALL_RIDING] = true; - status->DisplayType[SC_PUSH_CART] = true; - status->DisplayType[SC_SUMMON1] = true; - status->DisplayType[SC_SUMMON2] = true; - status->DisplayType[SC_SUMMON3] = true; - status->DisplayType[SC_SUMMON4] = true; - status->DisplayType[SC_SUMMON5] = true; - status->DisplayType[SC_CAMOUFLAGE] = true; - status->DisplayType[SC_DUPLELIGHT] = true; - status->DisplayType[SC_ORATIO] = true; - status->DisplayType[SC_FROSTMISTY] = true; - status->DisplayType[SC_VENOMIMPRESS] = true; - status->DisplayType[SC_HALLUCINATIONWALK] = true; - status->DisplayType[SC_ROLLINGCUTTER] = true; - status->DisplayType[SC_BANDING] = true; - status->DisplayType[SC_COLD] = true; - status->DisplayType[SC_DEEP_SLEEP] = true; - status->DisplayType[SC_CURSEDCIRCLE_ATKER] = true; - status->DisplayType[SC_CURSEDCIRCLE_TARGET] = true; - status->DisplayType[SC_BLOOD_SUCKER] = true; - status->DisplayType[SC__SHADOWFORM] = true; - status->DisplayType[SC_MONSTER_TRANSFORM] = true; - status->DisplayType[SC_MOONSTAR] = true; - status->DisplayType[SC_SUPER_STAR] = true; - status->DisplayType[SC_STRANGELIGHTS] = true; - status->DisplayType[SC_DECORATION_OF_MUSIC] = true; + status->dbs->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED; + + status->dbs->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_BOOST500] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; + status->dbs->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2; + status->dbs->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2; + status->dbs->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP; + + status->dbs->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_WEDDING] = SCB_SPEED; + + status->dbs->ChangeFlagTable[SC_MTF_ASPD] = SCB_ASPD|SCB_HIT; + status->dbs->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK; + status->dbs->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL; + + status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE; + + /* status->dbs->DisplayType Table [Ind/Hercules] */ + status->dbs->DisplayType[SC_ALL_RIDING] = true; + status->dbs->DisplayType[SC_PUSH_CART] = true; + status->dbs->DisplayType[SC_SUMMON1] = true; + status->dbs->DisplayType[SC_SUMMON2] = true; + status->dbs->DisplayType[SC_SUMMON3] = true; + status->dbs->DisplayType[SC_SUMMON4] = true; + status->dbs->DisplayType[SC_SUMMON5] = true; + status->dbs->DisplayType[SC_CAMOUFLAGE] = true; + status->dbs->DisplayType[SC_DUPLELIGHT] = true; + status->dbs->DisplayType[SC_ORATIO] = true; + status->dbs->DisplayType[SC_FROSTMISTY] = true; + status->dbs->DisplayType[SC_VENOMIMPRESS] = true; + status->dbs->DisplayType[SC_HALLUCINATIONWALK] = true; + status->dbs->DisplayType[SC_ROLLINGCUTTER] = true; + status->dbs->DisplayType[SC_BANDING] = true; + status->dbs->DisplayType[SC_COLD] = true; + status->dbs->DisplayType[SC_DEEP_SLEEP] = true; + status->dbs->DisplayType[SC_CURSEDCIRCLE_ATKER] = true; + status->dbs->DisplayType[SC_CURSEDCIRCLE_TARGET] = true; + status->dbs->DisplayType[SC_BLOOD_SUCKER] = true; + status->dbs->DisplayType[SC__SHADOWFORM] = true; + status->dbs->DisplayType[SC_MONSTER_TRANSFORM] = true; + status->dbs->DisplayType[SC_MOONSTAR] = true; + status->dbs->DisplayType[SC_SUPER_STAR] = true; + status->dbs->DisplayType[SC_STRANGELIGHTS] = true; + status->dbs->DisplayType[SC_DECORATION_OF_MUSIC] = true; if( !battle_config.display_hallucination ) //Disable Hallucination. - status->IconChangeTable[SC_ILLUSION] = SI_BLANK; + status->dbs->IconChangeTable[SC_ILLUSION] = SI_BLANK; #undef add_sc #undef set_sc_with_vfx } @@ -1076,7 +1079,6 @@ void initDummyData(void) status->dummy.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) { @@ -1189,12 +1191,12 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, struct status_change_entry *sce; #ifdef DEVOTION_REFLECT_DAMAGE - if(src && (sce = sc->data[SC_DEVOTION])) { + if (src && (sce = sc->data[SC_DEVOTION]) != NULL) { 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, 0, 0, hp, 0, 0, 0); + clif->damage(d_bl, d_bl, 0, 0, hp, 0, BDT_NORMAL, 0); status_fix_damage(NULL, d_bl, hp, 0); return 0; } @@ -1261,7 +1263,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, } if( src && target->type == BL_PC && (((TBL_PC*)target)->disguise) > 0 ) {// stop walking when attacked in disguise to prevent walk-delay bug - unit->stop_walking( target, 1 ); + unit->stop_walking(target, STOPWALKING_FLAG_FIXPOS); } if (st->hp || (flag&8)) { @@ -1344,7 +1346,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, unit->remove_map(target,CLR_DEAD,ALC_MARK); else { //Some death states that would normally be handled by unit_remove_map unit->stop_attack(target); - unit->stop_walking(target,1); + unit->stop_walking(target, STOPWALKING_FLAG_FIXPOS); unit->skillcastcancel(target,0); clif->clearunit_area(target,CLR_DEAD); skill->unit_move(target,timer->gettick(),4); @@ -1585,7 +1587,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin //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_COLD] && src->type != BL_MOB) + if( src && (sc = status->get_sc(src)) != NULL && sc->data[SC_COLD] && src->type != BL_MOB) return 0; } @@ -1596,13 +1598,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) { if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) { - if( src->type == BL_PC ) - clif->msg((TBL_PC*)src, SKILL_CANT_USE_AREA); // This skill cannot be used within this area - else if( src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) { - if( st->mode&MD_BOSS ) { /** is boss **/ + if (src->type == BL_PC) { + clif->msgtable((TBL_PC*)src, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area + } else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) { + if( st->mode&MD_BOSS ) { /* is boss */ if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) ) break; - } else { /** is not boss **/ + } else { /* is not boss */ if( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) break; } @@ -1627,7 +1629,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin 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) + if (src && map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR) && !(st->mode&MD_BOSS) && (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)) return 0; @@ -1656,10 +1658,15 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; if (sc->data[SC_DC_WINKCHARM] && target && !flag) { //Prevents skill usage - if( unit->bl2ud(src) && (unit->bl2ud(src))->walktimer == INVALID_TIMER ) - unit->walktobl(src, map->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1); - clif->emotion(src, E_LV); - return 0; + struct block_list *winkcharm_target = map->id2bl(sc->data[SC_DC_WINKCHARM]->val2); + if (winkcharm_target != NULL) { + if (unit->bl2ud(src) && (unit->bl2ud(src))->walktimer == INVALID_TIMER) + unit->walktobl(src, map->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1); + clif->emotion(src, E_LV); + return 0; + } else { + status_change_end(src, SC_DC_WINKCHARM, INVALID_TIMER); + } } if (sc->data[SC_BLADESTOP]) { @@ -1867,14 +1874,14 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { if (md->special_state.size) flag|=2; - if( md->guardian_data && md->guardian_data->g - && (guardup_lv = guild->checkskill(md->guardian_data->g,GD_GUARDUP)) ) + if (md->guardian_data && md->guardian_data->g + && (guardup_lv = guild->checkskill(md->guardian_data->g,GD_GUARDUP)) > 0) flag|=4; if (battle_config.slaves_inherit_speed && md->master_id) flag|=8; - if (md->master_id && md->special_state.ai>1) + if (md->master_id && md->special_state.ai > AI_ATTACK) flag|=16; if (!flag) @@ -1910,8 +1917,8 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { //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 (mbl->type == BL_MOB && ((TBL_MOB*)mbl)->special_state.ai == AI_NONE) + md->special_state.ai = AI_NONE; if (ud) { // different levels of HP according to skill level if (ud->skill_id == AM_SPHEREMINE) { @@ -1944,7 +1951,6 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { mstatus->speed -= cap_value(diff, 0, mstatus->speed - 10); } - if (flag&2 && battle_config.mob_size_influence) { // change for sized monsters [Valaris] if (md->special_state.size==SZ_MEDIUM) { @@ -2084,7 +2090,7 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) unsigned int status_get_base_maxsp(struct map_session_data* sd, struct status_data *st) { uint64 val = pc->class2idx(sd->status.class_); - val = status->SP_table[val][sd->status.base_level]; + val = status->dbs->SP_table[val][sd->status.base_level]; if ( sd->class_&JOBL_UPPER ) val += val * 25 / 100; @@ -2101,7 +2107,7 @@ unsigned int status_get_base_maxsp(struct map_session_data* sd, struct status_da unsigned int status_get_base_maxhp(struct map_session_data *sd, struct status_data *st) { uint64 val = pc->class2idx(sd->status.class_); - val = status->HP_table[val][sd->status.base_level]; + val = status->dbs->HP_table[val][sd->status.base_level]; if ( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99 ) val += 2000; //Supernovice lvl99 hp bonus. @@ -2121,6 +2127,11 @@ unsigned int status_get_base_maxhp(struct map_session_data *sd, struct status_da return (unsigned int)cap_value(val,0,UINT_MAX); } +void status_calc_pc_additional(struct map_session_data* sd, enum e_status_calc_opt opt) { + /* Just used for Plugin to give bonuses. */ + return; +} + //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, enum e_status_calc_opt opt) { @@ -2143,7 +2154,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { pc->calc_skilltree(sd); // SkillTree calculation - sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300; + sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300; if(opt&SCO_FIRST) { //Load Hp/SP from char-received data. @@ -2181,40 +2192,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { 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->magic_atk_ele) - + sizeof(sd->critaddrace) - + sizeof(sd->expaddrace) - + sizeof(sd->ignore_mdef) - + sizeof(sd->ignore_def) - + sizeof(sd->sp_gain_race) - + sizeof(sd->sp_gain_race_attack) - + sizeof(sd->hp_gain_race_attack) -#ifdef RENEWAL - + sizeof(sd->race_tolerance) -#endif - ); + // zeroed arrays + memset(ZEROED_BLOCK_POS(sd), 0, ZEROED_BLOCK_SIZE(sd)); - 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)); + memset(ZEROED_BLOCK_POS(&(sd->right_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->right_weapon))); + memset(ZEROED_BLOCK_POS(&(sd->left_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->left_weapon))); if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE); @@ -2246,41 +2228,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } bstatus->aspd_rate = 1000; bstatus->ele_lv = 1; - bstatus->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) - + sizeof(sd->skillfixcastrate) - + sizeof(sd->def_set_race) - + sizeof(sd->mdef_set_race) - ); - - memset (&sd->bonus, 0,sizeof(sd->bonus)); + bstatus->race = RC_PLAYER; // Autobonus pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); @@ -2319,7 +2267,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script) { //Execute equip-script on login - script->run(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + script->run_item_equip_script(sd, sd->inventory_data[index], 0); if (!calculating) return 1; } @@ -2343,27 +2291,27 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } wa->atk += sd->inventory_data[index]->atk; if ( (r = sd->status.inventory[index].refine) ) - wa->atk2 = status->refine_info[wlv].bonus[r-1] / 100; + wa->atk2 = status->dbs->refine_info[wlv].bonus[r-1] / 100; #ifdef RENEWAL wa->matk += sd->inventory_data[index]->matk; wa->wlv = wlv; if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus - wa->matk += status->refine_info[wlv].bonus[r-1] / 100; + wa->matk += status->dbs->refine_info[wlv].bonus[r-1] / 100; #endif //Overrefined bonus. if (r) - wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100; + wd->overrefine = status->dbs->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; - script->run(sd->inventory_data[index]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[index], 0); sd->state.lr_flag = 0; } else - script->run(sd->inventory_data[index]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[index], 0); if (!calculating) //Abort, script->run retriggered this. [Skotlex] return 1; } @@ -2382,11 +2330,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { else if(sd->inventory_data[index]->type == IT_ARMOR) { int r; if ( (r = sd->status.inventory[index].refine) ) - refinedef += status->refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; + refinedef += status->dbs->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; - script->run(sd->inventory_data[index]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[index], 0); if( i == EQI_HAND_L ) //Shield sd->state.lr_flag = 0; if (!calculating) //Abort, script->run retriggered this. [Skotlex] @@ -2402,7 +2350,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { 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 - script->run(sd->inventory_data[index]->script,0,sd->bl.id,0); + script->run_use_script(sd, sd->inventory_data[index], 0); sd->state.lr_flag = 0; if (!calculating) //Abort, script->run retriggered status_calc_pc. [Skotlex] return 1; @@ -2480,7 +2428,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { continue; if(opt&SCO_FIRST && data->equip_script) {//Execute equip-script on login - script->run(data->equip_script,0,sd->bl.id,0); + script->run_item_equip_script(sd, data, 0); if (!calculating) return 1; } @@ -2490,10 +2438,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { //Left hand status. sd->state.lr_flag = 1; - script->run(data->script,0,sd->bl.id,0); + script->run_use_script(sd, data, 0); sd->state.lr_flag = 0; } else - script->run(data->script,0,sd->bl.id,0); + script->run_use_script(sd, data, 0); if (!calculating) //Abort, script->run his function. [Skotlex] return 1; } @@ -2503,9 +2451,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if( sc->count && sc->data[SC_ITEMSCRIPT] ) { struct item_data *data = itemdb->exists(sc->data[SC_ITEMSCRIPT]->val1); if( data && data->script ) - script->run(data->script,0,sd->bl.id,0); + script->run_use_script(sd, data, 0); } + status->calc_pc_additional(sd, opt); + 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 ) @@ -2525,12 +2475,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->bonus.splash_range += sd->bonus.splash_add_range; // Damage modifiers from weapon type - sd->right_weapon.atkmods[0] = status->atkmods[0][sd->weapontype1]; - sd->right_weapon.atkmods[1] = status->atkmods[1][sd->weapontype1]; - sd->right_weapon.atkmods[2] = status->atkmods[2][sd->weapontype1]; - sd->left_weapon.atkmods[0] = status->atkmods[0][sd->weapontype2]; - sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2]; - sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2]; + sd->right_weapon.atkmods[0] = status->dbs->atkmods[0][sd->weapontype1]; + sd->right_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype1]; + sd->right_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype1]; + sd->left_weapon.atkmods[0] = status->dbs->atkmods[0][sd->weapontype2]; + sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2]; + sd->left_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype2]; if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR) @@ -2546,9 +2496,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Job bonuses index = pc->class2idx(sd->status.class_); for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){ - if(!status->job_bonus[index][i]) + if(!status->dbs->job_bonus[index][i]) continue; - switch(status->job_bonus[index][i]) { + switch(status->dbs->job_bonus[index][i]) { case 1: bstatus->str++; break; case 2: bstatus->agi++; break; case 3: bstatus->vit++; break; @@ -2650,7 +2600,6 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 ) bstatus->max_sp += 30 * skill_lv; - // Apply relative modifiers from equipment if(sd->sprate < 0) sd->sprate = 0; @@ -2752,7 +2701,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 ) bstatus->hit += 3*skill_lv; - if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && ((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)) + if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) bstatus->hit += 2*skill_lv; // ----- FLEE CALCULATION ----- @@ -2829,7 +2778,6 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { #endif bstatus->adelay = 2*bstatus->amotion; - // ----- DMOTION ----- // i = 800-bstatus->agi*4; @@ -3090,7 +3038,7 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { nstatus->def_ele = ELE_NEUTRAL; nstatus->ele_lv = 1; - nstatus->race = RC_DEMIHUMAN; + nstatus->race = RC_PLAYER; nstatus->size = nd->size; nstatus->rhw.range = 1 + nstatus->size; nstatus->mode = (MD_CANMOVE|MD_CANATTACK); @@ -3144,6 +3092,8 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { hstatus->aspd_rate = 1000; #ifdef RENEWAL + hstatus->def = 0; + amotion = hd->homunculusDB->baseASPD; amotion = amotion - amotion * (hstatus->dex + hom->dex_value) / 1000 - (hstatus->agi + hom->agi_value) * amotion / 250; #else @@ -3158,7 +3108,6 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { hstatus->amotion = cap_value(amotion, battle_config.max_aspd, 2000); hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus. - hstatus->max_hp = hom->max_hp; hstatus->max_sp = hom->max_sp; @@ -3613,7 +3562,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if (!(st->mode&MD_CANATTACK)) unit->stop_attack(bl); if (!(st->mode&MD_CANMOVE)) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } // No status changes alter these yet. @@ -3976,11 +3925,11 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) #ifdef RENEWAL_ASPD /* [malufett/Hercules] */ float temp; int skill_lv, val = 0; - amotion = status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]; + amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]; if ( sd->status.weapon > MAX_WEAPON_TYPE ) - amotion += status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4; + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4; if ( sd->status.shield ) - amotion += status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE]; + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE]; switch ( sd->status.weapon ) { case W_BOW: case W_MUSICAL: case W_WHIP: case W_REVOLVER: @@ -4000,8 +3949,8 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) #else // base weapon delay amotion = (sd->status.weapon < MAX_WEAPON_TYPE) - ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield + ? (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield // percentual delay reduction from stats amotion -= amotion * (4 * st->agi + st->dex) / 1000; @@ -4105,7 +4054,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) if ( bl->type == BL_HOM ) { st->def2 = status_get_homvit(bl) + status_get_homagi(bl) / 2; st->mdef2 = (status_get_homvit(bl) + status_get_homint(bl)) / 2; - st->def += status_get_homvit(bl) + level / 2; + st->def += status_get_homvit(bl) + level / 2; // Increase. Already initialized in status_calc_homunculus_ st->mdef = (int)(((float)status_get_homvit(bl) + level) / 4 + (float)status_get_homint(bl) / 2); st->hit = level + st->dex + 150; st->flee = level + status_get_homagi(bl); @@ -5127,7 +5076,6 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i #endif } - defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) { if(!sc || !sc->count) @@ -5196,7 +5144,7 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, if(sc->data[SC_MINDBREAKER]) mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; #ifdef RENEWAL - if(sc && sc->data[SC_ASSUMPTIO]) + if (sc->data[SC_ASSUMPTIO]) mdef2 <<= 1; return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else @@ -5841,7 +5789,6 @@ unsigned char status_calc_element_lv(struct block_list *bl, struct status_change 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) @@ -6016,7 +5963,7 @@ int status_get_party_id(struct block_list *bl) { 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) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->status.party_id; return -md->master_id; } @@ -6059,7 +6006,7 @@ int status_get_guild_id(struct block_list *bl) { // Guardian guild data may not been available yet, castle data is always set return (md->guardian_data->g)?md->guardian_data->g->guild_id:md->guardian_data->castle->guild_id; } - if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL ) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->status.guild_id; //Alchemist's mobs [Skotlex] break; } @@ -6101,7 +6048,7 @@ int status_get_emblem_id(struct block_list *bl) { struct mob_data *md = (struct mob_data *)bl; if (md->guardian_data) //Guardian's guild [Skotlex] return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0; - if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->guild_emblem_id; //Alchemist's mobs [Skotlex] } break; @@ -6284,7 +6231,7 @@ void status_set_viewdata(struct block_list *bl, int class_) if (vd) nd->vd = vd; else - ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); + ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name); } break; case BL_HOM: //[blackhole89] @@ -6573,9 +6520,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ case SC_COLD: tick_def2 = bst->vit*100 + status->get_lv(bl)*20; break; - case SC_VACUUM_EXTREME: - tick_def2 = bst->str*50; - break; case SC_MANDRAGORA: sc_def = (st->vit + st->luk)*20; break; @@ -7030,7 +6974,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (!opt_flag) return 0; } @@ -7046,7 +6990,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7058,7 +7002,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_ARMOR]; if ( i < 0 || !sd->inventory_data[i] ) return 0; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7070,7 +7014,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_HEAD_TOP]; if ( i < 0 || !sd->inventory_data[i] ) return 0; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7140,12 +7084,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( !(sd->bonus.unstripable_equip&EQP_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 + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //L-Accessory } if( !(sd->bonus.unstripable_equip&EQP_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 + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //R-Accessory } if( i < 0 ) return 0; @@ -7376,7 +7320,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); break; case SC_ENDURE: - if( val4 ) + if( val4 == 1 ) status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); break; case SC_FIGHTINGSPIRIT: @@ -7579,7 +7523,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } vd = status->get_viewdata(bl); - calc_flag = status->ChangeFlagTable[type]; + calc_flag = status->dbs->ChangeFlagTable[type]; if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs switch(type) { case SC_ADORAMUS: @@ -7595,12 +7539,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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])) ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL); } - } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + } else if (bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) != NULL) { status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL); + } } //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) if( val4 ) @@ -7694,12 +7639,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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])) ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); } - } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + } else if (bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) != NULL) { status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + } } break; case SC_NOEQUIPWEAPON: @@ -7952,13 +7898,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_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])) ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); } } - else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + else if (bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) != NULL) { status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + } } } break; @@ -7972,9 +7919,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (sd) { struct map_session_data *tsd; int i; - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_PC_DEVOTION; i++) { //See if there are devoted characters, and pass the status to them. [Skotlex] - if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i]))) + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID); } } @@ -8111,7 +8058,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t 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) { + if ((d_bl = map->id2bl(val1)) && (d_sc = status->get_sc(d_bl)) != NULL && d_sc->count) { // Inherits Status From Source const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; int i = (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground)?2:3; @@ -8865,6 +8812,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t else val2 = val2 / 4 * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] break; + case SC_GENTLETOUCH_ENERGYGAIN: + val2 = 10 + 5 * val1; + break; case SC_PYROTECHNIC_OPTION: val2 = 60; break; @@ -9107,7 +9057,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 20+(20*val1); break; default: - if (calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0) { + if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) { //Status change with no calc, no icon, and no skill associated...? ShowError("UnknownStatusChange [%d]\n", type); return 0; @@ -9261,7 +9211,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } /* [Ind/Hercules] */ - if( sd && status->DisplayType[type] ) { + if( sd && status->dbs->DisplayType[type] ) { int dval1 = 0, dval2 = 0, dval3 = 0; switch( type ) { case SC_ALL_RIDING: @@ -9313,11 +9263,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_NEEDLE_OF_PARALYZE: case SC_DEATHBOUND: case SC_NETHERWORLD: - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); break; case SC_ANKLESNARE: if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); break; case SC_HIDING: case SC_CLOAKING: @@ -9554,8 +9504,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t calc_flag&=~SCB_DYE; } - if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->DisplayType[type])) - clif->status_change(bl,status->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) + clif->status_change(bl,status->dbs->IconChangeTable[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. @@ -9571,12 +9521,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t ++(sc->count); sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); } - + sce->val1 = val1; sce->val2 = val2; sce->val3 = val3; sce->val4 = val4; - + if (tick >= 0) { sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); sce->infinite_duration = false; @@ -9767,7 +9717,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 0; st = status->get_status_data(bl); - + if( sd && sce->infinite_duration && !sd->state.loggingout ) chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type); @@ -9802,7 +9752,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->data[type] = NULL; - if( sd && status->DisplayType[type] ) { + if( sd && status->dbs->DisplayType[type] ) { status->display_remove(sd,type); } @@ -9812,7 +9762,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const #endif vd = status->get_viewdata(bl); - calc_flag = status->ChangeFlagTable[type]; + calc_flag = status->dbs->ChangeFlagTable[type]; switch(type) { case SC_GRANITIC_ARMOR: { @@ -9839,7 +9789,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const begin_spurt = false; ud->state.running = 0; if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } if (begin_spurt && sce->val1 >= 7 && DIFF_TICK(timer->gettick(), starttick) <= 1000 @@ -9862,8 +9812,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const 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] ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL && tsd->sc.data[type]) status_change_end(&tsd->bl, type, INVALID_TIMER); } } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag ) { @@ -9924,7 +9874,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sd->delunit_prevline = line; } - if (sce->val4 && sce->val4 != BCT_SELF && (dsd=map->id2sd(sce->val4))) { + if (sce->val4 && sce->val4 != BCT_SELF && (dsd=map->id2sd(sce->val4)) != NULL) { // end status on partner as well dsc = dsd->sc.data[SC_DANCING]; if (dsc) { @@ -9949,7 +9899,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } sce->val2 = 0; - + if( group ) skill->del_unitgroup(group,ALC_MARK); } @@ -9983,11 +9933,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (src && sc2 && sc2->data[SC_RG_CCONFINE_M]) { //If status was already ended, do nothing. //Decrease count - if (--(sc2->data[SC_RG_CCONFINE_M]->val1) <= 0) //No more holds, free him up. + if (--(sc2->data[SC_RG_CCONFINE_M]->val2) <= 0) //No more holds, free him up. status_change_end(src, SC_RG_CCONFINE_M, INVALID_TIMER); } } - /* Fall through */ + break; case SC_RG_CCONFINE_M: if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. @@ -10113,12 +10063,13 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list *tbl = map->id2bl(sce->val2); struct status_change *tsc = NULL; sce->val2 = 0; - if( tbl && (tsc = status->get_sc(tbl)) && tsc->data[SC_STOP] && tsc->data[SC_STOP]->val2 == bl->id ) + if (tbl && (tsc = status->get_sc(tbl)) != NULL && tsc->data[SC_STOP] && tsc->data[SC_STOP]->val2 == bl->id) status_change_end(tbl, SC_STOP, INVALID_TIMER); } break; case SC_LKCONCENTRATION: - status_change_end(bl, SC_ENDURE, INVALID_TIMER); + if (sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 != 2) + status_change_end(bl, SC_ENDURE, INVALID_TIMER); break; /** * 3rd Stuff @@ -10134,7 +10085,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list* src = map->id2bl(sce->val2); if( tid == -1 || !src) break; // Terminated by Damage - status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,0,0)); + status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,BDT_NORMAL,0)); } break; case SC_WUGDASH: @@ -10143,7 +10094,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (ud) { ud->state.running = 0; if (ud->walktimer != -1) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } } break; @@ -10186,15 +10137,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const map->foreachinrange(status->change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, timer->gettick()); break; case SC_RAISINGDRAGON: - if( sd && sce->val2 && !pc_isdead(sd) ) { + if ( sd && sce->val2 && !pc_isdead(sd) ) { int i; - i = min(sd->spiritball,5); - pc->delspiritball(sd, sd->spiritball, 0); + if ( (i = (sd->spiritball - 5)) > 0 ) + pc->delspiritball(sd, i, 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: @@ -10459,7 +10406,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif->sc_end(bl,bl->id,AREA,status->IconChangeTable[type]); + clif->sc_end(bl,bl->id,AREA,status->dbs->IconChangeTable[type]); if( opt_flag&8 ) //bugreport:681 clif->changeoption2(bl); @@ -10481,7 +10428,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const skill->unit_move(bl,timer->gettick(),1); if (opt_flag & 2 && sd) { - if (map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) + if (map->getcell(bl->m, bl, bl->x, bl->y, CELL_CHKNPC)) npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. else npc->untouch_areanpc(sd, bl->m, bl->x, bl->y); @@ -10498,10 +10445,7 @@ int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { struct status_data *st; int hp; - if(!( (bl=map->id2bl(id)) - && (sc=status->get_sc(bl)) - && (sce=sc->data[SC_KAAHI]) - )) + if ((bl=map->id2bl(id)) == NULL || (sc=status->get_sc(bl)) == NULL || (sce=sc->data[SC_KAAHI]) == NULL) return 0; if(sce->val4 != tid) { @@ -10545,7 +10489,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { sc = status->get_sc(bl); st = status->get_status_data(bl); - if (!(sc && (sce = sc->data[type]))) { + if (!sc || (sce = sc->data[type]) == NULL) { ShowDebug("status_change_timer: Null pointer id: %d data: %"PRIdPTR" bl-type: %d\n", id, data, bl->type); return 0; } @@ -10554,7 +10498,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); return 0; } - + sce->timer = INVALID_TIMER; sd = BL_CAST(BL_PC, bl); @@ -10633,12 +10577,12 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_STONE: if(sc->opt1 == OPT1_STONEWAIT && sce->val3) { sce->val4 = 0; - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); 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, status->ChangeFlagTable[type]); + status_calc_bl(bl, status->dbs->ChangeFlagTable[type]); return 0; } if(--(sce->val3) > 0) { @@ -10680,14 +10624,16 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { 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; + { + int i; + for (i = 0; i < MAX_PC_FEELHATE; i++) { + if (bl->m == sd->feel_map[i].m) { + //Timeout will be handled by pc->setpos + sce->timer = INVALID_TIMER; + return 0; + } } + } break; case SC_BLOODING: @@ -10874,7 +10820,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_PYREXIA: if( --(sce->val4) > 0 ) { map->freeblock_lock(); - clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); + clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,BDT_NORMAL,0); status_fix_damage(NULL,bl,100,0); if( sc->data[type] ) { sc_timer_next(3000+tick,status->change_timer,bl->id,data); @@ -10890,7 +10836,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { damage += st->vit * (sce->val1 - 3); unit->skillcastcancel(bl,2); map->freeblock_lock(); - status->damage(bl, bl, damage, 0, clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); + status->damage(bl, bl, damage, 0, clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,BDT_NORMAL,0), 1); if( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data ); } @@ -10922,7 +10868,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { unit->skillcastcancel(bl,0); do { int i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB; - mushroom_skill_id = skill->magicmushroom_db[i].skill_id; + mushroom_skill_id = skill->dbs->magicmushroom_db[i].skill_id; } while (mushroom_skill_id == 0); switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage @@ -10952,7 +10898,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if( --(sce->val4) > 0 ) { //Damage is every 10 seconds including 3%sp drain. map->freeblock_lock(); - clif->damage(bl,bl,status_get_amotion(bl),1,1,0,0,0); + clif->damage(bl,bl,status_get_amotion(bl),1,1,0,BDT_NORMAL,0); status->damage(NULL, bl, 1, st->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 ); @@ -10990,15 +10936,14 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int heal = st->max_hp * 3 / 100; if (sc->count && sc->data[SC_AKAITSUKI] && heal) heal = ~heal + 1; - + map->freeblock_lock(); - status->heal(bl, heal, 0, 2); if( sc->data[type] ) { sc_timer_next(5000 + tick, status->change_timer, bl->id, data); } map->freeblock_unlock(); - + return 0; } break; @@ -11009,7 +10954,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) map->freeblock_lock(); - clif->damage(bl,bl,0,0,damage,1,9,0); //damage is like endure effect with no walk delay + clif->damage(bl,bl,0,0,damage,1,BDT_MULTIENDURE,0); //damage is like endure effect with no walk delay status->damage(src, bl, damage, 0, 0, 1); if( sc->data[type]){ // Target still lives. [LimitLine] @@ -11111,7 +11056,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; map->freeblock_lock(); damage = sce->val3; - status->damage(src, bl, damage, 0, clif->damage(bl,bl,st->amotion,st->dmotion+200,damage,1,0,0), 1); + status->damage(src, bl, damage, 0, clif->damage(bl,bl,st->amotion,st->dmotion+200,damage,1,BDT_NORMAL,0), 1); unit->skillcastcancel(bl,1); if ( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); @@ -11157,7 +11102,6 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } break; - case SC_SATURDAY_NIGHT_FEVER: if( --(sce->val3) >= 0 ) { if( !status->charge(bl, st->max_hp * 1 / 100, st->max_sp * 1 / 100) ) @@ -11219,7 +11163,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int damage = st->max_hp / 100; // Suggestion 1% each second if( damage >= st->hp ) damage = st->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,0,0,damage,0,0,0)); + status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,0,0,damage,0,BDT_NORMAL,0)); if( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } @@ -11317,7 +11261,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { 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_walking(sd, STOPWALKING_FLAG_FIXPOS|STOPWALKING_FLAG_NEXTCELL); pc_stop_attack(sd); pc_setsit(sd); clif->sitting(bl); @@ -11501,7 +11445,7 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; + int r = status->dbs->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; if ( r ) max += (rnd() % 100) % r + 1; } @@ -11600,7 +11544,7 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; + int r = status->dbs->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; if ( r ) *matk_max += (rnd() % 100) % r + 1; } @@ -11698,7 +11642,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) { return 0; map->freeblock_lock(); - + if (type&6) //Debuffs for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) status_change_end(bl, (sc_type)i, INVALID_TIMER); @@ -11745,9 +11689,9 @@ int status_change_clear_buffs (struct block_list* bl, int type) { } status_change_end(bl, (sc_type)i, INVALID_TIMER); } - + map->freeblock_unlock(); - + return 0; } @@ -11880,7 +11824,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { if (flag&(RGN_SHP|RGN_SSP) && regen->ssregen - && (vd = status->get_viewdata(bl)) + && (vd = status->get_viewdata(bl)) != NULL && vd->dead_sit == 2 ) { //Apply sitting regen bonus. @@ -12043,7 +11987,7 @@ int status_get_refine_chance(enum refine_type wlv, int refine) { if ( refine < 0 || refine >= MAX_REFINE) return 0; - return status->refine_info[wlv].chance[refine]; + return status->dbs->refine_info[wlv].chance[refine]; } int status_get_sc_type(sc_type type) { @@ -12051,7 +11995,7 @@ int status_get_sc_type(sc_type type) { if( type <= SC_NONE || type >= SC_MAX ) return 0; - return status->sc_conf[type]; + return status->dbs->sc_conf[type]; } void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) @@ -12102,25 +12046,37 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) continue; } iidx = pc->class2idx(iclass); - status->max_weight_base[idx] = status->max_weight_base[iidx]; - memcpy(&status->aspd_base[idx], &status->aspd_base[iidx], sizeof(status->aspd_base[iidx])); + status->dbs->max_weight_base[idx] = status->dbs->max_weight_base[iidx]; + memcpy(&status->dbs->aspd_base[idx], &status->dbs->aspd_base[iidx], sizeof(status->dbs->aspd_base[iidx])); - for (i = 1; i <= MAX_LEVEL && status->HP_table[iidx][i]; i++) { - status->HP_table[idx][i] = status->HP_table[iidx][i]; + for (i = 1; i <= MAX_LEVEL && status->dbs->HP_table[iidx][i]; i++) { + status->dbs->HP_table[idx][i] = status->dbs->HP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + if (i > 2) { + if (i >= MAX_LEVEL + 1) + i = MAX_LEVEL; + avg_increment = (status->dbs->HP_table[idx][i] - base) / (i - 1); + } else { + avg_increment = 5; } - base = (i > 1 ? status->HP_table[idx][1] : 35); // Safe value if none are specified - avg_increment = (i > 2 ? (status->HP_table[idx][i] - base) / (i-1) : 5); // Safe value if none are specified for ( ; i <= pc->max_level[idx][0]; i++) { - status->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); + status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } - for (i = 1; i <= MAX_LEVEL && status->SP_table[iidx][i]; i++) { - status->SP_table[idx][i] = status->SP_table[iidx][i]; + for (i = 1; i <= MAX_LEVEL && status->dbs->SP_table[iidx][i]; i++) { + status->dbs->SP_table[idx][i] = status->dbs->SP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + if (i > 2) { + if (i >= MAX_LEVEL + 1) + i = MAX_LEVEL; + avg_increment = (status->dbs->SP_table[idx][i] - base) / (i - 1); + } else { + avg_increment = 1; } - base = (i > 1 ? status->SP_table[idx][1] : 10); // Safe value if none are specified - avg_increment = (i > 2 ? (status->SP_table[idx][i] - base) / (i-1) : 1); // Safe value if none are specified for ( ; i <= pc->max_level[idx][0]; i++) { - status->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); + status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); } } } @@ -12134,13 +12090,19 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) continue; } iidx = pc->class2idx(iclass); - for (i = 1; i <= MAX_LEVEL && status->HP_table[iidx][i]; i++) { - status->HP_table[idx][i] = status->HP_table[iidx][i]; + for (i = 1; i <= MAX_LEVEL && status->dbs->HP_table[iidx][i]; i++) { + status->dbs->HP_table[idx][i] = status->dbs->HP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + if (i > 2) { + if (i >= MAX_LEVEL + 1) + i = MAX_LEVEL; + avg_increment = (status->dbs->HP_table[idx][i] - base) / (i - 1); + } else { + avg_increment = 5; } - base = (i > 1 ? status->HP_table[idx][1] : 35); // Safe value if none are specified - avg_increment = (i > 2 ? (status->HP_table[idx][i] - base) / (i-1) : 5); // Safe value if none are specified for ( ; i <= pc->max_level[idx][0]; i++) { - status->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); + status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } } } @@ -12154,21 +12116,27 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) continue; } iidx = pc->class2idx(iclass); - for (i = 1; i <= MAX_LEVEL && status->SP_table[iidx][i]; i++) { - status->SP_table[idx][i] = status->SP_table[iidx][i]; + for (i = 1; i <= MAX_LEVEL && status->dbs->SP_table[iidx][i]; i++) { + status->dbs->SP_table[idx][i] = status->dbs->SP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + if (i > 2) { + if (i >= MAX_LEVEL + 1) + i = MAX_LEVEL; + avg_increment = (status->dbs->SP_table[idx][i] - base) / (i - 1); + } else { + avg_increment = 1; } - base = (i > 1 ? status->SP_table[idx][1] : 10); // Safe value if none are specified - avg_increment = (i > 2 ? (status->SP_table[idx][i] - base) / (i-1) : 1); // Safe value if none are specified for ( ; i <= pc->max_level[idx][0]; i++) { - status->SP_table[idx][i] = min(avg_increment * i, battle_config.max_sp); + status->dbs->SP_table[idx][i] = min(avg_increment * i, battle_config.max_sp); } } } if (libconfig->setting_lookup_int(jdb, "Weight", &i32)) - status->max_weight_base[idx] = i32; - else if (!status->max_weight_base[idx]) - status->max_weight_base[idx] = 20000; + status->dbs->max_weight_base[idx] = i32; + else if (!status->dbs->max_weight_base[idx]) + status->dbs->max_weight_base[idx] = 20000; if ((temp = libconfig->setting_get_member(jdb, "BaseASPD"))) { int widx = 0; @@ -12179,7 +12147,7 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) ARR_FIND(0, wlen, w, strcmp(wnames[w].name, wname) == 0); if (w != wlen) { - status->aspd_base[idx][wnames[w].id] = libconfig->setting_get_int(wpn); + status->dbs->aspd_base[idx][wnames[w].id] = libconfig->setting_get_int(wpn); } else { ShowWarning("status_read_job_db: unknown weapon type '%s'!\n", wname); } @@ -12189,28 +12157,40 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) if ((temp = libconfig->setting_get_member(jdb, "HPTable"))) { int level = 0, avg_increment, base; config_setting_t *hp = NULL; - while (level <= MAX_LEVEL && (hp = libconfig->setting_get_elem(temp, level))) { + while (level <= MAX_LEVEL && (hp = libconfig->setting_get_elem(temp, level)) != NULL) { i32 = libconfig->setting_get_int(hp); - status->HP_table[idx][++level] = min(i32, battle_config.max_hp); + status->dbs->HP_table[idx][++level] = min(i32, battle_config.max_hp); + } + base = (level > 0 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + if (level > 2) { + if (level >= MAX_LEVEL + 1) + level = MAX_LEVEL; + avg_increment = (status->dbs->HP_table[idx][level] - base) / level; + } else { + avg_increment = 5; } - base = (level > 0 ? status->HP_table[idx][1] : 35); // Safe value if none are specified - avg_increment = (level > 1 ? (status->HP_table[idx][level] - base) / level : 5); // Safe value if none are specified for (++level; level <= pc->max_level[idx][0]; ++level) { /* limit only to possible maximum level of the given class */ - status->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */ + status->dbs->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */ } } if ((temp = libconfig->setting_get_member(jdb, "SPTable"))) { int level = 0, avg_increment, base; config_setting_t *sp = NULL; - while (level <= MAX_LEVEL && (sp = libconfig->setting_get_elem(temp, level))) { + while (level <= MAX_LEVEL && (sp = libconfig->setting_get_elem(temp, level)) != NULL) { i32 = libconfig->setting_get_int(sp); - status->SP_table[idx][++level] = min(i32, battle_config.max_sp); + status->dbs->SP_table[idx][++level] = min(i32, battle_config.max_sp); + } + base = (level > 0 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + if (level > 2) { + if (level >= MAX_LEVEL + 1) + level = MAX_LEVEL; + avg_increment = (status->dbs->SP_table[idx][level] - base) / level; + } else { + avg_increment = 1; } - base = (level > 0 ? status->SP_table[idx][1] : 10); // Safe value if none are specified - avg_increment = (level > 1 ? (status->SP_table[idx][level] - base) / level : 1); for ( ; level <= pc->max_level[idx][0]; level++ ) { - status->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp); + status->dbs->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp); } } } @@ -12226,11 +12206,10 @@ void status_read_job_db(void) { /* [malufett/Hercules] */ int i = 0; config_t job_db_conf; config_setting_t *jdb = NULL; - const char *config_filename = #ifdef RENEWAL_ASPD - "db/re/job_db.conf"; + const char *config_filename = "db/re/job_db.conf"; #else - "db/pre-re/job_db.conf"; + const char *config_filename = "db/pre-re/job_db.conf"; #endif if ( libconfig->read_file(&job_db_conf, config_filename) ) { @@ -12268,7 +12247,7 @@ bool status_readdb_job2(char* fields[], int columns, int current) for(i = 1; i < columns; i++) { - status->job_bonus[idx][i-1] = atoi(fields[i]); + status->dbs->job_bonus[idx][i-1] = atoi(fields[i]); } return true; } @@ -12279,7 +12258,7 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) for(i = 0; i < MAX_WEAPON_TYPE; i++) { - status->atkmods[current][i] = atoi(fields[i]); + status->dbs->atkmods[current][i] = atoi(fields[i]); } return true; } @@ -12306,14 +12285,14 @@ bool status_readdb_refine(char* fields[], int columns, int current) *delim = '\0'; - status->refine_info[current].chance[i] = atoi(fields[4+i]); + status->dbs->refine_info[current].chance[i] = atoi(fields[4+i]); if (i >= random_bonus_start_level - 1) - status->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); + status->dbs->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); - status->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); + status->dbs->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); if (i > 0) - status->refine_info[current].bonus[i] += status->refine_info[current].bonus[i-1]; + status->dbs->refine_info[current].bonus[i] += status->dbs->refine_info[current].bonus[i-1]; } return true; } @@ -12327,7 +12306,7 @@ bool status_readdb_scconfig(char* fields[], int columns, int current) { return false; } - status->sc_conf[val] = (int)strtol(fields[1], NULL, 0); + status->dbs->sc_conf[val] = (int)strtol(fields[1], NULL, 0); return true; } @@ -12344,41 +12323,41 @@ int status_readdb(void) // initialize databases to default // - if( runflag == MAPSERVER_ST_RUNNING ) {//not necessary during boot + if( core->runflag == MAPSERVER_ST_RUNNING ) {//not necessary during boot // reset job_db.conf data - memset(status->max_weight_base, 0, sizeof(status->max_weight_base)); - memset(status->HP_table, 0, sizeof(status->HP_table)); - memset(status->SP_table, 0, sizeof(status->SP_table)); + memset(status->dbs->max_weight_base, 0, sizeof(status->dbs->max_weight_base)); + memset(status->dbs->HP_table, 0, sizeof(status->dbs->HP_table)); + memset(status->dbs->SP_table, 0, sizeof(status->dbs->SP_table)); // reset job_db2.txt data - memset(status->job_bonus,0,sizeof(status->job_bonus)); // Job-specific stats bonus + memset(status->dbs->job_bonus,0,sizeof(status->dbs->job_bonus)); // Job-specific stats bonus } for ( i = 0; i < CLASS_COUNT; i++ ) { for ( j = 0; j < MAX_WEAPON_TYPE; j++ ) - status->aspd_base[i][j] = 2000; + status->dbs->aspd_base[i][j] = 2000; #ifdef RENEWAL_ASPD - status->aspd_base[i][MAX_WEAPON_TYPE] = 0; + status->dbs->aspd_base[i][MAX_WEAPON_TYPE] = 0; #endif } // size_fix.txt - for(i = 0; i < ARRAYLENGTH(status->atkmods); i++) + for(i = 0; i < ARRAYLENGTH(status->dbs->atkmods); i++) for(j = 0; j < MAX_WEAPON_TYPE; j++) - status->atkmods[i][j] = 100; + status->dbs->atkmods[i][j] = 100; // refine_db.txt - for(i=0;i<ARRAYLENGTH(status->refine_info);i++) { + for(i=0;i<ARRAYLENGTH(status->dbs->refine_info);i++) { for(j=0;j<MAX_REFINE; j++) { - status->refine_info[i].chance[j] = 100; - status->refine_info[i].bonus[j] = 0; - status->refine_info[i].randombonus_max[j] = 0; + status->dbs->refine_info[i].chance[j] = 100; + status->dbs->refine_info[i].bonus[j] = 0; + status->dbs->refine_info[i].randombonus_max[j] = 0; } } // read databases // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); - sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix); - sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->refine_info), status->readdb_refine); + sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); + sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->dbs->refine_info), status->readdb_refine); sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); status->read_job_db(); @@ -12414,6 +12393,7 @@ void do_final_status(void) { *-------------------------------------*/ void status_defaults(void) { status = &status_s; + status->dbs = &statusdbs; /* vars */ //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only @@ -12421,21 +12401,8 @@ void status_defaults(void) { status->current_equip_item_index = 0; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus] status->current_equip_card_id = 0; //To prevent card-stacking (from jA) [Skotlex] - memset(status->max_weight_base,0,sizeof(status->max_weight_base) - + sizeof(status->HP_table) - + sizeof(status->SP_table) - + sizeof(status->aspd_base) - + sizeof(status->Skill2SCTable) - + sizeof(status->IconChangeTable) - + sizeof(status->ChangeFlagTable) - + sizeof(status->SkillChangeTable) - + sizeof(status->RelevantBLTypes) - + sizeof(status->DisplayType) - + sizeof(status->refine_info) - + sizeof(status->atkmods) - + sizeof(status->job_bonus) - + sizeof(status->sc_conf) - ); + // These macros are used instead of a sum of sizeof(), to ensure that padding won't interfere with our size, and code won't rot when adding more fields + memset(ZEROED_BLOCK_POS(status->dbs), 0, ZEROED_BLOCK_SIZE(status->dbs)); status->data_ers = NULL; memset(&status->dummy, 0, sizeof(status->dummy)); @@ -12497,6 +12464,7 @@ void status_defaults(void) { status->calc_mob_ = status_calc_mob_; status->calc_pet_ = status_calc_pet_; status->calc_pc_ = status_calc_pc_; + status->calc_pc_additional = status_calc_pc_additional; status->calc_homunculus_ = status_calc_homunculus_; status->calc_mercenary_ = status_calc_mercenary_; status->calc_elemental_ = status_calc_elemental_; diff --git a/src/map/status.h b/src/map/status.h index 3b85c4014..274c64c5b 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -5,10 +5,9 @@ #ifndef MAP_STATUS_H #define MAP_STATUS_H -#include "../config/core.h" // defType, RENEWAL, RENEWAL_ASPD -#include "../common/conf.h" -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // NEW_CARTS +#include "common/conf.h" +#include "common/hercules.h" +#include "common/mmo.h" // NEW_CARTS struct block_list; struct elemental_data; @@ -1655,49 +1654,6 @@ enum { 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_HANBOK = 0x08000000, - OPTION_OKTOBERFEST = 0x10000000, - -#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, -#endif - - // compound constants - OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, - OPTION_COSTUME = OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST, -}; - //Defines for the manner system [Skotlex] enum manner_flags { @@ -1970,17 +1926,8 @@ struct s_refine_info { int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage }; -/*===================================== -* Interface : status.h -* Generated by HerculesInterfaceMaker -* created by Susu -*-------------------------------------*/ -struct status_interface { - - /* vars */ - int current_equip_item_index; - int current_equip_card_id; - /* */ +struct s_status_dbs { +BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */ int max_weight_base[CLASS_COUNT]; int HP_table[CLASS_COUNT][MAX_LEVEL + 1]; int SP_table[CLASS_COUNT][MAX_LEVEL + 1]; @@ -1997,6 +1944,22 @@ struct status_interface { int atkmods[3][MAX_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt) char job_bonus[CLASS_COUNT][MAX_LEVEL]; sc_conf_type sc_conf[SC_MAX]; +END_ZEROED_BLOCK; /* End */ +}; + +/*===================================== +* Interface : status.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct status_interface { + + /* vars */ + int current_equip_item_index; + int current_equip_card_id; + + struct s_status_dbs *dbs; + struct eri *data_ers; //For sc_data entries struct status_data dummy; int64 natural_heal_prev_tick; @@ -2054,6 +2017,7 @@ struct status_interface { int (*calc_mob_) (struct mob_data* md, enum e_status_calc_opt opt); int (*calc_pet_) (struct pet_data* pd, enum e_status_calc_opt opt); int (*calc_pc_) (struct map_session_data* sd, enum e_status_calc_opt opt); + void (*calc_pc_additional) (struct map_session_data* sd, enum e_status_calc_opt opt); int (*calc_homunculus_) (struct homun_data *hd, enum e_status_calc_opt opt); int (*calc_mercenary_) (struct mercenary_data *md, enum e_status_calc_opt opt); int (*calc_elemental_) (struct elemental_data *ed, enum e_status_calc_opt opt); @@ -2119,10 +2083,10 @@ struct status_interface { void (*read_job_db_sub) (int idx, const char *name, config_setting_t *jdb); }; -struct status_interface *status; - #ifdef HERCULES_CORE void status_defaults(void); #endif // HERCULES_CORE +HPShared struct status_interface *status; + #endif /* MAP_STATUS_H */ diff --git a/src/map/storage.c b/src/map/storage.c index 79a5ad52d..fb6e2ed45 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -6,28 +6,31 @@ #include "storage.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" // struct map_session_data +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" // struct map_session_data -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" - struct storage_interface storage_s; struct guild_storage_interface gstorage_s; +struct storage_interface *storage; +struct guild_storage_interface *gstorage; + /*========================================== * Sort items in the warehouse *------------------------------------------*/ @@ -83,7 +86,7 @@ int storage_storageopen(struct map_session_data *sd) { nullpo_ret(sd); - if(sd->state.storage_flag) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) return 1; //Already open? if( !pc_can_give_items(sd) ) { @@ -92,7 +95,7 @@ int storage_storageopen(struct map_session_data *sd) return 1; } - sd->state.storage_flag = 1; + sd->state.storage_flag = STORAGE_FLAG_NORMAL; 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); @@ -109,7 +112,8 @@ int compare_item(struct item *a, struct item *b) a->refine == b->refine && a->attribute == b->attribute && a->expire_time == b->expire_time && - a->bound == b->bound ) + a->bound == b->bound && + a->unique_id == b->unique_id) { int i; for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); @@ -155,6 +159,7 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo {// 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; @@ -190,9 +195,11 @@ int storage_delitem(struct map_session_data* sd, int n, int amount) { 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 == STORAGE_FLAG_NORMAL ) + clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); } - if( sd->state.storage_flag == 1 ) clif->storageitemremoved(sd,n,amount); + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) + clif->storageitemremoved(sd,n,amount); return 0; } @@ -219,9 +226,9 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) { return 0; if( storage->additem(sd,&sd->status.inventory[index],amount) == 0 ) - pc->delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); + pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_STORAGE); else - clif->dropitem(sd, index,0); + clif->dropitem(sd, index, 0); return 1; } @@ -325,7 +332,7 @@ void storage_storageclose(struct map_session_data* sd) { if( map->save_settings&4 ) chrif->save(sd,0); //Invokes the storage saving as well. - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; } /*========================================== @@ -337,7 +344,7 @@ void storage_storage_quit(struct map_session_data* sd, int flag) { if (map->save_settings&4) chrif->save(sd, flag); //Invokes the storage saving as well. - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; } /** @@ -380,7 +387,7 @@ int storage_guild_storageopen(struct map_session_data* sd) if(sd->status.guild_id <= 0) return 2; - if(sd->state.storage_flag) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) 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] @@ -399,7 +406,7 @@ int storage_guild_storageopen(struct map_session_data* sd) return 1; gstor->storage_status = 1; - sd->state.storage_flag = 2; + sd->state.storage_flag = STORAGE_FLAG_GUILD; storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items)); clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); @@ -525,10 +532,10 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) return 0; } - if(gstorage->additem(sd,stor,&sd->status.inventory[index],amount)==0) - pc->delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); + if( gstorage->additem(sd,stor,&sd->status.inventory[index],amount) == 0 ) + pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_GSTORAGE); else - clif->dropitem(sd, index,0); + clif->dropitem(sd, index, 0); return 1; } @@ -694,7 +701,7 @@ int storage_guild_storageclose(struct map_session_data* sd) { gstorage->save(sd->status.account_id, sd->status.guild_id,0); stor->storage_status=0; } - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; return 0; } @@ -707,7 +714,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) { if(flag) { //Only during a guild break flag is 1 (don't save storage) - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; stor->storage_status = 0; clif->storageclose(sd); if (map->save_settings&4) @@ -721,7 +728,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) { else gstorage->save(sd->status.account_id,sd->status.guild_id,1); } - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; stor->storage_status = 0; return 0; diff --git a/src/map/storage.h b/src/map/storage.h index 6393e124a..37f894f76 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -5,13 +5,22 @@ #ifndef MAP_STORAGE_H #define MAP_STORAGE_H -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/hercules.h" +#include "common/db.h" struct guild_storage; struct item; struct map_session_data; +/** + * Acceptable values for map_session_data.state.storage_flag + */ +enum storage_flag { + STORAGE_FLAG_CLOSED = 0, // Closed + STORAGE_FLAG_NORMAL = 1, // Normal Storage open + STORAGE_FLAG_GUILD = 2, // Guild Storage open +}; + struct storage_interface { /* */ void (*reconnect) (void); @@ -29,7 +38,6 @@ struct storage_interface { void (*sortitem) (struct item* items, unsigned int size); int (*reconnect_sub) (DBKey key, DBData *data, va_list ap); }; -struct storage_interface *storage; struct guild_storage_interface { struct DBMap* db; // int guild_id -> struct guild_storage* @@ -54,11 +62,12 @@ struct guild_storage_interface { DBData (*create) (DBKey key, va_list args); }; -struct guild_storage_interface *gstorage; - #ifdef HERCULES_CORE void storage_defaults(void); void gstorage_defaults(void); #endif // HERCULES_CORE +HPShared struct storage_interface *storage; +HPShared struct guild_storage_interface *gstorage; + #endif /* MAP_STORAGE_H */ diff --git a/src/map/trade.c b/src/map/trade.c index 7417f05af..8af3ddf4a 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -6,25 +6,26 @@ #include "trade.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/storage.h" +#include "common/nullpo.h" +#include "common/socket.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "storage.h" -#include "../common/nullpo.h" -#include "../common/socket.h" - struct trade_interface trade_s; +struct trade_interface *trade; /*========================================== * Initiates a trade request. @@ -145,8 +146,8 @@ void trade_tradeack(struct map_session_data *sd, int type) { } //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 + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED + || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED ) { //Fail clif->tradestart(sd, 2); @@ -208,14 +209,14 @@ int impossible_trade_check(struct map_session_data *sd) intif->wis_message_to_gm(map->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 + chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0); + sockt->eof(sd->fd); // forced to disconnect because of the hack // message about the ban safestrncpy(message_to_gm, msg_txt(540), sizeof(message_to_gm)); // 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 + chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BAN, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second) + sockt->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 @@ -561,7 +562,7 @@ void trade_tradecommit(struct map_session_data *sd) { 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); + pc->delitem(sd, n, sd->deal.item[trade_i].amount, 1, DELITEM_SOLD, LOG_TYPE_TRADE); else clif->additem(sd, n, sd->deal.item[trade_i].amount, 0); sd->deal.item[trade_i].index = 0; @@ -573,7 +574,7 @@ void trade_tradecommit(struct map_session_data *sd) { 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); + pc->delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, DELITEM_SOLD, LOG_TYPE_TRADE); else clif->additem(tsd, n, tsd->deal.item[trade_i].amount, 0); tsd->deal.item[trade_i].index = 0; diff --git a/src/map/trade.h b/src/map/trade.h index 85e73025c..010f67e26 100644 --- a/src/map/trade.h +++ b/src/map/trade.h @@ -5,6 +5,8 @@ #ifndef MAP_TRADE_H #define MAP_TRADE_H +#include "common/hercules.h" + //Max distance from traders to enable a trade to take place. //TODO: battle_config candidate? #define TRADE_DISTANCE 2 @@ -23,10 +25,10 @@ struct trade_interface { void (*commit) (struct map_session_data *sd); }; -struct trade_interface *trade; - #ifdef HERCULES_CORE void trade_defaults(void); #endif // HERCULES_CORE +HPShared struct trade_interface *trade; + #endif /* MAP_TRADE_H */ diff --git a/src/map/unit.c b/src/map/unit.c index b44d58d9a..04a8befc2 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -4,51 +4,52 @@ #define HERCULES_CORE -#include "../config/core.h" // RENEWAL_CAST +#include "config/core.h" // RENEWAL_CAST #include "unit.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/vending.h" +#include "common/HPM.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "battleground.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.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_interface unit_s; +struct unit_interface *unit; /** * Returns the unit_data for the given block_list. If the object is using @@ -97,11 +98,11 @@ int unit_walktoxy_sub(struct block_list *bl) memset(&wpd, 0, sizeof(wpd)); - if( !path->search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) ) + if( !path->search(&wpd,bl,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) ) return 0; #ifdef OFFICIAL_WALKPATH - if( !path->search_long(NULL, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between + if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] && (bl->type != BL_NPC) ) // If type is a NPC, please disregard. return 0; @@ -267,13 +268,13 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { icewall_walk_block = 0; //Monsters will walk into an icewall from the west and south if they already started walking - if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS) - && (icewall_walk_block == 0 || !map->getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL) || dx < 0 || dy < 0)) + if (map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKNOPASS) + && (icewall_walk_block == 0 || !map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKICEWALL) || dx < 0 || dy < 0)) return unit->walktoxy_sub(bl); //Monsters can only leave icewalls to the west and south //But if movement fails more than icewall_walk_block times, they can ignore this rule - if(md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) { + if (md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m, bl, x, y, CELL_CHKICEWALL) && (dx > 0 || dy > 0)) { //Needs to be done here so that rudeattack skills are invoked md->walktoxy_fail_count++; clif->fixpos(bl); @@ -305,7 +306,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { if(sd) { if( sd->touching_id ) npc->touchnext_areanpc(sd,false); - if(map->getcell(bl->m,x,y,CELL_CHKNPC)) { + if (map->getcell(bl->m, bl, 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; @@ -337,7 +338,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { } else if (md) { //Movement was successful, reset walktoxy_fail_count md->walktoxy_fail_count = 0; - if( map->getcell(bl->m,x,y,CELL_CHKNPC) ) { + if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC)) { if( npc->touch_areanpc2(md) ) return 0; // Warped } else md->areanpc_id = 0; @@ -493,14 +494,14 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) if( ud == NULL) return 0; - if (battle_config.check_occupied_cells && (flag&8) && !map->closest_freecell(bl->m, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y + if (battle_config.check_occupied_cells && (flag&8) && !map->closest_freecell(bl->m, bl, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y return 0; - if (!path->search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells + if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells return 0; #ifdef OFFICIAL_WALKPATH - if( !path->search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between + if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between && (wpd.path_len > (battle_config.max_walk_path/17)*14) // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] && (bl->type != BL_NPC) ) // If type is a NPC, please disregard. return 0; @@ -682,7 +683,7 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type // Search for available path for(i = 0; i < AREA_SIZE; i++) { - if(!map->getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) + if (!map->getcell(bl->m, bl, to_x + dir_x, to_y + dir_y, CELL_CHKPASS)) break; //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] @@ -719,7 +720,7 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type //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) { uint8 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) ) + while (dist > 0 && map->getcell(bl->m, bl, 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) ); } @@ -737,10 +738,10 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if( ud == NULL) return 0; - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); 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)) ) + if (checkpath && (map->getcell(bl->m, bl, dst_x, dst_y, CELL_CHKNOPASS) || !path->search(NULL, bl, bl->m, bl->x, bl->y, dst_x, dst_y, easy, CELL_CHKNOREACH)) ) return 0; // unreachable ud->to_x = dst_x; @@ -763,7 +764,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if(sd) { if( sd->touching_id ) npc->touchnext_areanpc(sd,false); - if(map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) { + if (map->getcell(bl->m, bl, 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; @@ -774,7 +775,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool { // Check if pet needs to be teleported. [Skotlex] int flag = 0; struct block_list* pbl = &sd->pd->bl; - if( !checkpath && !path->search(NULL,pbl->m,pbl->x,pbl->y,dst_x,dst_y,0,CELL_CHKNOPASS) ) + if( !checkpath && !path->search(NULL,pbl,pbl->m,pbl->x,pbl->y,dst_x,dst_y,0,CELL_CHKNOPASS) ) flag = 1; else if (!check_distance_bl(&sd->bl, pbl, AREA_SIZE)) //Too far, teleport. flag = 2; @@ -828,13 +829,13 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) sd = BL_CAST(BL_PC, bl); su = BL_CAST(BL_SKILL, bl); - result = path->blownpos(bl->m, bl->x, bl->y, dx, dy, count); + result = path->blownpos(bl, bl->m, bl->x, bl->y, dx, dy, count); nx = result>>16; ny = result&0xffff; if(!su) { - unit->stop_walking(bl, 0); + unit->stop_walking(bl, STOPWALKING_FLAG_NONE); } if( sd ) { @@ -865,7 +866,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) if(sd->touching_id) { npc->touchnext_areanpc(sd, false); } - if(map->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) { + if (map->getcell(bl->m, bl, bl->x, bl->y, CELL_CHKNPC)) { npc->touch_areanpc(sd, bl->m, bl->x, bl->y); } else { npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);; @@ -918,7 +919,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) return 2; } - } else if (map->getcell(m,x,y,CELL_CHKNOREACH)) { + } else if (map->getcell(m, bl, x, y, CELL_CHKNOREACH)) { //Invalid target cell ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map->list[m].name, x,y); @@ -952,14 +953,10 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) /*========================================== * Caused the target object to stop moving. - * Flag values: - * &0x1: Issue a fixpos packet afterwards - * &0x2: Force the unit to move one cell if it hasn't yet - * &0x4: Enable moving to the next cell when unit was already half-way there - * (may cause on-touch/place side-effects, such as a scripted map change) + * Flag values: @see unit_stopwalking_flag. + * Upper bytes may be used for other purposes depending on the unit type. *------------------------------------------*/ -int unit_stop_walking(struct block_list *bl,int type) -{ +int unit_stop_walking(struct block_list *bl, int flag) { struct unit_data *ud; const struct TimerData* td; int64 tick; @@ -976,22 +973,22 @@ int unit_stop_walking(struct block_list *bl,int type) ud->walktimer = INVALID_TIMER; ud->state.change_walk_target = 0; tick = timer->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 + if( (flag&STOPWALKING_FLAG_ONESTEP && !ud->walkpath.path_pos) //Force moving at least one cell. + || (flag&STOPWALKING_FLAG_NEXTCELL && 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) + if(flag&STOPWALKING_FLAG_FIXPOS) 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 = timer->gettick() + (type>>8); + if(bl->type == BL_PET && flag&~STOPWALKING_FLAG_MASK) + ud->canmove_tick = timer->gettick() + (flag>>8); //Read, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin] if (ud->state.running) { @@ -1107,8 +1104,8 @@ int unit_can_move(struct block_list *bl) { // Icewall walk block special trapped monster mode if(bl->type == BL_MOB) { struct mob_data *md = BL_CAST(BL_MOB, bl); - if(md && ((md->status.mode&MD_BOSS && battle_config.boss_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)) - || (!(md->status.mode&MD_BOSS) && battle_config.mob_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)))) { + if (md && ((md->status.mode&MD_BOSS && battle_config.boss_icewall_walk_block == 1 && map->getcell(bl->m, bl, bl->x, bl->y, CELL_CHKICEWALL)) + || (!(md->status.mode&MD_BOSS) && battle_config.mob_icewall_walk_block == 1 && map->getcell(bl->m, bl, bl->x, bl->y, CELL_CHKICEWALL)))) { md->walktoxy_fail_count = 1; //Make sure rudeattacked skills are invoked return 0; } @@ -1169,17 +1166,14 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) { //Stop walking, if chasing, readjust timers. if (delay == 1) { //Minimal delay (walk-delay) disabled. Just stop walking. - unit->stop_walking(bl,4); + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); } else { //Resume running after can move again [Kevin] - if(ud->state.running) - { + if (ud->state.running) { timer->add(ud->canmove_tick, unit->resume_running, bl->id, (intptr_t)ud); - } - else - { - unit->stop_walking(bl,4); - if(ud->target) + } else { + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); + if (ud->target) timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target); } } @@ -1354,18 +1348,21 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } } - if (sd || src->type == BL_HOM){ - if (!sd && (target = battle->get_master(src))) - sd = map->id2sd(target->id); - if (sd){ - /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ + if (src->type == BL_HOM) { + // In case of homunuculus, set the sd to the homunculus' master, as needed below + struct block_list *master = battle->get_master(src); + if (master) + sd = map->id2sd(master->id); + } + + if (sd) { + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ #if 0 - if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) + if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) #else - if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) + if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) #endif - return 0; - } + return 0; } if( src->type == BL_MOB ) @@ -1373,7 +1370,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui case NPC_SUMMONSLAVE: case NPC_SUMMONMONSTER: case AL_TELEPORT: - if( ((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai ) + if (((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai != AI_NONE) return 0; } @@ -1544,8 +1541,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } } - if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 - unit->stop_walking(src,1);// even though this is not how official works but this will do the trick. bugreport:6829 + if (!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);// even though 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_id, skill->get_ele(skill_id, skill_lv), casttime); @@ -1654,14 +1651,14 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui * "WHY IS IT HEREE": ice wall cannot be canceled past this point, the client displays the animation even, * if we cancel it from castend_pos, so it has to be here for it to not display the animation. **/ - if ( skill_id == WZ_ICEWALL && map->getcell(src->m, skill_x, skill_y, CELL_CHKNOICEWALL) ) + if (skill_id == WZ_ICEWALL && map->getcell(src->m, src, skill_x, skill_y, CELL_CHKNOICEWALL)) return 0; } if (!status->check_skilluse(src, NULL, skill_id, 0)) return 0; - if( map->getcell(src->m, skill_x, skill_y, CELL_CHKWALL) ) { + if (map->getcell(src->m, src, skill_x, skill_y, CELL_CHKWALL)) { // can't cast ground targeted spells on wall cells if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; @@ -1742,7 +1739,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui } } - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); // in official this is triggered even if no cast time. clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime); if( casttime > 0 ) { @@ -1768,10 +1765,10 @@ int unit_set_target(struct unit_data* ud, int target_id) if (ud->target != target_id) { struct unit_data * ux; struct block_list* target; - 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 = map->id2bl(ud->target)) != NULL && (ux = unit->bl2ud(target)) != NULL && ux->target_count > 0) + --ux->target_count; + if (target_id && (target = map->id2bl(target_id)) != NULL && (ux = unit->bl2ud(target)) != NULL) + ++ux->target_count; } ud->target = target_id; @@ -1943,7 +1940,7 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy) 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,bl->m,bl->x,bl->y,x,y,easy,CELL_CHKNOREACH); } /*========================================== @@ -1970,10 +1967,10 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, 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)) { + if (map->getcell(tbl->m, bl, tbl->x - dx, tbl->y - dy, CELL_CHKNOPASS)) { int i; //Look for a suitable cell to place in. - for(i=0;i<8 && map->getcell(tbl->m,tbl->x-dirx[i],tbl->y-diry[i],CELL_CHKNOPASS);i++); + for (i=0;i<8 && map->getcell(tbl->m, bl, tbl->x - dirx[i], tbl->y - diry[i], CELL_CHKNOPASS); i++); if (i==8) return false; //No valid cells. dx = dirx[i]; dy = diry[i]; @@ -1981,7 +1978,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, 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); + return path->search(NULL,bl,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH); } /*========================================== * Calculates position of Pet/Mercenary/Homunculus/Elemental @@ -2067,7 +2064,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { 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, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) #endif || (sd && !pc->can_attack(sd, ud->target) ) ) @@ -2102,7 +2099,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { range = sstatus->rhw.range; if( (unit->is_walking(target) || ud->state.step_attack) - && (target->type == BL_PC || !map->getcell(target->m,target->x,target->y,CELL_CHKICEWALL)) ) + && (target->type == BL_PC || !map->getcell(target->m, src, target->x, target->y, CELL_CHKICEWALL))) range++; // Extra range when chasing (does not apply to mobs locked in an icewall) if(sd && !check_distance_client_bl(src,target,range)) { @@ -2131,7 +2128,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { ud->dir = map->calc_dir(src, target->x,target->y ); } if(ud->walktimer != INVALID_TIMER) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if(md) { //First attack is always a normal attack if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) { @@ -2271,7 +2268,7 @@ void unit_dataset(struct block_list *bl) { int unit_counttargeted(struct block_list* bl) { struct unit_data* ud; - if( bl && (ud = unit->bl2ud(bl)) ) + if (bl && (ud = unit->bl2ud(bl)) != NULL) return ud->target_count; return 0; } @@ -2326,7 +2323,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i map->freeblock_lock(); if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(bl,0); + unit->stop_walking(bl, STOPWALKING_FLAG_NONE); if (ud->skilltimer != INVALID_TIMER) unit->skillcastcancel(bl,0); @@ -2395,18 +2392,18 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i } //Leave/reject all invitations. if(sd->chatID) - chat->leave(sd,0); + chat->leave(sd, false); if(sd->trade_partner) trade->cancel(sd); buyingstore->close(sd); searchstore->close(sd); if( sd->menuskill_id != AL_TELEPORT ) { // issue: 8027 - if(sd->state.storage_flag == 1) + if(sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->pc_quit(sd,0); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->pc_quit(sd,0); - sd->state.storage_flag = 0; //Force close it when being warped. + sd->state.storage_flag = STORAGE_FLAG_CLOSED; //Force close it when being warped. } if(sd->party_invite>0) party->reply_invite(sd,sd->party_invite,0); diff --git a/src/map/unit.h b/src/map/unit.h index 881fa16f4..0d970ca16 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -5,14 +5,27 @@ #ifndef MAP_UNIT_H #define MAP_UNIT_H -#include "clif.h" // clr_type -#include "path.h" // struct walkpath_data -#include "skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset -#include "../common/cbasetypes.h" +#include "map/clif.h" // clr_type +#include "map/path.h" // struct walkpath_data +#include "map/skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset +#include "common/hercules.h" struct map_session_data; struct block_list; +/** + * Bitmask values usable as a flag in unit_stopwalking + */ +enum unit_stopwalking_flag { + STOPWALKING_FLAG_NONE = 0x00, + STOPWALKING_FLAG_FIXPOS = 0x01, ///< Issue a fixpos packet afterwards + STOPWALKING_FLAG_ONESTEP = 0x02, ///< Force the unit to move one cell if it hasn't yet + STOPWALKING_FLAG_NEXTCELL = 0x04, ///< Enable moving to the next cell when unit was already half-way there + /// (may cause on-touch/place side-effects, such as a scripted map change) + STOPWALKING_FLAG_MASK = 0xff, ///< Mask all of the above + // Note: Upper bytes are reserved for duration. +}; + struct unit_data { struct block_list *bl; struct walkpath_data walkpath; @@ -71,9 +84,6 @@ struct view_data { unsigned dead_sit : 2; }; -extern const short dirx[8]; -extern const short diry[8]; - struct unit_interface { int (*init) (bool minimal); int (*final) (void); @@ -126,8 +136,13 @@ struct unit_interface { int (*free) (struct block_list *bl, clr_type clrtype); }; -struct unit_interface *unit; +#ifdef HERCULES_CORE +extern const short dirx[8]; +extern const short diry[8]; void unit_defaults(void); +#endif // HERCULES_CORE + +HPShared struct unit_interface *unit; #endif /* MAP_UNIT_H */ diff --git a/src/map/vending.c b/src/map/vending.c index 8ae3f36a4..80c79984e 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -6,25 +6,26 @@ #include "vending.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/skill.h" +#include "common/nullpo.h" +#include "common/strlib.h" +#include "common/utils.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "skill.h" -#include "../common/nullpo.h" -#include "../common/strlib.h" -#include "../common/utils.h" - struct vending_interface vending_s; +struct vending_interface *vending; /// Returns an unique vending shop id. static inline unsigned int getid(void) { @@ -38,7 +39,7 @@ void vending_closevending(struct map_session_data* sd) { nullpo_retv(sd); if( sd->state.vending ) { - sd->state.vending = false; + sd->state.vending = 0; clif->closevendingboard(&sd->bl, 0); idb_remove(vending->db, sd->status.char_id); } diff --git a/src/map/vending.h b/src/map/vending.h index 00d3eefff..2f624fac7 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -5,8 +5,8 @@ #ifndef MAP_VENDING_H #define MAP_VENDING_H -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/hercules.h" +#include "common/db.h" struct map_session_data; struct s_search_store_search; @@ -32,10 +32,10 @@ struct vending_interface { bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s); }; -struct vending_interface *vending; - #ifdef HERCULES_CORE void vending_defaults(void); #endif // HERCULES_CORE +HPShared struct vending_interface *vending; + #endif /* MAP_VENDING_H */ |