diff options
Diffstat (limited to 'src/map')
82 files changed, 4875 insertions, 3972 deletions
diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt deleted file mode 100644 index 51c3538ef..000000000 --- a/src/map/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ - -# -# setup -# -set( MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" ) -set( SQL_MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" ) - - -# -# targets -# -add_subdirectory( sql ) diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index 061479d87..cb8c979c6 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -1,25 +1,15 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/HPM.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/des.h" -#include "../common/ers.h" -#include "../common/mapindex.h" -#include "../common/mmo.h" -#include "../common/socket.h" -#include "../common/strlib.h" - +#define HERCULES_CORE #include "HPMmap.h" -#include "pc.h" -#include "map.h" -// +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + #include "atcommand.h" #include "battle.h" #include "battleground.h" @@ -37,12 +27,14 @@ #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" @@ -54,11 +46,19 @@ #include "trade.h" #include "unit.h" #include "vending.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.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" diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index f291575fb..99c4224ff 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -1,8 +1,8 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _MAP_HPMMAP_H_ -#define _MAP_HPMMAP_H_ +#ifndef MAP_HPMMAP_H +#define MAP_HPMMAP_H #include "../common/cbasetypes.h" #include "../map/atcommand.h" @@ -26,4 +26,4 @@ bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name void HPM_map_do_init(void); -#endif /* _MAP_HPMMAP_H_ */ +#endif /* MAP_HPMMAP_H */ diff --git a/src/map/Makefile.in b/src/map/Makefile.in index e3a47abeb..fc58c9d70 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -1,9 +1,14 @@ +# Copyright (c) Hercules Dev Team, licensed under GNU GPL. +# See the LICENSE file + +# @configure_input@ CONFIG_D = ../config 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 LIBCONFIG_D = ../../3rdparty/libconfig LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \ @@ -33,7 +38,7 @@ MAP_H = atcommand.h battle.h battleground.h buyingstore.h chat.h chrif.h \ HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) - MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) + MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ $(SYSINFO_INC)) else MAP_SERVER_SQL_DEPENDS=needs_mysql endif @@ -79,6 +84,10 @@ help: Makefile: Makefile.in @$(MAKE) -C ../.. src/map/Makefile +$(SYSINFO_INC): $(MAP_C) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) + @echo " MAKE $@" + @$(MAKE) -C ../.. sysinfo + needs_mysql: @echo "MySQL not found or disabled by the configure script" @exit 1 @@ -102,7 +111,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@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_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 9e33f3c68..e22e2101c 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -2,55 +2,59 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/mmo.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/core.h" -#include "../common/showmsg.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/conf.h" +#define HERCULES_CORE +#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP #include "atcommand.h" + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "HPMmap.h" #include "battle.h" #include "chat.h" -#include "clif.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 "pc.h" -#include "pc_groups.h" // groupid2name -#include "status.h" -#include "skill.h" +#include "mapreg.h" +#include "mercenary.h" #include "mob.h" #include "npc.h" -#include "pet.h" -#include "homunculus.h" -#include "mail.h" -#include "mercenary.h" -#include "elemental.h" #include "party.h" -#include "guild.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 "mapreg.h" -#include "quest.h" -#include "searchstore.h" -#include "HPMmap.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.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; @@ -403,6 +407,11 @@ ACMD(mapmove) { clif->message(fd, msg_txt(1)); // Map not found. return false; } + + if( sd->bl.m == m && sd->bl.x == x && sd->bl.y == y ) { + clif->message(fd, msg_txt(253)); // You already are at your destination! + return false; + } if ((x || y) && map->getcell(m, 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. @@ -460,12 +469,22 @@ ACMD(where) { *------------------------------------------*/ ACMD(jumpto) { struct map_session_data *pl_sd = NULL; - + if (!message || !*message) { clif->message(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). return false; } - + + if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return false; + } + + if( pc_isdead(sd) ) { + clif->message(fd, msg_txt(864)); // "You cannot use this command when dead." + return false; + } + if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_txt(3)); // Character not found. return false; @@ -475,21 +494,16 @@ ACMD(jumpto) { clif->message(fd, msg_txt(247)); // You are not authorized to warp to this map. return false; } - - if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return false; - } - - if( pc_isdead(sd) ) { - clif->message(fd, msg_txt(864)); // "You cannot use this command when dead." + + if( pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y ) { + clif->message(fd, msg_txt(253)); // You already are at your destination! return false; } - + pc->setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); sprintf(atcmd_output, msg_txt(4), pl_sd->status.name); // Jumped to %s - clif->message(fd, atcmd_output); - + clif->message(fd, atcmd_output); + return true; } @@ -520,6 +534,11 @@ ACMD(jump) 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 ) { + clif->message(fd, msg_txt(253)); // You already are at your destination! + return false; + } pc->setpos(sd, sd->mapindex, x, y, CLR_TELEPORT); sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d @@ -824,7 +843,11 @@ ACMD(guildstorage) return false; } - gstorage->open(sd); + if( gstorage->open(sd) ) { + clif->message(fd, msg_txt(1201)); // Your guild's storage has already been opened by another member, try again later. + return false; + } + clif->message(fd, msg_txt(920)); // Guild storage opened. return true; } @@ -924,7 +947,7 @@ ACMD(jobchange) { } } - // High Jobs, Babys and Third + // High Jobs, Babies and Third for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){ if (strncmpi(message, pc->job_name(i), 16) == 0) { job = i; @@ -1100,14 +1123,14 @@ 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 + sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 2 && + sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2 ))) { clif->message(fd, msg_txt(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 )) + sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && + sscanf(message, "%99s %d", item_name, &number) < 1 )) { clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). return false; @@ -1306,7 +1329,7 @@ ACMD(baselevelup) clif->message(fd, msg_txt(47)); // Base level can't go any higher. return false; } // End Addition - if ((unsigned int)level > pc->maxbaselv(sd) || (unsigned int)level > pc->maxbaselv(sd) - sd->status.base_level) // fix positiv overflow + if ((unsigned int)level > pc->maxbaselv(sd) || (unsigned int)level > pc->maxbaselv(sd) - sd->status.base_level) // fix positive overflow level = pc->maxbaselv(sd) - sd->status.base_level; for (i = 0; i < level; i++) status_point += pc->gets_status_point(sd->status.base_level + i); @@ -1366,7 +1389,7 @@ ACMD(joblevelup) clif->message(fd, msg_txt(23)); // Job level can't go any higher. return false; } - if ((unsigned int)level > pc->maxjoblv(sd) || (unsigned int)level > pc->maxjoblv(sd) - sd->status.job_level) // fix positiv overflow + if ((unsigned int)level > pc->maxjoblv(sd) || (unsigned int)level > pc->maxjoblv(sd) - sd->status.job_level) // fix positive overflow level = pc->maxjoblv(sd) - sd->status.job_level; sd->status.job_level += (unsigned int)level; sd->status.skill_point += level; @@ -1378,11 +1401,11 @@ ACMD(joblevelup) return false; } level *=-1; - if ((unsigned int)level >= sd->status.job_level) // fix negativ overflow + if ((unsigned int)level >= sd->status.job_level) // fix negative overflow level = sd->status.job_level-1; sd->status.job_level -= (unsigned int)level; if (sd->status.skill_point < level) - pc->resetskill(sd,0); //Reset skills since we need to substract more points. + pc->resetskill(sd,0); //Reset skills since we need to subtract more points. if (sd->status.skill_point < level) sd->status.skill_point = 0; else @@ -1608,7 +1631,7 @@ ACMD(model) pc->changelook(sd, LOOK_HAIR, hair_style); pc->changelook(sd, LOOK_HAIR_COLOR, hair_color); pc->changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif->message(fd, msg_txt(36)); // Appearence changed. + clif->message(fd, msg_txt(36)); // Appearance changed. } else { clif->message(fd, msg_txt(37)); // An invalid number was specified. return false; @@ -1634,7 +1657,7 @@ ACMD(dye) if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { pc->changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif->message(fd, msg_txt(36)); // Appearence changed. + clif->message(fd, msg_txt(36)); // Appearance changed. } else { clif->message(fd, msg_txt(37)); // An invalid number was specified. return false; @@ -1660,7 +1683,7 @@ ACMD(hair_style) if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) { pc->changelook(sd, LOOK_HAIR, hair_style); - clif->message(fd, msg_txt(36)); // Appearence changed. + clif->message(fd, msg_txt(36)); // Appearance changed. } else { clif->message(fd, msg_txt(37)); // An invalid number was specified. return false; @@ -1686,7 +1709,7 @@ ACMD(hair_color) if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) { pc->changelook(sd, LOOK_HAIR_COLOR, hair_color); - clif->message(fd, msg_txt(36)); // Appearence changed. + clif->message(fd, msg_txt(36)); // Appearance changed. } else { clif->message(fd, msg_txt(37)); // An invalid number was specified. return false; @@ -1698,67 +1721,63 @@ ACMD(hair_color) /*========================================== * @go [city_number or city_name] - Updated by Harbin *------------------------------------------*/ -ACMD(go) -{ +ACMD(go) { int i; - int town; + int town = INT_MAX; // Initialized to INT_MAX instead of -1 to avoid conflicts with those who map [-3:-1] to @memo locations. char map_name[MAP_NAME_LENGTH]; - int16 m; const struct { char map[MAP_NAME_LENGTH]; int x, y; + int min_match; ///< Minimum string length to match } data[] = { - { MAP_PRONTERA, 156, 191 }, // 0=Prontera - { MAP_MORROC, 156, 93 }, // 1=Morroc - { MAP_GEFFEN, 119, 59 }, // 2=Geffen - { MAP_PAYON, 162, 233 }, // 3=Payon - { MAP_ALBERTA, 192, 147 }, // 4=Alberta + { MAP_PRONTERA, 156, 191, 3 }, // 0 = Prontera + { MAP_MORROC, 156, 93, 4 }, // 1 = Morroc + { MAP_GEFFEN, 119, 59, 3 }, // 2 = Geffen + { MAP_PAYON, 162, 233, 3 }, // 3 = Payon + { MAP_ALBERTA, 192, 147, 3 }, // 4 = Alberta #ifdef RENEWAL - { MAP_IZLUDE, 128, 146 }, // 5=Izlude (Renewal) + { MAP_IZLUDE, 128, 146, 3 }, // 5 = Izlude (Renewal) #else - { MAP_IZLUDE, 128, 114 }, // 5=Izlude + { MAP_IZLUDE, 128, 114, 3 }, // 5 = Izlude #endif - { MAP_ALDEBARAN, 140, 131 }, // 6=Al de Baran - { MAP_LUTIE, 147, 134 }, // 7=Lutie - { MAP_COMODO, 209, 143 }, // 8=Comodo - { MAP_YUNO, 157, 51 }, // 9=Yuno - { MAP_AMATSU, 198, 84 }, // 10=Amatsu - { MAP_GONRYUN, 160, 120 }, // 11=Gonryun - { MAP_UMBALA, 89, 157 }, // 12=Umbala - { MAP_NIFLHEIM, 21, 153 }, // 13=Niflheim - { MAP_LOUYANG, 217, 40 }, // 14=Louyang - { MAP_NOVICE, 53, 111 }, // 15=Training Grounds - { MAP_JAIL, 23, 61 }, // 16=Prison - { MAP_JAWAII, 249, 127 }, // 17=Jawaii - { MAP_AYOTHAYA, 151, 117 }, // 18=Ayothaya - { MAP_EINBROCH, 64, 200 }, // 19=Einbroch - { MAP_LIGHTHALZEN, 158, 92 }, // 20=Lighthalzen - { MAP_EINBECH, 70, 95 }, // 21=Einbech - { MAP_HUGEL, 96, 145 }, // 22=Hugel - { MAP_RACHEL, 130, 110 }, // 23=Rachel - { MAP_VEINS, 216, 123 }, // 24=Veins - { MAP_MOSCOVIA, 223, 184 }, // 25=Moscovia - { MAP_MIDCAMP, 180, 240 }, // 26=Midgard Camp - { MAP_MANUK, 282, 138 }, // 27=Manuk - { MAP_SPLENDIDE, 197, 176 }, // 28=Splendide - { MAP_BRASILIS, 182, 239 }, // 29=Brasilis - { MAP_DICASTES, 198, 187 }, // 30=El Dicastes - { MAP_MORA, 44, 151 }, // 31=Mora - { MAP_DEWATA, 200, 180 }, // 32=Dewata - { MAP_MALANGDO, 140, 114 }, // 33=Malangdo Island - { MAP_MALAYA, 242, 211 }, // 34=Malaya Port - { MAP_ECLAGE, 110, 39 }, // 35=Eclage + { MAP_ALDEBARAN, 140, 131, 3 }, // 6 = Aldebaran + { MAP_LUTIE, 147, 134, 3 }, // 7 = Lutie + { MAP_COMODO, 209, 143, 3 }, // 8 = Comodo + { MAP_YUNO, 157, 51, 3 }, // 9 = Juno + { MAP_AMATSU, 198, 84, 3 }, // 10 = Amatsu + { MAP_GONRYUN, 160, 120, 3 }, // 11 = Kunlun + { MAP_UMBALA, 89, 157, 3 }, // 12 = Umbala + { MAP_NIFLHEIM, 21, 153, 3 }, // 13 = Niflheim + { MAP_LOUYANG, 217, 40, 3 }, // 14 = Luoyang + { MAP_NOVICE, 53, 111, 3 }, // 15 = Training Grounds + { MAP_JAIL, 23, 61, 3 }, // 16 = Prison + { MAP_JAWAII, 249, 127, 3 }, // 17 = Jawaii + { MAP_AYOTHAYA, 151, 117, 3 }, // 18 = Ayothaya + { MAP_EINBROCH, 64, 200, 5 }, // 19 = Einbroch + { MAP_LIGHTHALZEN, 158, 92, 3 }, // 20 = Lighthalzen + { MAP_EINBECH, 70, 95, 5 }, // 21 = Einbech + { MAP_HUGEL, 96, 145, 3 }, // 22 = Hugel + { MAP_RACHEL, 130, 110, 3 }, // 23 = Rachel + { MAP_VEINS, 216, 123, 3 }, // 24 = Veins + { MAP_MOSCOVIA, 223, 184, 3 }, // 25 = Moscovia + { MAP_MIDCAMP, 180, 240, 3 }, // 26 = Midgard Camp + { MAP_MANUK, 282, 138, 3 }, // 27 = Manuk + { MAP_SPLENDIDE, 197, 176, 3 }, // 28 = Splendide + { MAP_BRASILIS, 182, 239, 3 }, // 29 = Brasilis + { MAP_DICASTES, 198, 187, 3 }, // 30 = El Dicastes + { MAP_MORA, 44, 151, 4 }, // 31 = Mora + { MAP_DEWATA, 200, 180, 3 }, // 32 = Dewata + { MAP_MALANGDO, 140, 114, 5 }, // 33 = Malangdo Island + { MAP_MALAYA, 242, 211, 5 }, // 34 = Malaya Port + { MAP_ECLAGE, 110, 39, 3 }, // 35 = Eclage }; memset(map_name, '\0', sizeof(map_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - // get the number - town = atoi(message); - - if (!message || !*message || sscanf(message, "%11s", map_name) < 1 || town < 0 || town >= ARRAYLENGTH(data)) - {// no value matched so send the list of locations + if (!message || !*message || sscanf(message, "%11s", map_name) < 1) { + // no value matched so send the list of locations const char* text; // attempt to find the text help string @@ -1772,98 +1791,49 @@ ACMD(go) return false; } - - // get possible name of the city - map_name[MAP_NAME_LENGTH-1] = '\0'; - for (i = 0; map_name[i]; i++) - map_name[i] = TOLOWER(map_name[i]); - // try to identify the map name - if (strncmp(map_name, "prontera", 3) == 0) { - town = 0; - } else if (strncmp(map_name, "morocc", 4) == 0 || - strncmp(map_name, "morroc", 4) == 0) { - town = 1; - } else if (strncmp(map_name, "geffen", 3) == 0) { - town = 2; - } else if (strncmp(map_name, "payon", 3) == 0) { - town = 3; - } else if (strncmp(map_name, "alberta", 3) == 0) { - town = 4; - } else if (strncmp(map_name, "izlude", 3) == 0) { - town = 5; - } else if (strncmp(map_name, "aldebaran", 3) == 0) { - town = 6; - } else if (strncmp(map_name, "lutie", 3) == 0 || - strcmp(map_name, "christmas") == 0 || - strncmp(map_name, "xmas", 3) == 0 || - strncmp(map_name, "x-mas", 3) == 0) { - town = 7; - } else if (strncmp(map_name, "comodo", 3) == 0) { - town = 8; - } else if (strncmp(map_name, "juno", 3) == 0 || - strncmp(map_name, "yuno", 3) == 0) { - town = 9; - } else if (strncmp(map_name, "amatsu", 3) == 0) { - town = 10; - } else if (strncmp(map_name, "kunlun", 3) == 0 || - strncmp(map_name, "gonryun", 3) == 0) { - town = 11; - } else if (strncmp(map_name, "umbala", 3) == 0) { - town = 12; - } else if (strncmp(map_name, "niflheim", 3) == 0) { - town = 13; - } else if (strncmp(map_name, "louyang", 3) == 0) { - town = 14; - } else if (strncmp(map_name, "new_1-1", 3) == 0 || - strncmp(map_name, "startpoint", 3) == 0 || - strncmp(map_name, "beginning", 3) == 0) { - town = 15; - } else if (strncmp(map_name, "sec_pri", 3) == 0 || - strncmp(map_name, "prison", 3) == 0 || - strncmp(map_name, "jail", 3) == 0) { - town = 16; - } else if (strncmp(map_name, "jawaii", 3) == 0) { - town = 17; - } else if (strncmp(map_name, "ayothaya", 3) == 0) { - town = 18; - } else if (strncmp(map_name, "einbroch", 5) == 0) { - town = 19; - } else if (strncmp(map_name, "lighthalzen", 3) == 0) { - town = 20; - } else if (strncmp(map_name, "einbech", 5) == 0) { - town = 21; - } else if (strncmp(map_name, "hugel", 3) == 0) { - town = 22; - } else if (strncmp(map_name, "rachel", 3) == 0) { - town = 23; - } else if (strncmp(map_name, "veins", 3) == 0) { - town = 24; - } else if (strncmp(map_name, "moscovia", 3) == 0) { - town = 25; - } else if (strncmp(map_name, "mid_camp", 3) == 0) { - town = 26; - } else if (strncmp(map_name, "manuk", 3) == 0) { - town = 27; - } else if (strncmp(map_name, "splendide", 3) == 0) { - town = 28; - } else if (strncmp(map_name, "brasilis", 3) == 0) { - town = 29; - } else if (strncmp(map_name, "dicastes01", 3) == 0) { - town = 30; - } else if (strcmp(map_name, "mora") == 0) { - town = 31; - } else if (strncmp(map_name, "dewata", 3) == 0) { - town = 32; - } else if (strncmp(map_name, "malangdo", 5) == 0) { - town = 33; - } else if (strncmp(map_name, "malaya", 5) == 0) { - town = 34; - } else if (strncmp(map_name, "eclage", 3) == 0) { - town = 35; + + // Numeric entry + if (ISDIGIT(*message) || (message[0] == '-' && ISDIGIT(message[1]))) { + town = atoi(message); } - + + if (town < 0 || town >= ARRAYLENGTH(data)) { + map_name[MAP_NAME_LENGTH-1] = '\0'; + + // Match maps on the list + for (i = 0; i < ARRAYLENGTH(data); i++) { + if (strncmpi(map_name, data[i].map, data[i].min_match) == 0) { + town = i; + break; + } + } + } + + if (town < 0 || town >= ARRAYLENGTH(data)) { + // Alternate spellings + if (strncmpi(map_name, "morroc", 4) == 0) { // Correct town name for 'morocc' + town = 1; + } else if (strncmpi(map_name, "lutie", 3) == 0) { // Correct town name for 'xmas' + town = 7; + } else if (strncmpi(map_name, "juno", 3) == 0) { // Correct town name for 'yuno' + town = 9; + } else if (strncmpi(map_name, "kunlun", 3) == 0) { // Original town name for 'gonryun' + town = 11; + } else if (strncmpi(map_name, "luoyang", 3) == 0) { // Original town name for 'louyang' + town = 14; + } else if (strncmpi(map_name, "startpoint", 3) == 0 // Easy to remember alternatives to 'new_1-1' + || strncmpi(map_name, "beginning", 3) == 0) { + town = 15; + } else if (strncmpi(map_name, "prison", 3) == 0 // Easy to remember alternatives to 'sec_pri' + || strncmpi(map_name, "jail", 3) == 0) { + town = 16; + } else if (strncmpi(map_name, "rael", 3) == 0) { // Original town name for 'rachel' + town = 23; + } + } + if (town >= 0 && town < ARRAYLENGTH(data)) { - m = map->mapname2mapid(data[town].map); + int16 m = map->mapname2mapid(data[town].map); if (m >= 0 && map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif->message(fd, msg_txt(247)); return false; @@ -1878,7 +1848,7 @@ ACMD(go) clif->message(fd, msg_txt(1)); // Map not found. return false; } - } else { // if you arrive here, you have an error in town variable when reading of names + } else { clif->message(fd, msg_txt(38)); // Invalid location number or name. return false; } @@ -1926,7 +1896,7 @@ ACMD(monster) return false; } - if ((mob_id = mob->db_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) + if ((mob_id = mob->db_searchname(monster)) == 0) // check name first (to avoid possible name beginning by a number) mob_id = mob->db_checkid(atoi(monster)); if (mob_id == 0) { @@ -2353,7 +2323,11 @@ ACMD(zeny) if((ret=pc->payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL)) == 1) clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } - if(!ret) clif->message(fd, msg_txt(176)); //ret=0 mean cmd success + + if( ret ) //ret != 0 means cmd failure + return false; + + clif->message(fd, msg_txt(176)); return true; } @@ -2737,7 +2711,7 @@ ACMD(char_block) * mn: minute * s: second * <example> @ban +1m-2mn1s-6y test_player - * this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time. + * this example adds 1 month and 1 second, and subtracts 2 minutes and 6 years at the same time. *------------------------------------------*/ ACMD(char_ban) { @@ -2905,12 +2879,12 @@ ACMD(doom) { status_kill(&pl_sd->bl); clif->specialeffect(&pl_sd->bl,450,AREA); - clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgment. } } mapit->free(iter); - clif->message(fd, msg_txt(62)); // Judgement was made. + clif->message(fd, msg_txt(62)); // Judgment was made. return true; } @@ -2930,12 +2904,12 @@ ACMD(doommap) { status_kill(&pl_sd->bl); clif->specialeffect(&pl_sd->bl,450,AREA); - clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgment. } } mapit->free(iter); - clif->message(fd, msg_txt(62)); // Judgement was made. + clif->message(fd, msg_txt(62)); // Judgment was made. return true; } @@ -3010,7 +2984,7 @@ ACMD(kick) if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } @@ -3313,7 +3287,7 @@ ACMD(mapexit) { } /*========================================== - * idsearch <part_of_name>: revrited by [Yor] + * idsearch <part_of_name>: rewrite by [Yor] *------------------------------------------*/ ACMD(idsearch) { @@ -3359,7 +3333,7 @@ ACMD(recallall) memset(atcmd_output, '\0', sizeof(atcmd_output)); if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map. return false; } @@ -3411,7 +3385,7 @@ ACMD(guildrecall) } if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map. return false; } @@ -3468,7 +3442,7 @@ ACMD(partyrecall) } if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map. return false; } @@ -3943,7 +3917,12 @@ ACMD(mount_peco) return false; } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT && pc->checkskill(sd,RK_DRAGONTRAINING) > 0 ) { + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) { + if( !pc->checkskill(sd,RK_DRAGONTRAINING) ) { + sprintf(atcmd_output, msg_txt(213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount! + clif->message(fd, atcmd_output); + return false; + } if( !(sd->sc.option&OPTION_DRAGON1) ) { clif->message(sd->fd,msg_txt(1119)); // You have mounted your Dragon. pc->setoption(sd, sd->sc.option|OPTION_DRAGON1); @@ -3953,7 +3932,12 @@ ACMD(mount_peco) } return true; } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER && pc->checkskill(sd,RA_WUGRIDER) > 0 ) { + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { + if( !pc->checkskill(sd,RA_WUGRIDER) ) { + sprintf(atcmd_output, msg_txt(213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount! + clif->message(fd, atcmd_output); + return false; + } if( !pc_isridingwug(sd) ) { clif->message(sd->fd,msg_txt(1121)); // You have mounted your Warg. pc->setoption(sd, sd->sc.option|OPTION_WUGRIDER); @@ -3973,21 +3957,23 @@ ACMD(mount_peco) } return true; } - if (!pc_isriding(sd)) { // if actually no peco - - if (!pc->checkskill(sd, KN_RIDING)) { - clif->message(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job. - return false; + if( sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2 ) { + if( !pc_isriding(sd) ) { // if actually no peco + if (!pc->checkskill(sd, KN_RIDING)) { + sprintf(atcmd_output, msg_txt(213), skill->get_desc(KN_RIDING)); // You need %s to mount! + clif->message(fd, atcmd_output); + return false; + } + pc->setoption(sd, sd->sc.option | OPTION_RIDING); + clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco. + } else {//Dismount + pc->setoption(sd, sd->sc.option & ~OPTION_RIDING); + clif->message(fd, msg_txt(214)); // You have released your Peco Peco. } - - pc->setoption(sd, sd->sc.option | OPTION_RIDING); - clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco. - } else {//Dismount - pc->setoption(sd, sd->sc.option & ~OPTION_RIDING); - clif->message(fd, msg_txt(214)); // You have released your Peco Peco. + return true; } - - return true; + clif->message(fd, msg_txt(215)); // Your class can't mount! + return false; } /*========================================== @@ -4115,7 +4101,7 @@ ACMD(nuke) { skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, timer->gettick(), 0); clif->message(fd, msg_txt(109)); // Player has been nuked! } else { - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } } else { @@ -4312,7 +4298,7 @@ ACMD(servertime) { const struct TimerData * timer_data2 = timer->get(pc->day_timer_tid); if (map->night_flag == 0) { - sprintf(temp, msg_txt(235), // Game time: The game is actualy in daylight for %s. + sprintf(temp, msg_txt(235), // Game time: The game is actually in daylight for %s. txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) @@ -4323,7 +4309,7 @@ ACMD(servertime) { txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000))); clif->message(fd, temp); } else { - sprintf(temp, msg_txt(233), // Game time: The game is actualy in night for %s. + sprintf(temp, msg_txt(233), // Game time: The game is actually in night for %s. txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer->gettick()) / 1000))); clif->message(fd, temp); if (DIFF_TICK(timer_data2->tick,timer_data->tick) > 0) @@ -4397,7 +4383,7 @@ ACMD(jail) { if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } @@ -4448,7 +4434,7 @@ ACMD(unjail) { if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } @@ -4525,7 +4511,7 @@ ACMD(jailfor) { } if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } @@ -5183,9 +5169,10 @@ ACMD(clearcart) return false; } - if (sd->state.vending == 1) { //Somehow... - return false; - } + if( sd->state.vending == 1 ) { + clif->message(fd, msg_txt(548)); // You can't clean a cart while vending! + return false; + } for( i = 0; i < MAX_CART; i++ ) if(sd->status.cart[i].nameid > 0) @@ -5270,7 +5257,7 @@ ACMD(useskill) { if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorized you to do this action on this player. return false; } @@ -5485,7 +5472,7 @@ ACMD(autotrade) { status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); } - /* currently standalones are not supporting buyingstores, so we rely on the previous method */ + /* currently standalone is not supporting buyingstores, so we rely on the previous method */ if( sd->state.buyingstore ) { clif->authfail_fd(fd, 15); return true; @@ -6410,7 +6397,7 @@ ACMD(changesex) int i; pc->resetskill(sd,4); - // to avoid any problem with equipment and invalid sex, equipment is unequiped. + // 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); chrif->changesex(sd); @@ -6436,7 +6423,7 @@ ACMD(mute) { if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player. return false; } @@ -6673,20 +6660,29 @@ 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_txt(546)); // Please enter a mob name/id (usage: @showmobs <mob name/id>) return false; - - if((mob_id = atoi(mob_name)) == 0) + } + + if( (mob_id = atoi(mob_name)) == 0 ) mob_id = mob->db_searchname(mob_name); + + if( mob_id == 0 ) { + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(547), mob_name); // Invalid mob name %s! + clif->message(fd, atcmd_output); + return false; + } + if(mob_id > 0 && mob->db_checkid(mob_id) == 0){ snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1250),mob_name); // Invalid mob id %s! clif->message(fd, atcmd_output); - return true; + return false; } if(mob->db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs. clif->message(fd, msg_txt(1251)); // Can't show boss mobs! - return true; + return false; } if(mob_id == atoi(mob_name) && mob->db(mob_id)->jname) @@ -7208,18 +7204,11 @@ ACMD(whereis) } ACMD(version) { - const char *git = get_git_hash(); - const char *svn = get_svn_revision(); - - if ( git[0] != HERC_UNKNOWN_VER ) { - sprintf(atcmd_output,msg_txt(1295),git); // Git Hash '%s' - clif->message(fd,atcmd_output); - } else if ( svn[0] != HERC_UNKNOWN_VER ) { - sprintf(atcmd_output,msg_txt(1294),git); // SVN r%s - clif->message(fd,atcmd_output); - } else - clif->message(fd,msg_txt(1296)); // Cannot determine version - + sprintf(atcmd_output, msg_txt(1296), sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); // Hercules %d-bit for %s + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts) + clif->message(fd, atcmd_output); + return true; } @@ -7438,6 +7427,8 @@ ACMD(fakename){ { sd->fakename[0] = '\0'; clif->charnameack(0, &sd->bl); + if( sd->disguise ) + clif->charnameack(sd->fd, &sd->bl); clif->message(sd->fd, msg_txt(1307)); // Returned to real name. return true; } @@ -7454,6 +7445,8 @@ 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 + clif->charnameack(sd->fd, &sd->bl); clif->message(sd->fd, msg_txt(1310)); // Fake name enabled. return true; @@ -7723,7 +7716,7 @@ ACMD(accept) { } if(sd->duel_invite <= 0) { - // "Duel: @accept without invititation." + // "Duel: @accept without invitation." clif->message(fd, msg_txt(360)); return false; } @@ -7743,7 +7736,7 @@ ACMD(accept) { ACMD(reject) { if(sd->duel_invite <= 0) { - // "Duel: @reject without invititation." + // "Duel: @reject without invitation." clif->message(fd, msg_txt(362)); return false; } @@ -8441,7 +8434,7 @@ ACMD(set) { if( is_str ) script->set_var(sd, reg, (void*) val); else - script->set_var(sd, reg, (void*)__64BPTRSIZE((atoi(val)))); + script->set_var(sd, reg, (void*)h64BPTRSIZE((atoi(val)))); } @@ -8655,7 +8648,7 @@ ACMD(join) { if( hChSys.local && strcmpi(name + 1, hChSys.local_name) == 0 ) { if( !map->list[sd->bl.m].channel ) { clif->chsys_mjoin(sd); - if( map->list[sd->bl.m].channel ) /* mjoin might have refused, map has chatting capabilities disabled */ + if( map->list[sd->bl.m].channel ) /* join might have refused, map has chatting capabilities disabled */ return true; } else channel = map->list[sd->bl.m].channel; @@ -10058,7 +10051,7 @@ void atcommand_config_read(const char* config_filename) { } commandinfo->log = false; } - } + } // Commands help // We only check if all commands exist @@ -10105,7 +10098,7 @@ static inline int AtCommandType2idx(AtCommandType type) { return (type-1); } /** * Loads permissions for groups to use commands. - * + * */ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **commands_, size_t sz) { diff --git a/src/map/atcommand.h b/src/map/atcommand.h index bc4ab30a3..356487bd1 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -2,12 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_ATCOMMAND_H_ -#define _MAP_ATCOMMAND_H_ +#ifndef MAP_ATCOMMAND_H +#define MAP_ATCOMMAND_H +#include "pc_groups.h" #include "../common/conf.h" #include "../common/db.h" -#include "pc_groups.h" /** * Declarations @@ -121,4 +121,4 @@ void atcommand_defaults(void); /* 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) -#endif /* _MAP_ATCOMMAND_H_ */ +#endif /* MAP_ATCOMMAND_H */ diff --git a/src/map/battle.c b/src/map/battle.c index 2217ccecc..7610d97b2 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2,40 +2,44 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/ers.h" -#include "../common/random.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/HPM.h" +#define HERCULES_CORE -#include "map.h" -#include "path.h" -#include "pc.h" -#include "status.h" -#include "skill.h" -#include "homunculus.h" -#include "mercenary.h" -#include "elemental.h" -#include "mob.h" -#include "itemdb.h" -#include "clif.h" -#include "pet.h" -#include "guild.h" -#include "party.h" +#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 "battleground.h" -#include "chrif.h" +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.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; @@ -54,7 +58,7 @@ int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last s } /*========================================== - * Get random targetting enemy + * Get random targeting enemy *------------------------------------------*/ int battle_gettargeted_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list; @@ -98,7 +102,7 @@ struct block_list* battle_gettargeted(struct block_list *target) { } -//Returns the id of the current targetted character of the passed bl. [Skotlex] +//Returns the id of the current targeted character of the passed bl. [Skotlex] int battle_gettarget(struct block_list* bl) { switch (bl->type) { @@ -258,7 +262,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct if ( !battle_config.delay_battle_damage || amotion <= 1 ) { map->freeblock_lock(); - status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope] + status_fix_damage(src, target, damage, ddelay); // We have to separate here between reflect damage and others [icescope] if( attack_type && !status->isdead(target) && additional_effects ) skill->additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, timer->gettick()); if( dmg_lv > ATK_BLOCK && attack_type ) @@ -354,7 +358,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d } } } - if( tsc && tsc->count ) { //since an atk can only have one type let's optimise this a bit + if( tsc && tsc->count ) { //since an atk can only have one type let's optimize this a bit switch(atk_elem){ case ELE_FIRE: if( tsc->data[SC_SPIDERWEB]) { @@ -442,7 +446,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u if( sc && sc->count ){ if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) eatk += 200; - #ifdef RENEWAL_EDP + #ifdef RENEWAL_EDP if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ){ eatk = eatk * (sc->data[SC_EDP]->val4 / 100 - 1); damage = damage * (sc->data[SC_EDP]->val4 / 100); @@ -459,7 +463,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage + eatk, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag); /** - * In RE Shield Bommerang takes weapon element only for damage calculation, + * In RE Shield Boomerang takes weapon element only for damage calculation, * - resist calculation is always against neutral **/ if ( skill_id == CR_SHIELDBOOMERANG ) @@ -478,7 +482,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u } /*========================================== * Calculates the standard damage of a normal attack assuming it hits, - * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex] + * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex] *------------------------------------------ * Pass damage2 as NULL to not calc it. * Flag values: @@ -563,7 +567,7 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st else damage += st->batk; - //rodatazone says that Overrefine bonuses are part of baseatk + //rodatazone says that Overrefined bonuses are part of baseatk //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. if(sd) { if (type == EQI_HAND_L) { @@ -600,7 +604,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in nullpo_ret(sd); if((skill_lv = pc->checkskill(sd,AL_DEMONBANE)) > 0 && - target->type == BL_MOB && //This bonus doesnt work against players. + target->type == BL_MOB && //This bonus doesn't work against players. (battle->check_undead(st->race,st->def_ele) || st->race==RC_DEMON) ) damage += (int)(skill_lv*(3+sd->status.base_level/20.0)); //damage += (skill_lv * 3); @@ -651,7 +655,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in damage += (skill_lv * 10); else if(pc_isriding(sd)) damage += (skill_lv * 5); - else + else damage += (skill_lv * 4); } break; @@ -672,7 +676,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in case W_FIST: if((skill_lv = pc->checkskill(sd,TK_RUN)) > 0) damage += (skill_lv * 10); - // No break, fallthrough to Knuckles + // No break, fall through to Knuckles case W_KNUCKLE: if((skill_lv = pc->checkskill(sd,MO_IRONHAND)) > 0) damage += (skill_lv * 3); @@ -733,7 +737,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, #endif ) damage += 3 * skill2_lv; - break; + break; #ifndef RENEWAL case NJ_KUNAI: if( weapon ) @@ -744,7 +748,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, if( sd->weight ) damage += sd->weight / 8 ; case RA_WUGSTRIKE: - case RA_WUGBITE: + case RA_WUGBITE: damage += 30*pc->checkskill(sd, RA_TOOTHOFWUG); break; case HT_FREEZINGTRAP: @@ -995,7 +999,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ 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; + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; if( !(nk&NK_NO_ELEFIX) ){ int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { @@ -1015,9 +1019,9 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]) / 100; if( cflag&1 ){ - cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; + cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; if (!(nk&NK_NO_ELEFIX)){ - int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; + int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; if(!(sd->left_weapon.addele2[i].flag&wflag&BF_WEAPONMASK && @@ -1217,7 +1221,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ **/ defType def1 = status->get_def(target); //Don't use tstatus->def1 due to skill timer reductions. short def2 = tstatus->def2, vit_def; -#ifdef RENEWAL +#ifdef RENEWAL def1 = status->calc_def2(target, tsc, def1, false); // equip def(RE) def2 = status->calc_def(target, tsc, def2, false); // status def(RE) #else @@ -1268,9 +1272,9 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ #else vit_def = def2; #endif - if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players + if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesn't work vs players src->type == BL_MOB && (i=pc->checkskill(tsd,AL_DP)) > 0) - vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn + vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // [orn] if( src->type == BL_MOB && (i=pc->checkskill(tsd,RA_RANGERMAIN))>0 && (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) vit_def += i*5; @@ -1292,12 +1296,12 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ #ifdef RENEWAL /** * RE DEF Reduction - * Pierce defence gains 1 atk per def/2 + * Pierce defense gains 1 atk per def/2 **/ if( def1 < -399 ) // it stops at -399 def1 = 399; // in aegis it set to 1 but in our case it may lead to exploitation so limit it to 399 - //return 1; + //return 1; if( flag&2 ) damage += def1 >> 1; @@ -1353,7 +1357,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ **/ if( mdef < -99 ) // it stops at -99 mdef = 99; // in aegis it set to 1 but in our case it may lead to exploitation so limit it to 99 - //return 1; + //return 1; damage = (int)((100.0f - mdef / (mdef + 100.0f) * 90.0f) / 100.0f * damage - mdef2); #else @@ -1380,7 +1384,7 @@ int battle_calc_chorusbonus(struct map_session_data *sd) { if (members < 3) return 0; // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party. if (members > 7) - return 5; // Maximum effect possiable from 7 or more Minstrel's/Wanderer's + return 5; // Maximum effect possible from 7 or more Minstrel's/Wanderer's return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible } @@ -1720,9 +1724,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block skillratio += 1100; break; case MH_ERASER_CUTTER: - if(skill_lv%2) skillratio += 400; //600:800:1000 - else skillratio += 700; //1000:1200 - skillratio += 100 * skill_lv; + skillratio += 400 + 100 * skill_lv + (skill_lv%2 > 0 ? 0 : 300); break; case MH_XENO_SLASHER: if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700 @@ -2003,7 +2005,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block skillratio += 50 * skill_lv; break; case GS_BULLSEYE: - //Only works well against brute/demihumans non bosses. + //Only works well against brute/demi-humans non bosses. if((tst->race == RC_BRUTE || tst->race == RC_DEMIHUMAN) && !(tst->mode&MD_BOSS)) skillratio += 400; @@ -2107,15 +2109,6 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block if( st->rhw.ele == ELE_FIRE ) skillratio += 100 * skill_lv; break; - case RK_CRUSHSTRIKE: - if( sd ) - {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]% - short index = sd->equip_index[EQI_HAND_R]; - if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) - skillratio += -100 + sd->inventory_data[index]->weight/10 + st->rhw.atk + - 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); - } - break; case RK_STORMBLAST: skillratio = ((sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + status_get_int(src) / 8) * 100; break; @@ -2124,7 +2117,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block RE_LVL_DMOD(150); break; /** - * GC Guilotine Cross + * GC Guillotine Cross **/ case GC_CROSSIMPACT: skillratio += 900 + 100 * skill_lv; @@ -2408,7 +2401,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block { int chorusbonus = battle->calc_chorusbonus(sd); skillratio += 300 + 200 * skill_lv; - //Chorus bonus dont count the first 2 Minstrel's/Wanderer's and only increases when their's 3 or more. [Rytech] + //Chorus bonus don't count the first 2 Minstrel's/Wanderer's and only increases when their's 3 or more. [Rytech] if (chorusbonus >= 1 && chorusbonus <= 5) skillratio += 100<<(chorusbonus-1); // 1->100; 2->200; 3->400; 4->800; 5->1600 RE_LVL_DMOD(100); @@ -2461,7 +2454,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block if( sc && sc->data[SC_BLAST_OPTION] ) skillratio += (sd ? sd->status.job_level * 5 : 0); break; - // Physical Elemantal Spirits Attack Skills + // Physical Elemental Spirits Attack Skills case EL_CIRCLE_OF_FIRE: case EL_FIRE_BOMB_ATK: case EL_STONE_RAIN: @@ -2546,6 +2539,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block if( sd && sd->status.weapon == W_KATAR && (i=pc->checkskill(sd,ASC_KATAR)) > 0 ) skillratio += skillratio * (10 + 2 * i) / 100; #endif + if( (!skill_id || skill_id == KN_AUTOCOUNTER) && sc->data[SC_CRUSHSTRIKE] ){ + if( sd ) + {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]% + short index = sd->equip_index[EQI_HAND_R]; + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) + skillratio += -100 + sd->inventory_data[index]->weight/10 + st->rhw.atk + + 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); + } + status_change_end(src, SC_CRUSHSTRIKE, INVALID_TIMER); + skill->break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. + } } } if( skillratio < 1 ) @@ -2553,8 +2557,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block return skillratio; } /*========================================== - * Check dammage trough status. - * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status... + * Check damage trough status. + * ATK may be MISS, BLOCKED FAIL, reduce, increase, end status... * After this we apply bg/gvg reduction *------------------------------------------*/ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv) { @@ -2617,8 +2621,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } } - if(sc->data[SC_ZEPHYR] && - flag&(BF_LONG|BF_SHORT)){ + if( sc->data[SC_ZEPHYR] && ((flag&BF_LONG) || rand()%100 < 10) ) { d->dmg_lv = ATK_BLOCK; return 0; } @@ -2711,7 +2714,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage d->dmg_lv = ATK_BLOCK; - sc_start(src,bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. + sc_start(src,bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stunned when one shield is broken. if( sce->val3 <= 0 ) { // Shield Down sce->val2--; if( sce->val2 > 0 ) { @@ -2981,7 +2984,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam rnd()%100 < sce->val3) status->heal(src, damage*sce->val4/100, 0, 3); - if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON + if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 && sc->fv_counter <= sce->val3 ) clif->millenniumshield(bl, sc->fv_counter++); @@ -3025,7 +3028,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam short rate = 100; struct status_data *tstatus = status->get_status_data(bl); if ( !(flag&BF_SKILL) && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < tsc->data[SC_POISONINGWEAPON]->val3 ) { - if ( tsc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech] + if ( tsc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] rate = 100 - tstatus->int_ * 4 / 5; 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); } @@ -3042,7 +3045,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam /* no data claims these settings affect anything other than players */ if( damage && sd && bl->type == BL_PC ) { switch( skill_id ) { - //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so dont worry about it */ + //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so don't worry about it */ case HW_GRAVITATION: case NJ_ZENYNAGE: case KO_MUCHANAGE: @@ -3250,7 +3253,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { int i; if (!sd->skillblown[0].id) return 0; - //Apply the bonus blewcount. [Skotlex] + //Apply the bonus blow count. [Skotlex] for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { if (sd->skillblown[i].id == skill_id) return sd->skillblown[i].val; @@ -3331,7 +3334,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.flag |= battle->range_type(src, target, skill_id, skill_lv); flag.infdef=(tstatus->mode&MD_PLANT?1:0); if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION ) - flag.infdef = 1; // Reberberation takes 1 damage + flag.infdef = 1; // Reverberation takes 1 damage switch(skill_id) { case MG_FIREWALL: @@ -3596,7 +3599,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } /*========================================== - * Calculate Misc dammage for skill_id + * Calculate Misc damage for skill_id *------------------------------------------*/ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int temp; @@ -3904,7 +3907,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * { if (battle_config.agi_penalty_type == 1) flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; - else //asume type 2: absolute reduction + else // assume type 2: absolute reduction flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; if(flee < 1) flee = 1; } @@ -4042,7 +4045,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list unsigned lh : 1; //Attack considers left hand (wd.damage2) unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) #ifdef RENEWAL - unsigned tdef : 1; //Total defence reduction + unsigned tdef : 1; //Total defense reduction #endif } flag; @@ -4061,7 +4064,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list #endif ?1:0); if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION ) - flag.infdef = 1; // Reberberation takes 1 damage + flag.infdef = 1; // Reverberation takes 1 damage //Initial Values wd.type=0; //Normal attack @@ -4303,6 +4306,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list cri <<= 1; } switch (skill_id) { + case 0: + if(!(sc && sc->data[SC_AUTOCOUNTER])) + break; + status_change_end(src, SC_AUTOCOUNTER, INVALID_TIMER); case KN_AUTOCOUNTER: if(battle_config.auto_counter_type && (battle_config.auto_counter_type&src->type)) @@ -4509,7 +4516,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_RATE(50); RE_SKILL_REDUCTION(); } - break; + break; case NJ_SYURIKEN: // [malufett] GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) ); wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon) - status->get_total_def(target); @@ -4652,6 +4659,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADDRATE(sc->data[SC_EXEEDBREAK]->val1); status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); } + + #ifdef RENEWAL if( sd && skill_id == NJ_KUNAI ){ flag.tdef = 1; @@ -4876,7 +4885,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADDRATE(sd->bonus.long_attack_atk_rate); if( sc && sc->data[SC_MTF_RANGEATK] ) ATK_ADDRATE(25);// temporary it should be 'bonus.long_attack_atk_rate' - #endif + #endif if( (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 && (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) ) ATK_ADDRATE(-i); @@ -5114,12 +5123,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list temp = pc->checkskill(sd,TF_DOUBLE); wd.damage2 = wd.damage * (1 + (temp * 2))/100; - if(wd.damage && !wd.damage2) wd.damage2 = + if(wd.damage && !wd.damage2) { #ifdef RENEWAL - 0; + wd.damage2 = 0; #else - 1; + wd.damage2 = 1; #endif + } flag.lh = 1; } } @@ -5646,7 +5656,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ATK_BLOCK; } } - if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) ) { uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1; @@ -5684,7 +5693,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t /** * We need to calculate the DMG before the hp reduction, because it can kill the source. - * For futher information: bugreport:4950 + * For further information: bugreport:4950 **/ ret_val = (damage_lv)skill->attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0); @@ -5710,13 +5719,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); } - if( sc && sc->data[SC_CRUSHSTRIKE] ){ - uint16 skill_lv = sc->data[SC_CRUSHSTRIKE]->val1; - status_change_end(src, SC_CRUSHSTRIKE, INVALID_TIMER); - if( skill->attack(BF_WEAPON,src,src,target,RK_CRUSHSTRIKE,skill_lv,tick,0) ) - return ATK_DEF; - return ATK_MISS; - } + if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 ) clif->skill_nodamage(target, target, SM_ENDURE, 5, sc_start(target,target, SC_ENDURE, 100, 5, skill->get_time(SM_ENDURE, 5))); @@ -6054,7 +6057,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f 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 - { //Targettable by players + { //Targetable by players state |= BCT_ENEMY; strip_enemy = 0; } @@ -6133,7 +6136,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f sd = BL_CAST(BL_PC, t_bl); if( sd->state.monster_ignore && flag&BCT_ENEMY ) - return 0; // Global inminuty only to Attacks + return 0; // Global immunity only to Attacks if( sd->status.karma && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->status.karma ) state |= BCT_ENEMY; // Characters with bad karma may fight amongst them if( sd->state.killable ) { @@ -6146,7 +6149,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f { struct mob_data *md = BL_CAST(BL_MOB, t_bl); - if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id ) + if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) + && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->guild_id) ) return 0; // Disable guardians/emperiums owned by Guilds on non-woe times. break; } @@ -6206,7 +6210,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case BL_MOB: { struct mob_data *md = BL_CAST(BL_MOB, s_bl); - if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id ) + if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) + && 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 ) @@ -6227,7 +6232,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f break; } default: - //Need some sort of default behaviour for unhandled types. + //Need some sort of default behavior for unhandled types. if (t_bl->type != s_bl->type) state |= BCT_ENEMY; break; @@ -6347,12 +6352,12 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range return true; // No need for path checking. if( d > AREA_SIZE ) - return false; // Avoid targetting objects beyond your range of sight. + 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); } -static const struct _battle_data { +static const struct battle_data { const char* str; int* val; int defval; @@ -6711,8 +6716,9 @@ static const struct _battle_data { /** * rAthena **/ - { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, }, - { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, 10000, }, + { "max_third_parameter", &battle_config.max_third_parameter, 130, 10, 10000, }, + { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 117, 10, 10000, }, + { "max_extended_parameter", &battle_config.max_extended_parameter, 125, 10, 10000, }, { "atcommand_max_stat_bypass", &battle_config.atcommand_max_stat_bypass, 0, 0, 100, }, { "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 300 }, { "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 }, @@ -6740,6 +6746,8 @@ static const struct _battle_data { { "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, }, + { "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, }, }; #ifndef STATS_OPT_OUT /** @@ -6748,8 +6756,6 @@ static const struct _battle_data { void Hercules_report(char* date, char *time_c) { int i, bd_size = ARRAYLENGTH(battle_data); unsigned int config = 0; - const char *svn = get_svn_revision(); - const char *git = get_git_hash(); char timestring[25]; time_t curtime; char* buf; @@ -6757,7 +6763,7 @@ void Hercules_report(char* date, char *time_c) { enum config_table { C_CIRCULAR_AREA = 0x0001, C_CELLNOSTACK = 0x0002, - C_CONSOLE_INPUT = 0x0004, + C_CONSOLE_INPUT = 0x0004, C_SCRIPT_CALLFUNC_CHECK = 0x0008, C_OFFICIAL_WALKPATH = 0x0010, C_RENEWAL = 0x0020, @@ -6768,12 +6774,15 @@ void Hercules_report(char* date, char *time_c) { C_RENEWAL_EDP = 0x0400, C_RENEWAL_ASPD = 0x0800, C_SECURE_NPCTIMEOUT = 0x1000, - C_SQL_DBS = 0x2000, + C_SQL_DB_ITEM = 0x2000, C_SQL_LOGS = 0x4000, - C_MEMWATCH = 0x8000, - C_DMALLOC = 0x10000, - C_GCOLLECT = 0x20000, - C_SEND_SHORTLIST = 0x40000, + C_MEMWATCH = 0x8000, + C_DMALLOC = 0x10000, + C_GCOLLECT = 0x20000, + C_SEND_SHORTLIST = 0x40000, + C_SQL_DB_MOB = 0x80000, + C_SQL_DB_MOBSKILL = 0x100000, + C_PACKETVER_RE = 0x200000, }; /* we get the current time */ @@ -6831,10 +6840,18 @@ void Hercules_report(char* date, char *time_c) { #ifdef SECURE_NPCTIMEOUT config |= C_SECURE_NPCTIMEOUT; #endif + +#ifdef PACKETVER_RE + config |= C_PACKETVER_RE; +#endif /* non-define part */ - if( map->db_use_sql_item_db || map->db_use_sql_mob_db || map->db_use_sql_mob_skill_db ) - config |= C_SQL_DBS; //TODO: split this config into three. + if( map->db_use_sql_item_db ) + config |= C_SQL_DB_ITEM; + if( map->db_use_sql_mob_db ) + config |= C_SQL_DB_MOB; + if( map->db_use_sql_mob_skill_db ) + config |= C_SQL_DB_MOBSKILL; if( logs->config.sql_logs ) config |= C_SQL_LOGS; @@ -6855,30 +6872,40 @@ void Hercules_report(char* date, char *time_c) { #define BFLAG_LENGTH 35 - CREATE(buf, char, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 ); + CREATE(buf, char, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 ); /* build packet */ WBUFW(buf,0) = 0x3000; - WBUFW(buf,2) = 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); - WBUFW(buf,4) = 0x9e; + WBUFW(buf,2) = 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); + WBUFW(buf,4) = 0x9f; safestrncpy((char*)WBUFP(buf,6), date, 12); - safestrncpy((char*)WBUFP(buf,6 + 12), time_c, 9); - safestrncpy((char*)WBUFP(buf,6 + 12 + 9), timestring, 24); - - safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24), git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown", 41); - WBUFL(buf,6 + 12 + 9 + 24 + 41) = map->getusers(); - - WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4) = config; - WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4) = bd_size; - + safestrncpy((char*)WBUFP(buf,18), time_c, 9); + safestrncpy((char*)WBUFP(buf,27), timestring, 24); + + safestrncpy((char*)WBUFP(buf,51), sysinfo->platform(), 16); + safestrncpy((char*)WBUFP(buf,67), sysinfo->osversion(), 50); + safestrncpy((char*)WBUFP(buf,117), sysinfo->cpu(), 32); + WBUFL(buf,149) = sysinfo->cpucores(); + safestrncpy((char*)WBUFP(buf,153), sysinfo->arch(), 8); + WBUFB(buf,161) = sysinfo->vcstypeid(); + WBUFB(buf,162) = sysinfo->is64bit(); + safestrncpy((char*)WBUFP(buf,163), sysinfo->vcsrevision_src(), 41); + safestrncpy((char*)WBUFP(buf,204), sysinfo->vcsrevision_scripts(), 41); + WBUFB(buf,245) = (sysinfo->is_superuser()? 1 : 0); + WBUFL(buf,246) = map->getusers(); + + WBUFL(buf,250) = config; + WBUFL(buf,254) = PACKETVER; + + WBUFL(buf,258) = bd_size; for( i = 0; i < bd_size; i++ ) { - safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35); - WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; + safestrncpy((char*)WBUFP(buf,262 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, BFLAG_LENGTH); + WBUFL(buf,262 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; } - chrif->send_report(buf, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); + chrif->send_report(buf, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); aFree(buf); diff --git a/src/map/battle.h b/src/map/battle.h index b57476cb4..aab94420a 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -2,11 +2,11 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_BATTLE_H_ -#define _MAP_BATTLE_H_ +#ifndef MAP_BATTLE_H +#define MAP_BATTLE_H -#include "../common/cbasetypes.h" #include "map.h" //ELE_MAX +#include "../common/cbasetypes.h" /** * Declarations @@ -21,12 +21,12 @@ struct status_data; /** * Defines **/ -#define MIN_HAIR_STYLE (battle_config.min_hair_style) -#define MAX_HAIR_STYLE (battle_config.max_hair_style) -#define MIN_HAIR_COLOR (battle_config.min_hair_color) -#define MAX_HAIR_COLOR (battle_config.max_hair_color) -#define MIN_CLOTH_COLOR (battle_config.min_cloth_color) -#define MAX_CLOTH_COLOR (battle_config.max_cloth_color) +#define MIN_HAIR_STYLE (battle->bc->min_hair_style) +#define MAX_HAIR_STYLE (battle->bc->max_hair_style) +#define MIN_HAIR_COLOR (battle->bc->min_hair_color) +#define MAX_HAIR_COLOR (battle->bc->max_hair_color) +#define MIN_CLOTH_COLOR (battle->bc->min_cloth_color) +#define MAX_CLOTH_COLOR (battle->bc->max_cloth_color) #define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] @@ -79,7 +79,7 @@ enum e_battle_check_target { //New definitions [Skotlex] * Structures **/ -// dammage structure +// damage structure struct Damage { int64 damage,damage2; //right, left dmg int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit @@ -437,6 +437,7 @@ struct Battle_Config { // rAthena int max_third_parameter; int max_baby_third_parameter; + int max_extended_parameter; int atcommand_max_stat_bypass; int max_third_aspd; int vcast_stat_scale; @@ -468,7 +469,11 @@ struct Battle_Config { int mon_trans_disable_in_gvg; int case_sensitive_aegisnames; -} battle_config; + int guild_castle_invite; + int guild_castle_expulsion; +}; + +extern struct Battle_Config battle_config; /* criteria for battle_config.idletime_critera */ enum e_battle_config_idletime { @@ -484,7 +489,7 @@ enum e_battle_config_idletime { BCIDLE_ATCOMMAND = 0x200, }; -// Dammage delayed info +// Damage delayed info struct delay_damage { int src_id; int target_id; @@ -536,9 +541,9 @@ struct battle_interface { int64 (*attr_fix) (struct block_list *src, struct block_list *target, int64 damage, int atk_elem, int def_type, int def_lv); /* applies card modifiers */ int64 (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag); - /* applies element modifiers */ + /* applies element modifiers */ int64 (*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); - /* applies mastery modifiers */ + /* applies mastery modifiers */ int64 (*calc_masteryfix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon); /* calculates chorus bonus */ int (*calc_chorusbonus) (struct map_session_data *sd); @@ -566,7 +571,7 @@ struct battle_interface { int (*check_target) (struct block_list *src, struct block_list *target,int flag); /* is src and bl within range? */ bool (*check_range) (struct block_list *src,struct block_list *bl,int range); - /* consume amo for this skill and lv */ + /* consume ammo for this skill and lv */ void (*consume_ammo) (struct map_session_data* sd, int skill_id, int lv); int (*get_targeted_sub) (struct block_list *bl, va_list ap); int (*get_enemy_sub) (struct block_list *bl, va_list ap); @@ -598,4 +603,4 @@ struct battle_interface { struct battle_interface *battle; void battle_defaults(void); -#endif /* _MAP_BATTLE_H_ */ +#endif /* MAP_BATTLE_H */ diff --git a/src/map/battleground.c b/src/map/battleground.c index 68539e25d..f7131513d 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -2,29 +2,32 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/conf.h" +#define HERCULES_CORE #include "battleground.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 "pc.h" #include "party.h" +#include "pc.h" #include "pet.h" -#include "homunculus.h" -#include "mercenary.h" -#include "mapreg.h" - -#include <string.h> -#include <stdio.h> +#include "../common/cbasetypes.h" +#include "../common/conf.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; @@ -538,7 +541,7 @@ void bg_match_over(struct bg_arena *arena, bool canceled) { bg->queue_pc_cleanup(sd); } if( canceled ) - clif->colormes(sd->fd,COLOR_RED,"BG Match Cancelled: not enough players"); + clif->colormes(sd->fd,COLOR_RED,"BG Match Canceled: not enough players"); else { pc_setglobalreg(sd, script->add_str(arena->delay_var), (unsigned int)time(NULL)); } @@ -576,7 +579,7 @@ void bg_begin(struct bg_arena *arena) { if( bg->afk_timer_id == INVALID_TIMER && bg->mafksec > 0 ) bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0); - /* TODO: make this a arena-independant var? or just .@? */ + /* TODO: make this a arena-independent var? or just .@? */ mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id); mapreg->setregstr(script->add_str("$@bg_delay_var$"),bg->gdelay_var); diff --git a/src/map/battleground.h b/src/map/battleground.h index 05c4eb060..c1d3be054 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -2,12 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_BATTLEGROUND_H_ -#define _MAP_BATTLEGROUND_H_ +#ifndef MAP_BATTLEGROUND_H +#define MAP_BATTLEGROUND_H -#include "../common/mmo.h" // struct party #include "clif.h" #include "guild.h" +#include "../common/mmo.h" // struct party /** * Defines @@ -122,4 +122,4 @@ struct battleground_interface *bg; void battleground_defaults(void); -#endif /* _MAP_BATTLEGROUND_H_ */ +#endif /* MAP_BATTLEGROUND_H */ diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 2a15e66fc..80264b30d 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -2,18 +2,21 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#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 +#define HERCULES_CORE + +#include "buyingstore.h" // struct s_buyingstore + #include "atcommand.h" // msg_txt #include "battle.h" // battle_config.* -#include "buyingstore.h" // struct s_buyingstore +#include "chrif.h" #include "clif.h" // clif->buyingstore_* #include "log.h" // log_pick_pc, log_zeny #include "pc.h" // struct map_session_data -#include "chrif.h" +#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 struct buyingstore_interface buyingstore_s; diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index 5141a1013..c981cc444 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -2,8 +2,13 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_BUYINGSTORE_H_ -#define _MAP_BUYINGSTORE_H_ +#ifndef MAP_BUYINGSTORE_H +#define MAP_BUYINGSTORE_H + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" // MAX_SLOTS + +struct map_session_data; /** * Declarations @@ -70,4 +75,4 @@ struct buyingstore_interface *buyingstore; void buyingstore_defaults (void); -#endif // _MAP_BUYINGSTORE_H_ +#endif // MAP_BUYINGSTORE_H diff --git a/src/map/chat.c b/src/map/chat.c index 08fc4a575..cd7b5f811 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -2,12 +2,13 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/mmo.h" +#define HERCULES_CORE + +#include "chat.h" + +#include <stdio.h> +#include <string.h> + #include "atcommand.h" // msg_txt() #include "battle.h" // struct battle_config #include "clif.h" @@ -15,10 +16,12 @@ #include "npc.h" // npc_event_do() #include "pc.h" #include "skill.h" // ext_skill_unit_onplace() -#include "chat.h" - -#include <stdio.h> -#include <string.h> +#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; @@ -29,7 +32,7 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons struct chat_data* cd; nullpo_retr(NULL, bl); - /* Given the overhead and the numerous instances (npc allocatted or otherwise) wouldn't it be benefitial to have it use ERS? [Ind] */ + /* 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)); safestrncpy(cd->title, title, sizeof(cd->title)); @@ -154,8 +157,8 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { pc_setchatid(sd,cd->bl.id); clif->joinchatok(sd, cd); //To the person who newly joined the list of all - clif->addchat(cd, sd); //Reports To the person who already in the chat - clif->dispchat(cd, 0); //Reported number of changes to the people around + clif->addchat(cd, sd); //Reports To the person who already in the chat + clif->dispchat(cd, 0); //Reported number of changes to the people around chat->trigger_event(cd); //Event @@ -443,7 +446,7 @@ bool chat_npckickall(struct chat_data* cd) } /*===================================== -* Default Functions : chat.h +* Default Functions : chat.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/chat.h b/src/map/chat.h index b0c6cd905..e055c04ed 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -2,19 +2,22 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_CHAT_H_ -#define _MAP_CHAT_H_ +#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" -struct map_session_data; struct chat_data; +struct map_session_data; +struct npc_data; #define MAX_CHAT_USERS 20 struct chat_data { struct block_list bl; // data for this map object - char title[CHATROOM_TITLE_SIZE]; // room title + char title[CHATROOM_TITLE_SIZE]; // room title char pass[CHATROOM_PASS_SIZE]; // password bool pub; // private/public flag uint8 users; // current user count @@ -31,7 +34,7 @@ struct chat_data { }; /*===================================== -* Interface : chat.h +* Interface : chat.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -57,4 +60,4 @@ struct chat_interface *chat; void chat_defaults(void); -#endif /* _MAP_CHAT_H_ */ +#endif /* MAP_CHAT_H */ diff --git a/src/map/chrif.c b/src/map/chrif.c index 99a1935fd..54cc139f4 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -2,15 +2,16 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/ers.h" -#include "../common/HPM.h" +#define HERCULES_CORE + +#include "../config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT +#include "chrif.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> #include "map.h" #include "battle.h" @@ -25,15 +26,17 @@ #include "instance.h" #include "mercenary.h" #include "elemental.h" -#include "chrif.h" #include "quest.h" #include "storage.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <time.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; @@ -52,7 +55,7 @@ struct chrif_interface chrif_s; //2b03: Incoming, clif_charselectok -> '' (i think its the packet after enterworld?) (not sure) //2b04: Incoming, chrif_recvmap -> 'getting maps from charserver of other mapserver's' //2b05: Outgoing, chrif_changemapserver -> 'Tell the charserver the mapchange / quest for ok...' -//2b06: Incoming, chrif_changemapserverack -> 'awnser of 2b05, ok/fail, data: dunno^^' +//2b06: Incoming, chrif_changemapserverack -> 'answer of 2b05, ok/fail, data: dunno^^' //2b07: Outgoing, chrif_removefriend -> 'Tell charserver to remove friend_id from char_id friend list' //2b08: Outgoing, chrif_searchcharid -> '...' //2b09: Incoming, map_addchariddb -> 'Adds a name to the nick db' @@ -76,7 +79,7 @@ struct chrif_interface chrif_s; //2b1b: Incoming, chrif_recvfamelist -> 'Receive fame ranking lists' //2b1c: Outgoing, chrif_save_scdata -> 'Send sc_data of player for saving.' //2b1d: Incoming, chrif_load_scdata -> 'received sc_data of player for loading.' -//2b1e: Incoming, chrif_update_ip -> 'Reqest forwarded from char-server for interserver IP sync.' [Lance] +//2b1e: Incoming, chrif_update_ip -> 'Request forwarded from char-server for interserver IP sync.' [Lance] //2b1f: Incoming, chrif_disconnectplayer -> 'disconnects a player (aid X) with the message XY ... 0x81 ..' [Sirius] //2b20: Incoming, chrif_removemap -> 'remove maps of a server (sample: its going offline)' [Sirius] //2b21: Incoming, chrif_save_ack. Returned after a character has been "final saved" on the char-server. [Skotlex] @@ -268,7 +271,7 @@ bool chrif_save(struct map_session_data *sd, int flag) { if (flag) sd->state.storage_flag = 0; //Force close it. - //Saving of registry values. + //Saving of registry values. if (sd->vars_dirty) intif->saveregistry(sd); @@ -288,7 +291,7 @@ bool chrif_save(struct map_session_data *sd, int flag) { if( sd->md && mercenary->get_lifetime(sd->md) > 0 ) mercenary->save(sd->md); if( sd->ed && elemental->get_lifetime(sd->ed) > 0 ) - elemental->save(sd->ed); + elemental->save(sd->ed); if( sd->save_quest ) intif->quest_save(sd); @@ -390,7 +393,7 @@ bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) return true; } -/// map-server change request acknowledgement (positive or negative) +/// map-server change request acknowledgment (positive or negative) /// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map_index>.W <x>.W <y>.W <ip>.L <port>.W bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) { struct auth_node *node; @@ -850,9 +853,9 @@ void chrif_changedsex(int fd) { // Path to activate this response: // Map(start) (0x2b0e) -> Char(0x2727) -> Login // Login(0x2723) [ALL] -> Char (0x2b0d)[ALL] -> Map (HERE) - // Char will usually be "logged in" despite being forced to log-out in the begining + // Char will usually be "logged in" despite being forced to log-out in the beginning // of this process, but there's no need to perform map-server specific response - // as everything should've been changed through char-server [Panikon] + // as everything should been changed through char-server [Panikon] } /*========================================== * Request Char Server to Divorce Players @@ -941,14 +944,14 @@ void chrif_idbanned(int fd) { } sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters - if (RFIFOB(fd,6) == 0) { // 0: change of statut + if (RFIFOB(fd,6) == 0) { // 0: change of status int ret_status = RFIFOL(fd,7); // status or final date of a banishment if(0<ret_status && ret_status<=9) clif->message(sd->fd, msg_txt(411+ret_status)); // Message IDs (for search convenience): 412, 413, 414, 415, 416, 417, 418, 419, 420 else if(ret_status==100) clif->message(sd->fd, msg_txt(421)); else - clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorised." + clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorized." } else if (RFIFOB(fd,6) == 1) { // 1: ban time_t timestamp; char tmpstr[2048]; @@ -1203,7 +1206,7 @@ bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) { /*========================================= - * Tell char-server charcter disconnected [Wizputer] + * Tell char-server character disconnected [Wizputer] *-----------------------------------------*/ bool chrif_char_offline_nsd(int account_id, int char_id) { chrif_check(false); @@ -1244,7 +1247,7 @@ bool chrif_char_reset_offline(void) { } /*========================================= - * Tell char-server charcter is online [Wizputer] + * Tell char-server character is online [Wizputer] *-----------------------------------------*/ bool chrif_char_online(struct map_session_data *sd) { chrif_check(false); @@ -1364,7 +1367,7 @@ int chrif_parse(int fd) { if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) { r = intif->parse(fd); // Passed on to the intif - if (r == 1) continue; // Treated in intif + if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd); @@ -1530,7 +1533,7 @@ void chrif_send_report(char* buf, int len) { } /** - * Sends a single scdata for saving into char server, meant to ensure integrity of durationless conditions + * Sends a single scdata for saving into char server, meant to ensure integrity of duration-less conditions **/ void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) { @@ -1552,7 +1555,7 @@ void chrif_save_scdata_single(int account_id, int char_id, short type, struct st } /** - * Sends a single scdata deletion request into char server, meant to ensure integrity of durationless conditions + * Sends a single scdata deletion request into char server, meant to ensure integrity of duration-less conditions **/ void chrif_del_scdata_single(int account_id, int char_id, short type) { @@ -1635,7 +1638,7 @@ void do_init_chrif(bool minimal) { /*===================================== -* Default Functions : chrif.h +* Default Functions : chrif.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/chrif.h b/src/map/chrif.h index 25e955604..11baaf5ff 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -2,12 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_CHRIF_H_ -#define _MAP_CHRIF_H_ +#ifndef MAP_CHRIF_H +#define MAP_CHRIF_H -#include "../common/cbasetypes.h" #include <time.h> + #include "map.h" //TBL_stuff +#include "../common/cbasetypes.h" +#include "../common/db.h" struct status_change_entry; @@ -39,7 +41,7 @@ struct auth_node { }; /*===================================== -* Interface : chrif.h +* Interface : chrif.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -51,7 +53,7 @@ struct chrif_interface { int other_mapserver_count; //Holds count of how many other map servers are online (apart of this instance) [Skotlex] /* */ - struct eri *auth_db_ers; //For reutilizing player login structures. + struct eri *auth_db_ers; //For re-utilizing player login structures. DBMap* auth_db; // int id -> struct auth_node* /* */ int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE]; @@ -152,4 +154,4 @@ void chrif_defaults(void); // There's no need for another function when a simple macro can do exactly the same effect #define chrif_char_offline(x) chrif->char_offline_nsd((x)->status.account_id,(x)->status.char_id) -#endif /* _MAP_CHRIF_H_ */ +#endif /* MAP_CHRIF_H */ diff --git a/src/map/clif.c b/src/map/clif.c index 7715e6c6a..9e105e4a9 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2,56 +2,60 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/grfio.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 "../common/ers.h" -#include "../common/conf.h" -#include "../common/HPM.h" +#define HERCULES_CORE + +#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT +#include "clif.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <time.h> -#include "map.h" -#include "chrif.h" -#include "pc.h" -#include "status.h" -#include "npc.h" -#include "itemdb.h" -#include "chat.h" -#include "trade.h" -#include "storage.h" -#include "script.h" -#include "skill.h" #include "atcommand.h" -#include "intif.h" #include "battle.h" #include "battleground.h" -#include "mob.h" -#include "party.h" -#include "unit.h" +#include "chat.h" +#include "chrif.h" +#include "elemental.h" #include "guild.h" -#include "vending.h" -#include "pet.h" #include "homunculus.h" #include "instance.h" -#include "mercenary.h" -#include "elemental.h" +#include "intif.h" +#include "irc-bot.h" +#include "itemdb.h" #include "log.h" -#include "clif.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 "irc-bot.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <time.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; @@ -61,8 +65,10 @@ static struct packet_itemlist_equip itemlist_equip; static struct packet_storelist_normal storelist_normal; static struct packet_storelist_equip storelist_equip; static struct packet_viewequip_ack viewequip_list; +#if PACKETVER >= 20131223 static struct packet_npc_market_result_ack npcmarket_result; static struct packet_npc_market_open npcmarket_open; +#endif //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET @@ -1099,7 +1105,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { p.accessory = status->get_emblem_id(bl); p.accessory2 = GetWord(g_id, 1); p.accessory3 = GetWord(g_id, 0); - } + } p.headpalette = vd->hair_color; p.bodypalette = vd->cloth_color; p.headDir = (sd)? sd->head_dir : 0; @@ -1219,7 +1225,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.GID = -bl->id; #else p.GID = -bl->id; -#endif +#endif clif->send(&p,sizeof(p),bl,SELF); } } @@ -2582,7 +2588,7 @@ void clif_cartlist(struct map_session_data *sd) { /// Removes cart (ZC_CARTOFF). /// 012b -/// Client behaviour: +/// Client behavior: /// Closes the cart storage and removes all it's items from memory. /// The Num & Weight values of the cart are left untouched and the cart is NOT removed. void clif_clearcart(int fd) @@ -4616,6 +4622,8 @@ void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send /// 099f <lenght>.W <id> L <creator id>.L <x>.W <y>.W <unit id>.L <range>.W <visible>.B (ZC_SKILL_ENTRY4) void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, enum send_target target) { struct packet_skill_entry p; + nullpo_retv(bl); + nullpo_retv(su); if( su->group->state.guildaura ) return; @@ -5041,7 +5049,7 @@ void clif_skillcastcancel(struct block_list* bl) /// 4 = "no party" MsgStringTable[163] /// 5 = "no shout" MsgStringTable[164] /// 6 = "no PKing" MsgStringTable[165] -/// 7 = "no alligning" MsgStringTable[383] +/// 7 = "no aligning" MsgStringTable[383] /// ? = ignored /// cause: /// 0 = "not enough skill level" MsgStringTable[214] (AL_WARP) @@ -5419,7 +5427,7 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) { } -/// Presents a textual list of producable items (ZC_MAKABLEITEMLIST). +/// Presents a textual list of producible items (ZC_MAKABLEITEMLIST). /// 018d <packet len>.W { <name id>.W { <material id>.W }*3 }* /// material id: /// unused by the client @@ -5461,7 +5469,7 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int } -/// Present a list of producable items (ZC_MAKINGITEM_LIST). +/// Present a list of producible items (ZC_MAKINGITEM_LIST). /// 025a <packet len>.W <mk type>.W { <name id>.W }* /// mk type: /// 1 = cooking @@ -5597,7 +5605,7 @@ void clif_displaymessage(const int fd, const char* mes) { if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line. WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate safestrncpy((char *)WFIFOP(fd,4), mes, len + 1); WFIFOSET(fd, 5 + len); } @@ -5626,14 +5634,14 @@ void clif_displaymessage2(const int fd, const char* mes) { } else { WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate safestrncpy((char *)WFIFOP(fd,4), line, len + 1); WFIFOSET(fd, 5 + len); } } line = strtok(NULL, "\n"); } - aFree(message); + aFree(message); } } /* oh noo! another version of 0x8e! */ @@ -5643,7 +5651,7 @@ void clif_displaymessage_sprintf(const int fd, const char* mes, ...) { if( map->cpsd_active && fd == 0 ) { ShowInfo("HCP: "); va_start(ap,mes); - _vShowMessage(MSG_NONE,mes,ap); + vShowMessage_(MSG_NONE,mes,ap); va_end(ap); ShowMessage("\n"); } else if ( fd > 0 ) { @@ -5663,7 +5671,7 @@ void clif_displaymessage_sprintf(const int fd, const char* mes, ...) { /* */ WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate WFIFOSET(fd, 5 + len); } @@ -5918,8 +5926,8 @@ void clif_wis_message(int fd, const char* nick, const char* mes, size_t mes_len) /// Inform the player about the result of his whisper action (ZC_ACK_WHISPER). /// 0098 <result>.B /// result: -/// 0 = success to send wisper -/// 1 = target character is not loged in +/// 0 = success to send whisper +/// 1 = target character is not logged in /// 2 = ignored by target /// 3 = everyone ignored by target void clif_wis_end(int fd, int flag) { @@ -6164,7 +6172,7 @@ void clif_item_refine_list(struct map_session_data *sd) WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); WFIFOW(fd,0)=0x221; for(i=c=0;i<MAX_INVENTORY;i++){ - if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 && !sd->inventory_data[i]->flag.no_refine && !(sd->status.inventory[i].equip&EQP_ARMS)){ @@ -6185,7 +6193,7 @@ 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 <upgradable>.B +/// 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) { int fd; @@ -7270,7 +7278,7 @@ void clif_mvp_noitem(struct map_session_data* sd) /// 0 = "Guild has been created." /// 1 = "You are already in a Guild." /// 2 = "That Guild Name already exists." -/// 3 = "You need the neccessary item to create a Guild." +/// 3 = "You need the necessary item to create a Guild." void clif_guild_created(struct map_session_data *sd,int flag) { int fd; @@ -7663,7 +7671,7 @@ void clif_guild_emblem_area(struct block_list* bl) /// Sends guild skills (ZC_GUILD_SKILLINFO). -/// 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradable>.B }* +/// 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) { int fd; @@ -8131,7 +8139,7 @@ void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum /// result: /// 0 = failure /// 1 = success -void clif_GM_kickack(struct map_session_data *sd, int id) +void clif_GM_kickack(struct map_session_data *sd, int result) { int fd; @@ -8140,7 +8148,7 @@ void clif_GM_kickack(struct map_session_data *sd, int id) fd = sd->fd; WFIFOHEAD(fd,packet_len(0xcd)); WFIFOW(fd,0) = 0xcd; - WFIFOB(fd,2) = id; // FIXME: this is not account id + WFIFOB(fd,2) = result; WFIFOSET(fd, packet_len(0xcd)); } @@ -8154,7 +8162,7 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) { map->quit(tsd); if( sd ) - clif->GM_kickack(sd,tsd->status.account_id); + clif->GM_kickack(sd, 1); } @@ -8180,7 +8188,7 @@ void clif_manner_message(struct map_session_data* sd, uint32 type) } -/// Followup to 0x14a type 3/5, informs who did the manner adjustment action (ZC_NOTIFY_MANNER_POINT_GIVEN). +/// 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: /// 0 = positive (unmute) @@ -8271,7 +8279,7 @@ void clif_playBGM(struct map_session_data* sd, const char* name) /// term: /// unknown purpose, only relevant to act = 1 /// npc id: -/// The accustic direction of the sound is determined by the +/// The acoustic direction of the sound is determined by the /// relative position of the NPC to the player (3D sound). void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const char* name, int type) { @@ -8420,6 +8428,34 @@ void clif_message(struct block_list* bl, const char* msg) { 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 ) { + // Notify the client that the storage is open + if( sd->state.storage_flag == 1 ) { + storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); + clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); + clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + } + // 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 ) { + struct guild_storage *gstor; + if( (gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) { + // Shouldn't happen... The information should already be at the map-server + intif->request_guild_storage(sd->status.account_id,sd->status.guild_id); + } else { + storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items)); + clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); + clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); + } + } +} + // refresh the client's screen, getting rid of any effects void clif_refresh(struct map_session_data *sd) { @@ -8480,6 +8516,7 @@ void clif_refresh(struct map_session_data *sd) pc->disguise(sd, disguise); } + clif->refresh_storagewindow(sd); } @@ -8567,11 +8604,11 @@ void clif_charnameack (int fd, struct block_list *bl) nullpo_retv(md); memcpy(WBUFP(buf,6), md->name, NAME_LENGTH); - if( md->guardian_data && md->guardian_data->guild_id ) + if( md->guardian_data && md->guardian_data->g ) { WBUFW(buf, 0) = cmd = 0x195; WBUFB(buf,30) = 0; - memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH); + memcpy(WBUFP(buf,54), md->guardian_data->g->name, NAME_LENGTH); memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH); } else if( battle_config.show_mob_info ) @@ -8608,7 +8645,7 @@ void clif_charnameack (int fd, struct block_list *bl) return; } - // if no receipient specified just update nearby clients + // if no recipient specified just update nearby clients if (fd == 0) clif->send(buf, packet_len(cmd), bl, AREA); else { @@ -8703,7 +8740,7 @@ void clif_slide(struct block_list *bl, int x, int y) /// 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 theorical max is CHAT_SIZE + 8 (pads and extra inserted crap) + 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 if (len_mes > sizeof(buf)-8) { @@ -8811,7 +8848,7 @@ void clif_starskill(struct map_session_data* sd, const char* mapname, int monste } /*========================================== - * Info about Star Glaldiator save map [Komurka] + * Info about Star Gladiator save map [Komurka] * type: 1: Information, 0: Map registered *------------------------------------------*/ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsigned char type) @@ -8823,7 +8860,7 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig } /*========================================== - * Info about Star Glaldiator hate mob [Komurka] + * Info about Star Gladiator hate mob [Komurka] * type: 1: Register mob, 0: Information. *------------------------------------------*/ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type) @@ -9017,7 +9054,7 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : ' { - //Hacked message, or infamous "client desynch" issue where they pick one char while loading another. + //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. return false; @@ -9829,7 +9866,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) if( atcommand->exec(fd, sd, message, true) ) return; - if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( !pc->can_talk(sd) ) return; if( battle_config.min_chat_delay ) { //[Skotlex] @@ -10076,14 +10113,14 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, return; } - if (sd->sc.count && - (sd->sc.data[SC_TRICKDEAD] || - sd->sc.data[SC_AUTOCOUNTER] || - sd->sc.data[SC_BLADESTOP] || - sd->sc.data[SC_DEEP_SLEEP] || - sd->sc.data[SC__MANHOLE] || - sd->sc.data[SC_CURSEDCIRCLE_ATKER] || - sd->sc.data[SC_CURSEDCIRCLE_TARGET] )) + // Statuses that don't let the player sit / attack / talk with NPCs(targeted) + // (not all are included in pc_can_attack) + if( sd->sc.count && ( + sd->sc.data[SC_TRICKDEAD] || + (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) || + sd->sc.data[SC_BLADESTOP] || + sd->sc.data[SC_DEEP_SLEEP] ) + ) return; pc_stop_walking(sd, 1); @@ -10107,10 +10144,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if( sd->sc.option&OPTION_COSTUME ) return; - if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] || - (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) ) - return; - if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) { if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); @@ -10277,7 +10310,7 @@ void clif_hercules_chsys_quit(struct map_session_data *sd) { sd->channel_count = 0; aFree(sd->channels); - sd->channels = NULL; + sd->channels = NULL; } /// Request for an action. @@ -10288,7 +10321,7 @@ void clif_hercules_chsys_quit(struct map_session_data *sd) { /// 1 = pick up item /// 2 = sit down /// 3 = stand up -/// 7 = continous attack +/// 7 = continuous attack /// 12 = (touch skill?) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_ActionRequest(int fd, struct map_session_data *sd) @@ -10342,7 +10375,8 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if ( atcommand->exec(fd, sd, message, true) ) return; - if (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) + // Statuses that prevent the player from whispering + if( !pc->can_talk(sd) ) return; if (battle_config.min_chat_delay) { //[Skotlex] @@ -11002,7 +11036,7 @@ void clif_parse_ChatLeave(int fd, struct map_session_data* sd) } -//Handles notifying asker and rejecter of what has just ocurred. +//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) { @@ -11128,8 +11162,8 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) /// 012a void clif_parse_RemoveOption(int fd,struct map_session_data *sd) { - if( !(sd->sc.option&(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)) -#ifdef NEW_CARTS + if( !(sd->sc.option&(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)) +#ifdef NEW_CARTS && sd->sc.data[SC_PUSH_CART] ){ pc->setcart(sd,0); #else @@ -11341,10 +11375,6 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) ) return; - // Some self skills need to close the storage to work properly - if( skill_id == AL_TELEPORT && sd->state.storage_flag ) - storage->close(sd); - if( pc_issit(sd) ) return; @@ -11545,7 +11575,8 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) if(skill_id != sd->menuskill_id) return; - if( pc_cant_act(sd) ) { + // 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) ) { clif_menuskill_clear(sd); return; } @@ -12207,7 +12238,7 @@ void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) { /// Party Booking in KRO [Spiria] /// -/// Request to register a party booking advertisment (CZ_PARTY_BOOKING_REQ_REGISTER). +/// Request to register a party booking advertisement (CZ_PARTY_BOOKING_REQ_REGISTER). /// 0802 <level>.W <map id>.W { <job>.W }*6 void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) { @@ -12227,7 +12258,7 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) } -/// Result of request to register a party booking advertisment (ZC_PARTY_BOOKING_ACK_REGISTER). +/// Result of request to register a party booking advertisement (ZC_PARTY_BOOKING_ACK_REGISTER). /// 0803 <result>.W /// result: /// 0 = success @@ -12248,7 +12279,7 @@ void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag) } -/// Request to search for party booking advertisments (CZ_PARTY_BOOKING_REQ_SEARCH). +/// 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) { @@ -12299,7 +12330,7 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, } -/// Request to delete own party booking advertisment (CZ_PARTY_BOOKING_REQ_DELETE). +/// Request to delete own party booking advertisement (CZ_PARTY_BOOKING_REQ_DELETE). /// 0806 void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) { @@ -12312,7 +12343,7 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) } -/// Result of request to delete own party booking advertisment (ZC_PARTY_BOOKING_ACK_DELETE). +/// Result of request to delete own party booking advertisement (ZC_PARTY_BOOKING_ACK_DELETE). /// 0807 <result>.W /// result: /// 0 = success @@ -12334,7 +12365,7 @@ void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag) } -/// Request to update party booking advertisment (CZ_PARTY_BOOKING_REQ_UPDATE). +/// 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) { @@ -12352,7 +12383,7 @@ void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) } -/// Notification about new party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_INSERT). +/// 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) { @@ -12378,7 +12409,7 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo } -/// Notification about updated party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_UPDATE). +/// 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) { @@ -12399,7 +12430,7 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo } -/// Notification about deleted party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_DELETE). +/// Notification about deleted party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_DELETE). /// 080b <index>.L void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) { @@ -12418,7 +12449,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) /// Modified version of Party Booking System for 2012-04-10 or 2012-04-18 (RagexeRE). /// Code written by mkbu95, Spiria, Yommy and Ind -/// Request to register a party booking advertisment (CZ_PARTY_RECRUIT_REQ_REGISTER). +/// Request to register a party booking advertisement (CZ_PARTY_RECRUIT_REQ_REGISTER). /// 08e5 <level>.W <notice>.37B void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd) { @@ -12465,7 +12496,7 @@ void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results, #endif } -/// Result of request to register a party booking advertisment (ZC_PARTY_RECRUIT_ACK_REGISTER). +/// Result of request to register a party booking advertisement (ZC_PARTY_RECRUIT_ACK_REGISTER). /// 08e6 <result>.W /// result: /// 0 = success @@ -12485,7 +12516,7 @@ void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag) #endif } -/// Request to search for party booking advertisments (CZ_PARTY_RECRUIT_REQ_SEARCH). +/// 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) { @@ -12501,7 +12532,7 @@ void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd) #endif } -/// Request to delete own party booking advertisment (CZ_PARTY_RECRUIT_REQ_DELETE). +/// Request to delete own party booking advertisement (CZ_PARTY_RECRUIT_REQ_DELETE). /// 08e9 void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) { @@ -12513,7 +12544,7 @@ void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) #endif } -/// Result of request to delete own party booking advertisment (ZC_PARTY_RECRUIT_ACK_DELETE). +/// Result of request to delete own party booking advertisement (ZC_PARTY_RECRUIT_ACK_DELETE). /// 08ea <result>.W /// result: /// 0 = success @@ -12534,7 +12565,7 @@ void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag) #endif } -/// Request to update party booking advertisment (CZ_PARTY_RECRUIT_REQ_UPDATE). +/// 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) { @@ -12549,7 +12580,7 @@ void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) #endif } -/// Notification about new party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_INSERT). +/// Notification about new party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_INSERT). /// 08ec <index>.L <expire time>.L <char name>.24B <level>.W <notice>.37B void clif_PartyRecruitInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad) { @@ -12571,7 +12602,7 @@ void clif_PartyRecruitInsertNotify(struct map_session_data* sd, struct party_boo #endif } -/// Notification about updated party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_UPDATE). +/// Notification about updated party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_UPDATE). /// 08ed <index>.L <notice>.37B void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info* pb_ad) { @@ -12588,7 +12619,7 @@ void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_boo #endif } -/// Notification about deleted party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_DELETE). +/// Notification about deleted party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_DELETE). /// 08ee <index>.L void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index) { @@ -13140,7 +13171,7 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) if(!sd->state.gmaster_flag) return; - // compensate for some client defects when using multilanguage mode + // compensate for some client defects when using multilingual mode if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string @@ -13580,7 +13611,7 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) { /// Request to execute GM commands. /// usage: /// /item n - summon n monster or acquire n item/s -/// /item money - grants 2147483647 zenies +/// /item money - grants 2147483647 Zeny /// /item whereisboss - locate boss mob in current map.(not yet implemented) /// /item regenboss_n t - regenerate n boss monster by t millisecond.(not yet implemented) /// /item onekillmonster - toggle an ability to kill mobs in one hit.(not yet implemented) @@ -13684,7 +13715,7 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) { return; value = battle_config.client_accept_chatdori; - dstsd = sd; + dstsd = sd; } else { dstsd = map->id2sd(id); if( dstsd == NULL ) @@ -13961,7 +13992,7 @@ void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int cha } -//Subfunction called from clif_foreachclient to toggle friends on/off [Skotlex] +//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) { int account_id, char_id, online; @@ -14310,7 +14341,7 @@ void clif_parse_ranklist(int fd, struct map_session_data *sd) { case RANKTYPE_BLACKSMITH: case RANKTYPE_ALCHEMIST: case RANKTYPE_TAEKWON: - clif->ranklist(sd, type); // pk_list unsuported atm + clif->ranklist(sd, type); // pk_list unsupported atm break; } } @@ -14581,18 +14612,27 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn] /// 0292 void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { int item_position = pc->search_inventory(sd, ITEMID_TOKEN_OF_SIEGFRIED); + int hpsp = 100; - if (item_position < 0) - return; + if (item_position < 0){ + if (sd->sc.data[SC_LIGHT_OF_REGENE]) + hpsp = 20 * sd->sc.data[SC_LIGHT_OF_REGENE]->val1; + else + return; + } if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER. return; - if (!status->revive(&sd->bl, 100, 100)) + if (!status->revive(&sd->bl, hpsp, hpsp)) return; + if ( item_position > 0) + pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); + else + status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); + clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); } @@ -14631,7 +14671,7 @@ void clif_check(int fd, struct map_session_data* pl_sd) { WFIFOW(fd,34) = pl_sd->battle_status.flee2/10; WFIFOW(fd,36) = pl_sd->battle_status.cri/10; WFIFOW(fd,38) = (2000-pl_sd->battle_status.amotion)/10; // aspd - WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe adelay? + WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe a delay? WFIFOSET(fd,packet_len(0x214)); } @@ -14696,7 +14736,7 @@ void clif_Mail_getattachment(int fd, uint8 flag) /// 0249 <result>.B /// result: /// 0 = success -/// 1 = recipinent does not exist +/// 1 = recipient does not exist void clif_Mail_send(int fd, bool fail) { WFIFOHEAD(fd,packet_len(0x249)); @@ -15521,20 +15561,10 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { WFIFOSET(fd,WFIFOW(fd,2)); } - /// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE). /// 0289 <cash point>.L <error>.W /// 0289 <cash point>.L <kafra point>.L <error>.W (PACKETVER >= 20070711) -/// error: -/// 0 = The deal has successfully completed. (ERROR_TYPE_NONE) -/// 1 = The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC) -/// 2 = The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM) -/// 3 = You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT) -/// 4 = You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE) -/// 5 = The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID) -/// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) -/// 7 = You can purchase up to 10 items. -/// 8 = Some items could not be purchased. +/// 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; @@ -16037,7 +16067,7 @@ void clif_mercenary_info(struct map_session_data *sd) { /// 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 <upgradable>.B }* +/// 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) { struct mercenary_data *md; @@ -17111,7 +17141,7 @@ void clif_parse_debug(int fd,struct map_session_data *sd) { } /*========================================== * Server tells client to display a window similar to Magnifier (item) one - * Server populates the window with avilable elemental converter options according to player's inventory + * Server populates the window with available elemental converter options according to player's inventory *------------------------------------------*/ int clif_elementalconverter_list(struct map_session_data *sd) { int i,c,view,fd; @@ -17526,7 +17556,7 @@ void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { WFIFOW(fd, 0) = 0x845; WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values WFIFOL(fd, 6) = sd->kafraPoints; - WFIFOSET(fd, 10); + WFIFOSET(fd, 10); } void clif_parse_CashShopClose(int fd, struct map_session_data *sd) { @@ -17556,7 +17586,7 @@ void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { } 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 curreny for us, confusing) + 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_txt(1489)); //Cash Shop is disabled in this map @@ -17761,7 +17791,7 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK clif->send(&p,sizeof(p), &sd->bl, SELF); } break; - } + } } @@ -17793,7 +17823,7 @@ void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) { default: clif->bgqueue_ack(sd,BGQA_FAIL_TYPE_INVALID, arena->id); return; - } + } bg->queue_add(sd, arena, (enum bg_queue_types)p->type); } @@ -18153,6 +18183,7 @@ void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) { } /* 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 item_data *id = NULL; @@ -18173,12 +18204,14 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) { npcmarket_open.PacketLength = 4 + ( sizeof(npcmarket_open.list[0]) * c ); clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF); +#endif } 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; npcmarket_result.PacketType = npcmarketresultackType; @@ -18211,11 +18244,14 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );; clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF); +#endif } void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { +#if PACKETVER >= 20131223 struct packet_npc_market_purchase *p = P2PTR(fd); clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p)); +#endif } /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { @@ -18646,6 +18682,7 @@ void clif_defaults(void) { clif->sitting = clif_sitting; clif->standing = clif_standing; clif->arrow_create_list = clif_arrow_create_list; + clif->refresh_storagewindow = clif_refresh_storagewindow; clif->refresh = clif_refresh; clif->fame_blacksmith = clif_fame_blacksmith; clif->fame_alchemist = clif_fame_alchemist; @@ -18986,7 +19023,7 @@ void clif_defaults(void) { clif->search_store_info_failed = clif_search_store_info_failed; clif->open_search_store_info = clif_open_search_store_info; clif->search_store_info_click_ack = clif_search_store_info_click_ack; - /* elemental-related */ + /* elemental-related */ clif->elemental_info = clif_elemental_info; clif->elemental_updatestatus = clif_elemental_updatestatus; /* bgqueue */ @@ -18996,7 +19033,7 @@ void clif_defaults(void) { clif->bgqueue_joined = clif_bgqueue_joined; clif->bgqueue_pcleft = clif_bgqueue_pcleft; clif->bgqueue_battlebegins = clif_bgqueue_battlebegins; - /* misc-handling */ + /* misc-handling */ clif->adopt_reply = clif_Adopt_reply; clif->adopt_request = clif_Adopt_request; clif->readbook = clif_readbook; @@ -19033,7 +19070,7 @@ void clif_defaults(void) { clif->npc_market_purchase_ack = clif_npc_market_purchase_ack; /*------------------------ *- Parse Incoming Packet - *------------------------*/ + *------------------------*/ clif->pWantToConnection = clif_parse_WantToConnection; clif->pLoadEndAck = clif_parse_LoadEndAck; clif->pTickSend = clif_parse_TickSend; @@ -19087,7 +19124,7 @@ void clif_defaults(void) { clif->pUseSkillToPos = clif_parse_UseSkillToPos; clif->pUseSkillToPosSub = clif_parse_UseSkillToPosSub; clif->pUseSkillToPos_homun = clif_parse_UseSkillToPos_homun; - clif->pUseSkillToPos_mercenary = clif_parse_UseSkillToPos_mercenary; + clif->pUseSkillToPos_mercenary = clif_parse_UseSkillToPos_mercenary; clif->pUseSkillToPosMoreInfo = clif_parse_UseSkillToPosMoreInfo; clif->pUseSkillMap = clif_parse_UseSkillMap; clif->pRequestMemo = clif_parse_RequestMemo; diff --git a/src/map/clif.h b/src/map/clif.h index 36bd42718..48316427f 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -2,16 +2,16 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_CLIF_H_ -#define _MAP_CLIF_H_ +#ifndef MAP_CLIF_H +#define MAP_CLIF_H +#include <stdarg.h> + +#include "map.h" +#include "packets_struct.h" #include "../common/cbasetypes.h" #include "../common/db.h" #include "../common/mmo.h" -#include "../common/socket.h" -#include "../map/map.h" -#include "../map/packets_struct.h" -#include <stdarg.h> /** * Declarations @@ -20,7 +20,6 @@ struct item; struct item_data; struct storage_data; struct guild_storage; -struct block_list; struct unit_data; struct map_session_data; struct homun_data; @@ -67,7 +66,7 @@ typedef enum send_target { AREA, // area AREA_WOS, // area, without self AREA_WOC, // area, without chatrooms - AREA_WOSC, // area, without own chatroom + AREA_WOSC, // area, without own chatrooms AREA_CHAT_WOC, // hearable area, without chatrooms CHAT, // current chatroom CHAT_WOS, // current chatroom, without self @@ -350,6 +349,22 @@ enum clif_messages { }; /** + * Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy) + **/ +enum cashshop_error { + ERROR_TYPE_NONE = 0, // The deal has successfully completed. (ERROR_TYPE_NONE) + ERROR_TYPE_NPC, // The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC) + ERROR_TYPE_SYSTEM, // The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM) + ERROR_TYPE_INVENTORY_WEIGHT, // You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT) + ERROR_TYPE_EXCHANGE, // You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE) + ERROR_TYPE_ITEM_ID, // The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID) + ERROR_TYPE_MONEY, // You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) + // Unofficial type names + ERROR_TYPE_QUANTITY, // You can purchase up to 10 items. (ERROR_TYPE_QUANTITY) + ERROR_TYPE_NOT_ALL, // Some items could not be purchased. (ERROR_TYPE_NOT_ALL) +}; + +/** * Color Table **/ enum clif_colors { @@ -650,6 +665,7 @@ struct clif_interface { void (*sitting) (struct block_list* bl); void (*standing) (struct block_list* bl); void (*arrow_create_list) (struct map_session_data *sd); + void (*refresh_storagewindow) (struct map_session_data *sd); void (*refresh) (struct map_session_data *sd); void (*fame_blacksmith) (struct map_session_data *sd, int points); void (*fame_alchemist) (struct map_session_data *sd, int points); @@ -910,7 +926,7 @@ struct clif_interface { void (*friendslist_toggle) (struct map_session_data *sd,int account_id, int char_id, int online); void (*friendlist_req) (struct map_session_data* sd, int account_id, int char_id, const char* name); /* gm-related */ - void (*GM_kickack) (struct map_session_data *sd, int id); + void (*GM_kickack) (struct map_session_data *sd, int result); void (*GM_kick) (struct map_session_data *sd,struct map_session_data *tsd); void (*manner_message) (struct map_session_data* sd, uint32 type); void (*GM_silence) (struct map_session_data* sd, struct map_session_data* tsd, uint8 type); @@ -1274,4 +1290,4 @@ struct clif_interface *clif; void clif_defaults(void); -#endif /* _MAP_CLIF_H_ */ +#endif /* MAP_CLIF_H */ diff --git a/src/map/date.c b/src/map/date.c index f38ead858..975a00c50 100644 --- a/src/map/date.c +++ b/src/map/date.c @@ -1,10 +1,14 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include "../common/cbasetypes.h" +#define HERCULES_CORE + #include "date.h" + #include <time.h> +#include "../common/cbasetypes.h" + int date_get_year(void) { time_t t; diff --git a/src/map/date.h b/src/map/date.h index 46f0d86c3..c3f353f64 100644 --- a/src/map/date.h +++ b/src/map/date.h @@ -1,8 +1,10 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _MAP_DATE_H_ -#define _MAP_DATE_H_ +#ifndef MAP_DATE_H +#define MAP_DATE_H + +#include "../common/cbasetypes.h" int date_get_year(void); int date_get_month(void); @@ -15,4 +17,4 @@ bool is_day_of_sun(void); bool is_day_of_moon(void); bool is_day_of_star(void); -#endif /* _MAP_DATE_H_ */ +#endif /* MAP_DATE_H */ diff --git a/src/map/duel.c b/src/map/duel.c index af2741f77..4e4eeef1f 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -2,18 +2,20 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" +#define HERCULES_CORE -#include "atcommand.h" // msg_txt -#include "clif.h" #include "duel.h" -#include "pc.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" + /*========================================== * Duel organizing functions [LuzZza] *------------------------------------------*/ @@ -126,7 +128,7 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) { duel->list[did].members_count--; if(duel->list[did].members_count == 0) { - map->foreachpc(duel_leave_sub, did); + map->foreachpc(duel_leave_sub, did); duel->count--; } @@ -174,7 +176,7 @@ void do_init_duel(bool minimal) { } /*===================================== -* Default Functions : duel.h +* Default Functions : duel.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/duel.h b/src/map/duel.h index 5405d2eee..de2bd1bf6 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -2,8 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_DUEL_H_ -#define _MAP_DUEL_H_ +#ifndef MAP_DUEL_H +#define MAP_DUEL_H + +#include "../common/cbasetypes.h" + +struct map_session_data; struct duel { int members_count; @@ -14,7 +18,7 @@ struct duel { #define MAX_DUEL 1024 /*===================================== -* Interface : duel.h +* Interface : duel.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -42,4 +46,4 @@ struct duel_interface *duel; void duel_defaults(void); -#endif /* _MAP_DUEL_H_ */ +#endif /* MAP_DUEL_H */ diff --git a/src/map/elemental.c b/src/map/elemental.c index f335600d6..7ffeea410 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -2,42 +2,44 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/utils.h" -#include "../common/random.h" -#include "../common/strlib.h" +#define HERCULES_CORE -#include "log.h" -#include "clif.h" +#include "elemental.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 "pc.h" -#include "status.h" -#include "skill.h" #include "mob.h" -#include "pet.h" -#include "battle.h" +#include "npc.h" #include "party.h" -#include "guild.h" -#include "atcommand.h" +#include "pc.h" +#include "pet.h" #include "script.h" -#include "npc.h" +#include "skill.h" +#include "status.h" #include "trade.h" #include "unit.h" -#include "elemental.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.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; @@ -503,7 +505,7 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) { else unit->skilluse_id(&ed->bl,bl->id,skill_id,skill_lv); - ed->target_id = 0; // Reset target after casting the skill to avoid continious attack. + ed->target_id = 0; // Reset target after casting the skill to avoid continuous attack. return 1; } @@ -527,7 +529,7 @@ int elemental_change_mode(struct elemental_data *ed, int mode) { else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. - // Use a skill inmediately after every change mode. + // Use a skill immediately after every change mode. if( mode != EL_SKILLMODE_AGGRESSIVE ) elemental->change_mode_ack(ed,mode); return 1; @@ -949,7 +951,7 @@ void do_final_elemental(void) { } /*===================================== -* Default Functions : elemental.h +* Default Functions : elemental.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/elemental.h b/src/map/elemental.h index 6d04a41a5..0c8fff8b3 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -2,11 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_ELEMENTAL_H_ -#define _MAP_ELEMENTAL_H_ +#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 /** * Defines @@ -63,7 +64,7 @@ struct elemental_data { }; /*===================================== -* Interface : elemental.h +* Interface : elemental.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -120,4 +121,4 @@ struct elemental_interface *elemental; void elemental_defaults(void); -#endif /* _MAP_ELEMENTAL_H_ */ +#endif /* MAP_ELEMENTAL_H */ diff --git a/src/map/guild.c b/src/map/guild.c index 99c74c217..af29dc64e 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -2,35 +2,38 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/mapindex.h" -#include "../common/showmsg.h" -#include "../common/ers.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/HPM.h" +#define HERCULES_CORE -#include "map.h" +#include "../config/core.h" // GP_BOUND_ITEMS #include "guild.h" -#include "storage.h" -#include "battle.h" -#include "npc.h" -#include "pc.h" -#include "status.h" -#include "mob.h" -#include "intif.h" -#include "clif.h" -#include "skill.h" -#include "log.h" -#include "instance.h" #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "battle.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; /*========================================== @@ -58,7 +61,7 @@ int guild_skill_get_max (int id) { return guild->skill_tree[id-GD_SKILLBASE].max; } -// Retrive skill_lv learned by guild +// Retrieve skill_lv learned by guild int guild_checkskill(struct guild *g, int id) { int idx = id - GD_SKILLBASE; if (idx < 0 || idx >= MAX_GUILDSKILL) @@ -484,21 +487,27 @@ int guild_recv_info(struct guild *sg) { } for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { - if( sd->status.guild_id ) { - if( sd->status.guild_id == sg->guild_id ) { - clif->chsys_join(channel,sd); - sd->guild = g; - } - + if (!sd->status.guild_id) + continue; // Not interested in guildless users + + if (sd->status.guild_id == sg->guild_id) { + // Guild member + clif->chsys_join(channel,sd); + sd->guild = g; + for (i = 0; i < MAX_GUILDALLIANCE; i++) { - if( sg->alliance[i].opposition == 0 && sg->alliance[i].guild_id ) { - if( sg->alliance[i].guild_id == sd->status.guild_id ) { - clif->chsys_join(channel,sd); - } else if( tg[i] != NULL ) { - if( !(tg[i]->channel->banned && idb_exists(tg[i]->channel->banned, sd->status.account_id))) - clif->chsys_join(tg[i]->channel,sd); - } - } + // Join channels from allied guilds + if (tg[i] && !(tg[i]->channel->banned && idb_exists(tg[i]->channel->banned, sd->status.account_id))) + clif->chsys_join(tg[i]->channel, sd); + } + continue; + } + + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again + // Alliance member + if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id))) + clif->chsys_join(channel, sd); } } } @@ -568,9 +577,9 @@ int guild_recv_info(struct guild *sg) { if (before.skill_point != g->skill_point) clif->guild_skillinfo(sd); //Submit information skills - if (guild_new) { // Send information and affiliation if unsent + if (guild_new) { // Send information and affiliation if unsent clif->guild_belonginfo(sd, g); - clif->guild_notice(sd, g); + //clif->guild_notice(sd, g); Is already sent in clif_parse_LoadEndAck sd->guild_emblem_id = g->emblem_id; } } @@ -618,9 +627,12 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { return 0; } - if( tsd->status.guild_id > 0 - || tsd->guild_invite > 0 - || ((map->agit_flag || map->agit2_flag) && map->list[tsd->bl.m].flag.gvg_castle) + if( tsd->status.guild_id > 0 + || tsd->guild_invite > 0 + || ( (map->agit_flag || map->agit2_flag) + && map->list[tsd->bl.m].flag.gvg_castle + && !battle_config.guild_castle_invite + ) ) { //Can't invite people inside castles. [Skotlex] clif->guild_inviteack(sd,0); @@ -752,7 +764,7 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) { return 0; if(sd==NULL || sd->guild_invite==0){ - // cancel if player not present or invalide guild_id invitation + // cancel if player not present or invalid guild_id invitation if (flag == 0) { ShowError("guild: member added error %d is not online\n",account_id); intif->guild_leave(guild_id,account_id,char_id,0,"** Data Error **"); @@ -803,10 +815,13 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c return 0; if( sd->status.account_id != account_id - || sd->status.char_id != char_id - || sd->status.guild_id != guild_id - || ((map->agit_flag || map->agit2_flag) && map->list[sd->bl.m].flag.gvg_castle) - ) + || sd->status.char_id != char_id + || sd->status.guild_id != guild_id + // Can't leave inside castles + || ((map->agit_flag || map->agit2_flag) + && map->list[sd->bl.m].flag.gvg_castle + && !battle_config.guild_castle_expulsion) + ) return 0; intif->guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); @@ -835,10 +850,12 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i return 0; //Expulsion permission //Can't leave inside guild castles. - if ((tsd = map->id2sd(account_id)) - && tsd->status.char_id == char_id - && ((map->agit_flag || map->agit2_flag) && map->list[tsd->bl.m].flag.gvg_castle) - ) + if ((tsd = map->id2sd(account_id)) + && tsd->status.char_id == char_id + && ((map->agit_flag || map->agit2_flag) + && map->list[sd->bl.m].flag.gvg_castle + && !battle_config.guild_castle_expulsion) + ) return 0; // find the member and perform expulsion @@ -865,7 +882,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; // noone online to inform + return 0; // no one online to inform #ifdef GP_BOUND_ITEMS //Guild bound item check @@ -1001,7 +1018,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin //Ensure validity of pointer (ie: player logs in/out, changes map-server) g->member[idx].sd = guild->sd_check(guild_id, account_id, char_id); - if(oldonline!=online) + if(oldonline!=online) clif->guild_memberlogin_notice(g, idx, online); if(!g->member[idx].sd) @@ -1196,7 +1213,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) TBL_MOB* md = (gc->guardian[i].id ? map->id2md(gc->guardian[i].id) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; - md->guardian_data->emblem_id = emblem_id; + clif->guild_emblem_area(&md->bl); } // update temporary guardians @@ -1204,7 +1221,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) TBL_MOB* md = (gc->temp_guardians[i] ? map->id2md(gc->temp_guardians[i]) : NULL); if( md == NULL || md->guardian_data == NULL ) continue; - md->guardian_data->emblem_id = emblem_id; + clif->guild_emblem_area(&md->bl); } } @@ -1998,14 +2015,14 @@ int guild_castledatasave(int castle_id, int index, int value) void guild_castle_reconnect_sub(void *key, void *data, va_list ap) { - int castle_id = GetWord((int)__64BPTRSIZE(key), 0); - int index = GetWord((int)__64BPTRSIZE(key), 1); + int castle_id = GetWord((int)h64BPTRSIZE(key), 0); + int index = GetWord((int)h64BPTRSIZE(key), 1); intif->guild_castle_datasave(castle_id, index, *(int *)data); aFree(data); } /** - * Saves pending guild castle data changes when char-server is + * Saves pending guild castle data changes when char-server is * disconnected. * On reconnect pushes all changes to char-server for saving. */ @@ -2020,7 +2037,7 @@ void guild_castle_reconnect(int castle_id, int index, int value) int *data; CREATE(data, int, 1); *data = value; - linkdb_replace(&gc_save_pending, (void*)__64BPTRSIZE((MakeDWord(castle_id, index))), data); + linkdb_replace(&gc_save_pending, (void*)h64BPTRSIZE((MakeDWord(castle_id, index))), data); } } @@ -2356,11 +2373,11 @@ void guild_defaults(void) { guild->agit_end = guild_agit_end; guild->agit2_start = guild_agit2_start; guild->agit2_end = guild_agit2_end; - /* guild flag cachin */ + /* guild flag caching */ guild->flag_add = guild_flag_add; guild->flag_remove = guild_flag_remove; guild->flags_clear = guild_flags_clear; - /* guild aura */ + /* guild aura */ guild->aura_refresh = guild_guildaura_refresh; /* */ guild->payexp_timer = guild_payexp_timer; diff --git a/src/map/guild.h b/src/map/guild.h index b03bd664d..126325eef 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -2,21 +2,13 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_GUILD_H_ -#define _MAP_GUILD_H_ +#ifndef MAP_GUILD_H +#define MAP_GUILD_H -//#include "../common/mmo.h" -#include "map.h" // NAME_LENGTH - -/** - * Declarations - **/ -struct guild; -struct guild_member; -struct guild_position; -struct guild_castle; -struct map_session_data; -struct mob_data; +#include "map.h" // EVENT_NAME_LENGTH, TBL_PC +#include "../common/cbasetypes.h" +#include "../common/db.h" +#include "../common/mmo.h" /** * Defines @@ -32,13 +24,15 @@ struct eventlist { char name[EVENT_NAME_LENGTH]; struct eventlist *next; }; -//For quick linking to a guardian's info. [Skotlex] + +/** + * Guardian data + * For quick linking to a guardian's info. [Skotlex] + **/ struct guardian_data { int number; //0-MAX_GUARDIANS-1 = Guardians. MAX_GUARDIANS = Emperium. - int guild_id; - int emblem_id; - int guardup_lv; //Level of GD_GUARDUP skill. - char guild_name[NAME_LENGTH]; + + struct guild *g; struct guild_castle* castle; }; struct guild_expcache { @@ -173,4 +167,4 @@ struct guild_interface *guild; void guild_defaults(void); -#endif /* _MAP_GUILD_H_ */ +#endif /* MAP_GUILD_H */ diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 94c2ae5b1..8c47226db 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -2,43 +2,45 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/mmo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" +#define HERCULES_CORE -#include "log.h" -#include "clif.h" +#include "../config/core.h" // DBPATH +#include "homunculus.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 "pc.h" -#include "status.h" -#include "skill.h" #include "mob.h" -#include "pet.h" -#include "battle.h" +#include "npc.h" #include "party.h" -#include "guild.h" -#include "atcommand.h" +#include "pc.h" +#include "pet.h" #include "script.h" -#include "npc.h" +#include "skill.h" +#include "status.h" #include "trade.h" #include "unit.h" - -#include "homunculus.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.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; @@ -807,7 +809,7 @@ bool homunculus_call(struct map_session_data *sd) { return true; } -// Recv homunculus data from char server +// Receive homunculus data from char server bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) { struct map_session_data *sd; struct homun_data *hd; @@ -1155,7 +1157,7 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { classid = atoi(split[0]) - HM_CLASS_BASE; if ( classid >= MAX_HOMUNCULUS_CLASS ) { - ShowWarning("homunculus_read_skill_db_sub: Invalud homunculus class %d.\n", atoi(split[0])); + ShowWarning("homunculus_read_skill_db_sub: Invalid homunculus class %d.\n", atoi(split[0])); return false; } @@ -1182,6 +1184,24 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { return true; } +int8 homunculus_get_intimacy_grade(struct homun_data *hd) { + unsigned int val = hd->homunculus.intimacy / 100; + if( val > 100 ) { + if( val > 250 ) { + if( val > 750 ) { + if ( val > 900 ) + return 4; + else + return 3; + } else + return 2; + } else + return 1; + } + + return 0; +} + void homunculus_skill_db_read(void) { memset(homun->skill_tree,0,sizeof(homun->skill_tree)); sv->readdb(map->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub); @@ -1303,4 +1323,5 @@ void homunculus_defaults(void) { homun->exp_db_read = homunculus_exp_db_read; homun->addspiritball = homunculus_addspiritball; homun->delspiritball = homunculus_delspiritball; + homun->get_intimacy_grade = homunculus_get_intimacy_grade; } diff --git a/src/map/homunculus.h b/src/map/homunculus.h index db250f511..25ccabf48 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -2,12 +2,13 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_HOMUNCULUS_H_ -#define _MAP_HOMUNCULUS_H_ +#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 "pc.h" +#include "../common/mmo.h" #define MAX_HOM_SKILL_REQUIRE 5 #define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX) @@ -140,10 +141,11 @@ struct homunculus_interface { void (*exp_db_read) (void); void (*addspiritball) (struct homun_data *hd, int max); void (*delspiritball) (struct homun_data *hd, int count, int type); + int8 (*get_intimacy_grade) (struct homun_data *hd); }; struct homunculus_interface *homun; void homunculus_defaults(void); -#endif /* _MAP_HOMUNCULUS_H_ */ +#endif /* MAP_HOMUNCULUS_H */ diff --git a/src/map/instance.c b/src/map/instance.c index caf622b3d..5789d7dd6 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -2,30 +2,32 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/db.h" -#include "../common/HPM.h" +#define HERCULES_CORE -#include "clif.h" #include "instance.h" -#include "map.h" -#include "npc.h" -#include "party.h" -#include "pc.h" +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdarg.h> #include <time.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; /// Checks whether given instance id is valid or not. diff --git a/src/map/instance.h b/src/map/instance.h index 712a0f141..2ee77d3e3 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -2,12 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_INSTANCE_H_ -#define _MAP_INSTANCE_H_ +#ifndef MAP_INSTANCE_H +#define MAP_INSTANCE_H #include "script.h" // struct reg_db +#include "../common/cbasetypes.h" #include "../common/mmo.h" // struct point + struct block_list; +struct map_session_data; #define INSTANCE_NAME_LENGTH (60+1) @@ -85,4 +88,4 @@ struct instance_interface *instance; void instance_defaults(void); -#endif /* _MAP_INSTANCE_H_ */ +#endif /* MAP_INSTANCE_H */ diff --git a/src/map/intif.c b/src/map/intif.c index 40ceda917..432154f04 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -1,37 +1,40 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/strlib.h" -#include "map.h" +#define HERCULES_CORE + +#include "../config/core.h" // GP_BOUND_ITEMS +#include "intif.h" + +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "atcommand.h" #include "battle.h" #include "chrif.h" #include "clif.h" -#include "pc.h" -#include "intif.h" -#include "log.h" -#include "storage.h" -#include "party.h" +#include "elemental.h" #include "guild.h" -#include "pet.h" -#include "atcommand.h" -#include "mercenary.h" #include "homunculus.h" -#include "elemental.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 <sys/types.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <fcntl.h> -#include <string.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; @@ -47,7 +50,7 @@ int CheckForCharServer(void) // pet int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, - short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) + short pet_equip,short intimate,short hungry,char rename_flag,char incubate,char *pet_name) { if (intif->CheckForCharServer()) return 0; @@ -62,7 +65,7 @@ int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,sho WFIFOW(inter_fd,18) = intimate; WFIFOW(inter_fd,20) = hungry; WFIFOB(inter_fd,22) = rename_flag; - WFIFOB(inter_fd,23) = incuvate; + WFIFOB(inter_fd,23) = incubate; memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); WFIFOSET(inter_fd,24+NAME_LENGTH); @@ -235,7 +238,7 @@ int intif_wis_replay(int id, int flag) WFIFOHEAD(inter_fd,7); WFIFOW(inter_fd,0) = 0x3002; WFIFOL(inter_fd,2) = id; - WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + WFIFOB(inter_fd,6) = flag; // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target WFIFOSET(inter_fd,7); if (battle_config.etc_log) @@ -384,7 +387,7 @@ int intif_request_registry(struct map_session_data *sd, int flag) { nullpo_ret(sd); - /* if char server aint online it doesn't load, shouldn't we kill the session then? */ + /* if char server ain't online it doesn't load, shouldn't we kill the session then? */ if (intif->CheckForCharServer()) return 0; @@ -692,7 +695,10 @@ int intif_guild_message(int guild_id,int account_id,const char *mes,int len) return 0; } -// Request a change of Guild basic information +/** + * Requests to change a basic guild information, it is parsed via mapif_parse_GuildBasicInfoChange + * To see the information types that can be changed see mmo.h::guild_basic_info + **/ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) { if (intif->CheckForCharServer()) @@ -925,7 +931,7 @@ void intif_parse_WisMessage(int fd) { } //Success to send whisper. clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); - intif_wis_replay(id,0); // succes + intif_wis_replay(id,0); // success } // Wisp/page transmission result reception @@ -933,7 +939,7 @@ void intif_parse_WisEnd(int fd) { struct map_session_data* sd; if (battle_config.etc_log) - ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target sd = (struct map_session_data *)map->nick2sd((char *) RFIFOP(fd,2)); if (sd != NULL) clif->wis_end(sd->fd, RFIFOB(fd,26)); @@ -1061,7 +1067,7 @@ void intif_parse_Registers(int fd) ival = RFIFOL(fd, cursor); cursor += 4; - script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)__64BPTRSIZE(ival), NULL); + script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)h64BPTRSIZE(ival), NULL); } } @@ -1237,6 +1243,21 @@ void intif_parse_GuildBasicInfoChanged(int fd) { case GBI_EXP: g->exp = RFIFOQ(fd,10); break; case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; + case GBI_SKILLLV: { + int idx, max; + struct guild_skill *gs = (struct guild_skill *)RFIFOP(fd,10); + + if( gs == NULL ) + return; + + idx = gs->id - GD_SKILLBASE; + max = guild->skill_get_max(gs->id); + if( gs->lv > max ) + gs->lv = max; + + memcpy(&(g->skill[idx]), gs, sizeof(g->skill[idx])); + break; + } } } @@ -1316,7 +1337,7 @@ void intif_parse_GuildMasterChanged(int fd) { // Request pet creation void intif_parse_CreatePet(int fd) { - pet->get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); + pet->get_egg(RFIFOL(fd,2), RFIFOW(fd,6), RFIFOL(fd,8)); } // ACK pet data @@ -1345,7 +1366,7 @@ void intif_parse_DeletePetOk(int fd) { ShowError("pet data delete failure\n"); } -// ACK changing name resquest, players,pets,hommon +// ACK changing name request, players,pets,homun void intif_parse_ChangeNameOk(int fd) { struct map_session_data *sd = NULL; @@ -2284,7 +2305,7 @@ int intif_parse(int fd) } /*===================================== -* Default Functions : intif.h +* Default Functions : intif.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -2298,7 +2319,7 @@ void intif_defaults(void) { -1,-1, 7, 7, 7,11, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] - 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 + 12,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] }; diff --git a/src/map/intif.h b/src/map/intif.h index 290dcfcdc..fe47d6537 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -2,22 +2,25 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_INTIF_H_ -#define _MAP_INTIF_H_ +#ifndef MAP_INTIF_H +#define MAP_INTIF_H +#include "../common/cbasetypes.h" /** * Declarations **/ -struct party_member; +struct auction_data; struct guild_member; struct guild_position; -struct s_pet; +struct guild_storage; +struct mail_message; +struct map_session_data; +struct party_member; +struct s_elemental; struct s_homunculus; struct s_mercenary; -struct s_elemental; -struct mail_message; -struct auction_data; +struct s_pet; /** * Defines @@ -29,7 +32,7 @@ struct auction_data; /*===================================== -* Interface : intif.h +* Interface : intif.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -39,7 +42,7 @@ struct intif_interface { /* funcs */ int (*parse) (int fd); int (*create_pet)(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id, - short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name); + short pet_equip, short intimate, short hungry, char rename_flag, char incubate, char *pet_name); int (*broadcast) (const char* mes, size_t len, int type); int (*broadcast2) (const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY); int (*main_message) (struct map_session_data* sd, const char* message); @@ -183,4 +186,4 @@ struct intif_interface *intif; void intif_defaults(void); -#endif /* _MAP_INTIF_H_ */ +#endif /* MAP_INTIF_H */ diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index ff28082e7..6f016697f 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -2,23 +2,25 @@ // See the LICENSE file // Base Author: shennetsind @ http://hercules.ws -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/strlib.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/random.h" +#define HERCULES_CORE -#include "map.h" -#include "pc.h" -#include "clif.h" #include "irc-bot.h" #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "clif.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; diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index c15a5d46a..0c26c3cd8 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -3,8 +3,10 @@ // Base Author: shennetsind @ http://hercules.ws -#ifndef _MAP_IRC_BOT_H_ -#define _MAP_IRC_BOT_H_ +#ifndef MAP_IRC_BOT_H +#define MAP_IRC_BOT_H + +#include "../common/cbasetypes.h" #define IRC_NICK_LENGTH 40 #define IRC_IDENT_LENGTH 40 @@ -61,4 +63,4 @@ struct irc_bot_interface *ircbot; void ircbot_defaults(void); -#endif /* _MAP_IRC_BOT_H_ */ +#endif /* MAP_IRC_BOT_H */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index bfcc6f795..61b77748a 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -2,27 +2,32 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/conf.h" +#define HERCULES_CORE + +#include "../config/core.h" // DBPATH, RENEWAL #include "itemdb.h" -#include "map.h" -#include "battle.h" // struct battle_config -#include "script.h" // item script processing -#include "pc.h" // W_MUSICAL, W_WHIP #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/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; /** - * Search for item name + * Search for item name * name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) * @see DBApply */ @@ -50,7 +55,7 @@ int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap) } /*========================================== - * Return item data from item name. (lookup) + * Return item data from item name. (lookup) *------------------------------------------*/ struct item_data* itemdb_searchname(const char *str) { struct item_data* item; @@ -251,7 +256,7 @@ 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) + * Return a random item id from group. (takes into account % chance giving/tot group) *------------------------------------------*/ int itemdb_searchrandomid(struct item_group *group) { @@ -307,7 +312,7 @@ const char* itemdb_typename(int type) } /*========================================== - * Converts the jobid from the format in itemdb + * Converts the jobid from the format in itemdb * to the format used by the map server. [Skotlex] *------------------------------------------*/ void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask) @@ -465,8 +470,7 @@ int itemdb_isequip(int nameid) /*========================================== * Alternate version of itemdb_isequip *------------------------------------------*/ -int itemdb_isequip2(struct item_data *data) -{ +int itemdb_isequip2(struct item_data *data) { nullpo_ret(data); switch(data->type) { case IT_WEAPON: @@ -517,39 +521,39 @@ int itemdb_isstackable2(struct item_data *data) * Trade Restriction functions [Skotlex] *------------------------------------------*/ int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NODROP) || gmlv >= item->gm_lv_trade_override)); } int itemdb_cantrade_sub(struct item_data* item, int gmlv, int gmlv2) { - return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOTRADE) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); } int itemdb_canpartnertrade_sub(struct item_data* item, int gmlv, int gmlv2) { - return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); + return (item && (item->flag.trade_restriction&ITR_PARTNEROVERRIDE || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); } int itemdb_cansell_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOSELLTONPC) || gmlv >= item->gm_lv_trade_override)); } int itemdb_cancartstore_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOCART) || gmlv >= item->gm_lv_trade_override)); } int itemdb_canstore_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOSTORAGE) || gmlv >= item->gm_lv_trade_override)); } int itemdb_canguildstore_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOGSTORAGE) || gmlv >= item->gm_lv_trade_override)); } int itemdb_canmail_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&128) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOMAIL) || gmlv >= item->gm_lv_trade_override)); } int itemdb_canauction_sub(struct item_data* item, int gmlv, int unused) { - return (item && (!(item->flag.trade_restriction&256) || gmlv >= item->gm_lv_trade_override)); + return (item && (!(item->flag.trade_restriction&ITR_NOAUCTION) || gmlv >= item->gm_lv_trade_override)); } int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int)) @@ -597,39 +601,6 @@ int itemdb_isidentified2(struct item_data *data) { } } - -/*========================================== - * Search by name for the override flags available items - * (Give item another sprite) - *------------------------------------------*/ -bool itemdb_read_itemavail(char* str[], int columns, int current) -{// <nameid>,<sprite> - int nameid, sprite; - struct item_data *id; - - nameid = atoi(str[0]); - - if( ( id = itemdb->exists(nameid) ) == NULL ) - { - ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid); - return false; - } - - sprite = atoi(str[1]); - - if( sprite > 0 ) - { - id->flag.available = 1; - id->view_id = sprite; - } - else - { - id->flag.available = 0; - } - - return true; -} - void itemdb_read_groups(void) { config_t item_group_conf; config_setting_t *itg = NULL, *it = NULL; @@ -818,7 +789,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { hread(&random_qty,sizeof(random_qty),1,file); if( !(pdata = itemdb->exists(id)) ) - ShowWarning("itemdb_read_packages: unknown package item '%d', skipping..\n",id); + ShowWarning("itemdb_read_cached_packages: unknown package item '%d', skipping..\n",id); else pdata->package = &itemdb->packages[i]; @@ -848,7 +819,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { hread(&named,sizeof(announce),1,file); if( !(data = itemdb->exists(mid)) ) - ShowWarning("itemdb_read_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); + ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); entry->id = data ? data->nameid : 0; entry->hours = hours; @@ -893,7 +864,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { hread(&named,sizeof(announce),1,file); if( !(data = itemdb->exists(mid)) ) - ShowWarning("itemdb_read_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); + 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; @@ -932,7 +903,7 @@ void itemdb_read_packages(void) { 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); @@ -1119,7 +1090,7 @@ void itemdb_read_packages(void) { for( r = 0; r < itemdb->packages[count].random_qty; r++ ) { if( itemdb->packages[count].random_groups[r].random_qty == 1 ) { - //item packages dont stop looping until something comes out of them, so if you have only one item in it the drop is guaranteed. + //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. ShowWarning("itemdb_read_packages: in '%s' 'Random: %d' group has only 1 random option, drop rate will be 100%!\n",itemdb_name(itemdb->packages[count].id),r+1); itemdb->packages[count].random_groups[r].random_list[0].rate = 10000; } @@ -1214,163 +1185,6 @@ void itemdb_read_chains(void) { ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename); } - -/*========================================== - * Reads item trade restrictions [Skotlex] - *------------------------------------------*/ -bool itemdb_read_itemtrade(char* str[], int columns, int current) -{// <nameid>,<mask>,<gm level> - int nameid, flag, gmlv; - struct item_data *id; - - nameid = atoi(str[0]); - - if( ( id = itemdb->exists(nameid) ) == NULL ) - { - //ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid); - //return false; - // FIXME: item_trade.txt contains items, which are commented in item database. - return true; - } - - flag = atoi(str[1]); - gmlv = atoi(str[2]); - - if( flag < 0 || flag > 511 ) {//Check range - ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid); - return false; - } - if( gmlv < 1 ) - { - ShowWarning("itemdb_read_itemtrade: Invalid override GM level %d for item id %d.\n", gmlv, nameid); - return false; - } - - id->flag.trade_restriction = flag; - id->gm_lv_trade_override = gmlv; - - return true; -} - -/*========================================== - * Reads item delay amounts [Paradox924X] - *------------------------------------------*/ -bool itemdb_read_itemdelay(char* str[], int columns, int current) -{// <nameid>,<delay> - int nameid, delay; - struct item_data *id; - - nameid = atoi(str[0]); - - if( ( id = itemdb->exists(nameid) ) == NULL ) - { - ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", nameid); - return false; - } - - delay = atoi(str[1]); - - if( delay < 0 ) - { - ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid); - return false; - } - - id->delay = delay; - - return true; -} - -/*================================================================== - * Reads item stacking restrictions - *----------------------------------------------------------------*/ -bool itemdb_read_stack(char* fields[], int columns, int current) -{// <item id>,<stack limit amount>,<type> - unsigned short nameid, amount; - unsigned int type; - struct item_data* id; - - nameid = (unsigned short)strtoul(fields[0], NULL, 10); - - if( ( id = itemdb->exists(nameid) ) == NULL ) - { - ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid); - return false; - } - - if( !itemdb->isstackable2(id) ) - { - ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid); - return false; - } - - amount = (unsigned short)strtoul(fields[1], NULL, 10); - type = (unsigned int)strtoul(fields[2], NULL, 10); - - if( !amount ) - {// ignore - return true; - } - - id->stack.amount = amount; - id->stack.inventory = (type&1)!=0; - id->stack.cart = (type&2)!=0; - id->stack.storage = (type&4)!=0; - id->stack.guildstorage = (type&8)!=0; - - return true; -} - - -/// Reads items allowed to be sold in buying stores -bool itemdb_read_buyingstore(char* fields[], int columns, int current) -{// <nameid> - int nameid; - struct item_data* id; - - nameid = atoi(fields[0]); - - if( ( id = itemdb->exists(nameid) ) == NULL ) - { - ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid); - return false; - } - - if( !itemdb->isstackable2(id) ) - { - ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid); - return false; - } - - id->flag.buyingstore = true; - - return true; -} - -/******************************************* -** Item usage restriction (item_nouse.txt) -********************************************/ -bool itemdb_read_nouse(char* fields[], int columns, int current) -{// <nameid>,<flag>,<override> - int nameid, flag, override; - struct item_data* id; - - nameid = atoi(fields[0]); - - if( ( id = itemdb->exists(nameid) ) == NULL ) { - ShowWarning("itemdb_read_nouse: Invalid item id %d.\n", nameid); - return false; - } - - flag = atoi(fields[1]); - override = atoi(fields[2]); - - id->item_usage.flag = flag; - id->item_usage.override = override; - - return true; -} - /** * @return: amount of retrieved entries. **/ @@ -1440,7 +1254,7 @@ void itemdb_read_combos() { p++; str[1] = p; - p = strchr(p,','); + p = strchr(p,','); p++; if (str[1][0] != '{') { @@ -1478,7 +1292,7 @@ void itemdb_read_combos() { CREATE(combo, struct item_combo, 1); combo->count = retcount; - combo->script = script->parse(str[1], filepath, lines, 0); + combo->script = script->parse(str[1], filepath, lines, 0, NULL); combo->id = itemdb->combo_count - 1; /* populate ->nameid field */ for( v = 0; v < retcount; v++ ) { @@ -1574,7 +1388,8 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { || (entry->type > IT_DELAYCONSUME && entry->type < IT_CASH ) || entry->type >= IT_MAX ) { // catch invalid item types - ShowWarning("itemdb_validate_entry: Invalid item type %d for item %d. IT_ETC will be used.\n", entry->type, entry->nameid); + ShowWarning("itemdb_validate_entry: Invalid item type %d for item %d in '%s'. IT_ETC will be used.\n", + entry->type, entry->nameid, source); entry->type = IT_ETC; } else if( entry->type == IT_DELAYCONSUME ) { //Items that are consumed only after target confirmation @@ -1592,21 +1407,61 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { entry->value_sell = entry->value_buy / 2; } if( entry->value_buy/124. < entry->value_sell/75. ) { - ShowWarning("itemdb_validate_entry: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", - entry->value_buy, entry->value_sell, entry->nameid, entry->jname); + ShowWarning("itemdb_validate_entry: Buying/Selling [%d/%d] price of item %d (%s) in '%s' " + "allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", + entry->value_buy, entry->value_sell, entry->nameid, entry->jname, source); } if( entry->slot > MAX_SLOTS ) { - ShowWarning("itemdb_validate_entry: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", - entry->nameid, entry->jname, entry->slot, MAX_SLOTS, MAX_SLOTS); + ShowWarning("itemdb_validate_entry: Item %d (%s) in '%s' specifies %d slots, but the server only supports up to %d. Using %d slots.\n", + entry->nameid, entry->jname, source, entry->slot, MAX_SLOTS, MAX_SLOTS); entry->slot = MAX_SLOTS; } if (!entry->equip && itemdb->isequip2(entry)) { - ShowWarning("itemdb_validate_entry: Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", entry->nameid, entry->jname); + ShowWarning("itemdb_validate_entry: Item %d (%s) in '%s' is an equipment with no equip-field! Making it an etc item.\n", + entry->nameid, entry->jname, source); entry->type = IT_ETC; } + if (entry->flag.trade_restriction < 0 || entry->flag.trade_restriction > ITR_ALL) { + ShowWarning("itemdb_validate_entry: Invalid trade restriction flag 0x%x for item %d (%s) in '%s', defaulting to none.\n", + entry->flag.trade_restriction, entry->nameid, entry->jname, source); + entry->flag.trade_restriction = ITR_NONE; + } + + if (entry->gm_lv_trade_override < 0 || entry->gm_lv_trade_override > 100) { + ShowWarning("itemdb_validate_entry: Invalid trade-override GM level %d for item %d (%s) in '%s', defaulting to none.\n", + entry->gm_lv_trade_override, entry->nameid, entry->jname, source); + entry->gm_lv_trade_override = 0; + } + if (entry->gm_lv_trade_override == 0) { + // Default value if none or an ivalid one was specified + entry->gm_lv_trade_override = 100; + } + + if (entry->item_usage.flag > INR_ALL) { + ShowWarning("itemdb_validate_entry: Invalid nouse flag 0x%x for item %d (%s) in '%s', defaulting to none.\n", + entry->item_usage.flag, entry->nameid, entry->jname, source); + entry->item_usage.flag = INR_NONE; + } + + if (entry->item_usage.override > 100) { + ShowWarning("itemdb_validate_entry: Invalid nouse-override GM level %d for item %d (%s) in '%s', defaulting to none.\n", + entry->item_usage.override, entry->nameid, entry->jname, source); + entry->item_usage.override = 0; + } + if (entry->item_usage.override == 0) { + // Default value if none or an ivalid one was specified + entry->item_usage.override = 100; + } + + if (entry->stack.amount > 0 && !itemdb->isstackable2(entry)) { + ShowWarning("itemdb_validate_entry: Item %d (%s) of type %d is not stackable, ignoring stack settings in '%s'.\n", + entry->nameid, entry->jname, entry->type, source); + memset(&entry->stack, '\0', sizeof(entry->stack)); + } + entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX); if( !entry->elvmax ) @@ -1617,8 +1472,11 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { if( entry->type != IT_ARMOR && entry->type != IT_WEAPON && !entry->flag.no_refine ) entry->flag.no_refine = 1; - entry->flag.available = 1; - entry->view_id = 0; + if (entry->flag.available != 1) { + entry->flag.available = 1; + entry->view_id = 0; + } + entry->sex = itemdb->gendercheck(entry); //Apply gender filtering. // Validated. Finally insert it @@ -1681,6 +1539,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { * `refineable` tinyint(1) unsigned DEFAULT NULL * `view` smallint(3) unsigned DEFAULT NULL * `bindonequip` tinyint(1) unsigned DEFAULT NULL + * `buyingstore` tinyint(1) NOT NULL DEFAULT NULL + * `delay` mediumint(9) NOT NULL DEFAULT NULL + * `trade_flag` smallint(4) NOT NULL DEFAULT NULL + * `trade_group` smallint(4) NOT NULL DEFAULT NULL + * `nouse_flag` smallint(4) NOT NULL DEFAULT NULL + * `nouse_group` smallint(4) NOT NULL DEFAULT NULL + * `stack_amount` mediumint(6) NOT NULL DEFAULT NULL + * `stack_flag` smallint(2) NOT NULL DEFAULT NULL + * `sprite` mediumint(6) NOT NULL DEFAULT NULL * `script` text * `equip_script` text * `unequip_script` text @@ -1707,9 +1574,30 @@ 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.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL; - SQL->GetData(handle, 23, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL; - SQL->GetData(handle, 24, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL; + 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); + if (data) { + int stack_flag = atoi(data); + id.stack.inventory = (stack_flag&1)!=0; + id.stack.cart = (stack_flag&2)!=0; + id.stack.storage = (stack_flag&4)!=0; + id.stack.guildstorage = (stack_flag&8)!=0; + } + SQL->GetData(handle, 30, &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; return itemdb->validate_entry(&id, n, source); } @@ -1754,10 +1642,30 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) * Gender: Gender * Loc: Equip location * WeaponLv: Weapon Level - * EquipLv: Equip required level + * EquipLv: Equip required level or [min, max] * Refine: Refineable * View: View ID * BindOnEquip: (true or false) + * BuyingStore: (true or false) + * Delay: Delay to use item + * Trade: { + * override: Group to override + * nodrop: (true or false) + * notrade: (true or false) + * partneroverride: (true or false) + * noselltonpc: (true or false) + * nocart: (true or false) + * nostorage: (true or false) + * nogstorage: (true or false) + * nomail: (true or false) + * noauction: (true or false) + * } + * Nouse: { + * override: Group to override + * sitting: (true or false) + * } + * Stack: [Stackable Amount, Stack Type] + * Sprite: SpriteID * Script: <" * Script * (it can be multi-line) @@ -1874,14 +1782,124 @@ 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, "BuyingStore")) ) + id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0; + + if (libconfig->setting_lookup_int(it, "Delay", &i32) && i32 >= 0) + id.delay = i32; + + if ( (t = libconfig->setting_get_member(it, "Trade")) ) { + if (config_setting_is_group(t)) { + config_setting_t *tt = NULL; + + if ((tt = libconfig->setting_get_member(t, "override"))) { + id.gm_lv_trade_override = libconfig->setting_get_int(tt); + } + + if ((tt = libconfig->setting_get_member(t, "nodrop"))) { + id.flag.trade_restriction &= ~ITR_NODROP; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NODROP; + } + + if ((tt = libconfig->setting_get_member(t, "notrade"))) { + id.flag.trade_restriction &= ~ITR_NOTRADE; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOTRADE; + } + + if ((tt = libconfig->setting_get_member(t, "partneroverride"))) { + id.flag.trade_restriction &= ~ITR_PARTNEROVERRIDE; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_PARTNEROVERRIDE; + } + + if ((tt = libconfig->setting_get_member(t, "noselltonpc"))) { + id.flag.trade_restriction &= ~ITR_NOSELLTONPC; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOSELLTONPC; + } + + if ((tt = libconfig->setting_get_member(t, "nocart"))) { + id.flag.trade_restriction &= ~ITR_NOCART; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOCART; + } + + if ((tt = libconfig->setting_get_member(t, "nostorage"))) { + id.flag.trade_restriction &= ~ITR_NOSTORAGE; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOSTORAGE; + } + + if ((tt = libconfig->setting_get_member(t, "nogstorage"))) { + id.flag.trade_restriction &= ~ITR_NOGSTORAGE; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOGSTORAGE; + } + + if ((tt = libconfig->setting_get_member(t, "nomail"))) { + id.flag.trade_restriction &= ~ITR_NOMAIL; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOMAIL; + } + + if ((tt = libconfig->setting_get_member(t, "noauction"))) { + id.flag.trade_restriction &= ~ITR_NOAUCTION; + if (libconfig->setting_get_bool(tt)) + id.flag.trade_restriction |= ITR_NOAUCTION; + } + } else { // Fallback to int if it's not a group + id.flag.trade_restriction = libconfig->setting_get_int(t); + } + } + + if ((t = libconfig->setting_get_member(it, "Nouse"))) { + if (config_setting_is_group(t)) { + config_setting_t *nt = NULL; + + if ((nt = libconfig->setting_get_member(t, "override"))) { + id.item_usage.override = libconfig->setting_get_int(nt); + } + + if ((nt = libconfig->setting_get_member(t, "sitting"))) { + id.item_usage.flag &= ~INR_SITTING; + if (libconfig->setting_get_bool(nt)) + id.item_usage.flag |= INR_SITTING; + } + + } else { // Fallback to int if it's not a group + id.item_usage.flag = libconfig->setting_get_int(t); + } + } + + if ((t = libconfig->setting_get_member(it, "Stack"))) { + if (config_setting_is_aggregate(t) && libconfig->setting_length(t) >= 1) { + int stack_flag = libconfig->setting_get_int_elem(t, 1); + int stack_amount = libconfig->setting_get_int_elem(t, 0); + if (stack_amount >= 0) { + id.stack.amount = cap_value(stack_amount, 0, USHRT_MAX); + id.stack.inventory = (stack_flag&1)!=0; + id.stack.cart = (stack_flag&2)!=0; + id.stack.storage = (stack_flag&4)!=0; + id.stack.guildstorage = (stack_flag&8)!=0; + } + } + } + + if (libconfig->setting_lookup_int(it, "Sprite", &i32) && i32 >= 0) { + 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; + id.script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; if( libconfig->setting_lookup_string(it, "OnEquipScript", &str) ) - id.equip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL; + id.equip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; if( libconfig->setting_lookup_string(it, "OnUnequipScript", &str) ) - id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS) : NULL; + id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; return itemdb->validate_entry(&id, n, source); } @@ -1943,7 +1961,10 @@ int itemdb_readdb_sql(const char *tablename) { " `matk`, `defence`, `range`, `slots`," " `equip_jobs`, `equip_upper`, `equip_genders`, `equip_locations`," " `weapon_level`, `equip_level_min`, `equip_level_max`, `refineable`," - " `view`, `bindonequip`, `script`, `equip_script`, `unequip_script`" + " `view`, `bindonequip`, `buyingstore`, `delay`," + " `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`," + " `stack_amount`, `stack_flag`, `sprite`, `script`," + " `equip_script`, `unequip_script`" "FROM `%s`", tablename) ) { Sql_ShowDebug(map->mysql_handle); return 0; @@ -1966,44 +1987,10 @@ int itemdb_readdb_sql(const char *tablename) { /*========================================== * Unique item ID function * Only one operation by once -* Flag: -* 0 return new id -* 1 set new value, checked with current value -* 2 set new value bypassing anything -* 3/other return last value *------------------------------------------*/ -uint64 itemdb_unique_id(int8 flag, int64 value) { - static uint64 item_uid = 0; - - if(flag) - { - if(flag == 1) - { if(item_uid < value) - return (item_uid = value); - }else if(flag == 2) - return (item_uid = value); - - return item_uid; - } +uint64 itemdb_unique_id(struct map_session_data *sd) { - return ++item_uid; -} -int itemdb_uid_load() { - char * uid; - if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `value` FROM `%s` WHERE `varname`='unique_id'",map->interreg_db)) - Sql_ShowDebug(map->mysql_handle); - - if( SQL_SUCCESS != SQL->NextRow(map->mysql_handle) ) { - ShowError("itemdb_uid_load: Unable to fetch unique_id data\n"); - SQL->FreeResult(map->mysql_handle); - return -1; - } - - SQL->GetData(map->mysql_handle, 0, &uid, NULL); - itemdb->unique_id(1, (uint64)strtoull(uid, NULL, 10)); - SQL->FreeResult(map->mysql_handle); - - return 0; + return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++; } /** @@ -2050,15 +2037,7 @@ void itemdb_read(bool minimal) { itemdb->read_groups(); itemdb->read_chains(); itemdb->read_packages(); - - sv->readdb(map->db_path, "item_avail.txt", ',', 2, 2, -1, itemdb->read_itemavail); - sv->readdb(map->db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, itemdb->read_itemtrade); - sv->readdb(map->db_path, DBPATH"item_delay.txt", ',', 2, 2, -1, itemdb->read_itemdelay); - sv->readdb(map->db_path, "item_stack.txt", ',', 3, 3, -1, itemdb->read_stack); - sv->readdb(map->db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, itemdb->read_buyingstore); - sv->readdb(map->db_path, "item_nouse.txt", ',', 3, 3, -1, itemdb->read_nouse); - - itemdb->uid_load(); + } /** @@ -2112,9 +2091,10 @@ int itemdb_final_sub(DBKey key, DBData *data, va_list ap) void itemdb_clear(bool total) { int i; // clear the previous itemdb data - for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) + for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) { if( itemdb->array[i] ) itemdb->destroy_item_data(itemdb->array[i], 1); + } for( i = 0; i < itemdb->group_count; i++ ) { if( itemdb->groups[i].nameid ) @@ -2155,7 +2135,8 @@ void itemdb_clear(bool total) { itemdb->package_count = 0; for(i = 0; i < itemdb->combo_count; i++) { - script->free_code(itemdb->combos[i]->script); + if( itemdb->combos[i]->script ) // Check if script was loaded + script->free_code(itemdb->combos[i]->script); aFree(itemdb->combos[i]); } if( itemdb->combos ) @@ -2245,7 +2226,7 @@ void itemdb_name_constants(void) { script->parser_current_file = NULL; #endif // ENABLE_CASE_CHECK - dbi_destroy(iter); + dbi_destroy(iter); } void do_final_itemdb(void) { itemdb->clear(true); @@ -2333,12 +2314,6 @@ void itemdb_defaults(void) { itemdb->isrestricted = itemdb_isrestricted; itemdb->isidentified = itemdb_isidentified; itemdb->isidentified2 = itemdb_isidentified2; - itemdb->read_itemavail = itemdb_read_itemavail; - itemdb->read_itemtrade = itemdb_read_itemtrade; - itemdb->read_itemdelay = itemdb_read_itemdelay; - itemdb->read_stack = itemdb_read_stack; - itemdb->read_buyingstore = itemdb_read_buyingstore; - itemdb->read_nouse = itemdb_read_nouse; itemdb->combo_split_atoi = itemdb_combo_split_atoi; itemdb->read_combos = itemdb_read_combos; itemdb->gendercheck = itemdb_gendercheck; @@ -2348,7 +2323,6 @@ void itemdb_defaults(void) { itemdb->readdb_libconfig = itemdb_readdb_libconfig; itemdb->readdb_sql = itemdb_readdb_sql; itemdb->unique_id = itemdb_unique_id; - itemdb->uid_load = itemdb_uid_load; itemdb->read = itemdb_read; itemdb->destroy_item_data = destroy_item_data; itemdb->final_sub = itemdb_final_sub; diff --git a/src/map/itemdb.h b/src/map/itemdb.h index eebcd5d4d..2ad596ce1 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -2,12 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_ITEMDB_H_ -#define _MAP_ITEMDB_H_ +#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 "map.h" +#include "../common/sql.h" /** * Declarations @@ -316,10 +319,6 @@ enum geneticist_item_list { ITEMID_BLACK_THING_TO_THROW, // 13290 }; -enum item_nouse_list { - NOUSE_SITTING = 0x01, -}; - // enum e_chain_cache { ECC_ORE, @@ -338,6 +337,34 @@ enum item_class_upper { ITEMUPPER_ALL = 0x3f, // Sum of all the above }; +/** + * Item Trade restrictions + */ +enum ItemTradeRestrictions { + ITR_NONE = 0x000, ///< No restrictions + ITR_NODROP = 0x001, ///< Item can't be dropped + ITR_NOTRADE = 0x002, ///< Item can't be traded (nor vended) + ITR_PARTNEROVERRIDE = 0x004, ///< Wedded partner can override ITR_NOTRADE restriction + ITR_NOSELLTONPC = 0x008, ///< Item can't be sold to NPCs + ITR_NOCART = 0x010, ///< Item can't be placed in the cart + ITR_NOSTORAGE = 0x020, ///< Item can't be placed in the storage + ITR_NOGSTORAGE = 0x040, ///< Item can't be placed in the guild storage + ITR_NOMAIL = 0x080, ///< Item can't be attached to mail messages + ITR_NOAUCTION = 0x100, ///< Item can't be auctioned + + ITR_ALL = 0x1ff ///< Sum of all the above values +}; + +/** + * Iten No-use restrictions + */ +enum ItemNouseRestrictions { + INR_NONE = 0x0, ///< No restrictions + INR_SITTING = 0x1, ///< Item can't be used while sitting + + INR_ALL = 0x1 ///< Sum of all the above values +}; + struct item_data { uint16 nameid; char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; @@ -377,7 +404,7 @@ struct item_data { unsigned available : 1; unsigned no_refine : 1; // [celest] unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex] - unsigned trade_restriction : 9; //Item restrictions mask [Skotlex] + unsigned trade_restriction : 9; ///< Item trade restrictions mask (@see enum ItemTradeRestrictions) unsigned autoequip: 1; unsigned buyingstore : 1; unsigned bindonequip : 1; @@ -389,8 +416,8 @@ struct item_data { unsigned int storage:1; unsigned int guildstorage:1; } stack; - struct {// used by item_nouse.txt - unsigned int flag; + struct { + unsigned int flag; ///< Item nouse restriction mask (@see enum ItemNouseRestrictions) unsigned short override; } item_usage; short gm_lv_trade_override; //GM-level to override trade_restriction @@ -562,12 +589,6 @@ struct itemdb_interface { int (*isrestricted) (struct item *item, int gmlv, int gmlv2, int(*func)(struct item_data *, int, int)); int (*isidentified) (int nameid); int (*isidentified2) (struct item_data *data); - bool (*read_itemavail) (char *str[], int columns, int current); - bool (*read_itemtrade) (char *str[], int columns, int current); - bool (*read_itemdelay) (char *str[], int columns, int current); - bool (*read_stack) (char *fields[], int columns, int current); - bool (*read_buyingstore) (char *fields[], int columns, int current); - bool (*read_nouse) (char *fields[], int columns, int current); int (*combo_split_atoi) (char *str, int *val); void (*read_combos) (); int (*gendercheck) (struct item_data *id); @@ -576,8 +597,7 @@ struct itemdb_interface { int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source); int (*readdb_libconfig) (const char *filename); int (*readdb_sql) (const char *tablename); - uint64 (*unique_id) (int8 flag, int64 value); - int (*uid_load) (); + uint64 (*unique_id) (struct map_session_data *sd); void (*read) (bool minimal); void (*destroy_item_data) (struct item_data *self, int free_self); int (*final_sub) (DBKey key, DBData *data, va_list ap); @@ -589,4 +609,4 @@ struct itemdb_interface *itemdb; void itemdb_defaults(void); -#endif /* _MAP_ITEMDB_H_ */ +#endif /* MAP_ITEMDB_H */ diff --git a/src/map/log.c b/src/map/log.c index 19a98f34b..523ef1d65 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -2,22 +2,25 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/sql.h" // SQL_INNODB -#include "../common/strlib.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "battle.h" -#include "itemdb.h" +#define HERCULES_CORE + #include "log.h" -#include "map.h" -#include "mob.h" -#include "pc.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" + struct log_interface log_s; /// obtain log type character for item/zeny logs diff --git a/src/map/log.h b/src/map/log.h index b2cb92c20..6ab142f87 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_LOG_H_ -#define _MAP_LOG_H_ +#ifndef MAP_LOG_H +#define MAP_LOG_H #include "../common/cbasetypes.h" #include "../common/sql.h" @@ -11,11 +11,10 @@ /** * Declarations **/ -struct block_list; -struct map_session_data; -struct mob_data; struct item; struct item_data; +struct map_session_data; +struct mob_data; /** * Defines @@ -134,4 +133,4 @@ struct log_interface *logs; void log_defaults(void); -#endif /* _MAP_LOG_H_ */ +#endif /* MAP_LOG_H */ diff --git a/src/map/mail.c b/src/map/mail.c index 371aa892f..7ba7d7470 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -2,19 +2,21 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/nullpo.h" -#include "../common/showmsg.h" +#define HERCULES_CORE #include "mail.h" -#include "atcommand.h" -#include "itemdb.h" -#include "clif.h" -#include "pc.h" -#include "log.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; void mail_clear(struct map_session_data *sd) diff --git a/src/map/mail.h b/src/map/mail.h index 8df537ff3..64b0f9779 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -2,10 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_MAIL_H_ -#define _MAP_MAIL_H_ +#ifndef MAP_MAIL_H +#define MAP_MAIL_H -#include "../common/mmo.h" +#include "../common/cbasetypes.h" + +struct item; +struct mail_message; +struct map_session_data; struct mail_interface { void (*clear) (struct map_session_data *sd); @@ -23,4 +27,4 @@ struct mail_interface *mail; void mail_defaults(void); -#endif /* _MAP_MAIL_H_ */ +#endif /* MAP_MAIL_H */ diff --git a/src/map/map.c b/src/map/map.c index a423e6973..b254b6792 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2,62 +2,66 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/core.h" -#include "../common/timer.h" -#include "../common/ers.h" -#include "../common/grfio.h" -#include "../common/malloc.h" -#include "../common/socket.h" // WFIFO*() -#include "../common/showmsg.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/conf.h" -#include "../common/console.h" -#include "../common/HPM.h" +#define HERCULES_CORE +#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL #include "map.h" -#include "path.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 "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 "mob.h" -#include "npc.h" // npc_setcells(), npc_unsetcells() -#include "chat.h" -#include "itemdb.h" #include "storage.h" -#include "skill.h" #include "trade.h" -#include "party.h" #include "unit.h" -#include "battle.h" -#include "battleground.h" -#include "quest.h" -#include "script.h" -#include "mapreg.h" -#include "guild.h" -#include "pet.h" -#include "homunculus.h" -#include "instance.h" -#include "mercenary.h" -#include "elemental.h" -#include "atcommand.h" -#include "log.h" -#include "mail.h" -#include "irc-bot.h" -#include "HPMmap.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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <math.h> #ifndef _WIN32 #include <unistd.h> #endif @@ -163,31 +167,32 @@ int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -/*========================================== - * These pair of functions update the counter of how many objects - * lie on a tile. - *------------------------------------------*/ -void map_addblcell(struct block_list *bl) { +/** + * Updates the counter (cell.cell_bl) of how many objects are on a tile. + * @param add Whether the counter should be increased or decreased + **/ +void map_update_cell_bl( struct block_list *bl, bool increase ) { #ifdef CELL_NOSTACK + int pos; + if( bl->m < 0 || bl->x < 0 || bl->x >= map->list[bl->m].xs || bl->y < 0 || bl->y >= map->list[bl->m].ys || !(bl->type&BL_CHAR) ) return; - map->list[bl->m].cell[bl->x+bl->y*map->list[bl->m].xs].cell_bl++; -#else - return; -#endif -} -void map_delblcell(struct block_list *bl) { -#ifdef CELL_NOSTACK - if( bl->m < 0 || bl->x < 0 || bl->x >= map->list[bl->m].xs - || bl->y < 0 || bl->y >= map->list[bl->m].ys - || !(bl->type&BL_CHAR) ) - map->list[bl->m].cell[bl->x+bl->y*map->list[bl->m].xs].cell_bl--; -#else - return; + // When reading from mapcache the cell isn't initialized + // TODO: Maybe start initializing cells when they're loaded instead of + // having to get them here? [Panikon] + if( map->list[bl->m].cell == (struct mapcell *)0xdeadbeaf ) + map->cellfromcache(&map->list[bl->m]); + + pos = bl->x + bl->y*map->list[bl->m].xs; + if( increase ) + map->list[bl->m].cell[pos].cell_bl++; + else + map->list[bl->m].cell[pos].cell_bl--; #endif + return; } /*========================================== @@ -233,7 +238,7 @@ int map_addblock(struct block_list* bl) } #ifdef CELL_NOSTACK - map->addblcell(bl); + map->update_cell_bl(bl, true); #endif return 0; @@ -250,14 +255,14 @@ int map_delblock(struct block_list* bl) // blocklist (2ways chainlist) if (bl->prev == NULL) { if (bl->next != NULL) { - // can't delete block (already at the begining of the chain) + // can't delete block (already at the beginning of the chain) ShowError("map_delblock error : bl->next!=NULL\n"); } return 0; } #ifdef CELL_NOSTACK - map->delblcell(bl); + map->update_cell_bl(bl, false); #endif pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map->list[bl->m].bxs; @@ -315,13 +320,13 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) { if (moveblock) map->delblock(bl); #ifdef CELL_NOSTACK - else map->delblcell(bl); + else map->update_cell_bl(bl, false); #endif bl->x = x1; bl->y = y1; if (moveblock) map->addblock(bl); #ifdef CELL_NOSTACK - else map->addblcell(bl); + else map->update_cell_bl(bl, true); #endif if (bl->type&BL_CHAR) { @@ -464,7 +469,7 @@ static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount, map->freeblock_lock(); for (i = blockcount; i < map->bl_list_count && returnCount < max; i++) { - if (map->bl_list[i]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + if (map->bl_list[i]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasn't queued for deletion. va_list argscopy; va_copy(argscopy, args); returnCount += func(map->bl_list[i], argscopy); @@ -490,7 +495,7 @@ static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount, static int map_vforeachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, va_list args) { int i; int returnCount = 0; - int bsize; + int bsize; va_list argscopy; struct block_list *bl; int blockcount = map->bl_list_count; @@ -2033,7 +2038,7 @@ void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) { } /// Applies func to everything in the db. -/// Stops iteratin gif func returns -1. +/// Stops iterating gif func returns -1. void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list args) { DBIterator* iter; struct block_list* bl; @@ -2053,7 +2058,7 @@ void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list } /// Applies func to everything in the db. -/// Stops iteratin gif func returns -1. +/// Stops iterating gif func returns -1. /// @see map_vforeachregen void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) { va_list args; @@ -2517,8 +2522,13 @@ void map_cellfromcache(struct map_data *m) { decode_zip(decode_buffer, &size, m->cellPos+sizeof(struct map_cache_map_info), info->len); CREATE(m->cell, struct mapcell, size); - for( xy = 0; xy < size; ++xy ) + // Set cell properties + for( xy = 0; xy < size; ++xy ) { m->cell[xy] = map->gat2cell(decode_buffer[xy]); +#ifdef CELL_NOSTACK + m->cell[xy].cell_bl = 0; +#endif + } m->getcellp = map->getcellp; m->setcell = map->setcell; @@ -2846,6 +2856,7 @@ int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port) { * [Shinryo]: Init the mapcache *------------------------------------------*/ char *map_init_mapcache(FILE *fp) { + struct map_cache_main_header header; size_t size = 0; char *buffer; @@ -2866,6 +2877,21 @@ char *map_init_mapcache(FILE *fp) { // Read file into buffer.. if(fread(buffer, sizeof(char), size, fp) != size) { ShowError("map_init_mapcache: Could not read entire mapcache file\n"); + aFree(buffer); + return NULL; + } + + rewind(fp); + + // Get main header to verify if data is corrupted + if( fread(&header, sizeof(header), 1, fp) != 1 ) { + ShowError("map_init_mapcache: Error obtaining main header!\n"); + aFree(buffer); + return NULL; + } + if( GetULong((unsigned char *)&(header.file_size)) != size ) { + ShowError("map_init_mapcache: Map cache is corrupted!\n"); + aFree(buffer); return NULL; } @@ -3273,6 +3299,9 @@ int map_readgat (struct map_data* m) type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) m->cell[xy] = map->gat2cell(type); +#ifdef CELL_NOSTACK + m->cell[xy].cell_bl = 0; +#endif } aFree(gat); @@ -3636,6 +3665,8 @@ int inter_config_read(char *cfgName) { strcpy(map->autotrade_merchants_db, w2); else if(strcmpi(w1,"autotrade_data_db")==0) strcpy(map->autotrade_data_db, w2); + else if(strcmpi(w1,"npc_market_data_db")==0) + strcpy(map->npc_market_data_db, w2); /* sql log db */ else if(strcmpi(w1,"log_db_ip")==0) strcpy(logs->db_ip, w2); @@ -3765,10 +3796,9 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone 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->disabled_commands[i], sizeof(struct map_zone_skill_damage_cap_entry)); + 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++ ) { @@ -3826,7 +3856,7 @@ void map_zone_remove(int m) { } } - npc->parse_mapflag(map->list[m].name,empty,flag,params,empty,empty,empty); + npc->parse_mapflag(map->list[m].name,empty,flag,params,empty,empty,empty, NULL); aFree(map->list[m].zone_mf[k]); map->list[m].zone_mf[k] = NULL; } @@ -4381,7 +4411,7 @@ bool map_zone_mf_cache(int m, char *flag, char *params) { } if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { - ;/* we dont mind it, the server will take care of it next. */ + ;/* we don't mind it, the server will take care of it next. */ } else { int idx = map->list[m].unit_count; @@ -4414,7 +4444,7 @@ bool map_zone_mf_cache(int m, char *flag, char *params) { } if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { - ;/* we dont mind it, the server will take care of it next. */ + ;/* we don't mind it, the server will take care of it next. */ } else { int idx = map->list[m].skill_count; @@ -4558,7 +4588,7 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const if( map->zone_mf_cache(m,flag,params) ) continue; - npc->parse_mapflag(map->list[m].name,empty,flag,params,start,buffer,filepath); + npc->parse_mapflag(map->list[m].name, empty, flag, params, start, buffer, filepath, NULL); } } /* used on npc load and reload to apply all "Normal" and "PK Mode" zones */ @@ -4586,7 +4616,7 @@ void map_zone_init(void) { if( map->list[j].zone == zone ) { if( map->zone_mf_cache(j,flag,params) ) break; - npc->parse_mapflag(map->list[j].name,empty,flag,params,empty,empty,empty); + npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL); } } } @@ -4608,7 +4638,7 @@ void map_zone_init(void) { if( map->list[j].zone == zone ) { if( map->zone_mf_cache(j,flag,params) ) break; - npc->parse_mapflag(map->list[j].name,empty,flag,params,empty,empty,empty); + npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL); } } } @@ -4771,7 +4801,7 @@ void read_map_zone_db(void) { --h; continue; } - if( !map->zone_bl_type(libconfig->setting_get_string_elem(skills,h),&subtype) )/* we dont remove it from the three due to inheritance */ + if( !map->zone_bl_type(libconfig->setting_get_string_elem(skills,h),&subtype) )/* we don't remove it from the three due to inheritance */ --disabled_skills_count; } /* all ok, process */ @@ -4809,7 +4839,7 @@ void read_map_zone_db(void) { --h; continue; } - if( !libconfig->setting_get_bool(item) )/* we dont remove it from the three due to inheritance */ + if( !libconfig->setting_get_bool(item) )/* we don't remove it from the three due to inheritance */ --disabled_items_count; } /* all ok, process */ @@ -4854,7 +4884,7 @@ void read_map_zone_db(void) { --h; continue; } - if( !libconfig->setting_get_int(command) )/* we dont remove it from the three due to inheritance */ + if( !libconfig->setting_get_int(command) )/* we don't remove it from the three due to inheritance */ --disabled_commands_count; } /* all ok, process */ @@ -4890,7 +4920,7 @@ void read_map_zone_db(void) { --h; continue; } - if( !map->zone_bl_type(libconfig->setting_get_string_elem(cap,1),&subtype) )/* we dont remove it from the three due to inheritance */ + if( !map->zone_bl_type(libconfig->setting_get_string_elem(cap,1),&subtype) )/* we don't remove it from the three due to inheritance */ --capped_skills_count; } /* all ok, process */ @@ -5213,8 +5243,7 @@ int cleanup_db_sub(DBKey key, DBData *data, va_list va) { /*========================================== * map destructor *------------------------------------------*/ -void do_final(void) -{ +int do_final(void) { int i; struct map_session_data* sd; struct s_mapiterator* iter; @@ -5309,6 +5338,7 @@ void do_final(void) HPM->event(HPET_POST_FINAL); ShowStatus("Finished.\n"); + return map->retval; } int map_abort_sub(struct map_session_data* sd, va_list ap) { @@ -5373,9 +5403,6 @@ void map_helpscreen(bool do_exit) * Map-Server Version Screen [MC Cameri] *------------------------------------------------------*/ void map_versionscreen(bool do_exit) { - const char *svn = get_svn_revision(); - const char *git = get_git_hash(); - ShowInfo(CL_WHITE"Hercules version: %s" CL_RESET"\n", git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown"); ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n"); ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n"); ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n"); @@ -5468,8 +5495,8 @@ void map_cp_defaults(void) { map->cpsd->bl.y = MAP_DEFAULT_Y; map->cpsd->bl.m = map->mapname2mapid(MAP_DEFAULT); - console->addCommand("gm:info",CPCMD_A(gm_position)); - console->addCommand("gm:use",CPCMD_A(gm_use)); + console->input->addCommand("gm:info",CPCMD_A(gm_position)); + console->input->addCommand("gm:use",CPCMD_A(gm_use)); #endif } /* Hercules Plugin Mananger */ @@ -5694,7 +5721,7 @@ int do_init(int argc, char *argv[]) char ip_str[16]; ip2str(sockt->addr_[0], ip_str); - ShowWarning("Not all IP addresses in /conf/map-server.conf configured, autodetecting...\n"); + ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n"); if (sockt->naddr_ == 0) ShowError("Unable to determine your IP address...\n"); @@ -5718,7 +5745,7 @@ int do_init(int argc, char *argv[]) map->id_db = idb_alloc(DB_OPT_BASE); map->pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map->id2sd() use. [Skotlex] - map->mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob ai. [Skotlex] + map->mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob AI. [Skotlex] map->bossid_db = idb_alloc(DB_OPT_BASE); // Used for Convex Mirror quick MVP search map->map_db = uidb_alloc(DB_OPT_BASE); map->nick_db = idb_alloc(DB_OPT_BASE); @@ -5777,7 +5804,7 @@ int do_init(int argc, char *argv[]) itemdb->init(minimal); skill->init(minimal); if (!minimal) - map->read_zone_db();/* read after item and skill initalization */ + map->read_zone_db();/* read after item and skill initialization */ mob->init(minimal); pc->init(minimal); status->init(minimal); @@ -5798,7 +5825,7 @@ int do_init(int argc, char *argv[]) if (scriptcheck) { bool failed = load_extras_count > 0 ? false : true; for (i = 0; i < load_extras_count; i++) { - if (npc->parsesrcfile(load_extras[i], false) != 0) + if (npc->parsesrcfile(load_extras[i], false) != EXIT_SUCCESS) failed = true; } if (failed) @@ -5816,7 +5843,7 @@ int do_init(int argc, char *argv[]) exit(EXIT_SUCCESS); } - npc->event_do_oninit(); // Init npcs (OnInit) + npc->event_do_oninit( false ); // Init npcs (OnInit) npc->market_fromsql(); /* after OnInit */ if (battle_config.pk_mode) @@ -5825,7 +5852,7 @@ int do_init(int argc, char *argv[]) Sql_HerculesUpdateCheck(map->mysql_handle); #ifdef CONSOLE_INPUT - console->setSQL(map->mysql_handle); + 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); @@ -5843,7 +5870,7 @@ int do_init(int argc, char *argv[]) } /*===================================== -* Default Functions : map.h +* Default Functions : map.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -5853,6 +5880,7 @@ void map_defaults(void) { /* */ map->minimal = false; map->count = 0; + map->retval = EXIT_SUCCESS; sprintf(map->db_path ,"db"); sprintf(map->help_txt ,"conf/help.txt"); @@ -6107,8 +6135,7 @@ void map_defaults(void) { map->versionscreen = map_versionscreen; map->arg_next_value = map_arg_next_value; - map->addblcell = map_addblcell; - map->delblcell = map_delblcell; + map->update_cell_bl = map_update_cell_bl; map->get_new_bonus_id = map_get_new_bonus_id; diff --git a/src/map/map.h b/src/map/map.h index c1eaeb40d..4f7f09131 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -2,21 +2,21 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_MAP_H_ -#define _MAP_MAP_H_ +#ifndef MAP_MAP_H +#define MAP_MAP_H +#include <stdarg.h> + +#include "atcommand.h" #include "../common/cbasetypes.h" #include "../common/core.h" // CORE_ST_LAST -#include "../common/mmo.h" -#include "../common/mapindex.h" #include "../common/db.h" -#include "../config/core.h" +#include "../common/mapindex.h" +#include "../common/mmo.h" #include "../common/sql.h" -#include "atcommand.h" -#include <stdarg.h> +struct mob_data; struct npc_data; -struct item_data; struct hChSysCh; enum E_MAPSERVER_ST { @@ -26,7 +26,7 @@ enum E_MAPSERVER_ST { }; #define MAX_NPC_PER_MAP 512 -#define AREA_SIZE (battle_config.area_size) +#define AREA_SIZE (battle->bc->area_size) #define DAMAGELOG_SIZE 30 #define LOOTITEM_SIZE 10 #define MAX_MOBSKILL 50 @@ -36,7 +36,6 @@ enum E_MAPSERVER_ST { #define NATURAL_HEAL_INTERVAL 500 #define MIN_FLOORITEM 2 #define MAX_FLOORITEM START_ACCOUNT_NUM -#define MAX_LEVEL 150 #define MAX_IGNORE_LIST 20 // official is 14 #define MAX_VENDING 12 #define MAX_MAP_SIZE (512*512) // Wasn't there something like this already? Can't find it.. [Shinryo] @@ -325,7 +324,7 @@ struct spawn_data { unsigned int level; struct { unsigned int size : 2; //Holds if mob has to be tiny/large - unsigned int ai : 4; //Special ai for summoned monsters. + unsigned int ai : 4; //Special AI for summoned monsters. //0: Normal mob | 1: Standard summon, attacks mobs //2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list @@ -343,7 +342,7 @@ struct flooritem_data { struct item item_data; }; -enum _sp { +enum status_point_types { SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7 SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15 SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23 @@ -416,7 +415,7 @@ enum _sp { SP_LAST_KNOWN, }; -enum _look { +enum look { LOOK_BASE, LOOK_HAIR, LOOK_WEAPON, @@ -487,7 +486,7 @@ struct mapcell { icewall : 1; #ifdef CELL_NOSTACK - unsigned char cell_bl; //Holds amount of bls in this cell. + int cell_bl; //Holds amount of bls in this cell. #endif }; @@ -580,9 +579,9 @@ struct map_data { "Algorithms in Java, Parts 1-4" 3.18, Robert Sedgewick Map is divided into squares, called blocks (side length = BLOCK_SIZE). For each block there is a linked list of objects in that block (block_list). - Array provides capability to access immediately the set of objects close + Array provides capability to access immediately the set of objects close to a given object. - The linked lists provide the flexibility to store the objects without + The linked lists provide the flexibility to store the objects without knowing ahead how many objects fall into each block. */ struct block_list **block; // Grid array of block_lists containing only non-BL_MOB objects @@ -660,8 +659,8 @@ struct map_data { int nocommand; //Blocks @/# commands for non-gms. [Skotlex] /** * Ice wall reference counter for bugreport:3574 - * - since there are a thounsand mobs out there in a lot of maps checking on, - * - every targetting for icewall on attack path would just be a waste, so, + * - since there are a thousand mobs out there in a lot of maps checking on, + * - every targeting for icewall on attack path would just be a waste, so, * - this counter allows icewall checking be only run when there is a actual ice wall on the map **/ int icewall_num; @@ -733,7 +732,7 @@ struct map_data_other_server { /// Bitfield of flags for the iterator. enum e_mapitflags { MAPIT_NORMAL = 0, - // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold auth'ed, active players. + // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold authed, active players. }; struct s_mapiterator; @@ -797,7 +796,7 @@ struct map_cache_map_info { /*===================================== -* Interface : map.h +* Interface : map.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -805,6 +804,7 @@ struct map_interface { /* vars */ bool minimal; + int retval; int count; int autosave_interval; @@ -845,6 +845,7 @@ struct map_interface { char interreg_db[32]; char autotrade_merchants_db[32]; char autotrade_data_db[32]; + char npc_market_data_db[32]; char default_codepage[32]; @@ -1058,8 +1059,7 @@ struct map_interface { void (*helpscreen) (bool do_exit); void (*versionscreen) (bool do_exit); bool (*arg_next_value) (const char *option, int i, int argc, bool must); - void (*addblcell) (struct block_list *bl); - void (*delblcell) (struct block_list *bl); + void (*update_cell_bl) (struct block_list *bl, bool increase); int (*get_new_bonus_id) (void); void (*add_questinfo) (int m, struct questinfo *qi); bool (*remove_questinfo) (int m, struct npc_data *nd); @@ -1070,4 +1070,4 @@ struct map_interface *map; void map_defaults(void); -#endif /* _MAP_MAP_H_ */ +#endif /* MAP_MAP_H */ diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 2aa2943a2..59d226cda 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_MAPREG_H_ -#define _MAP_MAPREG_H_ +#ifndef MAP_MAPREG_H +#define MAP_MAPREG_H #include "script.h" // struct reg_db #include "../common/cbasetypes.h" @@ -50,4 +50,4 @@ struct mapreg_interface *mapreg; void mapreg_defaults(void); -#endif /* _MAP_MAPREG_H_ */ +#endif /* MAP_MAPREG_H */ diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 61c25f24e..f026fde00 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -2,6 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#include "mapreg.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" @@ -10,11 +19,6 @@ #include "../common/sql.h" #include "../common/strlib.h" #include "../common/timer.h" -#include "map.h" // map->mysql_handle -#include "script.h" -#include "mapreg.h" -#include <stdlib.h> -#include <string.h> struct mapreg_interface mapreg_s; diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 495621014..80bcfdf05 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -2,42 +2,44 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/mmo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" +#define HERCULES_CORE -#include "log.h" -#include "clif.h" +#include "mercenary.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 "pc.h" -#include "status.h" -#include "skill.h" #include "mob.h" -#include "pet.h" -#include "battle.h" +#include "npc.h" #include "party.h" -#include "guild.h" -#include "atcommand.h" +#include "pc.h" +#include "pet.h" #include "script.h" -#include "npc.h" +#include "skill.h" +#include "status.h" #include "trade.h" #include "unit.h" -#include "mercenary.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.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; @@ -501,7 +503,7 @@ void do_init_mercenary(bool minimal) { } /*===================================== -* Default Functions : mercenary.h +* Default Functions : mercenary.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/mercenary.h b/src/map/mercenary.h index dd9266b2e..270245e96 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -1,11 +1,12 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_MERCENARY_H_ -#define _MAP_MERCENARY_H_ +#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" // number of cells that a mercenary can walk to from it's master before being warped #define MAX_MER_DISTANCE 15 @@ -47,7 +48,7 @@ struct mercenary_data { }; /*===================================== -* Interface : mercenary.h +* Interface : mercenary.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -98,4 +99,4 @@ struct mercenary_interface *mercenary; void mercenary_defaults(void); -#endif /* _MAP_MERCENARY_H_ */ +#endif /* MAP_MERCENARY_H */ diff --git a/src/map/mob.c b/src/map/mob.c index 8f12d4b1b..38ddffa37 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -2,46 +2,49 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/db.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/ers.h" -#include "../common/random.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/socket.h" +#define HERCULES_CORE -#include "map.h" -#include "path.h" -#include "clif.h" -#include "intif.h" -#include "pc.h" -#include "pet.h" -#include "status.h" +#include "../config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP #include "mob.h" -#include "homunculus.h" -#include "mercenary.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 "skill.h" -#include "battle.h" -#include "party.h" -#include "npc.h" #include "log.h" -#include "script.h" -#include "atcommand.h" -#include "date.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 <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <math.h> +#include "script.h" +#include "skill.h" +#include "status.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; @@ -353,7 +356,7 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) { return false; // KS Protection Disabled if( !(md = BL_CAST(BL_MOB,target)) ) - return false; // Tarjet is not MOB + return false; // Target is not MOB if( (s_bl = battle->get_master(src)) == NULL ) s_bl = src; @@ -484,20 +487,17 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const if (!md) continue; - if (class_ == MOBID_EMPERIUM && !no_guardian_data) { + if ( class_ == MOBID_EMPERIUM && !no_guardian_data ) { struct guild_castle* gc = guild->mapindex2gc(map_id2index(m)); struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL; - if (gc) { + if( gc ) { md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); md->guardian_data->castle = gc; md->guardian_data->number = MAX_GUARDIANS; - md->guardian_data->guild_id = gc->guild_id; - if (g) { - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - } - else if (gc->guild_id) //Guild not yet available, retry in 5. - timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); + if( g ) + md->guardian_data->g = g; + else if( gc->guild_id ) //Guild not yet available, retry in 5. + timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id); } } // end addition [Valaris] @@ -567,21 +567,23 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0 return id; // id of last spawned mob } -/*========================================== - * Set a Guardian's guild data [Skotlex] - *------------------------------------------*/ + +/** + * Sets a guardian's guild data and liberates castle if couldn't retrieve guild data + * @param data (int)guild_id + * @retval Always 0 + * @author Skotlex + **/ int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) { - //Needed because the guild_data may not be available at guardian spawn time. + //Needed because the guild data may not be available at guardian spawn time. struct block_list* bl = map->id2bl(id); struct mob_data* md; struct guild* g; - int guardup_lv; - if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] + if( bl == NULL ) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] return 0; - if (bl->type != BL_MOB) - { + if( bl->type != BL_MOB ) { ShowError("mob_spawn_guardian_sub: Block error!\n"); return 0; } @@ -590,30 +592,28 @@ int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) { nullpo_ret(md->guardian_data); g = guild->search((int)data); - if (g == NULL) - { //Liberate castle, if the guild is not found this is an error! [Skotlex] + if( g == NULL ) { //Liberate castle, if the guild is not found this is an error! [Skotlex] ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n", (int)data); - if (md->class_ == MOBID_EMPERIUM && md->guardian_data) - { //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on. - md->guardian_data->guild_id = 0; - if (md->guardian_data->castle->guild_id) //Free castle up. - { + //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on. + if( md->class_ == MOBID_EMPERIUM && md->guardian_data ) { + md->guardian_data->g = NULL; + if( md->guardian_data->castle->guild_id ) {//Free castle up. ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name); guild->castledatasave(md->guardian_data->castle->castle_id, 1, 0); } } else { - if (md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) + if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS + && md->guardian_data->castle->guardian[md->guardian_data->number].visible ) guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); - unit->free(&md->bl,CLR_OUTSIGHT); //Remove guardian. + + unit->free(&md->bl,CLR_OUTSIGHT); // Remove guardian. } return 0; } - guardup_lv = guild->checkskill(g,GD_GUARDUP); - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guardup_lv; - if( guardup_lv ) - status_calc_mob(md, SCO_NONE); //Give bonuses. + + if( guild->checkskill(g,GD_GUARDUP) ) + status_calc_mob(md, SCO_NONE); // Give bonuses. + return 0; } @@ -689,7 +689,6 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam md = mob->spawn_dataset(&data); md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); md->guardian_data->number = guardian; - md->guardian_data->guild_id = gc->guild_id; md->guardian_data->castle = gc; if( has_index ) {// permanent guardian @@ -706,13 +705,10 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam } gc->temp_guardians[i] = md->bl.id; } - if (g) - { - md->guardian_data->emblem_id = g->emblem_id; - memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP); - } else if (md->guardian_data->guild_id) - timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); + if( g ) + md->guardian_data->g = g; + else if( gc->guild_id ) + timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id); mob->spawn(md); return md->bl.id; @@ -1070,7 +1066,7 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) default: if (battle_config.hom_setting&0x4 && (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM) - return 0; //For some reason Homun targets are never overriden. + return 0; //For some reason Homun targets are never overridden. dist = distance_bl(&md->bl, bl); if( @@ -1440,7 +1436,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { //Unlock current target. if (mob->warpchase(md, tbl)) return true; //Chasing this target. - mob->unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk. + mob->unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Immediately do random walk. tbl = NULL; } } @@ -1617,7 +1613,19 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { if(tbl->type == BL_PC) mob->log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus) - unit->attack(&md->bl,tbl->id,1); + + if(!(mode&MD_RANDOMTARGET)) + unit->attack(&md->bl,tbl->id,1); + else { // Attack once and find new random target + int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range; + unit->attack(&md->bl,tbl->id,0); + tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size); + // If no target was found, keep atacking the old one + if( tbl ) { + md->target_id = tbl->id; + md->min_chase = md->db->range3; + } + } return true; } @@ -2072,7 +2080,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { unsigned int base_exp,job_exp; } pt[DAMAGELOG_SIZE]; int i, temp, count, m = md->bl.m, pnum = 0; - int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution + int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are eligible for exp distribution unsigned int mvp_damage; int64 tick = timer->gettick(); bool rebirth, homkillonly; @@ -2290,7 +2298,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { int drop_modifier = mvp_sd ? pc->level_penalty_mod( md->level - mvp_sd->status.base_level, md->status.race, md->status.mode, 2) : second_sd ? pc->level_penalty_mod( md->level - second_sd->status.base_level, md->status.race, md->status.mode, 2): third_sd ? pc->level_penalty_mod( md->level - third_sd->status.base_level, md->status.race, md->status.mode, 2) : - 100;/* no player was attached, we dont use any modifier (100 = rates are not touched) */ + 100;/* no player was attached, we don't use any modifier (100 = rates are not touched) */ #endif dlist->m = md->bl.m; dlist->x = md->bl.x; @@ -2601,7 +2609,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { if( !rebirth ) { if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client. - /* first we set them dead, then we delay the outsight effect */ + /* first we set them dead, then we delay the out sight effect */ clif->clearunit_area(&md->bl,CLR_DEAD); clif->clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000); } else @@ -2654,14 +2662,11 @@ int mob_guardian_guildchange(struct mob_data *md) if (!md->guardian_data) return 0; - if (md->guardian_data->castle->guild_id == 0) + if( md->guardian_data->castle->guild_id == 0 ) { //Castle with no owner? Delete the guardians. - if (md->class_ == MOBID_EMPERIUM) - { //But don't delete the emperium, just clear it's guild-data - md->guardian_data->guild_id = 0; - md->guardian_data->emblem_id = 0; - md->guardian_data->guild_name[0] = '\0'; - } else { + if( md->class_ == MOBID_EMPERIUM ) //But don't delete the emperium, just clear it's guild-data + md->guardian_data->g = NULL; + else { if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); unit->free(&md->bl,CLR_OUTSIGHT); //Remove guardian. @@ -2670,19 +2675,16 @@ int mob_guardian_guildchange(struct mob_data *md) } g = guild->search(md->guardian_data->castle->guild_id); - if (g == NULL) + if( g == NULL ) { //Properly remove guardian info from Castle data. - ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id); + ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->castle->guild_id); if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); unit->free(&md->bl,CLR_OUTSIGHT); return 0; } - md->guardian_data->guild_id = g->guild_id; - md->guardian_data->emblem_id = g->emblem_id; - md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP); - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); + md->guardian_data->g = g; return 1; } @@ -2830,7 +2832,7 @@ int mob_warpslave(struct block_list *bl, int range) { } /*========================================== - * Counts slave sub, curently checking if mob master is the given ID. + * Counts slave sub, currently checking if mob master is the given ID. *------------------------------------------*/ int mob_countslave_sub(struct block_list *bl,va_list ap) { @@ -3070,6 +3072,7 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { struct block_list *bl; struct mob_data *fmd = NULL; int i,j,n; + short skill_target; nullpo_ret(md); nullpo_ret(ms = md->db->skill); @@ -3168,10 +3171,12 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { if (!flag) continue; //Skill requisite failed to be fulfilled. + //Execute skill + skill_target = (md->db->status.mode&MD_RANDOMTARGET)? MST_RANDOM : ms[i].target; if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill. short x, y; - switch (ms[i].target) { + switch (skill_target) { case MST_RANDOM: //Pick a random enemy within skill range. bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); @@ -3201,10 +3206,10 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { x = bl->x; y = bl->y; // Look for an area to cast the spell around... - if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) { - j = ms[i].target >= MST_AROUND1? - (ms[i].target-MST_AROUND1) +1: - (ms[i].target-MST_AROUND5) +1; + if (skill_target >= MST_AROUND1 || skill_target >= MST_AROUND5) { + j = skill_target >= MST_AROUND1? + (skill_target-MST_AROUND1) +1: + (skill_target-MST_AROUND5) +1; map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3); } md->skill_idx = i; @@ -3216,8 +3221,8 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) { continue; } } else { - //Targetted skill - switch (ms[i].target) { + //Targeted skill + switch (skill_target) { case MST_RANDOM: //Pick a random enemy within skill range. bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); @@ -3320,7 +3325,7 @@ int mob_is_clone(int class_) } //Flag values: -//&1: Set special ai (fight mobs, not players) +//&1: Set special AI (fight mobs, not players) //If mode is not passed, a default aggressive mode is used. //If master_id is passed, clone is attached to him. //Returns: ID of newly crafted copy. @@ -3606,7 +3611,7 @@ unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_ } /** - * Check if global item drop rate is overriden for given item + * Check if global item drop rate is overridden for given item * in db/mob_item_ratio.txt * @param nameid ID of the item * @param mob_id ID of the monster @@ -3758,7 +3763,7 @@ bool mob_parse_dbrow(char** str) { status->calc_misc(&data.bl, mstatus, db->lv); // MVP EXP Bonus: MEXP - // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza] + // Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza] exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); @@ -3820,7 +3825,7 @@ bool mob_parse_dbrow(char** str) { ratemax = battle_config.item_drop_treasure_max; } else switch (type) - { // Added suport to restrict normal drops of MVP's [Reddozen] + { // Added support to restrict normal drops of MVP's [Reddozen] case IT_HEALING: rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; ratemin = battle_config.item_drop_heal_min; @@ -3877,7 +3882,7 @@ bool mob_parse_dbrow(char** str) { mob->db_data[class_] = (struct mob_db*)aMalloc(sizeof(struct mob_db)); else //Copy over spawn data - memcpy(&db->spawn, mob->db_data[class_]->spawn, sizeof(db->spawn)); + memcpy(&db->spawn, mob->db_data[class_]->spawn, sizeof(db->spawn)); memcpy(mob->db_data[class_], db, sizeof(struct mob_db)); return true; diff --git a/src/map/mob.h b/src/map/mob.h index 80175b1db..c8d43dbb2 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -2,19 +2,18 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_MOB_H_ -#define _MAP_MOB_H_ +#ifndef MAP_MOB_H +#define MAP_MOB_H -#include "../common/mmo.h" // struct item -#include "guild.h" // struct guardian_data #include "map.h" // struct status_data, struct view_data, struct mob_skill -#include "status.h" // struct status data, struct status_change -#include "unit.h" // unit_stop_walking(), unit_stop_attack() -#include "npc.h" +#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 #define MAX_RANDOMMONSTER 5 -// Change this to increase the table size in your mob_db to accomodate a larger mob database. +// Change this to increase the table size in your mob_db to accommodate a larger mob database. // Be sure to note that IDs 4001 to 4048 are reserved for advanced/baby/expanded classes. // Notice that the last 1000 entries are used for player clones, so always set this to desired value +1000 #define MAX_MOB_DB 4000 @@ -36,7 +35,7 @@ #define MOB_CLONE_START (MAX_MOB_DB-999) #define MOB_CLONE_END MAX_MOB_DB -//Used to determine default enemy type of mobs (for use in eachinrange calls) +//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 MAX_MOB_CHAT 250 //Max Skill's messages @@ -128,7 +127,7 @@ struct mob_data { char name[NAME_LENGTH]; struct { unsigned int size : 2; //Small/Big monsters. - unsigned int ai : 4; //Special ai for summoned monsters. + unsigned int ai : 4; //Special AI for summoned monsters. //0: Normal mob. //1: Standard summon, attacks mobs. //2: Alchemist Marine Sphere @@ -364,4 +363,4 @@ struct mob_interface *mob; void mob_defaults(void); -#endif /* _MAP_MOB_H_ */ +#endif /* MAP_MOB_H */ diff --git a/src/map/npc.c b/src/map/npc.c index ae374e961..417aa6c61 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2,41 +2,44 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/ers.h" -#include "../common/db.h" -#include "../common/socket.h" -#include "../common/HPM.h" +#define HERCULES_CORE -#include "map.h" -#include "log.h" +#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 <errno.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "battle.h" +#include "chat.h" #include "clif.h" +#include "instance.h" #include "intif.h" -#include "pc.h" -#include "status.h" #include "itemdb.h" -#include "script.h" +#include "log.h" +#include "map.h" #include "mob.h" +#include "pc.h" #include "pet.h" -#include "instance.h" -#include "battle.h" +#include "script.h" #include "skill.h" +#include "status.h" #include "unit.h" -#include "npc.h" -#include "chat.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <time.h> -#include <errno.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; @@ -447,14 +450,17 @@ int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) { return c; } -/*========================================== - * OnInit Event execution (the start of the event and watch) - *------------------------------------------*/ -void npc_event_do_oninit(void) +/** + * OnInit event execution (the start of the event and watch) + * @param reload Is the server reloading? + **/ +void npc_event_do_oninit( bool reload ) { ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc->event_doall("OnInit")); - timer->add_interval(timer->gettick()+100,npc->event_do_clock,0,0,1000); + // This interval has already been added on startup + if( !reload ) + timer->add_interval(timer->gettick()+100,npc->event_do_clock,0,0,1000); } /*========================================== @@ -660,7 +666,7 @@ void npc_timerevent_quit(struct map_session_data* sd) struct npc_data* nd; struct timer_event_data *ted; - // Check timer existance + // Check timer existence if( sd->npc_timer_id == INVALID_TIMER ) return; if( !(td = timer->get(sd->npc_timer_id)) ) @@ -1148,10 +1154,10 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) // This usually happens when the player clicked on a NPC that has the view id // of a mob, to activate this kind of npc it's needed to be in a 2,2 range - // from it. If the OnTouch area of a npc, coincides with the 2,2 range of + // from it. If the OnTouch area of a npc, coincides with the 2,2 range of // another it's expected that the OnTouch event be put first in stack, because // unit_walktoxy_timer is executed before any other function in this case. - // So it's best practice to put an 'end;' before OnTouch events in npcs that + // So it's best practice to put an 'end;' before OnTouch events in npcs that // have view ids of mobs to avoid this "issue" [Panikon] if (sd->npc_id != 0) { // The player clicked a npc after entering an OnTouch area @@ -1295,23 +1301,23 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns unsigned short shop_size = 0; if( sd->state.trading ) - return 4; + return ERROR_TYPE_EXCHANGE; if( count <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( points < 0 ) - return 6; + return ERROR_TYPE_MONEY; if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) - return 1; + 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; shop_size = nd->u.scr.shop->items; } else - return 1; + return ERROR_TYPE_NPC; } else { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; @@ -1327,14 +1333,14 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns amount = item_list[i*2+0]; if( !itemdb->exists(nameid) || amount <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; ARR_FIND(0,shop_size,j,shop[j].nameid == nameid); if( j == shop_size || shop[j].value <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( !itemdb->isstackable(nameid) && amount > 1 ) { - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + 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; } @@ -1344,7 +1350,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns new_++; break; case ADDITEM_OVERAMOUNT: - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; } vt += shop[j].value * amount; @@ -1352,20 +1358,20 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } if( w + sd->weight > sd->max_weight ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( pc->inventoryblank(sd) < new_ ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( points > vt ) points = vt; // Payment Process ---------------------------------------------------- if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { if( !npc->trader_pay(nd,sd,vt,points) ) - return 6; + return ERROR_TYPE_MONEY; } else { if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) - return 6; + return ERROR_TYPE_MONEY; pc->paycash(sd,vt,points); } // Delivery Process ---------------------------------------------------- @@ -1384,7 +1390,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } } - return 0; + return ERROR_TYPE_NONE; } //npc_buylist for script-controlled shops. @@ -1420,8 +1426,7 @@ void npc_market_fromsql(void) { int itemid; int amount; - /* TODO inter-server.conf npc_market_data */ - if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `npc_market_data`") + if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `%s`", map->npc_market_data_db) || SQL_ERROR == SQL->StmtExecute(stmt) ) { SqlStmt_ShowDebug(stmt); @@ -1468,20 +1473,20 @@ void npc_market_fromsql(void) { * Saves persistent NPC Market Data into SQL **/ void npc_market_tosql(struct npc_data *nd, unsigned short index) { - /* TODO inter-server.conf npc_market_data */ - if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `npc_market_data` VALUES ('%s','%d','%d')", nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%d')", + map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty) ) Sql_ShowDebug(map->mysql_handle); } /** * Removes persistent NPC Market Data from SQL */ void npc_market_delfromsql_sub(const char *npcname, unsigned short index) { - /* TODO inter-server.conf npc_market_data */ if( index == USHRT_MAX ) { - if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `npc_market_data` WHERE `name`='%s'", npcname) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_market_data_db, npcname) ) Sql_ShowDebug(map->mysql_handle); } else { - if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `npc_market_data` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1", npcname, index) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1", + map->npc_market_data_db, npcname, index) ) Sql_ShowDebug(map->mysql_handle); } } @@ -1514,7 +1519,7 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { /* nothing to display, no items available */ if( i == nd->u.scr.shop->items ) { - clif->colormes(sd->fd,COLOR_RED,"Shop is out of stock! Come again later!");/* TODO messages.conf-it */ + clif->colormes(sd->fd,COLOR_RED, msg_txt(881)); return false; } @@ -1628,26 +1633,26 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po unsigned short shop_size = 0; if( amount <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if( points < 0 ) - return 6; + return ERROR_TYPE_MONEY; if( sd->state.trading ) - return 4; + return ERROR_TYPE_EXCHANGE; if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) ) - return 1; + return ERROR_TYPE_NPC; if( (item = itemdb->exists(nameid)) == NULL ) - return 5; // Invalid Item + return ERROR_TYPE_ITEM_ID; // Invalid Item 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; shop_size = nd->u.scr.shop->items; } else - return 1; + return ERROR_TYPE_NPC; } else { shop = nd->u.shop.shop_item; shop_size = nd->u.shop.count; @@ -1656,13 +1661,13 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po ARR_FIND(0, shop_size, i, shop[i].nameid == nameid); if( i == shop_size ) - return 5; + return ERROR_TYPE_ITEM_ID; if( shop[i].value <= 0 ) - return 5; + return ERROR_TYPE_ITEM_ID; if(!itemdb->isstackable(nameid) && amount > 1) { - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + 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 = 1; } @@ -1670,15 +1675,15 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po switch( pc->checkadditem(sd, nameid, amount) ) { case ADDITEM_NEW: if( pc->inventoryblank(sd) == 0 ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; break; case ADDITEM_OVERAMOUNT: - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; } w = item->weight * amount; if( w + sd->weight > sd->max_weight ) - return 3; + return ERROR_TYPE_INVENTORY_WEIGHT; if( (double)shop[i].value * amount > INT_MAX ) { ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); @@ -1686,7 +1691,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po nd->exname, map->list[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, shop[i].value, amount); - return 5; + return ERROR_TYPE_ITEM_ID; } price = shop[i].value * amount; @@ -1696,10 +1701,10 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) { if( !npc->trader_pay(nd,sd,price,points) ) - return 6; + return ERROR_TYPE_MONEY; } else { if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) - return 6; + return ERROR_TYPE_MONEY; pc->paycash(sd, price, points); } @@ -1713,7 +1718,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po pc->additem(sd,&item_tmp, amount, LOG_TYPE_NPC); } - return 0; + return ERROR_TYPE_NONE; } /// Player item purchase from npc shop. @@ -1770,7 +1775,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { if( !itemdb->isstackable(nameid) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + 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; } @@ -1893,7 +1898,7 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st if( !itemdb->isstackable(nameid) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + 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; } @@ -2532,8 +2537,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short } /// Parses a warp npc. -const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) { int x, y, xs, ys, to_x, to_y, m; unsigned short i; char mapname[32], to_mapname[32]; @@ -2542,22 +2546,24 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s // w1=<from map name>,<fromX>,<fromY>,<facing> // w4=<spanx>,<spany>,<to map name>,<toX>,<toY> if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3 - || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5 ) - { + || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5 + ) { ShowError("npc_parse_warp: Invalid warp definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } m = map->mapname2mapid(mapname); i = mapindex->name2id(to_mapname); - if( i == 0 ) - { + if( i == 0 ) { ShowError("npc_parse_warp: Unknown destination map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), to_mapname, w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) { ShowError("npc_parse_warp: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');;//try next } @@ -2596,26 +2602,35 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s return strchr(start,'\n');// continue } -/// Parses a shop/cashshop npc. -const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +/** + * Parses a SHOP/CASHSHOP npc + * @param retval Pointer to the status, used to know whether there was an error or not, if so it will be EXIT_FAILURE + * @retval Parsing position (currently only '\n') + **/ +const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) { //TODO: could be rewritten to NOT need this temp array [ultramage] - #define MAX_SHOPITEM 100 - struct npc_item_list items[MAX_SHOPITEM]; + // We could use nd->u.shop.shop_item to store directly the items, but this could lead + // to unecessary memory usage by the server, using a temp dynamic array is the + // best way to do this without having to do multiple reallocs [Panikon] + struct npc_item_list *items = NULL; + size_t items_count = 40; // Starting items size + char *p; int x, y, dir, m, i; struct npc_data *nd; enum npc_subtype type; - if( strcmp(w1,"-") == 0 ) {// 'floating' shop? + if( strcmp(w1,"-") == 0 ) { + // 'floating' shop x = y = dir = 0; m = -1; } else {// w1=<map name>,<x>,<y>,<facing> char mapname[32]; if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 - || strchr(w4, ',') == NULL ) - { + || strchr(w4, ',') == NULL + ) { ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } @@ -2624,7 +2639,8 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) { ShowError("npc_parse_shop: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer)); - return strchr(start,'\n');;//try next + if (retval) *retval = EXIT_FAILURE; + return strchr(start,'\n');//try next } if( strcmp(w2,"cashshop") == 0 ) @@ -2632,39 +2648,51 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s else type = SHOP; + items = aMalloc(sizeof(items[0])*items_count); + p = strchr(w4,','); - for( i = 0; i < ARRAYLENGTH(items) && p; ++i ) - { + for( i = 0; p; ++i ) { int nameid, value; struct item_data* id; - if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) - { + + if( i == items_count-1 ) { // Grow array + items_count *= 2; + items = aRealloc(items, sizeof(items[0])*items_count); + } + + if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) { ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; break; } - if( (id = itemdb->exists(nameid)) == NULL ) - { + if( (id = itemdb->exists(nameid)) == NULL ) { ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid); p = strchr(p+1,','); + if (retval) *retval = EXIT_FAILURE; continue; } - if( value < 0 ) - { + if( value < 0 ) { + if( value != -1 ) + ShowWarning("npc_parse_shop: Item %s [%d] with invalid selling value '%d' in file '%s', line '%d', defaulting to buy price...\n", + id->name, nameid, value, filepath, strline(buffer,start-buffer)); + if( type == SHOP ) value = id->value_buy; else value = 0; // Cashshop doesn't have a "buy price" in the item_db } - if( type == SHOP && value == 0 ) - { // NPC selling items for free! + if( type == SHOP && value == 0 ) { + // NPC selling items for free! ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n", id->name, nameid, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } - if( type == SHOP && value*0.75 < id->value_sell*1.24 ) - {// Exploit possible: you can buy and sell back with profit + if( type == SHOP && value*0.75 < id->value_sell*1.24 ) { + // Exploit possible: you can buy and sell back with profit ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in file '%s', line '%d'.\n", id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } //for logs filters, atcommands and iteminfo script command if( id->maxchance == 0 ) @@ -2674,15 +2702,18 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s items[i].value = value; p = strchr(p+1,','); } - if( i == 0 ) - { + if( i == 0 ) { ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer)); + aFree(items); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// continue } CREATE(nd, struct npc_data, 1); CREATE(nd->u.shop.shop_item, struct npc_item_list, i); - memcpy(nd->u.shop.shop_item, items, sizeof(struct npc_item_list)*i); + memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i); + aFree(items); + nd->u.shop.count = i; nd->bl.prev = nd->bl.next = NULL; nd->bl.m = m; @@ -2704,7 +2735,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->dir = dir; if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); - } else {// 'floating' shop? + } else {// 'floating' shop map->addiddb(&nd->bl); } strdb_put(npc->name_db, nd->exname, nd); @@ -2743,8 +2774,7 @@ void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath } // Skip the contents of a script. -const char* npc_skip_script(const char* start, const char* buffer, const char* filepath) -{ +const char* npc_skip_script(const char* start, const char* buffer, const char* filepath, int *retval) { const char* p; int curly_count; @@ -2753,9 +2783,9 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f // initial bracket (assumes the previous part is ok) p = strchr(start,'{'); - if( p == NULL ) - { + if( p == NULL ) { ShowError("npc_skip_script: Missing left curly in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue } @@ -2775,16 +2805,15 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f {// string for( ++p; *p != '"' ; ++p ) { - if( *p == '\\' && (unsigned char)p[-1] <= 0x7e ) + if( *p == '\\' && (unsigned char)p[-1] <= 0x7e ) { ++p;// escape sequence (not part of a multibyte character) - else if( *p == '\0' ) - { + } else if( *p == '\0' ) { script->error(buffer, filepath, 0, "Unexpected end of string.", p); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue - } - else if( *p == '\n' ) - { + } else if( *p == '\n' ) { script->error(buffer, filepath, 0, "Unexpected newline at string.", p); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue } } @@ -2792,6 +2821,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f else if( *p == '\0' ) {// end of buffer ShowError("Missing %d right curlys in file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer)); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue } } @@ -2804,7 +2834,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f /// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} -const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options) { +const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) { int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov char mapname[32]; struct script_code *scriptroot; @@ -2824,6 +2854,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* } else {// npc in a map if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ) { ShowError("npc_parse_script: Invalid placement format for a script in file '%s', line '%d'. Skipping the rest of file...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return NULL;// unknown format, don't continue } m = map->mapname2mapid(mapname); @@ -2834,15 +2865,16 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* 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); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue } ++script_start; - end = npc->skip_script(script_start, buffer, filepath); + end = npc->skip_script(script_start, buffer, filepath, retval); if( end == NULL ) return NULL;// (simple) parse error, don't continue - scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB); + scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB, retval); label_list = NULL; label_list_num = 0; if( script->label_count ) { @@ -2906,6 +2938,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* if (npc->event_export(nd, i)) { ShowWarning("npc_parse_script: duplicate event %s::%s in file '%s'.\n", nd->exname, nd->u.scr.label_list[i].name, filepath); + if (retval) *retval = EXIT_FAILURE; } npc->timerevent_export(nd, i); } @@ -2935,8 +2968,8 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* /// shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id> /// npc: -%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> /// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> -const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +/// !!Only NPO_ONINIT is available trough options!! +const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) { int x, y, dir, m, xs = -1, ys = -1; char mapname[32]; char srcname[128]; @@ -2956,6 +2989,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) ) {// does not match 'duplicate(%127s)', name is empty or too long ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), w2); + if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } safestrncpy(srcname, w2+10, length-10); @@ -2963,6 +2997,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch dnd = npc->name2id(srcname); if( dnd == NULL) { ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), srcname); + if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } src_id = dnd->bl.id; @@ -2978,6 +3013,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch dir = 0; } else if( fields != 4 ) {// <map name>,<x>,<y>,<facing> ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } m = map->mapname2mapid(mapname); @@ -2985,6 +3021,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) { ShowError("npc_parse_duplicate: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return end;//try next } @@ -2992,6 +3029,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY> else if( type == WARP ) { ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } @@ -3068,12 +3106,27 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if (npc->event_export(nd, i)) { ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n", nd->exname, nd->u.scr.label_list[i].name, filepath); + if (retval) *retval = EXIT_FAILURE; } npc->timerevent_export(nd, i); } nd->u.scr.timerid = INVALID_TIMER; + if( type == SCRIPT && options&NPO_ONINIT ) { + // From npc_parse_script + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev; + + snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname); + + 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); + + } + } return end; } @@ -3137,7 +3190,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { else snprintf(w4, sizeof(w4), "%d", snd->class_); - npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING"); + npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE, NULL); } return 0; @@ -3315,7 +3368,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c } } - script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)__64BPTRSIZE(j), NULL); + script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(j), NULL); aFree(temp); script->run_main(st); @@ -3324,8 +3377,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c /// Parses a function. /// function%TAB%script%TAB%<function name>%TAB%{<code>} -const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) { DBMap* func_db; DBData old_data; struct script_code *scriptroot; @@ -3334,18 +3386,18 @@ const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const cha script_start = strstr(start,"\t{"); end = strchr(start,'\n'); - if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) - { + if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) { ShowError("npc_parse_function: Missing left curly '%%TAB%%{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return NULL;// can't continue } ++script_start; - end = npc->skip_script(script_start,buffer,filepath); + end = npc->skip_script(script_start,buffer,filepath, retval); if( end == NULL ) return NULL;// (simple) parse error, don't continue - scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT); + scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT, retval); if( scriptroot == NULL )// parse error, continue return end; @@ -3379,7 +3431,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn) } } -const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { +const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) { int num, class_, m,x,y,xs,ys, i,j; int mob_lv = -1, ai = -1, size = -1; char mapname[32], mobname[NAME_LENGTH]; @@ -3398,10 +3450,12 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2 ) { ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } if( mapindex->name2id(mapname) == 0 ) { ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } m = map->mapname2mapid(mapname); @@ -3411,32 +3465,38 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st if( x < 0 || x >= map->list[mobspawn.m].xs || y < 0 || y >= map->list[mobspawn.m].ys ) { ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s in file '%s', line '%d'.\n", map->list[mobspawn.m].name, x, y, (map->list[mobspawn.m].xs-1), (map->list[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } // check monster ID if exists! if( mob->db_checkid(class_) == 0 ) { ShowError("npc_parse_mob: Unknown mob ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } if( num < 1 || num > 1000 ) { ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] in file '%s', line '%d'.\n", num, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) { ShowError("npc_parse_mob: Invalid size number %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start, '\n'); } if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && 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'); } if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) { ShowError("npc_parse_mob: Invalid level %d for mob ID %d in file '%s', line '%d'.\n", mob_lv, class_, filepath, strline(buffer, start - buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start, '\n'); } @@ -3467,6 +3527,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st if(mobspawn.delay1>0xfffffff || mobspawn.delay2>0xfffffff) { ShowError("npc_parse_mob: Invalid spawn delays %u %u in file '%s', line '%d'.\n", mobspawn.delay1, mobspawn.delay2, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } @@ -3481,6 +3542,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st //Verify dataset. if( !mob->parse_dataset(&mobspawn) ) { ShowError("npc_parse_mob: Invalid dataset for monster ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } @@ -3540,7 +3602,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st * eg : bat_c01 mapflag battleground 2 * also chking if mapflag conflict with another *------------------------------------------*/ -const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { +const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) { int16 m; char mapname[32]; int state = 1; @@ -3549,11 +3611,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char if( sscanf(w1, "%31[^,]", mapname) != 1 ) { ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } m = map->mapname2mapid(mapname); if( m < 0 ) { ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');// skip and continue } @@ -3575,6 +3639,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].save.y = savey; if (!map->list[m].save.map) { ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found in file '%s', line '%d', using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + if (retval) *retval = EXIT_FAILURE; map->list[m].save.x = -1; map->list[m].save.y = -1; } @@ -3613,10 +3678,12 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].flag.gvg_dungeon = 0; map->list[m].flag.gvg_castle = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } if( state && map->list[m].flag.battleground ) { map->list[m].flag.battleground = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s 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 ) { map->zone_change(m,zone,start,buffer,filepath); @@ -3663,10 +3730,12 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char if( state && map->list[m].flag.pvp ) { map->list[m].flag.pvp = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } if( state && map->list[m].flag.battleground ) { map->list[m].flag.battleground = 0; ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s 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 ) { map->zone_change(m,zone,start,buffer,filepath); @@ -3695,12 +3764,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char if( map->list[m].flag.battleground && map->list[m].flag.pvp ) { map->list[m].flag.pvp = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } if( map->list[m].flag.battleground && (map->list[m].flag.gvg || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg_castle) ) { map->list[m].flag.gvg = 0; map->list[m].flag.gvg_dungeon = 0; map->list[m].flag.gvg_castle = 0; ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s 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 ) { @@ -3803,10 +3874,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char 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; } else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) { ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } else { int idx = map->list[m].unit_count; @@ -3859,10 +3933,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char 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; } else if( !( skill_id = skill->name2id(skill_name) ) ) { ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", skill_name, map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; } else { int idx = map->list[m].skill_count; @@ -3901,6 +3978,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char 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; } else if( map->list[m].zone != zone ) { map->zone_change(m,zone,start,buffer,filepath); } @@ -3924,15 +4002,25 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].flag.src4instance = (state) ? 1 : 0; } else if ( !strcmpi(w3,"nocashshop") ) { map->list[m].flag.nocashshop = (state) ? 1 : 0; - } else + } else { ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer)); + if (retval) *retval = EXIT_FAILURE; + } return strchr(start,'\n');// continue } -//Read file and create npc/func/mapflag/monster... accordingly. -//@runOnInit should we exec OnInit when it's done ? +/** + * Parses a script file and creates NPCs/functions/mapflags/monsters/etc + * accordingly. + * + * @param filepath File name and path. + * @param runOnInit Whether the OnInit label should be called. + * @retval EXIT_SUCCESS if filepath was loaded correctly. + * @retval EXIT_FAILURE if there were errors/warnings when loading filepath. + */ int npc_parsesrcfile(const char* filepath, bool runOnInit) { + int success = EXIT_SUCCESS; int16 m, x, y; int lines = 0; FILE* fp; @@ -3942,10 +4030,9 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { // read whole file to buffer fp = fopen(filepath, "rb"); - if( fp == NULL ) - { + if( fp == NULL ) { ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath); - return -1; + return EXIT_FAILURE; } fseek(fp, 0, SEEK_END); len = ftell(fp); @@ -3953,12 +4040,11 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { fseek(fp, 0, SEEK_SET); len = fread(buffer, sizeof(char), len, fp); buffer[len] = '\0'; - if( ferror(fp) ) - { + if( ferror(fp) ) { ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno)); aFree(buffer); fclose(fp); - return -1; + return EXIT_FAILURE; } fclose(fp); @@ -3971,12 +4057,11 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { ShowError("npc_parsesrcfile: Detected unsupported UTF-8 BOM in file '%s'. Stopping (please consider using another character set.)\n", filepath); aFree(buffer); fclose(fp); - return -1; + return EXIT_FAILURE; } // parse buffer - for( p = script->skip_space(buffer); p && *p ; p = script->skip_space(p) ) - { + for( p = script->skip_space(buffer); p && *p ; p = script->skip_space(p) ) { int pos[9]; char w1[2048], w2[2048], w3[2048], w4[2048]; int i, count; @@ -3987,41 +4072,50 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { if( count < 0 ) { ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer)); + success = EXIT_FAILURE; break; } // fill w1 - if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 ) + if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 ) { ShowWarning("npc_parsesrcfile: w1 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[3]-pos[2], filepath, strline(buffer,p-buffer)); + success = EXIT_FAILURE; + } i = min(pos[3]-pos[2], ARRAYLENGTH(w1)-1); memcpy(w1, p+pos[2], i*sizeof(char)); w1[i] = '\0'; // fill w2 - if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 ) + if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 ) { ShowWarning("npc_parsesrcfile: w2 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[5]-pos[4], filepath, strline(buffer,p-buffer)); + success = EXIT_FAILURE; + } i = min(pos[5]-pos[4], ARRAYLENGTH(w2)-1); memcpy(w2, p+pos[4], i*sizeof(char)); w2[i] = '\0'; // fill w3 - if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 ) + if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 ) { ShowWarning("npc_parsesrcfile: w3 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[7]-pos[6], filepath, strline(buffer,p-buffer)); + success = EXIT_FAILURE; + } i = min(pos[7]-pos[6], ARRAYLENGTH(w3)-1); memcpy(w3, p+pos[6], i*sizeof(char)); w3[i] = '\0'; // fill w4 (to end of line) - if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 ) + if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 ) { ShowWarning("npc_parsesrcfile: w4 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[1]-pos[8], filepath, strline(buffer,p-buffer)); - if( pos[8] != -1 ) - { + success = EXIT_FAILURE; + } + if( pos[8] != -1 ) { i = min(pos[1]-pos[8], ARRAYLENGTH(w4)-1); memcpy(w4, p+pos[8], i*sizeof(char)); w4[i] = '\0'; - } - else + } else { w4[0] = '\0'; + } - if( count < 3 ) - {// Unknown syntax + if( count < 3 ) { + // Unknown syntax ShowError("npc_parsesrcfile: Unknown syntax in file '%s', line '%d'. Stopping...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); + success = EXIT_FAILURE; break; } @@ -4030,13 +4124,12 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { char mapname[MAP_NAME_LENGTH*2]; x = y = 0; sscanf(w1,"%23[^,],%hd,%hd[^,]",mapname,&x,&y); - if( !mapindex->name2id(mapname) ) - {// Incorrect map, we must skip the script info... + if( !mapindex->name2id(mapname) ) { + // Incorrect map, we must skip the script info... ShowError("npc_parsesrcfile: Unknown map '%s' in file '%s', line '%d'. Skipping line...\n", mapname, filepath, strline(buffer,p-buffer)); - if( strcmp(w2,"script") == 0 && count > 3 ) - { - if((p = npc->skip_script(p,buffer,filepath)) == NULL) - { + success = EXIT_FAILURE; + if( strcmp(w2,"script") == 0 && count > 3 ) { + if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) { break; } } @@ -4046,10 +4139,8 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { m = map->mapname2mapid(mapname); if( m < 0 ) { // "mapname" is not assigned to this server, we must skip the script info... - if( strcmp(w2,"script") == 0 && count > 3 ) - { - if((p = npc->skip_script(p,buffer,filepath)) == NULL) - { + if( strcmp(w2,"script") == 0 && count > 3 ) { + if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) { break; } } @@ -4058,10 +4149,9 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { } if (x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys) { ShowError("npc_parsesrcfile: Unknown coordinates ('%d', '%d') for map '%s' in file '%s', line '%d'. Skipping line...\n", x, y, mapname, filepath, strline(buffer,p-buffer)); - if( strcmp(w2,"script") == 0 && count > 3 ) - { - if((p = npc->skip_script(p,buffer,filepath)) == NULL) - { + success = EXIT_FAILURE; + if( strcmp(w2,"script") == 0 && count > 3 ) { + if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) { break; } } @@ -4070,39 +4160,44 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { } } - if( strcmp(w2,"warp") == 0 && count > 3 ) + if( strcmp(w2,"mapflag") == 0 && count >= 3 ) { - p = npc->parse_warp(w1,w2,w3,w4, p, buffer, filepath); + p = npc->parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath, &success); } - else if( (strcmp(w2,"shop") == 0 || strcmp(w2,"cashshop") == 0) && count > 3 ) - { - p = npc->parse_shop(w1,w2,w3,w4, p, buffer, filepath); + else if( count == 3 ) { + ShowError("npc_parsesrcfile: Unable to parse, probably a missing TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); + p = strchr(p,'\n');// skip and continue + success = EXIT_FAILURE; } - else if( strcmp(w2,"script") == 0 && count > 3 ) + else if( strcmp(w2,"script") == 0 ) { if( strcmp(w1,"function") == 0 ) { - p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath); + p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath, &success); } else { #ifdef ENABLE_CASE_CHECK if( strcasecmp(w1, "function") == 0 ) DeprecationWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO #endif // ENABLE_CASE_CHECK - p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE); + p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE, &success); } } - else if( strcmp(w2,"trader") == 0 && count > 3 ) { - p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER); + else if( strcmp(w2,"trader") == 0 ) { + p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER, &success); + } + else if( strcmp(w2,"warp") == 0 ) + { + p = npc->parse_warp(w1,w2,w3,w4, p, buffer, filepath, &success); } - else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 ) + else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) ) { - p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath); + p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE), &success); } - else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) && count > 3 ) + else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) ) { - p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath); + p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath, &success); } - else if( strcmp(w2,"mapflag") == 0 && count >= 3 ) + else if( (strcmp(w2,"shop") == 0 || strcmp(w2,"cashshop") == 0) ) { - p = npc->parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath); + p = npc->parse_shop(w1,w2,w3,w4, p, buffer, filepath, &success); } else { @@ -4124,11 +4219,12 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { #endif // ENABLE_CASE_CHECK ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); p = strchr(p,'\n');// skip and continue + success = EXIT_FAILURE; } } aFree(buffer); - return 0; + return success; } int npc_script_event(struct map_session_data* sd, enum npce_event type) @@ -4227,14 +4323,39 @@ int npc_ev_label_db_clear_sub(DBKey key, DBData *data, va_list args) return 0; } +/** + * Main npc file processing + * @param npc_min Minimum npc id - used to know how many NPCs were loaded + **/ +void npc_process_files( int npc_min ) { + struct npc_src_list *file; // Current file + + ShowStatus("Loading NPCs...\r"); + for( file = npc->src_files; file != NULL; file = file->next ) { + ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); + if (npc->parsesrcfile(file->name, false) != EXIT_SUCCESS) + map->retval = EXIT_FAILURE; + } + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", + npc_id - npc_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); +} + //Clear then reload npcs files int npc_reload(void) { - struct npc_src_list *nsl; int16 m, i; int npc_new_min = npc_id; struct s_mapiterator* iter; struct block_list* bl; + if (map->retval == EXIT_FAILURE) + map->retval = EXIT_SUCCESS; // Clear return status in case something failed before. + /* clear guild flag cache */ guild->flags_clear(); @@ -4291,46 +4412,35 @@ int npc_reload(void) { // reset mapflags map->flags_init(); - //TODO: the following code is copy-pasted from do_init_npc(); clean it up - // Reloading npcs now - for (nsl = npc->src_files; nsl; nsl = nsl->next) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name); - npc->parsesrcfile(nsl->name,false); - } - ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - + // Reprocess npc files and reload constants itemdb->name_constants(); - + npc_process_files( npc_new_min ); + instance->reload(); map->zone_init(); - + npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */ - + //Re-read the NPC Script Events cache. npc->read_event_script(); - /* refresh guild castle flags on both woe setups */ - npc->event_doall("OnAgitInit"); - npc->event_doall("OnAgitInit2"); - - //Execute the OnInit event for freshly loaded npcs. [Skotlex] - ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc->event_doall("OnInit")); - - npc->market_fromsql();/* after OnInit */ - + // Execute main initialisation events + // The correct initialisation order is: + // OnInit -> OnInterIfInit -> OnInterIfInitOnce -> OnAgitInit -> OnAgitInit2 + npc->event_do_oninit( true ); + npc->market_fromsql(); // Execute rest of the startup events if connected to char-server. [Lance] - if(!intif->CheckForCharServer()){ + // Executed when connection is established with char-server in chrif_connectack + if( !intif->CheckForCharServer() ) { ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInit")); ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInitOnce")); } + // Refresh guild castle flags on both woe setups + // These events are only executed after receiving castle information from char-server + npc->event_doall("OnAgitInit"); + npc->event_doall("OnAgitInit2"); + return 0; } @@ -4412,7 +4522,6 @@ static void npc_debug_warps(void) { * npc initialization *------------------------------------------*/ int do_init_npc(bool minimal) { - struct npc_src_list *file; int i; memset(&npc->base_ud, 0, sizeof( struct unit_data) ); @@ -4441,28 +4550,17 @@ int do_init_npc(bool minimal) { npc_last_npd = NULL; npc_last_path = NULL; npc_last_ref = NULL; - + + // Should be loaded before npc processing, otherwise labels could overwrite constant values + // and lead to undefined behavior [Panikon] + itemdb->name_constants(); + if (!minimal) { npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE); - // process all npc files - ShowStatus("Loading NPCs...\r"); - for( file = npc->src_files; file != NULL; file = file->next ) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); - npc->parsesrcfile(file->name,false); - } - ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + npc_process_files(START_NPC_NUM); } - itemdb->name_constants(); - if (!minimal) { map->zone_init(); diff --git a/src/map/npc.h b/src/map/npc.h index 346a9f8c0..4c904e1ac 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -2,16 +2,16 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_NPC_H_ -#define _MAP_NPC_H_ +#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" struct HPluginData; -struct block_list; -struct npc_data; struct view_data; enum npc_parse_options { @@ -121,7 +121,7 @@ enum actor_classes { #define MAX_NPC_CLASS 1000 // New NPC range #define MAX_NPC_CLASS2_START 10000 -#define MAX_NPC_CLASS2_END 10070 +#define MAX_NPC_CLASS2_END 10110 //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) @@ -193,7 +193,7 @@ struct npc_interface { int (*event_doall_id) (const char *name, int rid); int (*event_doall) (const char *name); int (*event_do_clock) (int tid, int64 tick, int id, intptr_t data); - void (*event_do_oninit) (void); + void (*event_do_oninit) ( bool reload ); int (*timerevent_export) (struct npc_data *nd, int i); int (*timerevent) (int tid, int64 tick, int id, intptr_t data); int (*timerevent_start) (struct npc_data *nd, int rid); @@ -232,12 +232,12 @@ struct npc_interface { int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath); bool (*viewisid) (const char *viewid); struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); - const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); - const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); + const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); + const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath); - const char* (*skip_script) (const char *start, const char *buffer, const char *filepath); - const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options); - const char* (*parse_duplicate) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); + const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval); + const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval); + const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval); int (*duplicate4instance) (struct npc_data *snd, int16 m); void (*setcells) (struct npc_data *nd); int (*unsetcells_sub) (struct block_list *bl, va_list ap); @@ -246,10 +246,10 @@ struct npc_interface { void (*setdisplayname) (struct npc_data *nd, const char *newname); void (*setclass) (struct npc_data *nd, short class_); int (*do_atcmd_event) (struct map_session_data *sd, const char *command, const char *message, const char *eventname); - const char* (*parse_function) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); + const char* (*parse_function) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); void (*parse_mob2) (struct spawn_data *mobspawn); - const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); - const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath); + const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); + const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); int (*parsesrcfile) (const char *filepath, bool runOnInit); int (*script_event) (struct map_session_data *sd, enum npce_event type); void (*read_event_script) (void); @@ -347,4 +347,4 @@ struct pcre_interface *libpcre; void npc_chat_defaults(void); #endif -#endif /* _MAP_NPC_H_ */ +#endif /* MAP_NPC_H */ diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 9d5639efc..8bc246819 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -2,25 +2,27 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifdef PCRE_SUPPORT +#define HERCULES_CORE -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" +#ifdef PCRE_SUPPORT -#include "mob.h" // struct mob_data #include "npc.h" // struct npc_data -#include "pc.h" // struct map_session_data -#include "script.h" // set_var() - -#include "../../3rdparty/pcre/include/pcre.h" +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdarg.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 @@ -47,7 +49,7 @@ struct pcre_interface libpcre_s; * * defpattern 1, "[^:]+: (.*) loves (.*)", "label"; * - * this defines a new pattern in set 1 using perl syntax + * this defines a new pattern in set 1 using perl syntax * (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm) * and tells it to jump to the supplied label when the pattern * is matched. @@ -57,7 +59,7 @@ struct pcre_interface libpcre_s; * before the script gets executed. * * activatepset 1; - * + * * This activates a set of patterns.. You can have many pattern * sets defined and many active all at once. This feature allows * you to set up "conversations" and ever changing expectations of @@ -78,7 +80,7 @@ struct pcre_interface libpcre_s; /** - * delete everythign associated with a entry + * delete everything associated with a entry * * This does NOT do the list management */ @@ -93,11 +95,10 @@ void finalize_pcrematch_entry(struct pcrematch_entry* e) /** * Lookup (and possibly create) a new set of patterns by the set id */ -struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) -{ +struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) { struct pcrematch_set *pcreset; struct npc_parse *npcParse = nd->chatdb; - if (npcParse == NULL) + if (npcParse == NULL) nd->chatdb = npcParse = (struct npc_parse *)aCalloc(sizeof(struct npc_parse), 1); pcreset = npcParse->active; @@ -107,7 +108,7 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) break; pcreset = pcreset->next; } - if (pcreset == NULL) + if (pcreset == NULL) pcreset = npcParse->inactive; while (pcreset != NULL) { @@ -138,7 +139,7 @@ void activate_pcreset(struct npc_data* nd, int setid) { struct pcrematch_set *pcreset; struct npc_parse *npcParse = nd->chatdb; - if (npcParse == NULL) + if (npcParse == NULL) return; // Nothing to activate... pcreset = npcParse->inactive; while (pcreset != NULL) { @@ -152,7 +153,7 @@ void activate_pcreset(struct npc_data* nd, int setid) pcreset->next->prev = pcreset->prev; if (pcreset->prev != NULL) pcreset->prev->next = pcreset->next; - else + else npcParse->inactive = pcreset->next; pcreset->prev = NULL; @@ -171,7 +172,7 @@ void deactivate_pcreset(struct npc_data* nd, int setid) { struct pcrematch_set *pcreset; struct npc_parse *npcParse = nd->chatdb; - if (npcParse == NULL) + if (npcParse == NULL) return; // Nothing to deactivate... if (setid == -1) { while(npcParse->active != NULL) @@ -190,7 +191,7 @@ void deactivate_pcreset(struct npc_data* nd, int setid) pcreset->next->prev = pcreset->prev; if (pcreset->prev != NULL) pcreset->prev->next = pcreset->next; - else + else npcParse->active = pcreset->next; pcreset->prev = NULL; @@ -208,7 +209,7 @@ void delete_pcreset(struct npc_data* nd, int setid) int active = 1; struct pcrematch_set *pcreset; struct npc_parse *npcParse = nd->chatdb; - if (npcParse == NULL) + if (npcParse == NULL) return; // Nothing to deactivate... pcreset = npcParse->active; while (pcreset != NULL) { @@ -225,7 +226,7 @@ void delete_pcreset(struct npc_data* nd, int setid) pcreset = pcreset->next; } } - if (pcreset == NULL) + if (pcreset == NULL) return; if (pcreset->next != NULL) @@ -244,7 +245,7 @@ void delete_pcreset(struct npc_data* nd, int setid) while (pcreset->head) { struct pcrematch_entry* n = pcreset->head->next; npc_chat->finalize_pcrematch_entry(pcreset->head); - aFree(pcreset->head); // Cleanin' the last ones.. [Lance] + aFree(pcreset->head); // Cleaning the last ones.. [Lance] pcreset->head = n; } @@ -252,7 +253,7 @@ void delete_pcreset(struct npc_data* nd, int setid) } /** - * create a new pattern entry + * create a new pattern entry */ struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set) { @@ -298,9 +299,9 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c /** * Delete everything associated with a NPC concerning the pattern - * matching code + * matching code * - * this could be more efficent but.. how often do you do this? + * this could be more efficient but.. how often do you do this? */ void npc_chat_finalize(struct npc_data* nd) { @@ -343,10 +344,10 @@ int npc_chat_sub(struct block_list* bl, va_list ap) // iterate across all active sets for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next) { - // interate across all patterns in that set + // n across all patterns in that set for (e = pcreset->head; e != NULL; e = e->next) { - int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec + 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)); @@ -379,7 +380,7 @@ int npc_chat_sub(struct block_list* bl, va_list ap) return 0; } -// Various script builtins used to support these functions +// Various script built-ins used to support these functions BUILDIN(defpattern) { int setid = script_getnum(st,2); const char* pattern = script_getstr(st,3); diff --git a/src/map/packets.h b/src/map/packets.h index 1be5d2dbe..810f341d4 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -3,8 +3,8 @@ //Included directly by clif.h in packet_loaddb() -#ifndef _MAP_PACKETS_H_ -#define _MAP_PACKETS_H_ +#ifndef MAP_PACKETS_H +#define MAP_PACKETS_H #ifndef packet #define packet(a,b,...) @@ -2453,6 +2453,43 @@ packet(0x020d,-1); packet(0x0887,36,clif->pStoragePassword,0); #endif +//2013-08-14aRagexe - Themon +#if PACKETVER >= 20130814 + packet(0x0874,7,clif->pActionRequest,2,6); + packet(0x0947,10,clif->pUseSkillToId,2,4,6); + packet(0x093A,5,clif->pWalkToXY,2); + packet(0x088A,6,clif->pTickSend,2); + packet(0x088C,5,clif->pChangeDir,2,4); + packet(0x0926,6,clif->pTakeItem,2); + packet(0x095F,6,clif->pDropItem,2,4); + packet(0x0202,8,clif->pMoveToKafra,2,4); + packet(0x0873,8,clif->pMoveFromKafra,2,4); + packet(0x0887,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0962,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x0937,6,clif->pGetCharNameRequest,2); + packet(0x0923,6,clif->pSolveCharName,2); + packet(0x0868,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0941,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0889,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0835,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0895,6,clif->pReqClickBuyingStore,2); + packet(0x094E,2,clif->pReqCloseBuyingStore,0); + packet(0x0936,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); +#ifdef PACKETVER_RE + packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4); +#else // not PACKETVER_RE + packet(0x0959,18,clif->pPartyBookingRegisterReq,2,4); +#endif // PACKETVER_RE + // packet(0x0896,8); // CZ_JOIN_BATTLE_FIELD + packet(0x08A4,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0368,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0927,26,clif->pPartyInvite2,2); + // packet(0x0815,4); // CZ_GANGSI_RANK + packet(0x0281,26,clif->pFriendsListAdd,2); + packet(0x0958,5,clif->pHomMenu,2,4); + packet(0x0885,36,clif->pStoragePassword,0); +#endif + // 2013-12-18bRagexe - Yommy #if PACKETVER >= 20131218 packet(0x0369,7,clif->pActionRequest,2,6); @@ -2559,6 +2596,177 @@ packet(0x020d,-1); packet(0x091D,36,clif->pStoragePassword,0); #endif +// 2014 Packet Data + +// 2014-01-15eRagexe - YomRawr +#if PACKETVER >= 20140115 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x08A7,5,clif->pChangeDir,2,4); + packet(0x0940,6,clif->pTakeItem,2); + packet(0x0361,6,clif->pDropItem,2,4); + packet(0x088E,8,clif->pMoveToKafra,2,4); + packet(0x0367,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x0802,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0360,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0817,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0815,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x096A,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x088A,6,clif->pReqClickBuyingStore,2); + packet(0x0965,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x096A,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x088A,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0965,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0966,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x095D,26,clif->pPartyInvite2,2); + // packet(0x095B,4); // CZ_GANGSI_RANK + packet(0x089B,26,clif->pFriendsListAdd,2); + packet(0x092D,5,clif->pHomMenu,2,4); + packet(0x0865,36,clif->pStoragePassword,0); +#endif + +// 2014-02-05bRagexe - Themon +#if PACKETVER >= 20140205 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0202,5,clif->pChangeDir,2,4); + packet(0x07E4,6,clif->pTakeItem,2); + packet(0x0362,6,clif->pDropItem,2,4); + packet(0x07EC,8,clif->pMoveToKafra,2,4); + packet(0x0364,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0802,26,clif->pPartyInvite2,2); + // packet(0x0436,4); // CZ_GANGSI_RANK + packet(0x023B,26,clif->pFriendsListAdd,2); + packet(0x0361,5,clif->pHomMenu,2,4); + packet(0x0938,36,clif->pStoragePassword,0); + packet(0x09DF,7); +#endif + +// 2014-03-05bRagexe - Themon +#if PACKETVER >= 20140305 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0815,5,clif->pChangeDir,2,4); + packet(0x0202,6,clif->pTakeItem,2); + packet(0x0362,6,clif->pDropItem,2,4); + packet(0x07EC,8,clif->pMoveToKafra,2,4); + packet(0x0364,8,clif->pMoveFromKafra,2,4); + packet(0x0436,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0361,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0438,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0802,26,clif->pPartyInvite2,2); + // packet(0x0878,4); // CZ_GANGSI_RANK + packet(0x07E4,26,clif->pFriendsListAdd,2); + packet(0x0934,5,clif->pHomMenu,2,4); + packet(0x095e,36,clif->pStoragePassword,0); + packet(0x09DF,7); +#endif + +// 2014-04-02gRagexe - Themon +#if PACKETVER >= 20140402 + packet(0x0946,7,clif->pActionRequest,2,6); + packet(0x0868,10,clif->pUseSkillToId,2,4,6); + packet(0x093F,5,clif->pWalkToXY,2); + packet(0x0950,6,clif->pTickSend,2); + packet(0x0360,5,clif->pChangeDir,2,4); + packet(0x0958,6,clif->pTakeItem,2); + packet(0x0882,6,clif->pDropItem,2,4); + packet(0x095C,8,clif->pMoveToKafra,2,4); + packet(0x085B,8,clif->pMoveFromKafra,2,4); + packet(0x0364,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x092D,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x088A,6,clif->pGetCharNameRequest,2); + packet(0x07EC,6,clif->pSolveCharName,2); + packet(0x0965,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x085D,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0933,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x091F,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x023B,6,clif->pReqClickBuyingStore,2); + packet(0x0867,2,clif->pReqCloseBuyingStore,0); + packet(0x0944,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x08AC,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x094C,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0883,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0920,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0890,26,clif->pPartyInvite2,2); + // packet(0x088C,4); // CZ_GANGSI_RANK + packet(0x089A,26,clif->pFriendsListAdd,2); + packet(0x0896,5,clif->pHomMenu,2,4); + packet(0x0926,36,clif->pStoragePassword,0); + packet(0x09DF,7); +#endif + +// 2014-04-16aRagexe - Themon +#if PACKETVER >= 20140416 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0202,5,clif->pChangeDir,2,4); + packet(0x07E4,6,clif->pTakeItem,2); + packet(0x0362,6,clif->pDropItem,2,4); + packet(0x07EC,8,clif->pMoveToKafra,2,4); + packet(0x0364,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4); + // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0802,26,clif->pPartyInvite2,2); + // packet(0x0436,4); // CZ_GANGSI_RANK + packet(0x023B,26,clif->pFriendsListAdd,2); + packet(0x0361,5,clif->pHomMenu,2,4); + packet(0x095C,36,clif->pStoragePassword,0); + packet(0x09DF,7); +#endif + /* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ #if PACKETVER >= 20110817 packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */ @@ -2752,6 +2960,10 @@ packet(0x020d,-1); packetKeys(0x7E241DE0,0x5E805580,0x3D807D80); /* Thanks to Shakto */ #endif +#if PACKETVER >= 20130814 + packetKeys(0x23A23148,0x0C41420E,0x53785AD7); /* Themon */ +#endif + #if PACKETVER >= 20131218 packetKeys(0x6A596301,0x76866D0E,0x32294A45); #endif @@ -2764,8 +2976,30 @@ packet(0x020d,-1); packetKeys(0x611B7097,0x01F957A1,0x768A0FCB); #endif +// 2014 Packet Keys + +#if PACKETVER >= 20140115 + packetKeys(0x63224335,0x0F3A1F27,0x6D217B24); /* Thanks to Yommy */ +#endif + +#if PACKETVER >= 20140205 + packetKeys(0x63DC7BDC,0x7BDC7BDC,0x7BDC7BDC); /* Themon */ +#endif + +#if PACKETVER >= 20140305 + packetKeys(0x116763F2,0x41117DAC,0x7FD13C45); /* Themon */ +#endif + +#if PACKETVER >= 20140402 + packetKeys(0x15D3271C,0x004D725B,0x111A3A37); /* Themon */ +#endif + +#if PACKETVER >= 20140416 + packetKeys(0x04810281,0x42814281,0x42814281); /* Themon */ +#endif + #if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3) packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3); #endif -#endif /* _MAP_PACKETS_H_ */ +#endif /* MAP_PACKETS_H */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 55006db64..55ab0c66a 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3,8 +3,8 @@ /* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */ -#ifndef _MAP_PACKETS_STRUCT_H_ -#define _MAP_PACKETS_STRUCT_H_ +#ifndef MAP_PACKETS_STRUCT_H +#define MAP_PACKETS_STRUCT_H #include "../common/mmo.h" @@ -596,7 +596,7 @@ struct packet_status_change { #if PACKETVER >= 20120618 unsigned int Total; #endif -#if PACKETVER >= 20090121 +#if PACKETVER >= 20090121 unsigned int Left; int val1; int val2; @@ -943,6 +943,9 @@ struct packet_npc_market_open { unsigned int price; unsigned int qty; unsigned short view; + // It seems that the client doesn't have any hard-coded limit for this list + // it's possible to send up to 1890 items without dropping a packet that's + // too large [Panikon] } list[1000];/* TODO: whats the actual max of this? */ } __attribute__((packed)); @@ -959,4 +962,4 @@ struct packet_wis_end { #pragma pack(pop) #endif // not NetBSD < 6 / Solaris -#endif /* _MAP_PACKETS_STRUCT_H_ */ +#endif /* MAP_PACKETS_STRUCT_H */ diff --git a/src/map/party.c b/src/map/party.c index cf5e7bbe3..7cf340edb 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -2,34 +2,37 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/socket.h" // last_tick -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/utils.h" -#include "../common/strlib.h" -#include "../common/HPM.h" +#define HERCULES_CORE +#include "../config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP #include "party.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + #include "atcommand.h" //msg_txt() -#include "pc.h" -#include "map.h" -#include "instance.h" #include "battle.h" -#include "intif.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 "itemdb.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.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; @@ -210,7 +213,7 @@ void party_check_state(struct party_data *p) { int i; memset(&p->state, 0, sizeof(p->state)); for (i = 0; i < MAX_PARTY; i ++) { - if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that. + if (!p->party.member[i].online) continue; //Those not online shouldn't apart to skill usage and all that. switch (p->party.member[i].class_) { case JOB_MONK: case JOB_BABY_MONK: @@ -1129,7 +1132,7 @@ int party_sub_count_chorus(struct block_list *bl, va_list ap) { * @param func Function to execute * @param sd Reference character for party, map, area center * @param range Area size (0 = whole map) - * @param ... Adidtional parameters to pass to func() + * @param ... Additional parameters to pass to func() * @return Sum of the return values from func() */ int party_foreachsamemap(int (*func)(struct block_list*,va_list), struct map_session_data *sd, int range, ...) { @@ -1361,7 +1364,7 @@ void do_init_party(bool minimal) { timer->add_interval(timer->gettick()+battle_config.party_update_interval, party->send_xy_timer, 0, 0, battle_config.party_update_interval); } /*===================================== -* Default Functions : party.h +* Default Functions : party.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/map/party.h b/src/map/party.h index ed8289af6..d62db23a7 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -2,14 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_PARTY_H_ -#define _MAP_PARTY_H_ +#ifndef MAP_PARTY_H +#define MAP_PARTY_H -#include "../common/mmo.h" // struct party -#include "../config/core.h" #include <stdarg.h> -#include "map.h" +#include "map.h" // TBL_PC +#include "../common/cbasetypes.h" +#include "../common/db.h" +#include "../common/mmo.h" // struct party #define PARTY_BOOKING_JOBS 6 #define PARTY_BOOKING_RESULTS 10 @@ -70,7 +71,7 @@ struct party_booking_ad_info { #endif /* PARTY_RECRUIT */ /*===================================== -* Interface : party.h +* Interface : party.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -142,4 +143,4 @@ struct party_interface *party; void party_defaults(void); -#endif /* _MAP_PARTY_H_ */ +#endif /* MAP_PARTY_H */ diff --git a/src/map/path.c b/src/map/path.c index ae9fc389d..e90b26db5 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -2,20 +2,23 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#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 HERCULES_CORE +#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA #include "path.h" -#include "map.h" #include <stdio.h> #include <stdlib.h> #include <string.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 @@ -202,7 +205,7 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16 if (g_cost < tp[i].g_cost) { // New path to this node is better than old one // Update costs and parent tp[i].g_cost = g_cost; - tp[i].parent = parent; + tp[i].parent = parent; tp[i].f_cost = g_cost + h_cost; if (tp[i].flag == SET_CLOSED) { heap_push_node(heap, &tp[i]); // Put it in open set again @@ -296,7 +299,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x return true; } - return false; // easy path unsuccessful + return false; // easy path unsuccessful } else { // !(flag&1) // A* (A-star) pathfinding diff --git a/src/map/path.h b/src/map/path.h index 0b67a0120..8d02e6558 100644 --- a/src/map/path.h +++ b/src/map/path.h @@ -2,10 +2,11 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_PATH_H_ -#define _MAP_PATH_H_ +#ifndef MAP_PATH_H +#define MAP_PATH_H #include "map.h" // enum cell_chk +#include "../common/cbasetypes.h" #define MOVE_COST 10 #define MOVE_DIAGONAL_COST 14 @@ -46,4 +47,4 @@ struct path_interface *path; void path_defaults(void); -#endif /* _MAP_PATH_H_ */ +#endif /* MAP_PATH_H */ diff --git a/src/map/pc.c b/src/map/pc.c index 848238ed2..8b84ee3bc 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -2,20 +2,16 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/core.h" // get_svn_revision() -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // session[] -#include "../common/strlib.h" // safestrncpy() -#include "../common/timer.h" -#include "../common/utils.h" -#include "../common/conf.h" -#include "../common/mmo.h" //NAME_LENGTH +#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 "pc.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" @@ -24,32 +20,40 @@ #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 "path.h" -#include "homunculus.h" -#include "instance.h" #include "mercenary.h" -#include "elemental.h" +#include "mob.h" // struct mob_data #include "npc.h" // fake_nd -#include "pet.h" // pet_unlocktarget() #include "party.h" // party->search() -#include "guild.h" // guild->search(), guild_request_info() +#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 "pc_groups.h" -#include "quest.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.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; @@ -1147,19 +1151,12 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim if( !changing_mapservers ) { if (battle_config.display_version == 1) { - const char* svn = get_svn_revision(); - const char* git = get_git_hash(); char buf[256]; - if( git[0] != HERC_UNKNOWN_VER ) - sprintf(buf,"Git Hash: %s", git); - else if( svn[0] != HERC_UNKNOWN_VER ) - sprintf(buf,"SVN Revision: %s", svn); - else - sprintf(buf,"Unknown Version"); + sprintf(buf, msg_txt(1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts) clif->message(sd->fd, buf); } - if (expiration_time != 0) { + if (expiration_time != 0) { sd->expiration_time = expiration_time; } @@ -1394,7 +1391,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) { switch( skill->db[i].nameid ) { case NV_TRICKDEAD: - if( (sd->class_&MAPID_BASEMASK) != MAPID_NOVICE ) { + if( (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; @@ -3998,10 +3995,10 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l sd->inventory_data[i] = data; clif->additem(sd,i,amount,0); } -#ifdef NSI_UNIQUE_ID + if( !itemdb->isstackable2(data) && !item_data->unique_id ) - sd->status.inventory[i].unique_id = itemdb->unique_id(0,0); -#endif + 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]); sd->weight += w; @@ -4194,7 +4191,7 @@ 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&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) { + 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)); return 0; // You cannot use this item while sitting. @@ -4387,6 +4384,7 @@ int pc_useitem(struct map_session_data *sd,int n) { if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING) return 0; + // Statuses that don't let the player use items if (sd->sc.count && ( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) || @@ -4399,6 +4397,7 @@ int pc_useitem(struct map_session_data *sd,int n) { sd->sc.data[SC_WHITEIMPRISON] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER] || + sd->sc.data[SC_COLD] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) )) return 0; @@ -4451,7 +4450,7 @@ int pc_useitem(struct map_session_data *sd,int n) { } } - /* on restricted maps the item is consumed but the effect is not used */ + /* 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 @@ -5944,9 +5943,9 @@ int pc_checkjoblevelup(struct map_session_data *sd) return 1; } -/*========================================== - * Alters experienced based on self bonuses that do not get even shared to the party. - *------------------------------------------*/ +/** + * Alters EXP based on self bonuses that do not get shared with the party + **/ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) { int bonus = 0; struct status_data *st = status->get_status_data(src); @@ -5977,19 +5976,23 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in return; } -/*========================================== - * Give x exp at sd player and calculate remaining exp for next lvl - *------------------------------------------*/ -int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool is_quest) { + +/** + * Gives a determined EXP amount to sd and calculates remaining EXP for next level + * @param src if is NULL no bonuses are taken into account + * @param is_quest Used to let client know that the EXP was from a quest (clif->displayexp) PACKETVER >= 20091027 + * @retval true success + **/ +bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool is_quest) { float nextbp=0, nextjp=0; unsigned int nextb=0, nextj=0; nullpo_ret(sd); if(sd->bl.prev == NULL || pc_isdead(sd)) - return 0; + return false; if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr] - return 0; // no exp on pvp maps + return false; // no exp on pvp maps if(sd->status.guild_id>0) base_exp-=guild->payexp(sd,base_exp); @@ -6021,7 +6024,8 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int } } - //Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex] + // Cap exp to the level up requirement of the previous level when you are at max level, + // otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex] if (base_exp) { nextb = nextb?UINT_MAX:pc->thisbaseexp(sd); if(sd->status.base_exp > nextb - base_exp) @@ -6056,7 +6060,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int clif_disp_onlyself(sd,output,strlen(output)); } - return 1; + return true; } /*========================================== @@ -6231,7 +6235,7 @@ int pc_maxparameterincrease(struct map_session_data* sd, int type) { * Subtracts status points according to the cost of the increased stat points. * * @param sd The target character. - * @param type The stat to change (see enum _sp) + * @param type The stat to change (see enum status_point_types) * @param increase The stat increase (strictly positive) amount. * @retval true if the stat was increased by any amount. * @retval false if there were no changes. @@ -6290,7 +6294,7 @@ bool pc_statusup(struct map_session_data* sd, int type, int increase) { * Does not subtract status points for the cost of the modified stat points. * * @param sd The target character. - * @param type The stat to change (see enum _sp) + * @param type The stat to change (see enum status_point_types) * @param val The stat increase (or decrease) amount. * @return the stat increase amount. * @retval 0 if no changes were made. @@ -6613,7 +6617,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd) ) //Remove perma blindness due to skill-reset. [Skotlex] clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1); i = sd->sc.option; - if( i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) ) + if( i&OPTION_RIDING && pc->checkskill(sd, KN_RIDING) ) i &= ~OPTION_RIDING; if( i&OPTION_FALCON && pc->checkskill(sd, HT_FALCON) ) i &= ~OPTION_FALCON; @@ -6652,14 +6656,14 @@ int pc_resetskill(struct map_session_data* sd, int flag) skill_id = skill->db[i].nameid; // Don't reset trick dead if not a novice/baby - if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_BASEMASK) != MAPID_NOVICE ) { + if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; continue; } // do not reset basic skill - if( skill_id == NV_BASIC && (sd->class_&MAPID_BASEMASK) != MAPID_NOVICE ) + if( skill_id == NV_BASIC && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) continue; if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) @@ -6691,6 +6695,21 @@ int pc_resetskill(struct map_session_data* sd, int flag) sd->status.skill_point += skill_point; + + if( !(flag&2) ) { + // 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); + if( sd->sc.data[SC_DOWNKICK_READY] ) + status_change_end(&sd->bl, SC_DOWNKICK_READY, INVALID_TIMER); + if( sd->sc.data[SC_TURNKICK_READY] ) + status_change_end(&sd->bl, SC_TURNKICK_READY, INVALID_TIMER); + if( sd->sc.data[SC_COUNTERKICK_READY] ) + status_change_end(&sd->bl, SC_COUNTERKICK_READY, INVALID_TIMER); + if( sd->sc.data[SC_DODGE_READY] ) + status_change_end(&sd->bl, SC_DODGE_READY, INVALID_TIMER); + } + if( flag&1 ) { clif->updatestatus(sd,SP_SKILLPOINT); clif->skillinfoblock(sd); @@ -6839,13 +6858,14 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { int i=0,j=0; int64 tick = timer->gettick(); - for(j = 0; j < 5; j++) + for(j = 0; j < 5; 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); sd->devotion[j] = 0; } + } if(sd->status.pet_id > 0 && sd->pd) { struct pet_data *pd = sd->pd; @@ -6860,7 +6880,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { } if (sd->status.hom_id > 0){ - if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE]) + if(battle_config.homunculus_auto_vapor && sd->hd) homun->vaporize(sd, HOM_ST_REST); } @@ -7143,6 +7163,17 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { } } } + + // Remove autotrade to prevent autotrading from save point + if( (sd->state.standalone || sd->state.autotrade) + && (map->list[sd->bl.m].flag.pvp || map->list[sd->bl.m].flag.gvg) + ) { + sd->state.autotrade = 0; + sd->state.standalone = 0; + pc->autotrade_update(sd,PAUC_REMOVE); + map->quit(sd); + } + // pvp // disable certain pvp functions on pk_mode [Valaris] if( map->list[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map->list[sd->bl.m].flag.pvp_nocalcrank ) { @@ -7172,10 +7203,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { } } - //Reset "can log out" tick. if( battle_config.prevent_logout ) sd->canlog_tick = timer->gettick() - battle_config.prevent_logout; + return 1; } @@ -7255,7 +7286,7 @@ int pc_readparam(struct map_session_data* sd,int type) case SP_DEFELE: val = sd->battle_status.def_ele; break; #ifndef RENEWAL_CAST case SP_VARCASTRATE: -#endif +#endif case SP_CASTRATE: val = sd->castrate+=val; break; @@ -7973,22 +8004,21 @@ int pc_setoption(struct map_session_data *sd,int type) else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_FALCON); - if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { - if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting - clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0); - status_calc_pc(sd,SCO_NONE); - } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount - clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER); - status_calc_pc(sd,SCO_NONE); - } + if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting + clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0); + status_calc_pc(sd,SCO_NONE); + } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER); + status_calc_pc(sd,SCO_NONE); } - if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { + + if( (type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR)) + || (!(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR) ) { int i; - if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) - status_calc_pc(sd, SCO_NONE); - else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) - status_calc_pc(sd, SCO_NONE); - for( i = 0; i < SC_MAX; i++ ){ + status_calc_pc(sd, SCO_NONE); + + // End all SCs that can be reset when mado is taken off + for( i = 0; i < SC_MAX; i++ ) { if ( !sd->sc.data[i] || !status->get_sc_type(i) ) continue; if ( status->get_sc_type(i)&SC_MADO_NO_RESET ) @@ -8030,7 +8060,7 @@ int pc_setoption(struct map_session_data *sd,int type) *------------------------------------------*/ int pc_setcart(struct map_session_data *sd,int type) { #ifndef NEW_CARTS - int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; + int cart[6] = {OPTION_NOTHING,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; int option; #endif nullpo_ret(sd); @@ -8108,19 +8138,62 @@ int pc_setriding(TBL_PC* sd, int flag) return 0; } -/*========================================== - * Give player a mado - *------------------------------------------*/ -int pc_setmadogear(TBL_PC* sd, int flag) -{ - if( flag ){ - if( pc->checkskill(sd,NC_MADOLICENCE) > 0 ) +/** + * Gives player a mado + * @param flag 1 Set mado + **/ +void pc_setmadogear( struct map_session_data *sd, int flag ) { + if( flag ) { + if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR); - } else if( pc_ismadogear(sd) ){ - pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR); - } + } else if( pc_ismadogear(sd) ) + pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR); - return 0; + return; +} + +/** + * Determines whether a player can attack based on status changes + * Why not use status_check_skilluse? + * "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack." + * Even ground-based attacks should be blocked by these statuses + * Called from unit_attack and unit_attack_timer_sub + * @retval true Can attack + **/ +bool pc_can_attack( struct map_session_data *sd, int target_id ) { + nullpo_retr(false, sd); + + if( sd->sc.data[SC_BASILICA] || + sd->sc.data[SC__SHADOWFORM] || + sd->sc.data[SC__MANHOLE] || + sd->sc.data[SC_CURSEDCIRCLE_ATKER] || + sd->sc.data[SC_CURSEDCIRCLE_TARGET] || + sd->sc.data[SC_COLD] || + sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe + sd->sc.data[SC_TRICKDEAD] || + (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) || + sd->sc.data[SC_BLADESTOP] || + sd->sc.data[SC_DEEP_SLEEP] || + sd->sc.data[SC_FALLENEMPIRE] ) + return false; + + return true; +} + +/** + * Determines whether a player can talk/whisper based on status changes + * Called from clif_parse_GlobalMessage and clif_parse_WisMessage + * @retval true Can talk + **/ +bool pc_can_talk( struct map_session_data *sd ) { + nullpo_retr(false, sd); + + if( sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + return false; + + return true; } /*========================================== @@ -9936,7 +10009,7 @@ void pc_read_skill_tree(void) { if( a == MAX_SKILL_TREE ) { ShowWarning("pc_read_skill_tree: '%s' can't inherit '%s', skill tree is full!\n", name,iname); break; - } else if ( pc->skill_tree[idx][a].id || ( pc->skill_tree[idx][a].id == NV_TRICKDEAD && ((pc->jobid2mapid(jnames[k].id)&MAPID_BASEMASK)!=MAPID_NOVICE) ) ) /* we skip trickdead for non-novices */ + } else if ( pc->skill_tree[idx][a].id || ( pc->skill_tree[idx][a].id == NV_TRICKDEAD && ((pc->jobid2mapid(jnames[k].id)&(MAPID_BASEMASK|JOBL_2))!=MAPID_NOVICE) ) ) /* we skip trickdead for non-novices */ continue;/* skip */ memcpy(&pc->skill_tree[idx][a],&pc->skill_tree[fidx][f],sizeof(pc->skill_tree[fidx][f])); @@ -10320,7 +10393,7 @@ int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -void pc_expire_check(struct map_session_data *sd) { +void pc_expire_check(struct map_session_data *sd) { /* ongoing timer */ if( sd->expiration_tid != INVALID_TIMER ) return; @@ -10621,7 +10694,7 @@ void do_init_pc(bool minimal) { ers_chunk_size(pc->str_reg_ers, 50); } /*===================================== -* Default Functions : pc.h +* Default Functions : pc.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -10645,9 +10718,7 @@ void pc_defaults(void) { memset(pc->exp_table, 0, sizeof(pc->exp_table) + sizeof(pc->max_level) + sizeof(pc->statp) -#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) + sizeof(pc->level_penalty) -#endif + sizeof(pc->skill_tree) + sizeof(pc->smith_fame_list) + sizeof(pc->chemist_fame_list) @@ -10829,6 +10900,8 @@ void pc_defaults(void) { 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 diff --git a/src/map/pc.h b/src/map/pc.h index 3a1d15746..fcd6f39d0 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -2,26 +2,26 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_PC_H_ -#define _MAP_PC_H_ +#ifndef MAP_PC_H +#define MAP_PC_H -#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus -#include "../common/ers.h" -#include "../common/timer.h" // INVALID_TIMER -#include "atcommand.h" // AtCommandType -#include "battle.h" // battle_config -#include "battleground.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" -#include "log.h" -#include "map.h" // RC_MAX -#include "mob.h" -#include "pc_groups.h" -#include "script.h" // struct script_reg, struct script_regstr +#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" // OPTION_*, struct weapon_atk -#include "unit.h" // unit_stop_attack(), unit_stop_walking() +#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 /** * Defines @@ -565,7 +565,7 @@ struct map_session_data { #define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 ) #define pc_isdead(sd) ( (sd)->state.dead_sit == 1 ) #define pc_issit(sd) ( (sd)->vd.dead_sit == 2 ) -#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle_config.idle_no_share ) +#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle->bc->idle_no_share ) #define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading ) #define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend ) @@ -587,9 +587,9 @@ struct map_session_data { #define pc_isfalcon(sd) ( (sd)->sc.option&OPTION_FALCON ) #define pc_isriding(sd) ( (sd)->sc.option&OPTION_RIDING ) #define pc_isinvisible(sd) ( (sd)->sc.option&OPTION_INVISIBLE ) -#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate ) +#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle->bc->natural_heal_weight_rate ) #define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 ) -#define pc_maxparameter(sd) ( ((((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) || (((sd)->class_&MAPID_UPPERMASK) == MAPID_REBELLION) || (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter)) ) +#define pc_maxparameter(sd) ( (((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO || ((sd)->class_&MAPID_UPPERMASK) == MAPID_REBELLION || ((sd)->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E) ? battle->bc->max_extended_parameter : (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_third_parameter : battle->bc->max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_parameter : battle->bc->max_parameter) ) /** * Ranger **/ @@ -725,7 +725,7 @@ struct autotrade_vending { }; /*===================================== -* Interface : pc.h +* Interface : pc.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -742,9 +742,8 @@ struct pc_interface { unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL]; unsigned int max_level[CLASS_COUNT][2]; unsigned int statp[MAX_LEVEL+1]; -#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1]; -#endif + unsigned int equip_pos[EQI_MAX]; /* */ struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE]; @@ -772,6 +771,8 @@ struct pc_interface { //int (*getrefinebonus) (int lv,int type); FIXME: This function does not exist, nor it is ever called bool (*can_give_items) (struct map_session_data *sd); bool (*can_give_bound_items) (struct map_session_data *sd); + bool (*can_talk) (struct map_session_data *sd); + bool (*can_attack) ( struct map_session_data *sd, int target_id ); bool (*can_use_command) (struct map_session_data *sd, const char *command); int (*set_group) (struct map_session_data *sd, int group_id); @@ -857,7 +858,7 @@ struct pc_interface { unsigned int (*maxjoblv) (struct map_session_data *sd); int (*checkbaselevelup) (struct map_session_data *sd); int (*checkjoblevelup) (struct map_session_data *sd); - int (*gainexp) (struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool is_quest); + bool (*gainexp) (struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool is_quest); unsigned int (*nextbaseexp) (struct map_session_data *sd); unsigned int (*thisbaseexp) (struct map_session_data *sd); unsigned int (*nextjobexp) (struct map_session_data *sd); @@ -894,7 +895,7 @@ struct pc_interface { int (*setcart) (struct map_session_data* sd, int type); int (*setfalcon) (struct map_session_data* sd, int flag); int (*setriding) (struct map_session_data* sd, int flag); - int (*setmadogear) (struct map_session_data* sd, int flag); + void (*setmadogear) (struct map_session_data* sd, int flag); int (*changelook) (struct map_session_data *sd,int type,int val); int (*equiplookall) (struct map_session_data *sd); @@ -1025,4 +1026,4 @@ struct pc_interface *pc; void pc_defaults(void); -#endif /* _MAP_PC_H_ */ +#endif /* MAP_PC_H */ diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 906462c7e..e577c642f 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -2,6 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#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" @@ -10,12 +18,6 @@ #include "../common/showmsg.h" #include "../common/strlib.h" // strcmp -#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() - static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd() struct pc_groups_interface pcg_s; @@ -181,7 +183,7 @@ static void read_config(void) { int j, inherit_count = 0, done = 0; if (group_settings->inheritance_done) // group already processed - continue; + continue; if ((inherit = group_settings->inherit) == NULL || (inherit_count = libconfig->setting_length(inherit)) <= 0) { // this group does not inherit from others diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 5c03f999f..f52e2ba22 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -2,8 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_PC_GROUPS_H_ -#define _MAP_PC_GROUPS_H_ +#ifndef MAP_PC_GROUPS_H +#define MAP_PC_GROUPS_H + +#include "../common/cbasetypes.h" +#include "../common/conf.h" +#include "../common/db.h" /// PC permissions enum e_pc_permission { @@ -92,4 +96,4 @@ struct pc_groups_interface *pcg; void pc_groups_defaults(void); -#endif /* _MAP_PC_GROUPS_H_ */ +#endif /* MAP_PC_GROUPS_H */ diff --git a/src/map/pet.c b/src/map/pet.c index c04d9267a..e083e58d1 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -2,37 +2,39 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/db.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/ers.h" +#define HERCULES_CORE -#include "pc.h" -#include "status.h" -#include "map.h" -#include "path.h" -#include "intif.h" -#include "clif.h" -#include "chrif.h" #include "pet.h" -#include "itemdb.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 "atcommand.h" // msg_txt() -#include "log.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.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; @@ -97,7 +99,7 @@ int pet_unlocktarget(struct pet_data *pd) * Pet Attack Skill [Skotlex] *------------------------------------------*/ int pet_attackskill(struct pet_data *pd, int target_id) { - if (!battle_config.pet_status_support || !pd->a_skill || + if (!battle_config.pet_status_support || !pd->a_skill || (battle_config.pet_equip_required && !pd->pet.equip)) return 0; @@ -105,7 +107,7 @@ int pet_attackskill(struct pet_data *pd, int target_id) { return 0; if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) { - //Skotlex: Use pet's skill + //Skotlex: Use pet's skill int inf; struct block_list *bl; @@ -156,7 +158,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) if(pd->petDB->defence_attack_rate > 0 && rate <= 0) rate = 1; } - if(rnd()%10000 < rate) + if(rnd()%10000 < rate) { if(pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate) pd->target_id = bl->id; @@ -301,7 +303,7 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) clif->additem(sd,0,0,flag); map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - pd->pet.incuvate = 1; + pd->pet.incubate = 1; unit->free(&pd->bl,CLR_OUTSIGHT); status_calc_pc(sd,SCO_NONE); @@ -317,7 +319,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) nullpo_retr(1, sd); - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); if(sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->char_id) { sd->status.pet_id = 0; @@ -325,8 +327,8 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) } if (sd->status.pet_id != petinfo->pet_id) { if (sd->status.pet_id) { - //Wrong pet?? Set incuvate to no and send it back for saving. - petinfo->incuvate = 1; + //Wrong pet?? Set incubate to no and send it back for saving. + petinfo->incubate = 1; intif->save_petdata(sd->status.account_id,petinfo); sd->status.pet_id = 0; return 1; @@ -388,14 +390,14 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo) { nullpo_retr(1, sd); - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); - if(sd->status.pet_id && petinfo->incuvate == 1) { + if(sd->status.pet_id && petinfo->incubate == 1) { sd->status.pet_id = 0; return 1; } - petinfo->incuvate = 0; + petinfo->incubate = 0; petinfo->account_id = sd->status.account_id; petinfo->char_id = sd->status.char_id; sd->status.pet_id = petinfo->pet_id; @@ -416,7 +418,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo) clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); clif->send_petstatus(sd); } - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); return 0; } @@ -431,7 +433,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { sd->status.pet_id = 0; return 1; } - if(p->incuvate == 1) { + if(p->incubate == 1) { int i; //Delete egg from inventory. [Skotlex] for (i = 0; i < MAX_INVENTORY; i++) { @@ -537,25 +539,38 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) { return 0; } -///This function is invoked when a new pet has been created, and at no other time! -int pet_get_egg(int account_id,int pet_id,int flag) { +/** + * Is invoked _only_ when a new pet has been created is a product of packet 0x3880 + * see mapif_pet_created@int_pet.c for more information + * Handles new pet data from inter-server and prepares item information + * to add pet egg + * + * pet_id - Should contain pet id otherwise means failure + * returns true on success + **/ +bool pet_get_egg(int account_id, short pet_class, int pet_id ) { struct map_session_data *sd; struct item tmp_item; - int i=0,ret=0; + int i = 0, ret = 0; - if(flag) - return 0; - - sd = map->id2sd(account_id); - if(sd == NULL) - return 0; + if( pet_id == 0 || pet_class == 0 ) + return false; - i = pet->search_petDB_index(sd->catch_target_class,PET_CLASS); + sd = map->id2sd(account_id); + if( sd == NULL ) + return false; + + // i = pet->search_petDB_index(sd->catch_target_class,PET_CLASS); + // issue: 8150 + // Before this change in cases where more than one pet egg were requested in a short + // period of time it wasn't possible to know which kind of egg was being requested after + // 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 0; + return false; } memset(&tmp_item,0,sizeof(tmp_item)); @@ -570,7 +585,7 @@ int pet_get_egg(int account_id,int pet_id,int flag) { map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - return 1; + return true; } int pet_menu(struct map_session_data *sd,int menunum) @@ -581,12 +596,12 @@ int pet_menu(struct map_session_data *sd,int menunum) return 1; //You lost the pet already. - if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incuvate) + 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&0x01) && !pc->inventoryblank(sd)) { + if ((egg_id->flag.trade_restriction&ITR_NODROP) && !pc->inventoryblank(sd)) { clif->message(sd->fd, msg_txt(451)); // You can't return your pet because your inventory is full. return 1; } @@ -897,7 +912,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER)) return 0; //Target already locked. - if (target->type != BL_ITEM) + if (target->type != BL_ITEM) { //enemy targetted if(!battle->check_range(&pd->bl,target,pd->status.rhw.range)) { //Chase @@ -919,7 +934,7 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0])); pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount; map->clearflooritem(target); - } + } //Target is unlocked regardless of whether it was picked or not. pet->unlocktarget(pd); } @@ -1035,7 +1050,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) /*========================================== * pet bonus giving skills [Valaris] / Rewritten by [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; @@ -1076,7 +1091,7 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) { /*========================================== * pet recovery skills [Valaris] / Rewritten by [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ 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; @@ -1092,7 +1107,7 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) { } if(sd->sc.data[pd->recovery->type]) - { //Display a heal animation? + { //Display a heal animation? //Detoxify is chosen for now. clif->skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER); @@ -1140,7 +1155,7 @@ int pet_heal_timer(int tid, int64 tick, int id, intptr_t data) { /*========================================== * pet support skills [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd=map->id2sd(id); struct pet_data *pd; @@ -1187,12 +1202,12 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { * Pet read db data * pet->db.txt * pet->db2.txt - *------------------------------------------*/ + *------------------------------------------*/ int read_petdb() { char* filename[] = {"pet_db.txt","pet_db2.txt"}; FILE *fp; - int nameid,i,j,k; + int nameid,i,j,k; // Remove any previous scripts in case reloaddb was invoked. for( j = 0; j < MAX_PET_DB; j++ ) @@ -1314,9 +1329,9 @@ int read_petdb() pet->db[j].equip_script = NULL; if( *str[20] ) - pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0); + pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL); if( *str[21] ) - pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0); + pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL); j++; entries++; diff --git a/src/map/pet.h b/src/map/pet.h index 537a50c4b..5c890ef85 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -2,11 +2,17 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_PET_H_ -#define _MAP_PET_H_ +#ifndef MAP_PET_H +#define MAP_PET_H -#define MAX_PET_DB 300 -#define MAX_PETLOOT_SIZE 30 +#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 + +#define MAX_PET_DB 300 +#define MAX_PETLOOT_SIZE 30 struct s_pet_db { short class_; @@ -127,7 +133,7 @@ struct pet_interface { int (*select_egg) (struct map_session_data *sd, short egg_index); int (*catch_process1) (struct map_session_data *sd, int target_class); int (*catch_process2) (struct map_session_data *sd, int target_id); - int (*get_egg) (int account_id, int pet_id, int flag); + bool (*get_egg) (int account_id, short pet_class, int pet_id ); int (*unequipitem) (struct map_session_data *sd, struct pet_data *pd); int (*food) (struct map_session_data *sd, struct pet_data *pd); int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap); @@ -152,4 +158,4 @@ struct pet_interface *pet; void pet_defaults(void); -#endif /* _MAP_PET_H_ */ +#endif /* MAP_PET_H */ diff --git a/src/map/quest.c b/src/map/quest.c index bde276f9d..b76d6bc82 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -2,36 +2,37 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" +#define HERCULES_CORE -#include "map.h" -#include "pc.h" -#include "npc.h" -#include "itemdb.h" -#include "script.h" -#include "intif.h" -#include "battle.h" -#include "mob.h" -#include "party.h" -#include "unit.h" -#include "log.h" -#include "clif.h" #include "quest.h" -#include "chrif.h" +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdarg.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/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 quest_interface quest_s; diff --git a/src/map/quest.h b/src/map/quest.h index e01e35619..9d617e369 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -2,8 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_QUEST_H_ -#define _MAP_QUEST_H_ +#ifndef MAP_QUEST_H +#define MAP_QUEST_H + +#include "map.h" // TBL_PC +#include "../common/cbasetypes.h" +#include "../common/mmo.h" // MAX_QUEST_OBJECTIVES #define MAX_QUEST_DB (60355+1) // Highest quest ID + 1 @@ -48,4 +52,4 @@ struct quest_interface *quest; void quest_defaults(void); -#endif /* _MAP_QUEST_H_ */ +#endif /* MAP_QUEST_H */ diff --git a/src/map/script.c b/src/map/script.c index 312e40696..9fe746c8c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -2,58 +2,63 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#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 "script.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 "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 "map.h" -#include "path.h" -#include "clif.h" -#include "chrif.h" -#include "itemdb.h" -#include "pc.h" -#include "status.h" -#include "storage.h" -#include "mob.h" -#include "npc.h" -#include "pet.h" -#include "mapreg.h" -#include "homunculus.h" -#include "instance.h" -#include "mercenary.h" -#include "intif.h" -#include "skill.h" -#include "status.h" -#include "chat.h" -#include "battle.h" -#include "battleground.h" -#include "party.h" -#include "guild.h" -#include "atcommand.h" -#include "log.h" -#include "unit.h" -#include "pet.h" -#include "mail.h" -#include "script.h" -#include "quest.h" -#include "elemental.h" -#include "../config/core.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> #ifndef WIN32 #include <sys/time.h> #endif -#include <time.h> static inline int GETVALUE(const unsigned char* buf, int i) { return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0)); @@ -1497,9 +1502,9 @@ const char* parse_syntax(const char* p) script->set_label(l,script->pos,p); } // check duplication of case label [Rayce] - if(linkdb_search(&script->syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v)) != NULL) + if(linkdb_search(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v)) != NULL) disp_error_message("parse_syntax: dup 'case'",p); - linkdb_insert(&script->syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v), (void*)1); + linkdb_insert(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v), (void*)1); sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; @@ -2241,8 +2246,7 @@ void script_warning(const char* src, const char* file, int start_line, const cha /*========================================== * Analysis of the script *------------------------------------------*/ -struct script_code* parse_script(const char *src,const char *file,int line,int options) -{ +struct script_code* parse_script(const char *src,const char *file,int line,int options, int *retval) { const char *p,*tmpp; int i; struct script_code* code = NULL; @@ -2288,6 +2292,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->parser_current_file = NULL; script->parser_current_line = 0; #endif // ENABLE_CASE_CHECK + if (retval) *retval = EXIT_FAILURE; return NULL; } @@ -2314,8 +2319,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o } else {// requires brackets around the script - if( *p != '{' ) + if( *p != '{' ) { disp_error_message("not found '{'",p); + if (retval) *retval = EXIT_FAILURE; + } p = script->skip_space(p+1); if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) ) {// empty script and can return NULL @@ -2390,13 +2397,14 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o else if( script->str_data[i].type == C_USERFUNC ) {// 'function name;' without follow-up code ShowError("parse_script: function '%s' declared but not defined.\n", script->str_buf+script->str_data[i].str); + if (retval) *retval = EXIT_FAILURE; unresolved_names = true; } } - if( unresolved_names ) - { + if( unresolved_names ) { disp_error_message("parse_script: unresolved function references", p); + if (retval) *retval = EXIT_FAILURE; } #ifdef SCRIPT_DEBUG_DISP @@ -2619,7 +2627,7 @@ void* get_val2(struct script_state* st, int64 uid, struct reg_db *ref) { script->push_val(st->stack, C_NAME, uid, ref); data = script_getdatatop(st, -1); script->get_val(st, data); - return (data->type == C_INT ? (void*)__64BPTRSIZE((int32)data->u.num) : (void*)__64BPTRSIZE(data->u.str)); // u.num is int32 because it comes from script->get_val + return (data->type == C_INT ? (void*)h64BPTRSIZE((int32)data->u.num) : (void*)h64BPTRSIZE(data->u.str)); // u.num is int32 because it comes from script->get_val } /** * Because, currently, array members with key 0 are indifferenciable from normal variables, we should ensure its actually in @@ -2640,7 +2648,7 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data * insert = true; script_removetop(st, -1, 0); } else { - int32 num = (int32)__64BPTRSIZE(script->get_val2(st, uid, ref)); + int32 num = (int32)h64BPTRSIZE(script->get_val2(st, uid, ref)); if( num ) insert = true; script_removetop(st, -1, 0); @@ -2757,7 +2765,7 @@ void script_array_add_member(struct script_array *sa, unsigned int idx) { } /** * Obtains the source of the array database for this type and scenario - * Initializes such database when not yet initialised. + * Initializes such database when not yet initialized. **/ 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; @@ -2907,14 +2915,20 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co return pc_setglobalreg_str(sd, num, str); } } else {// integer variable - int val = (int)__64BPTRSIZE(value); + // FIXME: This isn't safe, in 32bits systems we're converting a 64bit pointer + // to a 32bit int, this will lead to overflows! [Panikon] + int val = (int)h64BPTRSIZE(value); if(script->str_data[script_getvarid(num)].type == C_PARAM) { if( pc->setparam(sd, script->str_data[script_getvarid(num)].val, val) == 0 ) { if( st != NULL ) { ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val); script->reportsrc(st); - st->state = END; + // Instead of just stop the script execution we let the character close + // the window if it was open. + st->state = (sd->state.dialog) ? CLOSE : END; + if( st->state == CLOSE ) + clif->scriptclose(sd, st->oid); } return 0; } @@ -3216,6 +3230,8 @@ void script_free_vars(struct DBMap* var_storage) { void script_free_code(struct script_code* code) { + nullpo_retv(code); + if( code->instances ) script->stop_instances(code); else { @@ -4200,7 +4216,7 @@ void script_run_autobonus(const char *autobonus, int id, int pos) void script_add_autobonus(const char *autobonus) { if( strdb_get(script->autobonus_db, autobonus) == NULL ) { - struct script_code *scriptroot = script->parse(autobonus, "autobonus", 0, 0); + struct script_code *scriptroot = script->parse(autobonus, "autobonus", 0, 0, NULL); if( scriptroot ) strdb_put(script->autobonus_db, autobonus, scriptroot); @@ -4499,6 +4515,8 @@ int script_reload(void) { itemdb->name_constants(); + sysinfo->vcsrevision_reload(); + return 0; } /* returns name of current function being run, from within the stack [Ind/Hercules] */ @@ -5647,7 +5665,7 @@ BUILDIN(input) else { int amount = sd->npc_amount; - script->set_reg(st, sd, uid, name, (void*)__64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2)); + script->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2)); script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); } st->state = RUN; @@ -5735,7 +5753,7 @@ BUILDIN(setr) { if( is_string_variable(name) ) script->set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2)); else - script->set_reg(st,sd,num,name,(void*)__64BPTRSIZE(script_getnum(st,3)),script_getref(st,2)); + script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(script_getnum(st,3)),script_getref(st,2)); return true; } @@ -5790,7 +5808,7 @@ BUILDIN(setarray) else {// int array for( i = 3; start < end; ++start, ++i ) - script->set_reg(st, sd, reference_uid(id, start), name, (void*)__64BPTRSIZE(script_getnum(st,i)), reference_getref(data)); + script->set_reg(st, sd, reference_uid(id, start), name, (void*)h64BPTRSIZE(script_getnum(st,i)), reference_getref(data)); } return true; } @@ -5832,7 +5850,7 @@ BUILDIN(cleararray) if( is_string_variable(name) ) v = (void*)script_getstr(st, 3); else - v = (void*)__64BPTRSIZE(script_getnum(st, 3)); + v = (void*)h64BPTRSIZE(script_getnum(st, 3)); end = start + script_getnum(st, 4); if( end > SCRIPT_MAX_ARRAYSIZE ) @@ -6190,10 +6208,8 @@ BUILDIN(countitem) { struct item_data* id = NULL; TBL_PC* sd = script->rid2sd(st); - if (!sd) { - script_pushint(st,0); + if( !sd ) return true; - } if( script_isstringtype(st, 2) ) { // item name @@ -6230,10 +6246,8 @@ BUILDIN(countitem2) { struct item_data* id = NULL; TBL_PC* sd = script->rid2sd(st); - if (!sd) { - script_pushint(st,0); + if( !sd ) return true; - } if( script_isstringtype(st, 2) ) { // item name @@ -6377,7 +6391,9 @@ BUILDIN(checkweight2) int nb_it, nb_nb; //array size TBL_PC *sd = script->rid2sd(st); - nullpo_retr(false,sd); + + if( sd == NULL ) + return false; data_it = script_getdata(st, 2); data_nb = script_getdata(st, 3); @@ -6409,9 +6425,9 @@ BUILDIN(checkweight2) slots = pc->inventoryblank(sd); for(i=0; i<nb_it; i++) { - nameid = (int32)__64BPTRSIZE(script->get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); + nameid = (int32)h64BPTRSIZE(script->get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); script_removetop(st, -1, 0); - amount = (int32)__64BPTRSIZE(script->get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); + amount = (int32)h64BPTRSIZE(script->get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); script_removetop(st, -1, 0); if(fail) continue; //cpntonie to depop rest @@ -6711,11 +6727,8 @@ BUILDIN(getnameditem) { TBL_PC *sd, *tsd; sd = script->rid2sd(st); - if (sd == NULL) { - //Player not attached! - script_pushint(st,0); + if (sd == NULL) // Player not attached! return true; - } if( script_isstringtype(st, 2) ) { const char *name = script_getstr(st, 2); @@ -7410,10 +7423,9 @@ BUILDIN(strcharinfo) struct party_data* p; sd=script->rid2sd(st); - if (!sd) { //Avoid crashing.... - script_pushconststr(st,""); + if (!sd) //Avoid crashing.... return true; - } + num=script_getnum(st,2); switch(num) { case 0: @@ -7964,6 +7976,9 @@ BUILDIN(delequip) if(i >= 0) { pc->unequipitem(sd,i,3); //recalculate bonus pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + script_pushint(st,1); + } else { + script_pushint(st,0); } return true; @@ -8263,20 +8278,36 @@ BUILDIN(addtoskill) { /// guildskill <skill id>,<amount>; /// guildskill "<skill name>",<amount>; BUILDIN(guildskill) { - int id; + int skill_id, id, max_points; int level; + TBL_PC* sd; - int i; + struct guild *gd; + struct guild_skill gd_skill; sd = script->rid2sd(st); if( sd == NULL ) - return true;// no player attached, report source + return false; // no player attached, report source - id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); + if( (gd = sd->guild) == NULL ) + return true; + + skill_id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); level = script_getnum(st,3); - for( i=0; i < level; i++ ) - guild->skillup(sd, id); + id = skill_id - GD_SKILLBASE; + max_points = guild->skill_get_max(skill_id); + + if( (gd->skill[id].lv + level) > max_points ) + level = max_points - gd->skill[id].lv; + + if( level <= 0 ) + return true; + + memcpy(&gd_skill, &(gd->skill[id]), sizeof(gd->skill[id])); + gd_skill.lv += level; + + intif->guild_change_basicinfo( gd->guild_id, GBI_SKILLLV, &(gd_skill), sizeof(gd_skill) ); return true; } @@ -8935,7 +8966,7 @@ BUILDIN(getexp) base = (int) cap_value(base * bonus, 0, INT_MAX); job = (int) cap_value(job * bonus, 0, INT_MAX); - pc->gainexp(sd, NULL, base, job, true); + pc->gainexp(sd, &sd->bl, base, job, true); return true; } @@ -9722,8 +9753,13 @@ BUILDIN(itemeffect) { TBL_PC *sd; struct item_data *item_data; - nullpo_retr( false, ( sd = script->rid2sd( st ) ) ); - nullpo_retr( false, ( nd = (TBL_NPC *)map->id2bl( sd->npc_id ) ) ); + sd = script->rid2sd(st); + if( sd == NULL ) + return false; + + nd = (TBL_NPC *)map->id2bl(sd->npc_id); + if( nd == NULL ) + return false; if( script_isstringtype(st, 2) ) { const char *name = script_getstr(st, 2); @@ -10404,10 +10440,8 @@ BUILDIN(eaclass) else { TBL_PC *sd; sd=script->rid2sd(st); - if (!sd) { - script_pushint(st,-1); + if( !sd ) return true; - } class_ = sd->status.class_; } script_pushint(st,pc->jobid2mapid(class_)); @@ -10478,6 +10512,8 @@ BUILDIN(resetstatus) { TBL_PC *sd; sd=script->rid2sd(st); + if( sd == NULL ) + return false; pc->resetstate(sd); return true; } @@ -10489,6 +10525,8 @@ BUILDIN(resetskill) { TBL_PC *sd; sd=script->rid2sd(st); + if( sd == NULL ) + return false; pc->resetskill(sd,1); return true; } @@ -10500,6 +10538,8 @@ 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)); return true; } @@ -10550,6 +10590,9 @@ BUILDIN(changesex) TBL_PC *sd = NULL; sd = script->rid2sd(st); + if( sd == NULL ) + return false; + pc->resetskill(sd,4); // to avoid any problem with equipment and invalid sex, equipment is unequiped. for( i=0; i<EQI_MAX; i++ ) @@ -11017,7 +11060,7 @@ BUILDIN(setmapflag) { char empty[1] = "\0"; char params[MAP_ZONE_MAPFLAG_LENGTH]; memcpy(params, val2, MAP_ZONE_MAPFLAG_LENGTH); - npc->parse_mapflag(map->list[m].name, empty, zone, params, empty, empty, empty); + npc->parse_mapflag(map->list[m].name, empty, zone, params, empty, empty, empty, NULL); } break; case MF_NOCOMMAND: map->list[m].nocommand = (val <= 0) ? 100 : val; break; @@ -11501,6 +11544,10 @@ BUILDIN(getequipcardcnt) num=script_getnum(st,2); sd=script->rid2sd(st); + + if( sd == NULL ) + return false; + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); @@ -11533,6 +11580,9 @@ BUILDIN(successremovecards) { TBL_PC* sd = script->rid2sd(st); int num = script_getnum(st,2); + if( sd == NULL ) + return false; + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); @@ -11600,6 +11650,9 @@ BUILDIN(failedremovecards) { int num = script_getnum(st,2); int typefail = script_getnum(st,3); + if( sd == NULL ) + return false; + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); @@ -11746,12 +11799,11 @@ BUILDIN(mobcount) { if( strcmp(mapname, "this") == 0 ) { struct map_session_data *sd = script->rid2sd(st); - if( sd ) - m = sd->bl.m; - else { - script_pushint(st,-1); - return true; - } + + if( sd == NULL ) + return false; + + m = sd->bl.m; } else if( (m = map->mapname2mapid(mapname)) < 0 ) { script_pushint(st,-1); return true; @@ -11783,10 +11835,10 @@ BUILDIN(wedding_effect) { TBL_PC *sd=script->rid2sd(st); struct block_list *bl; - if(sd==NULL) { - bl=map->id2bl(st->oid); - } else - bl=&sd->bl; + if( sd == NULL ) + return false; //bl=map->id2bl(st->oid); + + bl=&sd->bl; clif->wedding_effect(bl); return true; } @@ -11816,10 +11868,8 @@ BUILDIN(ispartneron) { BUILDIN(getpartnerid) { TBL_PC *sd=script->rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; script_pushint(st,sd->status.partner_id); return true; @@ -11827,10 +11877,8 @@ BUILDIN(getpartnerid) { BUILDIN(getchildid) { TBL_PC *sd=script->rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; script_pushint(st,sd->status.child); return true; @@ -11838,10 +11886,8 @@ BUILDIN(getchildid) { BUILDIN(getmotherid) { TBL_PC *sd=script->rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; script_pushint(st,sd->status.mother); return true; @@ -11849,10 +11895,8 @@ BUILDIN(getmotherid) { BUILDIN(getfatherid) { TBL_PC *sd=script->rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; script_pushint(st,sd->status.father); return true; @@ -12177,6 +12221,10 @@ BUILDIN(getequipcardid) num=script_getnum(st,2); slot=script_getnum(st,3); sd=script->rid2sd(st); + + if( sd == NULL ) + return false; + if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0 && slot>=0 && slot<4) @@ -12364,18 +12412,18 @@ BUILDIN(undisguise) } /*========================================== - * Transform a bl to another _class, + * Transform a bl to another class, * @type unused *------------------------------------------*/ BUILDIN(classchange) { - int _class,type; + int class_,type; struct block_list *bl=map->id2bl(st->oid); if(bl==NULL) return true; - _class=script_getnum(st,2); + class_=script_getnum(st,2); type=script_getnum(st,3); - clif->class_change(bl,_class,type); + clif->class_change(bl,class_,type); return true; } @@ -12722,6 +12770,9 @@ BUILDIN(skilleffect) { uint16 skill_lv=script_getnum(st,3); sd=script->rid2sd(st); + if( sd == NULL ) + return false; + /* ensure we're standing because the following packet causes the client to virtually set the char to stand, * which leaves the server thinking it still is sitting. */ if( pc_issit(sd) ) { @@ -12785,12 +12836,14 @@ BUILDIN(specialeffect) { } BUILDIN(specialeffect2) { - TBL_PC *sd=script->rid2sd(st); + TBL_PC *sd; int type = script_getnum(st,2); enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; if( script_hasdata(st,4) ) sd = map->nick2sd(script_getstr(st,4)); + else + sd = script->rid2sd(st); if (sd) clif->specialeffect(&sd->bl, type, target); @@ -12836,6 +12889,8 @@ BUILDIN(atcommand) { if (st->rid) { sd = script->rid2sd(st); + if( sd == NULL ) + return false; fd = sd->fd; } else { //Use a dummy character. sd = dummy_sd = pc->get_dummy_sd(); @@ -12977,10 +13032,8 @@ BUILDIN(getmercinfo) { return false; } } else { - if( ( sd = script->rid2sd(st) ) == NULL ) { - script_pushnil(st); + if( ( sd = script->rid2sd(st) ) == NULL ) return true; - } } md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL; @@ -13016,25 +13069,27 @@ BUILDIN(getmercinfo) { *------------------------------------------*/ BUILDIN(checkequipedcard) { + int n,i,c=0; TBL_PC *sd=script->rid2sd(st); - if(sd) { - int n,i,c=0; - c=script_getnum(st,2); + if( sd == NULL ) + return false; - for(i=0;i<MAX_INVENTORY;i++) { - if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]) { - if (itemdb_isspecial(sd->status.inventory[i].card[0])) - continue; - for(n=0;n<sd->inventory_data[i]->slot;n++) { - if(sd->status.inventory[i].card[n]==c) { - script_pushint(st,1); - return true; - } + c = script_getnum(st,2); + + for( i=0; i<MAX_INVENTORY; i++) { + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]) { + if (itemdb_isspecial(sd->status.inventory[i].card[0])) + continue; + for(n=0;n<sd->inventory_data[i]->slot;n++) { + if(sd->status.inventory[i].card[n]==c) { + script_pushint(st,1); + return true; } } } } + script_pushint(st,0); return true; } @@ -13174,6 +13229,8 @@ BUILDIN(getlook) int type,val; TBL_PC *sd; sd=script->rid2sd(st); + if( sd == NULL ) + return false; type=script_getnum(st,2); val = -1; @@ -13203,10 +13260,8 @@ BUILDIN(getsavepoint) int type; sd = script->rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; type = script_getnum(st,2); @@ -13384,7 +13439,7 @@ BUILDIN(getmapxy) sd=script->rid2sd(st); else sd=NULL; - script->set_reg(st,sd,num,name,(void*)__64BPTRSIZE(x),script_getref(st,3)); + script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(x),script_getref(st,3)); //Set MapY num=st->stack->stack_data[st->start+4].u.num; @@ -13395,7 +13450,7 @@ BUILDIN(getmapxy) sd=script->rid2sd(st); else sd=NULL; - script->set_reg(st,sd,num,name,(void*)__64BPTRSIZE(y),script_getref(st,4)); + script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(y),script_getref(st,4)); //Return Success value script_pushint(st,0); @@ -13421,7 +13476,7 @@ BUILDIN(logmes) BUILDIN(summon) { - int _class, timeout=0; + int class_, timeout=0; const char *str,*event=""; TBL_PC *sd; struct mob_data *md; @@ -13431,7 +13486,7 @@ BUILDIN(summon) if (!sd) return true; str = script_getstr(st,2); - _class = script_getnum(st,3); + class_ = script_getnum(st,3); if( script_hasdata(st,4) ) timeout=script_getnum(st,4); if( script_hasdata(st,5) ) { @@ -13441,7 +13496,7 @@ BUILDIN(summon) clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); - md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, _class, event, SZ_MEDIUM, AI_NONE); + md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_MEDIUM, AI_NONE); if (md) { md->master_id=sd->bl.id; md->special_state.ai = AI_ATTACK; @@ -13479,10 +13534,8 @@ BUILDIN(isequippedcnt) int ret = 0; sd = script->rid2sd(st); - if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; for (i=0; id!=0; i++) { script_fetch(st,i+2, id); @@ -13535,10 +13588,8 @@ BUILDIN(isequipped) sd = script->rid2sd(st); - if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; setitem_hash = sd->bonus.setitem_hash; setitem_hash2 = sd->bonus.setitem_hash2; @@ -13616,6 +13667,9 @@ BUILDIN(cardscnt) { sd = script->rid2sd(st); + if( sd == NULL ) + return false; + for (i=0; id!=0; i++) { script_fetch(st,i+2, id); if (id <= 0) @@ -13650,10 +13704,12 @@ BUILDIN(cardscnt) { *-------------------------------------------------------*/ BUILDIN(getrefine) { TBL_PC *sd; - if ((sd = script->rid2sd(st))!= NULL) - script_pushint(st,sd->status.inventory[status->current_equip_item_index].refine); - else - script_pushint(st,0); + + sd = script->rid2sd(st); + if( sd == NULL ) + return false; + + script_pushint(st,sd->status.inventory[status->current_equip_item_index].refine); return true; } @@ -13696,6 +13752,8 @@ BUILDIN(equip) struct item_data *item_data; sd = script->rid2sd(st); + if( sd == NULL ) + return false; nameid=script_getnum(st,2); if((item_data = itemdb->exists(nameid)) == NULL) @@ -14342,7 +14400,7 @@ BUILDIN(sscanf) { if(sscanf(str, buf, &ref_int)==0) { break; } - script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)__64BPTRSIZE(ref_int), reference_getref(data)); + script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)h64BPTRSIZE(ref_int), reference_getref(data)); } arg++; @@ -14709,7 +14767,7 @@ BUILDIN(setd) if( is_string_variable(varname) ) { script->setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL); } else { - script->setd_sub(st, sd, varname, elem, (void *)__64BPTRSIZE(script_getnum(st, 3)), NULL); + script->setd_sub(st, sd, varname, elem, (void *)h64BPTRSIZE(script_getnum(st, 3)), NULL); } return true; @@ -14733,11 +14791,8 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) name = reference_getname(data); if( not_server_variable(*name) && sd == NULL ) { // requires a player sd = script->rid2sd(st); - if( sd == NULL ) { // no player attached - script->reportdata(data); - st->state = END; + if( sd == NULL )// no player attached return false; - } } } else { ShowError("script:query_sql: not a variable\n"); @@ -14786,7 +14841,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) if( is_string_variable(name) ) script->setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data)); else - script->setd_sub(st, sd, name, i, (void *)__64BPTRSIZE((str?atoi(str):0)), reference_getref(data)); + script->setd_sub(st, sd, name, i, (void *)h64BPTRSIZE((str?atoi(str):0)), reference_getref(data)); } } if( i == max_rows && max_rows < SQL->NumRows(handle) ) { @@ -14881,10 +14936,8 @@ BUILDIN(callshop) const char *shopname; int flag = 0; sd = script->rid2sd(st); - if (!sd) { - script_pushint(st,0); - return true; - } + if( sd == NULL ) + return false; shopname = script_getstr(st, 2); if( script_hasdata(st,3) ) flag = script_getnum(st,3); @@ -15076,7 +15129,7 @@ BUILDIN(setitemscript) if(*dstscript) script->free_code(*dstscript); - *dstscript = new_bonus_script[0] ? script->parse(new_bonus_script, "script_setitemscript", 0, 0) : NULL; + *dstscript = new_bonus_script[0] ? script->parse(new_bonus_script, "script_setitemscript", 0, 0, NULL) : NULL; script_pushint(st,1); return true; } @@ -15342,7 +15395,7 @@ BUILDIN(searchitem) for( i = 0; i < count; ++start, ++i ) {// Set array - void* v = (void*)__64BPTRSIZE((int)items[i]->nameid); + void* v = (void*)h64BPTRSIZE((int)items[i]->nameid); script->set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); } @@ -16204,7 +16257,9 @@ BUILDIN(setquest) { struct map_session_data *sd = script->rid2sd(st); unsigned short i; int quest_id; - nullpo_retr(false,sd); + + if( sd == NULL ) + return false; quest_id = script_getnum(st, 2); @@ -16227,7 +16282,9 @@ BUILDIN(setquest) { BUILDIN(erasequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_retr(false,sd); + + if( sd == NULL ) + return false; quest->delete(sd, script_getnum(st, 2)); return true; @@ -16235,7 +16292,9 @@ BUILDIN(erasequest) { BUILDIN(completequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_retr(false,sd); + + if( sd == NULL ) + return false; quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE); return true; @@ -16243,7 +16302,9 @@ BUILDIN(completequest) { BUILDIN(changequest) { struct map_session_data *sd = script->rid2sd(st); - nullpo_retr(false,sd); + + if( sd == NULL ) + return false; quest->change(sd, script_getnum(st, 2),script_getnum(st, 3)); return true; @@ -16253,7 +16314,8 @@ BUILDIN(checkquest) { struct map_session_data *sd = script->rid2sd(st); enum quest_check_type type = HAVEQUEST; - nullpo_retr(false,sd); + if( sd == NULL ) + return false; if( script_hasdata(st, 3) ) type = (enum quest_check_type)script_getnum(st, 3); @@ -17315,19 +17377,6 @@ BUILDIN(is_function) { return true; } /** - * get_revision() -> retrieves the current svn revision (if available) - **/ -BUILDIN(get_revision) { - const char *svn = get_svn_revision(); - - if ( svn[0] != HERC_UNKNOWN_VER ) - script_pushint(st,atoi(svn)); - else - script_pushint(st,-1);//unknown - - return true; -} -/** * freeloop(<toggle>) -> toggles this script instance's looping-check ability **/ BUILDIN(freeloop) { @@ -17345,12 +17394,14 @@ BUILDIN(freeloop) { BUILDIN(sit) { struct map_session_data *sd = NULL; - if (script_hasdata(st, 2)) + if( script_hasdata(st, 2) ) sd = map->nick2sd(script_getstr(st, 2)); - - if (sd == NULL) + else sd = script->rid2sd(st); + if( sd == NULL ) + return false; + if (!pc_issit(sd)) { pc_setsit(sd); @@ -17363,12 +17414,14 @@ BUILDIN(sit) { BUILDIN(stand) { struct map_session_data *sd = NULL; - if (script_hasdata(st, 2)) + if( script_hasdata(st, 2) ) sd = map->nick2sd(script_getstr(st, 2)); - - if (sd == NULL) + else sd = script->rid2sd(st); + if( sd == NULL ) + return false; + if (pc_issit(sd)) { pc->setstand(sd); @@ -17381,12 +17434,14 @@ BUILDIN(stand) { BUILDIN(issit) { struct map_session_data *sd = NULL; - if (script_hasdata(st, 2)) + if( script_hasdata(st, 2) ) sd = map->nick2sd(script_getstr(st, 2)); - - if (sd == NULL) + else sd = script->rid2sd(st); + if( sd == NULL ) + return false; + if (pc_issit(sd)) script_pushint(st, 1); else @@ -17498,6 +17553,8 @@ BUILDIN(useatcmd) { if( st->rid ) { sd = script->rid2sd(st); + if( sd == NULL ) + return false; fd = sd->fd; } else { // Use a dummy character. @@ -17700,7 +17757,7 @@ BUILDIN(npcskill) { ShowError("npcskill: level exceeded maximum of %d.\n", MAX_LEVEL); return false; } - if (sd == NULL || nd == NULL) { //ain't possible, but I don't trust people. + if (sd == NULL || nd == NULL) { return false; } @@ -18546,6 +18603,13 @@ BUILDIN(tradertype) { npc->market_delfromsql(nd,USHRT_MAX); } +#if PACKETVER < 20131223 + if( type == NST_MARKET ) { + ShowWarning("buildin_tradertype: NST_MARKET is only available with PACKETVER 20131223 or newer!\n"); + script->reportsrc(st); + } +#endif + nd->u.scr.shop->type = type; return true; @@ -19152,7 +19216,6 @@ void script_parse_builtin(void) { BUILDIN_DEF(getargcount,""), BUILDIN_DEF(getcharip,"?"), BUILDIN_DEF(is_function,"s"), - BUILDIN_DEF(get_revision,""), BUILDIN_DEF(freeloop,"i"), BUILDIN_DEF(getrandgroupitem,"ii"), BUILDIN_DEF(cleanmap,"s"), diff --git a/src/map/script.h b/src/map/script.h index eed0dbf1d..48abf1487 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -2,20 +2,22 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_SCRIPT_H_ -#define _MAP_SCRIPT_H_ +#ifndef MAP_SCRIPT_H +#define MAP_SCRIPT_H -#include "../common/strlib.h" //StringBuf -#include "../common/cbasetypes.h" -#include "map.h" //EVENT_NAME_LENGTH - -#include <setjmp.h> #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 map_session_data; struct eri; /** @@ -564,7 +566,7 @@ struct script_interface { void (*final) (void); int (*reload) (void); /* parse */ - struct script_code* (*parse) (const char* src,const char* file,int line,int options); + struct script_code* (*parse) (const char* src,const char* file,int line,int options, int *retval); bool (*add_builtin) (const struct script_function *buildin, bool override); void (*parse_builtin) (void); const char* (*parse_subexpr) (const char* p,int limit); @@ -713,4 +715,4 @@ struct script_interface *script; void script_defaults(void); -#endif /* _MAP_SCRIPT_H_ */ +#endif /* MAP_SCRIPT_H */ diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 0144aea93..72b28aacd 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -2,14 +2,17 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#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 "battle.h" // battle_config.* -#include "clif.h" // clif->open_search_store_info, clif->search_store_info_* -#include "pc.h" // struct map_session_data -#include "searchstore.h" // struct s_search_store_info struct searchstore_interface searchstore_s; diff --git a/src/map/searchstore.h b/src/map/searchstore.h index 827e39053..d8abde615 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -2,8 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_SEARCHSTORE_H_ -#define _MAP_SEARCHSTORE_H_ +#ifndef MAP_SEARCHSTORE_H +#define MAP_SEARCHSTORE_H + +#include <time.h> + +#include "map.h" // MESSAGE_SIZE +#include "../common/cbasetypes.h" +#include "../common/mmo.h" // MAX_SLOTS /** * Defines @@ -93,4 +99,4 @@ struct searchstore_interface *searchstore; void searchstore_defaults (void); -#endif /* _MAP_SEARCHSTORE_H_ */ +#endif /* MAP_SEARCHSTORE_H */ diff --git a/src/map/skill.c b/src/map/skill.c index 612b205e9..c744dbde4 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2,46 +2,48 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/ers.h" +#define HERCULES_CORE -#include "map.h" -#include "path.h" -#include "clif.h" -#include "pc.h" -#include "status.h" +#include "../config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION() #include "skill.h" -#include "pet.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 "elemental.h" #include "mob.h" #include "npc.h" -#include "battle.h" -#include "battleground.h" #include "party.h" -#include "itemdb.h" +#include "path.h" +#include "pc.h" +#include "pet.h" #include "script.h" -#include "intif.h" -#include "log.h" -#include "chrif.h" -#include "guild.h" -#include "date.h" +#include "status.h" #include "unit.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <math.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 @@ -541,23 +543,6 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) return 1; } break; - case BS_GREED: - case WS_CARTBOOST: - case BS_HAMMERFALL: - case BS_ADRENALINE: - case MC_CARTREVOLUTION: - case MC_MAMMONITE: - case WS_MELTDOWN: - case MG_SIGHT: - case TF_HIDING: - /** - * These skills cannot be used while in mado gear (credits to Xantara) - **/ - if( pc_ismadogear(sd) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR_RIDE,0); - return 1; - } - break; case SC_MANHOLE: case WM_SOUND_OF_DESTRUCTION: @@ -585,12 +570,12 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd) return 1; switch(skill_id){ case MH_LIGHT_OF_REGENE: - if(hd->homunculus.intimacy <= 75000) //if not cordial - return 1; - break; - case MH_OVERED_BOOST: - if(hd->homunculus.hunger <= 1) //if we starving - return 1; + if( homun->get_intimacy_grade(hd) != 4 ){ + if( hd->master ) + clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_RELATIONGRADE, 0); + return 1; + } + break; case MH_GOLDENE_FERSE: //can be used with angriff if(hd->sc.data[SC_ANGRIFFS_MODUS]) return 1; @@ -760,15 +745,18 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 // Chance to trigger Taekwon kicks [Dralnu] if(sc && !sc->data[SC_COMBOATTACK]) { if(sc->data[SC_STORMKICK_READY] && - sc_start(src,src,SC_COMBOATTACK, 15, TK_STORMKICK, + sc_start4(src,src,SC_COMBOATTACK, 15, TK_STORMKICK, + bl->id, 2, 0, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sc->data[SC_DOWNKICK_READY] && - sc_start(src,src,SC_COMBOATTACK, 15, TK_DOWNKICK, + sc_start4(src,src,SC_COMBOATTACK, 15, TK_DOWNKICK, + bl->id, 2, 0, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sc->data[SC_TURNKICK_READY] && - sc_start(src,src,SC_COMBOATTACK, 15, TK_TURNKICK, + sc_start4(src,src,SC_COMBOATTACK, 15, TK_TURNKICK, + bl->id, 2, 0, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if (sc->data[SC_COUNTERKICK_READY]) { //additional chance from SG_FRIEND [Komurka] @@ -850,7 +838,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 #ifdef RENEWAL sc_start(src,bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); #else - //Tharis pointed out that this is normal freeze chance with a base of 300% + // [Tharis] pointed out that this is normal freeze chance with a base of 300% if(tsc->sg_counter >= 3 && sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv))) tsc->sg_counter = 0; @@ -991,7 +979,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case NPC_MENTALBREAKER: { - //Based on observations by Tharis, Mental Breaker should do SP damage + //Based on observations by [Tharis], Mental Breaker should do SP damage //equal to Matk*skLevel. rate = status->get_matk(src, 2); rate*=skill_lv; @@ -1030,7 +1018,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start(src,bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; - case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element + case LK_HEADCRUSH: // Headcrush has chance of causing Bleeding status, except on demon and undead element if (!(battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) sc_start2(src, bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); break; @@ -1257,7 +1245,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start(src, bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_FALLENEMPIRE: - sc_start(src, bl, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_FALLENEMPIRE, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_WINDMILL: if( dstsd ) @@ -1294,11 +1282,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start(src, bl, SC_BLOODING, 100, skill_lv, 10000); break; case ITEMID_MELON_BOMB: - sc_start(src, bl, SC_MELON_BOMB, 100, skill_lv, 60000); // Reduces ASPD and moviment speed + sc_start(src, bl, SC_MELON_BOMB, 100, skill_lv, 60000); // Reduces ASPD and movement speed break; case ITEMID_BANANA_BOMB: sc_start(src, bl, SC_BANANA_BOMB, 100, skill_lv, 60000); // Reduces LUK? Needed confirm it, may be it's bugged in kRORE? - sc_start(src, bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, (sd? sd->status.job_level:0) + sstatus->dex / 6 + tstatus->agi / 4 - tstatus->luk / 5 - status->get_lv(bl) + status->get_lv(src), skill_lv, 1000); // Sitdown for 3 seconds. + sc_start(src, bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, (sd? sd->status.job_level:0) + sstatus->dex / 6 + tstatus->agi / 4 - tstatus->luk / 5 - status->get_lv(bl) + status->get_lv(src), skill_lv, 1000); // Sit down for 3 seconds. break; } sd->itemid = -1; @@ -1341,6 +1329,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( sc_start(src, bl, SC_ILLUSIONDOPING, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)) ) //custom rate. sc_start(src, bl, SC_ILLUSION, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; + case MH_XENO_SLASHER: + sc_start2(src, bl, SC_BLOODING, 10 * skill_lv, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + break; } if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) { @@ -1652,7 +1643,7 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 return 1; } -/* Splitted off from skill->additional_effect, which is never called when the +/* Split off from skill->additional_effect, which is never called when the * attack skill kills the enemy. Place in this function counter status effects * when using skills (eg: Asura's sp regen penalty, or counter-status effects * from cards) that will take effect on the source, not the target. [Skotlex] @@ -1668,7 +1659,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b nullpo_ret(src); nullpo_ret(bl); - if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! - celest + if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! [celest] sd = BL_CAST(BL_PC, src); dstsd = BL_CAST(BL_PC, bl); @@ -1707,7 +1698,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b case GS_FULLBUSTER: sc_start(src,src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; - case HFLI_SBR44: //[orn] + case HFLI_SBR44: // [orn] case HVAN_EXPLOSION: if(src->type == BL_HOM){ TBL_HOM *hd = (TBL_HOM*)src; @@ -1723,15 +1714,15 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b } if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR - && rnd()%10000 < battle_config.sg_miracle_skill_ratio) //SG_MIRACLE [Komurka] + && rnd()%10000 < battle_config.sg_miracle_skill_ratio) // SG_MIRACLE [Komurka] sc_start(src,src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); if( sd && skill_id && attack_type&BF_MAGIC && status->isdead(bl) && !(skill->get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) && (rate=pc->checkskill(sd,HW_SOULDRAIN)) > 0 ) { - //Soul Drain should only work on targetted spells [Skotlex] - if( pc_issit(sd) ) pc->setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex] + // Soul Drain should only work on targeted spells [Skotlex] + if( pc_issit(sd) ) pc->setstand(sd); // Character stuck in attacking animation while 'sitting' fix. [Skotlex] if( skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id ) ; else { @@ -1751,7 +1742,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b if( attack_type&BF_MAGIC ) { sp += sd->bonus.magic_sp_gain_value; hp += sd->bonus.magic_hp_gain_value; - if( skill_id == WZ_WATERBALL ) {//(bugreport:5303) + if( skill_id == WZ_WATERBALL ) {// (bugreport:5303) struct status_change *sc = NULL; if( ( sc = status->get_sc(src) ) ) { if( sc->data[SC_SOULLINK] @@ -1846,7 +1837,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b break; } dstsd->state.autocast = 0; - //Set canact delay. [Skotlex] + // Set canact delay. [Skotlex] ud = unit->bl2ud(bl); if (ud) { rate = skill->delay_fix(bl, auto_skill_id, auto_skill_lv); @@ -1984,7 +1975,7 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int return 0; sc = status->get_sc(bl); - if (!sc || sc->option&OPTION_MADOGEAR ) //Mado Gear cannot be divested [Ind] + if (!sc || sc->option&OPTION_MADOGEAR ) // Mado Gear cannot be divested [Ind] return 0; for (i = 0; i < ARRAYLENGTH(pos); i++) { @@ -2013,16 +2004,16 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in nullpo_ret(src); if (src != target && map->list[src->m].flag.noknockback) - return 0; //No knocking + return 0; // No knocking if (count == 0) - return 0; //Actual knockback distance is 0. + return 0; // Actual knockback distance is 0. switch (target->type) { case BL_MOB: { struct mob_data* md = BL_CAST(BL_MOB, target); if( md->class_ == MOBID_EMPERIUM ) return 0; - if(src != target && is_boss(target)) //Bosses can't be knocked-back + if(src != target && is_boss(target)) // Bosses can't be knocked-back return 0; } break; @@ -2054,11 +2045,13 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in } -// Checks if 'bl' should reflect back a spell cast by 'src'. -// type is the type of magic attack: 0: indirect (aoe), 1: direct (targetted) -// In case of success returns type of reflection, otherwise 0 -// 1 - Regular reflection (Maya) -// 2 - SL_KAITE reflection +/* + Checks if 'bl' should reflect back a spell cast by 'src'. + type is the type of magic attack: 0: indirect (aoe), 1: direct (targeted) + In case of success returns type of reflection, otherwise 0 + 1 - Regular reflection (Maya) + 2 - SL_KAITE reflection +*/ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) { struct status_change *sc = status->get_sc(bl); struct map_session_data* sd = BL_CAST(BL_PC, bl); @@ -2117,8 +2110,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if(skill_id > 0 && !skill_lv) return 0; - nullpo_ret(src); //Source is the master behind the attack (player/mob/pet) - nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src. + nullpo_ret(src); // Source is the master behind the attack (player/mob/pet) + nullpo_ret(dsrc); // dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src. nullpo_ret(bl); //Target to be attacked. if (src != dsrc) { @@ -2126,7 +2119,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if (!status->check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skill_id, 2)) return 0; } else if ((flag&SD_ANIMATION) && skill->get_nk(skill_id)&NK_SPLASH) { - //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] + //Note that splash attacks often only check versus the targeted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] if (!status->check_skilluse(src, bl, skill_id, 2)) return 0; } @@ -2134,6 +2127,14 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, bl); + // To block skills that aren't called via battle_check_target [Panikon] + // issue: 8203 + if( sd + && ( (bl->type == BL_MOB && pc_has_permission(sd, PC_PERM_DISABLE_PVM)) + || (bl->type == BL_PC && pc_has_permission(sd, PC_PERM_DISABLE_PVP)) ) + ) + return 0; + sstatus = status->get_status_data(src); tstatus = status->get_status_data(bl); sc = status->get_sc(bl); @@ -2180,7 +2181,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr sc = NULL; //Don't need it. /* bugreport:2564 flag&2 disables double casting trigger */ flag |= 2; - /* bugreport:7859 magical reflect'd zeroes blewcount */ + /* 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 ) @@ -2202,11 +2203,11 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr #if MAGIC_REFLECTION_TYPE #ifdef RENEWAL - if( dmg.dmg_lv != ATK_MISS ) //Wiz SL cancelled and consumed fragment + if( dmg.dmg_lv != ATK_MISS ) // Wiz SL canceled and consumed fragment #else // issue:6415 in pre-renewal Kaite reflected the entire damage received - // regardless of caster's equipament (Aegis 11.1) - if( dmg.dmg_lv != ATK_MISS && type == 1 ) //Wiz SL cancelled and consumed fragment + // regardless of caster's equipment (Aegis 11.1) + if( dmg.dmg_lv != ATK_MISS && type == 1 ) //Wiz SL canceled and consumed fragment #endif { short s_ele = skill->get_ele(skill_id, skill_lv); @@ -2229,7 +2230,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); //Reduction: 6% + 6% every 20% dmg.damage -= dmg.damage * (6 * (1+per)) / 100; - } + } } #endif /* MAGIC_REFLECTION_TYPE */ } @@ -2324,10 +2325,11 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr combo=1; break; case AC_DOUBLE: - if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc->checkskill(sd, HT_POWER)) - { - //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] - sc_start2(NULL,src,SC_COMBOATTACK,100,HT_POWER,bl->id,2000); + // AC_DOUBLE can start the combo with other monster types, but the + // monster that's going to be hit by HT_POWER should be RC_BRUTE or RC_INSECT [Panikon] + if( pc->checkskill(sd, HT_POWER) ) + { + sc_start4(NULL,src,SC_COMBOATTACK,100,HT_POWER,0,1,0,2000); clif->combo_delay(src,2000); } break; @@ -2429,6 +2431,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case EL_ROCK_CRUSHER_ATK: case EL_HURRICANE: case EL_HURRICANE_ATK: + case EL_TYPOON_MIS: + case EL_TYPOON_MIS_ATK: case KO_BAKURETSU: case NC_MAGMA_ERUPTION: dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); @@ -2498,7 +2502,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr { //Updated to not be able to copy skills if the blow will kill you. [Skotlex] int copy_skill = skill_id, cidx = 0; /** - * Copy Referal: dummy skills should point to their source upon copying + * Copy Referral: dummy skills should point to their source upon copying **/ switch( skill_id ) { case AB_DUPLELIGHT_MELEE: @@ -2642,7 +2646,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr //blown-specific handling switch( skill_id ) { case LG_OVERBRAND_BRANDISH: - if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) < dmg.blewcount ) + if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) < dmg.blewcount ) skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION); break; case SR_KNUCKLEARROW: @@ -2730,15 +2734,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr * Post-damage effects **/ switch( skill_id ) { - case RK_CRUSHSTRIKE: - skill->break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. - break; case GC_VENOMPRESSURE: { struct status_change *ssc = status->get_sc(src); if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) { short rate = 100; - if ( ssc->data[SC_POISONINGWEAPON]->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech] + if ( ssc->data[SC_POISONINGWEAPON]->val1 == 9 )// Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] rate = 100 - tstatus->int_ * 4 / 5; sc_start(src, bl,ssc->data[SC_POISONINGWEAPON]->val2,rate,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); status_change_end(src,SC_POISONINGWEAPON,-1); @@ -2773,8 +2774,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } /*========================================== - * sub fonction for recursive skill call. - * Checking bl battle flag and display dammage + * sub function for recursive skill call. + * Checking bl battle flag and display damage * then call func with source,target,skill_id,skill_lv,tick,flag *------------------------------------------*/ int skill_area_sub(struct block_list *bl, va_list ap) { @@ -2965,7 +2966,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, if( (idx = skill->get_index(skill_id)) == 0 ) return 0; - // Requeriments + // Requirements for( i = 0; i < ARRAYLENGTH(itemid); i++ ) { itemid[i] = skill->db[idx].itemid[i]; @@ -2987,7 +2988,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, else sp += (st->max_sp * (-sp_rate)) / 100; - if( bl->type == BL_HOM ) { // Intimacy Requeriments + if( bl->type == BL_HOM ) { // Intimacy Requirements struct homun_data *hd = BL_CAST(BL_HOM, bl); switch( skill_id ) { case HFLI_SBR44: @@ -3095,10 +3096,11 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - case SR_FLASHCOMBO_ATK_STEP1: - case SR_FLASHCOMBO_ATK_STEP2: - case SR_FLASHCOMBO_ATK_STEP3: - case SR_FLASHCOMBO_ATK_STEP4: + // SR_FLASHCOMBO + case SR_DRAGONCOMBO: + case SR_FALLENEMPIRE: + case SR_TIGERCANNON: + case SR_SKYNETBLOW: break; default: continue; // Caster is Dead @@ -3122,6 +3124,9 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { map->foreachinarea(skill->frostjoke_scream,skl->map,skl->x-range,skl->y-range, skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick); break; + case KN_AUTOCOUNTER: + clif->skill_nodamage(src,target,skl->skill_id,skl->skill_lv,1); + break; case NPC_EARTHQUAKE: if( skl->type > 1 ) skill->addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); @@ -3160,7 +3165,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { BL_CHAR|BL_SKILL, target->id); // Search for a new Target around current one... if( nbl == NULL) skl->x++; - else + else skl->x = 0; skill->addtimerskill(src, tick + 651, (nbl?nbl:target)->id, skl->x, 0, WL_CHAINLIGHTNING_ATK, skl->skill_lv, skl->type + 1, skl->flag); @@ -3172,9 +3177,9 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: clif->skill_nodamage(src, target, skl->skill_id, skl->skill_lv, 1); - skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); + skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if( skl->type == 4 ){ + if( skl->type == 4 ){ const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used. int rate = skl->y, index = skl->x-1; sc_start2(src,target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1)); @@ -3211,22 +3216,23 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { map->foreachinrange(skill->area_sub, target, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, (int64)0, skl->flag|1|BCT_ENEMY, skill->castend_damage_id); break; - case SR_FLASHCOMBO_ATK_STEP1: - case SR_FLASHCOMBO_ATK_STEP2: - case SR_FLASHCOMBO_ATK_STEP3: - case SR_FLASHCOMBO_ATK_STEP4: - if( src->type == BL_PC ) { - struct map_session_data *sd = NULL; - const enum e_skill combos[] = {SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW}; - if( (sd = ((TBL_PC*)src)) ){ - uint16 cid = combos[skl->skill_id-SR_FLASHCOMBO_ATK_STEP1]; - if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) - break; - skill->consume_requirement(sd,cid,pc->checkskill(sd, cid),1); - skill->castend_damage_id(src, target, cid, pc->checkskill(sd, cid), tick, 0); - } + // SR_FLASHCOMBO + case SR_DRAGONCOMBO: + case SR_FALLENEMPIRE: + case SR_TIGERCANNON: + case SR_SKYNETBLOW: + { + struct map_session_data *sd = NULL; + + if( src->type == BL_PC && (sd = ((TBL_PC*)src)) ) { + if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) // FIXME: Don't combos ignore distance? [Panikon] + break; + + skill->consume_requirement(sd, skl->skill_id, pc->checkskill(sd, skl->skill_id),1); + skill->castend_damage_id(src, target, skl->skill_id, pc->checkskill(sd, skl->skill_id), tick, 0); } 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); @@ -3344,10 +3350,11 @@ int skill_cleartimerskill (struct block_list *src) case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - case SR_FLASHCOMBO_ATK_STEP1: - case SR_FLASHCOMBO_ATK_STEP2: - case SR_FLASHCOMBO_ATK_STEP3: - case SR_FLASHCOMBO_ATK_STEP4: + // SR_FLASHCOMBO + case SR_DRAGONCOMBO: + case SR_FALLENEMPIRE: + case SR_TIGERCANNON: + case SR_SKYNETBLOW: continue; } timer->delete(ud->skilltimerskill[i]->timer, skill->timerskill); @@ -3409,7 +3416,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 return 1; if (skill_id && skill->get_type(skill_id) == BF_MAGIC && status->isimmune(bl) == 100) { - //GTB makes all targetted magic display miss with a single bolt. + //GTB makes all targeted magic display miss with a single bolt. sc_type sct = status->skill2sc(skill_id); if(sct != SC_NONE) status_change_end(bl, sct, INVALID_TIMER); @@ -3492,7 +3499,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case WS_CARTTERMINATION: // Cart Termination case AS_VENOMKNIFE: case HT_PHANTASMIC: - case HT_POWER: case TK_DOWNKICK: case TK_COUNTER: case GS_CHAINACTION: @@ -3516,7 +3522,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case NPC_HELLPOWER: case RK_SONICWAVE: case RK_STORMBLAST: - case RK_CRUSHSTRIKE: case AB_DUPLELIGHT_MELEE: case RA_AIMEDBOLT: case NC_AXEBOOMERANG: @@ -3715,6 +3720,11 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 } break; + case HT_POWER: + if( tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT ) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; + //Splash attack skills. case AS_GRIMTOOTH: case MC_CARTREVOLUTION: @@ -3769,6 +3779,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case KO_MUCHANAGE: case KO_BAKURETSU: case GN_ILLUSIONDOPING: + case MH_XENO_SLASHER: if( flag&1 ) {//Recursive invocation // skill->area_temp[0] holds number of targets in area // skill->area_temp[1] holds the id of the original target @@ -3796,6 +3807,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case GC_ROLLINGCUTTER: flag |= SD_ANIMATION; 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); break; case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all? @@ -4048,7 +4060,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); break; - // Celest + // [Celest] case PF_SOULBURN: if (rnd()%100 < (skill_lv < 5 ? 30 + skill_lv * 10 : 70)) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -4133,7 +4145,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( unit->movepos(src, bl->x+x, bl->y+y, 1, 1) ) { clif->slide(src,bl->x+x,bl->y+y); - clif->fixpos(src); // the official server send these two packts. + clif->fixpos(src); // the official server send these two packets. skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); if( rnd()%100 < 4 * skill_lv ) skill->castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag); @@ -4190,7 +4202,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case WL_TETRAVORTEX: if( sc ){ int i = SC_SUMMON5, x = 0; - int types[][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; + int types[][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; for(; i >= SC_SUMMON1; i--){ if( sc->data[i] ){ int skillid = WL_TETRAVORTEX_FIRE + (sc->data[i]->val1 - WLS_FIRE) + (sc->data[i]->val1 == WLS_WIND) - (sc->data[i]->val1 == WLS_WATER), sc_index = 0, rate = 0; @@ -4266,7 +4278,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if (sd->skillcooldown[i].id == spell_skill_id){ cooldown += sd->skillcooldown[i].val; break; - } + } } if(cooldown) skill->blockpc_start(sd, spell_skill_id, cooldown); @@ -4556,9 +4568,8 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 } break; - //recursive homon skill + // Recursive homun skill case MH_MAGMA_FLOW: - case MH_XENO_SLASHER: case MH_HEILIGE_STANGE: if(flag & 1) skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); @@ -4764,10 +4775,10 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { inf &= ~BCT_NEUTRAL; } - if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) { - clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0); - break; - } + if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) { + clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0); + break; + } if( ud->skill_id >= SL_SKE && ud->skill_id <= SL_SKA && target->type == BL_MOB ) { @@ -4786,7 +4797,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { && (sc = status->get_sc(target)) && sc->data[SC_FOGWALL] && rnd() % 100 < 75 ) { - //Fogwall makes all offensive-type targetted skills fail at 75% + // Fogwall makes all offensive-type targeted skills fail at 75% if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0); break; } @@ -4837,8 +4848,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { unit->stop_walking(src,1); 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] - if (sd) { //Cooldown application + 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] + if (sd) { // Cooldown application int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv); for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. if (sd->skillcooldown[i].id == ud->skill_id){ @@ -4881,7 +4892,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { // SC_MAGICPOWER needs to switch states before any damage is actually dealt skill->toggle_magicpower(src, ud->skill_id); - /* On aegis damage skills are also increase by camouflage. Need confirmation on kRo. + /* On aegis damage skills are also increase by camouflage. Need confirmation on kRO. if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); */ @@ -4978,7 +4989,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int element = 0; enum sc_type type; - if(skill_id > 0 && !skill_lv) return 0; // celest + if(skill_id > 0 && !skill_lv) return 0; // [Celest] nullpo_retr(1, src); nullpo_retr(1, bl); @@ -5014,12 +5025,27 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } + // Supportive skills that can't be cast in users with mado + if( sd && dstsd && pc_ismadogear(dstsd) ) { + switch( skill_id ) { + case AL_HEAL: + case AL_INCAGI: + case AL_DECAGI: + case AB_RENOVATIO: + case AB_HIGHNESSHEAL: + clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); + return 0; + default: + break; + } + } + tstatus = status->get_status_data(bl); sstatus = status->get_status_data(src); //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] switch (skill_id) { - case HLIF_HEAL: //[orn] + case HLIF_HEAL: // [orn] if (bl->type != BL_HOM) { if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; break ; @@ -5031,11 +5057,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin **/ case AB_RENOVATIO: case AB_HIGHNESSHEAL: - case AL_INCAGI: - if( sd && dstsd && pc_ismadogear(dstsd) ){ - clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); - return 0; - } + case AL_INCAGI: case ALL_RESURRECTION: case PR_ASPERSIO: //Apparently only player casted skills can be offensive like this. @@ -5090,7 +5112,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin struct block_list *s_src = battle->get_master(src); short ret = 0; if(!skill->check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration - ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon + ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homun if(s_src && !skill->check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv)) ret |= skill->castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master if (hd) @@ -5133,7 +5155,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_lock(); switch(skill_id) { - case HLIF_HEAL: //[orn] + case HLIF_HEAL: // [orn] case AL_HEAL: /** * Arch Bishop @@ -5489,7 +5511,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (dstsd) { if(dstsd->status.weapon == W_FIST || (dstsd->sc.count && !dstsd->sc.data[type] && - ( //Allow re-enchanting to lenghten time. [Skotlex] + ( //Allow re-enchanting to lengthen time. [Skotlex] dstsd->sc.data[SC_PROPERTYFIRE] || dstsd->sc.data[SC_PROPERTYWATER] || dstsd->sc.data[SC_PROPERTYWIND] || @@ -5594,7 +5616,6 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case PR_BENEDICTIO: case LK_BERSERK: case MS_BERSERK: - case KN_AUTOCOUNTER: case KN_TWOHANDQUICKEN: case KN_ONEHAND: case MER_QUICKEN: @@ -5667,6 +5688,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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; + + case KN_AUTOCOUNTER: + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + skill->addtimerskill(src, tick + 100, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); + break; case SO_STRIKING: if (sd) { @@ -5707,7 +5733,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { int duration = skill->get_time(skill_id,skill_lv); clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,duration)); // Master - clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,duration)); // Homunc + clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,duration)); // Homun } break; case NJ_BUNSINJYUTSU: @@ -6041,7 +6067,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); break; - case HVAN_EXPLOSION: //[orn] + case HVAN_EXPLOSION: // [orn] case NPC_SELFDESTRUCTION: { //Self Destruction hits everyone in range (allies+enemies) @@ -6174,7 +6200,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 0; } clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit->getdir(bl),0,0,0)); - if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] + if (sd) // If the client receives a skill-use packet immediately before a walkok packet, it will discard the walk packet! [Skotlex] clif->walkok(sd); // So aegis has to resend the walk ok. break; case AS_CLOAKING: @@ -6410,7 +6436,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case MC_IDENTIFY: if(sd) { clif->item_identify_list(sd); - if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, dont consume anything, return */ + if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, don't consume anything, return */ map->freeblock_unlock(); return 1; } @@ -6752,7 +6778,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); if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) - || (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. + || (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends against dispel. || (dstsd && pc_ismadogear(dstsd)) || rnd()%100 >= 50+10*skill_lv ) { @@ -7062,7 +7088,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin unit->stop_attack(src); //Run skillv tiles overriding the can-move check. if (unit->walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md) - md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. + md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the AI. } break; @@ -7128,14 +7154,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 gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] + 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 gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] + 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); } break; @@ -7239,7 +7265,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // if it is already trapping something don't spring it, // remove trap should be used instead break; - // otherwise fallthrough to below + // otherwise fall through to below case UNT_BLASTMINE: case UNT_SKIDTRAP: case UNT_LANDMINE: @@ -7472,7 +7498,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (count == -1) count = 3; else - count++; //Should not retrigger this one. + count++; //Should not re-trigger this one. break; case 7: // stop freeze or stoned { @@ -7687,7 +7713,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; - case AM_CALLHOMUN: //[orn] + case AM_CALLHOMUN: // [orn] if( sd ) { if (homun->call(sd)) clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); @@ -7705,7 +7731,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; - case HAMI_CASTLE: //[orn] + case HAMI_CASTLE: // [orn] if(rnd()%100 < 20*skill_lv && src != bl) { int x,y; @@ -7715,7 +7741,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); if (unit->movepos(src,bl->x,bl->y,0,0)) { - clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc + clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homun clif->slide(src,bl->x,bl->y) ; if (unit->movepos(bl,x,y,0,0)) { @@ -7734,7 +7760,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin else if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; - case HVAN_CHAOTIC: //[orn] + case HVAN_CHAOTIC: // [orn] { static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; int r = rnd()%100; @@ -7755,7 +7781,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status->heal(bl, hp, 0, 0); } break; - //Homun single-target support skills [orn] + // Homun single-target support skills [orn] case HAMI_BLOODLUST: case HFLI_FLEET: case HFLI_SPEED: @@ -8007,7 +8033,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { // Every time the skill is casted the status change is reseted adding a counter. count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; if( count > 10 ) - count = 10; // Max coounter + count = 10; // Max counter status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); } sc_start(src,bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); @@ -8113,15 +8139,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( dstsd && dstsd->special_state.no_magic_damage ) break; - if ( sd && sd->status.party_id == 0 ) - count = 1; - else - count = party->foreachsamemap(party->sub_count, sd, 0); + if( sd && sd->status.party_id != 0 ) + count = party->foreachsamemap(party->sub_count, sd, 0); - if (count > 0) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start4(src, bl, type, 100, skill_lv, 0, 0, count, skill->get_time(skill_id, skill_lv))); - } else + clif->skill_nodamage(bl, bl, skill_id, skill_lv, + sc_start4(src, bl, type, 100, skill_lv, 0, 0, count, skill->get_time(skill_id, skill_lv))); + } else if( sd ) party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; case AB_CHEAL: @@ -8526,7 +8549,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //First we set the success chance based on the caster's build which increases the chance. rate = 10 * skill_lv + rnd_value( sstatus->dex / 12, sstatus->dex / 4 ) + joblvbonus + status->get_lv(src) / 10; // We then reduce the success chance based on the target's build. - rate -= rnd_value( tstatus->agi / 6, tstatus->agi / 3 ) - tstatus->luk / 10 - ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0 ) - status->get_lv(bl) / 10; + rate -= rnd_value( tstatus->agi / 6, tstatus->agi / 3 ) + tstatus->luk / 10 + ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0 ) + status->get_lv(bl) / 10; //Finally we set the minimum success chance cap based on the caster's skill level and DEX. rate = cap_value( rate, skill_lv + sstatus->dex / 20, 100); clif->skill_nodamage(src,bl,skill_id,0,sc_start(src,bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv))); @@ -8539,7 +8562,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } if ( tsc && tsc->data[SC__UNLUCKY] && skill_id == SC_UNLUCKY) { //If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's. - switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's reguardless of resistance. + switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's regardless of resistance. case 0: status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10); break; @@ -8568,9 +8591,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case LG_SHIELDSPELL: + if( !sd ) + break; if( flag&1 ) { sc_start(src,bl,SC_SILENCE,100,skill_lv,sd->bonus.shieldmdef * 30000); - } else if( sd ) { + } else { int opt = 0, val = 0, splashrange = 0; struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; if( !shield_data || shield_data->type != IT_ARMOR ) { @@ -8607,6 +8632,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; case 2: + if( sd->bonus.shieldmdef == 0 ) + break; // Nothing should happen if the shield has no mdef, not even displaying a message if ( sd->bonus.shieldmdef >= 1 && sd->bonus.shieldmdef <= 3 ) splashrange = 1; else if ( sd->bonus.shieldmdef >= 4 && sd->bonus.shieldmdef <= 5 ) @@ -8634,8 +8661,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case 3: { - struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; int rate = 0; + struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; + + if( shield->refine == 0 ) + break; // Nothing should happen if the shield has no refine, not even displaying a message + switch( opt ) { case 1: sc_start(src,bl,SC_SHIELDSPELL_REF,100,opt,shield->refine * 30000); //Now breaks Armor at 100% rate @@ -8723,7 +8754,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); - count = map->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors + 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); clif->skill_nodamage(src, src, skill_id, skill_lv, @@ -8749,8 +8780,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { sp = dstsd->spiritball; //1%sp per spiritball. pc->delspiritball(dstsd, dstsd->spiritball, 0); + status_percent_heal(src, 0, sp); } - if( sp ) status_percent_heal(src, 0, sp); 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); @@ -8801,16 +8832,23 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SR_GENTLETOUCH_CHANGE: case SR_GENTLETOUCH_REVITALIZE: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + sc_start2(src,bl,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv))); break; case SR_FLASHCOMBO: { + const int combo[] = { + SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW + }; int i; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - for(i = SR_FLASHCOMBO_ATK_STEP1; i <= SR_FLASHCOMBO_ATK_STEP4; i++) - skill->addtimerskill(src, tick + 400 * (i - SR_FLASHCOMBO_ATK_STEP1), bl->id, 0, 0, i, skill_lv, BF_WEAPON, flag|SD_LEVEL); + + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(src,bl,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv))); + + for( i = 0; i < ARRAYLENGTH(combo); i++ ) + skill->addtimerskill(src, tick + 400 * i, bl->id, 0, 0, combo[i], skill_lv, BF_WEAPON, flag|SD_LEVEL); + + break; } - break; case WA_SWING_DANCE: case WA_SYMPHONY_OF_LOVER: case WA_MOONLIT_SERENADE: @@ -8851,7 +8889,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if ( flag&1 ) sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); else if ( sd ) { - int rate = 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 1) + status->get_lv(src) / 15 + (sd? sd->status.job_level:0) / 5; + int rate = 4 * skill_lv + 2 * pc->checkskill(sd,WM_LESSON) + status->get_lv(src)/15 + sd->status.job_level/5; if ( rnd()%100 < rate ) { flag |= BCT_PARTY|BCT_GUILD; map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_NPC|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); @@ -8868,7 +8906,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( flag&1 ) { sc_start2(src,bl,type,100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv)); } else if( sd ) { - int rate = 6 * skill_lv + (sd ? pc->checkskill(sd,WM_LESSON) : 1) + (sd? sd->status.job_level:0) / 2; + int rate = 6 * skill_lv + pc->checkskill(sd,WM_LESSON) + sd->status.job_level/2; if ( rnd()%100 < rate ) { flag |= BCT_PARTY|BCT_GUILD; map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_NPC|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); @@ -8912,7 +8950,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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)); - //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 dealed as reflected damage which I dont have it coded like that yet. [Rytech] + //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; if ( rnd()%100 < rate ) { @@ -9038,7 +9076,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { int elemental_class = skill->get_elemental_type(skill_id,skill_lv); - // Remove previous elemental fisrt. + // Remove previous elemental first. if( sd->ed ) elemental->delete(sd->ed,0); @@ -9061,7 +9099,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin elemental->delete(sd->ed, 0); break; } - switch( skill_lv ) {// Select mode bassed on skill level used. + switch( skill_lv ) {// Select mode based on skill level used. case 2: mode = EL_MODE_ASSIST; break; case 3: mode = EL_MODE_AGGRESSIVE; break; } @@ -9397,10 +9435,23 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; + case MH_LIGHT_OF_REGENE: + if( hd && battle->get_master(src) ) { + hd->homunculus.intimacy = (751 + rnd()%99) * 100; // random between 751 ~ 850 + clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100); //refresh intimacy info + sc_start(src, battle->get_master(src), type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + } + break; + + case MH_OVERED_BOOST: + if ( hd && battle->get_master(src) ) { + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, battle->get_master(src), type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + } + break; + case MH_SILENT_BREEZE: { - struct status_change *ssc = status->get_sc(src); - struct block_list *m_bl = battle->get_master(src); const enum sc_type scs[] = { SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION }; @@ -9410,40 +9461,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin for (i = 0; i < ARRAYLENGTH(scs); i++) { if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); } - if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target - status->change_start(src, bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); } - heal = status_get_matk_min(src)*4; - status->heal(bl, heal, 0, 7); - - //now inflict silence on everyone - if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status->change_start(src, src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); - if(m_bl){ - struct status_change *msc = status->get_sc(m_bl); - if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status->change_start(src, m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); - } - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl)); + status->heal(bl, heal, 0, 0); + clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1)); + status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8); + status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8); } break; - case MH_OVERED_BOOST: - if (hd) { - struct block_list *s_bl = battle->get_master(src); - if(hd->homunculus.hunger>50) //reduce hunger - hd->homunculus.hunger = hd->homunculus.hunger/2; - else - hd->homunculus.hunger = min(1,hd->homunculus.hunger); - if(s_bl && s_bl->type==BL_PC) { - status->set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp - clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info - sc_start(src, s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus - } - sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - } - break; + case MH_GRANITIC_ARMOR: case MH_PYROCLASTIC: if( hd ){ @@ -9458,12 +9484,6 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; - case MH_LIGHT_OF_REGENE: - if(hd) { - hd->homunculus.intimacy = 25100; //change to neutral (can't be cast if < 750) - if(sd) clif->send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info - } - //don't break need to start status and start block timer case MH_MAGMA_FLOW: case MH_PAIN_KILLER: sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); @@ -9759,10 +9779,15 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char switch(skill_id) { case AL_TELEPORT: + // The storage window is closed automatically by the client when there's + // any kind of map change, so we need to restore it automatically + // issue: 8027 if(strcmp(mapname,"Random")==0) pc->randomwarp(sd,CLR_TELEPORT); else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + + clif->refresh_storagewindow(sd); break; case AL_WARP: @@ -9852,7 +9877,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui int r; //if(skill_lv <= 0) return 0; - if(skill_id > 0 && !skill_lv) return 0; // celest + if(skill_id > 0 && !skill_lv) return 0; // [Celest] nullpo_ret(src); @@ -10047,10 +10072,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case MH_VOLCANIC_ASH: case MH_POISON_MIST: case MH_STEINWAND: - case MH_XENO_SLASHER: case NC_MAGMA_ERUPTION: case SO_ELEMENTAL_SHIELD: case RL_B_TRAP: + case MH_XENO_SLASHER: flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). case GS_GROUNDDRIFT: //Ammo should be deleted right away. skill->unitsetting(src,skill_id,skill_lv,x,y,0); @@ -10158,7 +10183,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui int class_ = skill_id==AM_SPHEREMINE?1142:summons[skill_lv-1]; struct mob_data *md; - // Correct info, don't change any of this! [celest] + // Correct info, don't change any of this! [Celest] md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE); if (md) { md->master_id = src->id; @@ -10298,7 +10323,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui sc_start(src,src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; - case AM_RESURRECTHOMUN: //[orn] + case AM_RESURRECTHOMUN: // [orn] if (sd) { if (!homun->ressurect(sd, 20*skill_lv, x, y)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -10320,7 +10345,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case WM_SOUND_OF_DESTRUCTION: r = skill->get_splash(skill_id,skill_lv); map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - break; + break; case WM_LULLABY_DEEPSLEEP: r = skill->get_splash(skill_id,skill_lv); @@ -10610,14 +10635,22 @@ int skill_dance_overlap(struct skill_unit* su, int flag) { return map->foreachincell(skill->dance_overlap_sub, su->bl.m,su->bl.x,su->bl.y,BL_SKILL, su,flag); } -/*========================================== +/** * Converts this group information so that it is handled as a Dissonance or Ugly Dance cell. - * Flag: 0 - Convert, 1 - Revert. - *------------------------------------------*/ + * This function is safe to call even when the unit or the group were freed by other function + * previously. + * @param su Skill unit data (from BA_DISSONANCE or DC_UGLYDANCE) + * @param flag 0 Convert + * @param flag 1 Revert + * @retval true success + **/ bool skill_dance_switch(struct skill_unit* su, int flag) { static int prevflag = 1; // by default the backup is empty static struct skill_unit_group backup; - struct skill_unit_group* group = su->group; + struct skill_unit_group* group; + + if( su == NULL || (group = su->group) == NULL ) + return false; // val2&UF_ENSEMBLE is a hack to indicate dissonance if ( !(group->state.song_dance&0x1 && su->val2&UF_ENSEMBLE) ) @@ -11674,7 +11707,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_FIREPILLAR_ACTIVE: case UNT_CLAYMORETRAP: if( sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP ) - map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl,tick); + map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl,tick); else map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) @@ -11876,7 +11909,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_POISONSMOKE: if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 50 ) { short rate = 100; - if ( sg->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech] + if ( sg->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] rate = 100 - tstatus->int_ * 4 / 5 ; sc_start(ss,bl,sg->val2,rate,sg->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); } @@ -11911,7 +11944,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_STEALTHFIELD: if( bl->id == sg->src_id ) - break; // Dont work on Self (video shows that) + break; // Don't work on Self (video shows that) case UNT_NEUTRALBARRIER: sc_start(ss,bl,type,100,sg->skill_lv,sg->interval + 100); break; @@ -12193,8 +12226,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { //We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance. //FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner, //it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble - //which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel - //your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it. + //which overlaps, by stepping outside of the other partner's ensemble will cause you to cancel + //your own. Let's pray that scenario is pretty unlikely and none will complain too much about it. status_change_end(bl, SC_DANCING, INVALID_TIMER); } case MH_STEINWAND: @@ -12240,7 +12273,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { if (sce) { status_change_end(bl, type, INVALID_TIMER); if ((sce=sc->data[SC_BLIND])) { - if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex] + if (bl->type == BL_PC) //Players get blind ended immediately, others have it still for 30 secs. [Skotlex] status_change_end(bl, SC_BLIND, INVALID_TIMER); else { timer->delete(sce->timer, status->change_timer); @@ -12646,6 +12679,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id // Check the skills that can be used while mounted on a warg if( pc_isridingwug(sd) ) { switch( skill_id ) { + // Hunter skills case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: @@ -12655,43 +12689,39 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case HT_FREEZINGTRAP: case HT_BLASTMINE: case HT_CLAYMORETRAP: - case HT_SPRINGTRAP: + case HT_TALKIEBOX: + // Ranger skills case RA_DETONATOR: + case RA_ELECTRICSHOCKER: case RA_CLUSTERBOMB: - case HT_TALKIEBOX: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: case RA_WUGDASH: case RA_WUGRIDER: case RA_WUGSTRIKE: + // Other + case BS_GREED: break; default: // in official there is no message. return 0; } } + + // Check the skills that can be used whiled using mado if( pc_ismadogear(sd) ) { - switch( skill_id ) { //None Mado skills are unusable when Mado is equipped. [Jobbie] - case BS_REPAIRWEAPON: - case WS_MELTDOWN: - case BS_HAMMERFALL: - case WS_CARTBOOST: - case BS_ADRENALINE: - case WS_WEAPONREFINE: - case BS_WEAPONPERFECT: - case WS_CARTTERMINATION: - case BS_OVERTHRUST: - case WS_OVERTHRUSTMAX: - case BS_MAXIMIZE: - case BS_ADRENALINE2: - case BS_UNFAIRLYTRICK: - case BS_GREED: - clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0); - return 0; - default: //Only Mechanic exlcusive skill can be used. - break; + if( !(skill_id > NC_MADOLICENCE && skill_id <= NC_DISJOINT) + && skill_id != NC_MAGMA_ERUPTION + && skill_id != BS_GREED ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0); + return 0; } } + if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return 0; @@ -13001,7 +13031,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; } break; - case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80% + case AM_REST: //Can't vapo homun if you don't have an active homun or it's hp is < 80% if (!homun_alive(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -13042,14 +13072,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case WL_COMET: { int idx; + + if( !require.itemid[0] ) // issue: 7935 + break; if( skill->check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && ((idx = pc->search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[idx].amount < require.amount[0]) ) { //clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } - } break; + } case WL_SUMMONFB: case WL_SUMMONBL: case WL_SUMMONWB: @@ -13059,7 +13092,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id { int j, i = 0; for(j = SC_SUMMON1; j <= SC_SUMMON5; j++) - if( sc && sc->data[j] ) + if( sc && sc->data[j] ) i++; switch(skill_id){ @@ -13438,7 +13471,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id // There's no need to check if the skill is part of a combo if it's // already been checked before, see unit_skilluse_id2 [Panikon] - // Note that if this check is readded part of issue:8047 will reapear! + // Note that if this check is read part of issue:8047 will reappear! //if( sd->sc.data[SC_COMBOATTACK] && !skill->is_combo(skill_id ) ) // return 0; @@ -13686,7 +13719,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin continue; if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD ) - continue; //Gemstones are checked, but not substracted from inventory. + continue; //Gemstones are checked, but not subtracted from inventory. switch( skill_id ){ case SA_SEISMICWEAPON: @@ -13881,7 +13914,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN ) { if( sd->special_state.no_gemstone ) - { // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card -helvetica + { // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card [helvetica] if( skill_id != SA_ABRACADABRA ) req.itemid[i] = req.amount[i] = 0; else if( --req.amount[i] < 1 ) @@ -14129,9 +14162,9 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 if( sd->bonus.varcastrate < 0 ) VARCAST_REDUCTION(sd->bonus.varcastrate); if( sd->bonus.add_varcast != 0 ) // bonus bVariableCast - time += sd->bonus.add_varcast; + time += sd->bonus.add_varcast; if( sd->bonus.add_fixcast != 0 ) // bonus bFixedCast - fixed += sd->bonus.add_fixcast; + fixed += sd->bonus.add_fixcast; for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++) if (sd->skillfixcast[i].id == skill_id){ // bonus2 bSkillFixedCast fixed += sd->skillfixcast[i].val; @@ -14202,7 +14235,7 @@ 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) ) + 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)}] % // Fixed cast non percentage bonuses if( sc->data[SC_MANDRAGORA] ) @@ -15038,7 +15071,7 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) { if( su == NULL || su->group == NULL || (*alive) == 0 ) return 0; - if( su->group->state.guildaura ) /* guild auras are not cancelled! */ + if( su->group->state.guildaura ) /* guild auras are not canceled! */ return 0; switch (skill_id) { @@ -15290,6 +15323,36 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce return wall; } + +/** + * Verifies if an user can use SC_CLOAKING + **/ +bool skill_can_cloak(struct map_session_data *sd) { + nullpo_retr(false, sd); + + //Avoid cloaking with no wall and low skill level. [Skotlex] + //Due to the cloaking card, we have to check the wall versus to known + //skill level rather than the used one. [Skotlex] + //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) + if (pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(&sd->bl,NULL)) + return false; + + return true; +} + +/** + * Verifies if an user can still be cloaked (AS_CLOAKING) + * Is called via map->foreachinrange when any kind of wall disapears + **/ +int skill_check_cloaking_end(struct block_list *bl, va_list ap) { + TBL_PC *sd = BL_CAST(BL_PC, bl); + + if (sd && sd->sc.data[SC_CLOAKING] && !skill->can_cloak(sd)) + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + + return 0; +} + bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce) { static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; @@ -15328,7 +15391,7 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit){ if( sc && sc->data[SC__SHADOWFORM] && damage ) { src = map->id2bl(sc->data[SC__SHADOWFORM]->val2); - if( !src || src->m != bl->m ) { + if( !src || src->m != bl->m ) { status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); return false; } @@ -15438,6 +15501,13 @@ int skill_delunit (struct skill_unit* su) { clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,su->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); map->list[su->bl.m].icewall_num--; + // AS_CLOAKING in low levels requires a wall to be cast, thus it needs to be + // checked again when a wall disapears! issue:8182 [Panikon] + map->foreachinarea(skill->check_cloaking_end, su->bl.m, + // Use 3x3 area to check for users near cell + su->bl.x - 1, su->bl.y - 1, + su->bl.x + 1, su->bl.x + 1, + BL_PC); break; case SA_LANDPROTECTOR: skill->unitsetmapcell(su,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); @@ -15452,7 +15522,7 @@ int skill_delunit (struct skill_unit* su) { } break; case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) - if( group->val2 ) { // Someone Traped + if( group->val2 ) { // Someone Trapped struct status_change *tsc = status->get_sc(map->id2bl(group->val2)); if( tsc && tsc->data[SC__MANHOLE] ) tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID @@ -15599,7 +15669,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin struct status_change* sc = status->get_sc(src); if (sc && sc->data[SC_DANCING]) { - sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex] + sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to re-delete the group. [Skotlex] status_change_end(src, SC_DANCING, INVALID_TIMER); } } @@ -15981,7 +16051,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { return 0; } /*========================================== - * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds. + * Executes on all skill units every SKILLUNITTIMER_INTERVAL milliseconds. *------------------------------------------*/ int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) { map->freeblock_lock(); @@ -16073,9 +16143,6 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap) { } } - //TODO: Normally, this is dangerous since the unit and group could be freed - //inside the onout/onplace functions. Currently it is safe because we know song/dance - //cells do not get deleted within them. [Skotlex] if( dissonance ) skill->dance_switch(su, 1); if( flag&4 ) @@ -16388,7 +16455,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, make_per = 100000; // Star Crumbs are 100% success crafting rate? (made 1000% so it succeeds even after penalties) [Skotlex] break; default: // Enchanted Stones - make_per += 1000+i*500; // Enchantedstone Craft bonus: +15/+20/+25/+30/+35 + make_per += 1000+i*500; // Enchanted stone Craft bonus: +15/+20/+25/+30/+35 break; } break; @@ -16436,7 +16503,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, case ITEMID_COATING_BOTTLE: make_per -= (1+rnd()%100)*10; break; - //Common items, recieve no bonus or penalty, listed just because they are commonly produced + //Common items, receive no bonus or penalty, listed just because they are commonly produced case ITEMID_BLUE_POTION: case ITEMID_RED_SLIM_POTION: case ITEMID_ANODYNE: @@ -17339,7 +17406,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) return 0; } -int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) { //[orn] +int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) { // [orn] struct homun_data *hd = (TBL_HOM*)map->id2bl(id); if (data <= 0 || data >= MAX_SKILL) return 0; @@ -17348,7 +17415,7 @@ int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) { //[orn] return 1; } -int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { //[orn] +int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { // [orn] uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, hd); @@ -17364,7 +17431,7 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { / return timer->add(timer->gettick() + tick, skill->blockhomun_end, hd->bl.id, idx); } -int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data) {//[orn] +int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data) {// [orn] struct mercenary_data *md = (TBL_MER*)map->id2bl(id); if( data <= 0 || data >= MAX_SKILL ) return 0; @@ -17952,7 +18019,7 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) { skill->split_atoi(split[5],skill->db[idx].sp_rate); skill->split_atoi(split[6],skill->db[idx].zeny); - //Wich weapon type are required, see doc/item_db for types + //Which weapon type are required, see doc/item_db for types p = split[7]; for( j = 0; j < 32; j++ ) { int l = atoi(p); @@ -18449,7 +18516,7 @@ void skill_defaults(void) { memset(&skill->area_temp,0,sizeof(skill->area_temp)); memset(&skill->unit_temp,0,sizeof(skill->unit_temp)); skill->unit_group_newid = 0; - /* accesssors */ + /* accessors */ skill->get_index = skill_get_index; skill->get_type = skill_get_type; skill->get_hit = skill_get_hit; @@ -18520,7 +18587,7 @@ void skill_defaults(void) { skill->unit_onplace = skill_unit_onplace; skill->unit_ondamaged = skill_unit_ondamaged; skill->cast_fix = skill_castfix; - skill->cast_fix_sc = skill_castfix_sc; + skill->cast_fix_sc = skill_castfix_sc; skill->vf_cast_fix = skill_vfcastfix; skill->delay_fix = skill_delay_fix; skill->check_condition_castbegin = skill_check_condition_castbegin; @@ -18540,6 +18607,8 @@ void skill_defaults(void) { skill->autospell = skill_autospell; skill->calc_heal = skill_calc_heal; skill->check_cloaking = skill_check_cloaking; + skill->check_cloaking_end = skill_check_cloaking_end; + skill->can_cloak = skill_can_cloak; skill->enchant_elemental_end = skill_enchant_elemental_end; skill->not_ok = skillnotok; skill->not_ok_hom = skillnotok_hom; diff --git a/src/map/skill.h b/src/map/skill.h index dda310bd4..352e31f9e 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -2,22 +2,26 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_SKILL_H_ -#define _MAP_SKILL_H_ +#ifndef MAP_SKILL_H +#define MAP_SKILL_H + +#include "../config/core.h" // RENEWAL_CAST -#include "../common/mmo.h" // MAX_SKILL, struct square -#include "../common/db.h" #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 /** * Declarations **/ -struct map_session_data; struct homun_data; +struct map_session_data; +struct mercenary_data; struct skill_unit; -struct skill_unit_group; -struct status_change_entry; struct square; +struct status_change_entry; /** * Defines @@ -162,7 +166,7 @@ enum { enum e_skill { NV_BASIC = 1, - + SM_SWORD, SM_TWOHAND, SM_RECOVERY, @@ -170,7 +174,7 @@ enum e_skill { SM_PROVOKE, SM_MAGNUM, SM_ENDURE, - + MG_SRECOVERY, MG_SIGHT, MG_NAPALMBEAT, @@ -184,7 +188,7 @@ enum e_skill { MG_FIREBOLT, MG_LIGHTNINGBOLT, MG_THUNDERSTORM, - + AL_DP, AL_DEMONBANE, AL_RUWACH, @@ -199,7 +203,7 @@ enum e_skill { AL_ANGELUS, AL_BLESSING, AL_CURE, - + MC_INCCARRY, MC_DISCOUNT, MC_OVERCHARGE, @@ -207,22 +211,22 @@ enum e_skill { MC_IDENTIFY, MC_VENDING, MC_MAMMONITE, - + AC_OWL, AC_VULTURE, AC_CONCENTRATION, AC_DOUBLE, AC_SHOWER, - + TF_DOUBLE, TF_MISS, TF_STEAL, TF_HIDING, TF_POISON, TF_DETOXIFY, - + ALL_RESURRECTION, - + KN_SPEARMASTERY, KN_PIERCE, KN_BRANDISHSPEAR, @@ -233,7 +237,7 @@ enum e_skill { KN_BOWLINGBASH, KN_RIDING, KN_CAVALIERMASTERY, - + PR_MACEMASTERY, PR_IMPOSITIO, PR_SUFFRAGIUM, @@ -249,7 +253,7 @@ enum e_skill { PR_TURNUNDEAD, PR_LEXAETERNA, PR_MAGNUS, - + WZ_FIREPILLAR, WZ_SIGHTRASHER, WZ_FIREIVY, @@ -264,7 +268,7 @@ enum e_skill { WZ_HEAVENDRIVE, WZ_QUAGMIRE, WZ_ESTIMATION, - + BS_IRON, BS_STEEL, BS_ENCHANTEDSTONE, @@ -286,7 +290,7 @@ enum e_skill { BS_WEAPONPERFECT, BS_OVERTHRUST, BS_MAXIMIZE, - + HT_SKIDTRAP, HT_LANDMINE, HT_ANKLESNARE, @@ -304,7 +308,7 @@ enum e_skill { HT_BLITZBEAT, HT_DETECTING, HT_SPRINGTRAP, - + AS_RIGHT, AS_LEFT, AS_KATAR, @@ -315,7 +319,7 @@ enum e_skill { AS_POISONREACT, AS_VENOMDUST, AS_SPLASHER, - + NV_FIRSTAID, NV_TRICKDEAD, SM_MOVINGRECOVERY, @@ -332,7 +336,7 @@ enum e_skill { MC_LOUD, AL_HOLYLIGHT, MG_ENERGYCOAT, - + NPC_PIERCINGATT, NPC_MENTALBREAKER, NPC_RANGEATTACK, @@ -385,7 +389,7 @@ enum e_skill { NPC_HALLUCINATION, NPC_REBIRTH, NPC_SUMMONMONSTER, - + RG_SNATCHER, RG_STEALCOIN, RG_BACKSTAP, @@ -402,7 +406,7 @@ enum e_skill { RG_GANGSTER, RG_COMPULSION, RG_PLAGIARISM, - + AM_AXEMASTERY, AM_LEARNINGPOTION, AM_PHARMACY, @@ -425,7 +429,7 @@ enum e_skill { AM_DRILLMASTER, AM_HEALHOMUN, AM_RESURRECTHOMUN, - + CR_TRUST, CR_AUTOGUARD, CR_SHIELDCHARGE, @@ -437,7 +441,7 @@ enum e_skill { CR_PROVIDENCE, CR_DEFENDER, CR_SPEARQUICKEN, - + MO_IRONHAND, MO_SPIRITSRECOVERY, MO_CALLSPIRITS, @@ -453,7 +457,7 @@ enum e_skill { MO_EXTREMITYFIST, MO_CHAINCOMBO, MO_COMBOFINISH, - + SA_ADVANCEDBOOK, SA_CASTCANCEL, SA_MAGICROD, @@ -484,7 +488,7 @@ enum e_skill { SA_INSTANTDEATH, SA_FULLRECOVERY, SA_COMA, - + BD_ADAPTATION, BD_ENCORE, BD_LULLABY, @@ -496,7 +500,7 @@ enum e_skill { BD_INTOABYSS, BD_SIEGFRIED, BD_RAGNAROK, - + BA_MUSICALLESSON, BA_MUSICALSTRIKE, BA_DISSONANCE, @@ -505,7 +509,7 @@ enum e_skill { BA_ASSASSINCROSS, BA_POEMBRAGI, BA_APPLEIDUN, - + DC_DANCINGLESSON, DC_THROWARROW, DC_UGLYDANCE, @@ -514,17 +518,17 @@ enum e_skill { DC_DONTFORGETME, DC_FORTUNEKISS, DC_SERVICEFORYOU, - + NPC_RANDOMMOVE, NPC_SPEEDUP, NPC_REVENGE, - + WE_MALE, WE_FEMALE, WE_CALLPARTNER, - + ITM_TOMAHAWK, - + NPC_DARKCROSS, NPC_GRANDDARKNESS, NPC_DARKSTRIKE, @@ -542,7 +546,7 @@ enum e_skill { NPC_CALLSLAVE, NPC_INVISIBLE, NPC_RUN, - + LK_AURABLADE, LK_PARRYING, LK_CONCENTRATION, @@ -596,10 +600,11 @@ enum e_skill { PF_SPIDERWEB, ASC_METEORASSAULT, ASC_CDP, + WE_BABY, WE_CALLPARENT, WE_CALLBABY, - + TK_RUN, TK_READYSTORM, TK_STORMKICK, @@ -616,7 +621,7 @@ enum e_skill { TK_POWER, TK_SEVENWIND, TK_HIGHJUMP, - + SG_FEEL, SG_SUN_WARM, SG_MOON_WARM, @@ -635,7 +640,7 @@ enum e_skill { SG_FRIEND, SG_KNOWLEDGE, SG_FUSION, - + SL_ALCHEMIST, AM_BERSERKPITCHER, SL_MONK, @@ -664,7 +669,7 @@ enum e_skill { SL_SWOO, SL_SKE, SL_SKA, - + SM_SELFPROVOKE, NPC_EMOTION_ON, ST_PRESERVE, @@ -692,7 +697,7 @@ enum e_skill { AM_TWILIGHT2, AM_TWILIGHT3, HT_POWER, - + GS_GLITTERING, GS_FLING, GS_TRIPLEACTION, @@ -715,7 +720,7 @@ enum e_skill { GS_FULLBUSTER, GS_SPREADATTACK, GS_GROUNDDRIFT, - + NJ_TOBIDOUGU, NJ_SYURIKEN, NJ_KUNAI, @@ -739,7 +744,7 @@ enum e_skill { NJ_KAMAITACHI, NJ_NEN, NJ_ISSEN, - + MB_FIGHTING, MB_NEUTRAL, MB_TAIMING_PUTI, @@ -767,7 +772,7 @@ enum e_skill { MB_M_WALLCRASH, MB_M_REINCARNATION, MB_B_EQUIP, - + SL_DEATHKNIGHT, SL_COLLECTOR, SL_NINJA, @@ -776,7 +781,7 @@ enum e_skill { DA_RESET, DE_BERSERKAIZER, DA_DARKPOWER, - + DE_PASSIVE, DE_PATTACK, DE_PSPEED, @@ -816,7 +821,7 @@ enum e_skill { DE_TWINATTACK, DE_WINDATTACK, DE_WATERATTACK, - + DA_ENERGY, DA_CLOUD, DA_FIRSTSLOT, @@ -851,7 +856,7 @@ enum e_skill { ALL_TIMEIN, DA_ZENYRANK, DA_ACCESSORYMIX, - + NPC_EARTHQUAKE, NPC_FIREBREATH, NPC_ICEBREATH, @@ -880,7 +885,6 @@ enum e_skill { NPC_WIDESTUN, NPC_VAMPIRE_GIFT, NPC_WIDESOULDRAIN, - ALL_INCCARRY, NPC_TALK, NPC_HELLPOWER, @@ -909,6 +913,23 @@ enum e_skill { NPC_VENOMFOG, NPC_MILLENNIUMSHIELD, NPC_COMET, +// TODO: What PACKETVER are these skills added? [Panikon] +// After this addition all skills from NPC_WIDEWEB to NPC_LEX_AETERNA +// will have their IDs changed +#if PACKETVER >= 20140205 + NPC_ICEMINE, + NPC_ICEEXPLO, + NPC_FLAMECROSS, + NPC_PULSESTRIKE2, + NPC_DANCINGBLADE, + NPC_DANCINGBLADE_ATK, + NPC_DARKPIERCING, + NPC_MAXPAIN, + NPC_MAXPAIN_ATK, + NPC_DEATHSUMMON, + NPC_HELLBURNING, + NPC_JACKFROST, +#endif NPC_WIDEWEB, NPC_WIDESUCK, NPC_STORMGUST2, @@ -936,7 +957,7 @@ enum e_skill { SA_ELEMENTGROUND, SA_ELEMENTFIRE, SA_ELEMENTWIND, - + RK_ENCHANTBLADE = 2001, RK_SONICWAVE, RK_DEATHBOUND, @@ -957,7 +978,7 @@ enum e_skill { RK_FIGHTINGSPIRIT, RK_ABUNDANCE, RK_PHANTOMTHRUST, - + GC_VENOMIMPRESS, GC_CROSSIMPACT, GC_DARKILLUSION, @@ -975,7 +996,7 @@ enum e_skill { GC_HALLUCINATIONWALK, GC_ROLLINGCUTTER, GC_CROSSRIPPERSLASHER, - + AB_JUDEX, AB_ANCILLA, AB_ADORAMUS, @@ -996,7 +1017,7 @@ enum e_skill { AB_DUPLELIGHT_MELEE, AB_DUPLELIGHT_MAGIC, AB_SILENTIUM, - + WL_WHITEIMPRISON = 2201, WL_SOULEXPANSION, WL_FROSTMISTY, @@ -1029,7 +1050,7 @@ enum e_skill { WL_RELEASE, WL_READING_SB, WL_FREEZE_SP, - + RA_ARROWSTORM, RA_FEARBREEZE, RA_RANGERMAIN, @@ -1052,7 +1073,7 @@ enum e_skill { RA_VERDURETRAP, RA_FIRINGTRAP, RA_ICEBOUNDTRAP, - + NC_MADOLICENCE, NC_BOOSTKNUCKLE, NC_PILEBUNKER, @@ -1082,7 +1103,7 @@ enum e_skill { NC_SILVERSNIPER, NC_MAGICDECOY, NC_DISJOINT, - + SC_FATALMENACE, SC_REPRODUCE, SC_AUTOSHADOWSPELL, @@ -1104,7 +1125,7 @@ enum e_skill { SC_MAELSTROM, SC_BLOODYLUST, SC_FEINTBOMB, - + LG_CANNONSPEAR = 2307, LG_BANISHINGPOINT, LG_TRAMPLE, @@ -1124,7 +1145,7 @@ enum e_skill { LG_EARTHDRIVE, LG_HESPERUSLIT, LG_INSPIRATION, - + SR_DRAGONCOMBO, SR_SKYNETBLOW, SR_EARTHSHAKER, @@ -1148,15 +1169,15 @@ enum e_skill { SR_GENTLETOUCH_ENERGYGAIN, SR_GENTLETOUCH_CHANGE, SR_GENTLETOUCH_REVITALIZE, - + WA_SWING_DANCE = 2350, WA_SYMPHONY_OF_LOVER, WA_MOONLIT_SERENADE, - + MI_RUSH_WINDMILL = 2381, MI_ECHOSONG, MI_HARMONIZE, - + WM_LESSON = 2412, WM_METALICSOUND, WM_REVERBERATION, @@ -1180,7 +1201,7 @@ enum e_skill { WM_MELODYOFSINK, WM_BEYOND_OF_WARCRY, WM_UNLIMITED_HUMMING_VOICE, - + SO_FIREWALK = 2443, SO_ELECTRICWALK, SO_SPELLFIST, @@ -1207,7 +1228,7 @@ enum e_skill { SO_WATER_INSIGNIA, SO_WIND_INSIGNIA, SO_EARTH_INSIGNIA, - + GN_TRAINING_SWORD = 2474, GN_REMODELING_CART, GN_CART_TORNADO, @@ -1233,14 +1254,14 @@ enum e_skill { GN_MAKEBOMB, GN_S_PHARMACY, GN_SLINGITEM_RANGEMELEEATK, - + AB_SECRAMENT = 2515, WM_SEVERE_RAINSTORM_MELEE, SR_HOWLINGOFLION, SR_RIDEINLIGHTNING, LG_OVERBRAND_BRANDISH, LG_OVERBRAND_PLUSATK, - + ALL_ODINS_RECALL = 2533, RETURN_TO_ELDICASTES, ALL_BUYING_STORE, @@ -1253,7 +1274,12 @@ enum e_skill { ALL_TETANY, ALL_RAY_OF_PROTECTION, MC_CARTDECORATE, - + GM_ITEM_ATKMAX, + GM_ITEM_ATKMIN, + GM_ITEM_MATKMAX, + GM_ITEM_MATKMIN, + ALL_LIGHTGUARD, + RL_GLITTERING_GREED = 2551, RL_RICHS_COIN, RL_MASS_SPIRAL, @@ -1278,7 +1304,7 @@ enum e_skill { RL_R_TRIP_PLUSATK, RL_B_FLICKER_ATK, RL_GLITTERING_GREED_ATK, - + KO_YAMIKUMO = 3001, KO_RIGHT, KO_LEFT, @@ -1308,12 +1334,17 @@ enum e_skill { OB_OBOROGENSOU, OB_OBOROGENSOU_TRANSITION_ATK, OB_AKAITSUKI, - + ECL_SNOWFLIP = 3031, ECL_PEONYMAMY, ECL_SADAGUI, ECL_SEQUOIADUST, ECLAGE_RECALL, + BA_POEMBRAGI2, + DC_FORTUNEKISS2, + ITEM_OPTION_SPLASH_ATTACK, + GM_FORCE_TRANSFER, + GM_WIDE_RESURRECTION, GC_DARKCROW = 5001, RA_UNLIMIT, @@ -1329,10 +1360,7 @@ enum e_skill { WL_TELEKINESIS_INTENSE, LG_KINGS_GRACE, ALL_FULL_THROTTLE, - SR_FLASHCOMBO_ATK_STEP1, - SR_FLASHCOMBO_ATK_STEP2, - SR_FLASHCOMBO_ATK_STEP3, - SR_FLASHCOMBO_ATK_STEP4, + NC_MAGMA_ERUPTION_DOTDAMAGE, HLIF_HEAL = 8001, HLIF_AVOID, @@ -1377,7 +1405,7 @@ enum e_skill { MH_LAVA_SLIDE, MH_PYROCLASTIC, MH_VOLCANIC_ASH, - + MS_BASH = 8201, MS_MAGNUM, MS_BOWLINGBASH, @@ -1418,7 +1446,8 @@ enum e_skill { MER_KYRIE, MER_BLESSING, MER_INCAGI, - + MER_INVINCIBLEOFF2, + EL_CIRCLE_OF_FIRE = 8401, EL_FIRE_CLOAK, EL_FIRE_MANTLE, @@ -1593,7 +1622,7 @@ enum { UNT_ZENKAI_WIND, UNT_MAKIBISHI, UNT_VENOMFOG, - UNT_ICEMINE, + UNT_ICEMINE, UNT_FLAMECROSS, UNT_HELLBURNING, UNT_MAGMA_ERUPTION, @@ -1914,6 +1943,8 @@ struct skill_interface { int (*autospell) (struct map_session_data *md,uint16 skill_id); int (*calc_heal) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal); bool (*check_cloaking) (struct block_list *bl, struct status_change_entry *sce); + int (*check_cloaking_end) (struct block_list *bl, va_list ap); + bool (*can_cloak) (struct map_session_data *sd); int (*enchant_elemental_end) (struct block_list *bl, int type); int (*not_ok) (uint16 skill_id, struct map_session_data *sd); int (*not_ok_hom) (uint16 skill_id, struct homun_data *hd); @@ -2015,4 +2046,4 @@ struct skill_interface *skill; void skill_defaults(void); -#endif /* _MAP_SKILL_H_ */ +#endif /* MAP_SKILL_H */ diff --git a/src/map/sql/CMakeLists.txt b/src/map/sql/CMakeLists.txt deleted file mode 100644 index 11751a1a5..000000000 --- a/src/map/sql/CMakeLists.txt +++ /dev/null @@ -1,118 +0,0 @@ - -# -# map sql -# -if( BUILD_SQL_SERVERS ) -message( STATUS "Creating target map-server" ) -set( SQL_MAP_HEADERS - "${SQL_MAP_SOURCE_DIR}/atcommand.h" - "${SQL_MAP_SOURCE_DIR}/battle.h" - "${SQL_MAP_SOURCE_DIR}/battleground.h" - "${SQL_MAP_SOURCE_DIR}/buyingstore.h" - "${SQL_MAP_SOURCE_DIR}/chat.h" - "${SQL_MAP_SOURCE_DIR}/chrif.h" - "${SQL_MAP_SOURCE_DIR}/clif.h" - "${SQL_MAP_SOURCE_DIR}/date.h" - "${SQL_MAP_SOURCE_DIR}/duel.h" - "${SQL_MAP_SOURCE_DIR}/elemental.h" - "${SQL_MAP_SOURCE_DIR}/guild.h" - "${SQL_MAP_SOURCE_DIR}/homunculus.h" - "${SQL_MAP_SOURCE_DIR}/HPMmap.h" - "${SQL_MAP_SOURCE_DIR}/instance.h" - "${SQL_MAP_SOURCE_DIR}/intif.h" - "${SQL_MAP_SOURCE_DIR}/irc-bot.h" - "${SQL_MAP_SOURCE_DIR}/itemdb.h" - "${SQL_MAP_SOURCE_DIR}/log.h" - "${SQL_MAP_SOURCE_DIR}/mail.h" - "${SQL_MAP_SOURCE_DIR}/map.h" - "${SQL_MAP_SOURCE_DIR}/mapreg.h" - "${SQL_MAP_SOURCE_DIR}/mercenary.h" - "${SQL_MAP_SOURCE_DIR}/mob.h" - "${SQL_MAP_SOURCE_DIR}/npc.h" - "${SQL_MAP_SOURCE_DIR}/packets.h" - "${SQL_MAP_SOURCE_DIR}/packets_struct.h" - "${SQL_MAP_SOURCE_DIR}/party.h" - "${SQL_MAP_SOURCE_DIR}/path.h" - "${SQL_MAP_SOURCE_DIR}/pc.h" - "${SQL_MAP_SOURCE_DIR}/pc_groups.h" - "${SQL_MAP_SOURCE_DIR}/pet.h" - "${SQL_MAP_SOURCE_DIR}/quest.h" - "${SQL_MAP_SOURCE_DIR}/script.h" - "${SQL_MAP_SOURCE_DIR}/searchstore.h" - "${SQL_MAP_SOURCE_DIR}/skill.h" - "${SQL_MAP_SOURCE_DIR}/status.h" - "${SQL_MAP_SOURCE_DIR}/storage.h" - "${SQL_MAP_SOURCE_DIR}/trade.h" - "${SQL_MAP_SOURCE_DIR}/unit.h" - "${SQL_MAP_SOURCE_DIR}/vending.h" - ) -set( SQL_MAP_SOURCES - "${SQL_MAP_SOURCE_DIR}/atcommand.c" - "${SQL_MAP_SOURCE_DIR}/battle.c" - "${SQL_MAP_SOURCE_DIR}/battleground.c" - "${SQL_MAP_SOURCE_DIR}/buyingstore.c" - "${SQL_MAP_SOURCE_DIR}/chat.c" - "${SQL_MAP_SOURCE_DIR}/chrif.c" - "${SQL_MAP_SOURCE_DIR}/clif.c" - "${SQL_MAP_SOURCE_DIR}/date.c" - "${SQL_MAP_SOURCE_DIR}/duel.c" - "${SQL_MAP_SOURCE_DIR}/elemental.c" - "${SQL_MAP_SOURCE_DIR}/guild.c" - "${SQL_MAP_SOURCE_DIR}/homunculus.c" - "${SQL_MAP_SOURCE_DIR}/HPMmap.c" - "${SQL_MAP_SOURCE_DIR}/instance.c" - "${SQL_MAP_SOURCE_DIR}/intif.c" - "${SQL_MAP_SOURCE_DIR}/irc-bot.c" - "${SQL_MAP_SOURCE_DIR}/itemdb.c" - "${SQL_MAP_SOURCE_DIR}/log.c" - "${SQL_MAP_SOURCE_DIR}/mail.c" - "${SQL_MAP_SOURCE_DIR}/map.c" - "${SQL_MAP_SOURCE_DIR}/mapreg_sql.c" - "${SQL_MAP_SOURCE_DIR}/mercenary.c" - "${SQL_MAP_SOURCE_DIR}/mob.c" - "${SQL_MAP_SOURCE_DIR}/npc.c" - "${SQL_MAP_SOURCE_DIR}/npc_chat.c" - "${SQL_MAP_SOURCE_DIR}/party.c" - "${SQL_MAP_SOURCE_DIR}/path.c" - "${SQL_MAP_SOURCE_DIR}/pc.c" - "${SQL_MAP_SOURCE_DIR}/pc_groups.c" - "${SQL_MAP_SOURCE_DIR}/pet.c" - "${SQL_MAP_SOURCE_DIR}/quest.c" - "${SQL_MAP_SOURCE_DIR}/script.c" - "${SQL_MAP_SOURCE_DIR}/searchstore.c" - "${SQL_MAP_SOURCE_DIR}/skill.c" - "${SQL_MAP_SOURCE_DIR}/status.c" - "${SQL_MAP_SOURCE_DIR}/storage.c" - "${SQL_MAP_SOURCE_DIR}/trade.c" - "${SQL_MAP_SOURCE_DIR}/unit.c" - "${SQL_MAP_SOURCE_DIR}/vending.c" - ) -set( DEPENDENCIES common_sql ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} ) -set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS}" ) -if( WITH_PCRE ) - message( STATUS "Enabled PCRE code" ) - set( LIBRARIES ${LIBRARIES} ${PCRE_LIBRARIES} ) - set( INCLUDE_DIRS ${INCLUDE_DIRS} ${PCRE_INCLUDE_DIRS} ) - set( DEFINITIONS "${DEFINITIONS} -DPCRE_SUPPORT" ) -else() - message( STATUS "Disabled PCRE code" ) -endif() -set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} ) -source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) -source_group( map FILES ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} ) -include_directories( ${INCLUDE_DIRS} ) -add_executable( map-server ${SOURCE_FILES} ) -add_dependencies( map-server ${DEPENDENCIES} ) -target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} ) -set_target_properties( map-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server" GROUP Runtime ) - install( TARGETS map-server - DESTINATION "." - COMPONENT Runtime_mapserver_sql ) -endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} map-server CACHE INTERNAL "" ) -message( STATUS "Creating target map-server - done" ) -endif( BUILD_SQL_SERVERS ) diff --git a/src/map/status.c b/src/map/status.c index 9a2151971..c73f78c42 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2,43 +2,46 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/malloc.h" -#include "../common/utils.h" -#include "../common/ers.h" -#include "../common/strlib.h" +#define HERCULES_CORE + +#include "../config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP +#include "status.h" + +#include <math.h> +#include <memory.h> +#include <stdio.h> +#include <stdlib.h> +#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 "npc.h" -#include "mob.h" -#include "clif.h" -#include "guild.h" +#include "script.h" #include "skill.h" -#include "itemdb.h" -#include "battle.h" -#include "chrif.h" #include "skill.h" -#include "status.h" -#include "script.h" #include "unit.h" -#include "homunculus.h" -#include "mercenary.h" -#include "elemental.h" #include "vending.h" - -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <memory.h> -#include <string.h> -#include <math.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; @@ -177,7 +180,7 @@ void initChangeTables(void) { add_sc( TF_POISON , SC_POISON ); set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD ); add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER ); - set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , + set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , #ifdef RENEWAL SCB_NONE ); #else @@ -201,7 +204,7 @@ void initChangeTables(void) { set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE ); set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE ); set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN ); - add_sc( HT_LANDMINE , SC_STUN ); + add_sc( HT_LANDMINE , SC_STUN ); set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE ); add_sc( HT_SANDMAN , SC_SLEEP ); add_sc( HT_FLASHER , SC_BLIND ); @@ -466,13 +469,13 @@ void initChangeTables(void) { set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); // Homunculus S + set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE ); + set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF ); + add_sc(MH_STAHL_HORN, SC_STUN); set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); add_sc( MH_STEINWAND, SC_SAFETYWALL ); - add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER); - set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); - add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE); set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE); @@ -482,11 +485,11 @@ void initChangeTables(void) { add_sc(MH_POISON_MIST, SC_BLIND); set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); - add_sc(MH_STYLE_CHANGE , SC_STYLE_CHANGE); - set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE ); + set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE ); + add_sc( MH_STYLE_CHANGE , SC_STYLE_CHANGE); + set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE ); set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE ); - add_sc( MER_CRASH , SC_STUN ); set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY ); @@ -633,6 +636,7 @@ void initChangeTables(void) { **/ add_sc( SR_DRAGONCOMBO , SC_STUN ); add_sc( SR_EARTHSHAKER , SC_STUN ); + set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SI_FALLENEMPIRE , SCB_NONE ); set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE ); set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE ); set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE ); @@ -640,6 +644,7 @@ void initChangeTables(void) { set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE ); set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP ); set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN ); + set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK ); /** * Wanderer / Minstrel **/ @@ -1118,8 +1123,8 @@ int status_charge(struct block_list* bl, int64 hp, int64 sp) { } //Inflicts damage on the target with the according walkdelay. -//If flag&1, damage is passive and does not triggers cancelling status changes. -//If flag&2, fail if target does not has enough to substract. +//If flag&1, damage is passive and does not triggers canceling status changes. +//If flag&2, fail if target does not has enough to subtract. //If flag&4, if killed, mob must not give exp/loot. //flag will be set to &8 when damaging sp of a dead character int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) { @@ -1266,7 +1271,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, st->hp = 1; //To let the dead function cast skills and all that. //NOTE: These dead functions should return: [Skotlex] - //0: Death cancelled, auto-revived. + //0: Death canceled, auto-revived. //Non-zero: Standard death. Clear status, cancel move/attack, etc //&2: Also remove object from map. //&4: Also delete object from memory. @@ -1281,7 +1286,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, break; } - if(!flag) //Death cancelled. + if(!flag) //Death canceled. return (int)(hp+sp); //Normal death @@ -1319,16 +1324,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, return (int)(hp+sp); } - if(target->type == BL_PC) { - TBL_PC *sd = BL_CAST(BL_PC,target); - TBL_HOM *hd = sd->hd; - if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){ - clif->skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill->get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage - clif->skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status->revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); - status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); - return (int)(hp + sp); - } - } + if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) { // Ensure the monster has not already rebirthed before doing so. status->revive(target, sc->data[SC_REBIRTH]->val2, 0); @@ -1435,7 +1431,7 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { //If rates are > 0, percent is of current HP/SP //If rates are < 0, percent is of max HP/SP //If !flag, this is heal, otherwise it is damage. -//Furthermore, if flag==2, then the target must not die from the substraction. +//Furthermore, if flag==2, then the target must not die from the subtraction. int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) { struct status_data *st; unsigned int hp = 0, sp = 0; @@ -1639,16 +1635,16 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if( sc && sc->count ) { - if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc + if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stunned/Frozen/etc if (flag != 1) //Can't cast, casted stuff can't damage. return 0; if (!(skill->get_inf(skill_id)&INF_GROUND_SKILL)) - return 0; //Targetted spells can't come off. + return 0; //Targeted spells can't come off. } if ( (sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD) - || (sc->data[SC_AUTOCOUNTER] && !flag) + || (sc->data[SC_AUTOCOUNTER] && !flag && skill_id) || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL) || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2) ) @@ -1788,7 +1784,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if( ( tsc->data[SC_STEALTHFIELD] || tsc->data[SC_CAMOUFLAGE] ) && !(st->mode&(MD_BOSS|MD_DETECTOR)) && flag == 4 ) return 0; } - //If targetting, cloak+hide protect you, otherwise only hiding does. + //If targeting, cloak+hide protect you, otherwise only hiding does. hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK); //You cannot hide from ground skills. @@ -1821,7 +1817,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin } } break; - case BL_ITEM: //Allow targetting of items to pick'em up (or in the case of mobs, to loot them). + case BL_ITEM: //Allow targeting of items to pick'em up (or in the case of mobs, to loot them). //TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex] if (st->mode&MD_LOOTER) return 1; @@ -1897,7 +1893,7 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) #ifdef RENEWAL_ASPD short mod = -1; - switch( sd->weapontype2 ){ // adjustment for dual weilding + switch( sd->weapontype2 ){ // adjustment for dual wielding case W_DAGGER: mod = 0; break; // 0, 1, 1 case W_1HSWORD: case W_1HAXE: mod = 1; @@ -2074,6 +2070,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { struct status_data *mstatus; struct block_list *mbl = NULL; int flag=0; + int guardup_lv = 0; if(opt&SCO_FIRST) { //Set basic level on respawn. if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv) @@ -2089,7 +2086,8 @@ 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->guardup_lv) + if( md->guardian_data && md->guardian_data->g + && (guardup_lv = guild->checkskill(md->guardian_data->g,GD_GUARDUP)) ) flag|=4; if (battle_config.slaves_inherit_speed && md->master_id) @@ -2224,10 +2222,10 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { mstatus->mdef += (gc->defense+2)/3; } if(md->class_ != MOBID_EMPERIUM) { - mstatus->batk += mstatus->batk * 10*md->guardian_data->guardup_lv/100; - mstatus->rhw.atk += mstatus->rhw.atk * 10*md->guardian_data->guardup_lv/100; - mstatus->rhw.atk2 += mstatus->rhw.atk2 * 10*md->guardian_data->guardup_lv/100; - mstatus->aspd_rate -= 100*md->guardian_data->guardup_lv; + mstatus->batk += mstatus->batk * 10*guardup_lv/100; + mstatus->rhw.atk += mstatus->rhw.atk * 10*guardup_lv/100; + mstatus->rhw.atk2 += mstatus->rhw.atk2 * 10*guardup_lv/100; + mstatus->aspd_rate -= 100*guardup_lv; } } @@ -2561,7 +2559,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { return 1; } - // sanitize the refine level in case someone decreased the value inbetween + // sanitize the refine level in case someone decreased the value in between if (sd->status.inventory[index].refine > MAX_REFINE) sd->status.inventory[index].refine = MAX_REFINE; @@ -2589,7 +2587,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { wa->matk += status->refine_info[wlv].bonus[r-1] / 100; #endif - //Overrefine bonus. + //Overrefined bonus. if (r) wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100; @@ -3417,6 +3415,8 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) { struct map_session_data *sd; int val, skill_lv, reg_flag; + nullpo_retv(bl); + nullpo_retv(st); if( !(bl->type&BL_REGEN) || !regen ) return; @@ -3678,7 +3678,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { st->batk = status->calc_batk(bl, sc, st->batk, true); } - if(flag&SCB_WATK) { + if(flag&SCB_WATK) { st->rhw.atk = status->calc_watk(bl, sc, bst->rhw.atk, true); if (!sd) //Should not affect weapon refine bonus st->rhw.atk2 = status->calc_watk(bl, sc, bst->rhw.atk2, true); @@ -3884,7 +3884,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { } if(flag&SCB_MATK) { - status->get_matk(bl, 0); + status->update_matk(bl); } if(flag&SCB_ASPD) { @@ -4643,6 +4643,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; if(sc->data[SC_ANGRIFFS_MODUS]) watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; + if( sc->data[SC_FLASHCOMBO] ) + watk += sc->data[SC_FLASHCOMBO]->val2; return (unsigned short)cap_value(watk,0,USHRT_MAX); } @@ -4842,8 +4844,6 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i flee += 10; if (sc->data[SC_ANGRIFFS_MODUS]) flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; - if (sc->data[SC_OVERED_BOOST]) - flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); if(sc->data[SC_GS_ADJUSTMENT]) flee += 30; if(sc->data[SC_HLIF_SPEED]) @@ -4891,6 +4891,9 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i if(status_get_element(bl) == ELE_WATER) //water type flee /= 2; } + + if( sc->data[SC_OVERED_BOOST] ) // should be final and unmodifiable by any means + flee = sc->data[SC_OVERED_BOOST]->val2; return (short)cap_value(flee,1,SHRT_MAX); } @@ -4923,6 +4926,8 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def /* some statuses that are hidden in the status window */ if( sc && sc->data[SC_CAMOUFLAGE] ) def -= def * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100; + if( sc->data[SC_OVERED_BOOST] && bl->type == BL_PC ) + def -= def * 50 / 100; if( sc && sc->data[SC_GENTLETOUCH_REVITALIZE] && sc->data[SC_GENTLETOUCH_REVITALIZE]->val4 ) def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4; if( sc->data[SC_FORCEOFVANGUARD] ) @@ -4942,27 +4947,32 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def if(sc->data[SC_STEELBODY]) return 90; #endif + + if(sc->data[SC_STONEHARDSKIN]) + def += sc->data[SC_STONEHARDSKIN]->val1; + if(sc->data[SC_DRUMBATTLE]) + def += sc->data[SC_DRUMBATTLE]->val3; if(sc->data[SC_STONESKIN]) def += sc->data[SC_STONESKIN]->val2; - if(sc->data[SC_DRUMBATTLE]) - def += sc->data[SC_DRUMBATTLE]->val3; if(sc->data[SC_HAMI_DEFENCE]) //[orn] - def += sc->data[SC_HAMI_DEFENCE]->val2 ; - if(sc->data[SC_INCDEFRATE]) - def += def * sc->data[SC_INCDEFRATE]->val1/100; + def += sc->data[SC_HAMI_DEFENCE]->val2; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) def += 50; if(sc->data[SC_ODINS_POWER]) def -= 20; - if( sc->data[SC_ANGRIFFS_MODUS] ) - def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; - if(sc->data[SC_STONEHARDSKIN]) - def += sc->data[SC_STONEHARDSKIN]->val1; + +#ifndef RENEWAL if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) def >>=1; if(sc->data[SC_FREEZE]) def >>=1; + if(sc->data[SC_INCDEFRATE]) + def += def * sc->data[SC_INCDEFRATE]->val1/100; +#endif + if( sc->data[SC_ANGRIFFS_MODUS] ) + def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; if(sc->data[SC_CRUCIS]) def -= def * sc->data[SC_CRUCIS]->val2/100; if(sc->data[SC_LKCONCENTRATION]) @@ -4971,7 +4981,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def def >>=1; if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> def -= def * sc->data[SC_PROVOKE]->val4/100; - if(sc->data[SC_NOEQUIPSHIELD] && bl->type != BL_PC) + if(sc->data[SC_NOEQUIPSHIELD]) def -= def * sc->data[SC_NOEQUIPSHIELD]->val2/100; if (sc->data[SC_FLING]) def -= def * (sc->data[SC_FLING]->val2)/100; @@ -4981,20 +4991,17 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def def -= def * (10 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100; if(sc->data[SC_EARTHDRIVE]) def -= def * 25 / 100; - if(sc->data[SC_SOLID_SKIN_OPTION]) - def += def * sc->data[SC_SOLID_SKIN_OPTION]->val2 / 100; if( sc->data[SC_ROCK_CRUSHER] ) def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100; + if( sc->data[SC_FROSTMISTY] ) + def -= def * 10 / 100; + if( sc->data[SC_OVERED_BOOST] && bl->type == BL_HOM ) + def -= def * 50 / 100; + if( sc->data[SC_POWER_OF_GAIA] ) def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; - if( sc->data[SC_NEUTRALBARRIER] ) - def += def * (5 * sc->data[SC_NEUTRALBARRIER]->val1 + 10) / 100; - if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 2 ) - def += sc->data[SC_SHIELDSPELL_REF]->val2; if( sc->data[SC_PRESTIGE] ) - def += sc->data[SC_PRESTIGE]->val1; - if( sc->data[SC_FROSTMISTY] ) - def -= def * 10 / 100; + def += def * sc->data[SC_PRESTIGE]->val1 / 100; if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ if(status_get_race(bl)==RC_PLANT) def /= 2; @@ -5017,7 +5024,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i #ifdef RENEWAL if( sc && sc->data[SC_ASSUMPTIO] ) def2 <<= 1; -#endif +#endif if( sc && sc->data[SC_CAMOUFLAGE] ) def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100; #ifdef RENEWAL @@ -5471,11 +5478,6 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int if (!sc || !sc->count) return cap_value(aspd, 0, 2000); - if (!sc->data[SC_QUAGMIRE]) { - if (sc->data[SC_OVERED_BOOST]) - aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; - } - if ((sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION])) aspd -= 50; // +5 ASPD @@ -5484,6 +5486,8 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int if( sc && sc->data[SC_MTF_ASPD] ) aspd -= 10; + if (sc->data[SC_OVERED_BOOST]) // should be final and unmodifiable by any means + aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3 * 10; return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway } @@ -5916,7 +5920,7 @@ struct status_data *status_get_base_status(struct block_list *bl) case BL_HOM: return &((TBL_HOM*)bl)->base_status; case BL_MER: return &((TBL_MER*)bl)->base_status; case BL_ELEM: return &((TBL_ELEM*)bl)->base_status; - case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL); + case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL); default: return NULL; } @@ -5933,8 +5937,8 @@ defType status_get_def(struct block_list *bl) { } unsigned short status_get_speed(struct block_list *bl) { - if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex] - return ((struct npc_data *)bl)->speed; + if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex] + return ((struct npc_data *)bl)->speed; return status->get_status_data(bl)->speed; } @@ -5984,15 +5988,18 @@ int status_get_guild_id(struct block_list *bl) { if (((TBL_PET*)bl)->msd) return ((TBL_PET*)bl)->msd->status.guild_id; break; - case BL_MOB: { + case BL_MOB: + { struct map_session_data *msd; struct mob_data *md = (struct mob_data *)bl; - if (md->guardian_data) //Guardian's guild [Skotlex] - return md->guardian_data->guild_id; - if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL) + if( md->guardian_data ) { //Guardian's guild [Skotlex] + // 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 ) return msd->status.guild_id; //Alchemist's mobs [Skotlex] - } - break; + break; + } case BL_HOM: if (((TBL_HOM*)bl)->master) return ((TBL_HOM*)bl)->master->status.guild_id; @@ -6028,7 +6035,7 @@ int status_get_emblem_id(struct block_list *bl) { struct map_session_data *msd; struct mob_data *md = (struct mob_data *)bl; if (md->guardian_data) //Guardian's guild [Skotlex] - return md->guardian_data->emblem_id; + return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0; if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL) return msd->guild_emblem_id; //Alchemist's mobs [Skotlex] } @@ -6943,16 +6950,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_ASSNCROS: if(sc->option&OPTION_MADOGEAR) return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind] - case SC_INC_AGI: + case SC_INC_AGI: if (sc->data[SC_QUAGMIRE]) - return 0; + return 0; break; case SC_CLOAKING: - //Avoid cloaking with no wall and low skill level. [Skotlex] - //Due to the cloaking card, we have to check the wall versus to known - //skill level rather than the used one. [Skotlex] - //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) - if( sd && pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) ) + if (sd && !skill->can_cloak(sd)) return 0; break; case SC_MODECHANGE: @@ -7147,7 +7150,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_ROKISWEIL: case SC_FOGWALL: case SC_FROSTMISTY: - case SC_BURNING: + case SC_BURNING: case SC_MARSHOFABYSS: case SC_ADORAMUS: case SC_NEEDLE_OF_PARALYZE: @@ -7331,6 +7334,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); break; case SC_FIGHTINGSPIRIT: + case SC_OVERED_BOOST: status_change_end(bl, type, INVALID_TIMER); // Remove previous one. break; case SC_MARSHOFABYSS: @@ -8102,22 +8106,25 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } break; - case SC_COMBOATTACK: { + case SC_COMBOATTACK: + { //val1: Skill ID //val2: When given, target (for autotargetting skills) //val3: When set, this combo time should NOT delay attack/movement + //val3: If set to 2 this combo will delay ONLY attack //val3: TK: Last used kick //val4: TK: Combo time struct unit_data *ud = unit->bl2ud(bl); - if (ud && !val3) { + if( ud && (!val3 || val3 == 2) ) { tick += 300 * battle_config.combo_delay_rate/100; ud->attackabletime = timer->gettick()+tick; - unit->set_walkdelay(bl, timer->gettick(), tick, 1); + if( !val3 ) + unit->set_walkdelay(bl, timer->gettick(), tick, 1); } val3 = 0; val4 = tick; - } - break; + break; + } case SC_EARTHSCROLL: val2 = 11-val1; //Chance to consume: 11-skill_lv% break; @@ -8250,7 +8257,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t tick_time = 1000; // [GodLesZ] tick time break; case SC_JAILED: - //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. + // val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. + // When first called: + // val2 Jail map_index + // val3 x + // val4 y + // When renewing status' information + // val3 Return map_index + // val4 return coordinates tick = val1>0?1000:250; if (sd) { @@ -8263,7 +8277,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t //2. Set restore point (val3 -> return map, val4 return coords val3 = map_index; val4 = pos; - } else if (!val3 || val3 == sd->mapindex) { //Use save point. + } else if (!val3 + || val3 == sd->mapindex + || !sd->sc.data[SC_JAILED] // If player is being jailed and is already in jail (issue: 8206) + ) { //Use save point. val3 = sd->status.save_point.map; val4 = (sd->status.save_point.x&0xFFFF) |(sd->status.save_point.y<<16); @@ -8827,16 +8844,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_STONE_SHIELD_OPTION: val2 = 100; // Elemental modifier. break; + case SC_TROPIC: + case SC_CHILLY_AIR: + case SC_WILD_STORM: + case SC_UPHEAVAL: + val2 += 10; + case SC_HEATER: + case SC_COOLER: + case SC_BLAST: + case SC_CURSED_SOIL: + val2 += 10; + case SC_PYROTECHNIC: + case SC_AQUAPLAY: + case SC_GUST: + case SC_PETROLOGY: + val2 += 5; + val3 += 9000; case SC_CIRCLE_OF_FIRE: + case SC_WATER_SCREEN: + case SC_WIND_STEP: + case SC_SOLID_SKIN: case SC_FIRE_CLOAK: case SC_WATER_DROP: - case SC_WATER_SCREEN: case SC_WIND_CURTAIN: - case SC_WIND_STEP: case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - val2 = 10; - tick_time = 2000; // [GodLesZ] tick time + val2 += 5; + val3 += 1000; + val4 = tick; + tick_time = val3; break; case SC_WATER_BARRIER: val2 = 40; // Increasement. Mdef1 ??? @@ -8979,9 +9014,15 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val1 = 1002; // default poring break; case SC_ALL_RIDING: - unit->stop_attack(bl); tick = -1; break; + case SC_FLASHCOMBO: + /** + * val1 = <IN>skill_id + * val2 = <OUT>attack addition + **/ + val2 = 20+(20*val1); + break; default: if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 ) { //Status change with no calc, no icon, and no skill associated...? @@ -9168,6 +9209,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t // Cancel cast when get status [LuzZza] if (battle_config.sc_castcancel&bl->type) unit->skillcastcancel(bl, 0); + case SC_FALLENEMPIRE: case SC_WHITEIMPRISON: unit->stop_attack(bl); case SC_STOP: @@ -9201,6 +9243,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_WEIGHTOVER90: case SC_CAMOUFLAGE: case SC_SIREN: + case SC_ALL_RIDING: unit->stop_attack(bl); break; case SC_SILENCE: @@ -9404,7 +9447,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if(opt_flag) { + if(opt_flag) { clif->changeoption(bl); if( sd && opt_flag&0x4 ) { clif->changelook(bl,LOOK_BASE,vd->class_); @@ -9471,7 +9514,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t { struct unit_data *ud = unit->bl2ud(bl); if( ud ) - ud->state.running = unit->run(bl); + ud->state.running = unit->run(bl, NULL, SC_RUN); } break; case SC_CASH_BOSS_ALARM: @@ -9490,7 +9533,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t { struct unit_data *ud = unit->bl2ud(bl); if( ud ) - ud->state.running = unit->wugdash(bl, sd); + ud->state.running = unit->run(bl, sd, SC_WUGDASH); } break; case SC_COMBOATTACK: @@ -10114,6 +10157,20 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } } break; + case SC_OVERED_BOOST: + switch( bl->type ){ + case BL_HOM: + { + struct homun_data *hd = BL_CAST(BL_HOM, bl); + if( hd ) + hd->homunculus.hunger = max(1, hd->homunculus.hunger - 50); + } + break; + case BL_PC: + status_zap(bl, 0, status_get_max_sp(bl) / 2); + break; + } + break; } opt_flag = 1; @@ -11108,22 +11165,31 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } break; + case SC_TROPIC: + case SC_CHILLY_AIR: + case SC_WILD_STORM: + case SC_UPHEAVAL: + case SC_HEATER: + case SC_COOLER: + case SC_BLAST: + case SC_CURSED_SOIL: + case SC_PYROTECHNIC: + case SC_AQUAPLAY: + case SC_GUST: + case SC_PETROLOGY: case SC_CIRCLE_OF_FIRE: + case SC_WATER_SCREEN: + case SC_WIND_STEP: + case SC_SOLID_SKIN: case SC_FIRE_CLOAK: case SC_WATER_DROP: - case SC_WATER_SCREEN: case SC_WIND_CURTAIN: - case SC_WIND_STEP: case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - if( !status->charge(bl,0,sce->val2) ){ - struct block_list *s_bl = battle->get_master(bl); - if( s_bl ) - status_change_end(s_bl,type+1,INVALID_TIMER); - status_change_end(bl,type,INVALID_TIMER); - break; - } - sc_timer_next(2000 + tick, status->change_timer, bl->id, data); + if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0)) + sc_timer_next(sce->val3 + tick, status->change_timer, bl->id, data); + else + if (bl->type == BL_ELEM) + elemental->change_mode(BL_CAST(BL_ELEM,bl),MAX_ELESKILLTREE); return 0; case SC_STOMACHACHE: @@ -11307,88 +11373,149 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl #endif } -#define GETRANDMATK(st) do {\ - if( (st)->matk_max > (st)->matk_min ) \ - return (st)->matk_min + rnd()%((st)->matk_max - (st)->matk_min); \ - else \ - return (st)->matk_min; \ - } while(0) +/** + * Gets a random matk value depending on min matk and max matk + **/ +unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) { + if( matk_max > matk_min ) + return matk_min + rnd()%(matk_max - matk_min); + else + return matk_min; +} -/*========================================== -* flag [malufett] -* 0 - update matk values -* 1 - get matk w/o SC bonuses -* 2 - get modified matk -* 3 - get matk w/o eatk & SC bonuses -*------------------------------------------*/ -int status_get_matk(struct block_list *bl, int flag) { +/** + * Get bl's matk_max and matk_min values depending on flag + * @param flag + * 0 - Get MATK + * 1 - Get MATK w/o SC bonuses + * 3 - Get MATK w/o EATK & SC bonuses + **/ +void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min ) { struct status_data *st; struct status_change *sc; struct map_session_data *sd; if( bl == NULL ) - return 1; + return; + + if( flag != 0 && flag != 1 && flag != 3 ) { + ShowError("status_get_matk_sub: Unknown flag %d!\n", flag); + return; + } st = status->get_status_data(bl); sc = status->get_sc(bl); sd = BL_CAST(BL_PC, bl); - if( flag == 2 ) // just get matk - GETRANDMATK(st); - #ifdef RENEWAL /** * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers **/ - st->matk_min = status->base_matk(st, status->get_lv(bl)); + *matk_min = status->base_matk(st, status->get_lv(bl)); // Any +MATK you get from skills and cards, including cards in weapon, is added here. if( sd && sd->bonus.ematk > 0 && flag != 3 ) - st->matk_min += sd->bonus.ematk; + *matk_min += sd->bonus.ematk; if( flag != 3 ) - st->matk_min = status->calc_ematk(bl, sc, st->matk_min); + *matk_min = status->calc_ematk(bl, sc, *matk_min); - st->matk_max = st->matk_min; + *matk_max = *matk_min; //This is the only portion in MATK that varies depending on the weapon level and refinement rate. if( bl->type&BL_PC && (st->rhw.matk + st->lhw.matk) > 0 ) { int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level - st->matk_min += wMatk - variance; - st->matk_max += wMatk + variance; + *matk_min += wMatk - variance; + *matk_max += wMatk + variance; } else if( bl->type&BL_MOB ) { - st->matk_min = st->matk_max = status_get_int(bl) + status->get_lv(bl); - st->matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; - st->matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; + *matk_min = *matk_max = status_get_int(bl) + status->get_lv(bl); + *matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; + *matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; } #else // not RENEWAL - st->matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0); - st->matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0); + *matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0); + *matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0); #endif + if (sd && sd->matk_rate != 100) { - st->matk_max = st->matk_max * sd->matk_rate/100; - st->matk_min = st->matk_min * sd->matk_rate/100; + *matk_max = (*matk_max) * sd->matk_rate/100; + *matk_min = (*matk_min) * sd->matk_rate/100; } if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk || (sc && sc->data[SC_RECOGNIZEDSPELL])) - st->matk_min = st->matk_max; + *matk_min = *matk_max; #ifdef RENEWAL - if( sd && sd->right_weapon.overrefine > 0){ - st->matk_min++; - st->matk_max += sd->right_weapon.overrefine - 1; + if( sd && sd->right_weapon.overrefine > 0 ) { + (*matk_min)++; + *matk_max += sd->right_weapon.overrefine - 1; } #endif + return; +} - if( flag ) // get unmodified from sc matk - GETRANDMATK(st); +/** + * Get bl's matk value depending on flag + * @param flag [malufett] + * 1 - Get MATK w/o SC bonuses + * 2 - Get modified MATK + * 3 - Get MATK w/o eATK & SC bonuses + * @retval 1 failure + * @retval MATK success + * + * Shouldn't change _any_ value! [Panikon] + **/ +int status_get_matk( struct block_list *bl, int flag ) { + struct status_data *st; + unsigned short matk_max, matk_min; - st->matk_min = status->calc_matk(bl, sc, st->matk_min, true); - st->matk_max = status->calc_matk(bl, sc, st->matk_max, true); + if( bl == NULL ) + return 1; - return 0; + if( flag < 1 || flag > 3 ) { + ShowError("status_get_matk: Unknown flag %d!\n", flag); + return 1; + } + + if( (st = status->get_status_data(bl)) == NULL ) + return 0; + + // Just get matk + if( flag == 2 ) + return status_get_rand_matk(st->matk_max, st->matk_min); + + status_get_matk_sub( bl, flag, &matk_max, &matk_min ); + + // Get unmodified from sc matk + return status_get_rand_matk(matk_max, matk_min); +} + +/** + * Updates bl's MATK values + **/ +void status_update_matk( struct block_list *bl ) { + struct status_data *st; + struct status_change *sc; + unsigned short matk_max, matk_min; + + if( bl == NULL ) + return; + + if( (st = status->get_status_data(bl)) == NULL ) + return; + + if( (sc = status->get_sc(bl)) == NULL ) + return; + + status_get_matk_sub( bl, 0, &matk_max, &matk_min ); + + // Update matk + st->matk_min = status->calc_matk(bl, sc, matk_min, true); + st->matk_max = status->calc_matk(bl, sc, matk_max, true); + + return; } /*========================================== @@ -11947,7 +12074,7 @@ void do_final_status(void) { } /*===================================== -* Default Functions : status.h +* Default Functions : status.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -12062,6 +12189,7 @@ void status_defaults(void) { status->get_total_def = status_get_total_def; status->get_matk = status_get_matk; + status->update_matk = status_update_matk; status->readdb = status_readdb; status->init = do_init_status; diff --git a/src/map/status.h b/src/map/status.h index e47c2b365..599f36c73 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2,22 +2,26 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_STATUS_H_ -#define _MAP_STATUS_H_ +#ifndef MAP_STATUS_H +#define MAP_STATUS_H -#include "../common/mmo.h" +#include "../config/core.h" // defType, RENEWAL, RENEWAL_ASPD + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" // NEW_CARTS struct block_list; -struct mob_data; -struct pet_data; +struct elemental_data; struct homun_data; struct mercenary_data; -struct status_change; +struct mob_data; +struct npc_data; +struct pet_data; //Change the equation when the values are high enough to discard the //imprecision in exchange of overflow protection [Skotlex] //Also add 100% checks since those are the most used cases where we don't -//want aproximation errors. +//want approximation errors. #define APPLY_RATE(value, rate) ( \ (rate) == 100 ? \ (value) \ @@ -48,6 +52,10 @@ enum refine_type { REFINE_TYPE_MAX = 5 }; +/** + * SC configuration type + * @see db/sc_config.txt for more information + **/ typedef enum sc_conf_type { SC_NO_REM_DEATH = 0x01, SC_NO_SAVE = 0x02, @@ -704,769 +712,832 @@ typedef enum sc_type { SC__CHAOS, SC__FEINTBOMB_MASTER, - + SC_FALLENEMPIRE, + SC_FLASHCOMBO, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; -// Official status change ids, used to display status icons on the client. + +/// Official status change ids, used to display status icons in the client. enum si_type { - SI_BLANK = -1, - SI_PROVOKE = 0, - SI_ENDURE = 1, - SI_TWOHANDQUICKEN = 2, - SI_CONCENTRATION = 3, - SI_HIDING = 4, - SI_CLOAKING = 5, - SI_ENCHANTPOISON = 6, - SI_POISONREACT = 7, - SI_QUAGMIRE = 8, - SI_ANGELUS = 9, - SI_BLESSING = 10, - SI_CRUCIS = 11, - SI_INC_AGI = 12, - SI_DEC_AGI = 13, - SI_SLOWPOISON = 14, - SI_IMPOSITIO = 15, - SI_SUFFRAGIUM = 16, - SI_ASPERSIO = 17, - SI_BENEDICTIO = 18, - SI_KYRIE = 19, - SI_MAGNIFICAT = 20, - SI_GLORIA = 21, - SI_LEXAETERNA = 22, - SI_ADRENALINE = 23, - SI_WEAPONPERFECT = 24, - SI_OVERTHRUST = 25, - SI_MAXIMIZE = 26, - SI_RIDING = 27, - SI_FALCON = 28, - SI_TRICKDEAD = 29, - SI_SHOUT = 30, - SI_ENERGYCOAT = 31, - SI_BROKENARMOR = 32, - SI_BROKENWEAPON = 33, - SI_ILLUSION = 34, - SI_WEIGHTOVER50 = 35, - SI_WEIGHTOVER90 = 36, - SI_ATTHASTE_POTION1 = 37, - SI_ATTHASTE_POTION2 = 38, - SI_ATTHASTE_POTION3 = 39, - SI_ATTHASTE_INFINITY = 40, - SI_MOVHASTE_POTION = 41, - SI_MOVHASTE_INFINITY = 42, -// SI_AUTOCOUNTER = 43, -// SI_SPLASHER = 44, - SI_ANKLESNARE = 45, - SI_POSTDELAY = 46, -// SI_NOACTION = 47, -// SI_IMPOSSIBLEPICKUP = 48, -// SI_BARRIER = 49, - SI_NOEQUIPWEAPON = 50, - SI_NOEQUIPSHIELD = 51, - SI_NOEQUIPARMOR = 52, - SI_NOEQUIPHELM = 53, - SI_PROTECTWEAPON = 54, - SI_PROTECTSHIELD = 55, - SI_PROTECTARMOR = 56, - SI_PROTECTHELM = 57, - SI_AUTOGUARD = 58, - SI_REFLECTSHIELD = 59, -// SI_DEVOTION = 60, - SI_PROVIDENCE = 61, - SI_DEFENDER = 62, -// SI_MAGICROD = 63, -// SI_WEAPONPROPERTY = 64, - SI_AUTOSPELL = 65, -// SI_SPECIALZONE = 66, -// SI_MASK = 67, - SI_SPEARQUICKEN = 68, -// SI_BDPLAYING = 69, -// SI_WHISTLE = 70, -// SI_ASSASSINCROSS = 71, -// SI_POEMBRAGI = 72, -// SI_APPLEIDUN = 73, -// SI_HUMMING = 74, -// SI_DONTFORGETME = 75, -// SI_FORTUNEKISS = 76, -// SI_SERVICEFORYOU = 77, -// SI_RICHMANKIM = 78, -// SI_ETERNALCHAOS = 79, -// SI_DRUMBATTLEFIELD = 80, -// SI_RINGNIBELUNGEN = 81, -// SI_ROKISWEIL = 82, -// SI_INTOABYSS = 83, -// SI_SIEGFRIED = 84, -// SI_BLADESTOP = 85, - SI_EXPLOSIONSPIRITS = 86, - SI_STEELBODY = 87, - SI_EXTREMITYFIST = 88, -// SI_COMBOATTACK = 89, - SI_PROPERTYFIRE = 90, - SI_PROPERTYWATER = 91, - SI_PROPERTYWIND = 92, - SI_PROPERTYGROUND = 93, -// SI_MAGICATTACK = 94, - SI_STOP = 95, -// SI_WEAPONBRAKER = 96, - SI_PROPERTYUNDEAD = 97, -// SI_POWERUP = 98, -// SI_AGIUP = 99, -// SI_SIEGEMODE = 100, -// SI_INVISIBLE = 101, -// SI_STATUSONE = 102, - SI_AURABLADE = 103, - SI_PARRYING = 104, - SI_LKCONCENTRATION = 105, - SI_TENSIONRELAX = 106, - SI_BERSERK = 107, -// SI_SACRIFICE = 108, -// SI_GOSPEL = 109, - SI_ASSUMPTIO = 110, -// SI_BASILICA = 111, - SI_GROUNDMAGIC = 112, - SI_MAGICPOWER = 113, - SI_EDP = 114, - SI_TRUESIGHT = 115, - SI_WINDWALK = 116, - SI_MELTDOWN = 117, - SI_CARTBOOST = 118, -// SI_CHASEWALK = 119, - SI_SWORDREJECT = 120, - SI_MARIONETTE_MASTER = 121, - SI_MARIONETTE = 122, - SI_MOON = 123, - SI_BLOODING = 124, - SI_JOINTBEAT = 125, -// SI_MINDBREAKER = 126, -// SI_MEMORIZE = 127, -// SI_FOGWALL = 128, -// SI_SPIDERWEB = 129, - SI_PROTECTEXP = 130, -// SI_SUB_WEAPONPROPERTY = 131, - SI_AUTOBERSERK = 132, - SI_RUN = 133, - SI_TING = 134, - SI_STORMKICK_ON = 135, - SI_STORMKICK_READY = 136, - SI_DOWNKICK_ON = 137, - SI_DOWNKICK_READY = 138, - SI_TURNKICK_ON = 139, - SI_TURNKICK_READY = 140, - SI_COUNTER_ON = 141, - SI_COUNTER_READY = 142, - SI_DODGE_ON = 143, - SI_DODGE_READY = 144, - SI_STRUP = 145, - SI_PROPERTYDARK = 146, - SI_ADRENALINE2 = 147, - SI_PROPERTYTELEKINESIS = 148, - SI_SOULLINK = 149, - SI_PLUSATTACKPOWER = 150, - SI_PLUSMAGICPOWER = 151, - SI_DEVIL1 = 152, - SI_KAITE = 153, -// SI_SWOO = 154, -// SI_STAR2 = 155, - SI_KAIZEL = 156, - SI_KAAHI = 157, - SI_KAUPE = 158, - SI_SMA_READY = 159, - SI_SKE = 160, - SI_ONEHANDQUICKEN = 161, -// SI_FRIEND = 162, -// SI_FRIENDUP = 163, -// SI_SG_WARM = 164, - SI_SG_SUN_WARM = 165, -// 166 | The three show the exact same display: ultra red character (165, 166, 167) -// 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM -// SI_EMOTION = 168, - SI_SUN_COMFORT = 169, - SI_MOON_COMFORT = 170, - SI_STAR_COMFORT = 171, -// SI_EXPUP = 172, -// SI_GDSKILL_BATTLEORDER = 173, -// SI_GDSKILL_REGENERATION = 174, -// SI_GDSKILL_POSTDELAY = 175, -// SI_RESISTHANDICAP = 176, -// SI_MAXHPPERCENT = 177, -// SI_MAXSPPERCENT = 178, -// SI_DEFENCE = 179, -// SI_SLOWDOWN = 180, - SI_PRESERVE = 181, - SI_INCSTR = 182, -// SI_NOT_EXTREMITYFIST = 183, - SI_CLAIRVOYANCE = 184, -// SI_MOVESLOW_POTION = 185, - SI_DOUBLECASTING = 186, -// SI_GRAVITATION = 187, - SI_OVERTHRUSTMAX = 188, -// SI_LONGING = 189, -// SI_HERMODE = 190, - SI_TAROTCARD = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] -// SI_HLIF_AVOID = 192, -// SI_HFLI_FLEET = 193, -// SI_HFLI_SPEED = 194, -// SI_HLIF_CHANGE = 195, -// SI_HAMI_BLOODLUST = 196, - SI_CR_SHRINK = 197, - SI_WZ_SIGHTBLASTER = 198, - SI_DC_WINKCHARM = 199, - SI_RG_CCONFINE_M = 200, - SI_RG_CCONFINE_S = 201, -// SI_DISABLEMOVE = 202, - SI_GS_MADNESSCANCEL = 203, //[blackhole89] - SI_GS_GATLINGFEVER = 204, - SI_EARTHSCROLL = 205, - SI_NJ_UTSUSEMI = 206, - SI_NJ_BUNSINJYUTSU = 207, - SI_NJ_NEN = 208, - SI_GS_ADJUSTMENT = 209, - SI_GS_ACCURACY = 210, - SI_NJ_SUITON = 211, -// SI_PET = 212, -// SI_MENTAL = 213, -// SI_EXPMEMORY = 214, -// SI_PERFORMANCE = 215, -// SI_GAIN = 216, -// SI_GRIFFON = 217, -// SI_DRIFT = 218, -// SI_WALLSHIFT = 219, -// SI_REINCARNATION = 220, -// SI_PATTACK = 221, -// SI_PSPEED = 222, -// SI_PDEFENSE = 223, -// SI_PCRITICAL = 224, -// SI_RANKING = 225, -// SI_PTRIPLE = 226, -// SI_DENERGY = 227, -// SI_WAVE1 = 228, -// SI_WAVE2 = 229, -// SI_WAVE3 = 230, -// SI_WAVE4 = 231, -// SI_DAURA = 232, -// SI_DFREEZER = 233, -// SI_DPUNISH = 234, -// SI_DBARRIER = 235, -// SI_DWARNING = 236, -// SI_MOUSEWHEEL = 237, -// SI_DGAUGE = 238, -// SI_DACCEL = 239, -// SI_DBLOCK = 240, - SI_FOOD_STR = 241, - SI_FOOD_AGI = 242, - SI_FOOD_VIT = 243, - SI_FOOD_DEX = 244, - SI_FOOD_INT = 245, - SI_FOOD_LUK = 246, - SI_FOOD_BASICAVOIDANCE = 247, - SI_FOOD_BASICHIT = 248, - SI_FOOD_CRITICALSUCCESSVALUE = 249, - SI_CASH_PLUSEXP = 250, - SI_CASH_DEATHPENALTY = 251, - SI_CASH_RECEIVEITEM = 252, - SI_CASH_BOSS_ALARM = 253, -// SI_DA_ENERGY = 254, -// SI_DA_FIRSTSLOT = 255, -// SI_DA_HEADDEF = 256, -// SI_DA_SPACE = 257, -// SI_DA_TRANSFORM = 258, -// SI_DA_ITEMREBUILD = 259, -// SI_DA_ILLUSION = 260, //All mobs display as Turtle General -// SI_DA_DARKPOWER = 261, -// SI_DA_EARPLUG = 262, -// SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon -// SI_DA_BLACK = 264, //For short time blurry screen -// SI_DA_MAGICCART = 265, -// SI_CRYSTAL = 266, -// SI_DA_REBUILD = 267, -// SI_DA_EDARKNESS = 268, -// SI_DA_EGUARDIAN = 269, -// SI_DA_TIMEOUT = 270, - SI_FOOD_STR_CASH = 271, - SI_FOOD_AGI_CASH = 272, - SI_FOOD_VIT_CASH = 273, - SI_FOOD_DEX_CASH = 274, - SI_FOOD_INT_CASH = 275, - SI_FOOD_LUK_CASH = 276, - SI_MER_FLEE = 277, - SI_MER_ATK = 278, - SI_MER_HP = 279, - SI_MER_SP = 280, - SI_MER_HIT = 281, - SI_SLOWCAST = 282, -// SI_MAGICMIRROR = 283, -// SI_STONESKIN = 284, -// SI_ANTIMAGIC = 285, - SI_CRITICALWOUND = 286, -// SI_NPC_DEFENDER = 287, -// SI_NOACTION_WAIT = 288, - SI_MOVHASTE_HORSE = 289, - SI_PROTECT_DEF = 290, - SI_PROTECT_MDEF = 291, - SI_HEALPLUS = 292, - SI_S_LIFEPOTION = 293, - SI_L_LIFEPOTION = 294, - SI_CRITICALPERCENT = 295, - SI_PLUSAVOIDVALUE = 296, -// SI_ATKER_ASPD = 297, -// SI_TARGET_ASPD = 298, -// SI_ATKER_MOVESPEED = 299, - SI_ATKER_BLOOD = 300, - SI_TARGET_BLOOD = 301, - SI_ARMOR_PROPERTY = 302, -// SI_REUSE_LIMIT_A = 303, - SI_HELLPOWER = 304, -// SI_STEAMPACK = 305, -// SI_REUSE_LIMIT_B = 306, -// SI_REUSE_LIMIT_C = 307, -// SI_REUSE_LIMIT_D = 308, -// SI_REUSE_LIMIT_E = 309, -// SI_REUSE_LIMIT_F = 310, - SI_INVINCIBLE = 311, - SI_CASH_PLUSONLYJOBEXP = 312, - SI_PARTYFLEE = 313, - SI_ANGEL_PROTECT = 314, -// SI_ENDURE_MDEF = 315, - SI_ENCHANTBLADE = 316, - SI_DEATHBOUND = 317, - SI_REFRESH = 318, - SI_GIANTGROWTH = 319, - SI_STONEHARDSKIN = 320, - SI_VITALITYACTIVATION = 321, - SI_FIGHTINGSPIRIT = 322, - SI_ABUNDANCE = 323, - SI_REUSE_MILLENNIUMSHIELD = 324, - SI_REUSE_CRUSHSTRIKE = 325, - SI_REUSE_REFRESH = 326, - SI_REUSE_STORMBLAST = 327, - SI_VENOMIMPRESS = 328, - SI_EPICLESIS = 329, - SI_ORATIO = 330, - SI_LAUDAAGNUS = 331, - SI_LAUDARAMUS = 332, - SI_CLOAKINGEXCEED = 333, - SI_HALLUCINATIONWALK = 334, - SI_HALLUCINATIONWALK_POSTDELAY = 335, - SI_RENOVATIO = 336, - SI_WEAPONBLOCKING = 337, - SI_WEAPONBLOCKING_POSTDELAY = 338, - SI_ROLLINGCUTTER = 339, - SI_EXPIATIO = 340, - SI_POISONINGWEAPON = 341, - SI_TOXIN = 342, - SI_PARALYSE = 343, - SI_VENOMBLEED = 344, - SI_MAGICMUSHROOM = 345, - SI_DEATHHURT = 346, - SI_PYREXIA = 347, - SI_OBLIVIONCURSE = 348, - SI_LEECHESEND = 349, - SI_DUPLELIGHT = 350, - SI_FROSTMISTY = 351, - SI_FEARBREEZE = 352, - SI_ELECTRICSHOCKER = 353, - SI_MARSHOFABYSS = 354, - SI_RECOGNIZEDSPELL = 355, - SI_STASIS = 356, - SI_WUGRIDER = 357, - SI_WUGDASH = 358, - SI_WUGBITE = 359, - SI_CAMOUFLAGE = 360, - SI_ACCELERATION = 361, - SI_HOVERING = 362, - SI_SPHERE_1 = 363, - SI_SPHERE_2 = 364, - SI_SPHERE_3 = 365, - SI_SPHERE_4 = 366, - SI_SPHERE_5 = 367, - SI_MVPCARD_TAOGUNKA = 368, - SI_MVPCARD_MISTRESS = 369, - SI_MVPCARD_ORCHERO = 370, - SI_MVPCARD_ORCLORD = 371, - SI_OVERHEAT_LIMITPOINT = 372, - SI_OVERHEAT = 373, - SI_SHAPESHIFT = 374, - SI_INFRAREDSCAN = 375, - SI_MAGNETICFIELD = 376, - SI_NEUTRALBARRIER = 377, - SI_NEUTRALBARRIER_MASTER = 378, - SI_STEALTHFIELD = 379, - SI_STEALTHFIELD_MASTER = 380, - SI_MANU_ATK = 381, - SI_MANU_DEF = 382, - SI_SPL_ATK = 383, - SI_SPL_DEF = 384, - SI_REPRODUCE = 385, - SI_MANU_MATK = 386, - SI_SPL_MATK = 387, - SI_STR_SCROLL = 388, - SI_INT_SCROLL = 389, - SI_LG_REFLECTDAMAGE = 390, - SI_FORCEOFVANGUARD = 391, - SI_BUCHEDENOEL = 392, - SI_AUTOSHADOWSPELL = 393, - SI_SHADOWFORM = 394, - SI_RAID = 395, - SI_SHIELDSPELL_DEF = 396, - SI_SHIELDSPELL_MDEF = 397, - SI_SHIELDSPELL_REF = 398, - SI_BODYPAINT = 399, - SI_EXEEDBREAK = 400, - SI_ADORAMUS = 401, - SI_PRESTIGE = 402, - SI_INVISIBILITY = 403, - SI_DEADLYINFECT = 404, - SI_BANDING = 405, - SI_EARTHDRIVE = 406, - SI_INSPIRATION = 407, - SI_ENERVATION = 408, - SI_GROOMY = 409, - SI_RAISINGDRAGON = 410, - SI_IGNORANCE = 411, - SI_LAZINESS = 412, - SI_LIGHTNINGWALK = 413, - SI_ACARAJE = 414, - SI_UNLUCKY = 415, - SI_CURSEDCIRCLE_ATKER = 416, - SI_CURSEDCIRCLE_TARGET = 417, - SI_WEAKNESS = 418, - SI_CRESCENTELBOW = 419, - SI_NOEQUIPACCESSARY = 420, - SI_STRIPACCESSARY = 421, - SI_MANHOLE = 422, - SI_POPECOOKIE = 423, - SI_FALLENEMPIRE = 424, - SI_GENTLETOUCH_ENERGYGAIN = 425, - SI_GENTLETOUCH_CHANGE = 426, - SI_GENTLETOUCH_REVITALIZE = 427, - SI_BLOODYLUST = 428, - SI_SWINGDANCE = 429, - SI_SYMPHONYOFLOVERS = 430, - SI_PROPERTYWALK = 431, - SI_SPELLFIST = 432, - SI_NETHERWORLD = 433, - SI_SIREN = 434, - SI_DEEPSLEEP = 435, - SI_SIRCLEOFNATURE = 436, - SI_COLD = 437, - SI_GLOOMYDAY = 438, - SI_SONG_OF_MANA = 439, - SI_CLOUDKILL = 440, - SI_DANCEWITHWUG = 441, - SI_RUSHWINDMILL = 442, - SI_ECHOSONG = 443, - SI_HARMONIZE = 444, - SI_STRIKING = 445, - SI_WARMER = 446, - SI_MOONLITSERENADE = 447, - SI_SATURDAYNIGHTFEVER = 448, - SI_SITDOWN_FORCE = 449, - SI_ANALYZE = 450, - SI_LERADSDEW = 451, - SI_MELODYOFSINK = 452, - SI_WARCRYOFBEYOND = 453, - SI_UNLIMITEDHUMMINGVOICE = 454, - SI_SPELLBOOK1 = 455, - SI_SPELLBOOK2 = 456, - SI_SPELLBOOK3 = 457, - SI_FREEZE_SP = 458, - SI_GN_TRAINING_SWORD = 459, - SI_GN_REMODELING_CART = 460, - SI_CARTSBOOST = 461, - SI_FIXEDCASTINGTM_REDUCE = 462, - SI_THORNTRAP = 463, - SI_BLOODSUCKER = 464, - SI_SPORE_EXPLOSION = 465, - SI_DEMONIC_FIRE = 466, - SI_FIRE_EXPANSION_SMOKE_POWDER = 467, - SI_FIRE_EXPANSION_TEAR_GAS = 468, - SI_BLOCKING_PLAY = 469, - SI_MANDRAGORA = 470, - SI_ACTIVATE = 471, - SI_SECRAMENT = 472, - SI_ASSUMPTIO2 = 473, - SI_TK_SEVENWIND = 474, - SI_LIMIT_ODINS_RECALL = 475, - SI_STOMACHACHE = 476, - SI_MYSTERIOUS_POWDER = 477, - SI_MELON_BOMB = 478, - SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479, - SI_PROMOTE_HEALTH_RESERCH = 480, - SI_ENERGY_DRINK_RESERCH = 481, - SI_EXTRACT_WHITE_POTION_Z = 482, - SI_VITATA_500 = 483, - SI_EXTRACT_SALAMINE_JUICE = 484, - SI_BOOST500 = 485, - SI_FULL_SWING_K = 486, - SI_MANA_PLUS = 487, - SI_MUSTLE_M = 488, - SI_LIFE_FORCE_F = 489, - SI_VACUUM_EXTREME = 490, - SI_SAVAGE_STEAK = 491, - SI_COCKTAIL_WARG_BLOOD = 492, - SI_MINOR_BBQ = 493, - SI_SIROMA_ICE_TEA = 494, - SI_DROCERA_HERB_STEAMED = 495, - SI_PUTTI_TAILS_NOODLES = 496, - SI_BANANA_BOMB = 497, - SI_SUMMON_AGNI = 498, - SI_SPELLBOOK4 = 499, - SI_SPELLBOOK5 = 500, - SI_SPELLBOOK6 = 501, - SI_SPELLBOOK7 = 502, - SI_ELEMENTAL_AGGRESSIVE = 503, - SI_RETURN_TO_ELDICASTES = 504, - SI_BANDING_DEFENCE = 505, - SI_SKELSCROLL = 506, - SI_DISTRUCTIONSCROLL = 507, - SI_ROYALSCROLL = 508, - SI_IMMUNITYSCROLL = 509, - SI_MYSTICSCROLL = 510, - SI_BATTLESCROLL = 511, - SI_ARMORSCROLL = 512, - SI_FREYJASCROLL = 513, - SI_SOULSCROLL = 514, - SI_CIRCLE_OF_FIRE = 515, - SI_CIRCLE_OF_FIRE_OPTION = 516, - SI_FIRE_CLOAK = 517, - SI_FIRE_CLOAK_OPTION = 518, - SI_WATER_SCREEN = 519, - SI_WATER_SCREEN_OPTION = 520, - SI_WATER_DROP = 521, - SI_WATER_DROP_OPTION = 522, - SI_WIND_STEP = 523, - SI_WIND_STEP_OPTION = 524, - SI_WIND_CURTAIN = 525, - SI_WIND_CURTAIN_OPTION = 526, - SI_WATER_BARRIER = 527, - SI_ZEPHYR = 528, - SI_SOLID_SKIN = 529, - SI_SOLID_SKIN_OPTION = 530, - SI_STONE_SHIELD = 531, - SI_STONE_SHIELD_OPTION = 532, - SI_POWER_OF_GAIA = 533, - // SI_EL_WAIT = 534, - // SI_EL_PASSIVE = 535, - // SI_EL_DEFENSIVE = 536, - // SI_EL_OFFENSIVE = 537, - // SI_EL_COST = 538, - SI_PYROTECHNIC = 539, - SI_PYROTECHNIC_OPTION = 540, - SI_HEATER = 541, - SI_HEATER_OPTION = 542, - SI_TROPIC = 543, - SI_TROPIC_OPTION = 544, - SI_AQUAPLAY = 545, - SI_AQUAPLAY_OPTION = 546, - SI_COOLER = 547, - SI_COOLER_OPTION = 548, - SI_CHILLY_AIR = 549, - SI_CHILLY_AIR_OPTION = 550, - SI_GUST = 551, - SI_GUST_OPTION = 552, - SI_BLAST = 553, - SI_BLAST_OPTION = 554, - SI_WILD_STORM = 555, - SI_WILD_STORM_OPTION = 556, - SI_PETROLOGY = 557, - SI_PETROLOGY_OPTION = 558, - SI_CURSED_SOIL = 559, - SI_CURSED_SOIL_OPTION = 560, - SI_UPHEAVAL = 561, - SI_UPHEAVAL_OPTION = 562, - SI_TIDAL_WEAPON = 563, - SI_TIDAL_WEAPON_OPTION = 564, - SI_ROCK_CRUSHER = 565, - SI_ROCK_CRUSHER_ATK = 566, - SI_FIRE_INSIGNIA = 567, - SI_WATER_INSIGNIA = 568, - SI_WIND_INSIGNIA = 569, - SI_EARTH_INSIGNIA = 570, - SI_EQUIPED_FLOOR = 571, - SI_GUARDIAN_RECALL = 572, - SI_MORA_BUFF = 573, - SI_REUSE_LIMIT_G = 574, - SI_REUSE_LIMIT_H = 575, - SI_NEEDLE_OF_PARALYZE = 576, - SI_PAIN_KILLER = 577, - SI_G_LIFEPOTION = 578, - SI_VITALIZE_POTION = 579, - SI_LIGHT_OF_REGENE = 580, - SI_OVERED_BOOST = 581, - SI_SILENT_BREEZE = 582, - SI_ODINS_POWER = 583, - SI_STYLE_CHANGE = 584, - SI_SONIC_CLAW_POSTDELAY = 585, + SI_BLANK = -1, + + SI_PROVOKE = 0, + SI_ENDURE = 1, + SI_TWOHANDQUICKEN = 2, + SI_CONCENTRATION = 3, + SI_HIDING = 4, + SI_CLOAKING = 5, + SI_ENCHANTPOISON = 6, + SI_POISONREACT = 7, + SI_QUAGMIRE = 8, + SI_ANGELUS = 9, + SI_BLESSING = 10, + SI_CRUCIS = 11, + SI_INC_AGI = 12, + SI_DEC_AGI = 13, + SI_SLOWPOISON = 14, + SI_IMPOSITIO = 15, + SI_SUFFRAGIUM = 16, + SI_ASPERSIO = 17, + SI_BENEDICTIO = 18, + SI_KYRIE = 19, + SI_MAGNIFICAT = 20, + SI_GLORIA = 21, + SI_LEXAETERNA = 22, + SI_ADRENALINE = 23, + SI_WEAPONPERFECT = 24, + SI_OVERTHRUST = 25, + SI_MAXIMIZE = 26, + SI_RIDING = 27, + SI_FALCON = 28, + SI_TRICKDEAD = 29, + SI_SHOUT = 30, + SI_ENERGYCOAT = 31, + SI_BROKENARMOR = 32, + SI_BROKENWEAPON = 33, + SI_ILLUSION = 34, + SI_WEIGHTOVER50 = 35, + SI_WEIGHTOVER90 = 36, + SI_ATTHASTE_POTION1 = 37, + SI_ATTHASTE_POTION2 = 38, + SI_ATTHASTE_POTION3 = 39, + SI_ATTHASTE_INFINITY = 40, + SI_MOVHASTE_POTION = 41, + SI_MOVHASTE_INFINITY = 42, + //SI_AUTOCOUNTER = 43, + //SI_SPLASHER = 44, + SI_ANKLESNARE = 45, + SI_POSTDELAY = 46, + //SI_NOACTION = 47, + //SI_IMPOSSIBLEPICKUP = 48, + //SI_BARRIER = 49, + + SI_NOEQUIPWEAPON = 50, + SI_NOEQUIPSHIELD = 51, + SI_NOEQUIPARMOR = 52, + SI_NOEQUIPHELM = 53, + SI_PROTECTWEAPON = 54, + SI_PROTECTSHIELD = 55, + SI_PROTECTARMOR = 56, + SI_PROTECTHELM = 57, + SI_AUTOGUARD = 58, + SI_REFLECTSHIELD = 59, + //SI_DEVOTION = 60, + SI_PROVIDENCE = 61, + SI_DEFENDER = 62, + //SI_MAGICROD = 63, + //SI_WEAPONPROPERTY = 64, + SI_AUTOSPELL = 65, + //SI_SPECIALZONE = 66, + //SI_MASK = 67, + SI_SPEARQUICKEN = 68, + //SI_BDPLAYING = 69, + //SI_WHISTLE = 70, + //SI_ASSASSINCROSS = 71, + //SI_POEMBRAGI = 72, + //SI_APPLEIDUN = 73, + //SI_HUMMING = 74, + //SI_DONTFORGETME = 75, + //SI_FORTUNEKISS = 76, + //SI_SERVICEFORYOU = 77, + //SI_RICHMANKIM = 78, + //SI_ETERNALCHAOS = 79, + //SI_DRUMBATTLEFIELD = 80, + //SI_RINGNIBELUNGEN = 81, + //SI_ROKISWEIL = 82, + //SI_INTOABYSS = 83, + //SI_SIEGFRIED = 84, + //SI_BLADESTOP = 85, + SI_EXPLOSIONSPIRITS = 86, + SI_STEELBODY = 87, + SI_EXTREMITYFIST = 88, + //SI_COMBOATTACK = 89, + SI_PROPERTYFIRE = 90, + SI_PROPERTYWATER = 91, + SI_PROPERTYWIND = 92, + SI_PROPERTYGROUND = 93, + //SI_MAGICATTACK = 94, + SI_STOP = 95, + //SI_WEAPONBRAKER = 96, + SI_PROPERTYUNDEAD = 97, + //SI_POWERUP = 98, + //SI_AGIUP = 99, + + //SI_SIEGEMODE = 100, + //SI_INVISIBLE = 101, + //SI_STATUSONE = 102, + SI_AURABLADE = 103, + SI_PARRYING = 104, + SI_LKCONCENTRATION = 105, + SI_TENSIONRELAX = 106, + SI_BERSERK = 107, + //SI_SACRIFICE = 108, + //SI_GOSPEL = 109, + SI_ASSUMPTIO = 110, + //SI_BASILICA = 111, + SI_GROUNDMAGIC = 112, + SI_MAGICPOWER = 113, + SI_EDP = 114, + SI_TRUESIGHT = 115, + SI_WINDWALK = 116, + SI_MELTDOWN = 117, + SI_CARTBOOST = 118, + //SI_CHASEWALK = 119, + SI_SWORDREJECT = 120, + SI_MARIONETTE_MASTER = 121, + SI_MARIONETTE = 122, + SI_MOON = 123, + SI_BLOODING = 124, + SI_JOINTBEAT = 125, + //SI_MINDBREAKER = 126, + //SI_MEMORIZE = 127, + //SI_FOGWALL = 128, + //SI_SPIDERWEB = 129, + SI_PROTECTEXP = 130, + //SI_SUB_WEAPONPROPERTY = 131, + SI_AUTOBERSERK = 132, + SI_RUN = 133, + SI_TING = 134, + SI_STORMKICK_ON = 135, + SI_STORMKICK_READY = 136, + SI_DOWNKICK_ON = 137, + SI_DOWNKICK_READY = 138, + SI_TURNKICK_ON = 139, + SI_TURNKICK_READY = 140, + SI_COUNTER_ON = 141, + SI_COUNTER_READY = 142, + SI_DODGE_ON = 143, + SI_DODGE_READY = 144, + SI_STRUP = 145, + SI_PROPERTYDARK = 146, + SI_ADRENALINE2 = 147, + SI_PROPERTYTELEKINESIS = 148, + SI_SOULLINK = 149, + + SI_PLUSATTACKPOWER = 150, + SI_PLUSMAGICPOWER = 151, + SI_DEVIL1 = 152, + SI_KAITE = 153, + //SI_SWOO = 154, + //SI_STAR2 = 155, + SI_KAIZEL = 156, + SI_KAAHI = 157, + SI_KAUPE = 158, + SI_SMA_READY = 159, + SI_SKE = 160, + SI_ONEHANDQUICKEN = 161, + //SI_FRIEND = 162, + //SI_FRIENDUP = 163, + //SI_SG_WARM = 164, + SI_SG_SUN_WARM = 165, + //SI_SG_MOON_WARM = 166 | The three show the exact same display: ultra red character (165, 166, 167) + //SI_SG_STAR_WARM = 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM + //SI_EMOTION = 168, + SI_SUN_COMFORT = 169, + SI_MOON_COMFORT = 170, + SI_STAR_COMFORT = 171, + //SI_EXPUP = 172, + //SI_GDSKILL_BATTLEORDER = 173, + //SI_GDSKILL_REGENERATION = 174, + //SI_GDSKILL_POSTDELAY = 175, + //SI_RESISTHANDICAP = 176, + //SI_MAXHPPERCENT = 177, + //SI_MAXSPPERCENT = 178, + //SI_DEFENCE = 179, + //SI_SLOWDOWN = 180, + SI_PRESERVE = 181, + SI_INCSTR = 182, + //SI_NOT_EXTREMITYFIST = 183, + SI_CLAIRVOYANCE = 184, + //SI_MOVESLOW_POTION = 185, + SI_DOUBLECASTING = 186, + //SI_GRAVITATION = 187, + SI_OVERTHRUSTMAX = 188, + //SI_LONGING = 189, + //SI_HERMODE = 190, + SI_TAROTCARD = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] + //SI_HLIF_AVOID = 192, + //SI_HFLI_FLEET = 193, + //SI_HFLI_SPEED = 194, + //SI_HLIF_CHANGE = 195, + //SI_HAMI_BLOODLUST = 196, + SI_CR_SHRINK = 197, + SI_WZ_SIGHTBLASTER = 198, + SI_DC_WINKCHARM = 199, + + SI_RG_CCONFINE_M = 200, + SI_RG_CCONFINE_S = 201, + //SI_DISABLEMOVE = 202, + SI_GS_MADNESSCANCEL = 203, //[blackhole89] + SI_GS_GATLINGFEVER = 204, + SI_EARTHSCROLL = 205, + SI_NJ_UTSUSEMI = 206, + SI_NJ_BUNSINJYUTSU = 207, + SI_NJ_NEN = 208, + SI_GS_ADJUSTMENT = 209, + SI_GS_ACCURACY = 210, + SI_NJ_SUITON = 211, + //SI_PET = 212, + //SI_MENTAL = 213, + //SI_EXPMEMORY = 214, + //SI_PERFORMANCE = 215, + //SI_GAIN = 216, + //SI_GRIFFON = 217, + //SI_DRIFT = 218, + //SI_WALLSHIFT = 219, + //SI_REINCARNATION = 220, + //SI_PATTACK = 221, + //SI_PSPEED = 222, + //SI_PDEFENSE = 223, + //SI_PCRITICAL = 224, + //SI_RANKING = 225, + //SI_PTRIPLE = 226, + //SI_DENERGY = 227, + //SI_WAVE1 = 228, + //SI_WAVE2 = 229, + //SI_WAVE3 = 230, + //SI_WAVE4 = 231, + //SI_DAURA = 232, + //SI_DFREEZER = 233, + //SI_DPUNISH = 234, + //SI_DBARRIER = 235, + //SI_DWARNING = 236, + //SI_MOUSEWHEEL = 237, + //SI_DGAUGE = 238, + //SI_DACCEL = 239, + //SI_DBLOCK = 240, + SI_FOOD_STR = 241, + SI_FOOD_AGI = 242, + SI_FOOD_VIT = 243, + SI_FOOD_DEX = 244, + SI_FOOD_INT = 245, + SI_FOOD_LUK = 246, + SI_FOOD_BASICAVOIDANCE = 247, + SI_FOOD_BASICHIT = 248, + SI_FOOD_CRITICALSUCCESSVALUE = 249, + + SI_CASH_PLUSEXP = 250, + SI_CASH_DEATHPENALTY = 251, + SI_CASH_RECEIVEITEM = 252, + SI_CASH_BOSS_ALARM = 253, + //SI_DA_ENERGY = 254, + //SI_DA_FIRSTSLOT = 255, + //SI_DA_HEADDEF = 256, + //SI_DA_SPACE = 257, + //SI_DA_TRANSFORM = 258, + //SI_DA_ITEMREBUILD = 259, + //SI_DA_ILLUSION = 260, //All mobs display as Turtle General + //SI_DA_DARKPOWER = 261, + //SI_DA_EARPLUG = 262, + //SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon + //SI_DA_BLACK = 264, //For short time blurry screen + //SI_DA_MAGICCART = 265, + //SI_CRYSTAL = 266, + //SI_DA_REBUILD = 267, + //SI_DA_EDARKNESS = 268, + //SI_DA_EGUARDIAN = 269, + //SI_DA_TIMEOUT = 270, + SI_FOOD_STR_CASH = 271, + SI_FOOD_AGI_CASH = 272, + SI_FOOD_VIT_CASH = 273, + SI_FOOD_DEX_CASH = 274, + SI_FOOD_INT_CASH = 275, + SI_FOOD_LUK_CASH = 276, + SI_MER_FLEE = 277, + SI_MER_ATK = 278, + SI_MER_HP = 279, + SI_MER_SP = 280, + SI_MER_HIT = 281, + SI_SLOWCAST = 282, + //SI_MAGICMIRROR = 283, + //SI_STONESKIN = 284, + //SI_ANTIMAGIC = 285, + SI_CRITICALWOUND = 286, + //SI_NPC_DEFENDER = 287, + //SI_NOACTION_WAIT = 288, + SI_MOVHASTE_HORSE = 289, + SI_PROTECT_DEF = 290, + SI_PROTECT_MDEF = 291, + SI_HEALPLUS = 292, + SI_S_LIFEPOTION = 293, + SI_L_LIFEPOTION = 294, + SI_CRITICALPERCENT = 295, + SI_PLUSAVOIDVALUE = 296, + //SI_ATKER_ASPD = 297, + //SI_TARGET_ASPD = 298, + //SI_ATKER_MOVESPEED = 299, + + SI_ATKER_BLOOD = 300, + SI_TARGET_BLOOD = 301, + SI_ARMOR_PROPERTY = 302, + //SI_REUSE_LIMIT_A = 303, + SI_HELLPOWER = 304, + //SI_STEAMPACK = 305, + //SI_REUSE_LIMIT_B = 306, + //SI_REUSE_LIMIT_C = 307, + //SI_REUSE_LIMIT_D = 308, + //SI_REUSE_LIMIT_E = 309, + //SI_REUSE_LIMIT_F = 310, + SI_INVINCIBLE = 311, + SI_CASH_PLUSONLYJOBEXP = 312, + SI_PARTYFLEE = 313, + SI_ANGEL_PROTECT = 314, + //SI_ENDURE_MDEF = 315, + SI_ENCHANTBLADE = 316, + SI_DEATHBOUND = 317, + SI_REFRESH = 318, + SI_GIANTGROWTH = 319, + SI_STONEHARDSKIN = 320, + SI_VITALITYACTIVATION = 321, + SI_FIGHTINGSPIRIT = 322, + SI_ABUNDANCE = 323, + SI_REUSE_MILLENNIUMSHIELD = 324, + SI_REUSE_CRUSHSTRIKE = 325, + SI_REUSE_REFRESH = 326, + SI_REUSE_STORMBLAST = 327, + SI_VENOMIMPRESS = 328, + SI_EPICLESIS = 329, + SI_ORATIO = 330, + SI_LAUDAAGNUS = 331, + SI_LAUDARAMUS = 332, + SI_CLOAKINGEXCEED = 333, + SI_HALLUCINATIONWALK = 334, + SI_HALLUCINATIONWALK_POSTDELAY = 335, + SI_RENOVATIO = 336, + SI_WEAPONBLOCKING = 337, + SI_WEAPONBLOCKING_POSTDELAY = 338, + SI_ROLLINGCUTTER = 339, + SI_EXPIATIO = 340, + SI_POISONINGWEAPON = 341, + SI_TOXIN = 342, + SI_PARALYSE = 343, + SI_VENOMBLEED = 344, + SI_MAGICMUSHROOM = 345, + SI_DEATHHURT = 346, + SI_PYREXIA = 347, + SI_OBLIVIONCURSE = 348, + SI_LEECHESEND = 349, + + SI_DUPLELIGHT = 350, + SI_FROSTMISTY = 351, + SI_FEARBREEZE = 352, + SI_ELECTRICSHOCKER = 353, + SI_MARSHOFABYSS = 354, + SI_RECOGNIZEDSPELL = 355, + SI_STASIS = 356, + SI_WUGRIDER = 357, + SI_WUGDASH = 358, + SI_WUGBITE = 359, + SI_CAMOUFLAGE = 360, + SI_ACCELERATION = 361, + SI_HOVERING = 362, + SI_SPHERE_1 = 363, + SI_SPHERE_2 = 364, + SI_SPHERE_3 = 365, + SI_SPHERE_4 = 366, + SI_SPHERE_5 = 367, + SI_MVPCARD_TAOGUNKA = 368, + SI_MVPCARD_MISTRESS = 369, + SI_MVPCARD_ORCHERO = 370, + SI_MVPCARD_ORCLORD = 371, + SI_OVERHEAT_LIMITPOINT = 372, + SI_OVERHEAT = 373, + SI_SHAPESHIFT = 374, + SI_INFRAREDSCAN = 375, + SI_MAGNETICFIELD = 376, + SI_NEUTRALBARRIER = 377, + SI_NEUTRALBARRIER_MASTER = 378, + SI_STEALTHFIELD = 379, + SI_STEALTHFIELD_MASTER = 380, + SI_MANU_ATK = 381, + SI_MANU_DEF = 382, + SI_SPL_ATK = 383, + SI_SPL_DEF = 384, + SI_REPRODUCE = 385, + SI_MANU_MATK = 386, + SI_SPL_MATK = 387, + SI_STR_SCROLL = 388, + SI_INT_SCROLL = 389, + SI_LG_REFLECTDAMAGE = 390, + SI_FORCEOFVANGUARD = 391, + SI_BUCHEDENOEL = 392, + SI_AUTOSHADOWSPELL = 393, + SI_SHADOWFORM = 394, + SI_RAID = 395, + SI_SHIELDSPELL_DEF = 396, + SI_SHIELDSPELL_MDEF = 397, + SI_SHIELDSPELL_REF = 398, + SI_BODYPAINT = 399, + + SI_EXEEDBREAK = 400, + SI_ADORAMUS = 401, + SI_PRESTIGE = 402, + SI_INVISIBILITY = 403, + SI_DEADLYINFECT = 404, + SI_BANDING = 405, + SI_EARTHDRIVE = 406, + SI_INSPIRATION = 407, + SI_ENERVATION = 408, + SI_GROOMY = 409, + SI_RAISINGDRAGON = 410, + SI_IGNORANCE = 411, + SI_LAZINESS = 412, + SI_LIGHTNINGWALK = 413, + SI_ACARAJE = 414, + SI_UNLUCKY = 415, + SI_CURSEDCIRCLE_ATKER = 416, + SI_CURSEDCIRCLE_TARGET = 417, + SI_WEAKNESS = 418, + SI_CRESCENTELBOW = 419, + SI_NOEQUIPACCESSARY = 420, + SI_STRIPACCESSARY = 421, + SI_MANHOLE = 422, + SI_POPECOOKIE = 423, + SI_FALLENEMPIRE = 424, + SI_GENTLETOUCH_ENERGYGAIN = 425, + SI_GENTLETOUCH_CHANGE = 426, + SI_GENTLETOUCH_REVITALIZE = 427, + SI_BLOODYLUST = 428, + SI_SWINGDANCE = 429, + SI_SYMPHONYOFLOVERS = 430, + SI_PROPERTYWALK = 431, + SI_SPELLFIST = 432, + SI_NETHERWORLD = 433, + SI_SIREN = 434, + SI_DEEPSLEEP = 435, + SI_SIRCLEOFNATURE = 436, + SI_COLD = 437, + SI_GLOOMYDAY = 438, + SI_SONG_OF_MANA = 439, + SI_CLOUDKILL = 440, + SI_DANCEWITHWUG = 441, + SI_RUSHWINDMILL = 442, + SI_ECHOSONG = 443, + SI_HARMONIZE = 444, + SI_STRIKING = 445, + SI_WARMER = 446, + SI_MOONLITSERENADE = 447, + SI_SATURDAYNIGHTFEVER = 448, + SI_SITDOWN_FORCE = 449, + + SI_ANALYZE = 450, + SI_LERADSDEW = 451, + SI_MELODYOFSINK = 452, + SI_WARCRYOFBEYOND = 453, + SI_UNLIMITEDHUMMINGVOICE = 454, + SI_SPELLBOOK1 = 455, + SI_SPELLBOOK2 = 456, + SI_SPELLBOOK3 = 457, + SI_FREEZE_SP = 458, + SI_GN_TRAINING_SWORD = 459, + SI_GN_REMODELING_CART = 460, + SI_CARTSBOOST = 461, + SI_FIXEDCASTINGTM_REDUCE = 462, + SI_THORNTRAP = 463, + SI_BLOODSUCKER = 464, + SI_SPORE_EXPLOSION = 465, + SI_DEMONIC_FIRE = 466, + SI_FIRE_EXPANSION_SMOKE_POWDER = 467, + SI_FIRE_EXPANSION_TEAR_GAS = 468, + SI_BLOCKING_PLAY = 469, + SI_MANDRAGORA = 470, + SI_ACTIVATE = 471, + SI_SECRAMENT = 472, + SI_ASSUMPTIO2 = 473, + SI_TK_SEVENWIND = 474, + SI_LIMIT_ODINS_RECALL = 475, + SI_STOMACHACHE = 476, + SI_MYSTERIOUS_POWDER = 477, + SI_MELON_BOMB = 478, + SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479, + SI_PROMOTE_HEALTH_RESERCH = 480, + SI_ENERGY_DRINK_RESERCH = 481, + SI_EXTRACT_WHITE_POTION_Z = 482, + SI_VITATA_500 = 483, + SI_EXTRACT_SALAMINE_JUICE = 484, + SI_BOOST500 = 485, + SI_FULL_SWING_K = 486, + SI_MANA_PLUS = 487, + SI_MUSTLE_M = 488, + SI_LIFE_FORCE_F = 489, + SI_VACUUM_EXTREME = 490, + SI_SAVAGE_STEAK = 491, + SI_COCKTAIL_WARG_BLOOD = 492, + SI_MINOR_BBQ = 493, + SI_SIROMA_ICE_TEA = 494, + SI_DROCERA_HERB_STEAMED = 495, + SI_PUTTI_TAILS_NOODLES = 496, + SI_BANANA_BOMB = 497, + SI_SUMMON_AGNI = 498, + SI_SPELLBOOK4 = 499, + + SI_SPELLBOOK5 = 500, + SI_SPELLBOOK6 = 501, + SI_SPELLBOOK7 = 502, + SI_ELEMENTAL_AGGRESSIVE = 503, + SI_RETURN_TO_ELDICASTES = 504, + SI_BANDING_DEFENCE = 505, + SI_SKELSCROLL = 506, + SI_DISTRUCTIONSCROLL = 507, + SI_ROYALSCROLL = 508, + SI_IMMUNITYSCROLL = 509, + SI_MYSTICSCROLL = 510, + SI_BATTLESCROLL = 511, + SI_ARMORSCROLL = 512, + SI_FREYJASCROLL = 513, + SI_SOULSCROLL = 514, + SI_CIRCLE_OF_FIRE = 515, + SI_CIRCLE_OF_FIRE_OPTION = 516, + SI_FIRE_CLOAK = 517, + SI_FIRE_CLOAK_OPTION = 518, + SI_WATER_SCREEN = 519, + SI_WATER_SCREEN_OPTION = 520, + SI_WATER_DROP = 521, + SI_WATER_DROP_OPTION = 522, + SI_WIND_STEP = 523, + SI_WIND_STEP_OPTION = 524, + SI_WIND_CURTAIN = 525, + SI_WIND_CURTAIN_OPTION = 526, + SI_WATER_BARRIER = 527, + SI_ZEPHYR = 528, + SI_SOLID_SKIN = 529, + SI_SOLID_SKIN_OPTION = 530, + SI_STONE_SHIELD = 531, + SI_STONE_SHIELD_OPTION = 532, + SI_POWER_OF_GAIA = 533, + //SI_EL_WAIT = 534, + //SI_EL_PASSIVE = 535, + //SI_EL_DEFENSIVE = 536, + //SI_EL_OFFENSIVE = 537, + //SI_EL_COST = 538, + SI_PYROTECHNIC = 539, + SI_PYROTECHNIC_OPTION = 540, + SI_HEATER = 541, + SI_HEATER_OPTION = 542, + SI_TROPIC = 543, + SI_TROPIC_OPTION = 544, + SI_AQUAPLAY = 545, + SI_AQUAPLAY_OPTION = 546, + SI_COOLER = 547, + SI_COOLER_OPTION = 548, + SI_CHILLY_AIR = 549, + + SI_CHILLY_AIR_OPTION = 550, + SI_GUST = 551, + SI_GUST_OPTION = 552, + SI_BLAST = 553, + SI_BLAST_OPTION = 554, + SI_WILD_STORM = 555, + SI_WILD_STORM_OPTION = 556, + SI_PETROLOGY = 557, + SI_PETROLOGY_OPTION = 558, + SI_CURSED_SOIL = 559, + SI_CURSED_SOIL_OPTION = 560, + SI_UPHEAVAL = 561, + SI_UPHEAVAL_OPTION = 562, + SI_TIDAL_WEAPON = 563, + SI_TIDAL_WEAPON_OPTION = 564, + SI_ROCK_CRUSHER = 565, + SI_ROCK_CRUSHER_ATK = 566, + SI_FIRE_INSIGNIA = 567, + SI_WATER_INSIGNIA = 568, + SI_WIND_INSIGNIA = 569, + SI_EARTH_INSIGNIA = 570, + SI_EQUIPED_FLOOR = 571, + SI_GUARDIAN_RECALL = 572, + SI_MORA_BUFF = 573, + SI_REUSE_LIMIT_G = 574, + SI_REUSE_LIMIT_H = 575, + SI_NEEDLE_OF_PARALYZE = 576, + SI_PAIN_KILLER = 577, + SI_G_LIFEPOTION = 578, + SI_VITALIZE_POTION = 579, + SI_LIGHT_OF_REGENE = 580, + SI_OVERED_BOOST = 581, + SI_SILENT_BREEZE = 582, + SI_ODINS_POWER = 583, + SI_STYLE_CHANGE = 584, + SI_SONIC_CLAW_POSTDELAY = 585, // ID's 586 - 595 Currently Unused - SI_SILVERVEIN_RUSH_POSTDELAY = 596, - SI_MIDNIGHT_FRENZY_POSTDELAY = 597, - SI_GOLDENE_FERSE = 598, - SI_ANGRIFFS_MODUS = 599, - SI_TINDER_BREAKER = 600, - SI_TINDER_BREAKER_POSTDELAY = 601, - SI_CBC = 602, - SI_CBC_POSTDELAY = 603, - SI_EQC = 604, - SI_MAGMA_FLOW = 605, - SI_GRANITIC_ARMOR = 606, - SI_PYROCLASTIC = 607, - SI_VOLCANIC_ASH = 608, - SI_SPIRITS_SAVEINFO1 = 609, - SI_SPIRITS_SAVEINFO2 = 610, - SI_MAGIC_CANDY = 611, - SI_SEARCH_STORE_INFO = 612, - SI_ALL_RIDING = 613, - SI_ALL_RIDING_REUSE_LIMIT = 614, - SI_MACRO = 615, - SI_MACRO_POSTDELAY = 616, - SI_BEER_BOTTLE_CAP = 617, - SI_OVERLAPEXPUP = 618, - SI_PC_IZ_DUN05 = 619, - SI_CRUSHSTRIKE = 620, - SI_MONSTER_TRANSFORM = 621, - SI_SIT = 622, - SI_ONAIR = 623, - SI_MTF_ASPD = 624, - SI_MTF_RANGEATK = 625, - SI_MTF_MATK = 626, - SI_MTF_MLEATKED = 627, - SI_MTF_CRIDAMAGE = 628, - SI_REUSE_LIMIT_MTF = 629, - SI_MACRO_PERMIT = 630, - SI_MACRO_PLAY = 631, - SI_SKF_CAST = 632, - SI_SKF_ASPD = 633, - SI_SKF_ATK = 634, - SI_SKF_MATK = 635, - SI_REWARD_PLUSONLYJOBEXP = 636, - SI_HANDICAPSTATE_NORECOVER = 637, - SI_SET_NUM_DEF = 638, - SI_SET_NUM_MDEF = 639, - SI_SET_PER_DEF = 640, - SI_SET_PER_MDEF = 641, - SI_PARTYBOOKING_SEARCH_DEALY = 642, - SI_PARTYBOOKING_REGISTER_DEALY = 643, - SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644, - SI_KO_JYUMONJIKIRI = 645, - SI_MEIKYOUSISUI = 646, - SI_ATTHASTE_CASH = 647, - SI_EQUIPPED_DIVINE_ARMOR = 648, - SI_EQUIPPED_HOLY_ARMOR = 649, - SI_2011RWC = 650, - SI_KYOUGAKU = 651, - SI_IZAYOI = 652, - SI_ZENKAI = 653, - SI_KG_KAGEHUMI = 654, - SI_KYOMU = 655, - SI_KAGEMUSYA = 656, - SI_ZANGETSU = 657, - SI_PHI_DEMON = 658, - SI_GENSOU = 659, - SI_AKAITSUKI = 660, - SI_TETANY = 661, - SI_GM_BATTLE = 662, - SI_GM_BATTLE2 = 663, - SI_2011RWC_SCROLL = 664, - SI_ACTIVE_MONSTER_TRANSFORM = 665, - SI_MYSTICPOWDER = 666, - SI_ECLAGE_RECALL = 667, - SI_ENTRY_QUEUE_APPLY_DELAY = 668, - SI_REUSE_LIMIT_ECL = 669, - SI_M_LIFEPOTION = 670, + SI_SILVERVEIN_RUSH_POSTDELAY = 596, + SI_MIDNIGHT_FRENZY_POSTDELAY = 597, + SI_GOLDENE_FERSE = 598, + SI_ANGRIFFS_MODUS = 599, + + SI_TINDER_BREAKER = 600, + SI_TINDER_BREAKER_POSTDELAY = 601, + SI_CBC = 602, + SI_CBC_POSTDELAY = 603, + SI_EQC = 604, + SI_MAGMA_FLOW = 605, + SI_GRANITIC_ARMOR = 606, + SI_PYROCLASTIC = 607, + SI_VOLCANIC_ASH = 608, + SI_SPIRITS_SAVEINFO1 = 609, + SI_SPIRITS_SAVEINFO2 = 610, + SI_MAGIC_CANDY = 611, + SI_SEARCH_STORE_INFO = 612, + SI_ALL_RIDING = 613, + SI_ALL_RIDING_REUSE_LIMIT = 614, + SI_MACRO = 615, + SI_MACRO_POSTDELAY = 616, + SI_BEER_BOTTLE_CAP = 617, + SI_OVERLAPEXPUP = 618, + SI_PC_IZ_DUN05 = 619, + SI_CRUSHSTRIKE = 620, + SI_MONSTER_TRANSFORM = 621, + SI_SIT = 622, + SI_ONAIR = 623, + SI_MTF_ASPD = 624, + SI_MTF_RANGEATK = 625, + SI_MTF_MATK = 626, + SI_MTF_MLEATKED = 627, + SI_MTF_CRIDAMAGE = 628, + SI_REUSE_LIMIT_MTF = 629, + SI_MACRO_PERMIT = 630, + SI_MACRO_PLAY = 631, + SI_SKF_CAST = 632, + SI_SKF_ASPD = 633, + SI_SKF_ATK = 634, + SI_SKF_MATK = 635, + SI_REWARD_PLUSONLYJOBEXP = 636, + SI_HANDICAPSTATE_NORECOVER = 637, + SI_SET_NUM_DEF = 638, + SI_SET_NUM_MDEF = 639, + SI_SET_PER_DEF = 640, + SI_SET_PER_MDEF = 641, + SI_PARTYBOOKING_SEARCH_DEALY = 642, + SI_PARTYBOOKING_REGISTER_DEALY = 643, + SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644, + SI_KO_JYUMONJIKIRI = 645, + SI_MEIKYOUSISUI = 646, + SI_ATTHASTE_CASH = 647, + SI_EQUIPPED_DIVINE_ARMOR = 648, + SI_EQUIPPED_HOLY_ARMOR = 649, + + SI_2011RWC = 650, + SI_KYOUGAKU = 651, + SI_IZAYOI = 652, + SI_ZENKAI = 653, + SI_KG_KAGEHUMI = 654, + SI_KYOMU = 655, + SI_KAGEMUSYA = 656, + SI_ZANGETSU = 657, + SI_PHI_DEMON = 658, + SI_GENSOU = 659, + SI_AKAITSUKI = 660, + SI_TETANY = 661, + SI_GM_BATTLE = 662, + SI_GM_BATTLE2 = 663, + SI_2011RWC_SCROLL = 664, + SI_ACTIVE_MONSTER_TRANSFORM = 665, + SI_MYSTICPOWDER = 666, + SI_ECLAGE_RECALL = 667, + SI_ENTRY_QUEUE_APPLY_DELAY = 668, + SI_REUSE_LIMIT_ECL = 669, + SI_M_LIFEPOTION = 670, SI_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT = 671, - SI_UNKNOWN_NAME = 672, - SI_ON_PUSH_CART = 673, - SI_HAT_EFFECT = 674, - SI_FLOWER_LEAF = 675, - SI_RAY_OF_PROTECTION = 676, - SI_GLASTHEIM_ATK = 677, - SI_GLASTHEIM_DEF = 678, - SI_GLASTHEIM_HEAL = 679, - SI_GLASTHEIM_HIDDEN = 680, - SI_GLASTHEIM_STATE = 681, - SI_GLASTHEIM_ITEMDEF = 682, - SI_GLASTHEIM_HPSP = 683, - SI_HOMUN_SKILL_POSTDELAY = 684, - SI_ALMIGHTY = 685, - SI_GVG_GIANT = 686, - SI_GVG_GOLEM = 687, - SI_GVG_STUN = 688, - SI_GVG_STONE = 689, - SI_GVG_FREEZ = 690, - SI_GVG_SLEEP = 691, - SI_GVG_CURSE = 692, - SI_GVG_SILENCE = 693, - SI_GVG_BLIND = 694, - SI_CLIENT_ONLY_EQUIP_ARROW = 695, - SI_CLAN_INFO = 696, - SI_JP_EVENT01 = 697, - SI_JP_EVENT02 = 698, - SI_JP_EVENT03 = 699, - SI_JP_EVENT04 = 700, - SI_TELEPORT_FIXEDCASTINGDELAY = 701, - SI_GEFFEN_MAGIC1 = 702, - SI_GEFFEN_MAGIC2 = 703, - SI_GEFFEN_MAGIC3 = 704, - SI_QUEST_BUFF1 = 705, - SI_QUEST_BUFF2 = 706, - SI_QUEST_BUFF3 = 707, - SI_REUSE_LIMIT_RECALL = 708, - SI_SAVEPOSITION = 709, - SI_HANDICAPSTATE_ICEEXPLO = 710, - SI_FENRIR_CARD = 711, - SI_REUSE_LIMIT_ASPD_POTION = 712, - SI_MAXPAIN = 713, - SI_PC_STOP = 714, - SI_FRIGG_SONG = 715, - SI_OFFERTORIUM = 716, - SI_TELEKINESIS_INTENSE = 717, - SI_MOONSTAR = 718, - SI_STRANGELIGHTS = 719, - SI_FULL_THROTTLE = 720, - SI_REBOUND = 721, - SI_UNLIMIT = 722, - SI_KINGS_GRACE = 723, - SI_ITEM_ATKMAX = 724, - SI_ITEM_ATKMIN = 725, - SI_ITEM_MATKMAX = 726, - SI_ITEM_MATKMIN = 727, - SI_SUPER_STAR = 728, - SI_HIGH_RANKER = 729, - SI_DARKCROW = 730, - SI_2013_VALENTINE1 = 731, - SI_2013_VALENTINE2 = 732, - SI_2013_VALENTINE3 = 733, - SI_ILLUSIONDOPING = 734, - //SI_ = 735, - SI_CHILL = 736, - SI_BURNT = 737, - SI_FLASHCOMBO = 740, - SI_B_TRAP = 752, - SI_E_CHAIN = 753, - SI_E_QD_SHOT_READY = 754, - SI_C_MARKER = 755, - SI_H_MINE = 756, - SI_H_MINE_SPLASH = 757, - SI_P_ALTER = 758, - SI_HEAT_BARREL = 759, - SI_ANTI_M_BLAST = 760, - SI_SLUGSHOT = 761, - SI_SWORDCLAN = 762, - SI_ARCWANDCLAN = 763, - SI_GOLDENMACECLAN = 764, - SI_CROSSBOWCLAN = 765, - SI_PACKING_ENVELOPE1 = 766, - SI_PACKING_ENVELOPE2 = 767, - SI_PACKING_ENVELOPE3 = 768, - SI_PACKING_ENVELOPE4 = 769, - SI_PACKING_ENVELOPE5 = 770, - SI_PACKING_ENVELOPE6 = 771, - SI_PACKING_ENVELOPE7 = 772, - SI_PACKING_ENVELOPE8 = 773, - SI_PACKING_ENVELOPE9 = 774, - SI_PACKING_ENVELOPE10 = 775, - SI_GLASTHEIM_TRANS = 776, - SI_HEAT_BARREL_AFTER = 778, - SI_DECORATION_OF_MUSIC = 779, + SI_UNKNOWN_NAME = 672, + SI_ON_PUSH_CART = 673, + SI_HAT_EFFECT = 674, + SI_FLOWER_LEAF = 675, + SI_RAY_OF_PROTECTION = 676, + SI_GLASTHEIM_ATK = 677, + SI_GLASTHEIM_DEF = 678, + SI_GLASTHEIM_HEAL = 679, + SI_GLASTHEIM_HIDDEN = 680, + SI_GLASTHEIM_STATE = 681, + SI_GLASTHEIM_ITEMDEF = 682, + SI_GLASTHEIM_HPSP = 683, + SI_HOMUN_SKILL_POSTDELAY = 684, + SI_ALMIGHTY = 685, + SI_GVG_GIANT = 686, + SI_GVG_GOLEM = 687, + SI_GVG_STUN = 688, + SI_GVG_STONE = 689, + SI_GVG_FREEZ = 690, + SI_GVG_SLEEP = 691, + SI_GVG_CURSE = 692, + SI_GVG_SILENCE = 693, + SI_GVG_BLIND = 694, + SI_CLIENT_ONLY_EQUIP_ARROW = 695, + SI_CLAN_INFO = 696, + SI_JP_EVENT01 = 697, + SI_JP_EVENT02 = 698, + SI_JP_EVENT03 = 699, + + SI_JP_EVENT04 = 700, + SI_TELEPORT_FIXEDCASTINGDELAY = 701, + SI_GEFFEN_MAGIC1 = 702, + SI_GEFFEN_MAGIC2 = 703, + SI_GEFFEN_MAGIC3 = 704, + SI_QUEST_BUFF1 = 705, + SI_QUEST_BUFF2 = 706, + SI_QUEST_BUFF3 = 707, + SI_REUSE_LIMIT_RECALL = 708, + SI_SAVEPOSITION = 709, + SI_HANDICAPSTATE_ICEEXPLO = 710, + SI_FENRIR_CARD = 711, + SI_REUSE_LIMIT_ASPD_POTION = 712, + SI_MAXPAIN = 713, + SI_PC_STOP = 714, + SI_FRIGG_SONG = 715, + SI_OFFERTORIUM = 716, + SI_TELEKINESIS_INTENSE = 717, + SI_MOONSTAR = 718, + SI_STRANGELIGHTS = 719, + SI_FULL_THROTTLE = 720, + SI_REBOUND = 721, + SI_UNLIMIT = 722, + SI_KINGS_GRACE = 723, + SI_ITEM_ATKMAX = 724, + SI_ITEM_ATKMIN = 725, + SI_ITEM_MATKMAX = 726, + SI_ITEM_MATKMIN = 727, + SI_SUPER_STAR = 728, + SI_HIGH_RANKER = 729, + SI_DARKCROW = 730, + SI_2013_VALENTINE1 = 731, + SI_2013_VALENTINE2 = 732, + SI_2013_VALENTINE3 = 733, + SI_ILLUSIONDOPING = 734, + //SI_ = 735, + SI_CHILL = 736, + SI_BURNT = 737, +// SI_PCCAFE_PLAY_TIME = 738, +// SI_TWISTED_TIME = 739, + SI_FLASHCOMBO = 740, + +// SI_JITTER_BUFF1 = 741, +// SI_JITTER_BUFF2 = 742, +// SI_JITTER_BUFF3 = 743, +// SI_JITTER_BUFF4 = 744, +// SI_JITTER_BUFF5 = 745, +// SI_JITTER_BUFF6 = 746, +// SI_JITTER_BUFF7 = 747, +// SI_JITTER_BUFF8 = 748, +// SI_JITTER_BUFF9 = 749, +// SI_JITTER_BUFF10 = 750, +// SI_CUP_OF_BOZA = 751, + SI_B_TRAP = 752, + SI_E_CHAIN = 753, + SI_E_QD_SHOT_READY = 754, + SI_C_MARKER = 755, + SI_H_MINE = 756, + SI_H_MINE_SPLASH = 757, + SI_P_ALTER = 758, + SI_HEAT_BARREL = 759, + SI_ANTI_M_BLAST = 760, + SI_SLUGSHOT = 761, + SI_SWORDCLAN = 762, + SI_ARCWANDCLAN = 763, + SI_GOLDENMACECLAN = 764, + SI_CROSSBOWCLAN = 765, + SI_PACKING_ENVELOPE1 = 766, + SI_PACKING_ENVELOPE2 = 767, + SI_PACKING_ENVELOPE3 = 768, + SI_PACKING_ENVELOPE4 = 769, + SI_PACKING_ENVELOPE5 = 770, + SI_PACKING_ENVELOPE6 = 771, + SI_PACKING_ENVELOPE7 = 772, + SI_PACKING_ENVELOPE8 = 773, + SI_PACKING_ENVELOPE9 = 774, + SI_PACKING_ENVELOPE10 = 775, + SI_GLASTHEIM_TRANS = 776, +// SI_ZONGZI_POUCH_TRANS = 777, + SI_HEAT_BARREL_AFTER = 778, + SI_DECORATION_OF_MUSIC = 779, + +// SI_OVERSEAEXPUP = 780, +// SI_CLOWN_N_GYPSY_CARD = 781, +// SI_OPEN_NPC_MARKET = 782, +// SI_BEEF_RIB_STEW = 783, +// SI_PORK_RIB_STEW = 784, +// SI_CHUSEOK_MONDAY = 785, +// SI_CHUSEOK_TUESDAY = 786, +// SI_CHUSEOK_WEDNESDAY = 787, +// SI_CHUSEOK_THURSDAY = 788, +// SI_CHUSEOK_FRIDAY = 789, +// SI_CHUSEOK_WEEKEND = 790, +// SI_ALL_LIGHTGUARD = 791, +// SI_ALL_LIGHTGUARD_COOL_TIME = 792, +// SI_MTF_MHP = 793, +// SI_MTF_MSP = 794, +// SI_MTF_PUMPKIN = 795, +// SI_MTF_HITFLEE = 796, +// SI_MTF_CRIDAMAGE2 = 797, +// SI_MTF_SPDRAIN = 798, +// SI_ACUO_MINT_GUM = 799, +// ... +// SI_GUILD_STORAGE = 810, +// ... +// SI_JUMPINGCLAN = 815, +// ... +// SI_MTF_RANGEATK2 = 818, +// SI_MTF_ASPD2 = 819, +// SI_MTF_MATK2 = 820, + SI_MAX, }; // JOINTBEAT stackable ailments @@ -1500,6 +1571,7 @@ enum e_mode MD_CHANGETARGET_MELEE = 0x1000, MD_CHANGETARGET_CHASE = 0x2000, MD_TARGETWEAK = 0x4000, + MD_RANDOMTARGET = 0x8000, MD_MASK = 0xFFFF, }; @@ -1694,7 +1766,7 @@ struct status_data { speed, amotion, adelay, dmotion, mode; - short + short hit, flee, cri, flee2, def2, mdef2, #ifdef RENEWAL_ASPD @@ -1863,7 +1935,7 @@ struct s_refine_info { }; /*===================================== -* Interface : status.h +* Interface : status.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -1878,11 +1950,7 @@ struct status_interface { int hp_coefficient2[CLASS_COUNT]; int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; int sp_coefficient[CLASS_COUNT]; -#ifdef RENEWAL_ASPD - int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; -#else - int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] -#endif + int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD sc_type Skill2SCTable[MAX_SKILL]; // skill -> status int IconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) unsigned int ChangeFlagTable[SC_MAX]; // status -> flags @@ -1971,6 +2039,7 @@ struct status_interface { int (*get_total_mdef) (struct block_list *src); int (*get_total_def) (struct block_list *src); int (*get_matk) (struct block_list *src, int flag); + void (*update_matk) ( struct block_list *bl ); int (*readdb) (void); void (*initChangeTables) (void); @@ -2020,4 +2089,4 @@ struct status_interface *status; void status_defaults(void); -#endif /* _MAP_STATUS_H_ */ +#endif /* MAP_STATUS_H */ diff --git a/src/map/storage.c b/src/map/storage.c index e65ed7b80..217f14a3a 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -2,38 +2,39 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" +#define HERCULES_CORE -#include "map.h" // struct map_session_data #include "storage.h" -#include "chrif.h" -#include "itemdb.h" -#include "clif.h" -#include "intif.h" -#include "pc.h" -#include "guild.h" -#include "battle.h" -#include "atcommand.h" -#include "log.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; /*========================================== * Sort items in the warehouse *------------------------------------------*/ -int storage_comp_item(const void *_i1, const void *_i2) +int storage_comp_item(const void *i1_, const void *i2_) { - struct item *i1 = (struct item *)_i1; - struct item *i2 = (struct item *)_i2; + struct item *i1 = (struct item *)i1_; + struct item *i2 = (struct item *)i2_; if (i1->nameid == i2->nameid) return 0; @@ -542,7 +543,7 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) * @index : storage idx * return * 0 : fail -* 1 : succes +* 1 : success *------------------------------------------*/ int storage_guild_storageget(struct map_session_data* sd, int index, int amount) { @@ -583,7 +584,7 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount) * @index : cart inventory idx * return * 0 : fail -* 1 : succes +* 1 : success *------------------------------------------*/ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount) { @@ -615,7 +616,7 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int * @index : storage idx * return * 0 : fail -* 1 : succes +* 1 : success *------------------------------------------*/ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount) { @@ -646,7 +647,7 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a * Request to save guild storage * return * 0 : fail (no storage) -* 1 : succes +* 1 : success *------------------------------------------*/ int storage_guild_storagesave(int account_id, int guild_id, int flag) { @@ -667,7 +668,7 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag) * ACK save of guild storage * return * 0 : fail (no storage) -* 1 : succes +* 1 : success *------------------------------------------*/ int storage_guild_storagesaved(int guild_id) { diff --git a/src/map/storage.h b/src/map/storage.h index 8f9f904f6..186f21263 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -2,14 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_STORAGE_H_ -#define _MAP_STORAGE_H_ +#ifndef MAP_STORAGE_H +#define MAP_STORAGE_H + +#include "../common/cbasetypes.h" +#include "../common/db.h" -struct storage_data; struct guild_storage; struct item; struct map_session_data; -struct DBMap; struct storage_interface { /* */ @@ -24,7 +25,7 @@ struct storage_interface { int (*gettocart) (struct map_session_data *sd,int index,int amount); void (*close) (struct map_session_data *sd); void (*pc_quit) (struct map_session_data *sd, int flag); - int (*comp_item) (const void *_i1, const void *_i2); + int (*comp_item) (const void *i1_, const void *i2_); void (*sortitem) (struct item* items, unsigned int size); int (*reconnect_sub) (DBKey key, DBData *data, va_list ap); }; @@ -59,4 +60,4 @@ struct guild_storage_interface *gstorage; void storage_defaults(void); void gstorage_defaults(void); -#endif /* _MAP_STORAGE_H_ */ +#endif /* MAP_STORAGE_H */ diff --git a/src/map/trade.c b/src/map/trade.c index 44b669ebd..3bbb73568 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -2,25 +2,27 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/nullpo.h" -#include "../common/socket.h" +#define HERCULES_CORE #include "trade.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 "npc.h" -#include "battle.h" -#include "chrif.h" #include "storage.h" -#include "intif.h" -#include "atcommand.h" -#include "log.h" - -#include <stdio.h> -#include <string.h> +#include "../common/nullpo.h" +#include "../common/socket.h" struct trade_interface trade_s; @@ -59,7 +61,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta if( previous_sd ){ previous_sd->trade_partner = 0; clif->tradecancelled(previous_sd); - } // Once cancelled then continue to the new one. + } // Once canceled then continue to the new one. sd->trade_partner = 0; clif->tradecancelled(sd); } @@ -164,11 +166,13 @@ void trade_tradeack(struct map_session_data *sd, int type) { clif->tradestart(sd, type); } -/*========================================== - * Check here hacker for duplicate item in trade - * normal client refuse to have 2 same types of item (except equipment) in same trade window - * normal client authorise only no equiped item and only from inventory - *------------------------------------------*/ +/** + * Checks if an impossible trade will occur + * Normal clients refuse to have 2 items of the same type (except equipment) in the same trade window + * Normal clients authorize only no equipped items and only items from inventory + * @retval 0 The trade can continue + * @retval 1 Hack attempt + **/ int impossible_trade_check(struct map_session_data *sd) { struct item inventory[MAX_INVENTORY]; @@ -177,17 +181,15 @@ int impossible_trade_check(struct map_session_data *sd) nullpo_retr(1, sd); - if(sd->deal.zeny > sd->status.zeny) { - pc_setglobalreg(sd,script->add_str("ZENY_HACKER"),1); - return -1; - } + if( sd->deal.zeny > sd->status.zeny ) + return 1; // get inventory of player memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); - // remove this part: arrows can be trade and equiped + // remove this part: arrows can be trade and equipped // re-added! [celest] - // remove equiped items (they can not be trade) + // remove equipped items (they can not be trade) for (i = 0; i < MAX_INVENTORY; i++) if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO)) memset(&inventory[i], 0, sizeof(struct item)); @@ -455,7 +457,7 @@ void trade_tradeok(struct map_session_data *sd) { } /*========================================== - * 'Cancel' is pressed. (or trade was force-cancelled by the code) + * 'Cancel' is pressed. (or trade was force-canceled by the code) *------------------------------------------*/ void trade_tradecancel(struct map_session_data *sd) { struct map_session_data *target_sd; @@ -464,7 +466,7 @@ void trade_tradecancel(struct map_session_data *sd) { target_sd = map->id2sd(sd->trade_partner); if(!sd->state.trading) - { // Not trade acepted + { // Not trade accepted if( target_sd ) { target_sd->trade_partner = 0; clif->tradecancelled(target_sd); diff --git a/src/map/trade.h b/src/map/trade.h index f2c0d4622..f91ccd4a2 100644 --- a/src/map/trade.h +++ b/src/map/trade.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_TRADE_H_ -#define _MAP_TRADE_H_ +#ifndef MAP_TRADE_H +#define MAP_TRADE_H //Max distance from traders to enable a trade to take place. //TODO: battle_config candidate? @@ -27,4 +27,4 @@ struct trade_interface *trade; void trade_defaults(void); -#endif /* _MAP_TRADE_H_ */ +#endif /* MAP_TRADE_H */ diff --git a/src/map/unit.c b/src/map/unit.c index 39fff0eab..78a85ba3e 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2,45 +2,48 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/showmsg.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/HPM.h" +#define HERCULES_CORE +#include "../config/core.h" // RENEWAL_CAST +#include "unit.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 "mob.h" #include "pet.h" -#include "homunculus.h" -#include "instance.h" -#include "mercenary.h" -#include "elemental.h" +#include "script.h" #include "skill.h" -#include "clif.h" -#include "duel.h" -#include "npc.h" -#include "guild.h" #include "status.h" -#include "unit.h" -#include "battle.h" -#include "battleground.h" -#include "chat.h" +#include "storage.h" #include "trade.h" #include "vending.h" -#include "party.h" -#include "intif.h" -#include "chrif.h" -#include "script.h" -#include "storage.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.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}; @@ -241,7 +244,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { { if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)) { //Skill used, abort walking - clif->fixpos(bl); //Fix position as walk has been cancelled. + clif->fixpos(bl); //Fix position as walk has been canceled. return 0; } //Resend walk packet for proper Self Destruction display. @@ -289,7 +292,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { clif->move(ud); } else if(ud->state.running) { //Keep trying to run. - if ( !(unit->run(bl) || unit->wugdash(bl,sd)) ) + if ( !(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)) ) ud->state.running = 0; } else if (ud->target_to) { //Update target trajectory. @@ -377,8 +380,12 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) unit->set_target(ud, 0); sc = status->get_sc(bl); - if (sc && (sc->data[SC_CONFUSION] || sc->data[SC__CHAOS])) //Randomize the target position - map->random_dir(bl, &ud->to_x, &ud->to_y); + if( sc ) { + if( sc->data[SC_CONFUSION] || sc->data[SC__CHAOS] ) //Randomize the target position + map->random_dir(bl, &ud->to_x, &ud->to_y); + if( sc->data[SC_COMBOATTACK] ) + status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER); + } if(ud->walktimer != INVALID_TIMER) { // When you come to the center of the grid because the change of destination while you're walking right now @@ -479,137 +486,95 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int return 0; } -int unit_run(struct block_list *bl) { - struct status_change *sc = status->get_sc(bl); - short to_x,to_y,dir_x,dir_y; - int lv; - int i; - - if (!(sc && sc->data[SC_RUN])) - return 0; - - if (!unit->can_move(bl)) { - status_change_end(bl, SC_RUN, INVALID_TIMER); - return 0; - } - - lv = sc->data[SC_RUN]->val1; - dir_x = dirx[sc->data[SC_RUN]->val2]; - dir_y = diry[sc->data[SC_RUN]->val2]; - // determine destination cell - to_x = bl->x; - to_y = bl->y; - for(i=0;i<AREA_SIZE;i++) { - if(!map->getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) - break; - - //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] - if(sc->data[SC_RUN] && map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) - break; - - to_x += dir_x; - to_y += dir_y; - } +/** + * Called by unit_run when an object was hit + * @param sd Required only when using SC_WUGDASH + **/ +void unit_run_hit( struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type ) { + int lv = sc->data[type]->val1; - if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { - //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] + //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] + if( type == SC_RUN ) clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0); - //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] - unit->bl2ud(bl)->state.running = 0; - status_change_end(bl, SC_RUN, INVALID_TIMER); + //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] + unit->bl2ud(bl)->state.running = 0; + status_change_end(bl, type, INVALID_TIMER); + if( type == SC_RUN ) { skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit->getdir(bl),0); clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis. clif->sc_end(bl,bl->id,AREA,SI_TING); - return 0; - } - if (unit->walktoxy(bl, to_x, to_y, 1)) - return 1; - //There must be an obstacle nearby. Attempt walking one cell at a time. - do { - to_x -= dir_x; - to_y -= dir_y; - } while (--i > 0 && !unit->walktoxy(bl, to_x, to_y, 1)); - if ( i == 0 ) { - // copy-paste from above - clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0); - - //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] - unit->bl2ud(bl)->state.running = 0; - status_change_end(bl, SC_RUN, INVALID_TIMER); - - skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit->getdir(bl),0); + } else if( sd ) { clif->fixpos(bl); - clif->sc_end(bl,bl->id,AREA,SI_TING); - return 0; + skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL); } - return 1; + return; } -//Exclusive function to Wug Dash state. [Jobbie/3CeAM] -int unit_wugdash(struct block_list *bl, struct map_session_data *sd) { - struct status_change *sc = status->get_sc(bl); +/** + * Makes character run, used for SC_RUN and SC_WUGDASH + * @param sd Required only when using SC_WUGDASH + * @retval true Finished running + * @retval false Hit an object/Couldn't run + **/ +bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type type ) { + struct status_change *sc; short to_x,to_y,dir_x,dir_y; - int lv; int i; - if (!(sc && sc->data[SC_WUGDASH])) - return 0; - nullpo_ret(sd); - nullpo_ret(bl); + nullpo_retr(false, bl); + sc = status->get_sc(bl); - if (!unit->can_move(bl)) { - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); - return 0; + if( !(sc && sc->data[type]) ) + return false; + + if( !unit->can_move(bl) ) { + status_change_end(bl, type, INVALID_TIMER); + return false; } - lv = sc->data[SC_WUGDASH]->val1; - dir_x = dirx[sc->data[SC_WUGDASH]->val2]; - dir_y = diry[sc->data[SC_WUGDASH]->val2]; + dir_x = dirx[sc->data[type]->val2]; + dir_y = diry[sc->data[type]->val2]; + // determine destination cell to_x = bl->x; to_y = bl->y; - for(i=0;i<AREA_SIZE;i++) { + + // 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)) break; - if(sc->data[SC_WUGDASH] && map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) + //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] + if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC) ) break; to_x += dir_x; to_y += dir_y; } - if(to_x == bl->x && to_y == bl->y) { + // Can't run forward + if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { + unit->run_hit(bl, sc, sd, type); + return false; + } - unit->bl2ud(bl)->state.running = 0; - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); + if( unit->walktoxy(bl, to_x, to_y, 1) ) + return true; - if( sd ){ - clif->fixpos(bl); - skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL); - } - return 0; - } - if (unit->walktoxy(bl, to_x, to_y, 1)) - return 1; + //There must be an obstacle nearby. Attempt walking one cell at a time. do { to_x -= dir_x; to_y -= dir_y; } while (--i > 0 && !unit->walktoxy(bl, to_x, to_y, 1)); - if (i==0) { - - unit->bl2ud(bl)->state.running = 0; - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); - if( sd ){ - clif->fixpos(bl); - skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL); - } - return 0; + if ( i == 0 ) { + unit->run_hit(bl, sc, sd, type); + return false; } + return 1; } @@ -866,7 +831,7 @@ int unit_stop_walking(struct block_list *bl,int type) return 0; //NOTE: We are using timer data after deleting it because we know the //timer->delete function does not messes with it. If the function's - //behaviour changes in the future, this code could break! + //behavior changes in the future, this code could break! td = timer->get(ud->walktimer); timer->delete(ud->walktimer, unit->walktoxy_timer); ud->walktimer = INVALID_TIMER; @@ -889,7 +854,7 @@ int unit_stop_walking(struct block_list *bl,int type) if(bl->type == BL_PET && type&~0xff) ud->canmove_tick = timer->gettick() + (type>>8); - //Readded, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin] + //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) { status_change_end(bl, SC_RUN, INVALID_TIMER); status_change_end(bl, SC_WUGDASH, INVALID_TIMER); @@ -944,6 +909,7 @@ int unit_can_move(struct block_list *bl) { )) return 0; //Can't move + // Status changes that block movement if (sc) { if( sc->count && ( @@ -955,6 +921,7 @@ int unit_can_move(struct block_list *bl) { || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move || sc->data[SC_STOP] + || sc->data[SC_FALLENEMPIRE] || sc->data[SC_RG_CCONFINE_M] || sc->data[SC_RG_CCONFINE_S] || sc->data[SC_GS_MADNESSCANCEL] @@ -1100,7 +1067,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui ) { if (sc->data[SC_COMBOATTACK]->val2) target_id = sc->data[SC_COMBOATTACK]->val2; - else + else if( skill->get_inf(skill_id) != 1 ) // Only non-targetable skills should use auto target target_id = ud->target; if( skill->get_inf(skill_id)&INF_SELF_SKILL && skill->get_nk(skill_id)&NK_NO_DAMAGE )// exploit fix @@ -1177,8 +1144,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if( (skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1 ) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } + return 0; + } switch(skill_id){ case SA_CASTCANCEL: @@ -1247,7 +1214,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if (!temp) //Stop attack on non-combo skills [Skotlex] unit->stop_attack(src); - else if(ud->attacktimer != INVALID_TIMER) //Elsewise, delay current attack sequence + else if(ud->attacktimer != INVALID_TIMER) //Else-wise, delay current attack sequence ud->attackabletime = tick + status_get_adelay(src); ud->state.skillcastcancel = castcancel; @@ -1363,16 +1330,16 @@ 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);// eventhough this is not how official works but this will do the trick. bugreport:6829 + unit->stop_walking(src,1);// 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); if( casttime > 0 || temp ) - { + { if (sd && target->type == BL_MOB) { TBL_MOB *md = (TBL_MOB*)target; - mob->skill_event(md, src, tick, -1); //Cast targetted skill event. + mob->skill_event(md, src, tick, -1); //Cast targeted skill event. if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && battle->check_target(target, src, BCT_ENEMY) > 0) { @@ -1467,7 +1434,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( skill->not_ok(skill_id, sd) || !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) return 0; /** - * "WHY IS IT HEREE": pneuma cannot be cancelled past this point, the client displays the animation even, + * "WHY IS IT HEREE": pneuma cannot be canceled past this point, the client displays the animation even, * if we cancel it from nodamage_id, so it has to be here for it to not display the animation. **/ if( skill_id == AL_PNEUMA && map->getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) { @@ -1552,7 +1519,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( casttime > 0 ) { ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 ); if( (sd && pc->checkskill(sd,SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK) - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED); } else { ud->skilltimer = INVALID_TIMER; skill->castend_pos(ud->skilltimer,tick,src->id,0); @@ -1637,6 +1604,10 @@ int unit_attack(struct block_list *src,int target_id,int continuous) { unit->stop_attack(src); return 0; } + if( !pc->can_attack(sd, target_id) ) { + unit->stop_attack(src); + return 0; + } } if( battle->check_target(src,target,BCT_ENEMY) <= 0 || !status->check_skilluse(src, target, 0, 0) ) { unit->unattackable(src); @@ -1645,7 +1616,7 @@ int unit_attack(struct block_list *src,int target_id,int continuous) { ud->state.attack_continue = continuous; unit->set_target(ud, target_id); - if (continuous) //If you're to attack continously, set to auto-case character + if (continuous) //If you're to attack continuously, set to auto-case character ud->chaserange = status_get_range(src); //Just change target/type. [Skotlex] @@ -1826,6 +1797,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { #ifdef OFFICIAL_WALKPATH || !path->search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) #endif + || (sd && !pc->can_attack(sd, ud->target) ) ) return 0; // can't attack under these conditions @@ -1935,7 +1907,7 @@ int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) { /*========================================== * Cancels an ongoing skill cast. * flag&1: Cast-Cancel invoked. - * flag&2: Cancel only if skill is cancellable. + * flag&2: Cancel only if skill is can be cancel. *------------------------------------------*/ int unit_skillcastcancel(struct block_list *bl,int type) { @@ -1951,7 +1923,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) sd = BL_CAST(BL_PC, bl); if (type&2) { - //See if it can be cancelled. + //See if it can be canceled. if (!ud->state.skillcastcancel) return 0; @@ -2054,7 +2026,7 @@ int unit_changeviewsize(struct block_list *bl,short size) /*========================================== * Removes a bl/ud from the map. * Returns 1 on success. 0 if it couldn't be removed or the bl was free'd - * if clrtype is 1 (death), appropiate cleanup is performed. + * if clrtype is 1 (death), appropriate cleanup is performed. * Otherwise it is assumed bl is being warped. * On-Kill specific stuff is not performed here, look at status->damage for that. *------------------------------------------*/ @@ -2138,11 +2110,14 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i trade->cancel(sd); buyingstore->close(sd); searchstore->close(sd); - if(sd->state.storage_flag == 1) - storage->pc_quit(sd,0); - else if (sd->state.storage_flag == 2) - gstorage->pc_quit(sd,0); - sd->state.storage_flag = 0; //Force close it when being warped. + if( sd->menuskill_id != AL_TELEPORT ) { // issue: 8027 + if(sd->state.storage_flag == 1) + storage->pc_quit(sd,0); + else if (sd->state.storage_flag == 2) + gstorage->pc_quit(sd,0); + + sd->state.storage_flag = 0; //Force close it when being warped. + } if(sd->party_invite>0) party->reply_invite(sd,sd->party_invite,0); if(sd->guild_invite>0) @@ -2610,7 +2585,7 @@ void unit_defaults(void) { unit->walktobl_sub = unit_walktobl_sub; unit->walktobl = unit_walktobl; unit->run = unit_run; - unit->wugdash = unit_wugdash; + unit->run_hit = unit_run_hit; unit->escape = unit_escape; unit->movepos = unit_movepos; unit->setdir = unit_setdir; diff --git a/src/map/unit.h b/src/map/unit.h index 33fa4e052..9b95bae41 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -2,18 +2,16 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_UNIT_H_ -#define _MAP_UNIT_H_ - -//#include "map.h" -struct block_list; -struct unit_data; -struct map_session_data; +#ifndef MAP_UNIT_H +#define MAP_UNIT_H #include "clif.h" // clr_type -#include "map.h" // struct block_list #include "path.h" // struct walkpath_data -#include "skill.h" // struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset +#include "skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset +#include "../common/cbasetypes.h" + +struct map_session_data; +struct block_list; struct unit_data { struct block_list *bl; @@ -85,8 +83,8 @@ struct unit_interface { int (*walktoxy) (struct block_list *bl, short x, short y, int flag); int (*walktobl_sub) (int tid, int64 tick, int id, intptr_t data); int (*walktobl) (struct block_list *bl, struct block_list *tbl, int range, int flag); - int (*run) (struct block_list *bl); - int (*wugdash) (struct block_list *bl, struct map_session_data *sd); + bool (*run) (struct block_list *bl, struct map_session_data *sd, enum sc_type type); + void (*run_hit) (struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type); int (*escape) (struct block_list *bl, struct block_list *target, short dist); int (*movepos) (struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath); int (*setdir) (struct block_list *bl, unsigned char dir); @@ -126,4 +124,4 @@ struct unit_interface *unit; void unit_defaults(void); -#endif /* _MAP_UNIT_H_ */ +#endif /* MAP_UNIT_H */ diff --git a/src/map/vending.c b/src/map/vending.c index 9462975b3..7e9393bf2 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -2,24 +2,27 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/nullpo.h" -#include "../common/strlib.h" -#include "../common/utils.h" +#define HERCULES_CORE + +#include "vending.h" + +#include <stdio.h> +#include <string.h> + +#include "atcommand.h" +#include "battle.h" +#include "chrif.h" #include "clif.h" #include "itemdb.h" -#include "atcommand.h" +#include "log.h" #include "map.h" +#include "npc.h" #include "path.h" -#include "chrif.h" -#include "vending.h" #include "pc.h" -#include "npc.h" #include "skill.h" -#include "battle.h" -#include "log.h" - -#include <stdio.h> -#include <string.h> +#include "../common/nullpo.h" +#include "../common/strlib.h" +#include "../common/utils.h" struct vending_interface vending_s; @@ -57,7 +60,7 @@ void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) { // GM is not allowed to trade clif->message(sd->fd, msg_txt(246)); return; - } + } sd->vended_id = vsd->vender_id; // register vending uid diff --git a/src/map/vending.h b/src/map/vending.h index b2ba22955..63cb632a9 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -2,18 +2,19 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _MAP_VENDING_H_ -#define _MAP_VENDING_H_ +#ifndef MAP_VENDING_H +#define MAP_VENDING_H #include "../common/cbasetypes.h" #include "../common/db.h" + struct map_session_data; struct s_search_store_search; struct s_vending { short index; //cart index (return item data) - short amount; //amout of the item for vending - unsigned int value; //at wich price + short amount; //amount of the item for vending + unsigned int value; //at which price }; struct vending_interface { @@ -35,4 +36,4 @@ struct vending_interface *vending; void vending_defaults(void); -#endif /* _MAP_VENDING_H_ */ +#endif /* MAP_VENDING_H */ |