summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/HPMmap.c67
-rw-r--r--src/map/HPMmap.h2
-rw-r--r--src/map/Makefile.in67
-rw-r--r--src/map/achievement.c2010
-rw-r--r--src/map/achievement.h291
-rw-r--r--src/map/atcommand.c2109
-rw-r--r--src/map/atcommand.h31
-rw-r--r--src/map/battle.c1162
-rw-r--r--src/map/battle.h102
-rw-r--r--src/map/battleground.c155
-rw-r--r--src/map/battleground.h6
-rw-r--r--src/map/buyingstore.c93
-rw-r--r--src/map/buyingstore.h17
-rw-r--r--src/map/channel.c205
-rw-r--r--src/map/channel.h6
-rw-r--r--src/map/chat.c92
-rw-r--r--src/map/chat.h12
-rw-r--r--src/map/chrif.c281
-rw-r--r--src/map/chrif.h5
-rw-r--r--src/map/clan.c1075
-rw-r--r--src/map/clan.h85
-rw-r--r--src/map/clif.c12888
-rw-r--r--src/map/clif.h580
-rw-r--r--src/map/date.c25
-rw-r--r--src/map/date.h6
-rw-r--r--src/map/duel.c88
-rw-r--r--src/map/duel.h6
-rw-r--r--src/map/elemental.c121
-rw-r--r--src/map/elemental.h4
-rw-r--r--src/map/guild.c448
-rw-r--r--src/map/guild.h19
-rw-r--r--src/map/homunculus.c265
-rw-r--r--src/map/homunculus.h15
-rw-r--r--src/map/instance.c149
-rw-r--r--src/map/instance.h5
-rw-r--r--src/map/intif.c1299
-rw-r--r--src/map/intif.h53
-rw-r--r--src/map/irc-bot.c278
-rw-r--r--src/map/irc-bot.h135
-rw-r--r--src/map/itemdb.c1112
-rw-r--r--src/map/itemdb.h235
-rw-r--r--src/map/log.c445
-rw-r--r--src/map/log.h16
-rw-r--r--src/map/mail.c32
-rw-r--r--src/map/mail.h4
-rw-r--r--src/map/map.c2098
-rw-r--r--src/map/map.h497
-rw-r--r--src/map/mapdefines.h119
-rw-r--r--src/map/mapreg.h8
-rw-r--r--src/map/mapreg_sql.c67
-rw-r--r--src/map/mercenary.c83
-rw-r--r--src/map/mercenary.h6
-rw-r--r--src/map/messages.h36
-rw-r--r--src/map/messages_ad.h7311
-rw-r--r--src/map/messages_main.h22617
-rw-r--r--src/map/messages_re.h22094
-rw-r--r--src/map/messages_sak.h8268
-rw-r--r--src/map/messages_zero.h18706
-rw-r--r--src/map/mob.c2964
-rw-r--r--src/map/mob.h116
-rw-r--r--src/map/npc.c1637
-rw-r--r--src/map/npc.h87
-rw-r--r--src/map/npc_chat.c66
-rw-r--r--src/map/packets.h4163
-rw-r--r--src/map/packets_keys_main.h2137
-rw-r--r--src/map/packets_keys_zero.h228
-rw-r--r--src/map/packets_shuffle_main.h9859
-rw-r--r--src/map/packets_shuffle_re.h9802
-rw-r--r--src/map/packets_shuffle_zero.h859
-rw-r--r--src/map/packets_struct.h3711
-rw-r--r--src/map/party.c316
-rw-r--r--src/map/party.h7
-rw-r--r--src/map/path.c38
-rw-r--r--src/map/path.h4
-rw-r--r--src/map/pc.c4871
-rw-r--r--src/map/pc.h371
-rw-r--r--src/map/pc_groups.c49
-rw-r--r--src/map/pc_groups.h5
-rw-r--r--src/map/pet.c1403
-rw-r--r--src/map/pet.h44
-rw-r--r--src/map/quest.c393
-rw-r--r--src/map/quest.h53
-rw-r--r--src/map/refine.c669
-rw-r--r--src/map/refine.h148
-rw-r--r--src/map/refine.p.h144
-rw-r--r--src/map/rodex.c683
-rw-r--r--src/map/rodex.h87
-rw-r--r--src/map/script.c12419
-rw-r--r--src/map/script.h339
-rw-r--r--src/map/searchstore.c93
-rw-r--r--src/map/searchstore.h21
-rw-r--r--src/map/skill.c5251
-rw-r--r--src/map/skill.h271
-rw-r--r--src/map/status.c4551
-rw-r--r--src/map/status.h1158
-rw-r--r--src/map/storage.c409
-rw-r--r--src/map/storage.h4
-rw-r--r--src/map/stylist.c229
-rw-r--r--src/map/stylist.h69
-rw-r--r--src/map/trade.c87
-rw-r--r--src/map/trade.h4
-rw-r--r--src/map/unit.c1148
-rw-r--r--src/map/unit.h50
-rw-r--r--src/map/unitdefines.h58
-rw-r--r--src/map/vending.c62
-rw-r--r--src/map/vending.h6
106 files changed, 155449 insertions, 23705 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index 289375323..42c7b3c5f 100644
--- a/src/map/HPMmap.c
+++ b/src/map/HPMmap.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,10 +31,15 @@
#include "common/db.h"
#include "common/des.h"
#include "common/ers.h"
+#include "common/grfio.h"
+#include "common/md5calc.h"
#include "common/memmgr.h"
+#include "common/mutex.h"
#include "common/mapindex.h"
#include "common/mmo.h"
#include "common/nullpo.h"
+#include "common/packets.h"
+#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
#include "common/spinlock.h"
@@ -43,6 +48,7 @@
#include "common/sysinfo.h"
#include "common/timer.h"
#include "common/utils.h"
+#include "map/achievement.h"
#include "map/atcommand.h"
#include "map/battle.h"
#include "map/battleground.h"
@@ -50,6 +56,7 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/date.h"
#include "map/duel.h"
@@ -67,18 +74,21 @@
#include "map/mercenary.h"
#include "map/mob.h"
#include "map/npc.h"
-#include "map/packets_struct.h"
#include "map/party.h"
#include "map/path.h"
#include "map/pc.h"
#include "map/pc_groups.h"
#include "map/pet.h"
#include "map/quest.h"
+#include "map/rodex.h"
+#include "map/refine.h"
+#include "map/refine.p.h"
#include "map/script.h"
#include "map/searchstore.h"
#include "map/skill.h"
#include "map/status.h"
#include "map/storage.h"
+#include "map/stylist.h"
#include "map/trade.h"
#include "map/unit.h"
#include "map/vending.h"
@@ -98,8 +108,8 @@ struct HPM_atcommand_list {
AtCommandFunc func;
};
-struct HPM_atcommand_list *atcommand_list = NULL;
-unsigned int atcommand_list_items = 0;
+static struct HPM_atcommand_list *atcommand_list = NULL;
+static unsigned int atcommand_list_items = 0;
/**
* HPM plugin data store validator sub-handler (map-server)
@@ -109,33 +119,36 @@ unsigned int atcommand_list_items = 0;
bool HPM_map_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize)
{
switch (type) {
- case HPDT_MSD:
- case HPDT_NPCD:
- case HPDT_MAP:
- case HPDT_PARTY:
- case HPDT_GUILD:
- case HPDT_INSTANCE:
- case HPDT_MOBDB:
- case HPDT_MOBDATA:
- case HPDT_ITEMDATA:
- case HPDT_BGDATA:
- case HPDT_AUTOTRADE_VEND:
- // Initialized by the caller.
- return true;
- default:
- break;
+ case HPDT_MSD:
+ case HPDT_NPCD:
+ case HPDT_MAP:
+ case HPDT_PARTY:
+ case HPDT_GUILD:
+ case HPDT_INSTANCE:
+ case HPDT_MOBDB:
+ case HPDT_MOBDATA:
+ case HPDT_ITEMDATA:
+ case HPDT_BGDATA:
+ case HPDT_AUTOTRADE_VEND:
+ case HPDT_CLAN:
+ // Initialized by the caller.
+ return true;
+ default:
+ break;
}
return false;
}
-void HPM_map_plugin_load_sub(struct hplugin *plugin) {
+void HPM_map_plugin_load_sub(struct hplugin *plugin)
+{
plugin->hpi->sql_handle = map->mysql_handle;
plugin->hpi->addCommand = atcommand->create;
plugin->hpi->addScript = script->addScript;
plugin->hpi->addPCGPermission = HPM_map_add_group_permission;
}
-bool HPM_map_add_atcommand(char *name, AtCommandFunc func) {
+bool HPM_map_add_atcommand(char *name, AtCommandFunc func)
+{
unsigned int i = 0;
for(i = 0; i < atcommand_list_items; i++) {
@@ -155,7 +168,8 @@ bool HPM_map_add_atcommand(char *name, AtCommandFunc func) {
return true;
}
-void HPM_map_atcommands(void) {
+void HPM_map_atcommands(void)
+{
unsigned int i;
for(i = 0; i < atcommand_list_items; i++) {
@@ -166,7 +180,8 @@ void HPM_map_atcommands(void) {
/**
* Adds a new group permission to the HPM-provided list
**/
-void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask) {
+void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask)
+{
unsigned char index = pcg->HPMpermissions_count;
RECREATE(pcg->HPMpermissions, struct pc_groups_new_permission, ++pcg->HPMpermissions_count);
@@ -176,14 +191,16 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in
pcg->HPMpermissions[index].mask = mask;
}
-void HPM_map_do_init(void) {
+void HPM_map_do_init(void)
+{
HPM->load_sub = HPM_map_plugin_load_sub;
HPM->data_store_validate_sub = HPM_map_data_store_validate;
HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
HPM_shared_symbols(SERVER_TYPE_MAP);
}
-void HPM_map_do_final(void) {
+void HPM_map_do_final(void)
+{
if (atcommand_list)
aFree(atcommand_list);
/**
diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h
index a9d2a454e..52ab36cce 100644
--- a/src/map/HPMmap.h
+++ b/src/map/HPMmap.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index b5a3d4461..75093662f 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -1,8 +1,8 @@
# This file is part of Hercules.
# http://herc.ws - http://github.com/HerculesWS/Hercules
#
-# Copyright (C) 2012-2015 Hercules Dev Team
-# Copyright (C) Athena Dev Teams
+# Copyright (C) 2012-2020 Hercules Dev Team
+# Copyright (C) Athena Dev Teams
#
# Hercules is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@ CONFIG_D = ../config
CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h)
COMMON_D = ../common
-COMMON_H = $(wildcard $(COMMON_D)/*.h)
+COMMON_H = $(filter-out %.p.h, $(wildcard $(COMMON_D)/*.h)) ../plugins/HPMHooking.h
SYSINFO_INC = $(COMMON_D)/sysinfo.inc
COMMON_INCLUDE = -I..
@@ -36,27 +36,44 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
-MAP_C = atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \
- chrif.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \
+MAP_C = achievement.c atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \
+ chrif.c clan.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \
instance.c intif.c irc-bot.c itemdb.c log.c mail.c map.c mapreg_sql.c \
mercenary.c mob.c npc.c npc_chat.c party.c path.c pc.c pc_groups.c \
- pet.c quest.c script.c searchstore.c skill.c status.c storage.c \
- trade.c unit.c vending.c
+ pet.c quest.c refine.c rodex.c script.c searchstore.c skill.c status.c storage.c \
+ stylist.c trade.c unit.c vending.c
MAP_OBJ = $(addprefix obj_sql/, $(patsubst %c,%o,$(MAP_C)))
-MAP_H = atcommand.h battle.h battleground.h buyingstore.h channel.h chat.h \
- chrif.h clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \
+MAP_H = achievement.h atcommand.h battle.h battleground.h buyingstore.h channel.h chat.h \
+ chrif.h clan.h clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \
instance.h intif.h irc-bot.h itemdb.h log.h mail.h map.h mapreg.h \
- mercenary.h mob.h npc.h packets.h packets_struct.h party.h path.h \
- pc.h pc_groups.h pet.h quest.h script.h searchstore.h skill.h \
- status.h storage.h trade.h unit.h vending.h
+ mercenary.h messages.h messages_ad.h messages_main.h messages_re.h \
+ messages_sak.h messages_zero.h mob.h npc.h packets.h packets_keys_main.h \
+ packets_keys_zero.h packets_shuffle_main.h packets_shuffle_re.h \
+ packets_shuffle_zero.h packets_struct.h party.h path.h pc.h pc_groups.h \
+ pet.h quest.h refine.h rodex.h script.h searchstore.h skill.h status.h storage.h \
+ stylist.h trade.h unit.h vending.h
+MAP_PH = refine.p.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 $(SYSINFO_INC))
+ MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC)
else
MAP_SERVER_SQL_DEPENDS=needs_mysql
endif
@@ -95,7 +112,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/map/Makefile
-$(SYSINFO_INC): $(MAP_C) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(MAP_C) $(MAP_PH) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -115,14 +132,8 @@ map-server: ../../map-server@EXEEXT@
../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
- @$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
- $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
-
-# map object files
-
-obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
- @echo " CC $<"
- @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+ @$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \
+ $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@
# missing object files
$(COMMON_D)/obj_all/common.a:
@@ -140,3 +151,15 @@ $(MT19937AR_OBJ):
$(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)
+
+.SECONDEXPANSION:
+
+# map object files
+
+obj_sql/%.o: %.c $$(filter %.p.h, $(MAP_PH)) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj_sql
+ @echo " CC $<"
+ @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/map/achievement.c b/src/map/achievement.c
new file mode 100644
index 000000000..e6a9ae3be
--- /dev/null
+++ b/src/map/achievement.c
@@ -0,0 +1,2010 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2017-2020 Hercules Dev Team
+* Copyright (C) Smokexyz
+* Copyright (C) Dastgir
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#define HERCULES_CORE
+
+#include "map/achievement.h"
+
+#include "map/itemdb.h"
+#include "map/mob.h"
+#include "map/party.h"
+#include "map/pc.h"
+#include "map/script.h"
+
+#include "common/conf.h"
+#include "common/db.h"
+#include "common/memmgr.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+#include "common/strlib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct achievement_interface achievement_s;
+struct achievement_interface *achievement;
+
+/**
+ * Retrieve an achievement via it's ID.
+ * @param aid as the achievement ID.
+ * @return NULL or pointer to the achievement data.
+ */
+static const struct achievement_data *achievement_get(int aid)
+{
+ return (struct achievement_data *) idb_get(achievement->db, aid);
+}
+
+/**
+ * Searches the provided achievement data for an achievement,
+ * optionally creates a new one if no key exists.
+ * @param[in] sd a pointer to map_session_data.
+ * @param[in] aid ID of the achievement provided as key.
+ * @param[in] create new key creation flag.
+ * @return pointer to the session's achievement data.
+ */
+static struct achievement *achievement_ensure(struct map_session_data *sd, const struct achievement_data *ad)
+{
+ struct achievement *s_ad = NULL;
+ int i = 0;
+
+ nullpo_retr(NULL, sd);
+ nullpo_retr(NULL, ad);
+
+ /* Lookup for achievement entry */
+ ARR_FIND(0, VECTOR_LENGTH(sd->achievement), i, (s_ad = &VECTOR_INDEX(sd->achievement, i)) && s_ad->id == ad->id);
+
+ if (i == VECTOR_LENGTH(sd->achievement)) {
+ struct achievement ta = { 0 };
+ ta.id = ad->id;
+
+ VECTOR_ENSURE(sd->achievement, 1, 1);
+ VECTOR_PUSH(sd->achievement, ta);
+
+ s_ad = &VECTOR_LAST(sd->achievement);
+ }
+
+ return s_ad;
+}
+
+/**
+ * Calculates the achievement's totals via reference.
+ * @param[in] sd pointer to map_session_data
+ * @param[out] tota_points pointer to total points var
+ * @param[out] completed pointer to total var
+ * @param[out] rank pointer to completed var
+ * @param[out] curr_rank_points pointer to achievement rank var
+ */
+static void achievement_calculate_totals(const struct map_session_data *sd, int *total_points, int *completed, int *rank, int *curr_rank_points)
+{
+ const struct achievement *a = NULL;
+ const struct achievement_data *ad = NULL;
+ int tmp_curr_points = 0;
+ int tmp_total_points = 0;
+ int tmp_total_completed = 0;
+ int tmp_rank = 0;
+ int i = 0;
+
+ nullpo_retv(sd);
+
+ for (i = 0; i < VECTOR_LENGTH(sd->achievement); i++) {
+ a = &VECTOR_INDEX(sd->achievement, i);
+
+ if ((ad = achievement->get(a->id)) == NULL)
+ continue;
+
+ if (a->completed_at != 0) {
+ tmp_total_points += ad->points;
+ tmp_total_completed++;
+ }
+ }
+
+ if (tmp_total_points > 0) {
+ tmp_curr_points = tmp_total_points;
+ for (i = 0; i < MAX_ACHIEVEMENT_RANKS
+ && tmp_curr_points >= VECTOR_INDEX(achievement->rank_exp, i)
+ && i < VECTOR_LENGTH(achievement->rank_exp); i++) {
+ tmp_curr_points -= VECTOR_INDEX(achievement->rank_exp, i);
+ tmp_rank++;
+ }
+ }
+
+ if (total_points != NULL)
+ *total_points = tmp_total_points;
+
+ if (completed != NULL)
+ *completed = tmp_total_completed;
+
+ if (rank != NULL)
+ *rank = tmp_rank;
+
+ if (curr_rank_points != NULL)
+ *curr_rank_points = tmp_curr_points;
+}
+
+/**
+ * Checks whether all objectives of the achievement are completed.
+ * @param[in] sd as the map_session_data pointer
+ * @param[in] ad as the achievement_data pointer
+ * @return true if complete, false if not.
+ */
+static bool achievement_check_complete(struct map_session_data *sd, const struct achievement_data *ad)
+{
+ int i;
+ struct achievement *ach = NULL;
+
+ nullpo_retr(false, sd);
+ nullpo_retr(false, ad);
+
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return false;
+ for (i = 0; i < VECTOR_LENGTH(ad->objective); i++)
+ if (ach->objective[i] < VECTOR_INDEX(ad->objective, i).goal)
+ return false;
+
+ return true;
+}
+
+/**
+ * Compares the progress of an objective against it's goal.
+ * Increments the progress of the objective by the specified amount, towards the goal.
+ * @param sd [in] as a pointer to map_session_data
+ * @param ad [in] as a pointer to the achievement_data
+ * @param obj_idx [in] as the index of the objective.
+ * @param progress [in] as the progress of the objective to be added.
+ */
+static void achievement_progress_add(struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress)
+{
+ struct achievement *ach = NULL;
+
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ Assert_retv(progress != 0);
+ Assert_retv(obj_idx < VECTOR_LENGTH(ad->objective));
+
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return;
+
+ if (ach->completed_at)
+ return; // ignore the call if the achievement is completed.
+
+ // Check and increment the objective count.
+ if (!ach->objective[obj_idx] || ach->objective[obj_idx] < VECTOR_INDEX(ad->objective, obj_idx).goal) {
+ ach->objective[obj_idx] = min(progress + ach->objective[obj_idx], VECTOR_INDEX(ad->objective, obj_idx).goal);
+
+ // Check if the Achievement is complete.
+ if (achievement->check_complete(sd, ad)) {
+ achievement->validate_achieve(sd, ad->id);
+ ach->completed_at = time(NULL);
+ }
+
+ // update client.
+ clif->achievement_send_update(sd->fd, sd, ad);
+ }
+}
+
+/**
+ * Compare an absolute progress value against the goal of an objective.
+ * Does not add/increase progress.
+ * @param sd [in] pointer to map-server session data.
+ * @param ad [in] pointer to achievement data.
+ * @param obj_idx [in] index of the objective in question.
+ * @param progress progress of the objective in question.
+ */
+static void achievement_progress_set(struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress)
+{
+ struct achievement *ach = NULL;
+
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ Assert_retv(progress != 0);
+ Assert_retv(obj_idx < VECTOR_LENGTH(ad->objective));
+
+ if (progress >= VECTOR_INDEX(ad->objective, obj_idx).goal) {
+
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return;
+
+ if (ach->completed_at)
+ return;
+
+ ach->objective[obj_idx] = VECTOR_INDEX(ad->objective, obj_idx).goal;
+
+ if (achievement->check_complete(sd, ad)) {
+ achievement->validate_achieve(sd, ad->id);
+ ach->completed_at = time(NULL);
+ }
+
+ clif->achievement_send_update(sd->fd, sd, ad);
+ }
+}
+
+/**
+* Checks if the given criteria satisfies the achievement's objective.
+* @param objective [in] pointer to the achievement's objectives data.
+* @param criteria [in] pointer to the current session's criteria as a comparand.
+* @return true if all criteria are satisfied, else false.
+*/
+static bool achievement_check_criteria(const struct achievement_objective *objective, const struct achievement_objective *criteria)
+{
+ int i = 0, j = 0;
+
+ nullpo_retr(false, objective);
+ nullpo_retr(false, criteria);
+
+ /* Item Id */
+ if (objective->unique_type == CRITERIA_UNIQUE_ITEM_ID && objective->unique.itemid != criteria->unique.itemid)
+ return false;
+ /* Weapon Level */
+ else if (objective->unique_type == CRITERIA_UNIQUE_WEAPON_LV && objective->unique.weapon_lv != criteria->unique.weapon_lv)
+ return false;
+ /* Status Types */
+ else if (objective->unique_type == CRITERIA_UNIQUE_STATUS_TYPE && objective->unique.status_type != criteria->unique.status_type)
+ return false;
+ /* Achievement Id */
+ else if (objective->unique_type == CRITERIA_UNIQUE_ACHIEVE_ID && objective->unique.achieve_id != criteria->unique.achieve_id)
+ return false;
+
+ /* Monster Id */
+ if (objective->mobid > 0 && objective->mobid != criteria->mobid)
+ return false;
+
+ /* Item Type */
+ if (objective->item_type > 0 && (objective->item_type & (2 << criteria->item_type)) == 0)
+ return false;
+
+ /* Job Ids */
+ for (i = 0; i < VECTOR_LENGTH(objective->jobid); i++) {
+ ARR_FIND(0, VECTOR_LENGTH(criteria->jobid), j, VECTOR_INDEX(criteria->jobid, j) != VECTOR_INDEX(objective->jobid, i));
+ if (j < VECTOR_LENGTH(criteria->jobid))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates an Achievement Objective of similar types.
+ * @param[in] sd as a pointer to the map session data.
+ * @param[in] type as the type of the achievement.
+ * @param[in] criteria as the criteria of the objective (mob id, job id etc.. 0 for no criteria).
+ * @param[in] progress as the current progress of the objective.
+ * @return total number of updated achievements on success, 0 on failure.
+ */
+static int achievement_validate_type(struct map_session_data *sd, enum achievement_types type, const struct achievement_objective *criteria, bool additive)
+{
+ int i = 0, total = 0;
+ struct achievement *ach = NULL;
+
+ nullpo_ret(sd);
+ nullpo_ret(criteria);
+
+ Assert_ret(criteria->goal != 0);
+
+ if (battle_config.feature_enable_achievement == 0)
+ return 0;
+
+ if (type == ACH_QUEST) {
+ ShowError("achievement_validate_type: ACH_QUEST is not handled by this function. (use achievement_validate())\n");
+ return 0;
+ } else if (type >= ACH_TYPE_MAX) {
+ ShowError("achievement_validate_type: Invalid Achievement Type %d! (min: %d, max: %d)\n", (int)type, (int)ACH_QUEST, (int)ACH_TYPE_MAX - 1);
+ return 0;
+ }
+
+ /* Loop through all achievements of the type, checking for possible matches. */
+ for (i = 0; i < VECTOR_LENGTH(achievement->category[type]); i++) {
+ int j = 0;
+ bool updated = false;
+ const struct achievement_data *ad = NULL;
+
+ if ((ad = achievement->get(VECTOR_INDEX(achievement->category[type], i))) == NULL)
+ continue;
+
+ for (j = 0; j < VECTOR_LENGTH(ad->objective); j++) {
+ // Check if objective criteria matches.
+ if (achievement->check_criteria(&VECTOR_INDEX(ad->objective, j), criteria) == false)
+ continue;
+ // Ensure availability of the achievement.
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return false;
+ // Criteria passed, check if not completed and update progress.
+ if ((ach->completed_at == 0 && ach->objective[j] < VECTOR_INDEX(ad->objective, j).goal)) {
+ if (additive == true)
+ achievement->progress_add(sd, ad, j, criteria->goal);
+ else
+ achievement->progress_set(sd, ad, j, criteria->goal);
+ updated = true;
+ }
+ }
+
+ if (updated == true)
+ total++;
+ }
+
+ return total;
+}
+
+/**
+ * Validates any achievement's specific objective index.
+ * @param[in] sd pointer to the session data.
+ * @param[in] aid ID of the achievement.
+ * @param[in] index index of the objective.
+ * @param[in] progress progress to be added towards the goal.
+ */
+static bool achievement_validate(struct map_session_data *sd, int aid, unsigned int obj_idx, int progress, bool additive)
+{
+ const struct achievement_data *ad = NULL;
+ struct achievement *ach = NULL;
+
+ nullpo_retr(false, sd);
+ Assert_retr(false, progress > 0);
+ Assert_retr(false, obj_idx < MAX_ACHIEVEMENT_OBJECTIVES);
+
+ if (battle_config.feature_enable_achievement == 0)
+ return false;
+
+ if ((ad = achievement->get(aid)) == NULL) {
+ ShowError("achievement_validate: Invalid Achievement %d provided.", aid);
+ return false;
+ }
+
+ // Ensure availability of the achievement.
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return false;
+
+ // Check if not completed and update progress.
+ if ((!ach->completed_at && ach->objective[obj_idx] < VECTOR_INDEX(ad->objective, obj_idx).goal)) {
+ if (additive == true)
+ achievement->progress_add(sd, ad, obj_idx, progress);
+ else
+ achievement->progress_set(sd, ad, obj_idx, progress);
+ }
+
+ return true;
+}
+
+/**
+ * Validates monster kill type objectives.
+ * @type ACH_KILL_MOB_CLASS
+ * @param[in] sd pointer to session data.
+ * @param[in] mob_id (criteria) class of the monster checked for.
+ * @param[in] progress (goal) progress to be added.
+ * @see achievement_vaildate_type()
+ */
+static void achievement_validate_mob_kill(struct map_session_data *sd, int mob_id)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+ Assert_retv(mob_id > 0 && mob->db(mob_id) != NULL);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.mobid = mob_id;
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_KILL_MOB_CLASS, &criteria, true);
+}
+
+/**
+ * Validate monster damage type objectives.
+ * @types ACH_DAMAGE_MOB_REC_MAX
+ * ACH_DAMAGE_MOB_REC_TOTAL
+ * @param[in] sd pointer to session data.
+ * @param[in] damage amount of damage received/dealt.
+ * @param received received/dealt boolean switch.
+ */
+static void achievement_validate_mob_damage(struct map_session_data *sd, unsigned int damage, bool received)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+ Assert_retv(damage > 0);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = (int) damage;
+
+ if (received) {
+ achievement->validate_type(sd, ACH_DAMAGE_MOB_REC_MAX, &criteria, false);
+ achievement->validate_type(sd, ACH_DAMAGE_MOB_REC_TOTAL, &criteria, true);
+ } else {
+ achievement->validate_type(sd, ACH_DAMAGE_MOB_MAX, &criteria, false);
+ achievement->validate_type(sd, ACH_DAMAGE_MOB_TOTAL, &criteria, true);
+ }
+
+}
+
+/**
+ * Validate player kill (PVP) achievements.
+ * @types ACH_KILL_PC_TOTAL
+ * ACH_KILL_PC_JOB
+ * ACH_KILL_PC_JOBTYPE
+ * @param[in] sd pointer to killed player's session data.
+ * @param[in] dstsd pointer to killer's session data.
+ */
+static void achievement_validate_pc_kill(struct map_session_data *sd, struct map_session_data *dstsd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+ nullpo_retv(dstsd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+
+ /* */
+ achievement->validate_type(sd, ACH_KILL_PC_TOTAL, &criteria, true);
+
+ /* */
+ VECTOR_INIT(criteria.jobid);
+ VECTOR_ENSURE(criteria.jobid, 1, 1);
+ VECTOR_PUSH(criteria.jobid, dstsd->status.class);
+
+ /* Job class */
+ achievement->validate_type(sd, ACH_KILL_PC_JOB, &criteria, true);
+ /* Job Type */
+ achievement->validate_type(sd, ACH_KILL_PC_JOBTYPE, &criteria, true);
+
+ VECTOR_CLEAR(criteria.jobid);
+}
+
+/**
+ * Validate player kill (PVP) achievements.
+ * @types ACH_DAMAGE_PC_MAX
+ * ACH_DAMAGE_PC_TOTAL
+ * ACH_DAMAGE_PC_REC_MAX
+ * ACH_DAMAGE_PC_REC_TOTAL
+ * @param[in] sd pointer to source player's session data.
+ * @param[in] dstsd pointer to target player's session data.
+ * @param[in] damage amount of damage dealt / received.
+ */
+static void achievement_validate_pc_damage(struct map_session_data *sd, struct map_session_data *dstsd, unsigned int damage)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ if (damage == 0)
+ return;
+
+ criteria.goal = (int) damage;
+
+ /* */
+ achievement->validate_type(sd, ACH_DAMAGE_PC_MAX, &criteria, false);
+ achievement->validate_type(sd, ACH_DAMAGE_PC_TOTAL, &criteria, true);
+
+ /* */
+ achievement->validate_type(dstsd, ACH_DAMAGE_PC_REC_MAX, &criteria, false);
+ achievement->validate_type(dstsd, ACH_DAMAGE_PC_REC_TOTAL, &criteria, true);
+}
+
+/**
+ * Validates job change objectives.
+ * @type ACH_JOB_CHANGE
+ * @param[in] sd pointer to session data.
+ * @see achivement_validate_type()
+ */
+static void achievement_validate_jobchange(struct map_session_data *sd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ VECTOR_INIT(criteria.jobid);
+ VECTOR_ENSURE(criteria.jobid, 1, 1);
+ VECTOR_PUSH(criteria.jobid, sd->status.class);
+
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_JOB_CHANGE, &criteria, false);
+
+ VECTOR_CLEAR(criteria.jobid);
+}
+
+/**
+ * Validates stat type objectives.
+ * @types ACH_STATUS
+ * ACH_STATUS_BY_JOB
+ * ACH_STATUS_BY_JOBTYPE
+ * @param[in] sd pointer to session data.
+ * @param[in] stat_type (criteria) status point type. (see status_point_types)
+ * @param[in] progress (goal) amount of absolute progress to check.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_stats(struct map_session_data *sd, enum status_point_types stat_type, int progress)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+ Assert_retv(progress > 0);
+
+ if (sd->achievements_received == false)
+ return;
+
+ if (!achievement_valid_status_types(stat_type)) {
+ ShowError("achievement_validate_stats: Invalid status type %d given.\n", (int) stat_type);
+ return;
+ }
+
+ criteria.unique.status_type = stat_type;
+
+ criteria.goal = progress;
+
+ achievement->validate_type(sd, ACH_STATUS, &criteria, false);
+
+ VECTOR_INIT(criteria.jobid);
+ VECTOR_ENSURE(criteria.jobid, 1, 1);
+ VECTOR_PUSH(criteria.jobid, sd->status.class);
+
+ /* Stat and Job class */
+ achievement->validate_type(sd, ACH_STATUS_BY_JOB, &criteria, false);
+
+ /* Stat and Job Type */
+ achievement->validate_type(sd, ACH_STATUS_BY_JOBTYPE, &criteria, false);
+
+ VECTOR_CLEAR(criteria.jobid);
+}
+
+/**
+ * Validates chatroom creation type objectives.
+ * @types ACH_CHATROOM_CREATE
+ * ACH_CHATROOM_CREATE_DEAD
+ * @param[in] sd pointer to session data.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_chatroom_create(struct map_session_data *sd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+
+ if (pc_isdead(sd)) {
+ achievement->validate_type(sd, ACH_CHATROOM_CREATE_DEAD, &criteria, true);
+ return;
+ }
+
+ achievement->validate_type(sd, ACH_CHATROOM_CREATE, &criteria, true);
+}
+
+/**
+ * Validates chatroom member count type objectives.
+ * @type ACH_CHATROOM_MEMBERS
+ * @param[in] sd pointer to session data.
+ * @param[in] progress (goal) amount of progress to be added.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_chatroom_members(struct map_session_data *sd, int progress)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(progress > 0);
+
+ criteria.goal = progress;
+
+ achievement->validate_type(sd, ACH_CHATROOM_MEMBERS, &criteria, false);
+}
+
+/**
+ * Validates friend add type objectives.
+ * @type ACH_FRIEND_ADD
+ * @param[in] sd pointer to session data.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_friend_add(struct map_session_data *sd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_FRIEND_ADD, &criteria, true);
+}
+
+/**
+ * Validates party creation type objectives.
+ * @type ACH_PARTY_CREATE
+ * @param[in] sd pointer to session data.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_party_create(struct map_session_data *sd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+ achievement->validate_type(sd, ACH_PARTY_CREATE, &criteria, true);
+}
+
+/**
+ * Validates marriage type objectives.
+ * @type ACH_MARRY
+ * @param[in] sd pointer to session data.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_marry(struct map_session_data *sd)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_MARRY, &criteria, true);
+}
+
+/**
+ * Validates adoption type objectives.
+ * @types ACH_ADOPT_PARENT
+ * ACH_ADOPT_BABY
+ * @param[in] sd pointer to session data.
+ * @param[in] parent (type) boolean value to indicate if parent (true) or baby (false).
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_adopt(struct map_session_data *sd, bool parent)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ criteria.goal = 1;
+
+ if (parent)
+ achievement->validate_type(sd, ACH_ADOPT_PARENT, &criteria, true);
+ else
+ achievement->validate_type(sd, ACH_ADOPT_BABY, &criteria, true);
+}
+
+/**
+ * Validates zeny type objectives.
+ * @types ACH_ZENY_HOLD
+ * ACH_ZENY_GET_ONCE
+ * ACH_ZENY_GET_TOTAL
+ * ACH_ZENY_SPEND_ONCE
+ * ACH_ZENY_SPEND_TOTAL
+ * @param[in] sd pointer to session data.
+ * @param[in] amount (goal) amount of zeny earned or spent.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_zeny(struct map_session_data *sd, int amount)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(amount != 0);
+
+ if (amount > 0) {
+ criteria.goal = sd->status.zeny;
+ achievement->validate_type(sd, ACH_ZENY_HOLD, &criteria, false);
+ criteria.goal = amount;
+ achievement->validate_type(sd, ACH_ZENY_GET_ONCE, &criteria, false);
+ achievement->validate_type(sd, ACH_ZENY_GET_TOTAL, &criteria, true);
+ } else {
+ criteria.goal = -amount;
+ achievement->validate_type(sd, ACH_ZENY_SPEND_ONCE, &criteria, false);
+ achievement->validate_type(sd, ACH_ZENY_SPEND_TOTAL, &criteria, true);
+ }
+}
+
+/**
+ * Validates equipment refinement type objectives.
+ * @types ACH_EQUIP_REFINE_SUCCESS
+ * ACH_EQUIP_REFINE_FAILURE
+ * ACH_EQUIP_REFINE_SUCCESS_TOTAL
+ * ACH_EQUIP_REFINE_FAILURE_TOTAL
+ * ACH_EQUIP_REFINE_SUCCESS_WLV
+ * ACH_EQUIP_REFINE_FAILURE_WLV
+ * ACH_EQUIP_REFINE_SUCCESS_ID
+ * ACH_EQUIP_REFINE_FAILURE_ID
+ * @param[in] sd pointer to session data.
+ * @param[in] idx Inventory index of the item.
+ * @param[in] success (type) boolean switch for failure / success.
+ * @see achievement_validate_type()
+ */
+static void achievement_validate_refine(struct map_session_data *sd, unsigned int idx, bool success)
+{
+ struct achievement_objective criteria = { 0 };
+ struct item_data *id = NULL;
+
+ nullpo_retv(sd);
+ Assert_retv(idx < sd->status.inventorySize);
+
+ id = itemdb->exists(sd->status.inventory[idx].nameid);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(id != NULL);
+
+ criteria.goal = sd->status.inventory[idx].refine;
+
+ // achievement should not trigger if refine is 0
+ if (criteria.goal == 0)
+ return;
+
+ /* Universal */
+ achievement->validate_type(sd,
+ success ? ACH_EQUIP_REFINE_SUCCESS : ACH_EQUIP_REFINE_FAILURE,
+ &criteria, false);
+
+ /* Total */
+ criteria.goal = 1;
+ achievement->validate_type(sd,
+ success ? ACH_EQUIP_REFINE_SUCCESS_TOTAL : ACH_EQUIP_REFINE_FAILURE_TOTAL,
+ &criteria, true);
+
+ /* By Weapon Level */
+ if (id->type == IT_WEAPON) {
+ criteria.item_type = id->type;
+ criteria.unique.weapon_lv = id->wlv;
+ criteria.goal = sd->status.inventory[idx].refine;
+ achievement->validate_type(sd,
+ success ? ACH_EQUIP_REFINE_SUCCESS_WLV : ACH_EQUIP_REFINE_FAILURE_WLV,
+ &criteria, false);
+ criteria.item_type = 0;
+ criteria.unique.weapon_lv = 0; // cleanup
+ }
+
+ /* By NameId */
+ criteria.unique.itemid = id->nameid;
+ criteria.goal = sd->status.inventory[idx].refine;
+ achievement->validate_type(sd,
+ success ? ACH_EQUIP_REFINE_SUCCESS_ID : ACH_EQUIP_REFINE_FAILURE_ID,
+ &criteria, false);
+ criteria.unique.itemid = 0; // cleanup
+}
+
+/**
+ * Validates item received type objectives.
+ * @types ACH_ITEM_GET_COUNT
+ * ACH_ITEM_GET_WORTH
+ * ACH_ITEM_GET_COUNT_ITEMTYPE
+ * @param[in] sd pointer to session data.
+ * @param[in] nameid (criteria) ID of the item.
+ * @param[in] amount (goal) amount of the item collected.
+ */
+static void achievement_validate_item_get(struct map_session_data *sd, int nameid, int amount)
+{
+ struct item_data *it = itemdb->exists(nameid);
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(amount > 0);
+ nullpo_retv(it);
+
+ criteria.unique.itemid = it->nameid;
+ criteria.goal = amount;
+ achievement->validate_type(sd, ACH_ITEM_GET_COUNT, &criteria, false);
+ criteria.unique.itemid = 0; // cleanup
+
+ /* Item Buy Value*/
+ criteria.goal = max(it->value_buy, 1);
+ achievement->validate_type(sd, ACH_ITEM_GET_WORTH, &criteria, false);
+
+ /* Item Type */
+ criteria.item_type = it->type;
+ criteria.goal = 1;
+ achievement->validate_type(sd, ACH_ITEM_GET_COUNT_ITEMTYPE, &criteria, false);
+ criteria.item_type = 0; // cleanup
+}
+
+/**
+ * Validates item sold type objectives.
+ * @type ACH_ITEM_SELL_WORTH
+ * @param[in] sd pointer to session data.
+ * @param[in] nameid Item Id in question.
+ * @param[in] amount amount of item in question.
+ */
+static void achievement_validate_item_sell(struct map_session_data *sd, int nameid, int amount)
+{
+ struct item_data *it = itemdb->exists(nameid);
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(amount > 0);
+ nullpo_retv(it);
+
+ criteria.unique.itemid = it->nameid;
+
+ criteria.goal = max(it->value_sell, 1);
+
+ achievement->validate_type(sd, ACH_ITEM_SELL_WORTH, &criteria, false);
+}
+
+/**
+ * Validates achievement type objectives.
+ * @type ACH_ACHIEVE
+ * @param[in] sd pointer to session data.
+ * @param[in] achid (criteria) achievement id.
+ */
+static void achievement_validate_achieve(struct map_session_data *sd, int achid)
+{
+ const struct achievement_data *ad = achievement->get(achid);
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(achid > 0);
+
+ criteria.unique.achieve_id = ad->id;
+
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_ACHIEVE, &criteria, false);
+}
+
+/**
+ * Validates taming type objectives.
+ * @type ACH_PET_CREATE
+ * @param[in] sd pointer to session data.
+ * @param[in] class (criteria) class of the monster tamed.
+ */
+static void achievement_validate_taming(struct map_session_data *sd, int class)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(class > 0);
+ Assert_retv(mob->db(class) != mob->dummy);
+
+ criteria.mobid = class;
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_PET_CREATE, &criteria, true);
+}
+
+/**
+ * Validated achievement rank type objectives.
+ * @type ACH_ACHIEVEMENT_RANK
+ * @param[in] sd pointer to session data.
+ * @param[in] rank (goal) rank of earned.
+ */
+static void achievement_validate_achievement_rank(struct map_session_data *sd, int rank)
+{
+ struct achievement_objective criteria = { 0 };
+
+ nullpo_retv(sd);
+
+ if (sd->achievements_received == false)
+ return;
+
+ Assert_retv(rank >= 0 && rank <= VECTOR_LENGTH(achievement->rank_exp));
+
+ criteria.goal = 1;
+
+ achievement->validate_type(sd, ACH_ACHIEVEMENT_RANK, &criteria, false);
+}
+
+/**
+ * Verifies if an achievement type requires a criteria field.
+ * @param[in] type achievement type in question.
+ * @return true if required, false if not.
+ */
+static bool achievement_type_requires_criteria(enum achievement_types type)
+{
+ if (type == ACH_KILL_PC_JOB
+ || type == ACH_KILL_PC_JOBTYPE
+ || type == ACH_KILL_MOB_CLASS
+ || type == ACH_JOB_CHANGE
+ || type == ACH_STATUS
+ || type == ACH_STATUS_BY_JOB
+ || type == ACH_STATUS_BY_JOBTYPE
+ || type == ACH_EQUIP_REFINE_SUCCESS_WLV
+ || type == ACH_EQUIP_REFINE_FAILURE_WLV
+ || type == ACH_EQUIP_REFINE_SUCCESS_ID
+ || type == ACH_EQUIP_REFINE_FAILURE_ID
+ || type == ACH_ITEM_GET_COUNT
+ || type == ACH_PET_CREATE
+ || type == ACH_ACHIEVE)
+ return true;
+
+ return false;
+}
+
+/**
+ * Stores all the title ID that has been earned by player
+ * @param[in] sd pointer to session data.
+ */
+static void achievement_init_titles(struct map_session_data *sd)
+{
+ int i;
+ nullpo_retv(sd);
+
+ VECTOR_INIT(sd->title_ids);
+ /* Browse through the session's achievement list and gather their values. */
+ for (i = 0; i < VECTOR_LENGTH(sd->achievement); i++) {
+ struct achievement *a = &VECTOR_INDEX(sd->achievement, i);
+ const struct achievement_data *ad = NULL;
+
+ /* Sanity check for nonull pointers. */
+ if (a == NULL || (ad = achievement->get(a->id)) == NULL)
+ continue;
+
+ if (a->completed_at > 0 && a->rewarded_at > 0 && ad->rewards.title_id > 0) {
+ VECTOR_ENSURE(sd->title_ids, 1, 1);
+ VECTOR_PUSH(sd->title_ids, ad->rewards.title_id);
+ }
+ }
+}
+
+/**
+ * Validates whether player has earned the title.
+ * @param[in] sd pointer to session data.
+ * @param[in] title_id Title ID
+ * @return true, if title has been earned, else false
+ */
+static bool achievement_check_title(struct map_session_data *sd, int title_id) {
+ int i;
+
+ nullpo_retr(false, sd);
+
+ if (title_id == 0)
+ return true;
+
+ for (i = 0; i < VECTOR_LENGTH(sd->title_ids); i++) {
+ if (VECTOR_INDEX(sd->title_ids, i) == title_id) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void achievement_get_rewards_buffs(struct map_session_data *sd, const struct achievement_data *ad)
+{
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ if (ad->rewards.bonus != NULL)
+ script->run(ad->rewards.bonus, 0, sd->bl.id, 0);
+}
+
+// TODO: kro send items by rodex
+static void achievement_get_rewards_items(struct map_session_data *sd, const struct achievement_data *ad)
+{
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ struct item it = { 0 };
+ it.identify = 1;
+
+ for (int i = 0; i < VECTOR_LENGTH(ad->rewards.item); i++) {
+ it.nameid = VECTOR_INDEX(ad->rewards.item, i).id;
+ int total = VECTOR_INDEX(ad->rewards.item, i).amount;
+
+ //Check if it's stackable.
+ if (!itemdb->isstackable(it.nameid)) {
+ it.amount = 1;
+ for (int j = 0; j < total; ++j)
+ pc->additem(sd, &it, 1, LOG_TYPE_ACHIEVEMENT);
+ } else {
+ it.amount = total;
+ pc->additem(sd, &it, total, LOG_TYPE_ACHIEVEMENT);
+ }
+ }
+}
+
+/**
+ * Achievement rewards are given to player
+ * @param sd session data
+ * @param ad achievement data
+ */
+static bool achievement_get_rewards(struct map_session_data *sd, const struct achievement_data *ad)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, ad);
+
+ struct achievement *ach = achievement->ensure(sd, ad);
+ if (ach == NULL)
+ return false;
+
+ /* Buff */
+ achievement->get_rewards_buffs(sd, ad);
+
+ ach->rewarded_at = time(NULL);
+
+ if (ad->rewards.title_id > 0) { // Add Title
+ VECTOR_ENSURE(sd->title_ids, 1, 1);
+ VECTOR_PUSH(sd->title_ids, ad->rewards.title_id);
+ clif->achievement_send_list(sd->fd, sd);
+ } else {
+ clif->achievement_send_update(sd->fd, sd, ad); // send update.
+ clif->achievement_reward_ack(sd->fd, sd, ad);
+ }
+
+ /* Give Items */
+ achievement->get_rewards_items(sd, ad);
+
+ return true;
+}
+
+/**
+ * Parses the Achievement Ranks.
+ * @read db/achievement_rank_db.conf
+ */
+static void achievement_readdb_ranks(void)
+{
+ char filename[256];
+ libconfig->format_db_path("achievement_rank_db.conf", filename, sizeof(filename));
+ struct config_t ar_conf = { 0 };
+ struct config_setting_t *ardb = NULL, *conf = NULL;
+ int entry = 0;
+
+ if (!libconfig->load_file(&ar_conf, filename))
+ return; // report error.
+
+ if (!(ardb = libconfig->setting_get_member(ar_conf.root, "achievement_rank_db"))) {
+ ShowError("achievement_readdb_ranks: Could not process contents of file '%s', skipping...\n", filename);
+ libconfig->destroy(&ar_conf);
+ return;
+ }
+
+ while (entry < libconfig->setting_length(ardb) && entry < MAX_ACHIEVEMENT_RANKS) {
+ char rank[16];
+
+ if (!(conf = libconfig->setting_get_elem(ardb, entry))) {
+ ShowError("achievement_readdb_ranks: Could not read value for entry %d, skipping...\n", entry+1);
+ continue;
+ }
+
+ entry++; // Rank counter;
+
+ sprintf(rank, "Rank%d", entry);
+
+ if (strcmp(rank, config_setting_name(conf)) == 0) {
+ int exp = 0;
+
+ if ((exp = libconfig->setting_get_int(conf)) <= 0) {
+ ShowError("achievement_readdb_ranks: Invalid value provided for %s in '%s'.\n", rank, filename);
+ continue;
+ }
+
+ VECTOR_ENSURE(achievement->rank_exp, 1, 1);
+ VECTOR_PUSH(achievement->rank_exp, exp);
+ } else {
+ ShowWarning("achievement_readdb_ranks: Ranks are not in order! Ignoring all ranks after Rank %d...\n", entry);
+ break; // break if elements are not in order or rank doesn't exist.
+ }
+ }
+
+ if (libconfig->setting_length(ardb) > MAX_ACHIEVEMENT_RANKS)
+ ShowWarning("achievement_rankdb_ranks: Maximum number of achievement ranks exceeded. Skipping all after entry %d...\n", entry);
+
+ libconfig->destroy(&ar_conf);
+
+ if (!entry) {
+ ShowError("achievement_readdb_ranks: No ranks provided in '%s'!\n", filename);
+ return;
+ }
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entry, filename);
+}
+
+/**
+ * Validates Mob Id criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success
+ */
+static bool achievement_readdb_validate_criteria_mobid(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+ const char *string = NULL;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ if (libconfig->setting_lookup_int(t, "MobId", &val)) {
+ if (mob->db_checkid(val) == 0) {
+ ShowError("achievement_readdb_validate_criteria_mobid: Non-existant monster with ID %id provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->mobid = val;
+ } else if (libconfig->setting_lookup_string(t, "MobId", &string)) {
+ if (!script->get_constant(string, &val)) {
+ ShowError("achievement_readdb_validate_criteria_mobid: Non-existant constant %s provided (Achievement: %d, Objective: %d). Skipping...\n", string, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->mobid = val;
+ } else if (achievement_criteria_mobid(type)) {
+ ShowError("achievement_readdb_validate_criteria_mobid: Achievement type of ID %d requires MobId as objective criteria, setting not provided. Skipping...\n", entry_id);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates Job Id criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_jobid(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int job_id = 0;
+ const char *string = NULL;
+ struct config_setting_t *tt = NULL;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ // initialize the buffered objective jobid vector.
+ VECTOR_INIT(obj->jobid);
+
+ if (libconfig->setting_lookup_int(t, "JobId", &job_id)) {
+ if (pc->jobid2mapid(job_id) == -1) {
+ ShowError("achievement_readdb_validate_criteria_jobid: Invalid JobId %d provided (Achievement: %d, Objective: %d). Skipping...\n", job_id, entry_id, obj_idx);
+ return false;
+ }
+
+ VECTOR_ENSURE(obj->jobid, 1, 1);
+ VECTOR_PUSH(obj->jobid, job_id);
+ } else if (libconfig->setting_lookup_string(t, "JobId", &string)) {
+ if (script->get_constant(string, &job_id) == false) {
+ ShowError("achievement_readdb_validate_criteria_jobid: Invalid JobId %d provided (Achievement: %d, Objective: %d). Skipping...\n", job_id, entry_id, obj_idx);
+ return false;
+ }
+
+ VECTOR_ENSURE(obj->jobid, 1, 1);
+ VECTOR_PUSH(obj->jobid, job_id);
+ } else if ((tt = libconfig->setting_get_member(t, "JobId")) && config_setting_is_array(tt)) {
+ int j = 0;
+
+ while (j < libconfig->setting_length(tt)) {
+ if ((job_id = libconfig->setting_get_int_elem(tt, j)) == 0) {
+ if ((string = libconfig->setting_get_string_elem(tt, j)) != NULL && script->get_constant(string, &job_id) == false) {
+ ShowError("achievement_readdb_validate_criteria_jobid: Invalid JobId provided at index %d (Achievement: %d, Objective: %d). Skipping...\n", j, entry_id, obj_idx);
+ continue;
+ }
+ }
+
+ /* Ensure size and allocation */
+ VECTOR_ENSURE(obj->jobid, 1, 1);
+ /* push buffer */
+ VECTOR_PUSH(obj->jobid, job_id);
+ j++;
+ }
+ } else if (achievement_criteria_jobid(type)) {
+ ShowError("achievement_readdb_validate_criteria_jobid: Achievement type of ID %d requires a JobId field in the objective criteria, setting not provided. Skipping...\n", entry_id);
+ return false;
+ }
+
+ return true;
+
+}
+
+/**
+ * Validates Item Id criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_itemid(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+ const char *string = NULL;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+
+ if (libconfig->setting_lookup_int(t, "ItemId", &val)) {
+ if (itemdb->exists(val) == NULL) {
+ ShowError("achievement_readdb_validate_criteria_itemid: Invalid ItemID %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_itemid: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.itemid = val;
+ obj->unique_type = CRITERIA_UNIQUE_ITEM_ID;
+ } else if (libconfig->setting_lookup_string(t, "ItemId", &string)) {
+ if (script->get_constant(string, &val) == false) {
+ ShowError("achievement_readdb_validate_criteria_itemid: Invalid ItemID %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_itemid: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.itemid = val;
+ obj->unique_type = CRITERIA_UNIQUE_ITEM_ID;
+ } else if (achievement_criteria_itemid(type)) {
+ ShowError("achievement_readdb_validate_criteria_itemid: Criteria requires a ItemId field (Achievement: %d, Objective: %d). Skipping...\n", entry_id, obj_idx);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates Status Type criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_statustype(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+ const char *string = NULL;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ if (libconfig->setting_lookup_int(t, "StatusType", &val)) {
+ if (!achievement_valid_status_types(val)) {
+ ShowError("achievement_readdb_validate_criteria_statustype: Invalid StatusType %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_statustype: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.status_type = (enum status_point_types) val;
+ obj->unique_type = CRITERIA_UNIQUE_STATUS_TYPE;
+ } else if (libconfig->setting_lookup_string(t, "StatusType", &string)) {
+ if (strcmp(string, "SP_STR") == 0) val = SP_STR;
+ else if (strcmp(string, "SP_AGI") == 0) val = SP_AGI;
+ else if (strcmp(string, "SP_VIT") == 0) val = SP_VIT;
+ else if (strcmp(string, "SP_INT") == 0) val = SP_INT;
+ else if (strcmp(string, "SP_DEX") == 0) val = SP_DEX;
+ else if (strcmp(string, "SP_LUK") == 0) val = SP_LUK;
+ else if (strcmp(string, "SP_BASELEVEL") == 0) val = SP_BASELEVEL;
+ else if (strcmp(string, "SP_JOBLEVEL") == 0) val = SP_JOBLEVEL;
+ else val = SP_NONE;
+
+ if (!achievement_valid_status_types(val)) {
+ ShowError("achievement_readdb_validate_criteria_statustype: Invalid StatusType %s provided (Achievement: %d, Objective: %d). Skipping...\n", string, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_statustype: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.status_type = (enum status_point_types) val;
+ obj->unique_type = CRITERIA_UNIQUE_STATUS_TYPE;
+ } else if (achievement_criteria_stattype(type)) {
+ ShowError("achievement_readdb_validate_criteria_statustype: Criteria requires a StatusType field (Achievement: %d, Objective: %d). Skipping...\n", entry_id, obj_idx);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates Item Type criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_itemtype(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+ const char *string = NULL;
+ struct config_setting_t *tt = NULL;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ if (libconfig->setting_lookup_int(t, "ItemType", &val)) {
+ if (val < IT_HEALING || val > IT_MAX) {
+ ShowError("achievement_readdb_validate_criteria_itemtype: Invalid ItemType %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ }
+
+ if (val == IT_MAX) {
+ obj->item_type |= (2 << val) - 1;
+ } else {
+ obj->item_type |= (2 << val);
+ }
+
+ } else if (libconfig->setting_lookup_string(t, "ItemType", &string)) {
+ if (!script->get_constant(string, &val) || val < IT_HEALING || val > IT_MAX) {
+ ShowError("achievement_readdb_validate_criteria_itemtype: Invalid ItemType %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ }
+
+ if (val == IT_MAX) {
+ obj->item_type |= (2 << val) - 1;
+ } else {
+ obj->item_type |= (2 << val);
+ }
+ } else if ((tt = libconfig->setting_get_member(t, "ItemType")) && config_setting_is_array(tt)) {
+ int j = 0;
+
+ while (j < libconfig->setting_length(tt)) {
+ if ((val = libconfig->setting_get_int_elem(tt, j))) {
+ if (val < IT_HEALING || val > IT_MAX) {
+ ShowError("achievement_readdb_validate_criteria_itemtype: Invalid ItemType %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ continue;
+ }
+ if (val == IT_MAX) {
+ obj->item_type |= (2 << val) - 1;
+ } else {
+ obj->item_type |= (2 << val);
+ }
+ } else if ((string = libconfig->setting_get_string_elem(tt, j))) {
+ if (!script->get_constant(string, &val)) {
+ ShowError("achievement_readdb_validate_criteria_itemtype: Invalid ItemType %s provided (Achievement: %d, Objective: %d). Skipping...\n", string, entry_id, obj_idx);
+ continue;
+ }
+
+ if (val == IT_MAX) {
+ obj->item_type |= (2 << val) - 1;
+ } else {
+ obj->item_type |= (2 << val);
+ }
+ }
+ j++;
+ }
+ } else if (achievement_criteria_itemtype(type)) {
+ ShowError("achievement_readdb_validate_criteria_itemtype: Criteria requires a ItemType field (Achievement: %d, Objective: %d). Skipping...\n", entry_id, obj_idx);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates Weapon Level criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_weaponlv(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ if (libconfig->setting_lookup_int(t, "WeaponLevel", &val)) {
+ if (val < 1 || val > 4) {
+ ShowError("achievement_readdb_validate_criteria_weaponlv: Invalid WeaponLevel %d provided (Achievement: %d, Objective: %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_weaponlv: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.weapon_lv = val;
+ obj->unique_type = CRITERIA_UNIQUE_WEAPON_LV;
+ } else if (achievement_criteria_weaponlv(type)) {
+ ShowError("achievement_readdb_validate_criteria_weaponlv: Criteria requires a WeaponType field. (Achievement: %d, Objective: %d). Skipping...\n", entry_id, obj_idx);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validates achievement Id criteria of an objective while parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] obj pointer to the achievement objective entry being parsed.
+ * @param[in] type Type of the achievement being parsed.
+ * @param[in] entry_id Id of the entry being parsed.
+ * @param[in] obj_idx Index of the objective entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_criteria_achievement(const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx)
+{
+ int val = 0;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, obj);
+
+ if (libconfig->setting_lookup_int(t, "Achieve", &val)) {
+ if (achievement->get(val) == NULL) {
+ ShowError("achievement_readdb_validate_criteria_achievement: Invalid Achievement %d provided as objective (Achievement %d, Objective %d). Skipping...\n", val, entry_id, obj_idx);
+ return false;
+ } else if (obj->unique_type != CRITERIA_UNIQUE_NONE) {
+ ShowError("achievement_readdb_validate_criteria_achievement: Unique criteria has already been set to type %d. (Achievement: %d, Objective: %d). Skipping...\n", (int) obj->unique_type, entry_id, obj_idx);
+ return false;
+ }
+
+ obj->unique.achieve_id = val;
+ obj->unique_type = CRITERIA_UNIQUE_ACHIEVE_ID;
+ } else if (type == ACH_ACHIEVE) {
+ ShowError("achievement_readdb_validate_criteria_achievement: Achievement type of ID %d requires an Achieve field in the objective criteria, setting not provided. Skipping...\n", entry_id);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Read a single objective entry of an achievement.
+ * @param[in] conf config pointer.
+ * @param[in] index Index of the objective being in the objective list being parsed.
+ * @param[out] entry pointer to the achievement db entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_objective_sub(const struct config_setting_t *conf, int index, struct achievement_data *entry)
+{
+ struct config_setting_t *tt = NULL;
+ char objnum[12];
+
+ nullpo_retr(false, conf);
+ nullpo_retr(false, entry);
+
+ sprintf(objnum, "*%d", index); // Search Objective 1..MAX
+ if ((tt = libconfig->setting_get_member(conf, objnum)) && config_setting_is_group(tt)) {
+ struct achievement_objective obj = { 0 };
+ struct config_setting_t *c = NULL;
+
+ /* Description */
+ if (libconfig->setting_lookup_mutable_string(tt, "Description", obj.description, OBJECTIVE_DESCRIPTION_LENGTH) == 0) {
+ ShowError("achievement_readdb_objective_sub: Objective %d has no description for Achievement %d, skipping...\n", index, entry->id);
+ return false;
+ }
+
+ /* Criteria */
+ if ((c = libconfig->setting_get_member(tt, "Criteria")) && config_setting_is_group(tt)) {
+ /* MobId */
+ if (achievement->readdb_validate_criteria_mobid(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /* ItemId */
+ if (achievement->readdb_validate_criteria_itemid(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /* StatusType */
+ if (achievement->readdb_validate_criteria_statustype(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /* ItemType */
+ if (achievement->readdb_validate_criteria_itemtype(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /* WeaponLevel */
+ if (achievement->readdb_validate_criteria_weaponlv(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /* Achievement */
+ if (achievement->readdb_validate_criteria_achievement(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+
+ /**
+ * Vectors are read last to avoid memory leaks if either of the above break, in cases where they are stacked with other criteria.
+ * Note to future editors - be sure to cleanup previous vectors before breaks.
+ */
+ /* JobId */
+ if (achievement->readdb_validate_criteria_jobid(c, &obj, entry->type, entry->id, index) == false)
+ return false;
+ } else if (achievement->type_requires_criteria(entry->type)) {
+ ShowError("achievement_readdb_objective_sub: No criteria field added (Achievement: %d, Objective: %d)! Skipping...\n", entry->id, index);
+ return false;
+ }
+
+ /* Goal */
+ if (libconfig->setting_lookup_int(tt, "Goal", &obj.goal) <= 0)
+ obj.goal = 1; // 1 count by default.
+
+ /* Ensure size and allocation */
+ VECTOR_ENSURE(entry->objective, 1, 1);
+
+ /* Push buffer */
+ VECTOR_PUSH(entry->objective, obj);
+ } else { // Break if not in order, to comply with the client's objective order.
+ ShowWarning("achievement_readdb_objective_sub: Objectives for Achievement %d are not in order (starting from *%d). Remaining objectives will be skipped.\n", entry->id, index);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Parses achievement objective entries of the current achievement db entry being parsed.
+ * @param[in] conf config pointer.
+ * @param[out] entry pointer to the achievement db entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_objectives(const struct config_setting_t *conf, struct achievement_data *entry)
+{
+ struct config_setting_t *t = NULL;
+
+ nullpo_retr(false, conf);
+ nullpo_retr(false, entry);
+
+ if ((t = libconfig->setting_get_member(conf, "Objectives")) && config_setting_is_group(t)) {
+ int i = 0;
+ // Initialize the buffer objective vector.
+ VECTOR_INIT(entry->objective);
+
+ for (i = 0; i < libconfig->setting_length(t) && i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
+ if (achievement_readdb_objective_sub(t, i + 1, entry) == false)
+ break;
+
+ // Assess total objectives.
+ if (libconfig->setting_length(t) > MAX_ACHIEVEMENT_OBJECTIVES)
+ ShowWarning("achievement_readdb_objectives: Exceeded maximum number of objectives (%d) for Achievement %d. Remaining objectives will be skipped.\n", MAX_ACHIEVEMENT_OBJECTIVES, entry->id);
+ if (i == 0) {
+ ShowError("achievement_readdb_objectives: No Objectives provided for Achievement %d, skipping...\n", entry->id);
+ return false;
+ }
+ } else {
+ ShowError("achievement_readdb_objectives: No Objectives provided for Achievement %d, skipping...\n", entry->id);
+ return false;
+ } // end of "Objectives"
+
+ return true;
+}
+
+/**
+ * Validates a single reward item in the reward item list of an achievement.
+ * @param[in] t pointer to the config setting.
+ * @param[in] index Index of the item in the reward list.
+ * @param[out] entry pointer to the achievement entry being parsed.
+ * @return false on failure, true on success.
+ */
+static bool achievement_readdb_validate_reward_item_sub(const struct config_setting_t *t, int index, struct achievement_data *entry)
+{
+ struct config_setting_t *it = NULL;
+ struct achievement_reward_item item = { 0 };
+ const char *name = NULL;
+ int amount = 0;
+ int val = 0;
+
+ nullpo_retr(false, t);
+ nullpo_retr(false, entry);
+
+ if ((it = libconfig->setting_get_elem(t, index)) == NULL)
+ return false;
+
+ name = config_setting_name(it);
+ amount = libconfig->setting_get_int(it);
+
+ if (name[0] == 'I' && name[1] == 'D' && itemdb->exists(atoi(name+2))) {
+ val = atoi(name);
+ } else if (!script->get_constant(name, &val)) {
+ ShowWarning("achievement_readdb_validate_reward_item_sub: Non existant Item %s provided as a reward in Achievement %d, skipping...\n", name, entry->id);
+ return false;
+ }
+
+ if (amount <= 0) {
+ ShowWarning("achievement_readdb_validate_reward_item_sub: No amount provided for Item %s as a reward in Achievement %d, skipping...\n", name, entry->id);
+ return false;
+ }
+
+ /* Ensure size and allocation */
+ VECTOR_ENSURE(entry->rewards.item, 1, 1);
+
+ item.id = val;
+ item.amount = amount;
+
+ /* push buffer */
+ VECTOR_PUSH(entry->rewards.item, item);
+
+ return true;
+}
+
+/**
+ * Validates the reward items when parsing an achievement db entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] entry pointer to the achievement entry being parsed.
+ */
+static void achievement_readdb_validate_reward_items(const struct config_setting_t *t, struct achievement_data *entry)
+{
+ struct config_setting_t *tt = NULL;
+ int i = 0;
+
+ nullpo_retv(t);
+ nullpo_retv(entry);
+
+ if ((tt = libconfig->setting_get_member(t, "Items")) && config_setting_is_group(t)) {
+ for (i = 0; i < libconfig->setting_length(tt) && i < MAX_ACHIEVEMENT_ITEM_REWARDS; i++)
+ if (achievement->readdb_validate_reward_item_sub(tt, i, entry) == false)
+ continue;
+
+ if (libconfig->setting_length(tt) > MAX_ACHIEVEMENT_ITEM_REWARDS)
+ ShowError("achievement_readdb_validate_reward_items: Maximum amount of item rewards (%d) exceeded for Achievement %d. Remaining items will be skipped.\n", MAX_ACHIEVEMENT_ITEM_REWARDS, entry->id);
+ }
+}
+
+/**
+ * Validates the reward Bonus script when parsing an achievement db entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] entry pointer to the achievement entry being parsed.
+ * @param[in] source pointer to the source file name.
+ */
+static void achievement_readdb_validate_reward_bonus(const struct config_setting_t *t, struct achievement_data *entry, const char *source)
+{
+ const char *string = NULL;
+
+ nullpo_retv(source);
+ nullpo_retv(t);
+ nullpo_retv(entry);
+
+ if (libconfig->setting_lookup_string(t, "Bonus", &string))
+ entry->rewards.bonus = string ? script->parse(string, source, 0, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+}
+
+/**
+ * Validates the reward Title Id when parsing an achievement entry.
+ * @param[in] t pointer to the config setting.
+ * @param[out] entry pointer to the entry.
+ */
+static void achievement_readdb_validate_reward_titleid(const struct config_setting_t *t, struct achievement_data *entry)
+{
+ nullpo_retv(t);
+ nullpo_retv(entry);
+
+ libconfig->setting_lookup_int(t, "TitleId", &entry->rewards.title_id);
+}
+
+/**
+ * Validates the reward Bonus script when parsing an achievement db entry.
+ * @param[in] conf pointer to the config setting.
+ * @param[out] entry pointer to the achievement entry being parsed.
+ * @param[in] source pointer to the source file name.
+ */
+static bool achievement_readdb_rewards(const struct config_setting_t *conf, struct achievement_data *entry, const char *source)
+{
+ struct config_setting_t *t = NULL;
+
+ nullpo_retr(false, conf);
+ nullpo_retr(false, entry);
+ nullpo_retr(false, source);
+
+ VECTOR_INIT(entry->rewards.item);
+
+ if ((t = libconfig->setting_get_member(conf, "Rewards")) && config_setting_is_group(t)) {
+ /* Items */
+ achievement->readdb_validate_reward_items(t, entry);
+
+ /* Buff/Bonus Script Code */
+ achievement->readdb_validate_reward_bonus(t, entry, source);
+
+ /* Title Id */
+ // @TODO Check Title ID against title DB!
+ achievement->readdb_validate_reward_titleid(t, entry);
+
+ }
+
+ return true;
+}
+
+/**
+ * Validates the reward Bonus script when parsing an achievement db entry.
+ * @param[in] conf pointer to the config setting.
+ * @param[out] entry pointer to the achievement entry being parsed.
+ * @param[in] source pointer to the source file name.
+ */
+static void achievement_readdb_additional_fields(const struct config_setting_t *conf, struct achievement_data *entry, const char *source)
+{
+ // plugins do their own thing.
+}
+
+/**
+ * Parses the Achievement DB.
+ * @read achievement_db.conf
+ */
+static void achievement_readb(void)
+{
+ char filename[256];
+ libconfig->format_db_path(DBPATH"achievement_db.conf", filename, sizeof(filename));
+ struct config_t ach_conf = { 0 };
+ struct config_setting_t *achdb = NULL, *conf = NULL;
+ int entry = 0, count = 0;
+ VECTOR_DECL(int) duplicate;
+
+ if (!libconfig->load_file(&ach_conf, filename))
+ return; // report error.
+
+ if (!(achdb = libconfig->setting_get_member(ach_conf.root, "achievement_db"))) {
+ ShowError("achievement_readdb: Could not process contents of file '%s', skipping...\n", filename);
+ libconfig->destroy(&ach_conf);
+ return;
+ }
+
+ VECTOR_INIT(duplicate);
+
+ while ((conf = libconfig->setting_get_elem(achdb, entry++))) {
+ const char *string = NULL;
+ int val = 0, i = 0;
+ struct achievement_data t_ad = { 0 }, *p_ad = NULL;
+
+ /* Achievement ID */
+ if (libconfig->setting_lookup_int(conf, "Id", &t_ad.id) == 0) {
+ ShowError("achievement_readdb: Id field for entry %d is not provided! Skipping...\n", entry);
+ continue;
+ } else if (t_ad.id <= 0) {
+ ShowError("achievement_readdb: Invalid Id %d for entry %d. Skipping...\n", t_ad.id, entry);
+ continue;
+ }
+
+ ARR_FIND(0, VECTOR_LENGTH(duplicate), i, VECTOR_INDEX(duplicate, i) == t_ad.id);
+ if (i != VECTOR_LENGTH(duplicate)) {
+ ShowError("achievement_readdb: Duplicate Id %d for entry %d. Skipping...\n", t_ad.id, entry);
+ continue;
+ }
+
+ /* Achievement Name */
+ if (libconfig->setting_lookup_mutable_string(conf, "Name", t_ad.name, ACHIEVEMENT_NAME_LENGTH) == 0) {
+ ShowError("achievement_readdb: Name field not provided for Achievement %d!\n", t_ad.id);
+ continue;
+ }
+
+ /* Achievement Type*/
+ if (libconfig->setting_lookup_string(conf, "Type", &string) == 0) {
+ ShowError("achievement_readdb: Type field not provided for Achievement %d! Skipping...\n", t_ad.id);
+ continue;
+ } else if (!script->get_constant(string, &val)) {
+ ShowError("achievement_readdb: Invalid constant %s provided as type for Achievement %d! Skipping...\n", string, t_ad.id);
+ continue;
+ }
+
+ t_ad.type = (enum achievement_types) val;
+
+ /* Objectives */
+ achievement->readdb_objectives(conf, &t_ad);
+
+ /* Rewards */
+ achievement->readdb_rewards(conf, &t_ad, filename);
+
+ /* Achievement Points */
+ libconfig->setting_lookup_int(conf, "Points", &t_ad.points);
+
+ /* Additional Fields */
+ achievement->readdb_additional_fields(conf, &t_ad, filename);
+
+ /* Allocate memory for data. */
+ CREATE(p_ad, struct achievement_data, 1);
+ *p_ad = t_ad;
+
+ /* Place in the database. */
+ idb_put(achievement->db, p_ad->id, p_ad);
+
+ /* Put achievement key in categories. */
+ VECTOR_ENSURE(achievement->category[p_ad->type], 1, 1);
+ VECTOR_PUSH(achievement->category[p_ad->type], p_ad->id);
+
+ /* Qualify for duplicate Id checks */
+ VECTOR_ENSURE(duplicate, 1, 1);
+ VECTOR_PUSH(duplicate, t_ad.id);
+
+ count++;
+ } // end of achievement_db parsing.
+
+ /* Destroy the buffer */
+ libconfig->destroy(&ach_conf);
+
+ VECTOR_CLEAR(duplicate);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
+}
+
+/**
+ * On server initiation.
+ * @param[in] minimal ignores alocating/reading databases.
+ */
+static void do_init_achievement(bool minimal)
+{
+ int i = 0;
+
+ if (minimal)
+ return;
+
+ /* DB Initialization */
+ achievement->db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+ for (i = 0; i < ACH_TYPE_MAX; i++)
+ VECTOR_INIT(achievement->category[i]);
+
+ VECTOR_INIT(achievement->rank_exp);
+
+ /* Read LibConfig Files */
+ achievement->readdb();
+ achievement->readdb_ranks();
+}
+
+/**
+ * Cleaning function called through achievement->db->destroy()
+ */
+static int achievement_db_finalize(union DBKey key, struct DBData *data, va_list args)
+{
+ int i = 0;
+ struct achievement_data *ad = DB->data2ptr(data);
+
+ for(i = 0; i < VECTOR_LENGTH(ad->objective); i++)
+ VECTOR_CLEAR(VECTOR_INDEX(ad->objective, i).jobid);
+
+ VECTOR_CLEAR(ad->objective);
+ VECTOR_CLEAR(ad->rewards.item);
+
+ // Free the script
+ if (ad->rewards.bonus != NULL) {
+ script->free_code(ad->rewards.bonus);
+ ad->rewards.bonus = NULL;
+ }
+
+ return 0;
+}
+
+/**
+ * On server finalizing.
+ */
+static void do_final_achievement(void)
+{
+ int i = 0;
+
+ achievement->db->destroy(achievement->db, achievement->db_finalize);
+
+ for (i = 0; i < ACH_TYPE_MAX; i++)
+ VECTOR_CLEAR(achievement->category[i]);
+
+ VECTOR_CLEAR(achievement->rank_exp);
+}
+
+/**
+ * Achievement Interface
+ */
+void achievement_defaults(void)
+{
+ achievement = &achievement_s;
+ /* */
+ achievement->init = do_init_achievement;
+ achievement->final = do_final_achievement;
+ /* */
+ achievement->db_finalize = achievement_db_finalize;
+ /* */
+ achievement->readdb = achievement_readb;
+ /* */
+ achievement->readdb_objectives_sub = achievement_readdb_objective_sub;
+ achievement->readdb_objectives = achievement_readdb_objectives;
+ /* */
+ achievement->readdb_validate_criteria_mobid = achievement_readdb_validate_criteria_mobid;
+ achievement->readdb_validate_criteria_jobid = achievement_readdb_validate_criteria_jobid;
+ achievement->readdb_validate_criteria_itemid = achievement_readdb_validate_criteria_itemid;
+ achievement->readdb_validate_criteria_statustype = achievement_readdb_validate_criteria_statustype;
+ achievement->readdb_validate_criteria_itemtype = achievement_readdb_validate_criteria_itemtype;
+ achievement->readdb_validate_criteria_weaponlv = achievement_readdb_validate_criteria_weaponlv;
+ achievement->readdb_validate_criteria_achievement = achievement_readdb_validate_criteria_achievement;
+ /* */
+ achievement->readdb_rewards = achievement_readdb_rewards;
+ achievement->readdb_validate_reward_items = achievement_readdb_validate_reward_items;
+ achievement->readdb_validate_reward_item_sub = achievement_readdb_validate_reward_item_sub;
+ achievement->readdb_validate_reward_bonus = achievement_readdb_validate_reward_bonus;
+ achievement->readdb_validate_reward_titleid = achievement_readdb_validate_reward_titleid;
+ /* */
+ achievement->readdb_additional_fields = achievement_readdb_additional_fields;
+ /* */
+ achievement->readdb_ranks = achievement_readdb_ranks;
+ /* */
+ achievement->get = achievement_get;
+ achievement->ensure = achievement_ensure;
+ /* */
+ achievement->calculate_totals = achievement_calculate_totals;
+ achievement->check_complete = achievement_check_complete;
+ achievement->progress_add = achievement_progress_add;
+ achievement->progress_set = achievement_progress_set;
+ achievement->check_criteria = achievement_check_criteria;
+ /* */
+ achievement->validate = achievement_validate;
+ achievement->validate_type = achievement_validate_type;
+ /* */
+ achievement->validate_mob_kill = achievement_validate_mob_kill;
+ achievement->validate_mob_damage = achievement_validate_mob_damage;
+ achievement->validate_pc_kill = achievement_validate_pc_kill;
+ achievement->validate_pc_damage = achievement_validate_pc_damage;
+ achievement->validate_jobchange = achievement_validate_jobchange;
+ achievement->validate_stats = achievement_validate_stats;
+ achievement->validate_chatroom_create = achievement_validate_chatroom_create;
+ achievement->validate_chatroom_members = achievement_validate_chatroom_members;
+ achievement->validate_friend_add = achievement_validate_friend_add;
+ achievement->validate_party_create = achievement_validate_party_create;
+ achievement->validate_marry = achievement_validate_marry;
+ achievement->validate_adopt = achievement_validate_adopt;
+ achievement->validate_zeny = achievement_validate_zeny;
+ achievement->validate_refine = achievement_validate_refine;
+ achievement->validate_item_get = achievement_validate_item_get;
+ achievement->validate_item_sell = achievement_validate_item_sell;
+ achievement->validate_achieve = achievement_validate_achieve;
+ achievement->validate_taming = achievement_validate_taming;
+ achievement->validate_achievement_rank = achievement_validate_achievement_rank;
+ /* */
+ achievement->type_requires_criteria = achievement_type_requires_criteria;
+ /* */
+ achievement->init_titles = achievement_init_titles;
+ achievement->check_title = achievement_check_title;
+ achievement->get_rewards = achievement_get_rewards;
+ achievement->get_rewards_buffs = achievement_get_rewards_buffs;
+ achievement->get_rewards_items = achievement_get_rewards_items;
+}
diff --git a/src/map/achievement.h b/src/map/achievement.h
new file mode 100644
index 000000000..dd80f7a23
--- /dev/null
+++ b/src/map/achievement.h
@@ -0,0 +1,291 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2018-2020 Hercules Dev Team
+* Copyright (C) Smokexyz
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef MAP_ACHIEVEMENT_H
+#define MAP_ACHIEVEMENT_H
+
+#include "common/hercules.h"
+#include "common/db.h"
+#include "map/map.h" // enum status_point_types
+
+#define ACHIEVEMENT_NAME_LENGTH 50
+#define OBJECTIVE_DESCRIPTION_LENGTH 100
+
+struct achievement;
+struct map_session_data;
+struct char_achievements;
+
+/**
+ * Achievement Types
+ */
+enum achievement_types {
+ // Quest
+ ACH_QUEST, // achievement and objective specific
+ // PC Kills
+ ACH_KILL_PC_TOTAL,
+ ACH_KILL_PC_JOB,
+ ACH_KILL_PC_JOBTYPE,
+ // Mob Kills
+ ACH_KILL_MOB_CLASS,
+ // PC Damage
+ ACH_DAMAGE_PC_MAX,
+ ACH_DAMAGE_PC_TOTAL,
+ ACH_DAMAGE_PC_REC_MAX,
+ ACH_DAMAGE_PC_REC_TOTAL,
+ // Mob Damage
+ ACH_DAMAGE_MOB_MAX,
+ ACH_DAMAGE_MOB_TOTAL,
+ ACH_DAMAGE_MOB_REC_MAX,
+ ACH_DAMAGE_MOB_REC_TOTAL,
+ // Job
+ ACH_JOB_CHANGE,
+ // Status
+ ACH_STATUS,
+ ACH_STATUS_BY_JOB,
+ ACH_STATUS_BY_JOBTYPE,
+ // Chatroom
+ ACH_CHATROOM_CREATE_DEAD,
+ ACH_CHATROOM_CREATE,
+ ACH_CHATROOM_MEMBERS,
+ // Friend
+ ACH_FRIEND_ADD,
+ // Party
+ ACH_PARTY_CREATE,
+ ACH_PARTY_JOIN,
+ // Marriage
+ ACH_MARRY,
+ // Adoption
+ ACH_ADOPT_BABY,
+ ACH_ADOPT_PARENT,
+ // Zeny
+ ACH_ZENY_HOLD,
+ ACH_ZENY_GET_ONCE,
+ ACH_ZENY_GET_TOTAL,
+ ACH_ZENY_SPEND_ONCE,
+ ACH_ZENY_SPEND_TOTAL,
+ // Equipment
+ ACH_EQUIP_REFINE_SUCCESS,
+ ACH_EQUIP_REFINE_FAILURE,
+ ACH_EQUIP_REFINE_SUCCESS_TOTAL,
+ ACH_EQUIP_REFINE_FAILURE_TOTAL,
+ ACH_EQUIP_REFINE_SUCCESS_WLV,
+ ACH_EQUIP_REFINE_FAILURE_WLV,
+ ACH_EQUIP_REFINE_SUCCESS_ID,
+ ACH_EQUIP_REFINE_FAILURE_ID,
+ // Items
+ ACH_ITEM_GET_COUNT,
+ ACH_ITEM_GET_COUNT_ITEMTYPE,
+ ACH_ITEM_GET_WORTH,
+ ACH_ITEM_SELL_WORTH,
+ // Monsters
+ ACH_PET_CREATE,
+ // Achievement
+ ACH_ACHIEVE,
+ ACH_ACHIEVEMENT_RANK,
+ ACH_TYPE_MAX
+};
+
+enum unique_criteria_types {
+ CRITERIA_UNIQUE_NONE,
+ CRITERIA_UNIQUE_ACHIEVE_ID,
+ CRITERIA_UNIQUE_ITEM_ID,
+ CRITERIA_UNIQUE_STATUS_TYPE,
+ CRITERIA_UNIQUE_WEAPON_LV
+};
+
+/**
+ * Achievement Objective Structure
+ *
+ * @see achievement_type_requires_criteria()
+ * @see achievement_criteria_mobid()
+ * @see achievement_criteria_jobid()
+ * @see achievement_criteria_itemid()
+ * @see achievement_criteria_stattype()
+ * @see achievement_criteria_itemtype()
+ * @see achievement_criteria_weaponlv()
+ */
+struct achievement_objective {
+ int goal;
+ char description[OBJECTIVE_DESCRIPTION_LENGTH];
+ /**
+ * Those criteria that do not make sense if stacked together.
+ * union identifier is set in unique_type. (@see unique_criteria_type)
+ */
+ union {
+ int achieve_id;
+ int itemid;
+ enum status_point_types status_type;
+ int weapon_lv;
+ } unique;
+ enum unique_criteria_types unique_type;
+ /* */
+ uint32 item_type;
+ int mobid;
+ VECTOR_DECL(int) jobid;
+};
+
+struct achievement_reward_item {
+ int id, amount;
+};
+
+struct achievement_rewards {
+ int title_id;
+ struct script_code *bonus;
+ VECTOR_DECL(struct achievement_reward_item) item;
+};
+
+/**
+ * Achievement Data Structure
+ */
+struct achievement_data {
+ int id;
+ char name[ACHIEVEMENT_NAME_LENGTH];
+ enum achievement_types type;
+ int points;
+ VECTOR_DECL(struct achievement_objective) objective;
+ struct achievement_rewards rewards;
+};
+
+// Achievements types that use Mob ID as criteria.
+#define achievement_criteria_mobid(t) ( \
+ (t) == ACH_KILL_MOB_CLASS \
+ || (t) == ACH_PET_CREATE )
+
+// Achievements types that use JobID vector as criteria.
+#define achievement_criteria_jobid(t) ( \
+ (t) == ACH_KILL_PC_JOB \
+ || (t) == ACH_KILL_PC_JOBTYPE \
+ || (t) == ACH_JOB_CHANGE \
+ || (t) == ACH_STATUS_BY_JOB \
+ || (t) == ACH_STATUS_BY_JOBTYPE )
+
+// Achievements types that use Item ID as criteria.
+#define achievement_criteria_itemid(t) ( \
+ (t) == ACH_ITEM_GET_COUNT \
+ || (t) == ACH_EQUIP_REFINE_SUCCESS_ID \
+ || (t) == ACH_EQUIP_REFINE_FAILURE_ID )
+
+// Achievements types that use status type parameter as criteria.
+#define achievement_criteria_stattype(t) ( \
+ (t) == ACH_STATUS \
+ || (t) == ACH_STATUS_BY_JOB \
+ || (t) == ACH_STATUS_BY_JOBTYPE )
+
+// Achievements types that use item type mask as criteria.
+#define achievement_criteria_itemtype(t) ( \
+ (t) == ACH_ITEM_GET_COUNT_ITEMTYPE )
+
+// Achievements types that use weapon level as criteria.
+#define achievement_criteria_weaponlv(t) ( \
+ (t) == ACH_EQUIP_REFINE_SUCCESS_WLV \
+ || (t) == ACH_EQUIP_REFINE_FAILURE_WLV )
+
+// Valid status types for objective criteria.
+#define achievement_valid_status_types(s) ( \
+ (s) == SP_STR \
+ || (s) == SP_AGI \
+ || (s) == SP_VIT \
+ || (s) == SP_INT \
+ || (s) == SP_DEX \
+ || (s) == SP_LUK \
+ || (s) == SP_BASELEVEL || (s) == SP_JOBLEVEL )
+
+struct achievement_interface {
+ struct DBMap *db; // int id -> struct achievement_data *
+ /* */
+ VECTOR_DECL(int) rank_exp; // Achievement Rank Exp Requirements
+ VECTOR_DECL(int) category[ACH_TYPE_MAX]; /* A collection of Ids per type for faster processing. */
+ /* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ /* */
+ int (*db_finalize) (union DBKey key, struct DBData *data, va_list args);
+ /* */
+ void (*readdb)(void);
+ /* */
+ bool (*readdb_objectives_sub) (const struct config_setting_t *conf, int index, struct achievement_data *entry);
+ bool (*readdb_objectives) (const struct config_setting_t *conf, struct achievement_data *entry);
+ /* */
+ bool (*readdb_validate_criteria_mobid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_jobid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_itemid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_statustype) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_itemtype) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_weaponlv) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ bool (*readdb_validate_criteria_achievement) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
+ /* */
+ bool (*readdb_rewards) (const struct config_setting_t *conf, struct achievement_data *entry, const char *source);
+ void (*readdb_validate_reward_items) (const struct config_setting_t *t, struct achievement_data *entry);
+ bool (*readdb_validate_reward_item_sub) (const struct config_setting_t *t, int element, struct achievement_data *entry);
+ void (*readdb_validate_reward_bonus) (const struct config_setting_t *t, struct achievement_data *entry, const char *source);
+ void (*readdb_validate_reward_titleid) (const struct config_setting_t *t, struct achievement_data *entry);
+ /* */
+ void (*readdb_additional_fields) (const struct config_setting_t *conf, struct achievement_data *entry, const char *source);
+ /* */
+ void (*readdb_ranks) (void);
+ /* */
+ const struct achievement_data *(*get) (int aid);
+ struct achievement *(*ensure) (struct map_session_data *sd, const struct achievement_data *ad);
+ /* */
+ void (*calculate_totals) (const struct map_session_data *sd, int *points, int *completed, int *rank, int *curr_rank_points);
+ bool (*check_complete) (struct map_session_data *sd, const struct achievement_data *ad);
+ void (*progress_add) (struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress);
+ void (*progress_set) (struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress);
+ bool (*check_criteria) (const struct achievement_objective *objective, const struct achievement_objective *criteria);
+ /* */
+ bool (*validate) (struct map_session_data *sd, int aid, unsigned int obj_idx, int progress, bool additive);
+ int (*validate_type) (struct map_session_data *sd, enum achievement_types type, const struct achievement_objective *criteria, bool additive);
+ /* */
+ void (*validate_mob_kill) (struct map_session_data *sd, int mob_id);
+ void (*validate_mob_damage) (struct map_session_data *sd, unsigned int damage, bool received);
+ void (*validate_pc_kill) (struct map_session_data *sd, struct map_session_data *dstsd);
+ void (*validate_pc_damage) (struct map_session_data *sd, struct map_session_data *dstsd, unsigned int damage);
+ void (*validate_jobchange) (struct map_session_data *sd);
+ void (*validate_stats) (struct map_session_data *sd, enum status_point_types stat_type, int progress);
+ void (*validate_chatroom_create) (struct map_session_data *sd);
+ void (*validate_chatroom_members) (struct map_session_data *sd, int progress);
+ void (*validate_friend_add) (struct map_session_data *sd);
+ void (*validate_party_create) (struct map_session_data *sd);
+ void (*validate_marry) (struct map_session_data *sd);
+ void (*validate_adopt) (struct map_session_data *sd, bool parent);
+ void (*validate_zeny) (struct map_session_data *sd, int amount);
+ void (*validate_refine) (struct map_session_data *sd, unsigned int idx, bool success);
+ void (*validate_item_get) (struct map_session_data *sd, int nameid, int amount);
+ void (*validate_item_sell) (struct map_session_data *sd, int nameid, int amount);
+ void (*validate_achieve) (struct map_session_data *sd, int achid);
+ void (*validate_taming) (struct map_session_data *sd, int class);
+ void (*validate_achievement_rank) (struct map_session_data *sd, int rank);
+ /* */
+ bool (*type_requires_criteria) (enum achievement_types type);
+ /* */
+ void (*init_titles) (struct map_session_data *sd);
+ bool (*check_title) (struct map_session_data *sd, int title_id);
+ bool (*get_rewards) (struct map_session_data *sd, const struct achievement_data *ad);
+ void (*get_rewards_buffs) (struct map_session_data *sd, const struct achievement_data *ad);
+ void (*get_rewards_items) (struct map_session_data *sd, const struct achievement_data *ad);
+};
+
+#ifdef HERCULES_CORE
+void achievement_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct achievement_interface *achievement;
+
+#endif // MAP_ACHIEVEMENT_H
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 3da5c203f..3fe6c8581 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/duel.h"
#include "map/elemental.h"
@@ -47,6 +48,7 @@
#include "map/pc_groups.h" // groupid2name
#include "map/pet.h"
#include "map/quest.h"
+#include "map/refine.h"
#include "map/script.h"
#include "map/searchstore.h"
#include "map/skill.h"
@@ -54,12 +56,14 @@
#include "map/storage.h"
#include "map/trade.h"
#include "map/unit.h"
+#include "map/achievement.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/core.h"
#include "common/memmgr.h"
#include "common/mmo.h" // MAX_CARTS
#include "common/nullpo.h"
+#include "common/packets.h"
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
@@ -73,14 +77,15 @@
#include <stdlib.h>
#include <string.h>
-struct atcommand_interface atcommand_s;
+static struct atcommand_interface atcommand_s;
struct atcommand_interface *atcommand;
static char atcmd_output[CHAT_SIZE_MAX];
static char atcmd_player_name[NAME_LENGTH];
// @commands (script-based)
-struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
+static struct atcmd_binding_data *get_atcommandbind_byname(const char *name)
+{
int i = 0;
nullpo_retr(NULL, name);
@@ -92,14 +97,16 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
return ( i < atcommand->binding_count ) ? atcommand->binding[i] : NULL;
}
-const char* atcommand_msgsd(struct map_session_data *sd, int msg_number) {
+static const char *atcommand_msgsd(struct map_session_data *sd, int msg_number)
+{
Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG && atcommand->msg_table[0][msg_number] != NULL);
if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number])
return atcommand->msg_table[0][msg_number];
return atcommand->msg_table[sd->lang_id][msg_number];
}
-const char* atcommand_msgfd(int fd, int msg_number) {
+static const char *atcommand_msgfd(int fd, int msg_number)
+{
struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL;
Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG && atcommand->msg_table[0][msg_number] != NULL);
if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number])
@@ -110,7 +117,8 @@ const char* atcommand_msgfd(int fd, int msg_number) {
//-----------------------------------------------------------
// Return the message string of the specified number by [Yor]
//-----------------------------------------------------------
-const char* atcommand_msg(int msg_number) {
+static const char *atcommand_msg(int msg_number)
+{
Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG);
if (atcommand->msg_table[map->default_lang_id][msg_number] != NULL && atcommand->msg_table[map->default_lang_id][msg_number][0] != '\0')
return atcommand->msg_table[map->default_lang_id][msg_number];
@@ -128,11 +136,11 @@ const char* atcommand_msg(int msg_number) {
* @param[in] allow_override whether to allow duplicate message IDs to override the original value.
* @return success state.
*/
-bool msg_config_read(const char *cfg_name, bool allow_override) {
+static bool msg_config_read(const char *cfg_name, bool allow_override)
+{
int msg_number;
char line[1024], w1[1024], w2[1024];
FILE *fp;
- static int called = 1;
nullpo_retr(false, cfg_name);
if ((fp = fopen(cfg_name, "r")) == NULL) {
@@ -170,28 +178,14 @@ bool msg_config_read(const char *cfg_name, bool allow_override) {
}
fclose(fp);
- if( ++called == 1 ) { //Original
- if( script->lang_export_fp ) {
- int i;
- for(i = 0; i < MAX_MSG;i++) {
- if( atcommand->msg_table[0][i] != NULL ) {
- fprintf(script->lang_export_fp, "msgctxt \"messages.conf\"\n"
- "msgid \"%s\"\n"
- "msgstr \"\"\n",
- atcommand->msg_table[0][i]
- );
- }
- }
- }
- }
-
return true;
}
/*==========================================
* Cleanup Message Data
*------------------------------------------*/
-void do_final_msg(void) {
+static void do_final_msg(void)
+{
int i, j;
for(i = 0; i < atcommand->max_message_table; i++) {
@@ -209,7 +203,8 @@ void do_final_msg(void) {
/**
* retrieves the help string associated with a given command.
*/
-static inline const char* atcommand_help_string(AtCommandInfo *info) {
+static inline const char *atcommand_help_string(AtCommandInfo *info)
+{
return info->help;
}
@@ -266,22 +261,25 @@ ACMD(send)
clif->message(fd, atcmd_output);
return false;
}
-
+
if (len) {
// show packet length
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, clif->packet(type)->len); // Packet 0x%x length: %d
+ Assert_retr(false, type <= MAX_PACKET_DB && type >= MIN_PACKET_DB);
+ len = packets->db[type];
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, len); // Packet 0x%x length: %d
clif->message(fd, atcmd_output);
return true;
}
-
- len = clif->packet(type)->len;
-
+
+ Assert_retr(false, type <= MAX_PACKET_DB && type >= MIN_PACKET_DB);
+ len = packets->db[type];
+
if (len == -1) {
// dynamic packet
len = SHRT_MAX-4; // maximum length
off = 4;
}
-
+
WFIFOHEAD(sd->fd, len);
WFIFOW(sd->fd,0)=TOW(type);
@@ -422,7 +420,7 @@ ACMD(send)
SKIP_VALUE(message);
}
- if (clif->packet(type)->len == -1) { // send dynamic packet
+ if (packets->db[type] == -1) { // send dynamic packet
WFIFOW(sd->fd,2)=TOW(off);
WFIFOSET(sd->fd,off);
} else {// send static packet
@@ -446,7 +444,8 @@ ACMD(send)
/*==========================================
* @rura, @warp, @mapmove
*------------------------------------------*/
-ACMD(mapmove) {
+ACMD(mapmove)
+{
char map_name[MAP_NAME_LENGTH_EXT];
unsigned short map_index;
short x = 0, y = 0;
@@ -482,11 +481,11 @@ ACMD(mapmove) {
x = y = 0; //Invalid cell, use random spot.
}
if (map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,247));
+ clif->message(fd, msg_fd(fd,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_fd(fd,248));
+ clif->message(fd, msg_fd(fd,248)); // You are not authorized to warp from your current map.
return false;
}
if (pc->setpos(sd, map_index, x, y, CLR_TELEPORT) != 0) {
@@ -501,7 +500,8 @@ ACMD(mapmove) {
/*==========================================
* Displays where a character is. Corrected version by Silent. [Skotlex]
*------------------------------------------*/
-ACMD(where) {
+ACMD(where)
+{
struct map_session_data* pl_sd;
memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
@@ -511,7 +511,7 @@ ACMD(where) {
return false;
}
- pl_sd = map->nick2sd(atcmd_player_name);
+ pl_sd = map->nick2sd(atcmd_player_name, true);
if (pl_sd == NULL ||
strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 ||
(pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
@@ -529,7 +529,8 @@ ACMD(where) {
/*==========================================
*
*------------------------------------------*/
-ACMD(jumpto) {
+ACMD(jumpto)
+{
struct map_session_data *pl_sd = NULL;
if (!*message) {
@@ -547,7 +548,7 @@ ACMD(jumpto) {
return false;
}
- if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message, true)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -612,7 +613,8 @@ ACMD(jump)
* Display list of online characters with
* various info.
*------------------------------------------*/
-ACMD(who) {
+ACMD(who)
+{
const struct map_session_data *pl_sd = NULL;
struct s_mapiterator *iter = NULL;
char player_name[NAME_LENGTH] = "";
@@ -655,7 +657,7 @@ ACMD(who) {
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
StrBuf->Printf(&buf, msg_fd(fd,344), pcg->get_name(pl_sd->group)); // "(%s) "
StrBuf->Printf(&buf, msg_fd(fd,347), pl_sd->status.base_level, pl_sd->status.job_level,
- pc->job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s"
+ pc->job_name(pl_sd->status.class)); // "| Lv:%d/%d | Job: %s"
break;
}
case 3: {
@@ -764,7 +766,7 @@ ACMD(whogm)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,915), // BLvl: %d | Job: %s (Lvl: %d)
pl_sd->status.base_level,
- pc->job_name(pl_sd->status.class_), pl_sd->status.job_level);
+ pc->job_name(pl_sd->status.class), pl_sd->status.job_level);
clif->message(fd, atcmd_output);
p = party->search(pl_sd->status.party_id);
@@ -809,7 +811,8 @@ ACMD(save)
/*==========================================
*
*------------------------------------------*/
-ACMD(load) {
+ACMD(load)
+{
int16 m;
m = map->mapindex2mapid(sd->status.save_point.map);
@@ -866,11 +869,16 @@ ACMD(speed)
*------------------------------------------*/
ACMD(storage)
{
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
+ if (sd->npc_id || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
+ return false;
+
+ if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nostorage & 1)) { // mapflag nostorage already defined? can't open :c
+ clif->message(fd, msg_fd(fd, 1161)); // You currently cannot open your storage.
return false;
+ }
if (storage->open(sd) == 1) { //Already open.
- clif->message(fd, msg_fd(fd,250));
+ clif->message(fd, msg_fd(fd,250)); // You have already opened your storage. Close it first.
return false;
}
@@ -885,20 +893,25 @@ ACMD(storage)
ACMD(guildstorage)
{
if (!sd->status.guild_id) {
- clif->message(fd, msg_fd(fd,252));
+ clif->message(fd, msg_fd(fd,252)); // You are not in a guild.
return false;
}
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading)
+ if (sd->npc_id || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.trading)
return false;
if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) {
- clif->message(fd, msg_fd(fd,250));
+ clif->message(fd, msg_fd(fd,250)); // You have already opened your storage. Close it first.
return false;
}
if (sd->state.storage_flag == STORAGE_FLAG_GUILD) {
- clif->message(fd, msg_fd(fd,251));
+ clif->message(fd, msg_fd(fd,251)); // You have already opened your guild storage. Close it first.
+ return false;
+ }
+
+ if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nogstorage & 1)) { // mapflag nogstorage already defined? can't open :c
+ clif->message(fd, msg_fd(fd, 1161)); // You currently cannot open your storage. (there is no other messages...)
return false;
}
@@ -947,39 +960,12 @@ ACMD(option)
/*==========================================
*
*------------------------------------------*/
-ACMD(hide) {
- if (pc_isinvisible(sd)) {
- sd->sc.option &= ~OPTION_INVISIBLE;
- if (sd->disguise != -1 )
- status->set_viewdata(&sd->bl, sd->disguise);
- else
- status->set_viewdata(&sd->bl, sd->status.class_);
- clif->message(fd, msg_fd(fd,10)); // Invisible: Off
-
- // increment the number of pvp players on the map
- map->list[sd->bl.m].users_pvp++;
-
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
- // register the player for ranking calculations
- sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
- }
- //bugreport:2266
- map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
- } else {
- sd->sc.option |= OPTION_INVISIBLE;
- sd->vd.class_ = INVISIBLE_CLASS;
- clif->message(fd, msg_fd(fd,11)); // Invisible: On
-
- // decrement the number of pvp players on the map
- map->list[sd->bl.m].users_pvp--;
-
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {
- // unregister the player for ranking
- timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
- sd->pvp_timer = INVALID_TIMER;
- }
- }
- clif->changeoption(&sd->bl);
+ACMD(hide)
+{
+ if (pc_isinvisible(sd))
+ pc->unhide(sd, true);
+ else
+ pc->hide(sd, true);
return true;
}
@@ -1091,9 +1077,11 @@ ACMD(kami)
sscanf(message, "%199[^\n]", atcmd_output);
if (stristr(info->command, "l") != NULL)
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
+ clif->broadcast(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
+ else if (info->command[4] == 'b' || info->command[4] == 'B')
+ clif->broadcast(NULL, atcmd_output, (int)strlen(atcmd_output) + 1, BC_BLUE, ALL_CLIENT);
else
- intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW);
+ clif->broadcast(NULL, atcmd_output, (int)strlen(atcmd_output) + 1, BC_YELLOW, ALL_CLIENT);
} else {
if(!*message || (sscanf(message, "%10u %199[^\n]", &color, atcmd_output) < 2)) {
clif->message(fd, msg_fd(fd,981)); // Please enter color and message (usage: @kamic <color> <message>).
@@ -1104,7 +1092,7 @@ ACMD(kami)
clif->message(fd, msg_fd(fd,982)); // Invalid color.
return false;
}
- intif->broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
+ clif->broadcast2(NULL, atcmd_output, (int)strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0, ALL_CLIENT);
}
return true;
}
@@ -1131,7 +1119,7 @@ ACMD(heal)
}
if ( hp > 0 && sp >= 0 ) {
- if(!status->heal(&sd->bl, hp, sp, 0))
+ if (status->heal(&sd->bl, hp, sp, STATUS_HEAL_DEFAULT) == 0)
clif->message(fd, msg_fd(fd,157)); // HP and SP are already with the good value.
else
clif->message(fd, msg_fd(fd,17)); // HP, SP recovered.
@@ -1148,7 +1136,7 @@ ACMD(heal)
//Opposing signs.
if ( hp ) {
if (hp > 0)
- status->heal(&sd->bl, hp, 0, 0);
+ status->heal(&sd->bl, hp, 0, STATUS_HEAL_DEFAULT);
else {
status->damage(NULL, &sd->bl, -hp, 0, 0, 0);
clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0);
@@ -1157,7 +1145,7 @@ ACMD(heal)
if ( sp ) {
if (sp > 0)
- status->heal(&sd->bl, 0, sp, 0);
+ status->heal(&sd->bl, 0, sp, STATUS_HEAL_DEFAULT);
else
status->damage(NULL, &sd->bl, 0, -sp, 0, 0);
}
@@ -1266,20 +1254,20 @@ ACMD(item2)
struct item_data *item_data;
char item_name[100];
int item_id, number = 0, bound = 0;
- int identify = 0, refine = 0, attr = 0;
+ int identify = 0, refine_level = 0, attr = 0;
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(info->command,"itembound2") && (!*message || (
- sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
- sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) {
+ sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine_level, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
+ sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine_level, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) {
clif->message(fd, msg_fd(fd,296)); // Please enter all parameters (usage: @itembound2 <item name/ID> <quantity>
clif->message(fd, msg_fd(fd,297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>).
return false;
} else if (!*message
- || ( sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
- && sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
+ || ( sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine_level, &attr, &c1, &c2, &c3, &c4) < 9
+ && sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine_level, &attr, &c1, &c2, &c3, &c4) < 9
)) {
clif->message(fd, msg_fd(fd,984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity>
clif->message(fd, msg_fd(fd,985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>).
@@ -1315,20 +1303,20 @@ ACMD(item2)
get_count = 1;
if (item_data->type == IT_PETEGG) {
identify = 1;
- refine = 0;
+ refine_level = 0;
}
if (item_data->type == IT_PETARMOR)
- refine = 0;
+ refine_level = 0;
} else {
identify = 1;
- refine = attr = 0;
+ refine_level = attr = 0;
}
- refine = cap_value(refine, 0, MAX_REFINE);
+ refine_level = cap_value(refine_level, 0, MAX_REFINE);
for (i = 0; i < loop; i++) {
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = identify;
- item_tmp.refine = refine;
+ item_tmp.refine = refine_level;
item_tmp.attribute = attr;
item_tmp.bound = (unsigned char)bound;
item_tmp.card[0] = c1;
@@ -1355,9 +1343,7 @@ ACMD(item2)
*------------------------------------------*/
ACMD(itemreset)
{
- int i;
-
- for (i = 0; i < MAX_INVENTORY; i++) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) {
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND);
}
@@ -1384,13 +1370,13 @@ ACMD(baselevelup)
clif->message(fd, msg_fd(fd,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 positive overflow
+ if (level > pc->maxbaselv(sd) || 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);
sd->status.status_point += status_point;
- sd->status.base_level += (unsigned int)level;
+ sd->status.base_level += level;
status_calc_pc(sd, SCO_FORCE);
status_percent_heal(&sd->bl, 100, 100);
clif->misceffect(&sd->bl, 0);
@@ -1401,7 +1387,7 @@ ACMD(baselevelup)
return false;
}
level*=-1;
- if ((unsigned int)level >= sd->status.base_level)
+ if (level >= sd->status.base_level)
level = sd->status.base_level-1;
for (i = 0; i > -level; i--)
status_point += pc->gets_status_point(sd->status.base_level + i - 1);
@@ -1411,9 +1397,10 @@ ACMD(baselevelup)
sd->status.status_point = 0;
else
sd->status.status_point -= status_point;
- sd->status.base_level -= (unsigned int)level;
+ sd->status.base_level -= level;
clif->message(fd, msg_fd(fd,22)); // Base level lowered.
status_calc_pc(sd, SCO_FORCE);
+ level *= -1;
}
sd->status.base_exp = 0;
clif->updatestatus(sd, SP_STATUSPOINT);
@@ -1421,8 +1408,16 @@ ACMD(baselevelup)
clif->updatestatus(sd, SP_BASEEXP);
clif->updatestatus(sd, SP_NEXTBASEEXP);
pc->baselevelchanged(sd);
+
+ // achievements
+ achievement->validate_stats(sd, SP_BASELEVEL, sd->status.base_level);
+
if(sd->status.party_id)
party->send_levelup(sd);
+
+ if (level > 0 && battle_config.atcommand_levelup_events)
+ npc->script_event(sd, NPCE_BASELVUP); // Trigger OnPCBaseLvUpEvent
+
return true;
}
@@ -1442,9 +1437,9 @@ ACMD(joblevelup)
clif->message(fd, msg_fd(fd,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 positive overflow
+ if (level > pc->maxjoblv(sd) || 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.job_level += level;
sd->status.skill_point += level;
clif->misceffect(&sd->bl, 1);
clif->message(fd, msg_fd(fd,24)); // Job level raised.
@@ -1454,9 +1449,9 @@ ACMD(joblevelup)
return false;
}
level *=-1;
- if ((unsigned int)level >= sd->status.job_level) // fix negative overflow
+ if (level >= sd->status.job_level) // fix negative overflow
level = sd->status.job_level-1;
- sd->status.job_level -= (unsigned int)level;
+ sd->status.job_level -= level;
if (sd->status.skill_point < level)
pc->resetskill(sd, PCRESETSKILL_NONE); //Reset skills since we need to subtract more points.
if (sd->status.skill_point < level)
@@ -1464,6 +1459,7 @@ ACMD(joblevelup)
else
sd->status.skill_point -= level;
clif->message(fd, msg_fd(fd,25)); // Job level lowered.
+ level *= -1;
}
sd->status.job_exp = 0;
clif->updatestatus(sd, SP_JOBLEVEL);
@@ -1472,13 +1468,17 @@ ACMD(joblevelup)
clif->updatestatus(sd, SP_SKILLPOINT);
status_calc_pc(sd, SCO_FORCE);
+ if (level > 0 && battle_config.atcommand_levelup_events)
+ npc->script_event(sd, NPCE_JOBLVUP); // Trigger OnPCJobLvUpEvent
+
return true;
}
/*==========================================
* @help
*------------------------------------------*/
-ACMD(help) {
+ACMD(help)
+{
const char *command_name = NULL;
char *default_command = "help";
AtCommandInfo *tinfo = NULL;
@@ -1546,7 +1546,7 @@ ACMD(help) {
* Arglist parameters:
* - (int) id: If 0, stop any attacks. Otherwise, the target block list id to stop attacking.
*/
-int atcommand_stopattack(struct block_list *bl,va_list ap)
+static int atcommand_stopattack(struct block_list *bl, va_list ap)
{
struct unit_data *ud = NULL;
int id = 0;
@@ -1565,7 +1565,7 @@ int atcommand_stopattack(struct block_list *bl,va_list ap)
/*==========================================
*
*------------------------------------------*/
-int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
+static int atcommand_pvpoff_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
nullpo_ret(bl);
@@ -1603,7 +1603,7 @@ ACMD(pvpoff)
/*==========================================
*
*------------------------------------------*/
-int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
+static int atcommand_pvpon_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
nullpo_ret(bl);
@@ -1611,7 +1611,8 @@ int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
sd = BL_UCAST(BL_PC, bl);
if (sd->pvp_timer == INVALID_TIMER) {
- sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+ if (!map->list[sd->bl.m].flag.pvp_nocalcrank)
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -1645,7 +1646,8 @@ ACMD(pvpon)
/*==========================================
*
*------------------------------------------*/
-ACMD(gvgoff) {
+ACMD(gvgoff)
+{
if (!map->list[sd->bl.m].flag.gvg) {
clif->message(fd, msg_fd(fd,162)); // GvG is already Off.
@@ -1684,6 +1686,45 @@ ACMD(gvgon)
/*==========================================
*
*------------------------------------------*/
+ACMD(cvcoff)
+{
+ if (!map->list[sd->bl.m].flag.cvc) {
+ clif->message(fd, msg_fd(fd, 141)); // CvC is already Off.
+ return false;
+ }
+
+ map->zone_change2(sd->bl.m, map->list[sd->bl.m].prev_zone);
+ map->list[sd->bl.m].flag.cvc = 0;
+ clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
+ clif->maptypeproperty2(&sd->bl, ALL_SAMEMAP);
+ map->foreachinmap(atcommand->stopattack, sd->bl.m, BL_CHAR, 0);
+ clif->message(fd, msg_fd(fd, 137)); // CvC: Off.
+
+ return true;
+}
+
+/*==========================================
+ *
+ *------------------------------------------*/
+ACMD(cvcon)
+{
+ if (map->list[sd->bl.m].flag.cvc) {
+ clif->message(fd, msg_fd(fd, 142)); // CvC is already On.
+ return false;
+ }
+
+ map->zone_change2(sd->bl.m, strdb_get(map->zone_db, MAP_ZONE_CVC_NAME));
+ map->list[sd->bl.m].flag.cvc = 1;
+ clif->map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE);
+ clif->maptypeproperty2(&sd->bl, ALL_SAMEMAP);
+ clif->message(fd, msg_fd(fd, 138)); // CvC: On.
+
+ return true;
+}
+
+/*==========================================
+ *
+ *------------------------------------------*/
ACMD(model)
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
@@ -1721,7 +1762,12 @@ ACMD(bodystyle)
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!*message || sscanf(message, "%d", &body_style) < 1) {
+ if (!pc->has_second_costume(sd)) {
+ clif->message(fd, msg_fd(fd, 35)); // This job has no alternate body styles.
+ return false;
+ }
+
+ if (*message == '\0' || sscanf(message, "%d", &body_style) < 1) {
sprintf(atcmd_output, "Please, enter a body style (usage: @bodystyle <body ID: %d-%d>).", MIN_BODY_STYLE, MAX_BODY_STYLE);
clif->message(fd, atcmd_output);
return false;
@@ -1729,9 +1775,9 @@ ACMD(bodystyle)
if (body_style >= MIN_BODY_STYLE && body_style <= MAX_BODY_STYLE) {
pc->changelook(sd, LOOK_BODY2, body_style);
- clif->message(fd, msg_txt(36)); // Appearence changed.
+ clif->message(fd, msg_fd(fd, 36)); // Appearence changed.
} else {
- clif->message(fd, msg_txt(37)); // An invalid number was specified.
+ clif->message(fd, msg_fd(fd, 37)); // An invalid number was specified.
return false;
}
@@ -1816,10 +1862,68 @@ ACMD(hair_color)
return true;
}
+ACMD(setzone)
+{
+ char zone_name[MAP_ZONE_MAPFLAG_LENGTH];
+ memset(zone_name, '\0', sizeof(zone_name));
+
+ char fmt_str[8] = "";
+ safesnprintf(fmt_str, 8, "%%%ds", MAP_ZONE_MAPFLAG_LENGTH - 1);
+
+ if (*message == '\0' || sscanf(message, fmt_str, zone_name) < 1) {
+ clif->message(fd, msg_fd(fd, 924)); // usage info
+ return false;
+ }
+
+ struct map_zone_data *zone = strdb_get(map->zone_db, zone_name);
+ const char *prev_zone_name = map->list[sd->bl.m].zone->name;
+
+ // handle special zones:
+ if (zone == NULL && strcmp(zone_name, MAP_ZONE_NORMAL_NAME) == 0) {
+ zone = &map->zone_all;
+ } else if (zone == NULL && strcmp(zone_name, MAP_ZONE_PK_NAME) == 0) {
+ zone = &map->zone_pk;
+ }
+
+ if (zone != NULL) {
+ if (map->list[sd->bl.m].zone != zone) {
+ if (strcmp(prev_zone_name, MAP_ZONE_PVP_NAME) == 0) {
+ atcommand_pvpoff(fd, sd, command, message, info);
+ } else if (strcmp(prev_zone_name, MAP_ZONE_GVG_NAME) == 0) {
+ atcommand_gvgoff(fd, sd, command, message, info);
+ } else if (strcmp(prev_zone_name, MAP_ZONE_CVC_NAME) == 0) {
+ atcommand_cvcoff(fd, sd, command, message, info);
+ }
+ } else {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 925), zone_name);
+ clif->message(fd, atcmd_output); // nothing to do
+ return false;
+ }
+
+ if (strcmp(zone_name, MAP_ZONE_PVP_NAME) == 0) {
+ atcommand_pvpon(fd, sd, command, message, info);
+ } else if (strcmp(zone_name, MAP_ZONE_GVG_NAME) == 0) {
+ atcommand_gvgon(fd, sd, command, message, info);
+ } else if (strcmp(zone_name, MAP_ZONE_CVC_NAME) == 0) {
+ atcommand_cvcon(fd, sd, command, message, info);
+ } else {
+ map->zone_change2(sd->bl.m, zone);
+ }
+ } else {
+ clif->message(fd, msg_fd(fd, 926)); // zone not found
+ return false;
+ }
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 927), prev_zone_name, zone_name);
+ clif->message(fd, atcmd_output); // changed successfully
+ return true;
+}
+
/*==========================================
* @go [city_number or city_name] - Updated by Harbin
*------------------------------------------*/
-ACMD(go) {
+ACMD(go)
+{
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];
@@ -2006,7 +2110,7 @@ ACMD(monster)
number = 1;
if (!name[0])
- strcpy(name, "--ja--");
+ strcpy(name, DEFAULT_MOB_JNAME);
// If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit)
@@ -2049,7 +2153,7 @@ ACMD(monster)
/*==========================================
*
*------------------------------------------*/
-int atkillmonster_sub(struct block_list *bl, va_list ap)
+static int atkillmonster_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
int flag = va_arg(ap, int);
@@ -2067,7 +2171,8 @@ int atkillmonster_sub(struct block_list *bl, va_list ap)
return 1;
}
-ACMD(killmonster) {
+ACMD(killmonster)
+{
int map_id, drop_flag;
char map_name[MAP_NAME_LENGTH_EXT];
@@ -2094,59 +2199,100 @@ ACMD(killmonster) {
*------------------------------------------*/
ACMD(refine)
{
- int j, position = 0, refine = 0, current_position, final_refine;
+ int j, position = 0, refine_level = 0, current_position, final_refine;
int count;
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!*message || sscanf(message, "%12d %12d", &position, &refine) < 2) {
- clif->message(fd, msg_fd(fd,996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>).
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,997), EQP_HEAD_LOW); // %d: Lower Headgear
+ if (!*message || sscanf(message, "%12d %12d", &position, &refine_level) < 2) {
+ clif->message(fd, msg_fd(fd, 996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>).
+#if PACKETVER > 20100707
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1515), -3); // %d: Refine All Equip (Shadow)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1514), -2); // %d: Refine All Equip (Costume)
+ clif->message(fd, atcmd_output);
+#endif
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1513), -1); // %d: Refine All Equip (General)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 997), EQP_HEAD_LOW); // %d: Headgear (Low)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 998), EQP_HAND_R); // Hand (Right)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 999), EQP_GARMENT); // %d: Garment
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1000), EQP_ACC_L); // Accessory (Left)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1001), EQP_ARMOR); // %d: Body Armor
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1002), EQP_HAND_L); // Hand (Left)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1003), EQP_SHOES); // %d: Shoes
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1004), EQP_ACC_R); // Accessory (Right)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1005), EQP_HEAD_TOP); // %d: Headgear (Top)
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,998), EQP_HAND_R); // %d: Right Hand
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1006), EQP_HEAD_MID); // %d: Headgear (Mid)
+#if PACKETVER > 20100707
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1503), EQP_COSTUME_HEAD_TOP); // %d: Costume Headgear (Top)
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,999), EQP_GARMENT); // %d: Garment
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1504), EQP_COSTUME_HEAD_MID); // %d: Costume Headgear (Mid)
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1000), EQP_ACC_L); // %d: Left Accessory
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1505), EQP_COSTUME_HEAD_LOW); // %d: Costume Headgear (Low)
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1001), EQP_ARMOR); // %d: Body Armor
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1506), EQP_COSTUME_GARMENT); // %d: Costume Garment
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1002), EQP_HAND_L); // %d: Left Hand
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1507), EQP_SHADOW_ARMOR); // %d: Shadow Armor
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1003), EQP_SHOES); // %d: Shoes
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1508), EQP_SHADOW_WEAPON); // %d: Shadow Weapon
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1004), EQP_ACC_R); // %d: Right Accessory
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1509), EQP_SHADOW_SHIELD); // %d: Shadow Shield
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1005), EQP_HEAD_TOP); // %d: Top Headgear
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1510), EQP_SHADOW_SHOES); // %d: Shadow Shoes
clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1006), EQP_HEAD_MID); // %d: Mid Headgear
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1511), EQP_SHADOW_ACC_R); // %d: Shadow Accessory (Right)
+ clif->message(fd, atcmd_output);
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1512), EQP_SHADOW_ACC_L); // %d: Shadow Accessory (Left)
+ clif->message(fd, atcmd_output);
+#endif
clif->message(fd, atcmd_output);
return false;
}
- refine = cap_value(refine, -MAX_REFINE, MAX_REFINE);
+ refine_level = cap_value(refine_level, -MAX_REFINE, MAX_REFINE);
count = 0;
for (j = 0; j < EQI_MAX; j++) {
int idx = sd->equip_index[j];
if (idx < 0)
continue;
- if(j == EQI_AMMO) continue; /* can't equip ammo */
- if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == idx)
+ if (j == EQI_AMMO)
+ continue; /* can't equip ammo */
+ if (j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == idx)
+ continue;
+ if (j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == idx)
+ continue;
+ if (j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == idx || sd->equip_index[EQI_HEAD_LOW] == idx))
continue;
- if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == idx)
+ if (j == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == idx)
continue;
- if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == idx || sd->equip_index[EQI_HEAD_LOW] == idx))
+ if (j == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == idx || sd->equip_index[EQI_COSTUME_LOW] == idx))
continue;
- if(position && !(sd->status.inventory[idx].equip & position))
+ if (position == -3 && !itemdb_is_shadowequip(sd->status.inventory[idx].equip))
+ continue;
+ else if (position == -2 && !itemdb_is_costumeequip(sd->status.inventory[idx].equip))
+ continue;
+ else if (position == -1 && (itemdb_is_costumeequip(sd->status.inventory[idx].equip) || itemdb_is_shadowequip(sd->status.inventory[idx].equip)))
+ continue;
+ else if (position && !(sd->status.inventory[idx].equip & position))
continue;
- final_refine = cap_value(sd->status.inventory[idx].refine + refine, 0, MAX_REFINE);
+ final_refine = cap_value(sd->status.inventory[idx].refine + refine_level, 0, MAX_REFINE);
if (sd->status.inventory[idx].refine != final_refine) {
sd->status.inventory[idx].refine = final_refine;
current_position = sd->status.inventory[idx].equip;
- pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
+ pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC | PCUNEQUIPITEM_FORCE);
clif->refine(fd, 0, idx, sd->status.inventory[idx].refine);
clif->delitem(sd, idx, 1, DELITEM_MATERIALCHANGE);
clif->additem(sd, idx, 1, 0);
@@ -2157,11 +2303,11 @@ ACMD(refine)
}
if (count == 0)
- clif->message(fd, msg_fd(fd,166)); // No item has been refined.
+ clif->message(fd, msg_fd(fd, 166)); // No item has been refined.
else if (count == 1)
- clif->message(fd, msg_fd(fd,167)); // 1 item has been refined.
+ clif->message(fd, msg_fd(fd, 167)); // 1 item has been refined.
else {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,168), count); // %d items have been refined.
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 168), count); // %d items have been refined.
clif->message(fd, atcmd_output);
}
@@ -2264,7 +2410,8 @@ ACMD(memo)
/*==========================================
*
*------------------------------------------*/
-ACMD(gat) {
+ACMD(gat)
+{
int y;
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -2301,7 +2448,7 @@ ACMD(displaystatus)
if( flag == 0 )
clif->sc_end(&sd->bl,sd->bl.id,AREA,type);
else
- clif->status_change(&sd->bl, type, flag, tick, val1, val2, val3);
+ clif->status_change(&sd->bl, type, BL_PC, flag, tick, val1, val2, val3);
return true;
}
@@ -2312,30 +2459,18 @@ ACMD(displaystatus)
ACMD(statuspoint)
{
int point;
- unsigned int new_status_point;
+ int new_status_point;
if (!*message || (point = atoi(message)) == 0) {
clif->message(fd, msg_fd(fd,1010)); // Please enter a number (usage: @stpoint <number of points>).
return false;
}
- if(point < 0)
- {
- if(sd->status.status_point < (unsigned int)(-point))
- {
- new_status_point = 0;
- }
- else
- {
- new_status_point = sd->status.status_point + point;
- }
- }
- else if(UINT_MAX - sd->status.status_point < (unsigned int)point)
- {
- new_status_point = UINT_MAX;
- }
- else
- {
+ if (point < 0 && sd->status.status_point + point < 0) {
+ new_status_point = 0;
+ } else if (point > 0 && (int64)sd->status.status_point + point > INT_MAX) {
+ new_status_point = INT_MAX;
+ } else {
new_status_point = sd->status.status_point + point;
}
@@ -2360,30 +2495,18 @@ ACMD(statuspoint)
ACMD(skillpoint)
{
int point;
- unsigned int new_skill_point;
+ int new_skill_point;
if (!*message || (point = atoi(message)) == 0) {
clif->message(fd, msg_fd(fd,1011)); // Please enter a number (usage: @skpoint <number of points>).
return false;
}
- if(point < 0)
- {
- if(sd->status.skill_point < (unsigned int)(-point))
- {
- new_skill_point = 0;
- }
- else
- {
- new_skill_point = sd->status.skill_point + point;
- }
- }
- else if(UINT_MAX - sd->status.skill_point < (unsigned int)point)
- {
- new_skill_point = UINT_MAX;
- }
- else
- {
+ if (point < 0 && sd->status.skill_point + point < 0) {
+ new_skill_point = 0;
+ } else if (point > 0 && (int64)sd->status.skill_point + point > INT_MAX) {
+ new_skill_point = INT_MAX;
+ } else {
new_skill_point = sd->status.skill_point + point;
}
@@ -2434,7 +2557,8 @@ ACMD(zeny)
/*==========================================
*
*------------------------------------------*/
-ACMD(param) {
+ACMD(param)
+{
int i, value = 0, new_value, max;
const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" };
short* stats[6];
@@ -2480,6 +2604,7 @@ ACMD(param) {
clif->updatestatus(sd, SP_USTR + i);
status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_fd(fd,42)); // Stat changed.
+ achievement->validate_stats(sd, SP_STR + i, new_value); // Achievements [Smokexyz/Hercules]
} else {
if (value < 0)
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
@@ -2494,7 +2619,8 @@ ACMD(param) {
/*==========================================
* Stat all by fritz (rewritten by [Yor])
*------------------------------------------*/
-ACMD(stat_all) {
+ACMD(stat_all)
+{
int index, count, value, max, new_value;
short* stats[6];
//we don't use direct initialization because it isn't part of the c standard.
@@ -2550,7 +2676,8 @@ ACMD(stat_all) {
/*==========================================
*
*------------------------------------------*/
-ACMD(guildlevelup) {
+ACMD(guildlevelup)
+{
int level = 0;
int16 added_level;
struct guild *guild_info;
@@ -2588,42 +2715,49 @@ ACMD(guildlevelup) {
return true;
}
-/*==========================================
+/**
+ * Creates a pet egg in the character's inventory.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @makeegg <pet>
+ * @endcode
+ *
+ **/
ACMD(makeegg)
{
- struct item_data *item_data;
- int id, pet_id;
-
- if (!*message) {
- clif->message(fd, msg_fd(fd,1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
+ if (*message == '\0') {
+ clif->message(fd, msg_fd(fd, 1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
return false;
}
- if ((item_data = itemdb->search_name(message)) != NULL) // for egg name
+ struct item_data *item_data = itemdb->search_name(message);
+ int id;
+
+ if (item_data != NULL) { // Egg name.
id = item_data->nameid;
- else
- if ((id = mob->db_searchname(message)) != 0) // for monster name
- ;
- else
- id = atoi(message);
+ } else {
+ id = mob->db_searchname(message); // Monster name.
+
+ if (id == 0)
+ id = atoi(message); // Egg/monster ID.
+ }
- pet_id = pet->search_petDB_index(id, PET_CLASS);
- if (pet_id < 0)
+ int pet_id = pet->search_petDB_index(id, PET_CLASS);
+
+ if (pet_id == INDEX_NOT_FOUND)
pet_id = pet->search_petDB_index(id, PET_EGG);
- if (pet_id >= 0) {
- sd->catch_target_class = pet->db[pet_id].class_;
- intif->create_pet(
- sd->status.account_id, sd->status.char_id,
- (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv,
- (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
- 100, 0, 1, pet->db[pet_id].jname);
- } else {
- clif->message(fd, msg_fd(fd,180)); // The monster/egg name/id doesn't exist.
+
+ if (pet_id == INDEX_NOT_FOUND) {
+ clif->message(fd, msg_fd(fd, 180)); // The monster/egg name/ID doesn't exist.
return false;
}
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID, 0,
+ (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1,pet->db[pet_id].jname);
+
return true;
}
@@ -2642,72 +2776,90 @@ ACMD(hatch)
return true;
}
-/*==========================================
+/**
+ * Sets a pet's intimacy value.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @petfriendly <0-1000>
+ * @endcode
+ *
+ **/
ACMD(petfriendly)
{
- int friendly;
- struct pet_data *pd;
-
- if (!*message || (friendly = atoi(message)) < 0) {
- clif->message(fd, msg_fd(fd,1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
+ if (*message == '\0' || (atoi(message) == 0 && isdigit(*message) == 0)) {
+ clif->message(fd, msg_fd(fd, 1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
return false;
}
- pd = sd->pd;
- if (!pd) {
- clif->message(fd, msg_fd(fd,184)); // Sorry, but you have no pet.
+ int friendly = atoi(message);
+
+ if (friendly < PET_INTIMACY_NONE || friendly > PET_INTIMACY_MAX) {
+ clif->message(fd, msg_fd(fd, 1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
return false;
}
- if (friendly < 0 || friendly > 1000)
- {
- clif->message(fd, msg_fd(fd,37)); // An invalid number was specified.
+ struct pet_data *pd = sd->pd;
+
+ if (sd->status.pet_id == 0 || pd == NULL) {
+ clif->message(fd, msg_fd(fd, 184)); // Sorry, but you have no pet.
return false;
}
- if (friendly == pd->pet.intimate) {
- clif->message(fd, msg_fd(fd,183)); // Pet intimacy is already at maximum.
+ if (friendly == pd->pet.intimate && friendly == PET_INTIMACY_MAX) {
+ clif->message(fd, msg_fd(fd, 183)); // Pet intimacy is already at maximum.
return false;
}
- pet->set_intimate(pd, friendly);
- clif->send_petstatus(sd);
- clif->message(fd, msg_fd(fd,182)); // Pet intimacy changed.
+ if (friendly != pd->pet.intimate) { // No need to update the pet's status if intimacy value won't change.
+ pet->set_intimate(pd, friendly);
+ clif->send_petstatus(sd);
+ }
+
+ clif->message(fd, msg_fd(fd, 182)); // Pet intimacy changed. (Send message regardless of value has changed or not.)
+
return true;
}
-/*==========================================
+/**
+ * Sets a pet's hunger value.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @pethungry <0-100>
+ * @endcode
+ *
+ **/
ACMD(pethungry)
{
- int hungry;
- struct pet_data *pd;
-
- if (!*message || (hungry = atoi(message)) < 0) {
- clif->message(fd, msg_fd(fd,1017)); // Please enter a valid number (usage: @pethungry <0-100>).
+ if (*message == '\0' || (atoi(message) == 0 && isdigit(*message) == 0)) {
+ clif->message(fd, msg_fd(fd, 1017)); // Please enter a valid number (usage: @pethungry <0-100>).
return false;
}
- pd = sd->pd;
- if (!sd->status.pet_id || !pd) {
- clif->message(fd, msg_fd(fd,184)); // Sorry, but you have no pet.
+ int hungry = atoi(message);
+
+ if (hungry < PET_HUNGER_STARVING || hungry > PET_HUNGER_STUFFED) {
+ clif->message(fd, msg_fd(fd, 1017)); // Please enter a valid number (usage: @pethungry <0-100>).
return false;
}
- if (hungry < 0 || hungry > 100) {
- clif->message(fd, msg_fd(fd,37)); // An invalid number was specified.
+
+ struct pet_data *pd = sd->pd;
+
+ if (sd->status.pet_id == 0 || pd == NULL) {
+ clif->message(fd, msg_fd(fd, 184)); // Sorry, but you have no pet.
return false;
}
- if (hungry == pd->pet.hungry) {
- clif->message(fd, msg_fd(fd,186)); // Pet hunger is already at maximum.
+
+ if (hungry == pd->pet.hungry && hungry == PET_HUNGER_STUFFED) {
+ clif->message(fd, msg_fd(fd, 186)); // Pet hunger is already at maximum.
return false;
}
- pd->pet.hungry = hungry;
- clif->send_petstatus(sd);
- clif->message(fd, msg_fd(fd,185)); // Pet hunger changed.
+ if (hungry != pd->pet.hungry) { // No need to update the pet's status if hunger value won't change.
+ pd->pet.hungry = hungry;
+ clif->send_petstatus(sd);
+ }
+
+ clif->message(fd, msg_fd(fd, 185)); // Pet hunger changed. (Send message regardless of value has changed or not.)
return true;
}
@@ -2739,7 +2891,8 @@ ACMD(petrename)
/*==========================================
*
*------------------------------------------*/
-ACMD(recall) {
+ACMD(recall)
+{
struct map_session_data *pl_sd = NULL;
if (!*message) {
@@ -2747,7 +2900,7 @@ ACMD(recall) {
return false;
}
- if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message, true)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -3011,7 +3164,7 @@ ACMD(doommap)
/*==========================================
*
*------------------------------------------*/
-void atcommand_raise_sub(struct map_session_data* sd)
+static void atcommand_raise_sub(struct map_session_data *sd)
{
nullpo_retv(sd);
status->revive(&sd->bl, 100, 100);
@@ -3072,7 +3225,7 @@ ACMD(kick)
return false;
}
- if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message, true)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -3309,7 +3462,8 @@ ACMD(breakguild)
/*==========================================
*
*------------------------------------------*/
-ACMD(agitstart) {
+ACMD(agitstart)
+{
if (map->agit_flag == 1) {
clif->message(fd, msg_fd(fd,73)); // War of Emperium is currently in progress.
return false;
@@ -3325,7 +3479,8 @@ ACMD(agitstart) {
/*==========================================
*
*------------------------------------------*/
-ACMD(agitstart2) {
+ACMD(agitstart2)
+{
if (map->agit2_flag == 1) {
clif->message(fd, msg_fd(fd,404)); // "War of Emperium SE is currently in progress."
return false;
@@ -3341,7 +3496,8 @@ ACMD(agitstart2) {
/*==========================================
*
*------------------------------------------*/
-ACMD(agitend) {
+ACMD(agitend)
+{
if (map->agit_flag == 0) {
clif->message(fd, msg_fd(fd,75)); // War of Emperium is currently not in progress.
return false;
@@ -3357,7 +3513,8 @@ ACMD(agitend) {
/*==========================================
*
*------------------------------------------*/
-ACMD(agitend2) {
+ACMD(agitend2)
+{
if (map->agit2_flag == 0) {
clif->message(fd, msg_fd(fd,406)); // "War of Emperium SE is currently not in progress."
return false;
@@ -3373,7 +3530,8 @@ ACMD(agitend2) {
/*==========================================
* @mapexit - shuts down the map server
*------------------------------------------*/
-ACMD(mapexit) {
+ACMD(mapexit)
+{
map->do_shutdown();
return true;
}
@@ -3397,7 +3555,7 @@ ACMD(idsearch)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,77), item_name); // Search results for '%s' (name: id):
clif->message(fd, atcmd_output);
- match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0);
+ match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, IT_SEARCH_NAME_PARTIAL);
if (match > MAX_SEARCH) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,269), MAX_SEARCH, match);
clif->message(fd, atcmd_output);
@@ -3583,7 +3741,8 @@ ACMD(reloaditemdb)
/*==========================================
*
*------------------------------------------*/
-ACMD(reloadmobdb) {
+ACMD(reloadmobdb)
+{
mob->reload();
pet->read_db();
homun->reload();
@@ -3612,7 +3771,8 @@ ACMD(reloadskilldb)
/*==========================================
* @reloadatcommand - reloads conf/atcommand.conf conf/groups.conf
*------------------------------------------*/
-ACMD(reloadatcommand) {
+ACMD(reloadatcommand)
+{
struct config_t run_test;
if (!libconfig->load_file(&run_test, "conf/groups.conf")) {
@@ -3642,7 +3802,7 @@ ACMD(reloadbattleconf)
struct Battle_Config prev_config;
memcpy(&prev_config, &battle_config, sizeof(prev_config));
- battle->config_read(map->BATTLE_CONF_FILENAME);
+ battle->config_read(map->BATTLE_CONF_FILENAME, false);
if (prev_config.feature_roulette == 0 && battle_config.feature_roulette == 1 && !clif->parse_roulette_db())
battle_config.feature_roulette = 0;
@@ -3686,13 +3846,14 @@ ACMD(reloadbattleconf)
/*==========================================
* @reloadstatusdb - reloads job_db1.txt job_db2.txt job_db2-2.txt refine_db.txt size_fix.txt
*------------------------------------------*/
-ACMD(reloadstatusdb) {
+ACMD(reloadstatusdb)
+{
status->readdb();
clif->message(fd, msg_fd(fd,256));
return true;
}
/*==========================================
- * @reloadpcdb - reloads exp.txt skill_tree.txt attr_fix.txt statpoint.txt
+ * @reloadpcdb - reloads exp_group_db.conf skill_tree.txt attr_fix.txt statpoint.txt
*------------------------------------------*/
ACMD(reloadpcdb)
{
@@ -3704,7 +3865,8 @@ ACMD(reloadpcdb)
/*==========================================
* @reloadscript - reloads all scripts (npcs, warps, mob spawns, ...)
*------------------------------------------*/
-ACMD(reloadscript) {
+ACMD(reloadscript)
+{
struct s_mapiterator* iter;
struct map_session_data* pl_sd;
@@ -3748,7 +3910,7 @@ ACMD(reloadscript) {
* 1 = Show users in that map and their location
* 2 = Shows NPCs in that map
* 3 = Shows the chats in that map
- TODO# add the missing mapflags e.g. adjust_skill_damage to display
+ * TODO# add the missing mapflags e.g. adjust_skill_damage to display
*------------------------------------------*/
ACMD(mapinfo)
{
@@ -3793,7 +3955,7 @@ ACMD(mapinfo)
if( pl_sd->mapindex == m_index ) {
if( pl_sd->state.vending )
vend_num++;
- else if ((cd = map->id2cd(pl_sd->chatID)) != NULL && cd->usersd[0] == pl_sd)
+ else if ((cd = map->id2cd(pl_sd->chat_id)) != NULL && cd->usersd[0] == pl_sd)
chat_num++;
}
}
@@ -3813,6 +3975,9 @@ ACMD(mapinfo)
if (map->list[m_id].flag.battleground)
clif->message(fd, msg_fd(fd,1045)); // Battlegrounds ON
+ if (map->list[m_id].flag.cvc)
+ clif->message(fd, msg_fd(fd, 139)); // CvC ON
+
strcpy(atcmd_output,msg_fd(fd,1046)); // PvP Flags:
if (map->list[m_id].flag.pvp)
strcat(atcmd_output, msg_fd(fd,1047)); // Pvp ON |
@@ -3923,8 +4088,14 @@ ACMD(mapinfo)
strcat(atcmd_output, msg_fd(fd,1096)); // PartyLock |
if (map->list[m_id].flag.guildlock)
strcat(atcmd_output, msg_fd(fd,1097)); // GuildLock |
+ if (map->list[m_id].flag.noautoloot)
+ strcat(atcmd_output, msg_fd(fd, 1063)); // NoAutoloot |
if (map->list[m_id].flag.noviewid != EQP_NONE)
strcat(atcmd_output, msg_fd(fd,1079)); // NoViewID |
+ if (map->list[m_id].flag.pairship_startable)
+ strcat(atcmd_output, msg_fd(fd, 1292)); // PrivateAirshipStartable |
+ if (map->list[m_id].flag.pairship_endable)
+ strcat(atcmd_output, msg_fd(fd, 1293)); // PrivateAirshipEndable |
clif->message(fd, atcmd_output);
switch (list) {
@@ -3948,16 +4119,36 @@ ACMD(mapinfo)
for (i = 0; i < map->list[m_id].npc_num;) {
struct npc_data *nd = map->list[m_id].npc[i];
switch(nd->dir) {
- case 0: strcpy(direction, msg_fd(fd,1101)); break; // North
- case 1: strcpy(direction, msg_fd(fd,1102)); break; // North West
- case 2: strcpy(direction, msg_fd(fd,1103)); break; // West
- case 3: strcpy(direction, msg_fd(fd,1104)); break; // South West
- case 4: strcpy(direction, msg_fd(fd,1105)); break; // South
- case 5: strcpy(direction, msg_fd(fd,1106)); break; // South East
- case 6: strcpy(direction, msg_fd(fd,1107)); break; // East
- case 7: strcpy(direction, msg_fd(fd,1108)); break; // North East
- case 9: strcpy(direction, msg_fd(fd,1109)); break; // North
- default: strcpy(direction, msg_fd(fd,1110)); break; // Unknown
+ case UNIT_DIR_NORTH:
+ strcpy(direction, msg_fd(fd, 1101)); // North
+ break;
+ case UNIT_DIR_NORTHWEST:
+ strcpy(direction, msg_fd(fd, 1102)); // North West
+ break;
+ case UNIT_DIR_WEST:
+ strcpy(direction, msg_fd(fd, 1103)); // West
+ break;
+ case UNIT_DIR_SOUTHWEST:
+ strcpy(direction, msg_fd(fd, 1104)); // South West
+ break;
+ case UNIT_DIR_SOUTH:
+ strcpy(direction, msg_fd(fd, 1105)); // South
+ break;
+ case UNIT_DIR_SOUTHEAST:
+ strcpy(direction, msg_fd(fd, 1106)); // South East
+ break;
+ case UNIT_DIR_EAST:
+ strcpy(direction, msg_fd(fd, 1107)); // East
+ break;
+ case UNIT_DIR_NORTHEAST:
+ strcpy(direction, msg_fd(fd, 1108)); // North East
+ break;
+ case 9: // is this actually used? [skyleo]
+ strcpy(direction, msg_fd(fd, 1109)); // North
+ break;
+ default:
+ strcpy(direction, msg_fd(fd, 1110)); // Unknown
+ break;
}
if(strcmp(nd->name,nd->exname) == 0)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
@@ -3972,7 +4163,7 @@ ACMD(mapinfo)
clif->message(fd, msg_fd(fd,1113)); // ----- Chats in Map -----
iter = mapit_getallusers();
for (pl_sd = BL_UCCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCCAST(BL_PC, mapit->next(iter))) {
- if ((cd = map->id2cd(pl_sd->chatID)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd) {
+ if ((cd = map->id2cd(pl_sd->chat_id)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1114), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
clif->message(fd, atcmd_output);
@@ -4006,7 +4197,7 @@ ACMD(mount_peco)
return false;
}
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) {
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) {
if (!pc->checkskill(sd,RK_DRAGONTRAINING)) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount!
clif->message(fd, atcmd_output);
@@ -4021,7 +4212,7 @@ ACMD(mount_peco)
}
return true;
}
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) {
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_RANGER) {
if (!pc->checkskill(sd,RA_WUGRIDER)) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount!
clif->message(fd, atcmd_output);
@@ -4036,17 +4227,24 @@ ACMD(mount_peco)
}
return true;
}
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) {
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
+ int mtype = MADO_ROBOT;
+ if (!*message)
+ sscanf(message, "%d", &mtype);
+ if (mtype < MADO_ROBOT || mtype >= MADO_MAX) {
+ clif->message(fd, msg_fd(fd, 173)); // Please enter a valid madogear type.
+ return false;
+ }
if (!pc_ismadogear(sd)) {
clif->message(sd->fd,msg_fd(fd,1123)); // You have mounted your Mado Gear.
- pc->setmadogear(sd, true);
+ pc->setmadogear(sd, true, (enum mado_type)mtype);
} else {
clif->message(sd->fd,msg_fd(fd,1124)); // You have released your Mado Gear.
- pc->setmadogear(sd, false);
+ pc->setmadogear(sd, false, (enum mado_type)mtype);
}
return true;
}
- if (sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2) {
+ if ((sd->job & MAPID_BASEMASK) == MAPID_SWORDMAN && (sd->job & JOBL_2) != 0) {
if (!pc_isridingpeco(sd)) { // if actually no peco
if (!pc->checkskill(sd, KN_RIDING)) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,213), skill->get_desc(KN_RIDING)); // You need %s to mount!
@@ -4068,7 +4266,8 @@ ACMD(mount_peco)
/*==========================================
*Spy Commands by Syrus22
*------------------------------------------*/
-ACMD(guildspy) {
+ACMD(guildspy)
+{
char guild_name[NAME_LENGTH];
struct guild *g;
@@ -4107,7 +4306,8 @@ ACMD(guildspy) {
/*==========================================
*
*------------------------------------------*/
-ACMD(partyspy) {
+ACMD(partyspy)
+{
char party_name[NAME_LENGTH];
struct party_data *p;
@@ -4149,12 +4349,13 @@ ACMD(partyspy) {
*------------------------------------------*/
ACMD(repairall)
{
- int count, i;
-
- count = 0;
- for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) {
- sd->status.inventory[i].attribute = 0;
+ int count = 0;
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].card[0] == CARD0_PET)
+ continue;
+ if (sd->status.inventory[i].nameid && (sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
clif->produce_effect(sd, 0, sd->status.inventory[i].nameid);
count++;
}
@@ -4162,7 +4363,7 @@ ACMD(repairall)
if (count > 0) {
clif->misceffect(&sd->bl, 3);
- clif->equiplist(sd);
+ clif->equipList(sd);
clif->message(fd, msg_fd(fd,107)); // All items have been repaired.
} else {
clif->message(fd, msg_fd(fd,108)); // No item need to be repaired.
@@ -4175,7 +4376,8 @@ ACMD(repairall)
/*==========================================
* @nuke [Valaris]
*------------------------------------------*/
-ACMD(nuke) {
+ACMD(nuke)
+{
struct map_session_data *pl_sd;
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -4185,7 +4387,7 @@ ACMD(nuke) {
return false;
}
- if ((pl_sd = map->nick2sd(atcmd_player_name)) != NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name, true)) != NULL) {
if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level
skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, timer->gettick(), 0);
clif->message(fd, msg_fd(fd,109)); // Player has been nuked!
@@ -4204,7 +4406,8 @@ ACMD(nuke) {
/*==========================================
* @tonpc
*------------------------------------------*/
-ACMD(tonpc) {
+ACMD(tonpc)
+{
char npcname[NAME_LENGTH+1];
struct npc_data *nd;
@@ -4303,34 +4506,98 @@ ACMD(loadnpc)
return true;
}
+/**
+ * Unloads a specific NPC.
+ *
+ * @code{.herc}
+ * @unloadnpc <NPC_name> {<flag>}
+ * @endcode
+ *
+ **/
ACMD(unloadnpc)
{
- struct npc_data *nd;
- char NPCname[NAME_LENGTH+1];
+ char npc_name[NAME_LENGTH + 1] = {'\0'};
+ int flag = 1;
- memset(NPCname, '\0', sizeof(NPCname));
+ if (*message == '\0' || sscanf(message, "%24s %1d", npc_name, &flag) < 1) {
+ clif->message(fd, msg_fd(fd, 1133)); /// Please enter a NPC name (Usage: @unloadnpc <NPC_name> {<flag>}).
+ return false;
+ }
+
+ struct npc_data *nd = npc->name2id(npc_name);
+
+ if (nd == NULL) {
+ clif->message(fd, msg_fd(fd, 111)); /// This NPC doesn't exist.
+ return false;
+ }
+
+ npc->unload_duplicates(nd, (flag != 0));
+ npc->unload(nd, true, (flag != 0));
+ npc->read_event_script();
+ clif->message(fd, msg_fd(fd, 112)); /// Npc Disabled.
+ return true;
+}
- if (!*message || sscanf(message, "%24[^\n]", NPCname) < 1) {
- clif->message(fd, msg_fd(fd,1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>).
+/**
+ * Unloads a script file and reloads it.
+ * Note: Be aware that some changes made by NPC are not reverted on unload. See doc/atcommands.txt for details.
+ *
+ * @code{.herc}
+ * @reloadnpc <path> {<flag>}
+ * @endcode
+ *
+ **/
+ACMD(reloadnpc)
+{
+ char format[20];
+
+ snprintf(format, sizeof(format), "%%%ds %%1d", MAX_DIR_PATH);
+
+ char file_path[MAX_DIR_PATH + 1] = {'\0'};
+ int flag = 1;
+
+ if (*message == '\0' || (sscanf(message, format, file_path, &flag) < 1)) {
+ clif->message(fd, msg_fd(fd, 1516)); /// Usage: @reloadnpc <path> {<flag>}
return false;
}
- if ((nd = npc->name2id(NPCname)) == NULL) {
- clif->message(fd, msg_fd(fd,111)); // This NPC doesn't exist.
+ if (!exists(file_path)) {
+ clif->message(fd, msg_fd(fd, 1387)); /// File not found.
return false;
}
- npc->unload_duplicates(nd);
- npc->unload(nd,true);
+ if (!is_file(file_path)) {
+ clif->message(fd, msg_fd(fd, 1518)); /// Not a file.
+ return false;
+ }
+
+ FILE *fp = fopen(file_path, "r");
+
+ if (fp == NULL) {
+ clif->message(fd, msg_fd(fd, 1519)); /// Can't open file.
+ return false;
+ }
+
+ fclose(fp);
+
+ if (!npc->unloadfile(file_path, (flag != 0))) {
+ clif->message(fd, msg_fd(fd, 1517)); /// Script could not be unloaded.
+ return false;
+ }
+
+ clif->message(fd, msg_fd(fd, 1386)); /// File unloaded. Be aware that...
+ npc->addsrcfile(file_path);
+ npc->parsesrcfile(file_path, true);
npc->read_event_script();
- clif->message(fd, msg_fd(fd,112)); // Npc Disabled.
+ clif->message(fd, msg_fd(fd, 262)); /// Script loaded.
return true;
}
/*==========================================
* time in txt for time command (by [Yor])
*------------------------------------------*/
-char* txt_time(int fd, unsigned int duration) {
+static char *txt_time(int fd, unsigned int duration)
+{
int days, hours, minutes, seconds;
static char temp1[CHAT_SIZE_MAX];
int tlen = 0;
@@ -4368,7 +4635,8 @@ char* txt_time(int fd, unsigned int duration) {
* @time/@date/@serverdate/@servertime: Display the date/time of the server (by [Yor]
* Calculation management of GM modification (@day/@night GM commands) is done
*------------------------------------------*/
-ACMD(servertime) {
+ACMD(servertime)
+{
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
char temp[CHAT_SIZE_MAX];
@@ -4423,7 +4691,7 @@ ACMD(servertime) {
//Added by Coltaro
//We're using this function here instead of using time_t so that it only counts player's jail time when he/she's online (and since the idea is to reduce the amount of minutes one by one in status->change_timer...).
//Well, using time_t could still work but for some reason that looks like more coding x_x
-void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int* minute)
+static void get_jail_time(int jailtime, int *year, int *month, int *day, int *hour, int *minute)
{
const int factor_year = 518400; //12*30*24*60 = 518400
const int factor_month = 43200; //30*24*60 = 43200
@@ -4457,7 +4725,8 @@ void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int
* @jail <char_name> by [Yor]
* Special warp! No check with nowarp and nowarpto flag
*------------------------------------------*/
-ACMD(jail) {
+ACMD(jail)
+{
struct map_session_data *pl_sd;
int x, y;
unsigned short m_index;
@@ -4469,7 +4738,7 @@ ACMD(jail) {
return false;
}
- if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -4510,7 +4779,8 @@ ACMD(jail) {
* @unjail/@discharge <char_name> by [Yor]
* Special warp! No check with nowarp and nowarpto flag
*------------------------------------------*/
-ACMD(unjail) {
+ACMD(unjail)
+{
struct map_session_data *pl_sd;
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -4520,7 +4790,7 @@ ACMD(unjail) {
return false;
}
- if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -4544,7 +4814,8 @@ ACMD(unjail) {
return true;
}
-ACMD(jailfor) {
+ACMD(jailfor)
+{
struct map_session_data *pl_sd = NULL;
int year, month, day, hour, minute;
char * modif_p;
@@ -4598,7 +4869,7 @@ ACMD(jailfor) {
return false;
}
- if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -4828,7 +5099,8 @@ ACMD(undisguise)
/*==========================================
* UndisguiseAll
*------------------------------------------*/
-ACMD(undisguiseall) {
+ACMD(undisguiseall)
+{
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
@@ -4880,21 +5152,19 @@ ACMD(undisguiseguild)
*------------------------------------------*/
ACMD(exp)
{
- char output[CHAT_SIZE_MAX];
- double nextb, nextj;
-
- memset(output, '\0', sizeof(output));
+ double percentb = 0.0, percentj = 0.0;
+ uint64 nextb, nextj;
nextb = pc->nextbaseexp(sd);
- if (nextb)
- nextb = sd->status.base_exp*100.0/nextb;
+ if (nextb != 0)
+ percentb = sd->status.base_exp * 100.0 / nextb;
nextj = pc->nextjobexp(sd);
- if (nextj)
- nextj = sd->status.job_exp*100.0/nextj;
+ if (nextj != 0)
+ percentj = sd->status.job_exp * 100.0 / nextj;
- sprintf(output, msg_fd(fd,1148), sd->status.base_level, nextb, sd->status.job_level, nextj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%)
- clif->message(fd, output);
+ sprintf(atcmd_output, msg_fd(fd,1148), sd->status.base_level, percentb, sd->status.job_level, percentj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%)
+ clif->message(fd, atcmd_output);
return true;
}
@@ -4911,7 +5181,7 @@ ACMD(broadcast)
}
safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message);
- intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT);
+ clif->broadcast(NULL, atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT, ALL_CLIENT);
return true;
}
@@ -4930,7 +5200,7 @@ ACMD(localbroadcast)
safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message);
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
+ clif->broadcast(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
return true;
}
@@ -5008,7 +5278,8 @@ ACMD(killer)
* @killable by MouseJstr
* enable other people killing you
*------------------------------------------*/
-ACMD(killable) {
+ACMD(killable)
+{
sd->state.killable = !sd->state.killable;
if (sd->state.killable) {
@@ -5024,7 +5295,8 @@ ACMD(killable) {
* @skillon by MouseJstr
* turn skills on for the map
*------------------------------------------*/
-ACMD(skillon) {
+ACMD(skillon)
+{
map->list[sd->bl.m].flag.noskill = 0;
clif->message(fd, msg_fd(fd,244));
return true;
@@ -5034,7 +5306,8 @@ ACMD(skillon) {
* @skilloff by MouseJstr
* Turn skills off on the map
*------------------------------------------*/
-ACMD(skilloff) {
+ACMD(skilloff)
+{
map->list[sd->bl.m].flag.noskill = 1;
clif->message(fd, msg_fd(fd,243));
return true;
@@ -5044,7 +5317,8 @@ ACMD(skilloff) {
* @npcmove by MouseJstr
* move a npc
*------------------------------------------*/
-ACMD(npcmove) {
+ACMD(npcmove)
+{
int x = 0, y = 0, m;
struct npc_data *nd = 0;
@@ -5114,7 +5388,8 @@ ACMD(addwarp)
* @follow by [MouseJstr]
* Follow a player .. staying no more then 5 spaces away
*------------------------------------------*/
-ACMD(follow) {
+ACMD(follow)
+{
struct map_session_data *pl_sd = NULL;
if (!*message) {
@@ -5125,7 +5400,7 @@ ACMD(follow) {
return true;
}
- if ((pl_sd = map->nick2sd(message)) == NULL) {
+ if ((pl_sd = map->nick2sd(message, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -5142,20 +5417,49 @@ ACMD(follow) {
}
/*==========================================
- * @dropall by [MouseJstr]
- * Drop all your possession on the ground
+ * @dropall by [MouseJstr] and [Xantara]
+ * Drop all your possession on the ground based on item type
*------------------------------------------*/
ACMD(dropall)
{
- int i;
+ int type = -1;
- for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].amount) {
- if(sd->status.inventory[i].equip != 0)
- pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
- pc->dropitem(sd, i, sd->status.inventory[i].amount);
+ if (message[0] != '\0') {
+ type = atoi(message);
+ if (!((type >= IT_HEALING && type <= IT_DELAYCONSUME) || type == IT_CASH || type == -1)) {
+ clif->message(fd, msg_fd(fd, 1500));
+ clif->message(fd, msg_fd(fd, 1501));
+ return false;
}
}
+
+ int count = 0, count_skipped = 0;
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].amount > 0) {
+ struct item_data *item_data = itemdb->exists(sd->status.inventory[i].nameid);
+ if (item_data == NULL) {
+ ShowWarning("Non-existant item %d on dropall list (account_id: %d, char_id: %d)\n", sd->status.inventory[i].nameid, sd->status.account_id, sd->status.char_id);
+ continue;
+ }
+
+ if (!pc->candrop(sd, &sd->status.inventory[i]))
+ continue;
+
+ if (type == -1 || type == item_data->type) {
+ if (sd->status.inventory[i].equip != 0)
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC | PCUNEQUIPITEM_FORCE);
+
+ int amount = sd->status.inventory[i].amount;
+ if (pc->dropitem(sd, i, amount) != 0)
+ count += amount;
+ else
+ count_skipped += amount;
+ }
+ }
+ }
+
+ sprintf(atcmd_output, msg_fd(fd, 1502), count, count_skipped); // %d items are dropped (%d skipped)!
+ clif->message(fd, atcmd_output);
return true;
}
@@ -5165,8 +5469,6 @@ ACMD(dropall)
*------------------------------------------*/
ACMD(storeall)
{
- int i;
-
if (sd->state.storage_flag != STORAGE_FLAG_NORMAL) {
//Open storage.
if (storage->open(sd) == 1) {
@@ -5175,7 +5477,12 @@ ACMD(storeall)
}
}
- for (i = 0; i < MAX_INVENTORY; i++) {
+ if (sd->storage.received == false) {
+ clif->message(fd, msg_fd(fd, 27)); // "Storage has not been loaded yet"
+ return false;
+ }
+
+ for (int i = 0; i < sd->status.inventorySize; i++) {
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
@@ -5190,17 +5497,25 @@ ACMD(storeall)
ACMD(clearstorage)
{
- int i, j;
+ int i;
if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) {
clif->message(fd, msg_fd(fd,250));
return false;
}
- j = sd->status.storage.storage_amount;
- for (i = 0; i < j; ++i) {
- storage->delitem(sd, i, sd->status.storage.items[i].amount);
+ if (sd->storage.received == false) {
+ clif->message(fd, msg_fd(fd, 27)); // "Storage has not been loaded yet"
+ return false;
}
+
+ for (i = 0; i < VECTOR_LENGTH(sd->storage.item); ++i) {
+ if (VECTOR_INDEX(sd->storage.item, i).nameid == 0)
+ continue; // we skip the already deleted items.
+
+ storage->delitem(sd, i, VECTOR_INDEX(sd->storage.item, i).amount);
+ }
+
storage->close(sd);
clif->message(fd, msg_fd(fd,1394)); // Your storage was cleaned.
@@ -5256,7 +5571,7 @@ ACMD(clearcart)
return false;
}
- if (sd->state.vending) {
+ if (sd->state.vending || sd->state.prevend) {
clif->message(fd, msg_fd(fd,548)); // You can't clean a cart while vending!
return false;
}
@@ -5297,12 +5612,13 @@ ACMD(skillid)
iter = db_iterator(skill->name2id_db);
for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) {
- int idx = skill->get_index(DB->data2i(data));
- if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->dbs->db[idx].desc, message, skillen) == 0) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); // skill %d: %s (%s)
+ int skill_id = DB->data2i(data);
+ const char *skill_desc = skill->get_desc(skill_id);
+ if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_desc, message, skillen) == 0) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1164), skill_id, skill_desc, key.str); // skill %d: %s (%s)
clif->message(fd, atcmd_output);
- } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->dbs->db[idx].desc,message) ) ) {
- snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str);
+ } else if (found < MAX_SKILLID_PARTIAL_RESULTS && (stristr(key.str, message) != NULL || stristr(skill_desc, message) != NULL)) {
+ snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd, 1164), skill_id, skill_desc, key.str);
found++;
}
}
@@ -5325,7 +5641,8 @@ ACMD(skillid)
* @useskill by [MouseJstr]
* A way of using skills without having to find them in the skills menu
*------------------------------------------*/
-ACMD(useskill) {
+ACMD(useskill)
+{
struct map_session_data *pl_sd = NULL;
struct block_list *bl;
uint16 skill_id;
@@ -5339,7 +5656,7 @@ ACMD(useskill) {
if (!strcmp(target,"self"))
pl_sd = sd; //quick keyword
- else if ((pl_sd = map->nick2sd(target)) == NULL) {
+ else if ((pl_sd = map->nick2sd(target, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -5350,6 +5667,8 @@ ACMD(useskill) {
return false;
}
+ pc->autocast_clear(sd);
+
if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL
&& sd->hd && homun_alive(sd->hd)) // (If used with @useskill, put the homunc as dest)
bl = &sd->hd->bl;
@@ -5371,7 +5690,8 @@ ACMD(useskill) {
* Debug command to locate new skill IDs. It sends the
* three possible skill-effect packets to the area.
*------------------------------------------*/
-ACMD(displayskill) {
+ACMD(displayskill)
+{
struct status_data *st;
int64 tick;
uint16 skill_id;
@@ -5406,7 +5726,7 @@ ACMD(skilltree)
return false;
}
- if ( (pl_sd = map->nick2sd(target)) == NULL ) {
+ if ( (pl_sd = map->nick2sd(target, true)) == NULL ) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -5429,7 +5749,7 @@ ACMD(skilltree)
for (j = 0; j < VECTOR_LENGTH(entry->need); j++) {
struct skill_tree_requirement *req = &VECTOR_INDEX(entry->need, j);
if (pc->checkskill(sd, req->id) < req->lv) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1170), req->lv, skill->dbs->db[req->id].desc); // Player requires level %d of skill %s.
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1170), req->lv, skill->get_desc(req->id)); // Player requires level %d of skill %s.
clif->message(fd, atcmd_output);
meets = 0;
}
@@ -5442,7 +5762,8 @@ ACMD(skilltree)
}
// Hand a ring with partners name on it to this char
-void atcommand_getring(struct map_session_data* sd) {
+static void atcommand_getring(struct map_session_data *sd)
+{
int flag, item_id;
struct item item_tmp;
nullpo_retv(sd);
@@ -5451,13 +5772,13 @@ void atcommand_getring(struct map_session_data* sd) {
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = 1;
- item_tmp.card[0] = 255;
- item_tmp.card[2] = sd->status.partner_id;
- item_tmp.card[3] = sd->status.partner_id >> 16;
+ item_tmp.card[0] = CARD0_FORGE;
+ item_tmp.card[2] = GetWord(sd->status.partner_id, 0);
+ item_tmp.card[3] = GetWord(sd->status.partner_id, 1);
if((flag = pc->additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
@@ -5465,7 +5786,8 @@ void atcommand_getring(struct map_session_data* sd) {
* @marry by [MouseJstr], fixed by Lupus
* Marry two players
*------------------------------------------*/
-ACMD(marry) {
+ACMD(marry)
+{
struct map_session_data *pl_sd = NULL;
char player_name[NAME_LENGTH] = "";
@@ -5474,7 +5796,7 @@ ACMD(marry) {
return false;
}
- if ((pl_sd = map->nick2sd(player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(player_name, true)) == NULL) {
clif->message(fd, msg_fd(fd,3));
return false;
}
@@ -5584,7 +5906,8 @@ ACMD(autotrade)
* @changegm by durf (changed by Lupus)
* Changes Master of your Guild to a specified guild member
*------------------------------------------*/
-ACMD(changegm) {
+ACMD(changegm)
+{
struct guild *g;
struct map_session_data *pl_sd;
@@ -5603,12 +5926,12 @@ ACMD(changegm) {
return false;
}
- if ((pl_sd=map->nick2sd(message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
+ if ((pl_sd=map->nick2sd(message, true)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
clif->message(fd, msg_fd(fd,1184)); // Target character must be online and be a guild member.
return false;
}
- guild->gm_change(sd->status.guild_id, pl_sd);
+ guild->gm_change(sd->status.guild_id, pl_sd->status.char_id);
return true;
}
@@ -5616,14 +5939,15 @@ ACMD(changegm) {
* @changeleader by Skotlex
* Changes the leader of a party.
*------------------------------------------*/
-ACMD(changeleader) {
+ACMD(changeleader)
+{
if (!message[0]) {
clif->message(fd, msg_fd(fd,1185)); // Usage: @changeleader <party_member_name>
return false;
}
- if (party->changeleader(sd, map->nick2sd(message)))
+ if (party->changeleader(sd, map->nick2sd(message, true)))
return true;
return false;
}
@@ -5805,7 +6129,8 @@ ACMD(autolootitem)
* Credits:
* chriser,Aleos
*------------------------------------------*/
-ACMD(autoloottype) {
+ACMD(autoloottype)
+{
uint8 action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset
enum item_types type = -1;
int ITEM_NONE = 0;
@@ -5918,8 +6243,8 @@ ACMD(snow)
/*==========================================
* Cherry tree snowstorm is made to fall. (Sakura)
*------------------------------------------*/
-ACMD(sakura) {
-
+ACMD(sakura)
+{
if (map->list[sd->bl.m].flag.sakura) {
map->list[sd->bl.m].flag.sakura=0;
clif->weather(sd->bl.m);
@@ -5935,8 +6260,8 @@ ACMD(sakura) {
/*==========================================
* Clouds appear.
*------------------------------------------*/
-ACMD(clouds) {
-
+ACMD(clouds)
+{
if (map->list[sd->bl.m].flag.clouds) {
map->list[sd->bl.m].flag.clouds=0;
clif->weather(sd->bl.m);
@@ -5953,8 +6278,8 @@ ACMD(clouds) {
/*==========================================
* Different type of clouds using effect 516
*------------------------------------------*/
-ACMD(clouds2) {
-
+ACMD(clouds2)
+{
if (map->list[sd->bl.m].flag.clouds2) {
map->list[sd->bl.m].flag.clouds2=0;
clif->weather(sd->bl.m);
@@ -5971,8 +6296,8 @@ ACMD(clouds2) {
/*==========================================
* Fog hangs over.
*------------------------------------------*/
-ACMD(fog) {
-
+ACMD(fog)
+{
if (map->list[sd->bl.m].flag.fog) {
map->list[sd->bl.m].flag.fog=0;
clif->weather(sd->bl.m);
@@ -5988,8 +6313,8 @@ ACMD(fog) {
/*==========================================
* Fallen leaves fall.
*------------------------------------------*/
-ACMD(leaves) {
-
+ACMD(leaves)
+{
if (map->list[sd->bl.m].flag.leaves) {
map->list[sd->bl.m].flag.leaves=0;
clif->weather(sd->bl.m);
@@ -6006,8 +6331,8 @@ ACMD(leaves) {
/*==========================================
* Fireworks appear.
*------------------------------------------*/
-ACMD(fireworks) {
-
+ACMD(fireworks)
+{
if (map->list[sd->bl.m].flag.fireworks) {
map->list[sd->bl.m].flag.fireworks=0;
clif->weather(sd->bl.m);
@@ -6084,9 +6409,10 @@ ACMD(mobsearch)
clif->message(fd, atcmd_output);
return false;
}
- if (mob_id == atoi(mob_name))
- strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
- //strcpy(mob_name,mob_db(mob_id)->name); // --en--
+ if (mob_id == atoi(mob_name)) {
+ strcpy(mob_name,mob->db(mob_id)->jname); // DEFAULT_MOB_JNAME
+ //strcpy(mob_name,mob->db(mob_id)->name); // DEFAULT_MOB_NAME
+ }
snprintf(atcmd_output, sizeof atcmd_output, msg_fd(fd,1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s
clif->message(fd, atcmd_output);
@@ -6114,20 +6440,23 @@ ACMD(mobsearch)
* @cleanmap - cleans items on the ground
* @cleanarea - cleans items on the ground within an specified area
*------------------------------------------*/
-int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) {
+static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap)
+{
nullpo_ret(bl);
map->clearflooritem(bl);
return 0;
}
-ACMD(cleanmap) {
+ACMD(cleanmap)
+{
map->foreachinmap(atcommand->cleanfloor_sub, sd->bl.m, BL_ITEM);
clif->message(fd, msg_fd(fd,1221)); // All dropped items have been cleaned up.
return true;
}
-ACMD(cleanarea) {
+ACMD(cleanarea)
+{
int x0 = 0, y0 = 0, x1 = 0, y1 = 0, n = 0;
if (!*message || (n=sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1)) < 1) {
@@ -6148,7 +6477,7 @@ ACMD(cleanarea) {
*------------------------------------------*/
ACMD(npctalk)
{
- char name[NAME_LENGTH],mes[100],temp[100];
+ char name[NAME_LENGTH], mes[100], temp[200];
struct npc_data *nd;
bool ifcolor=(*(info->command + 7) != 'c' && *(info->command + 7) != 'C')?0:1;
unsigned int color = 0;
@@ -6178,14 +6507,14 @@ ACMD(npctalk)
snprintf(temp, sizeof(temp), "%s : %s", name, mes);
if(ifcolor) clif->messagecolor(&nd->bl,color,temp);
- else clif->disp_overhead(&nd->bl, temp);
+ else clif->disp_overhead(&nd->bl, temp, AREA_CHAT_WOC, NULL);
return true;
}
ACMD(pettalk)
{
- char mes[100],temp[100];
+ char mes[100], temp[200];
struct pet_data *pd;
if (battle_config.min_chat_delay) {
@@ -6238,7 +6567,7 @@ ACMD(pettalk)
}
snprintf(temp, sizeof temp ,"%s : %s", pd->pet.name, mes);
- clif->disp_overhead(&pd->bl, temp);
+ clif->disp_overhead(&pd->bl, temp, AREA_CHAT_WOC, NULL);
return true;
}
@@ -6291,7 +6620,8 @@ ACMD(users)
/*==========================================
*
*------------------------------------------*/
-ACMD(reset) {
+ACMD(reset)
+{
pc->resetstate(sd);
pc->resetskill(sd, PCRESETSKILL_RESYNC);
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,208), sd->status.name); // '%s' skill and stats points reseted!
@@ -6302,47 +6632,52 @@ ACMD(reset) {
/*==========================================
*
*------------------------------------------*/
+
+/**
+ * Spawns mobs which treats the invoking as its master.
+ *
+ * @code{.herc}
+ * @summon <monster name/ID> {<duration>}
+ * @endcode
+ *
+ **/
ACMD(summon)
{
- char name[NAME_LENGTH];
- int mob_id = 0;
+ char name[NAME_LENGTH + 1] = {'\0'};
int duration = 0;
- struct mob_data *md;
- int64 tick=timer->gettick();
- if (!*message || sscanf(message, "%23s %12d", name, &duration) < 1)
- {
- clif->message(fd, msg_fd(fd,1225)); // Please enter a monster name (usage: @summon <monster name> {duration}).
+ if (*message == '\0' || sscanf(message, "%24s %12d", name, &duration) < 1) {
+ clif->message(fd, msg_fd(fd, 1225)); /// Please enter a monster name (usage: @summon <monster name> {duration}).
return false;
}
- if (duration < 1)
- duration =1;
- else if (duration > 60)
- duration =60;
+ int mob_id = atoi(name);
- if ((mob_id = atoi(name)) == 0)
+ if (mob_id == 0)
mob_id = mob->db_searchname(name);
- if(mob_id == 0 || mob->db_checkid(mob_id) == 0)
- {
- clif->message(fd, msg_fd(fd,40)); // Invalid monster ID or name.
+
+ if (mob_id == 0 || mob->db_checkid(mob_id) == 0) {
+ clif->message(fd, msg_fd(fd, 40)); /// Invalid monster ID or name.
return false;
}
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE);
+ struct mob_data *md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, DEFAULT_MOB_JNAME, mob_id, "",
+ SZ_SMALL, AI_NONE, 0);
- if(!md)
+ if (md == NULL)
return false;
md->master_id = sd->bl.id;
md->special_state.ai = AI_ATTACK;
- md->deletetimer = timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0);
- clif->specialeffect(&md->bl,344,AREA);
- mob->spawn(md);
- sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
- clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick);
- clif->message(fd, msg_fd(fd,39)); // All monster summoned!
+ const int64 tick = timer->gettick();
+
+ md->deletetimer = timer->add(tick + (int64)cap_value(duration, 1, 60) * 60000, mob->timer_delete, md->bl.id, 0);
+ clif->specialeffect(&md->bl, 344, AREA);
+ mob->spawn(md);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
+ clif->skill_poseffect(&sd->bl, AM_CALLHOMUN, 1, md->bl.x, md->bl.y, tick);
+ clif->message(fd, msg_fd(fd, 39)); /// All monster summoned!
return true;
}
@@ -6374,7 +6709,8 @@ ACMD(adjgroup)
* @trade by [MouseJstr]
* Open a trade window with a remote player
*------------------------------------------*/
-ACMD(trade) {
+ACMD(trade)
+{
struct map_session_data *pl_sd = NULL;
if (!*message) {
@@ -6382,7 +6718,7 @@ ACMD(trade) {
return false;
}
- if ((pl_sd = map->nick2sd(message)) == NULL) {
+ if ((pl_sd = map->nick2sd(message, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -6417,7 +6753,8 @@ ACMD(setbattleflag)
/*==========================================
* @unmute [Valaris]
*------------------------------------------*/
-ACMD(unmute) {
+ACMD(unmute)
+{
struct map_session_data *pl_sd = NULL;
if (!*message) {
@@ -6425,7 +6762,7 @@ ACMD(unmute) {
return false;
}
- if ((pl_sd = map->nick2sd(message)) == NULL) {
+ if ((pl_sd = map->nick2sd(message, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -6468,7 +6805,8 @@ ACMD(uptime)
* @changesex <sex>
* => Changes one's sex. Argument sex can be 0 or 1, m or f, male or female.
*------------------------------------------*/
-ACMD(changesex) {
+ACMD(changesex)
+{
int i;
pc->resetskill(sd, PCRESETSKILL_CHSEX);
@@ -6479,10 +6817,23 @@ ACMD(changesex) {
return true;
}
+ACMD(changecharsex)
+{
+ int i;
+
+ pc->resetskill(sd, PCRESETSKILL_CHSEX);
+ // to avoid any problem with equipment and invalid sex, equipment is unequipped.
+ for (i=0; i<EQI_MAX; i++)
+ if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
+ chrif->changesex(sd, false);
+ return true;
+}
+
/*================================================
* @mute - Mutes a player for a set amount of time
*------------------------------------------------*/
-ACMD(mute) {
+ACMD(mute)
+{
struct map_session_data *pl_sd = NULL;
int manner;
@@ -6491,7 +6842,7 @@ ACMD(mute) {
return false;
}
- if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name, true)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -6523,6 +6874,9 @@ ACMD(mute) {
*------------------------------------------*/
ACMD(refresh)
{
+ if (sd->npc_id > 0)
+ return false;
+
clif->refresh(sd);
return true;
}
@@ -6534,33 +6888,46 @@ ACMD(refreshall)
iter = mapit_getallusers();
for (iter_sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); iter_sd = BL_UCAST(BL_PC, mapit->next(iter)))
- clif->refresh(iter_sd);
+ if (iter_sd->npc_id <= 0)
+ clif->refresh(iter_sd);
mapit->free(iter);
return true;
}
/*==========================================
- * @identify
+ * @identify / @identifyall
* => GM's magnifier.
*------------------------------------------*/
ACMD(identify)
{
- int i,num;
+ int num = 0;
+ bool identifyall = (strcmpi(info->command, "identifyall") == 0);
- for (i=num=0;i<MAX_INVENTORY;i++) {
- if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){
- num++;
+ if (!identifyall) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify != 1) {
+ num++;
+ }
}
- }
- if (num > 0) {
- clif->item_identify_list(sd);
} else {
- clif->message(fd,msg_fd(fd,1238)); // There are no items to appraise.
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify != 1) {
+ skill->identify(sd, i);
+ num++;
+ }
+ }
}
+
+ if (num == 0)
+ clif->message(fd,msg_fd(fd,1238)); // There are no items to appraise.
+ else if (!identifyall)
+ clif->item_identify_list(sd);
+
return true;
}
-ACMD(misceffect) {
+ACMD(misceffect)
+{
int effect = 0;
if (!*message)
@@ -6640,9 +7007,9 @@ ACMD(mobinfo)
// stats
if (monster->mexp)
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1240), monster->name, monster->jname, monster->sprite, monster->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d)
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1240), monster->name, monster->jname, monster->sprite, monster->vd.class); // MVP Monster: '%s'/'%s'/'%s' (%d)
else
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1241), monster->name, monster->jname, monster->sprite, monster->vd.class_); // Monster: '%s'/'%s'/'%s' (%d)
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1241), monster->name, monster->jname, monster->sprite, monster->vd.class); // Monster: '%s'/'%s'/'%s' (%d)
clif->message(fd, atcmd_output);
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1242), monster->lv, monster->status.max_hp, base_exp, job_exp, MOB_HIT(monster), MOB_FLEE(monster)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d
@@ -6770,16 +7137,17 @@ ACMD(showmobs)
return false;
}
- if(mob_id == atoi(mob_name))
- strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
- //strcpy(mob_name,mob_db(mob_id)->name); // --en--
+ if (mob_id == atoi(mob_name)) {
+ strcpy(mob_name,mob->db(mob_id)->jname); // DEFAULT_MOB_JNAME
+ //strcpy(mob_name,mob->db(mob_id)->name); // DEFAULT_MOB_NAME
+ }
snprintf(atcmd_output, sizeof atcmd_output, msg_fd(fd,1252), // Mob Search... %s %s
mob_name, mapindex_id2name(sd->mapindex));
clif->message(fd, atcmd_output);
it = mapit_geteachmob();
- for (md = BL_UCCAST(BL_MOB, mapit->first(it)); mapit->next(it); md = BL_UCCAST(BL_MOB, mapit->next(it))) {
+ for (md = BL_UCCAST(BL_MOB, mapit->first(it)); mapit->exists(it); md = BL_UCCAST(BL_MOB, mapit->next(it))) {
if( md->bl.m != sd->bl.m )
continue;
if( mob_id != -1 && md->class_ != mob_id )
@@ -6800,7 +7168,8 @@ ACMD(showmobs)
/*==========================================
* homunculus level up [orn]
*------------------------------------------*/
-ACMD(homlevel) {
+ACMD(homlevel)
+{
struct homun_data *hd;
int level = 0;
enum homun_type htype;
@@ -6871,7 +7240,8 @@ ACMD(homevolution)
return true;
}
-ACMD(hommutate) {
+ACMD(hommutate)
+{
int homun_id;
enum homun_type m_class, m_id;
@@ -6900,7 +7270,8 @@ ACMD(hommutate) {
/*==========================================
* call choosen homunculus [orn]
*------------------------------------------*/
-ACMD(makehomun) {
+ACMD(makehomun)
+{
int homunid;
if (!*message) {
@@ -6990,7 +7361,7 @@ ACMD(homhungry)
*------------------------------------------*/
ACMD(homtalk)
{
- char mes[100],temp[100];
+ char mes[100], temp[200];
if (battle_config.min_chat_delay) {
if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
@@ -7012,7 +7383,7 @@ ACMD(homtalk)
}
snprintf(temp, sizeof temp ,"%s : %s", sd->hd->homunculus.name, mes);
- clif->disp_overhead(&sd->hd->bl, temp);
+ clif->disp_overhead(&sd->hd->bl, temp, AREA_CHAT_WOC, NULL);
return true;
}
@@ -7020,7 +7391,8 @@ ACMD(homtalk)
/*==========================================
* Show homunculus stats
*------------------------------------------*/
-ACMD(hominfo) {
+ACMD(hominfo)
+{
struct homun_data *hd;
struct status_data *st;
@@ -7148,7 +7520,7 @@ ACMD(iteminfo)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
- count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);
if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
@@ -7199,7 +7571,7 @@ ACMD(whodrops)
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
- count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, IT_SEARCH_NAME_PARTIAL);
if (!count) {
clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
@@ -7280,7 +7652,8 @@ ACMD(whereis)
return true;
}
-ACMD(version) {
+ACMD(version)
+{
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1296), sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); // Hercules %d-bit for %s
clif->message(fd, atcmd_output);
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts)
@@ -7292,8 +7665,9 @@ ACMD(version) {
/*==========================================
* @mutearea by MouseJstr
*------------------------------------------*/
-int atcommand_mutearea_sub(struct block_list *bl, va_list ap)
-{ // As it is being used [ACMD(mutearea)] there's no need to be a bool, but if there's need to reuse it, it's better to be this way
+static int atcommand_mutearea_sub(struct block_list *bl, va_list ap)
+{
+ // As it is being used [ACMD(mutearea)] there's no need to be a bool, but if there's need to reuse it, it's better to be this way
int time, id;
struct map_session_data *pl_sd = BL_CAST(BL_PC, bl);
@@ -7313,7 +7687,8 @@ int atcommand_mutearea_sub(struct block_list *bl, va_list ap)
return 1;
}
-ACMD(mutearea) {
+ACMD(mutearea)
+{
int time;
if (!*message) {
@@ -7372,7 +7747,7 @@ ACMD(me)
}
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,270), sd->status.name, tempmes); // *%s %s*
- clif->disp_overhead(&sd->bl, atcmd_output);
+ clif->disp_overhead(&sd->bl, atcmd_output, AREA_CHAT_WOC, NULL);
return true;
}
@@ -7478,49 +7853,71 @@ ACMD(sizeguild)
*------------------------------------------*/
ACMD(monsterignore)
{
- if (!sd->state.monster_ignore) {
- sd->state.monster_ignore = 1;
+ if (!sd->block_action.immune) {
+ sd->block_action.immune = 1;
clif->message(sd->fd, msg_fd(fd,1305)); // You are now immune to attacks.
} else {
- sd->state.monster_ignore = 0;
+ sd->block_action.immune = 0;
clif->message(sd->fd, msg_fd(fd,1306)); // Returned to normal state.
}
return true;
}
-/*==========================================
- * @fakename
- * => Gives your character a fake name. [Valaris]
- *------------------------------------------*/
+
+/**
+ * Temporarily changes the character's name to the specified string.
+ *
+ * @code{.herc}
+ * @fakename {<options>} {<fake_name>}
+ * @endcode
+ *
+ **/
ACMD(fakename)
{
- if (!*message)
- {
- if (sd->fakename[0])
- {
+ if (*message == '\0') {
+ if (sd->fakename[0] != '\0') {
sd->fakename[0] = '\0';
- clif->charnameack(0, &sd->bl);
- if( sd->disguise )
- clif->charnameack(sd->fd, &sd->bl);
- clif->message(sd->fd, msg_fd(fd,1307)); // Returned to real name.
+ sd->fakename_options = FAKENAME_OPTION_NONE;
+ clif->blname_ack(0, &sd->bl);
+
+ if (sd->disguise != 0) // Another packet should be sent so the client updates the name for sd.
+ clif->blname_ack(sd->fd, &sd->bl);
+
+ clif->message(sd->fd, msg_fd(fd, 1307)); // Returned to real name.
return true;
}
- clif->message(sd->fd, msg_fd(fd,1308)); // You must enter a name.
+ clif->message(sd->fd, msg_fd(fd, 1308)); // You must enter a name.
return false;
}
- if (strlen(message) < 2)
- {
- clif->message(sd->fd, msg_fd(fd,1309)); // Fake name must be at least two characters.
+ int options = FAKENAME_OPTION_NONE;
+ char buf[NAME_LENGTH] = {'\0'};
+ const char *fake_name = NULL;
+
+ if (sscanf(message, "%d %23[^\n]", &options, buf) == 2) {
+ fake_name = buf;
+ } else {
+ options = FAKENAME_OPTION_NONE;
+ fake_name = message;
+ }
+
+ if (strlen(fake_name) < 2) {
+ clif->message(sd->fd, msg_fd(fd, 1309)); // Fake name must be at least two characters.
return false;
}
- 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_fd(fd,1310)); // Fake name enabled.
+ if (options < FAKENAME_OPTION_NONE)
+ options = FAKENAME_OPTION_NONE;
+
+ safestrncpy(sd->fakename, fake_name, sizeof(sd->fakename));
+ sd->fakename_options = options;
+ clif->blname_ack(0, &sd->bl);
+
+ if (sd->disguise != 0) // Another packet should be sent so the client updates the name for sd.
+ clif->blname_ack(sd->fd, &sd->bl);
+
+ clif->message(sd->fd, msg_fd(fd, 1310)); // Fake name enabled.
return true;
}
@@ -7528,7 +7925,8 @@ ACMD(fakename)
/*==========================================
* Ragnarok Resources
*------------------------------------------*/
-ACMD(mapflag) {
+ACMD(mapflag)
+{
#define CHECKFLAG( cmd ) do { if (map->list[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd);} while(0)
#define SETFLAG( cmd ) do { \
if (strcmp( flag_name , #cmd ) == 0) { \
@@ -7551,15 +7949,16 @@ ACMD(mapflag) {
CHECKFLAG(noreturn); CHECKFLAG(monster_noteleport); CHECKFLAG(nosave); CHECKFLAG(nobranch);
CHECKFLAG(noexppenalty); CHECKFLAG(pvp); CHECKFLAG(pvp_noparty); CHECKFLAG(pvp_noguild);
CHECKFLAG(pvp_nightmaredrop); CHECKFLAG(pvp_nocalcrank); CHECKFLAG(gvg_castle); CHECKFLAG(gvg);
- CHECKFLAG(gvg_dungeon); CHECKFLAG(gvg_noparty); CHECKFLAG(battleground); CHECKFLAG(nozenypenalty);
- CHECKFLAG(notrade); CHECKFLAG(noskill); CHECKFLAG(nowarp); CHECKFLAG(nowarpto);
- CHECKFLAG(noicewall); CHECKFLAG(snow); CHECKFLAG(clouds); CHECKFLAG(clouds2);
- CHECKFLAG(fog); CHECKFLAG(fireworks); CHECKFLAG(sakura); CHECKFLAG(leaves);
- CHECKFLAG(nobaseexp);
+ CHECKFLAG(gvg_dungeon); CHECKFLAG(gvg_noparty); CHECKFLAG(battleground); CHECKFLAG(cvc);
+ CHECKFLAG(nozenypenalty); CHECKFLAG(notrade); CHECKFLAG(noskill); CHECKFLAG(nowarp);
+ CHECKFLAG(nowarpto); CHECKFLAG(noicewall); CHECKFLAG(snow); CHECKFLAG(clouds);
+ CHECKFLAG(clouds2); CHECKFLAG(fog); CHECKFLAG(fireworks); CHECKFLAG(sakura);
+ CHECKFLAG(leaves); CHECKFLAG(nobaseexp);
CHECKFLAG(nojobexp); CHECKFLAG(nomobloot); CHECKFLAG(nomvploot); CHECKFLAG(nightenabled);
CHECKFLAG(nodrop); CHECKFLAG(novending); CHECKFLAG(loadevent);
CHECKFLAG(nochat); CHECKFLAG(partylock); CHECKFLAG(guildlock); CHECKFLAG(src4instance);
- CHECKFLAG(notomb); CHECKFLAG(nocashshop); CHECKFLAG(noviewid);
+ CHECKFLAG(notomb); CHECKFLAG(nocashshop); CHECKFLAG(noviewid); CHECKFLAG(town);
+ CHECKFLAG(nostorage); CHECKFLAG(nogstorage);
clif->message(sd->fd," ");
clif->message(sd->fd,msg_fd(fd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
clif->message(sd->fd,msg_fd(fd,1313)); // Type "@mapflag available" to list the available mapflags.
@@ -7567,48 +7966,54 @@ ACMD(mapflag) {
}
for (i = 0; flag_name[i]; i++) flag_name[i] = TOLOWER(flag_name[i]); //lowercase
- if (strcmp( flag_name , "gvg" ) == 0) {
- if( flag && !map->list[sd->bl.m].flag.gvg )
- map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
- else if ( !flag && map->list[sd->bl.m].flag.gvg )
- map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
- } else if ( strcmp( flag_name , "pvp" ) == 0 ) {
- if ( flag && !map->list[sd->bl.m].flag.pvp )
- map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
- else if ( !flag && map->list[sd->bl.m].flag.pvp )
- map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
- } else if ( strcmp( flag_name , "battleground" ) == 0 ) {
- if ( flag && !map->list[sd->bl.m].flag.battleground )
- map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_BG_NAME));
- else if ( !flag && map->list[sd->bl.m].flag.battleground )
- map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
+ if (strcmp(flag_name, "gvg") == 0) {
+ if (flag && !map->list[sd->bl.m].flag.gvg)
+ map->zone_change2(sd->bl.m, strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
+ else if (!flag && map->list[sd->bl.m].flag.gvg)
+ map->zone_change2(sd->bl.m, map->list[sd->bl.m].prev_zone);
+ } else if (strcmp(flag_name, "pvp") == 0) {
+ if (flag && !map->list[sd->bl.m].flag.pvp)
+ map->zone_change2(sd->bl.m, strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
+ else if (!flag && map->list[sd->bl.m].flag.pvp)
+ map->zone_change2(sd->bl.m, map->list[sd->bl.m].prev_zone);
+ } else if (strcmp(flag_name, "battleground") == 0) {
+ if (flag && !map->list[sd->bl.m].flag.battleground)
+ map->zone_change2(sd->bl.m, strdb_get(map->zone_db, MAP_ZONE_BG_NAME));
+ else if (!flag && map->list[sd->bl.m].flag.battleground)
+ map->zone_change2(sd->bl.m, map->list[sd->bl.m].prev_zone);
+ } else if (strcmp(flag_name, "cvc") == 0) {
+ if (flag && !map->list[sd->bl.m].flag.cvc)
+ map->zone_change2(sd->bl.m, strdb_get(map->zone_db, MAP_ZONE_CVC_NAME));
+ else if (!flag && map->list[sd->bl.m].flag.cvc)
+ map->zone_change2(sd->bl.m, map->list[sd->bl.m].prev_zone);
}
SETFLAG(autotrade); SETFLAG(allowks); SETFLAG(nomemo); SETFLAG(noteleport);
SETFLAG(noreturn); SETFLAG(monster_noteleport); SETFLAG(nosave); SETFLAG(nobranch);
SETFLAG(noexppenalty); SETFLAG(pvp); SETFLAG(pvp_noparty); SETFLAG(pvp_noguild);
SETFLAG(pvp_nightmaredrop); SETFLAG(pvp_nocalcrank); SETFLAG(gvg_castle); SETFLAG(gvg);
- SETFLAG(gvg_dungeon); SETFLAG(gvg_noparty); SETFLAG(battleground); SETFLAG(nozenypenalty);
- SETFLAG(notrade); SETFLAG(noskill); SETFLAG(nowarp); SETFLAG(nowarpto);
- SETFLAG(noicewall); SETFLAG(snow); SETFLAG(clouds); SETFLAG(clouds2);
- SETFLAG(fog); SETFLAG(fireworks); SETFLAG(sakura); SETFLAG(leaves);
- SETFLAG(nobaseexp);
- SETFLAG(nojobexp); SETFLAG(nomobloot); SETFLAG(nomvploot); SETFLAG(nightenabled);
- SETFLAG(nodrop); SETFLAG(novending); SETFLAG(loadevent);
- SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock); SETFLAG(src4instance);
- SETFLAG(notomb); SETFLAG(nocashshop); SETFLAG(noviewid);
-
- clif->message(sd->fd,msg_fd(fd,1314)); // Invalid flag name or flag.
- clif->message(sd->fd,msg_fd(fd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
- clif->message(sd->fd,msg_fd(fd,1315)); // Available Flags:
- clif->message(sd->fd,"----------------------------------");
- clif->message(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,");
- clif->message(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,");
- clif->message(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,");
- clif->message(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,");
- clif->message(sd->fd,"fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,");
- clif->message(sd->fd,"nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,");
- clif->message(sd->fd,"guildlock, src4instance, notomb, nocashshop, noviewid");
+ SETFLAG(gvg_dungeon); SETFLAG(gvg_noparty); SETFLAG(battleground); SETFLAG(cvc);
+ SETFLAG(nozenypenalty); SETFLAG(notrade); SETFLAG(noskill); SETFLAG(nowarp);
+ SETFLAG(nowarpto); SETFLAG(noicewall); SETFLAG(snow); SETFLAG(clouds);
+ SETFLAG(clouds2); SETFLAG(fog); SETFLAG(fireworks); SETFLAG(sakura);
+ SETFLAG(leaves); SETFLAG(nobaseexp); SETFLAG(nojobexp); SETFLAG(nomobloot);
+ SETFLAG(nomvploot); SETFLAG(nightenabled); SETFLAG(nodrop); SETFLAG(novending);
+ SETFLAG(loadevent); SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock);
+ SETFLAG(src4instance); SETFLAG(notomb); SETFLAG(nocashshop); SETFLAG(noviewid);
+ SETFLAG(town); SETFLAG(nostorage); SETFLAG(nogstorage);
+
+
+ clif->message(sd->fd, msg_fd(fd, 1314)); // Invalid flag name or flag.
+ clif->message(sd->fd, msg_fd(fd, 1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
+ clif->message(sd->fd, msg_fd(fd, 1315)); // Available Flags:
+ clif->message(sd->fd, "----------------------------------");
+ clif->message(sd->fd, "town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,");
+ clif->message(sd->fd, "nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,");
+ clif->message(sd->fd, "pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground, cvc,");
+ clif->message(sd->fd, "nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,");
+ clif->message(sd->fd, "fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,");
+ clif->message(sd->fd, "nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,");
+ clif->message(sd->fd, "guildlock, src4instance, notomb, nocashshop, noviewid, nostorage, nogstorage");
#undef CHECKFLAG
#undef SETFLAG
@@ -7669,7 +8074,7 @@ ACMD(showdelay)
ACMD(invite)
{
unsigned int did = sd->duel_group;
- struct map_session_data *target_sd = map->nick2sd(message);
+ struct map_session_data *target_sd = map->nick2sd(message, true);
if (did == 0)
{
@@ -7711,7 +8116,8 @@ ACMD(invite)
return true;
}
-ACMD(duel) {
+ACMD(duel)
+{
unsigned int maxpl = 0;
if (sd->duel_group > 0) {
@@ -7725,10 +8131,11 @@ ACMD(duel) {
return false;
}
- if (!duel->checktime(sd)) {
+ int64 diff = duel->difftime(sd);
+ if (diff > 0) {
char output[CHAT_SIZE_MAX];
- // "Duel: You can take part in duel only one time per %d minutes."
- sprintf(output, msg_fd(fd,356), battle_config.duel_time_interval);
+ // "Duel: You can take part in duel again after %d secconds."
+ sprintf(output, msg_fd(fd,356), (int)diff);
clif->message(fd, output);
return false;
}
@@ -7741,7 +8148,7 @@ ACMD(duel) {
}
duel->create(sd, maxpl);
} else {
- struct map_session_data *target_sd = map->nick2sd(message);
+ struct map_session_data *target_sd = map->nick2sd(message, true);
if (target_sd != NULL) {
unsigned int newduel;
if ((newduel = duel->create(sd, 2)) != -1) {
@@ -7764,7 +8171,8 @@ ACMD(duel) {
return true;
}
-ACMD(leave) {
+ACMD(leave)
+{
if (sd->duel_group <= 0) {
// "Duel: @leave without @duel."
clif->message(fd, msg_fd(fd,358));
@@ -7775,11 +8183,13 @@ ACMD(leave) {
return true;
}
-ACMD(accept) {
- if (!duel->checktime(sd)) {
+ACMD(accept)
+{
+ int64 diff = duel->difftime(sd);
+ if (diff > 0) {
char output[CHAT_SIZE_MAX];
- // "Duel: You can take part in duel only one time per %d minutes."
- sprintf(output, msg_fd(fd,356), battle_config.duel_time_interval);
+ // "Duel: You can take part in duel again after %d seconds."
+ sprintf(output, msg_fd(fd,356), (int)diff);
clif->message(fd, output);
return false;
}
@@ -7803,7 +8213,8 @@ ACMD(accept) {
return true;
}
-ACMD(reject) {
+ACMD(reject)
+{
if (sd->duel_invite <= 0) {
// "Duel: @reject without invitation."
clif->message(fd, msg_fd(fd,362));
@@ -7823,7 +8234,6 @@ ACMD(cash)
{
char output[128];
int value;
- int ret=0;
if (!*message || (value = atoi(message)) == 0) {
clif->message(fd, msg_fd(fd,1322)); // Please enter an amount.
@@ -7831,39 +8241,39 @@ ACMD(cash)
}
if (!strcmpi(info->command,"cash")) {
- if( value > 0 ) {
- if( (ret=pc->getcash(sd, value, 0)) >= 0){
+ if (value > 0) {
+ if ((pc->getcash(sd, value, 0)) >= 0) {
// If this option is set, the message is already sent by pc function
- if( !battle_config.cashshop_show_points ){
- sprintf(output, msg_fd(fd,505), ret, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ if (!battle_config.cashshop_show_points) {
+ sprintf(output, msg_fd(fd,505), value, sd->cashPoints);
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
}
} else
clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value.
} else {
- if( (ret=pc->paycash(sd, -value, 0)) >= 0){
- sprintf(output, msg_fd(fd,410), ret, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ if ((pc->paycash(sd, -value, 0)) >= 0) {
+ sprintf(output, msg_fd(fd,410), -value, sd->cashPoints);
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
}
} else { // @points
- if( value > 0 ) {
- if( (ret=pc->getcash(sd, 0, value)) >= 0) {
+ if (value > 0) {
+ if ((pc->getcash(sd, 0, value)) >= 0) {
// If this option is set, the message is already sent by pc function
- if( !battle_config.cashshop_show_points ){
- sprintf(output, msg_fd(fd,506), ret, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ if (!battle_config.cashshop_show_points) {
+ sprintf(output, msg_fd(fd,506), value, sd->kafraPoints);
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
}
} else
clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value.
} else {
- if( (ret=pc->paycash(sd, -value, -value)) >= 0){
- sprintf(output, msg_fd(fd,411), ret, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ if ((pc->paycash(sd, -value, -value)) >= 0) {
+ sprintf(output, msg_fd(fd,411), -value, sd->kafraPoints);
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
@@ -7874,7 +8284,8 @@ ACMD(cash)
}
// @clone/@slaveclone/@evilclone <playername> [Valaris]
-ACMD(clone) {
+ACMD(clone)
+{
int x=0,y=0,flag=0,master=0,i=0;
struct map_session_data *pl_sd=NULL;
@@ -7883,7 +8294,7 @@ ACMD(clone) {
return false;
}
- if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message, true)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -7957,8 +8368,8 @@ ACMD(request)
}
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,278), message); // (@request): %s
- intif->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
- clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
+ pc->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
+ clif_disp_onlyself(sd, atcmd_output);
clif->message(sd->fd,msg_fd(fd,279)); // @request sent.
return true;
}
@@ -7974,6 +8385,15 @@ ACMD(feelreset)
return true;
}
+// Reset hatred targets [Wolfie]
+ACMD(hatereset)
+{
+ pc->resethate(sd);
+ clif->message(fd, msg_fd(fd, 979)); // Reset 'Hatred' targets.
+
+ return true;
+}
+
/*==========================================
* AUCTION SYSTEM
*------------------------------------------*/
@@ -7992,7 +8412,8 @@ ACMD(auction)
/*==========================================
* Kill Steal Protection
*------------------------------------------*/
-ACMD(ksprotection) {
+ACMD(ksprotection)
+{
if( sd->state.noks ) {
sd->state.noks = KSPROTECT_NONE;
clif->message(fd, msg_fd(fd,1325)); // [ K.S Protection Inactive ]
@@ -8057,8 +8478,8 @@ ACMD(itemlist)
if( strcmpi(info->command, "storagelist") == 0 ) {
location = "storage";
- items = sd->status.storage.items;
- size = MAX_STORAGE;
+ items = VECTOR_DATA(sd->storage.item);
+ size = VECTOR_LENGTH(sd->storage.item);
} else if( strcmpi(info->command, "cartlist") == 0 ) {
location = "cart";
items = sd->status.cart;
@@ -8066,7 +8487,7 @@ ACMD(itemlist)
} else if( strcmpi(info->command, "itemlist") == 0 ) {
location = "inventory";
items = sd->status.inventory;
- size = MAX_INVENTORY;
+ size = sd->status.inventorySize;
} else
return false;
@@ -8079,7 +8500,7 @@ ACMD(itemlist)
const struct item* it = &items[i];
struct item_data* itd;
- if( it->nameid == 0 || (itd = itemdb->exists(it->nameid)) == NULL )
+ if (it->nameid == 0 || (itd = itemdb->exists(it->nameid)) == NULL)
continue;
counter += it->amount;
@@ -8240,7 +8661,7 @@ ACMD(stats)
output_table[14].value = sd->change_level_2nd;
output_table[15].value = sd->change_level_3rd;
- sprintf(job_jobname, "Job - %s %s", pc->job_name(sd->status.class_), "(level %d)");
+ sprintf(job_jobname, "Job - %s %s", pc->job_name(sd->status.class), "(level %d)");
sprintf(output, msg_fd(fd,53), sd->status.name); // '%s' stats:
clif->message(fd, output);
@@ -8252,7 +8673,8 @@ ACMD(stats)
return true;
}
-ACMD(delitem) {
+ACMD(delitem)
+{
char item_name[100];
int nameid, amount = 0, total, idx;
struct item_data* id;
@@ -8313,7 +8735,8 @@ ACMD(delitem) {
/*==========================================
* Custom Fonts
*------------------------------------------*/
-ACMD(font) {
+ACMD(font)
+{
int font_id;
font_id = atoi(message);
@@ -8348,7 +8771,7 @@ ACMD(font) {
/*==========================================
* type: 1 = commands (@), 2 = charcommands (#)
*------------------------------------------*/
-void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommandType type)
+static void atcommand_commands_sub(struct map_session_data *sd, const int fd, AtCommandType type)
{
char line_buff[CHATBOX_SIZE];
char* cur = line_buff;
@@ -8396,6 +8819,38 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
dbi_destroy(iter);
clif->message(fd,line_buff);
+ if (atcommand->binding_count > 0) {
+ int i, count_bind = 0;
+ int gm_lvl = pc_get_group_level(sd);
+
+ for (i = 0; i < atcommand->binding_count; i++) {
+ if (gm_lvl >= ((type == COMMAND_ATCOMMAND) ? atcommand->binding[i]->group_lv : atcommand->binding[i]->group_lv_char)
+ || (type == COMMAND_ATCOMMAND && atcommand->binding[i]->at_groups[pcg->get_idx(sd->group)] > 0)
+ || (type == COMMAND_CHARCOMMAND && atcommand->binding[i]->char_groups[pcg->get_idx(sd->group)] > 0)) {
+ size_t slen = strlen(atcommand->binding[i]->command);
+ if (count_bind == 0) {
+ cur = line_buff;
+ memset(line_buff, ' ', CHATBOX_SIZE);
+ line_buff[CHATBOX_SIZE - 1] = 0;
+ clif->message(fd, "------------------");
+ clif->message(fd, "Custom commands:");
+ }
+ if (slen + cur - line_buff >= CHATBOX_SIZE) {
+ clif->message(fd, line_buff);
+ cur = line_buff;
+ memset(line_buff, ' ', CHATBOX_SIZE);
+ line_buff[CHATBOX_SIZE - 1] = 0;
+ }
+ memcpy(cur, atcommand->binding[i]->command, slen);
+ cur += slen + (10 - slen % 10);
+ count_bind++;
+ }
+ }
+ if (count_bind > 0)
+ clif->message(fd, line_buff); // Last Line
+ count += count_bind;
+ }
+
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,274), count); // "%d commands found."
clif->message(fd, atcmd_output);
@@ -8420,26 +8875,29 @@ ACMD(charcommands)
return true;
}
-/* for new mounts */
+/* For new mounts */
ACMD(cashmount)
{
if (pc_hasmount(sd)) {
- clif->message(fd, msg_fd(fd,1476)); // You are already mounting something else
+ clif->message(fd, msg_fd(fd, 1476)); // You are already mounting something else
return false;
}
- clif->message(sd->fd,msg_fd(fd,1362)); // NOTICE: If you crash with mount your LUA is outdated.
+ clif->message(sd->fd, msg_fd(fd, 1362)); // NOTICE: If you crash with mount your LUA is outdated.
+
if (!sd->sc.data[SC_ALL_RIDING]) {
- clif->message(sd->fd,msg_fd(fd,1363)); // You have mounted.
- sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, 25, INFINITE_DURATION);
+ clif->message(sd->fd, msg_fd(fd, 1363)); // You have mounted.
+ sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, battle_config.boarding_halter_speed, INFINITE_DURATION);
} else {
- clif->message(sd->fd,msg_fd(fd,1364)); // You have released your mount.
+ clif->message(sd->fd, msg_fd(fd, 1364)); // You have released your mount.
status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
}
+
return true;
}
-ACMD(accinfo) {
+ACMD(accinfo)
+{
char query[NAME_LENGTH];
if (!*message || strlen(message) > NAME_LENGTH ) {
@@ -8504,19 +8962,19 @@ ACMD(set)
const char *str = NULL;
switch (reg[0]) {
case '@':
- str = pc->readregstr(sd, script->add_str(reg));
+ str = pc->readregstr(sd, script->add_variable(reg));
break;
case '$':
- str = mapreg->readregstr(script->add_str(reg));
+ str = mapreg->readregstr(script->add_variable(reg));
break;
case '#':
if (reg[1] == '#')
- str = pc_readaccountreg2str(sd, script->add_str(reg));// global
+ str = pc_readaccountreg2str(sd, script->add_variable(reg));// global
else
- str = pc_readaccountregstr(sd, script->add_str(reg));// local
+ str = pc_readaccountregstr(sd, script->add_variable(reg));// local
break;
default:
- str = pc_readglobalreg_str(sd, script->add_str(reg));
+ str = pc_readglobalreg_str(sd, script->add_variable(reg));
break;
}
if (str == NULL || str[0] == '\0') {
@@ -8532,19 +8990,19 @@ ACMD(set)
data->type = C_INT;
switch( reg[0] ) {
case '@':
- data->u.num = pc->readreg(sd, script->add_str(reg));
+ data->u.num = pc->readreg(sd, script->add_variable(reg));
break;
case '$':
- data->u.num = mapreg->readreg(script->add_str(reg));
+ data->u.num = mapreg->readreg(script->add_variable(reg));
break;
case '#':
if( reg[1] == '#' )
- data->u.num = pc_readaccountreg2(sd, script->add_str(reg));// global
+ data->u.num = pc_readaccountreg2(sd, script->add_variable(reg));// global
else
- data->u.num = pc_readaccountreg(sd, script->add_str(reg));// local
+ data->u.num = pc_readaccountreg(sd, script->add_variable(reg));// local
break;
default:
- data->u.num = pc_readglobalreg(sd, script->add_str(reg));
+ data->u.num = pc_readglobalreg(sd, script->add_variable(reg));
break;
}
}
@@ -8568,12 +9026,16 @@ ACMD(set)
aFree(data);
return true;
}
-ACMD(reloadquestdb) {
+
+ACMD(reloadquestdb)
+{
quest->reload();
clif->message(fd, msg_fd(fd,1377)); // Quest database has been reloaded.
return true;
}
-ACMD(addperm) {
+
+ACMD(addperm)
+{
int perm_size = pcg->permission_count;
bool add = (strcmpi(info->command, "addperm") == 0) ? true : false;
int i;
@@ -8629,22 +9091,60 @@ ACMD(addperm) {
return true;
}
+
+/**
+ * Unloads a script file.
+ * Note: Be aware that some changes made by NPC are not reverted on unload. See doc/atcommands.txt for details.
+ *
+ * @code{.herc}
+ * @unloadnpcfile <path> {<flag>}
+ * @endcode
+ *
+ **/
ACMD(unloadnpcfile)
{
- if (!*message) {
- clif->message(fd, msg_fd(fd,1385)); // Usage: @unloadnpcfile <file name>
+ char format[20];
+
+ snprintf(format, sizeof(format), "%%%ds %%1d", MAX_DIR_PATH);
+
+ char file_path[MAX_DIR_PATH + 1] = {'\0'};
+ int flag = 1;
+
+ if (*message == '\0' || (sscanf(message, format, file_path, &flag) < 1)) {
+ clif->message(fd, msg_fd(fd, 1385)); /// Usage: @unloadnpcfile <path> {<flag>}
return false;
}
- if (npc->unloadfile(message)) {
- clif->message(fd, msg_fd(fd,1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed.
- } else {
- clif->message(fd, msg_fd(fd,1387)); // File not found.
+ if (!exists(file_path)) {
+ clif->message(fd, msg_fd(fd, 1387)); /// File not found.
return false;
}
+
+ if (!is_file(file_path)) {
+ clif->message(fd, msg_fd(fd, 1518)); /// Not a file.
+ return false;
+ }
+
+ FILE *fp = fopen(file_path, "r");
+
+ if (fp == NULL) {
+ clif->message(fd, msg_fd(fd, 1519)); /// Can't open file.
+ return false;
+ }
+
+ fclose(fp);
+
+ if (!npc->unloadfile(file_path, (flag != 0))) {
+ clif->message(fd, msg_fd(fd, 1517)); /// Script could not be unloaded.
+ return false;
+ }
+
+ clif->message(fd, msg_fd(fd, 1386)); /// File unloaded. Be aware that...
return true;
}
-ACMD(cart) {
+
+ACMD(cart)
+{
#define MC_CART_MDFY(x,idx) do { \
sd->status.skill[idx].id = (x)?MC_PUSHCART:0; \
sd->status.skill[idx].lv = (x)?1:0; \
@@ -8653,7 +9153,7 @@ ACMD(cart) {
int val = atoi(message);
bool need_skill = pc->checkskill(sd, MC_PUSHCART) ? false : true;
- unsigned int index = skill->get_index(MC_PUSHCART);
+ int index = skill->get_index(MC_PUSHCART);
if (!*message || val < 0 || val > MAX_CARTS) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>).
@@ -8686,6 +9186,7 @@ ACMD(cart) {
return true;
#undef MC_CART_MDFY
}
+
/* [Ind/Hercules] */
ACMD(join)
{
@@ -8729,8 +9230,10 @@ ACMD(join)
return true;
}
+
/* [Ind/Hercules] */
-void atcommand_channel_help(int fd, const char *command, bool can_create) {
+static void atcommand_channel_help(int fd, const char *command, bool can_create)
+{
nullpo_retv(command);
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1404),command); // %s failed.
clif->message(fd, atcmd_output);
@@ -8759,9 +9262,7 @@ void atcommand_channel_help(int fd, const char *command, bool can_create) {
clif->message(fd, msg_fd(fd,1428));// - binds global chat to <channel name>, making anything you type in global be sent to the channel
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind
clif->message(fd, atcmd_output);
- clif->message(fd, msg_fd(fd,1430));// - unbinds your global chat from its attached channel (if binded)
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1429),command);// -- %s unbind
- clif->message(fd, atcmd_output);
+ clif->message(fd, msg_fd(fd,1430));// - unbinds your global chat from its attached channel (if bound)
if( can_create ) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1456),command);// -- %s ban <channel name> <character name>
clif->message(fd, atcmd_output);
@@ -8780,11 +9281,12 @@ void atcommand_channel_help(int fd, const char *command, bool can_create) {
clif->message(fd, msg_fd(fd,1463));// - adds or removes <option name> with <option value> to <channel name> channel
}
}
+
/* [Ind/Hercules] */
-ACMD(channel) {
+ACMD(channel)
+{
struct channel_data *chan;
char subcmd[HCS_NAME_LENGTH], sub1[HCS_NAME_LENGTH], sub2[HCS_NAME_LENGTH], sub3[HCS_NAME_LENGTH];
- unsigned char k = 0;
sub1[0] = sub2[0] = sub3[0] = '\0';
if (!*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) {
@@ -8821,7 +9323,7 @@ ACMD(channel) {
} else if (strcmpi(subcmd,"list") == 0) {
// sub1 = list type; sub2 = unused; sub3 = unused
if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) {
- for (k = 0; k < channel->config->colors_count; k++) {
+ for (int k = 0; k < channel->config->colors_count; k++) {
safesnprintf(atcmd_output, sizeof(atcmd_output), "[ %s list colors ] : %s", command, channel->config->colors_name[k]);
clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output);
@@ -8850,6 +9352,7 @@ ACMD(channel) {
}
} else if (strcmpi(subcmd,"setcolor") == 0) {
// sub1 = channel name; sub2 = color; sub3 = unused
+ int k;
if (sub1[0] != '#') {
clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#'
return false;
@@ -8867,10 +9370,7 @@ ACMD(channel) {
return false;
}
- for (k = 0; k < channel->config->colors_count; k++) {
- if (strcmpi(sub2, channel->config->colors_name[k]) == 0)
- break;
- }
+ ARR_FIND(0, channel->config->colors_count, k, strcmpi(sub2, channel->config->colors_name[k]) == 0);
if (k == channel->config->colors_count) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1411), sub2);// Unknown color '%s'
clif->message(fd, atcmd_output);
@@ -8881,51 +9381,45 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"leave") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
+ int k;
if (sub1[0] != '#') {
clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#'
return false;
}
- for (k = 0; k < sd->channel_count; k++) {
- if (strcmpi(sub1+1,sd->channels[k]->name) == 0)
- break;
- }
- if (k == sd->channel_count) {
+ ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, strcmpi(sub1 + 1, VECTOR_INDEX(sd->channels, k)->name) == 0);
+ if (k == VECTOR_LENGTH(sd->channels)) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
- if (sd->channels[k]->type == HCS_TYPE_ALLY) {
- do {
- for (k = 0; k < sd->channel_count; k++) {
- if (sd->channels[k]->type == HCS_TYPE_ALLY) {
- channel->leave(sd->channels[k],sd);
- break;
- }
+ if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) {
+ for (k = VECTOR_LENGTH(sd->channels) - 1; k >= 0; k--) {
+ // Loop downward to avoid issues when channel->leave() compacts the array
+ if (VECTOR_INDEX(sd->channels, k)->type == HCS_TYPE_ALLY) {
+ channel->leave(VECTOR_INDEX(sd->channels, k), sd);
}
- } while (k != sd->channel_count);
+ }
} else {
- channel->leave(sd->channels[k],sd);
+ channel->leave(VECTOR_INDEX(sd->channels, k), sd);
}
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1426),sub1); // You've left the '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"bindto") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
+ int k;
if (sub1[0] != '#') {
clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#'
return false;
}
- for (k = 0; k < sd->channel_count; k++) {
- if (strcmpi(sub1+1,sd->channels[k]->name) == 0)
- break;
- }
- if (k == sd->channel_count) {
+ ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, strcmpi(sub1 + 1, VECTOR_INDEX(sd->channels, k)->name) == 0);
+ if (k == VECTOR_LENGTH(sd->channels)) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1425),sub1);// You're not part of the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
- sd->gcbind = sd->channels[k];
+ sd->gcbind = VECTOR_INDEX(sd->channels, k);
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1431),sub1); // Your global chat is now bound to the '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"unbind") == 0) {
@@ -8962,7 +9456,7 @@ ACMD(channel) {
return false;
}
- if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
+ if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4, true)) == NULL) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
@@ -9009,7 +9503,7 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
return false;
}
- if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
+ if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4, true)) == NULL) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
@@ -9097,6 +9591,7 @@ ACMD(channel) {
dbi_destroy(iter);
} else if (strcmpi(subcmd,"setopt") == 0) {
// sub1 = channel name; sub2 = option name; sub3 = value
+ int k;
const char* opt_str[3] = {
"None",
"JoinAnnounce",
@@ -9152,8 +9647,8 @@ ACMD(channel) {
} else {
int v = atoi(sub3);
if (k == HCS_OPT_MSG_DELAY) {
- if (v < 0 || v > 10) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10)
+ if (v < 0 || v > channel->config->channel_opt_msg_delay) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1451), v, opt_str[k], channel->config->channel_opt_msg_delay);// value '%d' for option '%s' is out of range (limit is 0-%d)
clif->message(fd, atcmd_output);
return false;
}
@@ -9200,8 +9695,10 @@ ACMD(channel) {
}
return true;
}
+
/* debug only, delete after */
-ACMD(fontcolor) {
+ACMD(fontcolor)
+{
unsigned char k;
if (!*message) {
@@ -9233,7 +9730,9 @@ ACMD(fontcolor) {
return true;
}
-ACMD(searchstore){
+
+ACMD(searchstore)
+{
int val = atoi(message);
switch (val) {
@@ -9248,7 +9747,12 @@ ACMD(searchstore){
searchstore->open(sd, 99, val);
return true;
}
-ACMD(costume){
+
+/*==========================================
+* @costume
+*------------------------------------------*/
+ACMD(costume)
+{
const char* names[] = {
"Wedding",
"Xmas",
@@ -9257,6 +9761,9 @@ ACMD(costume){
#if PACKETVER >= 20131218
"Oktoberfest",
#endif
+#if PACKETVER >= 20141022
+ "Summer2",
+#endif
};
const int name2id[] = {
SC_WEDDING,
@@ -9266,41 +9773,54 @@ ACMD(costume){
#if PACKETVER >= 20131218
SC_OKTOBERFEST,
#endif
+#if PACKETVER >= 20141022
+ SC_DRESS_UP,
+#endif
};
unsigned short k = 0, len = ARRAYLENGTH(names);
+ bool isChangeDress = (strcmpi(info->command, "changedress") == 0 || strcmpi(info->command, "nocosplay") == 0);
+
if (!*message) {
- for( k = 0; k < len; k++ ) {
- if( sd->sc.data[name2id[k]] ) {
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1473),names[k]);//Costume '%s' removed.
- clif->message(sd->fd,atcmd_output);
- status_change_end(&sd->bl,name2id[k],INVALID_TIMER);
+ for (k = 0; k < len; k++) {
+ if (sd->sc.data[name2id[k]]) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1473), names[k]); // Costume '%s' removed.
+ clif->message(sd->fd, atcmd_output);
+ status_change_end(&sd->bl, name2id[k], INVALID_TIMER);
return true;
}
}
- clif->message(sd->fd,msg_fd(fd,1472));
- for( k = 0; k < len; k++ ) {
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1471),names[k]);//-- %s
- clif->message(sd->fd,atcmd_output);
+
+ if (isChangeDress)
+ return true;
+ clif->message(sd->fd, msg_fd(fd, 1472)); // - Available Costumes
+
+ for (k = 0; k < len; k++) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1471), names[k]); //-- %s
+ clif->message(sd->fd, atcmd_output);
}
return false;
}
- for( k = 0; k < len; k++ ) {
- if( sd->sc.data[name2id[k]] ) {
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it.
- clif->message(sd->fd,atcmd_output);
+ if (isChangeDress)
+ return true;
+
+ for (k = 0; k < len; k++) {
+ if (sd->sc.data[name2id[k]]) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1470), names[k]); // You're already with a '%s' costume, type '@costume' to remove it.
+ clif->message(sd->fd, atcmd_output);
return false;
}
}
- for( k = 0; k < len; k++ ) {
- if( strcmpi(message,names[k]) == 0 )
+ for (k = 0; k < len; k++) {
+ if (strcmpi(message,names[k]) == 0)
break;
}
- if( k == len ) {
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1469),message);// '%s' is not a known costume
- clif->message(sd->fd,atcmd_output);
+
+ if (k == len) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1469), message); // '%s' is not a known costume
+ clif->message(sd->fd, atcmd_output);
return false;
}
@@ -9308,10 +9828,12 @@ ACMD(costume){
return true;
}
+
/* for debugging purposes (so users can easily provide us with debug info) */
/* should be trashed as soon as its no longer necessary */
-ACMD(skdebug) {
- safesnprintf(atcmd_output, sizeof(atcmd_output),"second: %u; third: %u", sd->sktree.second, sd->sktree.third);
+ACMD(skdebug)
+{
+ safesnprintf(atcmd_output, sizeof(atcmd_output),"second: %d; third: %d", sd->sktree.second, sd->sktree.third);
clif->message(fd,atcmd_output);
safesnprintf(atcmd_output, sizeof(atcmd_output),"pc_calc_skilltree_normalize_job: %d",pc->calc_skilltree_normalize_job(sd));
clif->message(fd,atcmd_output);
@@ -9321,10 +9843,12 @@ ACMD(skdebug) {
clif->message(fd,atcmd_output);
return true;
}
+
/**
* cooldown-debug
**/
-ACMD(cddebug) {
+ACMD(cddebug)
+{
int i;
struct skill_cd* cd = NULL;
@@ -9345,7 +9869,7 @@ ACMD(cddebug) {
}
if (!cd || (*message && !strcmpi(message,"reset"))) {
- for(i = 0; i < MAX_SKILL; i++) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if( sd->blockskill[i] ) {
clif->messages(fd,"Found skill '%s', unblocking...",skill->dbs->db[i].name);
sd->blockskill[i] = false;
@@ -9369,7 +9893,8 @@ ACMD(cddebug) {
/**
*
**/
-ACMD(lang) {
+ACMD(lang)
+{
uint8 i;
if (!*message) {
@@ -9401,12 +9926,180 @@ ACMD(lang) {
return true;
}
+
+ACMD(claninfo)
+{
+ struct DBIterator *iter = db_iterator(clan->db);
+ struct clan *c;
+ int i, count;
+
+ for (c = dbi_first(iter); dbi_exists(iter); c = dbi_next(iter)) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "Clan #%d:", c->clan_id);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Name: %s", c->name);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Constant: %s", c->constant);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Master: %s", c->master);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Map: %s", c->map);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Max Member: %d", c->max_member);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Kick Time: %dh", c->kick_time / 3600);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Check Time: %dh", c->check_time / 3600000);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Connected Members: %d", c->connect_member);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Total Members: %d", c->member_count);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Allies: %d", VECTOR_LENGTH(c->allies));
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ count = 0;
+ for (i = 0; i < VECTOR_LENGTH(c->allies); i++) {
+ struct clan_relationship *ally = &VECTOR_INDEX(c->allies, i);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- - Ally #%d (Id: %d): %s", i + 1, ally->clan_id, ally->constant);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+ count++;
+ }
+
+ if (count == 0) {
+ clif->messagecolor_self(fd, COLOR_DEFAULT, "- - No Allies Found!");
+ }
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- Antagonists: %d", VECTOR_LENGTH(c->antagonists));
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+
+ count = 0;
+ for (i = 0; i < VECTOR_LENGTH(c->antagonists); i++) {
+ struct clan_relationship *antagonist = &VECTOR_INDEX(c->antagonists, i);
+
+ safesnprintf(atcmd_output, sizeof(atcmd_output), "- - Antagonist #%d (Id: %d): %s", i + 1, antagonist->clan_id, antagonist->constant);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, atcmd_output);
+ count++;
+ }
+
+ if (count == 0) {
+ clif->messagecolor_self(fd, COLOR_DEFAULT, "- - No Antagonists Found!");
+ }
+
+ clif->messagecolor_self(fd, COLOR_DEFAULT, "============================");
+ }
+ dbi_destroy(iter);
+ return true;
+}
+
+/**
+ * Clan System: Joins in the given clan
+ */
+ACMD(joinclan)
+{
+ int clan_id;
+
+ if (*message == '\0') {
+ clif->message(fd, "Please enter a Clan ID (usage: @joinclan <clan ID>).");
+ return false;
+ }
+ if (sd->status.clan_id != 0) {
+ clif->messagecolor_self(fd, COLOR_RED, "You are already in a clan.");
+ return false;
+ } else if (sd->status.guild_id != 0) {
+ clif->messagecolor_self(fd, COLOR_RED, "You must leave your guild before enter in a clan.");
+ return false;
+ }
+
+ clan_id = atoi(message);
+ if (clan_id <= 0) {
+ clif->messagecolor_self(fd, COLOR_RED, "Invalid Clan ID.");
+ return false;
+ }
+ if (!clan->join(sd, clan_id)) {
+ clif->messagecolor_self(fd, COLOR_RED, "The clan couldn't be joined.");
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Clan System: Leaves current clan
+ */
+ACMD(leaveclan)
+{
+ if (sd->status.clan_id == 0) {
+ clif->messagecolor_self(fd, COLOR_RED, "You aren't in a clan.");
+ return false;
+ }
+ if (!clan->leave(sd, false)) {
+ clif->messagecolor_self(fd, COLOR_RED, "Failed on leaving clan.");
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Clan System: Reloads clan db
+ */
+ACMD(reloadclans)
+{
+ clan->reload();
+ clif->messagecolor_self(fd, COLOR_DEFAULT, "Clan configuration and database have been reloaded.");
+ return true;
+}
+
+// show camera window or change camera parameters
+ACMD(camerainfo)
+{
+ if (*message == '\0') {
+ clif->camera_showWindow(sd);
+ return true;
+ }
+ float range = 0;
+ float rotation = 0;
+ float latitude = 0;
+ if (sscanf(message, "%15f %15f %15f", &range, &rotation, &latitude) < 3) {
+ clif->message(fd, msg_fd(fd, 452)); // usage @camerainfo range rotation latitude
+ return false;
+ }
+ clif->camera_change(sd, range, rotation, latitude, SELF);
+ return true;
+}
+
+ACMD(refineryui)
+{
+#if PACKETVER_MAIN_NUM >= 20161005 || PACKETVER_RE_NUM >= 20161005 || defined(PACKETVER_ZERO)
+ if (battle_config.enable_refinery_ui == 0) {
+ clif->message(fd, msg_fd(fd, 453));
+ return false;
+ }
+
+ clif->OpenRefineryUI(sd);
+ return true;
+#else
+ clif->message(fd, msg_fd(fd, 453));
+ return false;
+#endif
+}
+
/**
* Fills the reference of available commands in atcommand DBMap
**/
#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL, NULL, true }
#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL, NULL, true }
-void atcommand_basecommands(void) {
+static void atcommand_basecommands(void)
+{
/**
* Command reference list, place the base of your commands here
**/
@@ -9569,10 +10262,12 @@ void atcommand_basecommands(void) {
ACMD_DEF(clearweather),
ACMD_DEF(uptime),
ACMD_DEF(changesex),
+ ACMD_DEF(changecharsex),
ACMD_DEF(mute),
ACMD_DEF(refresh),
ACMD_DEF(refreshall),
ACMD_DEF(identify),
+ ACMD_DEF2("identifyall", identify),
ACMD_DEF(misceffect),
ACMD_DEF(mobsearch),
ACMD_DEF(cleanmap),
@@ -9635,6 +10330,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(homshuffle),
ACMD_DEF(showmobs),
ACMD_DEF(feelreset),
+ ACMD_DEF(hatereset),
ACMD_DEF(auction),
ACMD_DEF(mail),
ACMD_DEF2("noks", ksprotection),
@@ -9662,6 +10358,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(addperm),
ACMD_DEF2("rmvperm", addperm),
ACMD_DEF(unloadnpcfile),
+ ACMD_DEF(reloadnpc),
ACMD_DEF(cart),
ACMD_DEF(cashmount),
ACMD_DEF(join),
@@ -9669,10 +10366,21 @@ void atcommand_basecommands(void) {
ACMD_DEF(fontcolor),
ACMD_DEF(searchstore),
ACMD_DEF(costume),
+ ACMD_DEF2("changedress", costume),
+ ACMD_DEF2("nocosplay", costume),
ACMD_DEF(skdebug),
ACMD_DEF(cddebug),
ACMD_DEF(lang),
ACMD_DEF(bodystyle),
+ ACMD_DEF(cvcoff),
+ ACMD_DEF(cvcon),
+ ACMD_DEF(claninfo),
+ ACMD_DEF(joinclan),
+ ACMD_DEF(leaveclan),
+ ACMD_DEF(reloadclans),
+ ACMD_DEF(setzone),
+ ACMD_DEF(camerainfo),
+ ACMD_DEF(refineryui),
};
int i;
@@ -9691,7 +10399,8 @@ void atcommand_basecommands(void) {
#undef ACMD_DEF
#undef ACMD_DEF2
-bool atcommand_add(char *name, AtCommandFunc func, bool replace) {
+static bool atcommand_add(char *name, AtCommandFunc func, bool replace)
+{
AtCommandInfo* cmd;
nullpo_retr(false, name);
@@ -9714,18 +10423,21 @@ bool atcommand_add(char *name, AtCommandFunc func, bool replace) {
/*==========================================
* Command lookup functions
*------------------------------------------*/
-AtCommandInfo* atcommand_exists(const char* name) {
+static AtCommandInfo *atcommand_exists(const char *name)
+{
return strdb_get(atcommand->db, name);
}
-AtCommandInfo* get_atcommandinfo_byname(const char *name) {
+static AtCommandInfo *get_atcommandinfo_byname(const char *name)
+{
AtCommandInfo *cmd;
if ((cmd = strdb_get(atcommand->db, name)))
return cmd;
return NULL;
}
-const char* atcommand_checkalias(const char *aliasname) {
+static const char *atcommand_checkalias(const char *aliasname)
+{
AliasInfo *alias_info = NULL;
if ((alias_info = (AliasInfo*)strdb_get(atcommand->alias_db, aliasname)) != NULL)
return alias_info->command->command;
@@ -9733,7 +10445,8 @@ const char* atcommand_checkalias(const char *aliasname) {
}
/// AtCommand suggestion
-void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool is_atcmd_cmd) {
+static void atcommand_get_suggestions(struct map_session_data *sd, const char *name, bool is_atcmd_cmd)
+{
struct DBIterator *atcommand_iter, *alias_iter;
AtCommandInfo* command_info = NULL;
AliasInfo* alias_info = NULL;
@@ -9814,10 +10527,11 @@ void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bo
* @retval true if the message was recognized as atcommand.
* @retval false if the message should be considered a non-command message.
*/
-bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked)
+static bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked)
{
char params[100], command[100];
char output[CHAT_SIZE_MAX];
+ bool logCommand;
// Reconstructed message
char atcmd_msg[CHAT_SIZE_MAX];
@@ -9851,6 +10565,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
clif->message(fd, msg_fd(fd,143));
return false;
}
+ if (sd->block_action.commands) // *pcblock script command
+ return false;
}
if (*message == atcommand->char_symbol)
@@ -9883,7 +10599,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
return true;
}
- ssd = map->nick2sd(charname);
+ ssd = map->nick2sd(charname, true);
if (ssd == NULL) {
sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found.
clif->message(fd, output);
@@ -9916,6 +10632,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
&& (
(is_atcommand && pc_get_group_level(sd) >= binding->group_lv)
|| (!is_atcommand && pc_get_group_level(sd) >= binding->group_lv_char)
+ || (is_atcommand && binding->at_groups[pcg->get_idx(sd->group)] > 0)
+ || (!is_atcommand && binding->char_groups[pcg->get_idx(sd->group)] > 0)
)
) {
if (binding->log) /* log only if this command should be logged [Ind/Hercules] */
@@ -9959,6 +10677,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
}
}
+ logCommand = info->log;
//Attempt to use the command
if ((info->func(fd, ssd, command, params,info) != true)) {
#ifdef AUTOTRADE_PERSISTENCY
@@ -9970,7 +10689,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
return true;
}
- if (info->log) /* log only if this command should be logged [Ind/Hercules] */
+ // info->log cant be used here, because info can be freed [4144]
+ if (logCommand) /* log only if this command should be logged [Ind/Hercules] */
logs->atcommand(sd, is_atcommand ? atcmd_msg : message);
return true;
@@ -9979,7 +10699,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
/*==========================================
*
*------------------------------------------*/
-void atcommand_config_read(const char* config_filename) {
+static void atcommand_config_read(const char *config_filename)
+{
struct config_t atcommand_config;
struct config_setting_t *aliases = NULL, *help = NULL, *nolog = NULL;
const char *symbol = NULL;
@@ -10118,7 +10839,7 @@ static inline int atcommand_command_type2idx(AtCommandType type)
* Loads permissions for groups to use commands.
*
*/
-void atcommand_db_load_groups(GroupSettings **groups, struct config_setting_t **commands_, size_t sz)
+static void atcommand_db_load_groups(GroupSettings **groups, struct config_setting_t **commands_, size_t sz)
{
struct DBIterator *iter = db_iterator(atcommand->db);
AtCommandInfo *atcmd;
@@ -10178,37 +10899,44 @@ void atcommand_db_load_groups(GroupSettings **groups, struct config_setting_t **
return;
}
-bool atcommand_can_use(struct map_session_data *sd, const char *command) {
- AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
+static bool atcommand_can_use(struct map_session_data *sd, const char *command)
+{
+ AtCommandInfo *acmd_d;
+ struct atcmd_binding_data *bcmd_d;
nullpo_retr(false, sd);
- nullpo_retr(false, command);
- if (info == NULL)
- return false;
- if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
- (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
- return true;
+ if ((acmd_d = atcommand->get_info_byname(atcommand->check_alias(command + 1))) != NULL) {
+ return ((*command == atcommand->at_symbol && acmd_d->at_groups[pcg->get_idx(sd->group)] > 0) ||
+ (*command == atcommand->char_symbol && acmd_d->char_groups[pcg->get_idx(sd->group)] > 0));
+ } else if ((bcmd_d = atcommand->get_bind_byname(atcommand->check_alias(command + 1))) != NULL) {
+ return ((*command == atcommand->at_symbol && bcmd_d->at_groups[pcg->get_idx(sd->group)] > 0) ||
+ (*command == atcommand->char_symbol && bcmd_d->char_groups[pcg->get_idx(sd->group)] > 0));
}
return false;
}
-bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type) {
- AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command));
+
+static bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type)
+{
+ AtCommandInfo *acmd_d;
+ struct atcmd_binding_data *bcmd_d;
nullpo_retr(false, sd);
- nullpo_retr(false, command);
- if (info == NULL)
- return false;
- if ((type == COMMAND_ATCOMMAND && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
- (type == COMMAND_CHARCOMMAND && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
- return true;
+ if ((acmd_d = atcommand->get_info_byname(atcommand->check_alias(command))) != NULL) {
+ return ((type == COMMAND_ATCOMMAND && acmd_d->at_groups[pcg->get_idx(sd->group)] > 0) ||
+ (type == COMMAND_CHARCOMMAND && acmd_d->char_groups[pcg->get_idx(sd->group)] > 0));
+ } else if ((bcmd_d = atcommand->get_bind_byname(atcommand->check_alias(command))) != NULL) {
+ return ((type == COMMAND_ATCOMMAND && bcmd_d->at_groups[pcg->get_idx(sd->group)] > 0) ||
+ (type == COMMAND_CHARCOMMAND && bcmd_d->char_groups[pcg->get_idx(sd->group)] > 0));
}
return false;
}
-bool atcommand_hp_add(char *name, AtCommandFunc func) {
+
+static bool atcommand_hp_add(char *name, AtCommandFunc func)
+{
/* if commands are added after group permissions are thrown in, they end up with no permissions */
/* so we restrict commands to be linked in during boot */
if( core->runflag == MAPSERVER_ST_RUNNING ) {
@@ -10222,7 +10950,7 @@ bool atcommand_hp_add(char *name, AtCommandFunc func) {
/**
* @see DBApply
*/
-int atcommand_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
+static int atcommand_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
AtCommandInfo *cmd = DB->data2ptr(data);
aFree(cmd->at_groups);
@@ -10232,7 +10960,8 @@ int atcommand_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
return 0;
}
-void atcommand_db_clear(void) {
+static void atcommand_db_clear(void)
+{
if( atcommand->db != NULL ) {
atcommand->db->destroy(atcommand->db, atcommand->cmd_db_clear_sub);
atcommand->db = NULL;
@@ -10243,7 +10972,8 @@ void atcommand_db_clear(void) {
}
}
-void atcommand_doload(void) {
+static void atcommand_doload(void)
+{
if( core->runflag >= MAPSERVER_ST_RUNNING )
atcommand->cmd_db_clear();
if( atcommand->db == NULL )
@@ -10254,12 +10984,14 @@ void atcommand_doload(void) {
atcommand->config_read(map->ATCOMMAND_CONF_FILENAME);
}
-void atcommand_expand_message_table(void) {
+static void atcommand_expand_message_table(void)
+{
RECREATE(atcommand->msg_table, char **, ++atcommand->max_message_table);
CREATE(atcommand->msg_table[atcommand->max_message_table - 1], char *, MAX_MSG);
}
-void do_init_atcommand(bool minimal) {
+static void do_init_atcommand(bool minimal)
+{
if (minimal)
return;
@@ -10270,13 +11002,18 @@ void do_init_atcommand(bool minimal) {
atcommand->doload();
}
-void do_final_atcommand(void) {
+static void do_final_atcommand(void)
+{
atcommand->cmd_db_clear();
}
-void atcommand_defaults(void) {
+void atcommand_defaults(void)
+{
atcommand = &atcommand_s;
+ atcommand->atcmd_output = &atcmd_output;
+ atcommand->atcmd_player_name = &atcmd_player_name;
+
atcommand->db = NULL;
atcommand->alias_db = NULL;
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 0e7895825..f3a5155ab 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,9 +21,11 @@
#ifndef MAP_ATCOMMAND_H
#define MAP_ATCOMMAND_H
+#include "map/mapdefines.h"
#include "map/pc_groups.h"
#include "common/hercules.h"
#include "common/db.h"
+#include "common/mmo.h"
#include <stdarg.h>
@@ -39,7 +41,7 @@ struct config_setting_t;
* Defines
**/
#define ATCOMMAND_LENGTH 50
-#define MAX_MSG 1500
+#define MAX_MSG 1520
#define msg_txt(idx) atcommand->msg(idx)
#define msg_sd(sd,msg_number) atcommand->msgsd((sd),(msg_number))
#define msg_fd(fd,msg_number) atcommand->msgfd((fd),(msg_number))
@@ -52,6 +54,16 @@ typedef enum {
COMMAND_CHARCOMMAND = 2,
} AtCommandType;
+/** @fakename display option flags **/
+enum fakename_option_flag {
+ FAKENAME_OPTION_NONE = 0x00,
+ FAKENAME_OPTION_SHOW_PARTYNAME = 0x01,
+ FAKENAME_OPTION_SHOW_GUILDNAME = 0x02,
+ FAKENAME_OPTION_SHOW_GUILDPOSITION = 0x04,
+ FAKENAME_OPTION_SHOW_CLANPOSITION = 0x08,
+ FAKENAME_OPTION_SHOW_TITLE = 0x10
+};
+
/**
* Typedef
**/
@@ -79,8 +91,10 @@ struct AtCommandInfo {
struct atcmd_binding_data {
char command[ATCOMMAND_LENGTH];
char npc_event[ATCOMMAND_LENGTH];
- int group_lv;
- int group_lv_char;
+ int group_lv; // DEPRECATED
+ int group_lv_char; // DEPRECATED
+ char *at_groups; // quick @commands "can-use" lookup
+ char *char_groups; // quick @charcommands "can-use" lookup
bool log;
};
@@ -88,6 +102,8 @@ struct atcmd_binding_data {
* Interface
**/
struct atcommand_interface {
+ char (*atcmd_output)[CHAT_SIZE_MAX];
+ char (*atcmd_player_name)[NAME_LENGTH];
unsigned char at_symbol;
unsigned char char_symbol;
/* atcommand binding */
@@ -152,7 +168,8 @@ void atcommand_defaults(void);
HPShared struct atcommand_interface *atcommand;
/* stay here */
-#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) __attribute__((nonnull (2, 3, 4, 5))); \
- static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info)
+#define ACMD(x) \
+ static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) __attribute__((nonnull (2, 3, 4, 5))); \
+ static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info)
#endif /* MAP_ATCOMMAND_H */
diff --git a/src/map/battle.c b/src/map/battle.c
index 5ca54bf82..c8cd71b94 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,11 +20,11 @@
*/
#define HERCULES_CORE
-#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT
+#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT
#include "battle.h"
#include "map/battleground.h"
-#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/elemental.h"
#include "map/guild.h"
@@ -41,6 +41,7 @@
#include "map/status.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/ers.h"
#include "common/memmgr.h"
#include "common/nullpo.h"
@@ -58,7 +59,7 @@
#include <string.h>
struct Battle_Config battle_config;
-struct battle_interface battle_s;
+static struct battle_interface battle_s;
struct battle_interface *battle;
/**
@@ -67,7 +68,7 @@ struct battle_interface *battle;
* @param bl The bl to check.
* @return The current/last skill ID.
*/
-int battle_getcurrentskill(struct block_list *bl)
+static int battle_getcurrentskill(struct block_list *bl)
{
const struct unit_data *ud;
@@ -90,7 +91,8 @@ int battle_getcurrentskill(struct block_list *bl)
/*==========================================
* Get random targeting enemy
*------------------------------------------*/
-int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
+static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
+{
struct block_list **bl_list;
struct unit_data *ud;
int target_id;
@@ -118,7 +120,8 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
return 0;
}
-struct block_list* battle_gettargeted(struct block_list *target) {
+static struct block_list *battle_gettargeted(struct block_list *target)
+{
struct block_list *bl_list[24];
int c = 0;
nullpo_retr(NULL, target);
@@ -133,7 +136,8 @@ struct block_list* battle_gettargeted(struct block_list *target) {
}
//Returns the id of the current targeted character of the passed bl. [Skotlex]
-int battle_gettarget(struct block_list* bl) {
+static int battle_gettarget(struct block_list *bl)
+{
nullpo_ret(bl);
switch (bl->type) {
@@ -148,7 +152,8 @@ int battle_gettarget(struct block_list* bl) {
return 0;
}
-int battle_getenemy_sub(struct block_list *bl, va_list ap) {
+static int battle_getenemy_sub(struct block_list *bl, va_list ap)
+{
struct block_list **bl_list;
struct block_list *target;
int *c;
@@ -176,7 +181,8 @@ int battle_getenemy_sub(struct block_list *bl, va_list ap) {
}
// Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
-struct block_list* battle_getenemy(struct block_list *target, int type, int range) {
+static struct block_list *battle_getenemy(struct block_list *target, int type, int range)
+{
struct block_list *bl_list[24];
int c = 0;
@@ -192,7 +198,9 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang
return bl_list[rnd()%c];
}
-int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
+
+static int battle_getenemyarea_sub(struct block_list *bl, va_list ap)
+{
struct block_list **bl_list, *src;
int *c, ignore_id;
@@ -222,7 +230,8 @@ int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
}
// Pick a random enemy
-struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id) {
+static struct block_list *battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id)
+{
struct block_list *bl_list[24];
int c = 0;
@@ -238,7 +247,8 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
return bl_list[rnd()%c];
}
-int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
+static int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data)
+{
struct delay_damage *dat = (struct delay_damage *)data;
if ( dat ) {
@@ -279,7 +289,8 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) {
+static int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects)
+{
struct delay_damage *dat;
struct status_change *sc;
struct block_list *d_tbl = NULL;
@@ -327,7 +338,8 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct
return 0;
}
-int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
+
+static int battle_attr_ratio(int atk_elem, int def_type, int def_lv)
{
if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX)
return 100;
@@ -343,7 +355,7 @@ int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
* Added passing of the chars so that the status changes can affect it. [Skotlex]
* Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
*------------------------------------------*/
-int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv)
+static int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage, int atk_elem, int def_type, int def_lv)
{
struct status_change *sc=NULL, *tsc=NULL;
int ratio;
@@ -437,8 +449,10 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
return damage + (damage * (ratio - 100) / 100);
}
+// [malufett]
//FIXME: Missing documentation for flag, flag2
-int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett]
+static int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2)
+{
#ifdef RENEWAL
int64 damage, eatk = 0;
struct status_change *sc;
@@ -510,6 +524,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
return 0;
#endif
}
+
/*==========================================
* Calculates the standard damage of a normal attack assuming it hits,
* it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex]
@@ -524,7 +539,8 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
*/
/* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */
// FIXME: Missing documentation for flag2
-int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) {
+static int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2)
+{
int64 damage;
struct status_data *st = status->get_status_data(src);
struct status_change *sc = status->get_sc(src);
@@ -561,7 +577,9 @@ int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uin
return damage;
}
-int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) {
+
+static int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag)
+{
unsigned int atkmin=0, atkmax=0;
short type = 0;
int64 damage = 0;
@@ -642,7 +660,8 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st
return damage;
}
-int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore){
+static int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore)
+{
//SizeFix only for players
nullpo_retr(damage, sd);
if (!(sd->special_state.no_sizefix || (ignore)))
@@ -654,7 +673,8 @@ int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, i
* Passive skill damages increases
*------------------------------------------*/
// FIXME: type is undocumented
-int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) {
+static int64 battle_addmastery(struct map_session_data *sd, struct block_list *target, int64 dmg, int type)
+{
int64 damage;
struct status_data *st = status->get_status_data(target);
int weapon, skill_lv;
@@ -692,6 +712,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
#ifdef RENEWAL
if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
damage += (skill_lv * 3);
+ FALLTHROUGH
#endif
case W_DAGGER:
if((skill_lv = pc->checkskill(sd,SM_SWORD)) > 0)
@@ -736,6 +757,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
if((skill_lv = pc->checkskill(sd,TK_RUN)) > 0)
damage += (skill_lv * 10);
// No break, fall through to Knuckles
+ FALLTHROUGH
case W_KNUCKLE:
if((skill_lv = pc->checkskill(sd,MO_IRONHAND)) > 0)
damage += (skill_lv * 3);
@@ -764,7 +786,8 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
/*==========================================
* Calculates ATK masteries.
*------------------------------------------*/
-int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon) {
+static int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon)
+{
int skill2_lv, i;
struct status_change *sc;
struct map_session_data *sd;
@@ -872,7 +895,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
}
#else
if( skill_id != ASC_BREAKER && weapon ) // Adv Katar Mastery is does not applies to ASC_BREAKER, but other masteries DO apply >_>
- if( sd->status.weapon == W_KATAR && (skill2_lv=pc->checkskill(sd,ASC_KATAR)) > 0 )
+ if (sd->weapontype == W_KATAR && (skill2_lv=pc->checkskill(sd,ASC_KATAR)) > 0)
damage += damage * (10 + 2 * skill2_lv) / 100;
#endif
@@ -889,7 +912,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
damage += damage * ratio / 100;
}
- if( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ){
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_ARCH_BISHOP) {
if((skill2_lv = pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
damage += damage * skill2_lv / 100;
@@ -898,14 +921,16 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
return damage;
}
-void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int64 *damage, int *div, bool *left, bool *weapon) {
+static void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int64 *damage, int *div, bool *left, bool *weapon)
+{
}
/*==========================================
* Elemental attribute fix.
*------------------------------------------*/
// FIXME: flag is undocumented
-int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){
+static int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag)
+{
struct status_data *tstatus;
nullpo_ret(src);
@@ -950,7 +975,8 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint
#endif
return damage;
}
-int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 damage, int s_ele, int nk, int flag) {
+static int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 damage, int s_ele, int nk, int flag)
+{
#ifdef RENEWAL
struct map_session_data *tsd;
struct status_data *sstatus;
@@ -981,6 +1007,7 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64
#endif
return damage;
}
+
/*==========================================
* Calculates card bonuses damage adjustments.
* cflag(cardfix flag):
@@ -988,14 +1015,11 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64
* &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON).
*------------------------------------------*/
// FIXME: wflag is undocumented
-int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){
+static int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag)
+{
struct map_session_data *sd, *tsd;
-#ifdef RENEWAL
- short cardfix = 100;
-#else
- short cardfix = 1000;
-#endif
- short t_class, s_class, s_race2, t_race2;
+ int cardfix = 1000;
+ int t_class, s_class, s_race2, t_race2;
struct status_data *sstatus, *tstatus;
int i;
@@ -1070,24 +1094,14 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
if( tsd->sc.data[SC_PROTECT_MDEF] )
cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_MDEF]->val1 ) / 100;
}
-#ifdef RENEWAL
- if ( cardfix != 100 )
- damage += damage * (cardfix - 100) / 100;
-#else
if ( cardfix != 1000 )
damage = damage * cardfix / 1000;
-#endif
break;
case BF_WEAPON:
t_race2 = status->get_race2(target);
if( cflag&2 ){
if( sd && !(nk&NK_NO_CARDFIX_ATK) ){
- short cardfix_ =
-#ifdef RENEWAL
- 100;
-#else
- 1000;
-#endif
+ int cardfix_ = 1000;
if( sd->state.arrow_atk ){
cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race]) / 100;
if( !(nk&NK_NO_ELEFIX) ){
@@ -1187,16 +1201,11 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
#ifndef RENEWAL
if( wflag&BF_LONG )
cardfix = cardfix * (100 + sd->bonus.long_attack_atk_rate) / 100;
+#endif
if( (cflag&1) && cardfix_ != 1000 )
damage = damage * cardfix_ / 1000;
else if( cardfix != 1000 )
damage = damage * cardfix / 1000;
-#else
- if ((cflag & 1) && cardfix_ != 100)
- damage += damage * (cardfix_ - 100) / 100;
- else if (cardfix != 100)
- damage += damage * (cardfix - 100) / 100;
-#endif
}
}else{
// Target side
@@ -1246,13 +1255,8 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
#endif
if( tsd->sc.data[SC_PROTECT_DEF] )
cardfix = cardfix * (100 - tsd->sc.data[SC_PROTECT_DEF]->val1) / 100;
-#ifdef RENEWAL
- if ( cardfix != 100 )
- damage += damage * (cardfix - 100) / 100;
-#else
if( cardfix != 1000 )
damage = damage * cardfix / 1000;
-#endif
}
}
break;
@@ -1284,13 +1288,8 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
cardfix = cardfix*(100 - tsd->subsize[sstatus->size]) / 100;
cardfix = cardfix*(100 - tsd->subrace2[s_race2]) / 100;
cardfix = cardfix * (100 - tsd->bonus.misc_def_rate) / 100;
-#ifdef RENEWAL
- if ( cardfix != 100 )
- damage += damage * (cardfix - 100) / 100;
-#else
if ( cardfix != 1000 )
damage = damage * cardfix / 1000;
-#endif
}
break;
}
@@ -1306,7 +1305,8 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
* &4 - tdef(Total defense reduction)
*------------------------------------------*/
// TODO: Add an enum for flag
-int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){
+static int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef)
+{
struct status_data *sstatus, *tstatus;
struct map_session_data *sd, *tsd;
struct status_change *sc, *tsc;
@@ -1365,24 +1365,28 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
#endif
}
- if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
- unsigned char target_count; //256 max targets should be a sane max
- target_count = unit->counttargeted(target);
- if(target_count >= battle_config.vit_penalty_count) {
- if(battle_config.vit_penalty_type == 1) {
- if( !tsc || !tsc->data[SC_STEELBODY] )
- def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
- def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
- } else { //Assume type 2
- if( !tsc || !tsc->data[SC_STEELBODY] )
- def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
- def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ if (battle_config.vit_penalty_type != 0 && (battle_config.vit_penalty_target & target->type) != 0) {
+ int target_count = unit->counttargeted(target);
+ if (target_count >= battle_config.vit_penalty_count) {
+ int penalty = (target_count - (battle_config.vit_penalty_count - 1)) * battle_config.vit_penalty_num;
+ if (battle_config.vit_penalty_type == 1) {
+ if (tsc == NULL || tsc->data[SC_STEELBODY] == NULL)
+ def1 = def1 * (100 - penalty) / 100;
+ def2 = def2 * (100 - penalty) / 100;
+ } else { // Assume type 2
+ if (tsc == NULL || tsc->data[SC_STEELBODY] == NULL)
+ def1 -= penalty;
+ def2 -= penalty;
}
}
#ifndef RENEWAL
- if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
+ if (skill_id == AM_ACIDTERROR)
+ def1 = 0; // Acid Terror ignores only armor defense. [Skotlex]
#endif
- if(def2 < 1) def2 = 1;
+ if (def1 < 0)
+ def1 = 0;
+ if (def2 < 1)
+ def2 = 1;
}
//Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
if (tsd) {
@@ -1494,7 +1498,8 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
}
// Minstrel/Wanderer number check for chorus skills.
-int battle_calc_chorusbonus(struct map_session_data *sd) {
+static int battle_calc_chorusbonus(struct map_session_data *sd)
+{
int members = 0;
if (!sd || !sd->status.party_id)
@@ -1510,7 +1515,8 @@ int battle_calc_chorusbonus(struct map_session_data *sd) {
}
// FIXME: flag is undocumented
-int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){
+static int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag)
+{
int i;
struct status_change *sc, *tsc;
struct map_session_data *sd, *tsd;
@@ -1663,8 +1669,29 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
#endif
/**
- * Arch Bishop
- **/
+ * Summoner
+ **/
+ case SU_BITE:
+ skillratio += 100;
+ break;
+ case SU_SCRATCH:
+ skillratio += -50 + 50 * skill_lv;
+ break;
+ case SU_SCAROFTAROU:
+ skillratio += -100 + 100 * skill_lv;
+ break;
+ case SU_PICKYPECK:
+ case SU_PICKYPECK_DOUBLE_ATK:
+ skillratio += 100 + 100 * skill_lv;
+ if ((status_get_max_hp(target) / 100) <= 50)
+ skillratio *= 2;
+ break;
+ case SU_LUNATICCARROTBEAT:
+ skillratio += 100 + 100 * skill_lv;
+ break;
+ /**
+ * Arch Bishop
+ **/
case AB_JUDEX:
skillratio = 300 + 20 * skill_lv;
RE_LVL_DMOD(100);
@@ -1883,6 +1910,12 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
pc->del_charm(sd, sd->charm_count, sd->charm_type);
}
break;
+ case SU_SV_STEMSPEAR:
+ skillratio += 600;
+ break;
+ case SU_CN_METEOR:
+ skillratio += 100 + 100 * skill_lv;
+ break;
default:
battle->calc_skillratio_magic_unknown(&attack_type, src, target, &skill_id, &skill_lv, &skillratio, &flag);
break;
@@ -2002,7 +2035,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 + 100 * skill_lv + 100 * (skill_lv / 2);
break;
case RG_BACKSTAP:
- if( sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty )
+ if (sd != NULL && sd->weapontype == W_BOW && battle_config.backstab_bow_penalty)
skillratio += (200 + 40 * skill_lv) / 2;
else
skillratio += 200 + 40 * skill_lv;
@@ -2023,10 +2056,10 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case CR_HOLYCROSS:
{
int ratio = 35 * skill_lv;
- #ifdef RENEWAL
- if(sd && sd->status.weapon == W_2HSPEAR)
- ratio *= 2;
- #endif
+#ifdef RENEWAL
+ if (sd != NULL && sd->weapontype == W_2HSPEAR)
+ ratio *= 2;
+#endif
skillratio += ratio;
break;
}
@@ -2431,7 +2464,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_OVERBRAND_PLUSATK:
- skillratio = 200 * skill_lv + rnd_value( 10, 100);
+ skillratio = 200 * skill_lv + rnd->value(10, 100);
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
@@ -2684,7 +2717,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 2*sc->data[SC_TRUESIGHT]->val1;
if( sc->data[SC_LKCONCENTRATION] )
skillratio += sc->data[SC_LKCONCENTRATION]->val2;
- if( sd && sd->status.weapon == W_KATAR && (i=pc->checkskill(sd,ASC_KATAR)) > 0 )
+ if (sd != NULL && sd->weapontype == 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] ){
@@ -2705,10 +2738,12 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
return skillratio;
}
-void battle_calc_skillratio_magic_unknown(int *attack_type, struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *skillratio, int *flag) {
+static void battle_calc_skillratio_magic_unknown(int *attack_type, struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *skillratio, int *flag)
+{
}
-void battle_calc_skillratio_weapon_unknown(int *attack_type, struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *skillratio, int *flag) {
+static void battle_calc_skillratio_weapon_unknown(int *attack_type, struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *skillratio, int *flag)
+{
}
/*==========================================
@@ -2716,7 +2751,8 @@ void battle_calc_skillratio_weapon_unknown(int *attack_type, struct block_list *
* 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) {
+static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv)
+{
struct map_session_data *s_sd, *t_sd;
struct status_change *s_sc, *sc;
struct status_change_entry *sce;
@@ -2840,7 +2876,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) {
// {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2
int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (t_sd ? t_sd->status.job_level / 5 : 0)) / 2;
- status->heal(bl, 0, sp, 3);
+ status->heal(bl, 0, sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
d->dmg_lv = ATK_BLOCK;
return 0;
}
@@ -2993,7 +3029,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
status_change_end(bl,SC_DEEP_SLEEP,INVALID_TIMER);
}
if( s_sd && t_sd && sc->data[SC_COLD] && flag&BF_WEAPON ){
- switch(s_sd->status.weapon){
+ switch (s_sd->weapontype) {
case W_MACE:
case W_2HMACE:
case W_1HAXE:
@@ -3004,6 +3040,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
case W_WHIP:
if(!t_sd->state.arrow_atk)
break;
+ FALLTHROUGH
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
@@ -3064,6 +3101,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
damage -= 50 * damage / 100;//50% reduction to physical ranged attacks
}
+ if (sc->data[SC_SU_STOOP])
+ damage -= damage * 90 / 100;
+
// Compressed code, fixed by map.h [Epoque]
if (src->type == BL_MOB) {
const struct mob_data *md = BL_UCCAST(BL_MOB, src);
@@ -3131,7 +3171,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&(BF_SHORT|BF_WEAPON) && damage > 0 ) {
sce->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
if( src->type == BL_PC ) {
- if (s_sd && s_sd->status.weapon != W_BOW)
+ if (s_sd != NULL && s_sd->weapontype != W_BOW)
skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF);
} else
skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF);
@@ -3172,18 +3212,30 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
}
+ if ((sce = sc->data[SC_TUNAPARTY]) != NULL && damage > 0) {
+ clif->specialeffect(bl, 336, AREA);
+ sce->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+ if (sce->val2 >= 0) {
+ damage = 0;
+ } else {
+ damage = -sce->val2;
+ }
+ if (sce->val2 <= 0) {
+ status_change_end(bl, SC_TUNAPARTY, INVALID_TIMER);
+ }
+ }
+
if( sc->data[SC_MEIKYOUSISUI] && rnd()%100 < 40 ) // custom value
damage = 0;
if (!damage) return 0;
if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) {
- int dx[8]={0,-1,-1,-1,0,1,1,1};
- int dy[8]={1,1,0,-1,-1,-1,0,1};
- uint8 dir = map->calc_dir(bl, src->x, src->y);
- if( unit->movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) {
- clif->slide(bl,src->x-dx[dir],src->y-dy[dir]);
- unit->setdir(bl, dir);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ if (unit->movepos(bl, src->x - dirx[dir], src->y - diry[dir], 1, 1)) {
+ clif->slide(bl, src->x - dirx[dir], src->y - diry[dir]);
+ unit->set_dir(bl, dir);
}
d->dmg_lv = ATK_DEF;
status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER);
@@ -3194,7 +3246,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
//(since battle_drain is strictly for players currently)
if ((sce=sc->data[SC_HAMI_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
rnd()%100 < sce->val3)
- status->heal(src, damage*sce->val4/100, 0, 3);
+ status->heal(src, damage*sce->val4/100, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON
&& rnd()%100 < sce->val2 && sc->fv_counter <= sce->val3 )
@@ -3263,30 +3315,8 @@ 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 && t_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 don't worry about it */
- case HW_GRAVITATION:
- case NJ_ZENYNAGE:
- case KO_MUCHANAGE:
- break;
- default:
- if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
- if (flag&BF_WEAPON)
- damage = damage * map->list[bl->m].weapon_damage_rate / 100;
- if (flag&BF_MAGIC)
- damage = damage * map->list[bl->m].magic_damage_rate / 100;
- if (flag&BF_MISC)
- damage = damage * map->list[bl->m].misc_damage_rate / 100;
- } else { //Normal attacks get reductions based on range.
- if (flag & BF_SHORT)
- damage = damage * map->list[bl->m].short_damage_rate / 100;
- if (flag & BF_LONG)
- damage = damage * map->list[bl->m].long_damage_rate / 100;
- }
- if(!damage) damage = 1;
- break;
- }
+ if (damage && t_sd && bl->type == BL_PC) {
+ damage = battle->calc_pc_damage(src, bl, d, damage, skill_id, skill_lv);
}
if(battle_config.skill_min_damage && damage > 0 && damage < div_)
@@ -3331,11 +3361,43 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return damage;
}
+static int64 battle_calc_pc_damage(struct block_list *src, struct block_list *bl, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv)
+{
+ int flag = d->flag;
+
+ switch (skill_id) {
+ //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:
+ break;
+ default:
+ if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
+ if (flag & BF_WEAPON)
+ damage = damage * map->list[bl->m].weapon_damage_rate / 100;
+ if (flag & BF_MAGIC)
+ damage = damage * map->list[bl->m].magic_damage_rate / 100;
+ if (flag & BF_MISC)
+ damage = damage * map->list[bl->m].misc_damage_rate / 100;
+ } else { //Normal attacks get reductions based on range.
+ if (flag & BF_SHORT)
+ damage = damage * map->list[bl->m].short_damage_rate / 100;
+ if (flag & BF_LONG)
+ damage = damage * map->list[bl->m].long_damage_rate / 100;
+ }
+ if (!damage)
+ damage = 1;
+ break;
+ }
+ return damage;
+}
+
/*==========================================
* Calculates BG related damage adjustments.
*------------------------------------------*/
// FIXME: flag is undocumented
-int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) {
+static int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag)
+{
if (!damage)
return 0;
@@ -3355,7 +3417,8 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64
* Calculates GVG related damage adjustments.
*------------------------------------------*/
// FIXME: flag is undocumented
-int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) {
+static int64 battle_calc_gvg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag)
+{
struct mob_data* md = BL_CAST(BL_MOB, bl);
int class_ = status->get_class(bl);
@@ -3403,11 +3466,6 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
case NC_SELFDESTRUCTION:
break;
default:
- /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka]
- if (md && md->guardian_data) {
- damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
- }
- */
break;
}
return damage;
@@ -3416,7 +3474,8 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
/*==========================================
* HP/SP drain calculation
*------------------------------------------*/
-int battle_calc_drain(int64 damage, int rate, int per) {
+static int battle_calc_drain(int64 damage, int rate, int per)
+{
int64 diff = 0;
if (per && rnd()%1000 < rate) {
@@ -3434,7 +3493,7 @@ int battle_calc_drain(int64 damage, int rate, int per) {
/*==========================================
* Consumes ammo for the given skill.
*------------------------------------------*/
-void battle_consume_ammo(struct map_session_data *sd, int skill_id, int lv)
+static void battle_consume_ammo(struct map_session_data *sd, int skill_id, int lv)
{
int qty=1;
@@ -3454,7 +3513,8 @@ void battle_consume_ammo(struct map_session_data *sd, int skill_id, int lv)
}
//Skill Range Criteria
-int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) {
+static int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv)
+{
nullpo_retr(BF_SHORT, src);
nullpo_retr(BF_SHORT, target);
@@ -3478,7 +3538,9 @@ int battle_range_type(struct block_list *src, struct block_list *target, uint16
return BF_SHORT;
return BF_LONG;
}
-int battle_adjust_skill_damage(int m, unsigned short skill_id) {
+
+static int battle_adjust_skill_damage(int m, unsigned short skill_id)
+{
if( map->list[m].skill_count ) {
int i;
ARR_FIND(0, map->list[m].skill_count, i, map->list[m].skills[i]->skill_id == skill_id );
@@ -3491,7 +3553,8 @@ int battle_adjust_skill_damage(int m, unsigned short skill_id) {
return 0;
}
-int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
+static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
+{
int i;
nullpo_ret(sd);
if (!sd->skillblown[0].id)
@@ -3503,17 +3566,17 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
}
return 0;
}
+
//For quick div adjustment.
#define damage_div_fix(dmg, div) do { if ((div) > 1) (dmg)*=(div); else if ((div) < 0) (div)*=-1; } while(0)
/*==========================================
* battle_calc_magic_attack [DracoRPG]
*------------------------------------------*/
// FIXME: mflag is undocumented
-struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) {
+static struct Damage battle_calc_magic_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int mflag)
+{
int nk;
short s_ele = 0;
- unsigned int skillratio = 100; //Skill dmg modifiers.
-
struct map_session_data *sd = NULL;
struct status_change *sc;
struct Damage ad;
@@ -3665,7 +3728,14 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Damage calculation from iRO wiki. [Jobbie]
ad.damage = status->get_lv(src) * 10 + sstatus->int_;
break;
+ /**
+ * Summoner
+ */
+ case SU_SV_ROOTTWIST_ATK:
+ ad.damage = 100;
+ break;
default: {
+ unsigned int skillratio = 100; //Skill dmg modifiers.
MATK_ADD( status->get_matk(src, 2) );
#ifdef RENEWAL
ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
@@ -3699,10 +3769,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Constant/misc additions from skills
if (skill_id == WZ_FIREPILLAR)
MATK_ADD(100+50*skill_lv);
- if( sd && ( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ) &&
- (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
- (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
- MATK_ADDRATE(i);
+ if (sd != NULL && (sd->job & MAPID_THIRDMASK) == MAPID_ARCH_BISHOP) {
+ int eucharistica_level = pc->checkskill(sd,AB_EUCHARISTICA);
+ if (eucharistica_level > 0 && (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK))
+ MATK_ADDRATE(eucharistica_level);
+ }
}
}
#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE
@@ -3840,7 +3911,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
* Calculate Misc damage for skill_id
*------------------------------------------*/
// FIXME: mflag is undocumented
-struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) {
+static struct Damage battle_calc_misc_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int mflag)
+{
int temp;
short i, nk;
short s_ele;
@@ -4143,16 +4215,16 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
hitrate = 80; //Default hitrate
#endif
- if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
- unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit->counttargeted(target);
- if(attacker_count >= battle_config.agi_penalty_count)
- {
+ if (battle_config.agi_penalty_type != 0 && (battle_config.agi_penalty_target & target->type) != 0) {
+ int attacker_count = unit->counttargeted(target);
+ if (attacker_count >= battle_config.agi_penalty_count) {
+ int penalty = (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num;
if (battle_config.agi_penalty_type == 1)
- flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
+ flee = flee * (100 - penalty) / 100;
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;
+ flee -= penalty;
+ if (flee < 1)
+ flee = 1;
}
}
@@ -4240,7 +4312,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
switch( skill_id ) {
case RA_FIRINGTRAP:
case RA_ICEBOUNDTRAP:
- if( md.damage == 1 ) break;
+ if (md.damage == 1)
+ break;
+ FALLTHROUGH
case RA_CLUSTERBOMB:
{
struct Damage wd;
@@ -4257,19 +4331,21 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break;
}
+ battle->reflect_trap(target, src, &md, skill_id);
+
return md;
}
-void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *mflag, struct Damage *md) {
+static void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int *mflag, struct Damage *md)
+{
}
/*==========================================
* battle_calc_weapon_attack (by Skotlex)
*------------------------------------------*/
// FIXME: wflag is undocumented
-struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag)
+static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int wflag)
{
- unsigned int skillratio = 100; //Skill dmg modifiers.
short temp=0;
short s_ele, s_ele_;
int i, nk;
@@ -4505,8 +4581,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(!skill_id) {
//Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
- if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
- {
+ if (sd && sd->weapontype1 == W_FIST && sd->weapontype2 != W_FIST) {
flag.rh=0;
flag.lh=1;
}
@@ -4541,16 +4616,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.div_ = 5;
break;
}
+ FALLTHROUGH
case 4:
if( chance < 7){// 6 % chance to attack 4 times.
wd.div_ = 4;
break;
}
+ FALLTHROUGH
case 3:
if( chance < 10){// 9 % chance to attack 3 times.
wd.div_ = 3;
break;
}
+ FALLTHROUGH
case 2:
case 1:
if( chance < 13){// 12 % chance to attack 2 times.
@@ -4575,13 +4653,17 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
{
short cri = sstatus->cri;
if (sd != NULL) {
+ // Racial crit bonuses are affected by katar's crit bonus.
+ if (battle_config.show_katar_crit_bonus && sd->weapontype == W_KATAR)
+ cri += sd->critaddrace[tstatus->race] * 2;
+ else
+ cri += sd->critaddrace[tstatus->race];
+
// if show_katar_crit_bonus is enabled, it already done the calculation in status.c
- if (!battle_config.show_katar_crit_bonus && sd->status.weapon == W_KATAR) {
+ if (!battle_config.show_katar_crit_bonus && sd->weapontype == W_KATAR) {
cri <<= 1;
}
- cri+= sd->critaddrace[tstatus->race];
-
if (flag.arrow) {
cri += sd->bonus.arrow_cri;
}
@@ -4604,6 +4686,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(!(sc && sc->data[SC_AUTOCOUNTER]))
break;
status_change_end(src, SC_AUTOCOUNTER, INVALID_TIMER);
+ FALLTHROUGH
case KN_AUTOCOUNTER:
if(battle_config.auto_counter_type &&
(battle_config.auto_counter_type&src->type))
@@ -4663,15 +4746,16 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
short hitrate = 80; //Default hitrate
#endif
- if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
- unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit->counttargeted(target);
- if(attacker_count >= battle_config.agi_penalty_count) {
+ if (battle_config.agi_penalty_type != 0 && (battle_config.agi_penalty_target & target->type) != 0) {
+ int attacker_count = unit->counttargeted(target);
+ if (attacker_count >= battle_config.agi_penalty_count) {
+ int penalty = (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num;
if (battle_config.agi_penalty_type == 1)
- flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
- else //asume type 2: absolute reduction
- flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
- if(flee < 1) flee = 1;
+ flee = flee * (100 - penalty) / 100;
+ else // asume type 2: absolute reduction
+ flee -= penalty;
+ if (flee < 1)
+ flee = 1;
}
}
@@ -4748,8 +4832,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if ((temp = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0)
hitrate += hitrate * ( 2 * temp ) / 100;
- if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) &&
- (temp = pc->checkskill(sd, GN_TRAINING_SWORD))>0 )
+ if ((sd->weapontype == W_1HSWORD || sd->weapontype == W_DAGGER) && (temp = pc->checkskill(sd, GN_TRAINING_SWORD)) > 0)
hitrate += 3 * temp;
}
@@ -4768,6 +4851,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
} //End hit/miss calculation
if (flag.hit && !flag.infdef) { //No need to do the math for plants
+ unsigned int skillratio = 100; //Skill dmg modifiers.
//Hitting attack
//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
@@ -4888,9 +4972,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
(!skill_id && sc && sc->data[SC_HLIF_CHANGE]?4:0)|
(sc && sc->data[SC_WEAPONPERFECT]?8:0);
if (flag.arrow && sd)
- switch(sd->status.weapon) {
+ switch (sd->weapontype) {
case W_BOW:
case W_REVOLVER:
+ case W_RIFLE:
case W_GATLING:
case W_SHOTGUN:
case W_GRENADE:
@@ -5064,7 +5149,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag);
}
- /* Fall through */
+ FALLTHROUGH
#endif
default:
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
@@ -5180,8 +5265,16 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if (hd != NULL)
ATK_ADD(hd->homunculus.spiritball * 3);
}
+ if ((wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) {
+ if (sd != NULL && pc->checkskill(sd, SU_POWEROFLIFE) > 0) {
+ if (pc->checkskill(sd, SU_SCAROFTAROU) == 5 && pc->checkskill(sd, SU_PICKYPECK) == 5 && pc->checkskill(sd, SU_ARCLOUSEDASH) == 5 && pc->checkskill(sd, SU_LUNATICCARROTBEAT) == 5) {
+ ATK_ADDRATE(20);
+ }
+ }
+ }
}
+
switch (skill_id) {
case AS_SONICBLOW:
if (sc && sc->data[SC_SOULLINK] &&
@@ -5244,6 +5337,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sc && sc->data[SC_MTF_RANGEATK] )
ATK_ADDRATE(sc->data[SC_MTF_RANGEATK]->val1);// temporary it should be 'bonus.long_attack_atk_rate'
#endif
+ if (sc != NULL && sc->data[SC_ARCLOUSEDASH] != NULL && sc->data[SC_ARCLOUSEDASH]->val4 != 0) {
+ ATK_ADDRATE(sc->data[SC_ARCLOUSEDASH]->val4);
+ }
if( (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
ATK_ADDRATE(-i);
@@ -5454,7 +5550,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
if( flag.infdef ) { //Plants receive 1 damage when hit
- short class_ = status->get_class(target);
+ int class_ = status->get_class(target);
if( flag.hit || wd.damage > 0 )
wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage
if( flag.lh && (flag.hit || wd.damage2 > 0) )
@@ -5486,13 +5582,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
//Dual-wield
if (wd.damage) {
temp = pc->checkskill(sd,AS_RIGHT) * 10;
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO)
temp = pc->checkskill(sd,KO_RIGHT) * 10 + 20;
ATK_RATER( 50 + temp );
}
if (wd.damage2) {
temp = pc->checkskill(sd,AS_LEFT) * 10;
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO)
temp = pc->checkskill(sd,KO_LEFT) * 10 + 20;
ATK_RATEL( 30 + temp );
}
@@ -5503,7 +5599,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(wd.damage < 1) wd.damage = 1;
if(wd.damage2 < 1) wd.damage2 = 1;
#endif
- } else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
+ } else if (sd->weapontype == W_KATAR && skill_id == 0) {
+ // Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
temp = pc->checkskill(sd,TF_DOUBLE);
wd.damage2 = wd.damage * (1 + (temp * 2))/100;
@@ -5622,7 +5719,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
//Reject Sword bugreport:4493 by Daegaladh
if (wd.damage != 0 && tsc != NULL && tsc->data[SC_SWORDREJECT] != NULL
- && (sd == NULL || sd->weapontype1 == W_DAGGER || sd->weapontype1 == W_1HSWORD || sd->status.weapon == W_2HSWORD)
+ && (sd == NULL || sd->weapontype1 == W_DAGGER || sd->weapontype1 == W_1HSWORD || sd->weapontype == W_2HSWORD)
&& rnd()%100 < tsc->data[SC_SWORDREJECT]->val2
) {
ATK_RATER(50);
@@ -5645,7 +5742,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
/*==========================================
* Battle main entry, from skill->attack
*------------------------------------------*/
-struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count)
+static struct Damage battle_calc_attack(int attack_type, struct block_list *bl, struct block_list *target, uint16 skill_id, uint16 skill_lv, int count)
{
struct Damage d;
struct map_session_data *sd=BL_CAST(BL_PC,bl);
@@ -5707,7 +5804,8 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl
}
//Performs reflect damage (magic (maya) is performed over skill.c).
-void battle_reflect_damage(struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id) {
+static void battle_reflect_damage(struct block_list *target, struct block_list *src, struct Damage *wd, uint16 skill_id)
+{
int64 damage, rdamage = 0, trdamage = 0;
struct map_session_data *sd, *tsd;
struct status_change *sc;
@@ -5758,10 +5856,10 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
if( wd->flag & BF_SHORT ) {
if( !is_boss(src) ) {
if( sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION ) {
- uint8 dir = map->calc_dir(target,src->x,src->y),
- t_dir = unit->getdir(target);
+ enum unit_dir dir = map->calc_dir(target, src->x, src->y);
+ enum unit_dir t_dir = unit->getdir(target);
- if( !map->check_dir(dir,t_dir) ) {
+ if (map->check_dir(dir, t_dir) == 0) {
int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended.
@@ -5829,21 +5927,21 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
if( sc->data[SC_LG_REFLECTDAMAGE] && rnd()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) {
- bool change = false;
-
NORMALIZE_RDAMAGE(damage * sc->data[SC_LG_REFLECTDAMAGE]->val2 / 100);
trdamage -= rdamage;/* wont count towards total */
- if( sd && !sd->state.autocast ) {
- change = true;
- sd->state.autocast = 1;
+ enum autocast_type ac_type;
+
+ if (sd != NULL) {
+ ac_type = sd->autocast.type;
+ sd->autocast.type = AUTOCAST_TEMP;
}
map->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,delay,wd->dmotion,rdamage,status_get_race(target));
- if( change )
- sd->state.autocast = 0;
+ if (sd != NULL)
+ sd->autocast.type = ac_type;
delay += 150;/* gradual increase so the numbers don't clip in the client */
@@ -5915,7 +6013,38 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
#undef NORMALIZE_RDAMAGE
}
-void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss)
+/**
+ * Reflects damage from certain traps, if battle_config.trap_reflect is true.
+ * @param target : Player who triggered the trap
+ * @param src : Player who set the trap
+ * @param md : Trap damage structure
+ * @param skill_id : Trap skill ID
+ */
+static void battle_reflect_trap(struct block_list *target, struct block_list *src, struct Damage *md, uint16 skill_id)
+{
+ if (battle_config.trap_reflect == true) {
+ if (src != target) { // Don't reflect your own damage
+ switch (skill_id) {
+ case HT_CLAYMORETRAP:
+ case HT_LANDMINE:
+ case HT_FREEZINGTRAP:
+ case HT_BLASTMINE:
+ // Needs official info
+ //case RA_CLUSTERBOMB:
+ //case RA_FIRINGTRAP:
+ //case RA_ICEBOUNDTRAP:
+ //case GN_THORNS_TRAP:
+ //case KO_MAKIBISHI:
+ case MA_LANDMINE:
+ case MA_FREEZINGTRAP:
+ battle->reflect_damage(target, src, md, skill_id);
+ break;
+ }
+ }
+ }
+}
+
+static void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss)
{
struct weapon_data *wd;
int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i;
@@ -5968,13 +6097,15 @@ void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rda
if (!thp && !tsp) return;
- status->heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain ? 3 : 1);
+ status->heal(&sd->bl, thp, tsp, STATUS_HEAL_FORCED | (battle_config.show_hp_sp_drain ? STATUS_HEAL_SHOWEFFECT : STATUS_HEAL_DEFAULT));
if (rhp || rsp)
status_zap(tbl, rhp, rsp);
}
+
// Deals the same damage to targets in area. [pakpil]
-int battle_damage_area(struct block_list *bl, va_list ap) {
+static int battle_damage_area(struct block_list *bl, va_list ap)
+{
int64 tick;
int amotion, dmotion, damage;
struct block_list *src;
@@ -5989,31 +6120,70 @@ int battle_damage_area(struct block_list *bl, va_list ap) {
if (bl->type == BL_MOB && BL_UCCAST(BL_MOB, bl)->class_ == MOBID_EMPELIUM)
return 0;
if( bl != src && battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
- struct map_session_data *sd = NULL;
nullpo_ret(src);
map->freeblock_lock();
- sd = BL_CAST(BL_PC, src);
if (src->type == BL_PC)
- battle->drain(sd, bl, damage, damage, status_get_race(bl), is_boss(bl));
+ battle->drain(BL_UCAST(BL_PC, src), bl, damage, damage, status_get_race(bl), is_boss(bl));
if( amotion )
battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true);
else
status_fix_damage(src,bl,damage,0);
clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0);
- if (src->type != BL_PC || !sd->state.autocast)
+ if (src->type != BL_PC || BL_UCCAST(BL_PC, src)->autocast.type != AUTOCAST_TEMP)
skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
map->freeblock_unlock();
}
return 0;
}
+
+static bool battle_check_arrows(struct map_session_data *sd)
+{
+ int index = sd->equip_index[EQI_AMMO];
+ if (index < 0) {
+ if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA)
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0, 0);
+ else
+ clif->arrow_fail(sd, 0);
+ return false;
+ }
+ //Ammo check by Ishizu-chan
+ if (sd->inventory_data[index]) {
+ switch (sd->weapontype) {
+ case W_BOW:
+ if (sd->inventory_data[index]->subtype != A_ARROW) {
+ clif->arrow_fail(sd, 0);
+ return false;
+ }
+ break;
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ if (sd->inventory_data[index]->subtype != A_BULLET) {
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0, 0);
+ return false;
+ }
+ break;
+ case W_GRENADE:
+ if (sd->inventory_data[index]->subtype != A_GRENADE) {
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0, 0);
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
/*==========================================
* Do a basic physical attack (call trough unit_attack_timer)
*------------------------------------------*/
// FIXME: flag is undocumented
-enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) {
+static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_list *target, int64 tick, int flag)
+{
struct map_session_data *sd = NULL, *tsd = NULL;
struct status_data *sstatus, *tstatus;
struct status_change *sc, *tsc;
@@ -6043,42 +6213,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if (sd)
{
- sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
+ sd->state.arrow_atk = (sd->weapontype == W_BOW || (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE));
if (sd->state.arrow_atk)
{
- int index = sd->equip_index[EQI_AMMO];
- if (index<0) {
- if ( sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA )
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- else
- clif->arrow_fail(sd, 0);
+ if (battle->check_arrows(sd) == false)
return ATK_NONE;
- }
- //Ammo check by Ishizu-chan
- if (sd->inventory_data[index])
- switch (sd->status.weapon) {
- case W_BOW:
- if (sd->inventory_data[index]->look != A_ARROW) {
- clif->arrow_fail(sd,0);
- return ATK_NONE;
- }
- break;
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- if (sd->inventory_data[index]->look != A_BULLET) {
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- return ATK_NONE;
- }
- break;
- case W_GRENADE:
- if (sd->inventory_data[index]->look != A_GRENADE) {
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- return ATK_NONE;
- }
- break;
- }
}
}
if (sc && sc->count) {
@@ -6088,10 +6227,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
if( tsc && tsc->data[SC_AUTOCOUNTER] && status->check_skilluse(target, src, KN_AUTOCOUNTER, 1) ) {
- uint8 dir = map->calc_dir(target,src->x,src->y);
- int t_dir = unit->getdir(target);
+ enum unit_dir dir = map->calc_dir(target, src->x, src->y);
+ enum unit_dir t_dir = unit->getdir(target);
int dist = distance_bl(src, target);
- if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) {
+ if(dist <= 0 || (map->check_dir(dir, t_dir) == 0 && dist <= tstatus->rhw.range + 1)) {
uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1;
clif->skillcastcancel(target); //Remove the casting bar. [Skotlex]
clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS.
@@ -6100,7 +6239,7 @@ 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)) )
+ if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->weapontype == W_FIST ? 1 : 2)) )
{
uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1;
int duration = skill->get_time2(MO_BLADESTOP,skill_lv);
@@ -6180,6 +6319,18 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if (sd && sd->state.arrow_atk) //Consume arrow.
battle->consume_ammo(sd, 0, 0);
+ if (target->type == BL_MOB) {
+ struct mob_data *md = BL_CAST(BL_MOB, target);
+ if (md != NULL) {
+ if (md->db->dmg_taken_rate != 100) {
+ if (wd.damage > 0)
+ wd.damage = apply_percentrate64(wd.damage, md->db->dmg_taken_rate, 100);
+ if (wd.damage2 > 0)
+ wd.damage2 = apply_percentrate64(wd.damage2, md->db->dmg_taken_rate, 100);
+ }
+ }
+ }
+
damage = wd.damage + wd.damage2;
if( damage > 0 && src != target ) {
if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 ){
@@ -6220,7 +6371,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if (d_bl != NULL
&& ((d_bl->type == BL_MER && d_md->master != NULL && d_md->master->bl.id == target->id)
- || (d_bl->type == BL_PC && d_sd->devotion[sce->val2] == target->id)
+ || (d_sd != NULL && d_bl->type == BL_PC && d_sd->devotion[sce->val2] == target->id)
)
&& check_distance_bl(target, d_bl, sce->val3)
) {
@@ -6260,17 +6411,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
sp = skill->get_sp(skill_id,skill_lv) * 2 / 3;
if (status->charge(src, 0, sp)) {
- switch (skill->get_casttype(skill_id)) {
- case CAST_GROUND:
- skill->castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, target, skill_id, skill_lv, tick, flag);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(src, target, skill_id, skill_lv, tick, flag);
- break;
- }
+ skill->castend_type(skill->get_casttype(skill_id), src, target, skill_id, skill_lv, tick, flag);
}
}
if (sd) {
@@ -6308,29 +6449,18 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
if( type != CAST_GROUND ) {
- clif->skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, r_skill, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return wd.dmg_lv;
}
}
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,r_skill,r_lv,3);
- switch( type ) {
- case CAST_GROUND:
- skill->castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, target, r_skill, r_lv, tick, flag);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(src, target, r_skill, r_lv, tick, flag);
- break;
- }
- sd->state.autocast = 0;
-
+ skill->castend_type(type, src, target, r_skill, r_lv, tick, flag);
+ sd->autocast.type = AUTOCAST_NONE;
sd->ud.canact_tick = tick + skill->delay_fix(src, r_skill, r_lv);
- clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1);
}
}
@@ -6375,7 +6505,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
#undef GET_NORMAL_ATTACK
#undef GET_NORMAL_ATTACK2
-bool battle_check_undead(int race,int element)
+static bool battle_check_undead(int race, int element)
{
if(battle_config.undead_detect_type == 0) {
if(element == ELE_UNDEAD)
@@ -6393,7 +6523,7 @@ bool battle_check_undead(int race,int element)
}
//Returns the upmost level master starting with the given object
-struct block_list *battle_get_master(struct block_list *src)
+static struct block_list *battle_get_master(struct block_list *src)
{
struct block_list *prev = NULL; //Used for infinite loop check (master of yourself?)
nullpo_retr(NULL, src);
@@ -6457,7 +6587,7 @@ struct block_list *battle_get_master(struct block_list *src)
* -1: flag fails
* 0: Invalid target (non-targetable ever)
*------------------------------------------*/
-int battle_check_target( struct block_list *src, struct block_list *target,int flag)
+static int battle_check_target(struct block_list *src, struct block_list *target, int flag)
{
int16 m; //map
int state = 0; //Initial state none
@@ -6469,10 +6599,6 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
m = target->m;
- if (flag & BCT_ENEMY && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) || map->getcell(m, src, target->x, target->y, CELL_CHKBASILICA))) {
- return -1;
- }
-
//t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
//objects involved.
if( (t_bl = battle->get_master(target)) == NULL )
@@ -6481,6 +6607,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( (s_bl = battle->get_master(src)) == NULL )
s_bl = src;
+ if ((flag & BCT_ENEMY) != 0 && (status_get_mode(s_bl) & MD_BOSS) == 0 && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) != 0
+ || map->getcell(m, src, target->x, target->y, CELL_CHKBASILICA) != 0)) {
+ return -1;
+ }
+
if (s_bl->type == BL_PC) {
const struct map_session_data *s_sd = BL_UCCAST(BL_PC, s_bl);
switch (t_bl->type) {
@@ -6548,6 +6679,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case RK_DRAGONBREATH_WATER:
if( !map->list[m].flag.pvp && !map->list[m].flag.gvg )
break;
+ FALLTHROUGH
case 0://you can hit them without skills
case MA_REMOVETRAP:
case HT_REMOVETRAP:
@@ -6612,7 +6744,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if (t_bl == s_bl)
break;
- if( sd->state.monster_ignore && flag&BCT_ENEMY )
+ if (sd->block_action.immune && flag&BCT_ENEMY)
return 0; // Global immunity only to Attacks
if (sd->status.karma && s_bl->type == BL_PC && BL_UCCAST(BL_PC, s_bl)->status.karma)
state |= BCT_ENEMY; // Characters with bad karma may fight amongst them
@@ -6737,37 +6869,55 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return (flag&state)?1:-1;
}
- if( map_flag_vs(m) ) {
+ if (map_flag_vs(m)) {
//Check rivalry settings.
- int sbg_id = 0, tbg_id = 0;
- if( map->list[m].flag.battleground ) {
+ int sbg_id = 0, tbg_id = 0, s_clan = 0, t_clan = 0;
+ if (map->list[m].flag.battleground) {
sbg_id = bg->team_get_id(s_bl);
tbg_id = bg->team_get_id(t_bl);
+ } else if (map->list[m].flag.cvc) {
+ s_clan = clan->get_id(s_bl);
+ t_clan = clan->get_id(t_bl);
}
- if( flag&(BCT_PARTY|BCT_ENEMY) ) {
+ if (flag & (BCT_PARTY | BCT_ENEMY)) {
int s_party = status->get_party_id(s_bl);
int s_guild = status->get_guild_id(s_bl);
+ int t_guild = status->get_guild_id(t_bl);
- if( s_party && s_party == status->get_party_id(t_bl)
- && !(map->list[m].flag.pvp && map->list[m].flag.pvp_noparty)
- && !(map_flag_gvg(m) && map->list[m].flag.gvg_noparty && !( s_guild && s_guild == status->get_guild_id(t_bl) ))
- && (!map->list[m].flag.battleground || sbg_id == tbg_id) )
- state |= BCT_PARTY;
- else
+ if (s_party != 0 && s_party == status->get_party_id(t_bl)) {
+ if (map_flag_gvg(m) && map->list[m].flag.gvg_noparty) {
+ if (s_guild != 0 && t_guild != 0 && (s_guild == t_guild || guild->isallied(s_guild, t_guild)))
+ state |= BCT_PARTY;
+ else
+ state |= flag & BCT_ENEMY ? BCT_ENEMY : BCT_PARTY;
+ } else if (!(map->list[m].flag.pvp && map->list[m].flag.pvp_noparty)
+ && (!map->list[m].flag.battleground || sbg_id == tbg_id)) {
+ state |= BCT_PARTY;
+ } else if (!map->list[m].flag.cvc || s_clan == t_clan) {
+ state |= BCT_PARTY;
+ } else {
+ state |= BCT_ENEMY;
+ }
+ } else {
state |= BCT_ENEMY;
+ }
}
- if( flag&(BCT_GUILD|BCT_ENEMY) ) {
+ if (flag & (BCT_GUILD | BCT_ENEMY)) {
int s_guild = status->get_guild_id(s_bl);
int t_guild = status->get_guild_id(t_bl);
- if( !(map->list[m].flag.pvp && map->list[m].flag.pvp_noguild)
+ if (!(map->list[m].flag.pvp && map->list[m].flag.pvp_noguild)
&& s_guild && t_guild
- && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild)))
- && (!map->list[m].flag.battleground || sbg_id == tbg_id) )
+ && (s_guild == t_guild || (!(flag & BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild)))
+ && (!map->list[m].flag.battleground || sbg_id == tbg_id)
+ && (!map->list[m].flag.cvc || s_clan == t_clan)
+ ) {
state |= BCT_GUILD;
- else
+ } else {
state |= BCT_ENEMY;
+ }
}
- if( state&BCT_ENEMY && map->list[m].flag.battleground && sbg_id && sbg_id == tbg_id )
+
+ if (state & BCT_ENEMY && ((map->list[m].flag.battleground && sbg_id && sbg_id == tbg_id) || (map->list[m].flag.cvc && s_clan && s_clan == t_clan)))
state &= ~BCT_ENEMY;
if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC) {
@@ -6775,11 +6925,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
const struct map_session_data *s_sd = BL_UCCAST(BL_PC, s_bl);
const struct map_session_data *t_sd = BL_UCCAST(BL_PC, t_bl);
if (
- (s_sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
- (t_sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
- (int)s_sd->status.base_level < battle_config.pk_min_level ||
- (int)t_sd->status.base_level < battle_config.pk_min_level ||
- (battle_config.pk_level_range && abs((int)s_sd->status.base_level - (int)t_sd->status.base_level) > battle_config.pk_level_range)
+ (s_sd->job & MAPID_UPPERMASK) == MAPID_NOVICE ||
+ (t_sd->job & MAPID_UPPERMASK) == MAPID_NOVICE ||
+ s_sd->status.base_level < battle_config.pk_min_level ||
+ t_sd->status.base_level < battle_config.pk_min_level ||
+ (battle_config.pk_level_range && abs(s_sd->status.base_level - t_sd->status.base_level) > battle_config.pk_level_range)
)
state &= ~BCT_ENEMY;
}
@@ -6807,11 +6957,12 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return (flag&state)?1:-1;
}
+
/*==========================================
* Check if can attack from this range
* Basic check then calling path->search for obstacle etc..
*------------------------------------------*/
-bool battle_check_range(struct block_list *src, struct block_list *bl, int range)
+static bool battle_check_range(struct block_list *src, struct block_list *bl, int range)
{
int d;
nullpo_retr(false, src);
@@ -6864,7 +7015,8 @@ static const struct battle_data {
{ "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, },
{ "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, },
{ "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, },
- { "traps_setting", &battle_config.traps_setting, 0, 0, 1, },
+ { "trap_options/visibility", &battle_config.trap_visibility, 2, 0, 2, },
+ { "trap_options/display_on_trigger", &battle_config.trap_trigger, 1, 0, 1, },
{ "summon_flora_setting", &battle_config.summon_flora, 1|2, 0, 1|2, },
{ "clear_skills_on_death", &battle_config.clear_unit_ondeath, BL_NUL, BL_NUL, BL_ALL, },
{ "clear_skills_on_warp", &battle_config.clear_unit_onwarp, BL_ALL, BL_NUL, BL_ALL, },
@@ -6899,7 +7051,7 @@ static const struct battle_data {
{ "chase_range_rate", &battle_config.chase_range_rate, 100, 0, INT_MAX, },
{ "gtb_sc_immunity", &battle_config.gtb_sc_immunity, 50, 0, INT_MAX, },
{ "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, },
- { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, },
+ { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 2, },
{ "emergency_call", &battle_config.emergency_call, 11, 0, 31, },
{ "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, },
{ "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, },
@@ -6932,16 +7084,15 @@ static const struct battle_data {
{ "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, },
{ "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, },
{ "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, },
+ { "pet_catch_rate_official_formula", &battle_config.pet_catch_rate_official_formula, 1, 0, 1, },
{ "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, },
{ "pet_rename", &battle_config.pet_rename, 0, 0, 1, },
{ "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, },
{ "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, },
- { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, },
{ "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, },
{ "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, },
{ "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, },
{ "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, },
- { "pet_equip_min_friendly", &battle_config.pet_equip_min_friendly, 900, 0, 950, },
{ "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, },
{ "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, },
{ "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, },
@@ -6958,14 +7109,15 @@ static const struct battle_data {
{ "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, },
{ "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, },
{ "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, },
- { "item_check", &battle_config.item_check, 0, 0, 1, },
+ { "item_check", &battle_config.item_check, 0, 0, 0xF, },
{ "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, },
- { "cashfood_use_interval", &battle_config.cashfood_use_interval, 60000, 0, INT_MAX, },
{ "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, },
{ "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, },
{ "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, },
{ "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, },
{ "hanbok_ignorepalette", &battle_config.hanbok_ignorepalette, 0, 0, 1, },
+ { "oktoberfest_ignorepalette", &battle_config.oktoberfest_ignorepalette, 0, 0, 1, },
+ { "summer2_ignorepalette", &battle_config.summer2_ignorepalette, 0, 0, 1, },
{ "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, },
{ "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, },
{ "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, },
@@ -7020,8 +7172,9 @@ static const struct battle_data {
{ "vending_over_max", &battle_config.vending_over_max, 1, 0, 1, },
{ "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, },
{ "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, },
+ { "party_change_leader_same_map", &battle_config.party_change_leader_same_map, 0, 0, 1, },
{ "show_party_share_picker", &battle_config.party_show_share_picker, 1, 0, 1, },
- { "show_picker.item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, },
+ { "show_picker_item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, },
{ "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, },
{ "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3, },
{ "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, },
@@ -7033,7 +7186,6 @@ static const struct battle_data {
{ "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, },
{ "disp_experience", &battle_config.disp_experience, 0, 0, 1, },
{ "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, },
- { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, },
{ "bone_drop", &battle_config.bone_drop, 0, 0, 2, },
{ "buyer_name", &battle_config.buyer_name, 1, 0, 1, },
{ "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, },
@@ -7100,6 +7252,8 @@ static const struct battle_data {
{ "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, },
{ "vcast_stat_scale", &battle_config.vcast_stat_scale, 530, 1, INT_MAX, },
{ "area_size", &battle_config.area_size, 14, 0, INT_MAX, },
+ { "chat_area_size", &battle_config.chat_area_size, 9, 0, INT_MAX, },
+ { "dead_area_size", &battle_config.dead_area_size, 32, 0, INT_MAX, },
{ "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, },
{ "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, },
{ "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, },
@@ -7133,7 +7287,6 @@ static const struct battle_data {
{ "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, },
{ "character_size", &battle_config.character_size, 1|2, 0, 1|2, },
{ "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, },
- { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, },
{ "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, },
{ "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, },
{ "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, },
@@ -7165,6 +7318,7 @@ static const struct battle_data {
{ "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, },
{ "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, },
{ "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, },
+ { "slave_chase_masters_chasetarget", &battle_config.slave_chase_masters_chasetarget, 1, 0, 1, },
{ "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, },
{ "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, },
{ "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, },
@@ -7180,14 +7334,14 @@ static const struct battle_data {
{ "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, },
{ "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, },
{ "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, },
- { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
+ { "invincible_nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
{ "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, },
{ "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, },
{ "knockback_left", &battle_config.knockback_left, 1, 0, 1, },
{ "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
{ "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
- { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
- { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, },
+ { "features/buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
+ { "features/search_stores", &battle_config.feature_search_stores, 1, 0, 1, },
{ "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, },
{ "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, },
{ "display_party_name", &battle_config.display_party_name, 0, 0, 1, },
@@ -7207,7 +7361,8 @@ static const struct battle_data {
{ "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 },
- { "feature.atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 },
+ { "mvp_tomb_spawn_delay", &battle_config.mvp_tomb_spawn_delay, 10000, 0, INT_MAX },
+ { "features/atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 },
{ "min_npc_vendchat_distance", &battle_config.min_npc_vendchat_distance, 3, 0, 100 },
{ "vendchat_near_hiddennpc", &battle_config.vendchat_near_hiddennpc, 0, 0, 1 },
{ "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 },
@@ -7219,6 +7374,7 @@ static const struct battle_data {
* Hercules
**/
{ "skill_trap_type", &battle_config.skill_trap_type, 0, 0, 1, },
+ { "trap_reflect", &battle_config.trap_reflect, 1, 0, 1, },
{ "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, },
{ "unequip_restricted_equipment", &battle_config.unequip_restricted_equipment, 0, 0, 3, },
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
@@ -7228,8 +7384,8 @@ static const struct battle_data {
{ "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, },
{ "snovice_call_type", &battle_config.snovice_call_type, 0, 0, 1, },
{ "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, },
- { "feature.banking", &battle_config.feature_banking, 1, 0, 1, },
- { "feature.auction", &battle_config.feature_auction, 0, 0, 2, },
+ { "features/banking", &battle_config.feature_banking, 1, 0, 1, },
+ { "features/auction", &battle_config.feature_auction, 0, 0, 2, },
{ "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, },
{ "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, },
{ "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, },
@@ -7241,7 +7397,7 @@ static const struct battle_data {
{ "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, },
{ "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, },
{ "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, },
- { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, },
+ { "features/roulette", &battle_config.feature_roulette, 1, 0, 1, },
{ "show_monster_hp_bar", &battle_config.show_monster_hp_bar, 1, 0, 1, },
{ "fix_warp_hit_delay_abuse", &battle_config.fix_warp_hit_delay_abuse, 0, 0, 1, },
{ "costume_refine_def", &battle_config.costume_refine_def, 1, 0, 1, },
@@ -7250,195 +7406,83 @@ static const struct battle_data {
{ "min_body_style", &battle_config.min_body_style, 0, 0, SHRT_MAX, },
{ "max_body_style", &battle_config.max_body_style, 4, 0, SHRT_MAX, },
{ "save_body_style", &battle_config.save_body_style, 0, 0, 1, },
+ { "player_warp_keep_direction", &battle_config.player_warp_keep_direction, 0, 0, 1, },
+ { "atcommand_levelup_events", &battle_config.atcommand_levelup_events, 0, 0, 1, },
+ { "bow_unequip_arrow", &battle_config.bow_unequip_arrow, 1, 0, 1, },
+ { "max_summoner_parameter", &battle_config.max_summoner_parameter, 120, 10, 10000, },
+ { "mvp_exp_reward_message", &battle_config.mvp_exp_reward_message, 0, 0, 1, },
+ { "monster_eye_range_bonus", &battle_config.mob_eye_range_bonus, 0, 0, 10, },
+ { "prevent_logout_trigger", &battle_config.prevent_logout_trigger, 0xE, 0, 0xF, },
+ { "boarding_halter_speed", &battle_config.boarding_halter_speed, 25, 0, 100, },
+ { "features/rodex", &battle_config.feature_rodex, 1, 0, 1, },
+ { "features/rodex_use_accountmail", &battle_config.feature_rodex_use_accountmail, 0, 0, 1, },
+ { "features/enable_homun_autofeed", &battle_config.feature_enable_homun_autofeed, 1, 0, 1, },
+ { "features/enable_pet_autofeed", &battle_config.feature_enable_pet_autofeed, 1, 0, 1, },
+ { "storage_use_item", &battle_config.storage_use_item, 0, 0, 1, },
+ { "features/enable_attendance_system", &battle_config.feature_enable_attendance_system,1, 0, 1, },
+ { "features/feature_attendance_endtime",&battle_config.feature_attendance_endtime, 1, 0, 99999999, },
+ { "min_item_buy_price", &battle_config.min_item_buy_price, 1, 0, INT_MAX, },
+ { "min_item_sell_price", &battle_config.min_item_sell_price, 0, 0, INT_MAX, },
+ { "display_fake_hp_when_dead", &battle_config.display_fake_hp_when_dead, 1, 0, 1, },
+ { "magicrod_type", &battle_config.magicrod_type, 0, 0, 1, },
+ { "features/enable_achievement_system", &battle_config.feature_enable_achievement, 1, 0, 1, },
+ { "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, },
+ { "ping_time", &battle_config.ping_time, 20, 0, 99999999, },
+ { "option_drop_max_loop", &battle_config.option_drop_max_loop, 10, 1, 100000, },
+ { "drop_connection_on_quit", &battle_config.drop_connection_on_quit, 0, 0, 1, },
+ { "features/enable_refinery_ui", &battle_config.enable_refinery_ui, 1, 0, 1, },
+ { "features/replace_refine_npcs", &battle_config.replace_refine_npcs, 1, 0, 1, },
+ { "batk_min_limit", &battle_config.batk_min, 0, 0, INT_MAX, },
+ { "batk_max_limit", &battle_config.batk_max, USHRT_MAX, 1, INT_MAX, },
+ { "matk_min_limit", &battle_config.matk_min, 0, 0, INT_MAX, },
+ { "matk_max_limit", &battle_config.matk_max, USHRT_MAX, 1, INT_MAX, },
+ { "watk_min_limit", &battle_config.watk_min, 0, 0, INT_MAX, },
+ { "watk_max_limit", &battle_config.watk_max, USHRT_MAX, 1, INT_MAX, },
+ { "flee_min_limit", &battle_config.flee_min, 1, 1, INT_MAX, },
+ { "flee_max_limit", &battle_config.flee_max, SHRT_MAX, 1, INT_MAX, },
+ { "flee2_min_limit", &battle_config.flee2_min, 10, 1, INT_MAX, },
+ { "flee2_max_limit", &battle_config.flee2_max, SHRT_MAX, 1, INT_MAX, },
+ { "critical_min_limit", &battle_config.critical_min, 10, 1, INT_MAX, },
+ { "critical_max_limit", &battle_config.critical_max, SHRT_MAX, 1, INT_MAX, },
+ { "hit_min_limit", &battle_config.hit_min, 1, 1, INT_MAX, },
+ { "hit_max_limit", &battle_config.hit_max, SHRT_MAX, 1, INT_MAX, },
+ { "autoloot_adjust", &battle_config.autoloot_adjust, 0, 0, 1, },
+ { "hom_bonus_exp_from_master", &battle_config.hom_bonus_exp_from_master, 10, 0, 100, },
};
-#ifndef STATS_OPT_OUT
-/**
- * Hercules anonymous statistic usage report -- packet is built here, and sent to char server to report.
- **/
-void Hercules_report(char* date, char *time_c) {
- int i, bd_size = ARRAYLENGTH(battle_data);
- unsigned int config = 0;
- char timestring[25];
- time_t curtime;
- char* buf;
-
- enum config_table {
- C_CIRCULAR_AREA = 0x0001,
- C_CELLNOSTACK = 0x0002,
- C_CONSOLE_INPUT = 0x0004,
- C_SCRIPT_CALLFUNC_CHECK = 0x0008,
- C_OFFICIAL_WALKPATH = 0x0010,
- C_RENEWAL = 0x0020,
- C_RENEWAL_CAST = 0x0040,
- C_RENEWAL_DROP = 0x0080,
- C_RENEWAL_EXP = 0x0100,
- C_RENEWAL_LVDMG = 0x0200,
- C_RENEWAL_EDP = 0x0400,
- C_RENEWAL_ASPD = 0x0800,
- C_SECURE_NPCTIMEOUT = 0x1000,
- //C_SQL_DB_ITEM = 0x2000,
- C_SQL_LOGS = 0x4000,
- 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 */
- time(&curtime);
- strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime));
-
-#ifdef CIRCULAR_AREA
- config |= C_CIRCULAR_AREA;
-#endif
-
-#ifdef CELL_NOSTACK
- config |= C_CELLNOSTACK;
-#endif
-
-#ifdef CONSOLE_INPUT
- config |= C_CONSOLE_INPUT;
-#endif
-
-#ifdef SCRIPT_CALLFUNC_CHECK
- config |= C_SCRIPT_CALLFUNC_CHECK;
-#endif
-
-#ifdef OFFICIAL_WALKPATH
- config |= C_OFFICIAL_WALKPATH;
-#endif
-#ifdef RENEWAL
- config |= C_RENEWAL;
-#endif
-
-#ifdef RENEWAL_CAST
- config |= C_RENEWAL_CAST;
-#endif
-
-#ifdef RENEWAL_DROP
- config |= C_RENEWAL_DROP;
-#endif
-
-#ifdef RENEWAL_EXP
- config |= C_RENEWAL_EXP;
-#endif
-
-#ifdef RENEWAL_LVDMG
- config |= C_RENEWAL_LVDMG;
-#endif
-
-#ifdef RENEWAL_EDP
- config |= C_RENEWAL_EDP;
-#endif
-
-#ifdef RENEWAL_ASPD
- config |= C_RENEWAL_ASPD;
-#endif
-
-#ifdef SECURE_NPCTIMEOUT
- config |= C_SECURE_NPCTIMEOUT;
-#endif
-
-#ifdef PACKETVER_RE
- config |= C_PACKETVER_RE;
-#endif
-
- /* non-define part */
- if( logs->config.sql_logs )
- config |= C_SQL_LOGS;
-
-#ifdef MEMWATCH
- config |= C_MEMWATCH;
-#endif
-#ifdef DMALLOC
- config |= C_DMALLOC;
-#endif
-#ifdef GCOLLECT
- config |= C_GCOLLECT;
-#endif
-
-#ifdef SEND_SHORTLIST
- config |= C_SEND_SHORTLIST;
-#endif
-
-#define BFLAG_LENGTH 35
-
- CREATE(buf, char, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 );
-
- /* build packet */
-
- WBUFW(buf,0) = 0x3000;
- WBUFW(buf,2) = 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) );
- WBUFW(buf,4) = 0x9f;
-
- safestrncpy(WBUFP(buf,6), date, 12);
- safestrncpy(WBUFP(buf,18), time_c, 9);
- safestrncpy(WBUFP(buf,27), timestring, 24);
-
- safestrncpy(WBUFP(buf,51), sysinfo->platform(), 16);
- safestrncpy(WBUFP(buf,67), sysinfo->osversion(), 50);
- safestrncpy(WBUFP(buf,117), sysinfo->cpu(), 32);
- WBUFL(buf,149) = sysinfo->cpucores();
- safestrncpy(WBUFP(buf,153), sysinfo->arch(), 8);
- WBUFB(buf,161) = sysinfo->vcstypeid();
- WBUFB(buf,162) = sysinfo->is64bit();
- safestrncpy(WBUFP(buf,163), sysinfo->vcsrevision_src(), 41);
- safestrncpy(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(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, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) );
-
- aFree(buf);
-
-#undef BFLAG_LENGTH
-}
-static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) {
- if( chrif->isconnected() ) {/* char server relays it, so it must be online. */
- Hercules_report(__DATE__,__TIME__);
+static bool battle_set_value_sub(int index, int value)
+{
+ Assert_retr(false, index >= 0);
+ if (value < battle_data[index].min || value > battle_data[index].max) {
+ ShowWarning("Value for setting '%s': %d is invalid (min:%d max:%d)! Defaulting to %d...\n",
+ battle_data[index].str, value, battle_data[index].min, battle_data[index].max, battle_data[index].defval);
+ value = battle_data[index].defval;
}
- return 0;
+ *battle_data[index].val = value;
+ return true;
}
-#endif
-int battle_set_value(const char* w1, const char* w2)
+static bool battle_set_value(const char *param, const char *value)
{
- int val = config_switch(w2);
+ int val;
int i;
- nullpo_retr(1, w1);
- nullpo_retr(1, w2);
- ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
- if (i == ARRAYLENGTH(battle_data)) {
- if( HPM->parseConf(w1,w2,HPCT_BATTLE) ) /* if plugin-owned, succeed */
- return 1;
- return 0; // not found
- }
+ nullpo_retr(false, param);
+ nullpo_retr(false, value);
- if (val < battle_data[i].min || val > battle_data[i].max)
- {
- ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval);
- val = battle_data[i].defval;
+ val = config_switch(value);
+
+ ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(param, battle_data[i].str) == 0);
+ if (i == ARRAYLENGTH(battle_data)) {
+ if (HPM->parse_conf_entry(param, value, HPCT_BATTLE)) /* if plugin-owned, succeed */
+ return true;
+ return false; // not found
}
- *battle_data[i].val = val;
- return 1;
+ return battle->config_set_value_sub(i, val);
}
-bool battle_get_value(const char *w1, int *value)
+static bool battle_get_value(const char *w1, int *value)
{
int i;
@@ -7457,13 +7501,15 @@ bool battle_get_value(const char *w1, int *value)
return false;
}
-void battle_set_defaults(void) {
+static void battle_set_defaults(void)
+{
int i;
for (i = 0; i < ARRAYLENGTH(battle_data); i++)
*battle_data[i].val = battle_data[i].defval;
}
-void battle_adjust_conf(void) {
+static void battle_adjust_conf(void)
+{
battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10;
battle_config.max_aspd = 2000 - battle_config.max_aspd*10;
battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd*10;
@@ -7486,110 +7532,160 @@ void battle_adjust_conf(void) {
#if PACKETVER < 20100427
if( battle_config.feature_buying_store ) {
- ShowWarning("conf/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n");
+ ShowWarning("conf/map/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n");
battle_config.feature_buying_store = 0;
}
#endif
#if PACKETVER < 20100803
if( battle_config.feature_search_stores ) {
- ShowWarning("conf/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n");
+ ShowWarning("conf/map/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n");
battle_config.feature_search_stores = 0;
}
#endif
#if PACKETVER < 20130724
if( battle_config.feature_banking ) {
- ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n");
+ ShowWarning("conf/map/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n");
battle_config.feature_banking = 0;
}
#endif
#if PACKETVER < 20141022
if( battle_config.feature_roulette ) {
- ShowWarning("conf/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n");
+ ShowWarning("conf/map/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n");
battle_config.feature_roulette = 0;
}
#endif
#if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */
if( battle_config.feature_auction == 1 ) {
- ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n");
- ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n");
+ ShowWarning("conf/map/battle/feature.conf:features/auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n");
+ ShowWarning("conf/map/battle/feature.conf:features/auction change value to '2' to silence this warning and maintain it enabled\n");
battle_config.feature_auction = 0;
}
#endif
+#if PACKETVER < 20131223
+ if (battle_config.mvp_exp_reward_message) {
+ ShowWarning("conf/map/battle/client.conf MVP EXP reward message is enabled but it requires PACKETVER 2013-12-23 or newer, disabling...\n");
+ battle_config.mvp_exp_reward_message = 0;
+ }
+#endif
+
+#if !(PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO))
+ if (battle_config.enable_refinery_ui == 1) {
+ ShowWarning("conf/map/battle/feature.conf refinery ui is enabled but it requires PACKETVER 2016-11-09 RagexeRE/2016-11-30 Ragexe or newer, disabling...\n");
+ battle_config.enable_refinery_ui = 0;
+ }
+
+ if (battle_config.replace_refine_npcs == 1) {
+ ShowWarning("conf/map/battle/feature.conf replace refine npcs is enabled but it requires PACKETVER 2016-11-09 RagexeRE/2016-11-30 Ragexe or newer, disabling...\n");
+ battle_config.replace_refine_npcs = 0;
+ }
+#endif
+
#ifndef CELL_NOSTACK
if (battle_config.custom_cell_stack_limit != 1)
ShowWarning("Battle setting 'custom_cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
#endif
}
-int battle_config_read(const char* cfgName)
+/**
+ * Dynamically reads battle configuration and initializes required variables.
+ *
+ * @param filename Path to configuration file.
+ * @param imported Whether the current config is imported from another file.
+ * @retval false in case of error.
+ */
+static bool battle_config_read(const char *filename, bool imported)
{
- FILE* fp;
- static int count = 0;
+ struct config_t config;
+ const struct config_setting_t *setting = NULL;
+ int i;
+ const char *import = NULL;
+ bool retval = true;
- nullpo_ret(cfgName);
+ nullpo_retr(false, filename);
- if (count == 0)
+ if (!libconfig->load_file(&config, filename))
+ return false; // Error message is already shown by libconfig->load_file()
+
+ if (!imported)
battle->config_set_defaults();
- count++;
+ if (libconfig->lookup(&config, "battle_configuration/traps_setting") != NULL) {
+ ShowError("The `traps_setting` battle conf option has been replaced by `trap_visibility`. Please see conf/map/battle/skill.conf.\n");
+ }
- fp = fopen(cfgName,"r");
- if (fp == NULL)
- ShowError("File not found: %s\n", cfgName);
- else
- {
- char line[1024], w1[1024], w2[1024];
- while(fgets(line, sizeof(line), fp))
- {
- if (line[0] == '/' && line[1] == '/')
- continue;
- if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
- continue;
- if (strcmpi(w1, "import") == 0)
- battle->config_read(w2);
- else
- if (battle->config_set_value(w1, w2) == 0)
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
+ for (i = 0; i < ARRAYLENGTH(battle_data); i++) {
+ int type, val;
+ char config_name[256];
+ safesnprintf(config_name, sizeof config_name, "battle_configuration/%s", battle_data[i].str);
+
+ if ((setting = libconfig->lookup(&config, config_name)) == NULL) {
+ if (!imported) {
+ ShowWarning("Missing configuration '%s' in file %s!\n", config_name, filename);
+ retval = false;
+ }
+ continue;
+ }
+
+ switch ((type = config_setting_type(setting))) {
+ case CONFIG_TYPE_INT:
+ val = libconfig->setting_get_int(setting);
+ break;
+ case CONFIG_TYPE_BOOL:
+ val = libconfig->setting_get_bool(setting);
+ break;
+ default: // Unsupported type
+ ShowWarning("Setting %s has unsupported type %d, ignoring...\n", config_name, type);
+ retval = false;
+ continue;
}
- fclose(fp);
+ if (!battle->config_set_value_sub(i, val))
+ retval = false;
}
- count--;
+ if (!HPM->parse_battle_conf(&config, filename, imported))
+ retval = false;
- if (count == 0) {
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ if (strcmp(import, filename) == 0 || strcmp(import, map->BATTLE_CONF_FILENAME) == 0) {
+ ShowWarning("battle_config_read: Loop detected! Skipping 'import'...\n");
+ } else {
+ if (!battle->config_read(import, true))
+ retval = false;
+ }
+ }
+
+ libconfig->destroy(&config);
+ if (!imported) {
battle->config_adjust();
clif->bc_ready();
}
-
- return 0;
+ return retval;
}
-void do_init_battle(bool minimal) {
+static void do_init_battle(bool minimal)
+{
if (minimal)
return;
battle->delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
timer->add_func_list(battle->delay_damage_sub, "battle_delay_damage_sub");
-
-#ifndef STATS_OPT_OUT
- timer->add_func_list(Hercules_report_timer, "Hercules_report_timer");
- timer->add_interval(timer->gettick()+30000, Hercules_report_timer, 0, 0, 60000 * 30);
-#endif
-
}
-void do_final_battle(void) {
+static void do_final_battle(void)
+{
ers_destroy(battle->delay_damage_ers);
}
/* initialize the interface */
-void battle_defaults(void) {
+void battle_defaults(void)
+{
battle = &battle_s;
battle->bc = &battle_config;
@@ -7602,13 +7698,16 @@ void battle_defaults(void) {
battle->calc_attack = battle_calc_attack;
battle->calc_damage = battle_calc_damage;
+ battle->calc_pc_damage = battle_calc_pc_damage;
battle->calc_gvg_damage = battle_calc_gvg_damage;
battle->calc_bg_damage = battle_calc_bg_damage;
battle->weapon_attack = battle_weapon_attack;
+ battle->check_arrows = battle_check_arrows;
battle->calc_weapon_attack = battle_calc_weapon_attack;
battle->delay_damage = battle_delay_damage;
battle->drain = battle_drain;
battle->reflect_damage = battle_reflect_damage;
+ battle->reflect_trap = battle_reflect_trap;
battle->attr_ratio = battle_attr_ratio;
battle->attr_fix = battle_attr_fix;
battle->calc_cardfix = battle_calc_cardfix;
@@ -7644,6 +7743,7 @@ void battle_defaults(void) {
battle->calc_drain = battle_calc_drain;
battle->config_read = battle_config_read;
battle->config_set_defaults = battle_set_defaults;
+ battle->config_set_value_sub = battle_set_value_sub;
battle->config_set_value = battle_set_value;
battle->config_get_value = battle_get_value;
battle->config_adjust = battle_adjust_conf;
diff --git a/src/map/battle.h b/src/map/battle.h
index 49abdc730..bb907d5b9 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@ struct status_data;
enum {
// Flag of the final calculation
+ BF_NONE = 0x0000,
BF_WEAPON = 0x0001,
BF_MAGIC = 0x0002,
BF_MISC = 0x0004,
@@ -102,8 +103,8 @@ enum e_battle_check_target { //New definitions [Skotlex]
enum battle_dmg_type {
BDT_NORMAL = 0, // Normal attack
//BDT_PICKUP = 1, // Pick up item
- //BDT_SITDOWN = 2, // Sit down
- //BDT_STANDUP = 3, // Stand up
+ BDT_SITDOWN = 2, // Sit down
+ BDT_STANDUP = 3, // Stand up
BDT_ENDURE = 4, // Damage (endure)
BDT_SPLASH = 5, // Splash
BDT_SKILL = 6, // Skill
@@ -148,7 +149,8 @@ struct Battle_Config {
int pc_damage_delay_rate;
int defnotenemy;
int vs_traps_bctall;
- int traps_setting;
+ int trap_visibility;
+ int trap_trigger;
int summon_flora; //[Skotlex]
int clear_unit_ondeath; //[Skotlex]
int clear_unit_onwarp; //[Skotlex]
@@ -210,16 +212,15 @@ struct Battle_Config {
int guild_aura;
int pc_invincible_time;
+ int pet_catch_rate_official_formula;
int pet_catch_rate;
int pet_rename;
int pet_friendly_rate;
int pet_hungry_delay_rate;
- int pet_hungry_friendly_decrease;
int pet_status_support;
int pet_attack_support;
int pet_damage_support;
int pet_support_min_friendly; //[Skotlex]
- int pet_equip_min_friendly;
int pet_support_rate;
int pet_attack_exp_to_master;
int pet_attack_exp_rate;
@@ -240,12 +241,13 @@ struct Battle_Config {
int combo_delay_rate;
int item_check;
int item_use_interval; //[Skotlex]
- int cashfood_use_interval;
int wedding_modifydisplay;
int wedding_ignorepalette; //[Skotlex]
int xmas_ignorepalette; // [Valaris]
int summer_ignorepalette; // [Zephyrus]
int hanbok_ignorepalette;
+ int oktoberfest_ignorepalette;
+ int summer2_ignorepalette;
int natural_healhp_interval;
int natural_healsp_interval;
int natural_heal_skill_interval;
@@ -297,6 +299,7 @@ struct Battle_Config {
int show_steal_in_same_party;
int party_share_type;
int party_hp_mode;
+ int party_change_leader_same_map;
int party_show_share_picker;
int show_picker_item_type;
int attack_attr_none;
@@ -338,7 +341,6 @@ struct Battle_Config {
int skill_removetrap_type;
int disp_experience;
int disp_zeny;
- int castle_defense_rate;
int backstab_bow_penalty;
int hp_rate;
int sp_rate;
@@ -362,6 +364,8 @@ struct Battle_Config {
int castrate_dex_scale; // added by [MouseJstr]
int area_size; // added by [MouseJstr]
+ int chat_area_size; // added by [gumi]
+ int dead_area_size; // Monster die area [KirieZ]
int max_def, over_def_bonus; //added by [Skotlex]
@@ -399,6 +403,7 @@ struct Battle_Config {
int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex]
int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight.
int boss_active_time;
+ int slave_chase_masters_chasetarget;
int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex]
int show_katar_crit_bonus;
@@ -406,7 +411,6 @@ struct Battle_Config {
int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex]
int character_size; // if riders have size=2, and baby class riders size=1 [Lupus]
- int rare_drop_announce; // chance <= to show rare drops global announces
int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex]
@@ -473,6 +477,7 @@ struct Battle_Config {
int client_emblem_max_blank_percent;
int hom_max_level;
int hom_S_max_level;
+ int hom_bonus_exp_from_master;
// [BattleGround Settings]
int bg_update_interval;
@@ -487,6 +492,7 @@ struct Battle_Config {
int vcast_stat_scale;
int mvp_tomb_enabled;
+ int mvp_tomb_spawn_delay;
int atcommand_suggestions_enabled;
int min_npc_vendchat_distance;
@@ -501,6 +507,7 @@ struct Battle_Config {
/** Hercules **/
int skill_trap_type;
+ int trap_reflect;
int item_restricted_consumption_type;
int unequip_restricted_equipment;
int max_walk_path;
@@ -539,6 +546,67 @@ struct Battle_Config {
// BodyStyle
int min_body_style, max_body_style;
int save_body_style;
+
+ // Warp Face Direction
+ int player_warp_keep_direction;
+
+ int atcommand_levelup_events; // Enable atcommands trigger level up events for NPCs
+
+ int bow_unequip_arrow;
+
+ int max_summoner_parameter; // Summoner Max Stats
+ int mvp_exp_reward_message;
+
+ int mob_eye_range_bonus; //Vulture's Eye and Snake's Eye range bonus
+
+ int prevent_logout_trigger;
+ int boarding_halter_speed;
+
+ int feature_rodex;
+ int feature_rodex_use_accountmail;
+
+ int feature_enable_homun_autofeed;
+ int feature_enable_pet_autofeed;
+
+ int storage_use_item;
+
+ int feature_enable_attendance_system;
+ int feature_attendance_endtime;
+
+ int min_item_buy_price;
+ int min_item_sell_price;
+
+ int display_fake_hp_when_dead;
+
+ int magicrod_type;
+
+ int feature_enable_achievement;
+
+ int ping_timer_interval;
+ int ping_time;
+
+ int option_drop_max_loop;
+
+ int drop_connection_on_quit;
+ int enable_refinery_ui;
+ int replace_refine_npcs;
+
+ int batk_min;
+ int batk_max;
+ int matk_min;
+ int matk_max;
+ int watk_min;
+ int watk_max;
+ int flee_min;
+ int flee_max;
+ int flee2_min;
+ int flee2_max;
+ int critical_min;
+ int critical_max;
+ int hit_min;
+ int hit_max;
+
+ int autoloot_adjust;
};
/* criteria for battle_config.idletime_critera */
@@ -553,6 +621,7 @@ enum e_battle_config_idletime {
BCIDLE_EMOTION = 0x080,
BCIDLE_DROPITEM = 0x100,
BCIDLE_ATCOMMAND = 0x200,
+ BCIDLE_SCRIPT = 0x400,
};
// Damage delayed info
@@ -587,12 +656,16 @@ struct battle_interface {
struct Damage (*calc_attack) (int attack_type, struct block_list *bl, struct block_list *target, uint16 skill_id, uint16 skill_lv, int count);
/* generic final damage calculation */
int64 (*calc_damage) (struct block_list *src, struct block_list *bl, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv);
+ /* pc special damage calculation */
+ int64 (*calc_pc_damage) (struct block_list *src, struct block_list *bl, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv);
/* gvg final damage calculation */
int64 (*calc_gvg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
/* battlegrounds final damage calculation */
int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
/* normal weapon attack */
enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag);
+ /* check is equipped ammo and this ammo allowed */
+ bool (*check_arrows) (struct map_session_data *sd);
/* calculate weapon attack */
struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag);
/* delays damage or skills by a timer */
@@ -601,6 +674,8 @@ struct battle_interface {
void (*drain) (struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss);
/* damage reflect */
void (*reflect_damage) (struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id);
+ /* trap reflect */
+ void(*reflect_trap) (struct block_list *target, struct block_list *src, struct Damage *md, uint16 skill_id);
/* attribute rate */
int (*attr_ratio) (int atk_elem, int def_type, int def_lv);
/* applies attribute modifiers */
@@ -654,10 +729,11 @@ struct battle_interface {
int (*adjust_skill_damage) (int m, unsigned short skill_id);
int64 (*add_mastery) (struct map_session_data *sd,struct block_list *target,int64 dmg,int type);
int (*calc_drain) (int64 damage, int rate, int per);
- /* - battle_config */
- int (*config_read) (const char *cfgName);
+ /* battle_config */
+ bool (*config_read) (const char *filename, bool imported);
void (*config_set_defaults) (void);
- int (*config_set_value) (const char *w1, const char *w2);
+ bool (*config_set_value_sub) (int index, int value);
+ bool (*config_set_value) (const char *param, const char *value);
bool (*config_get_value) (const char *w1, int *value);
void (*config_adjust) (void);
/* ----------------------------------------- */
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 629122c87..7a9d54266 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,16 +47,18 @@
#include <stdio.h>
#include <string.h>
-struct battleground_interface bg_s;
+static struct battleground_interface bg_s;
struct battleground_interface *bg;
/// Search a BG Team using bg_id
-struct battleground_data* bg_team_search(int bg_id) {
+static struct battleground_data* bg_team_search(int bg_id)
+{
if( !bg_id ) return NULL;
return (struct battleground_data *)idb_get(bg->team_db, bg_id);
}
-struct map_session_data* bg_getavailablesd(struct battleground_data *bgd) {
+static struct map_session_data* bg_getavailablesd(struct battleground_data *bgd)
+{
int i;
nullpo_retr(NULL, bgd);
ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd != NULL);
@@ -64,7 +66,8 @@ struct map_session_data* bg_getavailablesd(struct battleground_data *bgd) {
}
/// Deletes BG Team from db
-bool bg_team_delete(int bg_id) {
+static bool bg_team_delete(int bg_id)
+{
int i;
struct battleground_data *bgd = bg->team_search(bg_id);
@@ -82,7 +85,8 @@ bool bg_team_delete(int bg_id) {
}
/// Warps a Team
-bool bg_team_warp(int bg_id, unsigned short map_index, short x, short y) {
+static bool bg_team_warp(int bg_id, unsigned short map_index, short x, short y)
+{
int i;
struct battleground_data *bgd = bg->team_search(bg_id);
if( bgd == NULL ) return false;
@@ -91,13 +95,15 @@ bool bg_team_warp(int bg_id, unsigned short map_index, short x, short y) {
return true;
}
-void bg_send_dot_remove(struct map_session_data *sd) {
+static void bg_send_dot_remove(struct map_session_data *sd)
+{
if( sd && sd->bg_id )
clif->bg_xy_remove(sd);
}
/// Player joins team
-bool bg_team_join(int bg_id, struct map_session_data *sd) {
+static bool bg_team_join(int bg_id, struct map_session_data *sd)
+{
int i;
struct battleground_data *bgd = bg->team_search(bg_id);
@@ -135,7 +141,8 @@ bool bg_team_join(int bg_id, struct map_session_data *sd) {
}
/// Single Player leaves team
-int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
+static int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag)
+{
int i, bg_id;
struct battleground_data *bgd;
@@ -162,16 +169,16 @@ int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
switch (flag) {
default:
case BGTL_QUIT:
- sprintf(output, "Server : %s has quit the game...", sd->status.name);
+ sprintf(output, msg_txt(464), sd->status.name); // Server : %s has quit the game...
break;
case BGTL_LEFT:
- sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
+ sprintf(output, msg_txt(454), sd->status.name); // Server : %s is leaving the battlefield...
break;
case BGTL_AFK:
- sprintf(output, "Server : %s has been afk-kicked from the battlefield...", sd->status.name);
+ sprintf(output, msg_txt(455), sd->status.name); // Server : %s has been afk-kicked from the battlefield...
break;
}
- clif->bg_message(bgd, 0, "Server", output, strlen(output) + 1);
+ clif->bg_message(bgd, 0, "Server", output);
}
if( bgd->logout_event[0] && flag )
@@ -185,7 +192,8 @@ int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
}
/// Respawn after killed
-bool bg_member_respawn(struct map_session_data *sd) {
+static bool bg_member_respawn(struct map_session_data *sd)
+{
struct battleground_data *bgd;
if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bgd = bg->team_search(sd->bg_id)) == NULL )
return false;
@@ -197,7 +205,8 @@ bool bg_member_respawn(struct map_session_data *sd) {
return true; // Warped
}
-int bg_create(unsigned short map_index, short rx, short ry, const char *ev, const char *dev) {
+static int bg_create(unsigned short map_index, short rx, short ry, const char *ev, const char *dev)
+{
struct battleground_data *bgd;
bg->team_counter++;
@@ -216,7 +225,8 @@ int bg_create(unsigned short map_index, short rx, short ry, const char *ev, cons
return bgd->bg_id;
}
-int bg_team_get_id(struct block_list *bl) {
+static int bg_team_get_id(struct block_list *bl)
+{
nullpo_ret(bl);
switch( bl->type ) {
case BL_PC:
@@ -265,21 +275,22 @@ int bg_team_get_id(struct block_list *bl) {
return 0;
}
-bool bg_send_message(struct map_session_data *sd, const char *mes, int len) {
+static bool bg_send_message(struct map_session_data *sd, const char *mes)
+{
struct battleground_data *bgd;
nullpo_ret(sd);
nullpo_ret(mes);
if( sd->bg_id == 0 || (bgd = bg->team_search(sd->bg_id)) == NULL )
return false; // Couldn't send message
- clif->bg_message(bgd, sd->bl.id, sd->status.name, mes, len);
+ clif->bg_message(bgd, sd->bl.id, sd->status.name, mes);
return true;
}
/**
* @see DBApply
*/
-int bg_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+static int bg_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct battleground_data *bgd = DB->data2ptr(data);
struct map_session_data *sd;
@@ -297,12 +308,14 @@ int bg_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
+static int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
+{
bg->team_db->foreach(bg->team_db, bg->send_xy_timer_sub, tick);
return 0;
}
-enum bg_queue_types bg_str2teamtype (const char *str) {
+static enum bg_queue_types bg_str2teamtype(const char *str)
+{
char temp[200], *parse;
enum bg_queue_types type = BGQT_INVALID;
@@ -330,7 +343,8 @@ enum bg_queue_types bg_str2teamtype (const char *str) {
return type;
}
-void bg_config_read(void) {
+static void bg_config_read(void)
+{
struct config_t bg_conf;
struct config_setting_t *data = NULL;
const char *config_filename = "conf/battlegrounds.conf"; // FIXME hardcoded name
@@ -496,7 +510,8 @@ void bg_config_read(void) {
}
libconfig->destroy(&bg_conf);
}
-struct bg_arena *bg_name2arena(const char *name)
+
+static struct bg_arena *bg_name2arena(const char *name)
{
int i;
nullpo_retr(NULL, name);
@@ -516,7 +531,7 @@ struct bg_arena *bg_name2arena(const char *name)
* @return the position (starting at 1).
* @retval 0 if the queue doesn't exist or the given account ID isn't present in it.
*/
-int bg_id2pos(int queue_id, int account_id)
+static int bg_id2pos(int queue_id, int account_id)
{
struct script_queue *queue = script->queue(queue_id);
if (queue) {
@@ -529,7 +544,7 @@ int bg_id2pos(int queue_id, int account_id)
return 0;
}
-void bg_queue_ready_ack(struct bg_arena *arena, struct map_session_data *sd, bool response)
+static void bg_queue_ready_ack(struct bg_arena *arena, struct map_session_data *sd, bool response)
{
nullpo_retv(arena);
nullpo_retv(sd);
@@ -560,7 +575,8 @@ void bg_queue_ready_ack(struct bg_arena *arena, struct map_session_data *sd, boo
}
}
-void bg_queue_player_cleanup(struct map_session_data *sd) {
+static void bg_queue_player_cleanup(struct map_session_data *sd)
+{
nullpo_retv(sd);
if ( sd->bg_queue.client_has_bg_data ) {
if( sd->bg_queue.arena )
@@ -575,7 +591,9 @@ void bg_queue_player_cleanup(struct map_session_data *sd) {
sd->bg_queue.client_has_bg_data = 0;
sd->bg_queue.type = 0;
}
-void bg_match_over(struct bg_arena *arena, bool canceled) {
+
+static void bg_match_over(struct bg_arena *arena, bool canceled)
+{
struct script_queue *queue = script->queue(arena->queue_id);
int i;
@@ -597,7 +615,7 @@ void bg_match_over(struct bg_arena *arena, bool canceled) {
if (canceled)
clif->messagecolor_self(sd->fd, COLOR_RED, "BG Match Canceled: not enough players");
else
- pc_setglobalreg(sd, script->add_str(arena->delay_var), (unsigned int)time(NULL));
+ pc_setglobalreg(sd, script->add_variable(arena->delay_var), (unsigned int)time(NULL));
}
arena->begin_timer = INVALID_TIMER;
@@ -605,7 +623,9 @@ void bg_match_over(struct bg_arena *arena, bool canceled) {
/* reset queue */
script->queue_clear(arena->queue_id);
}
-void bg_begin(struct bg_arena *arena) {
+
+static void bg_begin(struct bg_arena *arena)
+{
struct script_queue *queue = script->queue(arena->queue_id);
int i, count = 0;
@@ -634,8 +654,8 @@ void bg_begin(struct bg_arena *arena) {
bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0);
/* 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);
+ mapreg->setreg(script->add_variable("$@bg_queue_id"),arena->queue_id);
+ mapreg->setregstr(script->add_variable("$@bg_delay_var$"),bg->gdelay_var);
count = 0;
for (i = 0; i < VECTOR_LENGTH(queue->entries); i++) {
@@ -644,31 +664,34 @@ void bg_begin(struct bg_arena *arena) {
if (sd == NULL || sd->bg_queue.ready != 1)
continue;
- mapreg->setreg(reference_uid(script->add_str("$@bg_member"), count), sd->status.account_id);
- mapreg->setreg(reference_uid(script->add_str("$@bg_member_group"), count),
+ mapreg->setreg(reference_uid(script->add_variable("$@bg_member"), count), sd->status.account_id);
+ mapreg->setreg(reference_uid(script->add_variable("$@bg_member_group"), count),
sd->bg_queue.type == BGQT_GUILD ? sd->status.guild_id :
sd->bg_queue.type == BGQT_PARTY ? sd->status.party_id :
0
);
- mapreg->setreg(reference_uid(script->add_str("$@bg_member_type"), count),
+ mapreg->setreg(reference_uid(script->add_variable("$@bg_member_type"), count),
sd->bg_queue.type == BGQT_GUILD ? 1 :
sd->bg_queue.type == BGQT_PARTY ? 2 :
0
);
count++;
}
- mapreg->setreg(script->add_str("$@bg_member_size"),count);
+ mapreg->setreg(script->add_variable("$@bg_member_size"),count);
npc->event_do(arena->npc_event);
}
}
-int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) {
+
+static int bg_begin_timer(int tid, int64 tick, int id, intptr_t data)
+{
bg->begin(bg->arena[id]);
bg->arena[id]->begin_timer = INVALID_TIMER;
return 0;
}
-int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) {
+static int bg_afk_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct s_mapiterator* iter;
struct map_session_data* sd;
int count = 0;
@@ -690,7 +713,8 @@ int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void bg_queue_pregame(struct bg_arena *arena) {
+static void bg_queue_pregame(struct bg_arena *arena)
+{
struct script_queue *queue;
int i;
nullpo_retv(arena);
@@ -705,13 +729,16 @@ void bg_queue_pregame(struct bg_arena *arena) {
}
arena->begin_timer = timer->add( timer->gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 );
}
-int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data) {
+
+static int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data)
+{
bg->queue_pregame(bg->arena[id]);
bg->arena[id]->fillup_timer = INVALID_TIMER;
return 0;
}
-void bg_queue_check(struct bg_arena *arena) {
+static void bg_queue_check(struct bg_arena *arena)
+{
int count;
struct script_queue *queue;
nullpo_retv(arena);
@@ -728,7 +755,9 @@ void bg_queue_check(struct bg_arena *arena) {
arena->fillup_timer = timer->add( timer->gettick() + (arena->fillup_duration*1000), bg->fillup_timer, arena->id, 0 );
}
}
-void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
+
+static void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type)
+{
enum BATTLEGROUNDS_QUEUE_ACK result = bg->can_queue(sd,arena,type);
struct script_queue *queue = NULL;
int i, count = 0;
@@ -809,7 +838,9 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
clif->bgqueue_ack(sd,BGQA_SUCCESS,arena->id);
bg->queue_check(arena);
}
-enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
+
+static enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type)
+{
int tick;
unsigned int tsec;
@@ -821,27 +852,27 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->min_level )
return BGQA_FAIL_LEVEL_INCORRECT;
- if ( !(sd->class_&JOBL_2) ) /* TODO: maybe make this a per-arena setting, so users may make custom arenas like baby-only,whatever. */
+ if ((sd->job & JOBL_2) == 0) /* TODO: maybe make this a per-arena setting, so users may make custom arenas like baby-only,whatever. */
return BGQA_FAIL_CLASS_INVALID;
tsec = (unsigned int)time(NULL);
- if ( ( tick = pc_readglobalreg(sd, script->add_str(bg->gdelay_var)) ) && tsec < tick ) {
+ if ( ( tick = pc_readglobalreg(sd, script->add_variable(bg->gdelay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
- sprintf(response, "You are a deserter! Wait %u minute(s) before you can apply again", (tick - tsec) / 60);
+ sprintf(response, msg_sd(sd, 456), (tick - tsec) / 60); // You are a deserter! Wait %u minute(s) before you can apply again
else
- sprintf(response, "You are a deserter! Wait %u seconds before you can apply again", (tick - tsec));
+ sprintf(response, msg_sd(sd, 457), (tick - tsec)); // You are a deserter! Wait %u seconds before you can apply again
clif->messagecolor_self(sd->fd, COLOR_RED, response);
return BGQA_FAIL_DESERTER;
}
- if ( ( tick = pc_readglobalreg(sd, script->add_str(arena->delay_var)) ) && tsec < tick ) {
+ if ( ( tick = pc_readglobalreg(sd, script->add_variable(arena->delay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
- sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %u minute(s)", (tick - tsec) / 60);
+ sprintf(response, msg_sd(sd, 458), (tick - tsec) / 60); // You can't reapply to this arena so fast. Apply to the different arena or wait %u minute(s)
else
- sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %u seconds", (tick - tsec));
+ sprintf(response, msg_sd(sd, 459), (tick - tsec)); // You can't reapply to this arena so fast. Apply to the different arena or wait %u seconds
clif->messagecolor_self(sd->fd, COLOR_RED, response);
return BGQA_FAIL_COOLDOWN;
}
@@ -861,11 +892,11 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
count++;
}
if ( count < arena->min_team_players ) {
- char response[117];
+ char response[121];
if( count != sd->guild->connect_member && sd->guild->connect_member >= arena->min_team_players )
- sprintf(response, "Can't apply: not enough members in your team/guild that have not entered the queue in individual mode, minimum is %d",arena->min_team_players);
+ sprintf(response, msg_sd(sd, 460), arena->min_team_players); // Can't apply: not enough members in your team/guild that have not entered the queue in individual mode, minimum is %d
else
- sprintf(response, "Can't apply: not enough members in your team/guild, minimum is %d",arena->min_team_players);
+ sprintf(response, msg_sd(sd, 461), arena->min_team_players); // Can't apply: not enough members in your team/guild, minimum is %d
clif->messagecolor_self(sd->fd, COLOR_RED, response);
return BGQA_FAIL_TEAM_COUNT;
}
@@ -893,11 +924,11 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
return BGQA_NOT_PARTY_GUILD_LEADER;
if( count < arena->min_team_players ) {
- char response[117];
+ char response[121];
if( count != p->party.count && p->party.count >= arena->min_team_players )
- sprintf(response, "Can't apply: not enough members in your team/party that have not entered the queue in individual mode, minimum is %d",arena->min_team_players);
+ sprintf(response, msg_sd(sd, 462), arena->min_team_players); // Can't apply: not enough members in your team/party that have not entered the queue in individual mode, minimum is %d
else
- sprintf(response, "Can't apply: not enough members in your team/party, minimum is %d",arena->min_team_players);
+ sprintf(response, msg_sd(sd, 463), arena->min_team_players); // Can't apply: not enough members in your team/party, minimum is %d
clif->messagecolor_self(sd->fd, COLOR_RED, response);
return BGQA_FAIL_TEAM_COUNT;
}
@@ -913,7 +944,9 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
}
return BGQA_SUCCESS;
}
-void do_init_battleground(bool minimal) {
+
+static void do_init_battleground(bool minimal)
+{
if (minimal)
return;
@@ -926,7 +959,7 @@ void do_init_battleground(bool minimal) {
/**
* @see DBApply
*/
-int bg_team_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int bg_team_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct battleground_data* bgd = DB->data2ptr(data);
@@ -935,7 +968,7 @@ int bg_team_db_final(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-void do_final_battleground(void)
+static void do_final_battleground(void)
{
bg->team_db->destroy(bg->team_db,bg->team_db_final);
@@ -948,7 +981,9 @@ void do_final_battleground(void)
aFree(bg->arena);
}
}
-void battleground_defaults(void) {
+
+void battleground_defaults(void)
+{
bg = &bg_s;
bg->queue_on = false;
diff --git a/src/map/battleground.h b/src/map/battleground.h
index 8657beaf8..b567dddd4 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -130,7 +130,7 @@ struct battleground_interface {
bool (*member_respawn) (struct map_session_data *sd);
int (*create) (unsigned short map_index, short rx, short ry, const char *ev, const char *dev);
int (*team_get_id) (struct block_list *bl);
- bool (*send_message) (struct map_session_data *sd, const char *mes, int len);
+ bool (*send_message) (struct map_session_data *sd, const char *mes);
int (*send_xy_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
int (*afk_timer) (int tid, int64 tick, int id, intptr_t data);
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 3828a3c14..2c2fc13ae 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,15 +35,16 @@
#include "common/socket.h" // RBUF*
#include "common/strlib.h" // safestrncpy
-struct buyingstore_interface buyingstore_s;
+static struct buyingstore_interface buyingstore_s;
struct buyingstore_interface *buyingstore;
/// Returns unique buying store id
-unsigned int buyingstore_getuid(void) {
+static unsigned int buyingstore_getuid(void)
+{
return buyingstore->nextid++;
}
-bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
+static bool buyingstore_setup(struct map_session_data *sd, unsigned char slots)
{
nullpo_retr(false, sd);
if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 )
@@ -80,7 +81,7 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
return true;
}
-void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
+static void buyingstore_create(struct map_session_data *sd, int zenylimit, unsigned char result, const char *storename, const struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub *itemlist, unsigned int count)
{
unsigned int i, weight, listidx;
@@ -90,7 +91,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
return;
}
- if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
+ if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->state.prevend || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
{// disabled or invalid input
sd->buyingstore.slots = 0;
clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
@@ -100,7 +101,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to buy (give zeny)
sd->buyingstore.slots = 0;
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
return;
}
@@ -127,13 +128,14 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
// check item list
for (i = 0; i < count; i++) {
// itemlist: <name id>.W <amount>.W <price>.L
- unsigned short nameid, amount;
+ int nameid;
+ unsigned short amount;
int price, idx;
struct item_data* id;
- nameid = RBUFW(itemlist,i*8+0);
- amount = RBUFW(itemlist,i*8+2);
- price = RBUFL(itemlist,i*8+4);
+ nameid = itemlist[i].itemId;
+ amount = itemlist[i].amount;
+ price = itemlist[i].price;
if( ( id = itemdb->exists(nameid) ) == NULL || amount == 0 )
{// invalid input
@@ -161,7 +163,8 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid );
if( listidx != i )
{// duplicate
- ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
+ ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%d, amount=%hu, account_id=%d, char_id=%d).\n",
+ nameid, amount, sd->status.account_id, sd->status.char_id);
break;
}
}
@@ -196,7 +199,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
clif->buyingstore_entry(sd);
}
-void buyingstore_close(struct map_session_data* sd)
+static void buyingstore_close(struct map_session_data *sd)
{
nullpo_retv(sd);
if (sd->state.buyingstore)
@@ -210,19 +213,19 @@ void buyingstore_close(struct map_session_data* sd)
}
}
-void buyingstore_open(struct map_session_data* sd, int account_id)
+static void buyingstore_open(struct map_session_data *sd, int account_id)
{
struct map_session_data* pl_sd;
nullpo_retv(sd);
- if( !battle_config.feature_buying_store || pc_istrading(sd) )
+ if (!battle_config.feature_buying_store || pc_istrading(sd) || sd->state.prevend)
{// not allowed to sell
return;
}
if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to sell
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
return;
}
@@ -240,8 +243,7 @@ void buyingstore_open(struct map_session_data* sd, int account_id)
clif->buyingstore_itemlist(sd, pl_sd);
}
-
-void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
+static void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub* itemlist, unsigned int count)
{
int zeny = 0;
unsigned int i, weight, listidx, k;
@@ -253,7 +255,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
return;
}
- if( !battle_config.feature_buying_store || pc_istrading(sd) )
+ if (!battle_config.feature_buying_store || pc_istrading(sd) || sd->state.prevend)
{// not allowed to sell
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
return;
@@ -261,7 +263,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to sell
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
return;
}
@@ -289,20 +291,21 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
// check item list
for( i = 0; i < count; i++ )
{// itemlist: <index>.W <name id>.W <amount>.W
- unsigned short nameid, amount;
+ int nameid;
+ unsigned short amount;
int index;
- index = RBUFW(itemlist,i*6+0)-2;
- nameid = RBUFW(itemlist,i*6+2);
- amount = RBUFW(itemlist,i*6+4);
+ index = itemlist[i].index - 2;
+ nameid = itemlist[i].itemId;
+ amount = itemlist[i].amount;
- if( i )
+ if (i)
{// duplicate check. as the client does this too, only malicious intent should be caught here
- ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index );
- if( k != i )
+ ARR_FIND(0, i, k, itemlist[k].index - 2 == index);
+ if (k != i)
{// duplicate
- ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n",
- RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id);
+ ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%d, prevamount=%d, nameid=%d, amount=%hu, account_id=%d, char_id=%d).\n",
+ (int)itemlist[k].itemId, (int)itemlist[k].amount, nameid, amount, sd->status.account_id, sd->status.char_id);
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
return;
}
@@ -361,14 +364,15 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
// process item list
for( i = 0; i < count; i++ )
{// itemlist: <index>.W <name id>.W <amount>.W
- unsigned short nameid, amount;
+ int nameid;
+ unsigned short amount;
int index;
- index = RBUFW(itemlist,i*6+0)-2;
- nameid = RBUFW(itemlist,i*6+2);
- amount = RBUFW(itemlist,i*6+4);
+ index = itemlist[i].index - 2;
+ nameid = itemlist[i].itemId;
+ amount = itemlist[i].amount;
- ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
+ ARR_FIND(0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
zeny = amount*pl_sd->buyingstore.items[listidx].price;
// move item
@@ -383,7 +387,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
// notify clients
clif->buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price);
- clif->buyingstore_update_item(pl_sd, nameid, amount);
+ clif->buyingstore_update_item(pl_sd, nameid, amount, sd->status.char_id, zeny);
}
if( map->save_settings&128 ) {
@@ -415,9 +419,8 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
}
}
-
/// Checks if an item is being bought in given player's buying store.
-bool buyingstore_search(struct map_session_data* sd, unsigned short nameid)
+static bool buyingstore_search(struct map_session_data *sd, int nameid)
{
unsigned int i;
@@ -436,10 +439,9 @@ bool buyingstore_search(struct map_session_data* sd, unsigned short nameid)
return true;
}
-
/// Searches for all items in a buyingstore, that match given ids, price and possible cards.
/// @return Whether or not the search should be continued.
-bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s)
+static bool buyingstore_searchall(struct map_session_data *sd, const struct s_search_store_search *s)
{
unsigned int i, idx;
struct s_buyingstore_item* it;
@@ -475,7 +477,8 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
;
}
- if( !searchstore->result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore->blankslots, 0) )
+ // TODO: add support for cards and options
+ if (!searchstore->result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore->blankslots, 0, buyingstore->blankoptions))
{// result set full
return false;
}
@@ -483,11 +486,14 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
return true;
}
-void buyingstore_defaults(void) {
+
+void buyingstore_defaults(void)
+{
buyingstore = &buyingstore_s;
buyingstore->nextid = 0;
- memset(buyingstore->blankslots,0,sizeof(buyingstore->blankslots));
+ memset(buyingstore->blankslots, 0, sizeof(buyingstore->blankslots));
+ memset(buyingstore->blankoptions, 0, sizeof(buyingstore->blankoptions));
/* */
buyingstore->setup = buyingstore_setup;
buyingstore->create = buyingstore_create;
@@ -497,5 +503,4 @@ void buyingstore_defaults(void) {
buyingstore->search = buyingstore_search;
buyingstore->searchall = buyingstore_searchall;
buyingstore->getuid = buyingstore_getuid;
-
}
diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h
index 1e277b7fa..a35167fbc 100644
--- a/src/map/buyingstore.h
+++ b/src/map/buyingstore.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,6 +30,8 @@ struct map_session_data;
* Declarations
**/
struct s_search_store_search;
+struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub;
+struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub;
/**
* Defines
@@ -61,7 +63,7 @@ enum e_buyingstore_failure {
struct s_buyingstore_item {
int price;
unsigned short amount;
- unsigned short nameid;
+ int nameid;
};
struct s_buyingstore {
@@ -75,14 +77,15 @@ struct s_buyingstore {
**/
struct buyingstore_interface {
unsigned int nextid;
- short blankslots[MAX_SLOTS]; // used when checking whether or not an item's card slots are blank
+ int blankslots[MAX_SLOTS]; // used when checking whether or not an item's card slots are blank
+ struct item_option blankoptions[MAX_ITEM_OPTIONS]; // used for search result temporary.
/* */
bool (*setup) (struct map_session_data* sd, unsigned char slots);
- void (*create) (struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
+ void (*create) (struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub* itemlist, unsigned int count);
void (*close) (struct map_session_data* sd);
void (*open) (struct map_session_data* sd, int account_id);
- void (*trade) (struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
- bool (*search) (struct map_session_data* sd, unsigned short nameid);
+ void (*trade) (struct map_session_data* sd, int account_id, unsigned int buyer_id, const struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub* itemlist, unsigned int count);
+ bool (*search) (struct map_session_data* sd, int nameid);
bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s);
unsigned int (*getuid) (void);
};
diff --git a/src/map/channel.c b/src/map/channel.c
index 3d1b3f975..43e903fc9 100644
--- a/src/map/channel.c
+++ b/src/map/channel.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
#include "map/instance.h"
#include "map/irc-bot.h"
#include "map/map.h"
+#include "map/npc.h"
#include "map/pc.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
@@ -43,7 +44,7 @@
#include <stdlib.h>
#include <string.h>
-struct channel_interface channel_s;
+static struct channel_interface channel_s;
struct channel_interface *channel;
static struct Channel_Config channel_config;
@@ -55,7 +56,7 @@ static struct Channel_Config channel_config;
* @param sd The issuer character, for character-specific channels (i.e. map, ally)
* @return a pointer to the channel, or NULL.
*/
-struct channel_data *channel_search(const char *name, struct map_session_data *sd)
+static struct channel_data *channel_search(const char *name, struct map_session_data *sd)
{
const char *realname = name;
if (!realname || !*realname)
@@ -94,7 +95,7 @@ struct channel_data *channel_search(const char *name, struct map_session_data *s
* @param color The channel chat color.
* @return A pointer to the created channel.
*/
-struct channel_data *channel_create(enum channel_types type, const char *name, unsigned char color)
+static struct channel_data *channel_create(enum channel_types type, const char *name, unsigned char color)
{
struct channel_data *chan;
@@ -122,7 +123,7 @@ struct channel_data *channel_create(enum channel_types type, const char *name, u
*
* @param chan The channel to delete
*/
-void channel_delete(struct channel_data *chan)
+static void channel_delete(struct channel_data *chan)
{
nullpo_retv(chan);
@@ -155,7 +156,7 @@ void channel_delete(struct channel_data *chan)
* @param chan The channel to edit.
* @param pass The password to set. Pass NULL to remove existing passwords.
*/
-void channel_set_password(struct channel_data *chan, const char *password)
+static void channel_set_password(struct channel_data *chan, const char *password)
{
nullpo_retv(chan);
if (password)
@@ -175,7 +176,7 @@ void channel_set_password(struct channel_data *chan, const char *password)
* @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions.
* @retval HCS_STATUS_FAIL in case of generic failure.
*/
-enum channel_operation_status channel_ban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
+static enum channel_operation_status channel_ban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
{
struct channel_ban_entry *entry = NULL;
@@ -214,7 +215,7 @@ enum channel_operation_status channel_ban(struct channel_data *chan, const struc
* @retval HCS_STATUS_NOPERM if the source character doesn't have enough permissions.
* @retval HCS_STATUS_FAIL in case of generic failure.
*/
-enum channel_operation_status channel_unban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
+static enum channel_operation_status channel_unban(struct channel_data *chan, const struct map_session_data *ssd, struct map_session_data *tsd)
{
nullpo_retr(HCS_STATUS_FAIL, chan);
@@ -250,7 +251,7 @@ enum channel_operation_status channel_unban(struct channel_data *chan, const str
* @param chan The channel.
* @param options The new options set to apply.
*/
-void channel_set_options(struct channel_data *chan, unsigned int options)
+static void channel_set_options(struct channel_data *chan, unsigned int options)
{
nullpo_retv(chan);
@@ -266,7 +267,7 @@ void channel_set_options(struct channel_data *chan, unsigned int options)
*
* If no source character is specified, it'll send an anonymous message.
*/
-void channel_send(struct channel_data *chan, struct map_session_data *sd, const char *msg)
+static void channel_send(struct channel_data *chan, struct map_session_data *sd, const char *msg)
{
char message[150];
nullpo_retv(chan);
@@ -275,15 +276,26 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const
if (sd && chan->msg_delay != 0
&& DIFF_TICK(sd->hchsysch_tick + chan->msg_delay*1000, timer->gettick()) > 0
&& !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
- clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1455));
+ char output[CHAT_SIZE_MAX];
+ sprintf(output, msg_sd(sd, 1455), DIFF_TICK(sd->hchsysch_tick + chan->msg_delay * 1000, timer->gettick()) / 1000); // "You cannot send a message to this channel for another %d seconds."
+ clif->messagecolor_self(sd->fd, COLOR_RED, output);
return;
} else if (sd) {
+ int i;
+
safesnprintf(message, 150, "[ #%s ] %s : %s", chan->name, sd->status.name, msg);
clif->channel_msg(chan,sd,message);
if (chan->type == HCS_TYPE_IRC)
ircbot->relay(sd->status.name,msg);
if (chan->msg_delay != 0)
sd->hchsysch_tick = timer->gettick();
+
+ for (i = 0; i < MAX_EVENTQUEUE; i++) {
+ if (chan->handlers[i][0] != '\0') {
+ pc->setregstr(sd, script->add_variable("@channelmes$"), msg);
+ npc->event(sd, chan->handlers[i], 0);
+ }
+ }
} else {
safesnprintf(message, 150, "[ #%s ] %s", chan->name, msg);
clif->channel_msg2(chan, message);
@@ -299,7 +311,7 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const
* @param sd The character
* @param stealth If true, hide join announcements.
*/
-void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bool stealth)
+static void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bool stealth)
{
nullpo_retv(chan);
nullpo_retv(sd);
@@ -307,17 +319,17 @@ void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bo
if (idb_put(chan->users, sd->status.char_id, sd))
return;
- RECREATE(sd->channels, struct channel_data *, ++sd->channel_count);
- sd->channels[sd->channel_count - 1] = chan;
+ VECTOR_ENSURE(sd->channels, 1, 1);
+ VECTOR_PUSH(sd->channels, chan);
if (!stealth && (chan->options&HCS_OPT_ANNOUNCE_JOIN)) {
char message[60];
- sprintf(message, "#%s '%s' joined",chan->name,sd->status.name);
+ sprintf(message, msg_txt(897), chan->name, sd->status.name); // #%s '%s' joined
clif->channel_msg(chan,sd,message);
}
/* someone is cheating, we kindly disconnect the bastard */
- if (sd->channel_count > 200) {
+ if (VECTOR_LENGTH(sd->channels) > 200) {
sockt->eof(sd->fd);
}
@@ -339,7 +351,7 @@ void channel_join_sub(struct channel_data *chan, struct map_session_data *sd, bo
* @retval HCS_STATUS_BANNED if the character is in the channel's ban list
* @retval HCS_STATUS_FAIL in case of generic error
*/
-enum channel_operation_status channel_join(struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent)
+static enum channel_operation_status channel_join(struct channel_data *chan, struct map_session_data *sd, const char *password, bool silent)
{
bool stealth = false;
@@ -397,41 +409,25 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map
* @param chan The channel to leave
* @param sd The character
*/
-void channel_leave_sub(struct channel_data *chan, struct map_session_data *sd)
+static void channel_leave_sub(struct channel_data *chan, struct map_session_data *sd)
{
- unsigned char i;
+ int i;
nullpo_retv(chan);
nullpo_retv(sd);
- for (i = 0; i < sd->channel_count; i++) {
- if (sd->channels[i] == chan) {
- sd->channels[i] = NULL;
- break;
- }
- }
- if (i < sd->channel_count) {
- unsigned char cursor = 0;
- for (i = 0; i < sd->channel_count; i++) {
- if (sd->channels[i] == NULL)
- continue;
- if (cursor != i) {
- sd->channels[cursor] = sd->channels[i];
- }
- cursor++;
- }
- if (!(sd->channel_count = cursor)) {
- aFree(sd->channels);
- sd->channels = NULL;
- }
+ ARR_FIND(0, VECTOR_LENGTH(sd->channels), i, VECTOR_INDEX(sd->channels, i) == chan);
+ if (i < VECTOR_LENGTH(sd->channels)) {
+ VECTOR_ERASE(sd->channels, i);
}
}
+
/**
* Leaves a channel.
*
* @param chan The channel to leave
* @param sd The character
*/
-void channel_leave(struct channel_data *chan, struct map_session_data *sd)
+static void channel_leave(struct channel_data *chan, struct map_session_data *sd)
{
nullpo_retv(chan);
nullpo_retv(sd);
@@ -446,7 +442,7 @@ void channel_leave(struct channel_data *chan, struct map_session_data *sd)
channel->delete(chan);
} else if (!channel->config->closing && (chan->options & HCS_OPT_ANNOUNCE_JOIN)) {
char message[60];
- sprintf(message, "#%s '%s' left",chan->name,sd->status.name);
+ sprintf(message, msg_txt(898), chan->name, sd->status.name); // #%s '%s' left
clif->channel_msg(chan,sd,message);
}
@@ -460,17 +456,12 @@ void channel_leave(struct channel_data *chan, struct map_session_data *sd)
*
* @param sd The target character
*/
-void channel_quit(struct map_session_data *sd)
+static void channel_quit(struct map_session_data *sd)
{
nullpo_retv(sd);
- while (sd->channel_count > 0) {
+ while (VECTOR_LENGTH(sd->channels) > 0) {
// Loop downward to avoid unnecessary array compactions by channel_leave
- struct channel_data *chan = sd->channels[sd->channel_count-1];
-
- if (chan == NULL) {
- sd->channel_count--;
- continue;
- }
+ struct channel_data *chan = VECTOR_LAST(sd->channels);
channel->leave(chan, sd);
}
@@ -481,7 +472,7 @@ void channel_quit(struct map_session_data *sd)
*
* @param sd The target character (sd must be non null)
*/
-void channel_map_join(struct map_session_data *sd)
+static void channel_map_join(struct map_session_data *sd)
{
nullpo_retv(sd);
if (sd->state.autotrade || sd->state.standalone)
@@ -497,7 +488,7 @@ void channel_map_join(struct map_session_data *sd)
channel->join(map->list[sd->bl.m].channel, sd, "", false);
}
-void channel_irc_join(struct map_session_data *sd)
+static void channel_irc_join(struct map_session_data *sd)
{
struct channel_data *chan = ircbot->channel;
@@ -519,7 +510,7 @@ void channel_irc_join(struct map_session_data *sd)
* @param g_source Source guild
* @param g_ally Allied guild
*/
-void channel_guild_join_alliance(const struct guild *g_source, const struct guild *g_ally)
+static void channel_guild_join_alliance(const struct guild *g_source, const struct guild *g_ally)
{
struct channel_data *chan;
@@ -547,7 +538,7 @@ void channel_guild_join_alliance(const struct guild *g_source, const struct guil
* @param g_source Source guild
* @param g_ally Former allied guild
*/
-void channel_guild_leave_alliance(const struct guild *g_source, const struct guild *g_ally)
+static void channel_guild_leave_alliance(const struct guild *g_source, const struct guild *g_ally)
{
struct channel_data *chan;
@@ -571,22 +562,21 @@ void channel_guild_leave_alliance(const struct guild *g_source, const struct gui
*
* @param sd The character (must be non null)
*/
-void channel_quit_guild(struct map_session_data *sd)
+static void channel_quit_guild(struct map_session_data *sd)
{
- unsigned char i;
-
nullpo_retv(sd);
- for (i = 0; i < sd->channel_count; i++) {
- struct channel_data *chan = sd->channels[i];
+ for (int i = VECTOR_LENGTH(sd->channels) - 1; i >= 0; i--) {
+ // Loop downward to avoid issues when channel->leave() compacts the array
+ struct channel_data *chan = VECTOR_INDEX(sd->channels, i);
- if (chan == NULL || chan->type != HCS_TYPE_ALLY)
+ if (chan->type != HCS_TYPE_ALLY)
continue;
channel->leave(chan, sd);
}
}
-void read_channels_config(void)
+static void read_channels_config(void)
{
struct config_t channels_conf;
struct config_setting_t *chsys = NULL;
@@ -609,7 +599,11 @@ void read_channels_config(void)
local_autojoin = 0, ally_autojoin = 0,
allow_user_channel_creation = 0,
irc_enabled = 0,
- irc_autojoin = 0;
+ irc_autojoin = 0,
+ irc_flood_protection_rate = 0,
+ irc_flood_protection_burst = 0,
+ irc_flood_protection_enabled = 0,
+ channel_opt_msg_delay = 10;
if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
local_name = "map";
@@ -640,58 +634,52 @@ void read_channels_config(void)
const char *irc_server, *irc_channel,
*irc_nick, *irc_nick_pw;
int irc_use_ghost = 0;
- if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
- if( !strstr(irc_server,":") ) {
+ if (!libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server)) {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
+ } else {
+ char *server = aStrdup(irc_server);
+ char *port = strchr(server, ':');
+ if (port == NULL) {
+ channel->config->irc = false;
+ ShowWarning("channels.conf: network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
+ } else if ((size_t)(port-server) > sizeof channel->config->irc_server - 1) {
channel->config->irc = false;
- ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
+ ShowWarning("channels.conf: server name is too long in 'irc_channel_network', disabling irc channel...\n");
} else {
- unsigned char d = 0, dlen = strlen(irc_server);
- char server[40];
- if (dlen > 39)
- dlen = 39;
- memset(server, '\0', sizeof(server));
-
- for(d = 0; d < dlen; d++) {
- if(irc_server[d] == ':') {
- memcpy(server, irc_server, d);
- safestrncpy(channel->config->irc_server, server, 40);
- memcpy(server, &irc_server[d+1], dlen - d - 1);
- channel->config->irc_server_port = atoi(server);
- break;
- }
- }
+ *port = '\0';
+ port++;
+ safestrncpy(channel->config->irc_server, server, sizeof channel->config->irc_server);
+ channel->config->irc_server_port = atoi(port);
}
- } else {
- channel->config->irc = false;
- ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
+ aFree(server);
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
+ if (libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel)) {
safestrncpy(channel->config->irc_channel, irc_channel, 50);
- else {
+ } else {
channel->config->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
- if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
+ if (libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick)) {
+ if (strcmpi(irc_nick,"Hercules_chSysBot") == 0) {
sprintf(channel->config->irc_nick, "Hercules_chSysBot%d",rnd()%777);
- } else
+ } else {
safestrncpy(channel->config->irc_nick, irc_nick, 40);
+ }
} else {
channel->config->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
+ if (libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw)) {
safestrncpy(channel->config->irc_nick_pw, irc_nick_pw, 30);
config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
channel->config->irc_use_ghost = irc_use_ghost;
}
-
}
libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
libconfig->setting_lookup_bool(settings, "irc_channel_autojoin", &irc_autojoin);
-
if (local_autojoin)
channel->config->local_autojoin = true;
if (ally_autojoin)
@@ -699,6 +687,26 @@ void read_channels_config(void)
if (irc_autojoin)
channel->config->irc_autojoin = true;
+ libconfig->setting_lookup_bool(settings, "irc_flood_protection_enabled", &irc_flood_protection_enabled);
+
+ if (irc_flood_protection_enabled) {
+ ircbot->flood_protection_enabled = true;
+
+ libconfig->setting_lookup_int(settings, "irc_flood_protection_rate", &irc_flood_protection_rate);
+ libconfig->setting_lookup_int(settings, "irc_flood_protection_burst", &irc_flood_protection_burst);
+
+ if (irc_flood_protection_rate > 0)
+ ircbot->flood_protection_rate = irc_flood_protection_rate;
+ else
+ ircbot->flood_protection_rate = 1000;
+ if (irc_flood_protection_burst > 0)
+ ircbot->flood_protection_burst = irc_flood_protection_burst;
+ else
+ ircbot->flood_protection_burst = 3;
+ } else {
+ ircbot->flood_protection_enabled = false;
+ }
+
libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
if( allow_user_channel_creation )
@@ -791,6 +799,16 @@ void read_channels_config(void)
}
}
+ libconfig->setting_lookup_int(settings, "channel_opt_msg_delay", &channel_opt_msg_delay);
+ if (channel_opt_msg_delay < 0) {
+ ShowWarning("channels.conf: channel_opt_msg_delay value '%d' must be from 0-255. Defaulting to 0...\n", channel_opt_msg_delay);
+ channel_opt_msg_delay = 0;
+ } else if (channel_opt_msg_delay > 255) {
+ ShowWarning("channels.conf: channel_opt_msg_delay value '%d' must be from 0-255. Defaulting to 255...\n", channel_opt_msg_delay);
+ channel_opt_msg_delay = 255;
+ }
+ channel->config->channel_opt_msg_delay = channel_opt_msg_delay;
+
ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename);
}
libconfig->destroy(&channels_conf);
@@ -799,7 +817,7 @@ void read_channels_config(void)
/*==========================================
*
*------------------------------------------*/
-int do_init_channel(bool minimal)
+static int do_init_channel(bool minimal)
{
if (minimal)
return 0;
@@ -811,11 +829,10 @@ int do_init_channel(bool minimal)
return 0;
}
-void do_final_channel(void)
+static void do_final_channel(void)
{
struct DBIterator *iter = db_iterator(channel->db);
struct channel_data *chan;
- unsigned char i;
for( chan = dbi_first(iter); dbi_exists(iter); chan = dbi_next(iter) ) {
channel->delete(chan);
@@ -823,7 +840,7 @@ void do_final_channel(void)
dbi_destroy(iter);
- for(i = 0; i < channel->config->colors_count; i++) {
+ for (int i = 0; i < channel->config->colors_count; i++) {
aFree(channel->config->colors_name[i]);
}
diff --git a/src/map/channel.h b/src/map/channel.h
index e8696fd90..8f91b0777 100644
--- a/src/map/channel.h
+++ b/src/map/channel.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,8 @@
#include "common/hercules.h"
#include "common/mmo.h"
+#include "map/map.h" // EVENT_NAME_LENGTH, MAX_EVENTQUEUE
+
/**
* Declarations
**/
@@ -73,6 +75,7 @@ struct Channel_Config {
char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30];
unsigned short irc_server_port;
bool irc_use_ghost;
+ int channel_opt_msg_delay;
};
struct channel_ban_entry {
@@ -85,6 +88,7 @@ struct channel_data {
unsigned char color;
struct DBMap *users;
struct DBMap *banned;
+ char handlers[MAX_EVENTQUEUE][EVENT_NAME_LENGTH];
unsigned int options;
unsigned int owner;
enum channel_types type;
diff --git a/src/map/chat.c b/src/map/chat.c
index d60b9bece..097fbdca4 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "map/npc.h" // npc_event_do()
#include "map/pc.h"
#include "map/skill.h" // ext_skill_unit_onplace()
+#include "map/achievement.h"
#include "common/cbasetypes.h"
#include "common/memmgr.h"
#include "common/mmo.h"
@@ -39,12 +40,12 @@
#include <stdio.h>
#include <string.h>
-struct chat_interface chat_s;
+static struct chat_interface chat_s;
struct chat_interface *chat;
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
-struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
+static struct chat_data *chat_createchat(struct block_list *bl, const char *title, const char *pass, int limit, bool pub, int trigger, const char *ev, int zeny, int min_level, int max_level)
{
struct chat_data* cd;
nullpo_retr(NULL, bl);
@@ -62,8 +63,8 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons
cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
cd->trigger = trigger;
cd->zeny = zeny;
- cd->minLvl = minLvl;
- cd->maxLvl = maxLvl;
+ cd->min_level = min_level;
+ cd->max_level = max_level;
memset(cd->usersd, 0, sizeof(cd->usersd));
cd->owner = bl;
safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));
@@ -91,23 +92,24 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons
/*==========================================
* player chatroom creation
*------------------------------------------*/
-bool chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) {
+static bool chat_createpcchat(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub)
+{
struct chat_data* cd;
nullpo_ret(sd);
nullpo_ret(title);
nullpo_ret(pass);
- if( sd->chatID )
+ if (sd->chat_id != 0)
return false; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
- if( sd->state.vending || sd->state.buyingstore )
+ if (sd->state.vending || sd->state.prevend || sd->state.buyingstore)
{// not chat, when you already have a store open
return false;
}
if( map->list[sd->bl.m].flag.nochat ) {
- clif->message(sd->fd, msg_sd(sd,281));
- return false; //Can't create chatrooms on this map.
+ clif->message(sd->fd, msg_sd(sd,281)); // You can't create chat rooms in this map
+ return false;
}
if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOCHAT) ) {
@@ -125,6 +127,7 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha
pc_stop_attack(sd);
clif->createchat(sd,0); // 0 = success
clif->dispchat(cd,0);
+ achievement->validate_chatroom_create(sd); // Achievements [Smokexyz/Hercules]
return true;
}
clif->createchat(sd,1); // 1 = Room limit exceeded
@@ -135,15 +138,18 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha
/*==========================================
* join an existing chatroom
*------------------------------------------*/
-bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
+static bool chat_joinchat(struct map_session_data *sd, int chatid, const char *pass)
+{
struct chat_data* cd;
nullpo_ret(sd);
nullpo_ret(pass);
cd = map->id2cd(chatid);
- if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit )
- {
+ if (cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m
+ || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->chat_id != 0
+ || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit
+ ) {
clif->joinchatfail(sd,0); // room full
return false;
}
@@ -154,8 +160,8 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
return false;
}
- if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) {
- if(sd->status.base_level < cd->minLvl)
+ if (sd->status.base_level < cd->min_level || sd->status.base_level > cd->max_level) {
+ if(sd->status.base_level < cd->min_level)
clif->joinchatfail(sd,5); // too low level
else
clif->joinchatfail(sd,6); // too high level
@@ -177,6 +183,9 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
cd->usersd[cd->users] = sd;
cd->users++;
+ if (cd->owner->type == BL_PC)
+ achievement->validate_chatroom_members(BL_UCAST(BL_PC, cd->owner), cd->users);
+
pc_setchatid(sd,cd->bl.id);
clif->joinchatok(sd, cd); //To the person who newly joined the list of all
@@ -188,7 +197,6 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
return true;
}
-
/*==========================================
* Leave a chatroom
* Return
@@ -197,15 +205,16 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
* 2: Chat room deleted (chat room empty)
* 3: Owner changed (Owner left and a new one as assigned)
*------------------------------------------*/
-int chat_leavechat(struct map_session_data* sd, bool kicked) {
+static int chat_leavechat(struct map_session_data *sd, bool kicked)
+{
struct chat_data* cd;
int i;
int leavechar;
nullpo_retr(0, sd);
- cd = map->id2cd(sd->chatID);
- if( cd == NULL ) {
+ cd = map->id2cd(sd->chat_id);
+ if (cd == NULL) {
pc_setchatid(sd, 0);
return 0;
}
@@ -246,6 +255,14 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) {
}
if( leavechar == 0 && cd->owner->type == BL_PC ) {
+
+ // check if new location are CELL_CHKNOCHAT
+ if (map->getcell(cd->usersd[0]->bl.m, NULL, cd->usersd[0]->bl.x, cd->usersd[0]->bl.y, CELL_CHKNOCHAT)) {
+ for (i = (cd->users - 1); i >= 0; i--)
+ chat->leave(cd->usersd[i], false);
+ return 2;
+ }
+
// Set and announce new owner
cd->owner = &cd->usersd[0]->bl;
clif->changechatowner(cd, cd->usersd[0]);
@@ -271,7 +288,8 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) {
* 0: User not found/Missing data
* 1: Success
*------------------------------------------*/
-bool chat_changechatowner(struct map_session_data* sd, const char* nextownername) {
+static bool chat_changechatowner(struct map_session_data *sd, const char *nextownername)
+{
struct chat_data* cd;
struct map_session_data* tmpsd;
int i;
@@ -279,7 +297,7 @@ bool chat_changechatowner(struct map_session_data* sd, const char* nextownername
nullpo_ret(sd);
nullpo_ret(nextownername);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
@@ -317,14 +335,15 @@ bool chat_changechatowner(struct map_session_data* sd, const char* nextownername
* 0: Missing data
* 1: Success
*------------------------------------------*/
-bool chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) {
+static bool chat_changechatstatus(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub)
+{
struct chat_data* cd;
nullpo_ret(sd);
nullpo_ret(title);
nullpo_ret(pass);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
@@ -345,14 +364,15 @@ bool chat_changechatstatus(struct map_session_data* sd, const char* title, const
* 0: User cannot be kicked (is gm)/Missing data
* 1: Success
*------------------------------------------*/
-bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
+static bool chat_kickchat(struct map_session_data *sd, const char *kickusername)
+{
struct chat_data* cd;
int i;
nullpo_ret(sd);
nullpo_ret(kickusername);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
@@ -373,7 +393,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
/*==========================================
* Creates a chat room for the npc
*------------------------------------------*/
-bool chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
+static bool chat_createnpcchat(struct npc_data *nd, const char *title, int limit, bool pub, int trigger, const char *ev, int zeny, int min_level, int max_level)
{
struct chat_data* cd;
nullpo_ret(nd);
@@ -383,12 +403,12 @@ bool chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool
return false;
}
- if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL ) {
+ if (zeny > MAX_ZENY || max_level > MAX_LEVEL) {
ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname);
return false;
}
- cd = chat->create(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl);
+ cd = chat->create(&nd->bl, title, "", limit, pub, trigger, ev, zeny, min_level, max_level);
if( cd ) {
nd->chat_id = cd->bl.id;
@@ -405,7 +425,8 @@ bool chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool
* 0: Missing data
* 1: Success
*------------------------------------------*/
-bool chat_deletenpcchat(struct npc_data* nd) {
+static bool chat_deletenpcchat(struct npc_data *nd)
+{
struct chat_data *cd;
nullpo_ret(nd);
@@ -429,7 +450,7 @@ bool chat_deletenpcchat(struct npc_data* nd) {
* 0: Couldn't trigger / Missing data
* 1: Success
*------------------------------------------*/
-bool chat_triggerevent(struct chat_data *cd)
+static bool chat_triggerevent(struct chat_data *cd)
{
nullpo_ret(cd);
@@ -443,7 +464,7 @@ bool chat_triggerevent(struct chat_data *cd)
/// Enables the event of the chat room.
/// At most, 127 users are needed to trigger the event.
-bool chat_enableevent(struct chat_data* cd)
+static bool chat_enableevent(struct chat_data *cd)
{
nullpo_ret(cd);
@@ -453,7 +474,7 @@ bool chat_enableevent(struct chat_data* cd)
}
/// Disables the event of the chat room
-bool chat_disableevent(struct chat_data* cd)
+static bool chat_disableevent(struct chat_data *cd)
{
nullpo_ret(cd);
@@ -462,7 +483,7 @@ bool chat_disableevent(struct chat_data* cd)
}
/// Kicks all the users from the chat room.
-bool chat_npckickall(struct chat_data* cd)
+static bool chat_npckickall(struct chat_data *cd)
{
nullpo_ret(cd);
@@ -477,7 +498,8 @@ bool chat_npckickall(struct chat_data* cd)
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
-void chat_defaults(void) {
+void chat_defaults(void)
+{
chat = &chat_s;
/* funcs */
diff --git a/src/map/chat.h b/src/map/chat.h
index 59d61a46e..6c571c62e 100644
--- a/src/map/chat.h
+++ b/src/map/chat.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,8 +41,8 @@ struct chat_data {
uint8 limit; ///< join limit
uint8 trigger; ///< number of users needed to trigger event
uint32 zeny; ///< required zeny to join
- uint32 minLvl; ///< minimum base level to join
- uint32 maxLvl; ///< maximum base level allowed to join
+ int min_level; ///< minimum base level to join
+ int max_level; ///< maximum base level allowed to join
struct map_session_data* usersd[MAX_CHAT_USERS];
struct block_list* owner;
char npc_event[EVENT_NAME_LENGTH];
@@ -63,13 +63,13 @@ struct chat_interface {
bool (*change_owner) (struct map_session_data* sd, const char* nextownername);
bool (*change_status) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
bool (*kick) (struct map_session_data* sd, const char* kickusername);
- bool (*create_npc_chat) (struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
+ bool (*create_npc_chat) (struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int min_level, int max_level);
bool (*delete_npc_chat) (struct npc_data* nd);
bool (*enable_event) (struct chat_data* cd);
bool (*disable_event) (struct chat_data* cd);
bool (*npc_kick_all) (struct chat_data* cd);
bool (*trigger_event) (struct chat_data *cd);
- struct chat_data* (*create) (struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
+ struct chat_data* (*create) (struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int min_level, int max_level);
};
#ifdef HERCULES_CORE
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 52af1137e..b131907e0 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
*/
#define HERCULES_CORE
-#include "config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT
+#include "config/core.h" // AUTOTRADE_PERSISTENCY
#include "chrif.h"
#include "map/battle.h"
@@ -53,7 +53,7 @@
#include <stdlib.h>
#include <sys/types.h>
-struct chrif_interface chrif_s;
+static struct chrif_interface chrif_s;
struct chrif_interface *chrif;
//Used Packets:
@@ -109,18 +109,21 @@ struct chrif_interface *chrif;
//This define should spare writing the check in every function. [Skotlex]
#define chrif_check(a) do { if(!chrif->isconnected()) return a; } while(0)
+#if 0 // Unused
/// Resets all the data.
-void chrif_reset(void) __attribute__ ((noreturn));
-void chrif_reset(void)
+static void chrif_reset(void) __attribute__ ((noreturn));
+static void chrif_reset(void)
{
// TODO kick everyone out and reset everything [FlavioJS]
exit(EXIT_FAILURE);
}
+#endif // 0
/// Checks the conditions for the server to stop.
/// Releases the cookie when all characters are saved.
/// If all the conditions are met, it stops the core loop.
-void chrif_check_shutdown(void) {
+static void chrif_check_shutdown(void)
+{
if( core->runflag != MAPSERVER_ST_SHUTDOWN )
return;
if( db_size(chrif->auth_db) > 0 )
@@ -128,16 +131,19 @@ void chrif_check_shutdown(void) {
core->runflag = CORE_ST_STOP;
}
-struct auth_node* chrif_search(int account_id) {
+static struct auth_node* chrif_search(int account_id)
+{
return (struct auth_node*)idb_get(chrif->auth_db, account_id);
}
-struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) {
+static struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state)
+{
struct auth_node *node = chrif->search(account_id);
return ( node && node->char_id == char_id && node->state == state ) ? node : NULL;
}
-bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
+static bool chrif_auth_delete(int account_id, int char_id, enum sd_state state)
+{
struct auth_node *node;
if ( (node = chrif->auth_check(account_id, char_id, state) ) ) {
@@ -165,7 +171,7 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
}
//Moves the sd character to the auth_db structure.
-bool chrif_sd_to_auth(struct map_session_data *sd, enum sd_state state)
+static bool chrif_sd_to_auth(struct map_session_data *sd, enum sd_state state)
{
struct auth_node *node;
@@ -194,7 +200,7 @@ bool chrif_sd_to_auth(struct map_session_data *sd, enum sd_state state)
return true;
}
-bool chrif_auth_logout(struct map_session_data *sd, enum sd_state state)
+static bool chrif_auth_logout(struct map_session_data *sd, enum sd_state state)
{
nullpo_retr(false, sd);
if(sd->fd && state == ST_LOGOUT) { //Disassociate player, and free it after saving ack returns. [Skotlex]
@@ -207,7 +213,7 @@ bool chrif_auth_logout(struct map_session_data *sd, enum sd_state state)
return chrif->sd_to_auth(sd, state);
}
-bool chrif_auth_finished(struct map_session_data *sd)
+static bool chrif_auth_finished(struct map_session_data *sd)
{
struct auth_node *node;
@@ -223,28 +229,34 @@ bool chrif_auth_finished(struct map_session_data *sd)
}
// sets char-server's user id
-void chrif_setuserid(char *id) {
+static void chrif_setuserid(char *id)
+{
nullpo_retv(id);
memcpy(chrif->userid, id, NAME_LENGTH);
}
// sets char-server's password
-void chrif_setpasswd(char *pwd) {
+static void chrif_setpasswd(char *pwd)
+{
nullpo_retv(pwd);
memcpy(chrif->passwd, pwd, NAME_LENGTH);
}
// security check, prints warning if using default password
-void chrif_checkdefaultlogin(void) {
+static void chrif_checkdefaultlogin(void)
+{
+#ifndef BUILDBOT
if (strcmp(chrif->userid, "s1")==0 && strcmp(chrif->passwd, "p1")==0) {
ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
ShowNotice("and then edit your user/password in conf/map-server.conf (or conf/import/map_conf.txt)\n");
}
+#endif
}
// sets char-server's ip address
-bool chrif_setip(const char* ip) {
+static bool chrif_setip(const char *ip)
+{
char ip_str[16];
nullpo_retr(false, ip);
@@ -261,12 +273,14 @@ bool chrif_setip(const char* ip) {
}
// sets char-server's port number
-void chrif_setport(uint16 port) {
+static void chrif_setport(uint16 port)
+{
chrif->port = port;
}
// says whether the char-server is connected or not
-int chrif_isconnected(void) {
+static int chrif_isconnected(void)
+{
return (chrif->fd > 0 && sockt->session[chrif->fd] != NULL && chrif->state == 2);
}
@@ -276,7 +290,8 @@ int chrif_isconnected(void) {
* Flag = 2: Character is changing map-servers
*------------------------------------------*/
// TODO: Flag enum
-bool chrif_save(struct map_session_data *sd, int flag) {
+static bool chrif_save(struct map_session_data *sd, int flag)
+{
nullpo_ret(sd);
pc->makesavestatus(sd);
@@ -321,12 +336,18 @@ bool chrif_save(struct map_session_data *sd, int flag) {
elemental->save(sd->ed);
if( sd->save_quest )
intif->quest_save(sd);
+ if (VECTOR_LENGTH(sd->achievement) > 0)
+ intif->achievements_save(sd);
+
+ if (sd->storage.received == true && sd->storage.save == true)
+ intif->send_account_storage(sd);
return true;
}
// connects to char-server (plaintext)
-void chrif_connect(int fd) {
+static void chrif_connect(int fd)
+{
ShowStatus("Logging in to char server...\n");
WFIFOHEAD(fd,60);
WFIFOW(fd,0) = 0x2af8;
@@ -339,7 +360,8 @@ void chrif_connect(int fd) {
}
// sends maps to char-server
-void chrif_sendmap(int fd) {
+static void chrif_sendmap(int fd)
+{
int i;
ShowStatus("Sending maps to char server...\n");
@@ -354,7 +376,8 @@ void chrif_sendmap(int fd) {
}
// receive maps from some other map-server (relayed via char-server)
-void chrif_recvmap(int fd) {
+static void chrif_recvmap(int fd)
+{
int i, j;
uint32 ip = ntohl(RFIFOL(fd,4));
uint16 port = ntohs(RFIFOW(fd,8));
@@ -370,7 +393,8 @@ void chrif_recvmap(int fd) {
}
// remove specified maps (used when some other map-server disconnects)
-void chrif_removemap(int fd) {
+static void chrif_removemap(int fd)
+{
int i, j;
uint32 ip = RFIFOL(fd,4);
uint16 port = RFIFOW(fd,8);
@@ -385,13 +409,15 @@ void chrif_removemap(int fd) {
}
// received after a character has been "final saved" on the char-server
-void chrif_save_ack(int fd) {
+static void chrif_save_ack(int fd)
+{
chrif->auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT);
chrif->check_shutdown();
}
// request to move a character between mapservers
-bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) {
+static bool chrif_changemapserver(struct map_session_data *sd, uint32 ip, uint16 port)
+{
nullpo_ret(sd);
if (chrif->other_mapserver_count < 1) {//No other map servers are online!
@@ -422,7 +448,8 @@ bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port)
/// 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) {
+static 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;
if ( !( node = chrif->auth_check(account_id, char_id, ST_MAPCHANGE) ) )
@@ -432,7 +459,7 @@ bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int
ShowError("chrif_changemapserverack: map server change failed.\n");
clif->authfail_fd(node->fd, 0); // Disconnected from server
} else
- clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port));
+ clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port), NULL);
//Player has been saved already, remove him from memory. [Skotlex]
chrif->auth_delete(account_id, char_id, ST_MAPCHANGE);
@@ -443,7 +470,8 @@ bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int
/*==========================================
*
*------------------------------------------*/
-void chrif_connectack(int fd) {
+static void chrif_connectack(int fd)
+{
static bool char_init_done = false;
if (RFIFOB(fd,2)) {
@@ -471,7 +499,7 @@ void chrif_connectack(int fd) {
/**
* @see DBApply
*/
-int chrif_reconnect(union DBKey key, struct DBData *data, va_list ap)
+static int chrif_reconnect(union DBKey key, struct DBData *data, va_list ap)
{
struct auth_node *node = DB->data2ptr(data);
@@ -504,7 +532,8 @@ int chrif_reconnect(union DBKey key, struct DBData *data, va_list ap)
}
/// Called when all the connection steps are completed.
-void chrif_on_ready(void) {
+static void chrif_on_ready(void)
+{
static bool once = false;
ShowStatus("Map Server is now online.\n");
@@ -535,7 +564,7 @@ void chrif_on_ready(void) {
/*==========================================
*
*------------------------------------------*/
-void chrif_sendmapack(int fd)
+static void chrif_sendmapack(int fd)
{
if (RFIFOB(fd,2)) {
ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
@@ -550,7 +579,7 @@ void chrif_sendmapack(int fd)
/*==========================================
* Request sc_data from charserver [Skotlex]
*------------------------------------------*/
-bool chrif_scdata_request(int account_id, int char_id)
+static bool chrif_scdata_request(int account_id, int char_id)
{
#ifdef ENABLE_SC_SAVING
chrif_check(false);
@@ -567,7 +596,8 @@ bool chrif_scdata_request(int account_id, int char_id)
/*==========================================
* Request auth confirmation
*------------------------------------------*/
-void chrif_authreq(struct map_session_data *sd, bool hstandalone) {
+static void chrif_authreq(struct map_session_data *sd, bool hstandalone)
+{
struct auth_node *node= chrif->search(sd->bl.id);
nullpo_retv(sd);
@@ -591,7 +621,8 @@ void chrif_authreq(struct map_session_data *sd, bool hstandalone) {
/*==========================================
* Auth confirmation ack
*------------------------------------------*/
-void chrif_authok(int fd) {
+static void chrif_authok(int fd)
+{
int account_id, group_id, char_id;
uint32 login_id1,login_id2;
time_t expiration_time;
@@ -653,7 +684,9 @@ void chrif_authok(int fd) {
}
// client authentication failed
-void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (but is available) */
+static void chrif_authfail(int fd)
+{
+ /* HELLO WORLD. ip in RFIFOL 15 is not being used (but is available) */
int account_id, char_id;
uint32 login_id1;
char sex;
@@ -682,7 +715,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
* This can still happen (client times out while waiting for char to confirm auth data)
* @see DBApply
*/
-int auth_db_cleanup_sub(union DBKey key, struct DBData *data, va_list ap)
+static int auth_db_cleanup_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct auth_node *node = DB->data2ptr(data);
@@ -707,7 +740,8 @@ int auth_db_cleanup_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data) {
+static int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data)
+{
chrif_check(0);
chrif->auth_db->foreach(chrif->auth_db, chrif->auth_db_cleanup_sub);
return 0;
@@ -716,7 +750,8 @@ int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Request char selection
*------------------------------------------*/
-bool chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
+static bool chrif_charselectreq(struct map_session_data *sd, uint32 s_ip)
+{
nullpo_ret(sd);
if( !sd->bl.id || !sd->login_id1 )
@@ -739,7 +774,8 @@ bool chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
/*==========================================
* Search Char trough id on char serv
*------------------------------------------*/
-bool chrif_searchcharid(int char_id) {
+static bool chrif_searchcharid(int char_id)
+{
if( !char_id )
return false;
@@ -757,7 +793,8 @@ bool chrif_searchcharid(int char_id) {
/*==========================================
* Change Email
*------------------------------------------*/
-bool chrif_changeemail(int id, const char *actual_email, const char *new_email) {
+static bool chrif_changeemail(int id, const char *actual_email, const char *new_email)
+{
if (battle_config.etc_log)
ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email);
@@ -790,7 +827,7 @@ bool chrif_changeemail(int id, const char *actual_email, const char *new_email)
* charunban { n/a }
* changecharsex { <sex>.b } -- use chrif_changesex
*------------------------------------------*/
-bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second)
+static bool chrif_char_ask_name(int acc, const char *character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second)
{
nullpo_retr(false, character_name);
chrif_check(false);
@@ -821,7 +858,7 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope
* @param change_account Whether to change the per-account sex.
* @retval true.
*/
-bool chrif_changesex(struct map_session_data *sd, bool change_account)
+static bool chrif_changesex(struct map_session_data *sd, bool change_account)
{
nullpo_retr(false, sd);
chrif_check(false);
@@ -850,7 +887,8 @@ bool chrif_changesex(struct map_session_data *sd, bool change_account)
* type of operation: @see chrif_char_ask_name
* type of answer: @see hz_char_ask_name_answer
*------------------------------------------*/
-bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) {
+static bool chrif_char_ask_name_answer(int acc, const char *player_name, uint16 type, uint16 answer)
+{
struct map_session_data* sd;
char action[25];
char output[256];
@@ -888,7 +926,8 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u
/*==========================================
* Request char server to change sex of char (modified by Yor)
*------------------------------------------*/
-void chrif_changedsex(int fd) {
+static void chrif_changedsex(int fd)
+{
int acc = RFIFOL(fd,2);
//int sex = RFIFOL(fd,6); // Dead store. Uncomment if needed again.
@@ -905,10 +944,12 @@ void chrif_changedsex(int fd) {
// of this process, but there's no need to perform map-server specific response
// as everything should been changed through char-server [Panikon]
}
+
/*==========================================
* Request Char Server to Divorce Players
*------------------------------------------*/
-bool chrif_divorce(int partner_id1, int partner_id2) {
+static bool chrif_divorce(int partner_id1, int partner_id2)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,10);
@@ -924,7 +965,8 @@ bool chrif_divorce(int partner_id1, int partner_id2) {
* Divorce players
* only used if 'partner_id' is offline
*------------------------------------------*/
-bool chrif_divorceack(int char_id, int partner_id) {
+static bool chrif_divorceack(int char_id, int partner_id)
+{
struct map_session_data* sd;
int i;
@@ -933,24 +975,26 @@ bool chrif_divorceack(int char_id, int partner_id) {
if( ( sd = map->charid2sd(char_id) ) != NULL && sd->status.partner_id == partner_id ) {
sd->status.partner_id = 0;
- for(i = 0; i < MAX_INVENTORY; i++)
+ for (i = 0; i < sd->status.inventorySize; i++)
if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
}
if( ( sd = map->charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) {
sd->status.partner_id = 0;
- for(i = 0; i < MAX_INVENTORY; i++)
+ for (i = 0; i < sd->status.inventorySize; i++)
if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
}
return true;
}
+
/*==========================================
* Removes Baby from parents
*------------------------------------------*/
-void chrif_deadopt(int father_id, int mother_id, int child_id) {
+static void chrif_deadopt(int father_id, int mother_id, int child_id)
+{
struct map_session_data* sd;
int idx = skill->get_index(WE_CALLBABY);
@@ -975,7 +1019,8 @@ void chrif_deadopt(int father_id, int mother_id, int child_id) {
/*==========================================
* Disconnection of a player (account or char has been banned of has a status, from login or char server) by [Yor]
*------------------------------------------*/
-void chrif_idbanned(int fd) {
+static void chrif_idbanned(int fd)
+{
int id;
struct map_session_data *sd;
@@ -997,9 +1042,9 @@ void chrif_idbanned(int fd) {
if(0<ret_status && ret_status<=9)
clif->message(sd->fd, msg_sd(sd,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_sd(sd,421));
+ clif->message(sd->fd, msg_sd(sd,421)); // Your account has been totally erased.
else
- clif->message(sd->fd, msg_sd(sd,420)); //"Your account has not more authorized."
+ clif->message(sd->fd, msg_sd(sd,420)); //"Your account is not longer authorized."
} else if (RFIFOB(fd,6) == 1) { // 1: ban
time_t timestamp;
char tmpstr[2048];
@@ -1022,7 +1067,8 @@ void chrif_idbanned(int fd) {
//Disconnect the player out of the game, simple packet
//packet.w AID.L WHY.B 2+4+1 = 7byte
-int chrif_disconnectplayer(int fd) {
+static int chrif_disconnectplayer(int fd)
+{
struct map_session_data* sd;
int account_id = RFIFOL(fd, 2);
@@ -1057,19 +1103,17 @@ int chrif_disconnectplayer(int fd) {
/*==========================================
* Request/Receive top 10 Fame character list
*------------------------------------------*/
-int chrif_updatefamelist(struct map_session_data* sd) {
- char type;
+static int chrif_updatefamelist(struct map_session_data *sd)
+{
+ int type;
nullpo_retr(0, sd);
chrif_check(-1);
- switch(sd->class_ & MAPID_UPPERMASK) {
- case MAPID_BLACKSMITH: type = RANKTYPE_BLACKSMITH; break;
- case MAPID_ALCHEMIST: type = RANKTYPE_ALCHEMIST; break;
- case MAPID_TAEKWON: type = RANKTYPE_TAEKWON; break;
- default:
- return 0;
- }
+ type = pc->famelist_type(sd->job);
+
+ if (type == RANKTYPE_UNKNOWN)
+ return 0;
WFIFOHEAD(chrif->fd, 11);
WFIFOW(chrif->fd,0) = 0x2b10;
@@ -1081,7 +1125,8 @@ int chrif_updatefamelist(struct map_session_data* sd) {
return 0;
}
-bool chrif_buildfamelist(void) {
+static bool chrif_buildfamelist(void)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,2);
@@ -1091,7 +1136,8 @@ bool chrif_buildfamelist(void) {
return true;
}
-void chrif_recvfamelist(int fd) {
+static void chrif_recvfamelist(int fd)
+{
int num, size;
int total = 0, len = 8;
@@ -1125,7 +1171,8 @@ void chrif_recvfamelist(int fd) {
/// fame ranking update confirmation
/// R 2b22 <table>.B <index>.B <value>.L
-int chrif_updatefamelist_ack(int fd) {
+static int chrif_updatefamelist_ack(int fd)
+{
struct fame_list* list;
uint8 index;
@@ -1145,8 +1192,9 @@ int chrif_updatefamelist_ack(int fd) {
return 1;
}
-bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex]
-
+//parses the sc_data of the player and sends it to the char-server for saving. [Skotlex]
+static bool chrif_save_scdata(struct map_session_data *sd)
+{
#ifdef ENABLE_SC_SAVING
int i, count=0;
int64 tick;
@@ -1178,6 +1226,7 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th
} else {
data.tick = INFINITE_DURATION;
}
+ data.total_tick = sc->data[i]->total_tick;
data.type = i;
data.val1 = sc->data[i]->val1;
data.val2 = sc->data[i]->val2;
@@ -1200,8 +1249,8 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th
}
//Retrieve and load sc_data for a player. [Skotlex]
-bool chrif_load_scdata(int fd) {
-
+static bool chrif_load_scdata(int fd)
+{
#ifdef ENABLE_SC_SAVING
struct map_session_data *sd;
int aid, cid, i, count;
@@ -1225,8 +1274,8 @@ bool chrif_load_scdata(int fd) {
for (i = 0; i < count; i++) {
const struct status_change_data *data = RFIFOP(fd,14 + i*sizeof(struct status_change_data));
- status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4,
- data->tick, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE);
+ status->change_start_sub(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4,
+ data->tick, data->total_tick, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE);
}
pc->scdata_received(sd);
@@ -1238,7 +1287,8 @@ bool chrif_load_scdata(int fd) {
* Send rates to char server [Wizputer]
* S 2b16 <base rate>.L <job rate>.L <drop rate>.L
*------------------------------------------*/
-bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) {
+static bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,14);
@@ -1253,7 +1303,8 @@ bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) {
/*=========================================
* Tell char-server character disconnected [Wizputer]
*-----------------------------------------*/
-bool chrif_char_offline_nsd(int account_id, int char_id) {
+static bool chrif_char_offline_nsd(int account_id, int char_id)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,10);
@@ -1268,7 +1319,8 @@ bool chrif_char_offline_nsd(int account_id, int char_id) {
/*=========================================
* Tell char-server to reset all chars offline [Wizputer]
*-----------------------------------------*/
-bool chrif_flush(void) {
+static bool chrif_flush(void)
+{
chrif_check(false);
sockt->set_nonblocking(chrif->fd, 0);
@@ -1281,7 +1333,8 @@ bool chrif_flush(void) {
/*=========================================
* Tell char-server to reset all chars offline [Wizputer]
*-----------------------------------------*/
-bool chrif_char_reset_offline(void) {
+static bool chrif_char_reset_offline(void)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,2);
@@ -1294,7 +1347,8 @@ bool chrif_char_reset_offline(void) {
/*=========================================
* Tell char-server character is online [Wizputer]. Look like unused.
*-----------------------------------------*/
-bool chrif_char_online(struct map_session_data *sd) {
+static bool chrif_char_online(struct map_session_data *sd)
+{
chrif_check(false);
nullpo_retr(false, sd);
@@ -1308,7 +1362,8 @@ bool chrif_char_online(struct map_session_data *sd) {
}
/// Called when the connection to Char Server is disconnected.
-void chrif_on_disconnect(void) {
+static void chrif_on_disconnect(void)
+{
if( chrif->connected != 1 )
ShowWarning("Connection to Char Server lost.\n\n");
chrif->connected = 0;
@@ -1320,7 +1375,8 @@ void chrif_on_disconnect(void) {
timer->add(timer->gettick() + 1000, chrif->check_connect_char_server, 0, 0);
}
-void chrif_update_ip(int fd) {
+static void chrif_update_ip(int fd)
+{
uint32 new_ip;
WFIFOHEAD(fd,6);
@@ -1341,15 +1397,20 @@ void chrif_update_ip(int fd) {
}
// pings the charserver ( since on-demand flag.ping was introduced, shouldn't this be dropped? only wasting traffic and processing [Ind])
-void chrif_keepalive(int fd) {
+static void chrif_keepalive(int fd)
+{
WFIFOHEAD(fd,2);
WFIFOW(fd,0) = 0x2b23;
WFIFOSET(fd,2);
}
-void chrif_keepalive_ack(int fd) {
+
+static void chrif_keepalive_ack(int fd)
+{
sockt->session[fd]->flag.ping = 0;/* reset ping state, we received a packet */
}
-void chrif_skillid2idx(int fd) {
+
+static void chrif_skillid2idx(int fd)
+{
int i, count = 0;
if( fd == 0 ) fd = chrif->fd;
@@ -1357,11 +1418,11 @@ void chrif_skillid2idx(int fd) {
if (!sockt->session_is_valid(fd))
return;
- WFIFOHEAD(fd,4 + (MAX_SKILL * 4));
+ WFIFOHEAD(fd,4 + (MAX_SKILL_DB * 4));
WFIFOW(fd,0) = 0x2b0b;
- for(i = 0; i < MAX_SKILL; i++) {
- if( skill->dbs->db[i].nameid ) {
- WFIFOW(fd, 4 + (count*4)) = skill->dbs->db[i].nameid;
+ for (i = 0; i < MAX_SKILL_DB; i++) {
+ if (skill->dbs->db[i].nameid != 0) {
+ WFIFOW(fd, 4 + (count*4)) = skill->dbs->db[i].nameid; // really skill id
WFIFOW(fd, 6 + (count*4)) = i;
count++;
}
@@ -1370,10 +1431,12 @@ void chrif_skillid2idx(int fd) {
WFIFOSET(fd,4 + (count * 4));
}
+
/*==========================================
*
*------------------------------------------*/
-int chrif_parse(int fd) {
+static int chrif_parse(int fd)
+{
int packet_len, cmd;
// only process data from the char-server
@@ -1467,7 +1530,8 @@ int chrif_parse(int fd) {
return 0;
}
-int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data) {
+static int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data)
+{
chrif_check(-1);
WFIFOHEAD(chrif->fd,4);
@@ -1481,7 +1545,8 @@ int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data) {
* timerFunction
* Send to char the number of client connected to map
*------------------------------------------*/
-bool send_users_tochar(void) {
+static bool send_users_tochar(void)
+{
int users = 0, i = 0;
const struct map_session_data *sd;
struct s_mapiterator *iter;
@@ -1512,7 +1577,8 @@ bool send_users_tochar(void) {
* timerFunction
* Check the connection to char server, (if it down)
*------------------------------------------*/
-int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
+static int check_connect_char_server(int tid, int64 tick, int id, intptr_t data)
+{
static int displayed = 0;
if ( chrif->fd <= 0 || sockt->session[chrif->fd] == NULL ) {
if ( !displayed ) {
@@ -1527,6 +1593,7 @@ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
sockt->session[chrif->fd]->func_parse = chrif->parse;
sockt->session[chrif->fd]->flag.server = 1;
+ sockt->session[chrif->fd]->flag.validate = 0;
sockt->realloc_fifo(chrif->fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
chrif->connect(chrif->fd);
@@ -1546,7 +1613,7 @@ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Asks char server to remove friend_id from the friend list of char_id
*------------------------------------------*/
-bool chrif_removefriend(int char_id, int friend_id)
+static bool chrif_removefriend(int char_id, int friend_id)
{
chrif_check(false);
@@ -1558,26 +1625,10 @@ bool chrif_removefriend(int char_id, int friend_id)
return true;
}
-void chrif_send_report(char* buf, int len) {
-#ifndef STATS_OPT_OUT
- if( chrif->fd > 0 ) {
- nullpo_retv(buf);
- WFIFOHEAD(chrif->fd,len + 2);
-
- WFIFOW(chrif->fd,0) = 0x3008;
- memcpy(WFIFOP(chrif->fd,2), buf, len);
-
- WFIFOSET(chrif->fd,len + 2);
-
- sockt->flush(chrif->fd); /* ensure it's sent now. */
- }
-#endif
-}
-
/**
* 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)
+static void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce)
{
if( !chrif->isconnected() )
return;
@@ -1596,10 +1647,11 @@ void chrif_save_scdata_single(int account_id, int char_id, short type, struct st
WFIFOSET(chrif->fd, 28);
}
+
/**
* 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)
+static void chrif_del_scdata_single(int account_id, int char_id, short type)
{
if( !chrif->isconnected() ) {
ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id);
@@ -1619,7 +1671,7 @@ void chrif_del_scdata_single(int account_id, int char_id, short type)
/**
* @see DBApply
*/
-int auth_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int auth_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct auth_node *node = DB->data2ptr(data);
@@ -1641,7 +1693,7 @@ int auth_db_final(union DBKey key, struct DBData *data, va_list ap)
/*==========================================
* Destructor
*------------------------------------------*/
-void do_final_chrif(void)
+static void do_final_chrif(void)
{
if( chrif->fd != -1 ) {
sockt->close(chrif->fd);
@@ -1656,7 +1708,8 @@ void do_final_chrif(void)
/*==========================================
*
*------------------------------------------*/
-void do_init_chrif(bool minimal) {
+static void do_init_chrif(bool minimal)
+{
if (minimal)
return;
@@ -1682,7 +1735,8 @@ void do_init_chrif(bool minimal) {
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
-void chrif_defaults(void) {
+void chrif_defaults(void)
+{
const int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE] = { // U - used, F - free
60, 3, -1, 27, 10, -1, 6, -1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
6, -1, 18, 7, -1, 39, 30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
@@ -1753,7 +1807,6 @@ void chrif_defaults(void) {
chrif->divorce = chrif_divorce;
chrif->removefriend = chrif_removefriend;
- chrif->send_report = chrif_send_report;
chrif->flush = chrif_flush;
chrif->skillid2idx = chrif_skillid2idx;
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 4a1e1da47..e2e82c6cb 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -124,7 +124,6 @@ struct chrif_interface {
bool (*divorce) (int partner_id1, int partner_id2);
bool (*removefriend) (int char_id, int friend_id);
- void (*send_report) (char* buf, int len);
bool (*flush) (void);
void (*skillid2idx) (int fd);
diff --git a/src/map/clan.c b/src/map/clan.c
new file mode 100644
index 000000000..041ba1d6d
--- /dev/null
+++ b/src/map/clan.c
@@ -0,0 +1,1075 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017-2020 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#define HERCULES_CORE
+
+#include "config/core.h"
+#include "clan.h"
+
+#include "map/clif.h"
+#include "map/chrif.h"
+#include "map/homunculus.h"
+#include "map/intif.h"
+#include "map/log.h"
+#include "map/mercenary.h"
+#include "map/mob.h"
+#include "map/npc.h"
+#include "map/pc.h"
+#include "map/pet.h"
+#include "map/script.h"
+#include "map/skill.h"
+#include "map/status.h"
+#include "common/HPM.h"
+#include "common/conf.h"
+#include "common/cbasetypes.h"
+#include "common/db.h"
+#include "common/memmgr.h"
+#include "common/mapindex.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+#include "common/socket.h"
+#include "common/strlib.h"
+#include "common/timer.h"
+#include "common/utils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct clan_interface clan_s;
+struct clan_interface *clan;
+
+/**
+ * Searches a Clan by clan_id
+ *
+ * @param clan_id Clan ID
+ * @return struct clan*
+ */
+static struct clan *clan_search(int clan_id)
+{
+ if (clan_id <= 0) {
+ return NULL;
+ }
+ return (struct clan *)idb_get(clan->db, clan_id);
+}
+
+/**
+ * Searches a Clan by clan_name or constant
+ *
+ * @param name Clan Name
+ * @return struct clan*
+ */
+static struct clan *clan_searchname(const char *name)
+{
+ struct clan *c;
+ struct DBIterator *iter;
+
+ nullpo_retr(NULL, name);
+
+ iter = db_iterator(clan->db);
+ for (c = dbi_first(iter); dbi_exists(iter); c = dbi_next(iter)) {
+ if (strncmpi(c->name, name, NAME_LENGTH) == 0 || strncmpi(c->constant, name, NAME_LENGTH) == 0) {
+ break;
+ }
+ }
+ dbi_destroy(iter);
+ return c;
+}
+
+/**
+ * Returns the first online character of clan
+ *
+ * @param (struct clan *) c clan structure
+ * @return (struct map_session_data *)
+ */
+static struct map_session_data *clan_getonlinesd(struct clan *c)
+{
+ int i;
+ nullpo_retr(NULL, c);
+
+ ARR_FIND(0, VECTOR_LENGTH(c->members), i, (VECTOR_INDEX(c->members, i).sd != NULL && VECTOR_INDEX(c->members, i).online == 1));
+ return (i < VECTOR_LENGTH(c->members)) ? VECTOR_INDEX(c->members, i).sd : NULL;
+}
+
+/**
+ * Returns the member index of given Player
+ *
+ * @param c Clan Data
+ * @param char_id Player's Char ID
+ * @return int
+ */
+static int clan_getindex(const struct clan *c, int char_id)
+{
+ int i;
+ nullpo_retr(INDEX_NOT_FOUND, c);
+
+ ARR_FIND(0, VECTOR_LENGTH(c->members), i, VECTOR_INDEX(c->members, i).char_id == char_id);
+
+ if (i == VECTOR_LENGTH(c->members)) {
+ return INDEX_NOT_FOUND;
+ }
+ return i;
+}
+
+/**
+ * Starts clan buff
+ */
+static void clan_buff_start(struct map_session_data *sd, struct clan *c)
+{
+ nullpo_retv(sd);
+ nullpo_retv(c);
+
+ if (c->buff.icon <= 0) {
+ return;
+ }
+
+ clif->sc_load(&sd->bl, sd->bl.id, SELF, c->buff.icon, 0, c->clan_id, 0);
+ script->run(c->buff.script, 0, sd->bl.id, npc->fake_nd->bl.id);
+}
+
+/**
+ * Ends clan buff
+ */
+static void clan_buff_end(struct map_session_data *sd, struct clan *c)
+{
+ nullpo_retv(sd);
+ nullpo_retv(c);
+
+ if (c->buff.icon <= 0) {
+ return;
+ }
+
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, c->buff.icon);
+}
+
+/**
+ * Joins a Player into a Clan
+ *
+ * @param sd Player's Map Session Data
+ * @param clan_id Clan which will add this player
+ * @return bool
+ */
+static bool clan_join(struct map_session_data *sd, int clan_id)
+{
+ struct clan *c;
+ struct clan_member m;
+
+ nullpo_ret(sd);
+
+ // Already joined a guild or clan
+ if (sd->status.guild_id > 0 || sd->guild != NULL) {
+ ShowError("clan_join: Player already joined in a guild. char_id: %d\n", sd->status.char_id);
+ return false;
+ } else if ( sd->status.clan_id > 0 || sd->clan != NULL) {
+ ShowError("clan_join: Player already joined in a clan. char_id: %d\n", sd->status.char_id);
+ return false;
+ }
+
+ c = clan->search(clan_id);
+ if (c == NULL) {
+ ShowError("clan_join: Invalid Clan ID: %d\n", clan_id);
+ return false;
+ }
+
+ if (!c->received) {
+ return false;
+ }
+
+ if (clan->getindex(c, sd->status.char_id) != INDEX_NOT_FOUND) {
+ ShowError("clan_join: Player already joined this clan. char_id: %d clan_id: %d\n", sd->status.char_id, clan_id);
+ return false;
+ }
+
+ if (VECTOR_LENGTH(c->members) >= c->max_member || c->member_count >= c->max_member) {
+ ShowError("clan_join: Clan '%s' already reached its max capacity!\n", c->name);
+ return false;
+ }
+
+ VECTOR_ENSURE(c->members, 1, 1);
+
+ m.sd = sd;
+ m.char_id = sd->status.char_id;
+ m.online = 1;
+ m.last_login = sd->status.last_login;
+ VECTOR_PUSH(c->members, m);
+
+ c->connect_member++;
+ c->member_count++;
+
+ sd->status.clan_id = c->clan_id;
+ sd->clan = c;
+
+ sc_start2(NULL, &sd->bl, SC_CLAN_INFO, 10000, 0, c->clan_id, INFINITE_DURATION);
+ status_calc_pc(sd, SCO_FORCE);
+
+ chrif->save(sd, 0);
+ clif->clan_basicinfo(sd);
+ clif->clan_onlinecount(c);
+ return true;
+}
+
+/**
+ * Invoked when a player joins
+ * It assumes that clan_id is not 0
+ *
+ * @param sd Player Data
+ */
+static void clan_member_online(struct map_session_data *sd, bool first)
+{
+ struct clan *c;
+ int i, inactivity;
+ nullpo_retv(sd);
+
+ // For invalid values we must reset it to 0 (no clan)
+ if (sd->status.clan_id < 0) {
+ ShowError("clan_member_online: Invalid clan id, changing to '0'. clan_id='%d' char_id='%d'\n", sd->status.clan_id, sd->status.char_id);
+ sd->status.clan_id = 0;
+ return;
+ }
+
+ c = clan->search(sd->status.clan_id);
+ if (c == NULL) {
+ // This is a silent return because it will reset clan_id in case
+ // a custom clan that was removed and this is a remaining member
+ sd->status.clan_id = 0;
+ sd->clan = NULL;
+ if (!first) {
+ status_change_end(&sd->bl, SC_CLAN_INFO, INVALID_TIMER); // Remove the status
+ status_calc_pc(sd, SCO_FORCE);
+ }
+ clif->clan_leave(sd);
+ return;
+ }
+
+ if (!c->received) {
+ return;
+ }
+
+ if (c->max_member <= c->member_count || VECTOR_LENGTH(c->members) >= c->max_member) {
+ ShowError("Clan System: More members than the maximum allowed in clan #%d\n", c->clan_id);
+ return;
+ }
+
+ i = clan->getindex(c, sd->status.char_id);
+ inactivity = (int)(time(NULL) - sd->status.last_login);
+ if (i == INDEX_NOT_FOUND) {
+ struct clan_member m;
+
+ if (c->kick_time > 0 && inactivity > c->kick_time) {
+ sd->status.clan_id = 0;
+ sd->clan = NULL;
+ clan->buff_end(sd, c);
+ status_change_end(&sd->bl, SC_CLAN_INFO, INVALID_TIMER);
+ clif->clan_leave(sd);
+ return;
+ }
+
+ VECTOR_ENSURE(c->members, 1, 1);
+
+ m.sd = sd;
+ m.char_id = sd->status.char_id;
+ m.online = 1;
+ m.last_login = sd->status.last_login;
+ VECTOR_PUSH(c->members, m);
+ } else {
+ struct clan_member *m = &VECTOR_INDEX(c->members, i);
+
+
+ if (c->kick_time > 0 && inactivity > c->kick_time) {
+ if (m->online == 1) {
+ m->online = 0;
+ m->sd = NULL;
+ c->connect_member--;
+ c->member_count--;
+ }
+ clan->buff_end(sd, c);
+ sd->status.clan_id = 0;
+ sd->clan = NULL;
+ status_change_end(&sd->bl, SC_CLAN_INFO, INVALID_TIMER);
+ VECTOR_ERASE(c->members, i);
+ clif->clan_leave(sd);
+ return;
+ }
+
+ m->sd = sd;
+ m->online = 1;
+ m->last_login = sd->status.last_login;
+ }
+
+ sd->clan = c;
+ c->connect_member++;
+
+ sc_start2(NULL, &sd->bl, SC_CLAN_INFO, 10000, 0, c->clan_id, INFINITE_DURATION);
+
+ if (!first) {
+ // When first called from pc.c we don't need to do status_calc
+ status_calc_pc(sd, SCO_FORCE);
+ }
+
+ clif->clan_basicinfo(sd);
+ clif->clan_onlinecount(c);
+}
+
+/**
+ * Re-join a player on its clan
+ */
+static int clan_rejoin(struct map_session_data *sd, va_list ap)
+{
+ nullpo_ret(sd);
+
+ if (sd->status.clan_id != 0) {
+ // Note: Even if the value is invalid (lower than zero)
+ // the function will fix the invalid value
+ clan->member_online(sd, false);
+ }
+ return 0;
+}
+
+/**
+ * Removes Player from clan
+ */
+static bool clan_leave(struct map_session_data *sd, bool first)
+{
+ int i;
+ struct clan *c;
+
+ nullpo_ret(sd);
+
+ c = sd->clan;
+
+ if (c == NULL) {
+ return false;
+ }
+
+ if (!c->received) {
+ return false;
+ }
+
+ i = clan->getindex(c, sd->status.char_id);
+ if (i != INDEX_NOT_FOUND) {
+ VECTOR_ERASE(c->members, i);
+ c->connect_member--;
+ c->member_count--;
+ }
+
+ sd->status.clan_id = 0;
+ sd->clan = NULL;
+ clan->buff_end(sd, c);
+
+ status_change_end(&sd->bl, SC_CLAN_INFO, INVALID_TIMER);
+ if (!first) {
+ status_calc_pc(sd, SCO_FORCE);
+ }
+
+ chrif->save(sd, 0);
+ clif->clan_onlinecount(c);
+ clif->clan_leave(sd);
+ return true;
+}
+
+/**
+ * Sets a player offline
+ *
+ * @param (struct map_session_data *) sd Player Data
+ */
+static void clan_member_offline(struct map_session_data *sd)
+{
+ struct clan *c;
+ int i;
+
+ nullpo_retv(sd);
+
+ c = sd->clan;
+
+ if (c == NULL) {
+ return;
+ }
+
+ i = clan->getindex(c, sd->status.char_id);
+ if (i != INDEX_NOT_FOUND && VECTOR_INDEX(c->members, i).online == 1) {
+ // Only if it is online, because unit->free is called twice
+ VECTOR_INDEX(c->members, i).online = 0;
+ VECTOR_INDEX(c->members, i).sd = NULL;
+ c->connect_member--;
+ }
+ clif->clan_onlinecount(c);
+}
+
+
+/**
+ * Sends a message to the whole clan
+ */
+static bool clan_send_message(struct map_session_data *sd, const char *mes)
+{
+ int len;
+ nullpo_retr(false, sd);
+ nullpo_retr(false, mes);
+
+ len = (int)strlen(mes);
+
+ if (sd->status.clan_id == 0) {
+ return false;
+ }
+ clan->recv_message(sd->clan, mes, len);
+
+ // Chat logging type 'C' / Clan Chat
+ logs->chat(LOG_CHAT_CLAN, sd->status.clan_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
+
+ return true;
+}
+
+/**
+ * Clan receive a message, will be displayed to whole clan
+ */
+static void clan_recv_message(struct clan *c, const char *mes, int len)
+{
+ clif->clan_message(c, mes, len);
+}
+
+/**
+ * Set constants for each clan
+ */
+static void clan_set_constants(void)
+{
+ struct DBIterator *iter = db_iterator(clan->db);
+ struct clan *c;
+
+ for (c = dbi_first(iter); dbi_exists(iter); c = dbi_next(iter)) {
+ script->set_constant2(c->constant, c->clan_id, false, false);
+ }
+
+ dbi_destroy(iter);
+}
+
+/**
+ * Returns the clan_id of bl
+ */
+static int clan_get_id(const struct block_list *bl)
+{
+ nullpo_ret(bl);
+
+ switch (bl->type) {
+ case BL_PC: {
+ const struct map_session_data *sd = BL_UCCAST(BL_PC, bl);
+ return sd->status.clan_id;
+ }
+ case BL_NPC: {
+ const struct npc_data *nd = BL_UCCAST(BL_NPC, bl);
+ return nd->clan_id;
+ }
+ case BL_PET: {
+ const struct pet_data *pd = BL_UCCAST(BL_PET, bl);
+ if (pd->msd != NULL)
+ return pd->msd->status.clan_id;
+ }
+ break;
+ case BL_MOB: {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ const struct map_session_data *msd;
+ if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) {
+ return msd->status.clan_id;
+ }
+ return md->clan_id;
+ }
+ case BL_HOM: {
+ const struct homun_data *hd = BL_UCCAST(BL_HOM, bl);
+ if (hd->master != NULL) {
+ return hd->master->status.clan_id;
+ }
+ }
+ break;
+ case BL_MER: {
+ const struct mercenary_data *md = BL_UCCAST(BL_MER, bl);
+ if (md->master != NULL) {
+ return md->master->status.clan_id;
+ }
+ }
+ break;
+ case BL_SKILL: {
+ const struct skill_unit *su = BL_UCCAST(BL_SKILL, bl);
+ if (su->group != NULL)
+ return su->group->clan_id;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * Checks every clan player and remove those who are inactive
+ */
+static int clan_inactivity_kick(int tid, int64 tick, int id, intptr_t data)
+{
+ struct clan *c = NULL;
+ int i;
+
+ if ((c = clan->search(id)) != NULL) {
+ if (!c->kick_time || c->tid != tid || tid == INVALID_TIMER || c->tid == INVALID_TIMER) {
+ ShowError("Timer Mismatch (Time: %d seconds) %d != %d", c->kick_time, c->tid, tid);
+ Assert_report(0);
+ return 0;
+ }
+ for (i = 0; i < VECTOR_LENGTH(c->members); i++) {
+ struct clan_member *m = &VECTOR_INDEX(c->members, i);
+ if (m->char_id <= 0 || m->online <= 0)
+ continue;
+
+ if (m->online) {
+ struct map_session_data *sd = m->sd;
+ if (DIFF_TICK32(sockt->last_tick, sd->idletime) > c->kick_time) {
+ clan->leave(sd, false);
+ }
+ } else if ((time(NULL) - m->last_login) > c->kick_time) {
+ VECTOR_ERASE(c->members, i);
+ c->member_count--;
+ clif->clan_onlinecount(c);
+ }
+ }
+ //Perform the kick for offline members that didn't connect after a server restart
+ c->received = false;
+ intif->clan_kickoffline(c->clan_id, c->kick_time);
+ c->tid = timer->add(timer->gettick() + c->check_time, clan->inactivity_kick, c->clan_id, 0);
+ }
+ return 1;
+}
+
+/**
+ * Timeout for the request of offline kick
+ */
+static int clan_request_kickoffline(int tid, int64 tick, int id, intptr_t data)
+{
+ struct clan *c = NULL;
+
+ if ((c = clan->search(id)) != NULL) {
+ if (c->req_kick_tid != tid || c->req_kick_tid == INVALID_TIMER) {
+ ShowError("Timer Mismatch %d != %d", c->tid, tid);
+ return 0;
+ }
+
+ if (c->received) {
+ c->req_kick_tid = INVALID_TIMER;
+ return 1;
+ }
+
+ intif->clan_kickoffline(c->clan_id, c->kick_time);
+ c->req_kick_tid = timer->add(timer->gettick() + clan->req_timeout, clan->request_kickoffline, c->clan_id, 0);
+ }
+ return 1;
+}
+
+/**
+ * Timeout of the request for counting members
+ */
+static int clan_request_membercount(int tid, int64 tick, int id, intptr_t data)
+{
+ struct clan *c = NULL;
+
+ if ((c = clan->search(id)) != NULL) {
+ if (c->req_count_tid != tid || c->req_count_tid == INVALID_TIMER) {
+ ShowError("Timer Mismatch %d != %d", c->tid, tid);
+ return 0;
+ }
+
+ if (c->received) {
+ c->req_count_tid = INVALID_TIMER;
+ return 1;
+ }
+
+ intif->clan_membercount(c->clan_id, c->kick_time);
+ c->req_count_tid = timer->add(timer->gettick() + clan->req_timeout, clan->request_membercount, c->clan_id, 0);
+ }
+ return 1;
+}
+
+/**
+ * Processes any (plugin-defined) additional fields for a clan entry.
+ *
+ * @param[in, out] entry The destination clan entry, already initialized (clan_id is expected to be already set).
+ * @param[in] t The libconfig entry.
+ * @param[in] n Ordinal number of the entry, to be displayed in case of validation errors.
+ * @param[in] source Source of the entry (file name), to be displayed in case of validation errors.
+ */
+static void clan_read_db_additional_fields(struct clan *entry, struct config_setting_t *t, int n, const char *source)
+{
+ // do nothing. plugins can do own work
+}
+
+static void clan_read_buffs(struct clan *c, struct config_setting_t *buff, const char *source)
+{
+ struct clan_buff *b;
+ const char *str = NULL;
+
+ nullpo_retv(c);
+ nullpo_retv(buff);
+
+ b = &c->buff;
+
+ if (!libconfig->setting_lookup_int(buff, "Icon", &b->icon)) {
+ const char *temp_str = NULL;
+ if (libconfig->setting_lookup_string(buff, "Icon", &temp_str)) {
+ if (*temp_str && !script->get_constant(temp_str, &b->icon)) {
+ ShowWarning("Clan %d: Invalid Buff icon value. Defaulting to SI_BLANK.\n", c->clan_id);
+ b->icon = -1; // SI_BLANK
+ }
+ }
+ }
+
+ if (libconfig->setting_lookup_string(buff, "Script", &str)) {
+ b->script = *str ? script->parse(str, source, -b->icon, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ }
+}
+
+/**
+ * Processes one clandb entry from the libconfig file, loading and inserting it
+ * into the clan database.
+ *
+ * @param settings Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary).
+ * @param source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return int.
+ */
+static int clan_read_db_sub(struct config_setting_t *settings, const char *source, bool reload)
+{
+ int total, s, valid = 0;
+
+ nullpo_retr(false, settings);
+
+ total = libconfig->setting_length(settings);
+
+ for (s = 0; s < total; s++) {
+ struct clan *c;
+ struct config_setting_t *cl, *buff, *allies, *antagonists;
+ const char *aName, *aLeader, *aMap, *aConst;
+ int max_members, kicktime = 0, kickchecktime = 0, id, i, j;
+
+ cl = libconfig->setting_get_elem(settings, s);
+
+ if (libconfig->setting_lookup_int(cl, "Id", &id)) {
+ if (id <= 0) {
+ ShowError("clan_read_db: Invalid Clan Id %d, skipping...\n", id);
+ return false;
+ }
+
+ if (clan->search(id) != NULL) {
+ ShowError("clan_read_db: Duplicate entry for Clan Id %d, skipping...\n", id);
+ return false;
+ }
+ } else {
+ ShowError("clan_read_db: failed to find 'Id' for clan #%d\n", s);
+ return false;
+ }
+
+ if (libconfig->setting_lookup_string(cl, "Const", &aConst)) {
+ if (!*aConst) {
+ ShowError("clan_read_db: Invalid Clan Const '%s', skipping...\n", aConst);
+ return false;
+ }
+
+ if (strlen(aConst) > NAME_LENGTH) {
+ ShowError("clan_read_db: Clan Name '%s' is longer than %d characters, skipping...\n", aConst, NAME_LENGTH);
+ return false;
+ }
+
+ if (clan->searchname(aConst) != NULL) {
+ ShowError("clan_read_db: Duplicate entry for Clan Const '%s', skipping...\n", aConst);
+ return false;
+ }
+ } else {
+ ShowError("clan_read_db: failed to find 'Const' for clan #%d\n", s);
+ return false;
+ }
+
+ if (libconfig->setting_lookup_string(cl, "Name", &aName)) {
+ if (!*aName) {
+ ShowError("clan_read_db: Invalid Clan Name '%s', skipping...\n", aName);
+ return false;
+ }
+
+ if (strlen(aName) > NAME_LENGTH) {
+ ShowError("clan_read_db: Clan Name '%s' is longer than %d characters, skipping...\n", aName, NAME_LENGTH);
+ return false;
+ }
+
+ if (clan->searchname(aName) != NULL) {
+ ShowError("clan_read_db: Duplicate entry for Clan Name '%s', skipping...\n", aName);
+ return false;
+ }
+ } else {
+ ShowError("clan_read_db: failed to find 'Name' for clan #%d\n", s);
+ return false;
+ }
+
+ if (!libconfig->setting_lookup_string(cl, "Leader", &aLeader)) {
+ ShowError("clan_read_db: failed to find 'Leader' for clan #%d\n", s);
+ return false;
+ }
+
+ if (!libconfig->setting_lookup_string(cl, "Map", &aMap)) {
+ ShowError("clan_read_db: failed to find 'Map' for clan #%d\n", s);
+ return false;
+ }
+
+ CREATE(c, struct clan, 1);
+
+ c->clan_id = id;
+ safestrncpy(c->constant, aConst, NAME_LENGTH);
+ safestrncpy(c->name, aName, NAME_LENGTH);
+ safestrncpy(c->master, aLeader, NAME_LENGTH);
+ safestrncpy(c->map, aMap, MAP_NAME_LENGTH_EXT);
+ c->connect_member = 0;
+ c->member_count = 0; // Char server will count members for us
+ c->received = false;
+ c->req_count_tid = INVALID_TIMER;
+ c->req_kick_tid = INVALID_TIMER;
+ c->tid = INVALID_TIMER;
+
+ if (libconfig->setting_lookup_int(cl, "MaxMembers", &max_members)) {
+ if (max_members > 0) {
+ c->max_member = max_members;
+ } else {
+ ShowError("clan_read_db: Clan #%d has invalid value for 'MaxMembers' setting, defaulting to 'clan->max'...\n", id);
+ c->max_member = clan->max;
+ }
+ } else {
+ c->max_member = clan->max;
+ }
+
+ if (libconfig->setting_lookup_int(cl, "KickTime", &kicktime)) {
+ c->kick_time = 60 * 60 * kicktime;
+ } else {
+ c->kick_time = clan->kicktime;
+ }
+
+ if (libconfig->setting_lookup_int(cl, "CheckTime", &kickchecktime)) {
+ c->check_time = 60 * 60 * max(1, kickchecktime) * 1000;
+ } else {
+ c->check_time = clan->checktime;
+ }
+
+ if ((buff = libconfig->setting_get_member(cl, "Buff")) != NULL) {
+ clan->read_buffs(c, buff, source);
+ }
+
+ allies = libconfig->setting_get_member(cl, "Allies");
+
+ if (allies != NULL) {
+ int a = libconfig->setting_length(allies);
+
+ VECTOR_INIT(c->allies);
+ if (a > 0 && clan->max_relations > 0) {
+ const char *allyConst;
+
+ if (a > clan->max_relations) {
+ ShowWarning("clan_read_db: Clan %d has more allies(%d) than allowed(%d), reading only the first %d...\n", c->clan_id, a, clan->max_relations, clan->max_relations);
+ a = clan->max_relations;
+ }
+
+ VECTOR_ENSURE(c->allies, a, 1);
+ for (i = 0; i < a; i++) {
+ struct clan_relationship r;
+ if ((allyConst = libconfig->setting_get_string_elem(allies, i)) != NULL) {
+ ARR_FIND(0, VECTOR_LENGTH(c->allies), j, strcmp(VECTOR_INDEX(c->allies, j).constant, allyConst) == 0);
+ if (j != VECTOR_LENGTH(c->allies)) {
+ ShowError("clan_read_db: Duplicate entry '%s' in allies for Clan %d in '%s', skipping...\n", allyConst, c->clan_id, source);
+ continue;
+ } else if (strcmp(allyConst, c->constant) == 0) {
+ ShowError("clan_read_db: Clans can't be allies of themselves! Clan Id: %d, in '%s'\n", c->clan_id, source);
+ continue;
+ }
+ safestrncpy(r.constant, allyConst, NAME_LENGTH);
+ VECTOR_PUSH(c->allies, r);
+ }
+
+ }
+ }
+ }
+ antagonists = libconfig->setting_get_member(cl, "Antagonists");
+
+ if (antagonists != NULL) {
+ int a = libconfig->setting_length(antagonists);
+
+ VECTOR_INIT(c->antagonists);
+ if (a > 0 && clan->max_relations > 0) {
+ const char *antagonistConst;
+
+ if (a > clan->max_relations) {
+ ShowWarning("clan_read_db: Clan %d has more antagonists(%d) than allowed(%d), reading only the first %d...\n", c->clan_id, a, clan->max_relations, clan->max_relations);
+ a = clan->max_relations;
+ }
+
+ VECTOR_ENSURE(c->antagonists, a, 1);
+ for (i = 0; i < a; i++) {
+ struct clan_relationship r;
+ if ((antagonistConst = libconfig->setting_get_string_elem(antagonists, i)) != NULL) {
+ ARR_FIND(0, VECTOR_LENGTH(c->antagonists), j, strcmp(VECTOR_INDEX(c->antagonists, j).constant, antagonistConst) == 0);
+ if (j != VECTOR_LENGTH(c->antagonists)) {
+ ShowError("clan_read_db: Duplicate entry '%s' in antagonists for Clan %d in '%s', skipping...\n", antagonistConst, c->clan_id, source);
+ continue;
+ } else if (strcmp(antagonistConst, c->constant) == 0) {
+ ShowError("clan_read_db: Clans can't be antagonists of themselves! Clan Id: %d, in '%s'\n", c->clan_id, source);
+ continue;
+ }
+ safestrncpy(r.constant, antagonistConst, NAME_LENGTH);
+ VECTOR_PUSH(c->antagonists, r);
+ }
+ }
+ }
+ }
+
+ clan->read_db_additional_fields(c, cl, s, source);
+ if (c->kick_time > 0) {
+ c->tid = timer->add(timer->gettick() + c->check_time, clan->inactivity_kick, c->clan_id, 0);
+ }
+ c->received = false;
+ c->req_state = reload ? CLAN_REQ_RELOAD : CLAN_REQ_FIRST;
+ c->req_count_tid = timer->add(timer->gettick() + clan->req_timeout, clan->request_membercount, c->clan_id, 0);
+ idb_put(clan->db, c->clan_id, c);
+ VECTOR_INIT(c->members);
+ valid++;
+ }
+
+ // Validating Relations
+ if (valid > 0) {
+ struct DBIterator *iter = db_iterator(clan->db);
+ struct clan *c_ok, *c;
+ int i;
+
+ for (c_ok = dbi_first(iter); dbi_exists(iter); c_ok = dbi_next(iter)) {
+ i = VECTOR_LENGTH(c_ok->allies);
+ while ( i > 0) {
+ struct clan_relationship *r;
+
+ i--;
+ r = &VECTOR_INDEX(c_ok->allies, i);
+ if ((c = clan->searchname(r->constant)) == NULL) {
+ ShowError("clan_read_db: Invalid (nonexistent) Ally '%s' for clan %d in '%s', skipping ally...\n", r->constant, c_ok->clan_id, source);
+ VECTOR_ERASE(c_ok->allies, i);
+ } else {
+ r->clan_id = c->clan_id;
+ }
+ }
+
+ i = VECTOR_LENGTH(c_ok->antagonists);
+ while ( i > 0) {
+ struct clan_relationship *r;
+
+ i--;
+ r = &VECTOR_INDEX(c_ok->antagonists, i);
+ if ((c = clan->searchname(r->constant)) == NULL) {
+ ShowError("clan_read_db: Invalid (nonexistent) Antagonist '%s' for clan %d in '%s', skipping antagonist...", r->constant, c_ok->clan_id, source);
+ VECTOR_ERASE(c_ok->antagonists, i);
+ } else {
+ r->clan_id = c->clan_id;
+ }
+ }
+ }
+ dbi_destroy(iter);
+ }
+
+ ShowStatus("Done reading '" CL_WHITE "%d" CL_RESET "' valid clans of '" CL_WHITE "%d" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n", valid, total, source);
+ return valid;
+}
+
+/**
+ * Reads Clan DB included by clan configuration file.
+ *
+ * @param settings The Settings Group from config file.
+ * @param source File name.
+ */
+static void clan_read_db(struct config_setting_t *settings, const char *source, bool reload)
+{
+ struct config_setting_t *clans;
+
+ nullpo_retv(settings);
+
+ if ((clans = libconfig->setting_get_member(settings, "clans")) != NULL) {
+ int read;
+
+ read = clan->read_db_sub(clans, source, reload);
+ if (read > 0) {
+ clan->set_constants();
+ }
+ } else {
+ ShowError("clan_read_db: Can't find setting 'clans' in '%s'. No Clans found.\n", source);
+ }
+}
+
+/**
+ * Reads clan config file
+ *
+ * @param bool clear Whether to clear clan->db before reading clans
+ */
+static bool clan_config_read(bool reload)
+{
+ struct config_t clan_conf;
+ struct config_setting_t *settings = NULL;
+ const char *config_filename = "conf/clans.conf"; // FIXME: hardcoded name
+ int kicktime = 0, kickchecktime = 0;
+
+ if (reload) {
+ struct DBIterator *iter = db_iterator(clan->db);
+ struct clan *c_clear;
+
+ for (c_clear = dbi_first(iter); dbi_exists(iter); c_clear = dbi_next(iter)) {
+ if (c_clear->buff.script != NULL) {
+ script->free_code(c_clear->buff.script);
+ }
+ if (c_clear->tid != INVALID_TIMER) {
+ timer->delete(c_clear->tid, clan->inactivity_kick);
+ }
+ VECTOR_CLEAR(c_clear->allies);
+ VECTOR_CLEAR(c_clear->antagonists);
+ VECTOR_CLEAR(c_clear->members);
+ HPM->data_store_destroy(&c_clear->hdata);
+ }
+ dbi_destroy(iter);
+ clan->db->clear(clan->db, NULL);
+ }
+
+ if (!libconfig->load_file(&clan_conf, config_filename)) {
+ return false;
+ }
+
+ if ((settings = libconfig->lookup(&clan_conf, "clan_configuration")) == NULL) {
+ ShowError("clan_config_read: failed to find 'clan_configuration'.\n");
+ return false;
+ }
+
+ libconfig->setting_lookup_int(settings, "MaxMembers", &clan->max);
+ libconfig->setting_lookup_int(settings, "MaxRelations", &clan->max_relations);
+ libconfig->setting_lookup_int(settings, "InactivityKickTime", &kicktime);
+ if (!libconfig->setting_lookup_int(settings, "InactivityCheckTime", &kickchecktime)) {
+ ShowError("clan_config_read: failed to find InactivityCheckTime using official value.\n");
+ kickchecktime = 24;
+ }
+
+ // On config file we set the time in hours but here we use in seconds
+ clan->kicktime = 60 * 60 * kicktime;
+ clan->checktime = 60 * 60 * max(kickchecktime, 1) * 1000;
+
+ clan->config_read_additional_settings(settings, config_filename);
+ clan->read_db(settings, config_filename, reload);
+ libconfig->destroy(&clan_conf);
+ return true;
+}
+
+/**
+ * Processes any (plugin-defined) additional settings for clan config.
+ *
+ * @param settings The Settings Group from config file.
+ * @param source Source of the entry (file name), to be displayed in
+ * case of validation errors.
+ */
+static void clan_config_read_additional_settings(struct config_setting_t *settings, const char *source)
+{
+ // do nothing. plugins can do own work
+}
+
+/**
+ * Reloads Clan DB
+ */
+static void clan_reload(void)
+{
+ clan->config_read(true);
+}
+
+/**
+ *
+ */
+static void do_init_clan(bool minimal)
+{
+ clan->db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+ if (minimal) {
+ return;
+ }
+ clan->config_read(false);
+ timer->add_func_list(clan->inactivity_kick, "clan_inactivity_kick");
+}
+
+/**
+ *
+ */
+static void do_final_clan(void)
+{
+ struct DBIterator *iter = db_iterator(clan->db);
+ struct clan *c;
+
+ for (c = dbi_first(iter); dbi_exists(iter); c = dbi_next(iter)) {
+ if (c->buff.script) {
+ script->free_code(c->buff.script);
+ }
+ if (c->tid != INVALID_TIMER) {
+ timer->delete(c->tid, clan->inactivity_kick);
+ }
+ VECTOR_CLEAR(c->allies);
+ VECTOR_CLEAR(c->antagonists);
+ VECTOR_CLEAR(c->members);
+ HPM->data_store_destroy(&c->hdata);
+ }
+ dbi_destroy(iter);
+ db_destroy(clan->db);
+}
+
+/**
+ * Inits Clan Defaults
+ */
+void clan_defaults(void)
+{
+ clan = &clan_s;
+
+ clan->init = do_init_clan;
+ clan->final = do_final_clan;
+ /* */
+ clan->db = NULL;
+ clan->max = 0;
+ clan->max_relations = 0;
+ clan->kicktime = 0;
+ clan->checktime = 0;
+ clan->req_timeout = 60;
+ /* */
+ clan->config_read = clan_config_read;
+ clan->config_read_additional_settings = clan_config_read_additional_settings;
+ clan->read_db = clan_read_db;
+ clan->read_db_sub = clan_read_db_sub;
+ clan->read_db_additional_fields = clan_read_db_additional_fields;
+ clan->read_buffs = clan_read_buffs;
+ clan->search = clan_search;
+ clan->searchname = clan_searchname;
+ clan->getonlinesd = clan_getonlinesd;
+ clan->getindex = clan_getindex;
+ clan->join = clan_join;
+ clan->member_online = clan_member_online;
+ clan->leave = clan_leave;
+ clan->send_message = clan_send_message;
+ clan->recv_message = clan_recv_message;
+ clan->member_offline = clan_member_offline;
+ clan->set_constants = clan_set_constants;
+ clan->get_id = clan_get_id;
+ clan->buff_start = clan_buff_start;
+ clan->buff_end = clan_buff_end;
+ clan->reload = clan_reload;
+ clan->rejoin = clan_rejoin;
+ clan->inactivity_kick = clan_inactivity_kick;
+ clan->request_kickoffline = clan_request_kickoffline;
+ clan->request_membercount = clan_request_membercount;
+}
diff --git a/src/map/clan.h b/src/map/clan.h
new file mode 100644
index 000000000..95ea8565c
--- /dev/null
+++ b/src/map/clan.h
@@ -0,0 +1,85 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017-2020 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_CLAN_H
+#define MAP_CLAN_H
+
+#include "map/map.h"
+#include "common/hercules.h"
+#include "common/db.h"
+#include "common/mmo.h"
+
+struct map_session_data;
+
+enum clan_req_state {
+ CLAN_REQ_NONE = 0,
+ CLAN_REQ_FIRST = 1,
+ CLAN_REQ_RELOAD = 2,
+ CLAN_REQ_AFTER_KICK = 3,
+};
+
+/**
+ * clan Interface
+ **/
+struct clan_interface {
+ struct DBMap *db; // int clan_id -> struct clan*
+
+ int max;
+ int max_relations;
+ int kicktime;
+ int checktime;
+ int req_timeout;
+
+ void (*init) (bool minimal);
+ void (*final) (void);
+
+ bool (*config_read) (bool reload);
+ void (*config_read_additional_settings) (struct config_setting_t *settings, const char *source);
+ void (*read_db) (struct config_setting_t *settings, const char *source, bool reload);
+ int (*read_db_sub) (struct config_setting_t *settings, const char *source, bool reload);
+ void (*read_db_additional_fields) (struct clan *entry, struct config_setting_t *t, int n, const char *source);
+ void (*read_buffs) (struct clan *c, struct config_setting_t *buff, const char *source);
+ struct clan *(*search) (int clan_id);
+ struct clan *(*searchname) (const char *name);
+ struct map_session_data *(*getonlinesd) (struct clan *c);
+ int (*getindex) (const struct clan *c, int char_id);
+ bool (*join) (struct map_session_data *sd, int clan_id);
+ void (*member_online) (struct map_session_data *sd, bool first);
+ bool (*leave) (struct map_session_data *sd, bool first);
+ bool (*send_message) (struct map_session_data *sd, const char *mes);
+ void (*recv_message) (struct clan *c, const char *mes, int len);
+ void (*member_offline) (struct map_session_data *sd);
+ void (*set_constants) (void);
+ int (*get_id) (const struct block_list *bl);
+ void (*buff_start) (struct map_session_data *sd, struct clan *c);
+ void (*buff_end) (struct map_session_data *sd, struct clan *c);
+ void (*reload) (void);
+ int (*rejoin) (struct map_session_data *sd, va_list ap);
+ int (*inactivity_kick) (int tid, int64 tick, int id, intptr_t data);
+ int (*request_kickoffline) (int tid, int64 tick, int id, intptr_t data);
+ int (*request_membercount) (int tid, int64 tick, int id, intptr_t data);
+};
+
+#ifdef HERCULES_CORE
+void clan_defaults (void);
+#endif // HERCULES_CORE
+
+HPShared struct clan_interface *clan;
+
+#endif /* MAP_CLAN_H */
diff --git a/src/map/clif.c b/src/map/clif.c
index e1b4be8f4..7be5c6978 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/elemental.h"
#include "map/guild.h"
#include "map/homunculus.h"
@@ -40,27 +41,33 @@
#include "map/mail.h"
#include "map/map.h"
#include "map/mercenary.h"
+#include "map/messages.h"
#include "map/mob.h"
#include "map/npc.h"
#include "map/party.h"
#include "map/pc.h"
#include "map/pet.h"
#include "map/quest.h"
+#include "map/rodex.h"
+#include "map/refine.h"
#include "map/script.h"
#include "map/skill.h"
#include "map/status.h"
+#include "map/stylist.h"
#include "map/storage.h"
#include "map/trade.h"
#include "map/unit.h"
#include "map/vending.h"
+#include "map/achievement.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/ers.h"
#include "common/grfio.h"
#include "common/memmgr.h"
-#include "common/mmo.h" // NEW_CARTS
+#include "common/mmo.h" // NEW_CARTS, char_achievements
#include "common/nullpo.h"
+#include "common/packets.h"
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
@@ -74,26 +81,25 @@
#include <stdarg.h>
#include <time.h>
-struct clif_interface clif_s;
+static struct clif_interface clif_s;
struct clif_interface *clif;
-struct s_packet_db packet_db[MAX_PACKET_DB + 1];
+static struct s_packet_db packet_db[MAX_PACKET_DB + 1];
/* re-usable */
static struct packet_itemlist_normal itemlist_normal;
static struct packet_itemlist_equip itemlist_equip;
-static struct packet_storelist_normal storelist_normal;
-static struct packet_storelist_equip storelist_equip;
+static struct ZC_STORE_ITEMLIST_NORMAL storelist_normal;
+static struct ZC_STORE_ITEMLIST_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
+// temporart buffer for send big packets
+char packet_buf[0xffff];
//#define DUMP_UNKNOWN_PACKET
//#define DUMP_INVALID_PACKET
//Converts item type in case of pet eggs.
-static inline int itemtype(int type) {
+static inline int itemtype(int type)
+{
switch( type ) {
#if PACKETVER >= 20080827
case IT_WEAPON:
@@ -108,7 +114,8 @@ static inline int itemtype(int type) {
}
}
-static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) {
+static inline void WBUFPOS(uint8 *p, unsigned short pos, short x, short y, unsigned char dir)
+{
p += pos;
p[0] = (uint8)(x>>2);
p[1] = (uint8)((x<<6) | ((y>>4)&0x3f));
@@ -116,7 +123,8 @@ static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsig
}
// client-side: x0+=sx0*0.0625-0.5 and y0+=sy0*0.0625-0.5
-static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) {
+static inline void WBUFPOS2(uint8 *p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0)
+{
p += pos;
p[0] = (uint8)(x0>>2);
p[1] = (uint8)((x0<<6) | ((y0>>4)&0x3f));
@@ -127,16 +135,19 @@ static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, sh
}
#if 0 // Currently unused
-static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir) {
+static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir)
+{
WBUFPOS(WFIFOP(fd,pos), 0, x, y, dir);
}
#endif // 0
-static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) {
+static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0)
+{
WBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0);
}
-static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* y, unsigned char* dir) {
+static inline void RBUFPOS(const uint8 *p, unsigned short pos, short *x, short *y, unsigned char *dir)
+{
p += pos;
if( x ) {
@@ -152,12 +163,14 @@ static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short*
}
}
-static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) {
+static inline void RFIFOPOS(int fd, unsigned short pos, short *x, short *y, unsigned char *dir)
+{
RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir);
}
#if 0 // currently unused
-static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) {
+static inline void RBUFPOS2(const uint8 *p, unsigned short pos, short *x0, short *y0, short *x1, short *y1, unsigned char *sx0, unsigned char *sy0)
+{
p += pos;
if( x0 ) {
@@ -184,13 +197,15 @@ static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short
sy0[0] = ( p[5] & 0x0f ) >> 0;
}
}
-static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) {
+
+static inline void RFIFOPOS2(int fd, unsigned short pos, short *x0, short *y0, short *x1, short *y1, unsigned char *sx0, unsigned char *sy0)
+{
RBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0);
}
#endif // 0
//To identify disguised characters.
-static inline bool disguised(struct block_list* bl)
+static bool clif_isdisguised(struct block_list *bl)
{
struct map_session_data *sd = BL_CAST(BL_PC, bl);
if (sd == NULL || sd->disguise == -1)
@@ -201,7 +216,8 @@ static inline bool disguised(struct block_list* bl)
/*==========================================
* Ip setting of map-server
*------------------------------------------*/
-bool clif_setip(const char* ip) {
+static bool clif_setip(const char *ip)
+{
char ip_str[16];
nullpo_retr(false, ip);
clif->map_ip = sockt->host2ip(ip);
@@ -215,7 +231,8 @@ bool clif_setip(const char* ip) {
return true;
}
-bool clif_setbindip(const char* ip) {
+static bool clif_setbindip(const char *ip)
+{
nullpo_retr(false, ip);
clif->bind_ip = sockt->host2ip(ip);
if ( clif->bind_ip ) {
@@ -231,30 +248,35 @@ bool clif_setbindip(const char* ip) {
* Sets map port to 'port'
* is run from map.c upon loading map server configuration
*------------------------------------------*/
-void clif_setport(uint16 port)
+static void clif_setport(uint16 port)
{
clif->map_port = port;
}
+#if 0 // Unused function
/*==========================================
* Returns map server IP
*------------------------------------------*/
-uint32 clif_getip(void)
+static uint32 clif_getip(void)
{
return clif->map_ip;
}
+#endif // 0
+#if 0 // Unused function
/*==========================================
* Returns map port which is set by clif_setport()
*------------------------------------------*/
-uint16 clif_getport(void)
+static uint16 clif_getport(void)
{
return clif->map_port;
}
+#endif // 0
+
/*==========================================
* Updates server ip resolution and returns it
*------------------------------------------*/
-uint32 clif_refresh_ip(void)
+static uint32 clif_refresh_ip(void)
{
uint32 new_ip = sockt->host2ip(clif->map_ip_str);
if ( new_ip && new_ip != clif->map_ip ) {
@@ -265,24 +287,54 @@ uint32 clif_refresh_ip(void)
return 0;
}
+static unsigned char clif_bl_type(struct block_list *bl)
+{
#if PACKETVER >= 20071106
-static inline unsigned char clif_bl_type(struct block_list *bl) {
- nullpo_retr(0x1, bl);
+ struct view_data *vd;
+ nullpo_retr(CLUT_NPC, bl);
+
switch (bl->type) {
- case BL_PC: return (disguised(bl) && !pc->db_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
- case BL_ITEM: return 0x2; //ITEM_TYPE
- case BL_SKILL: return 0x3; //SKILL_TYPE
- case BL_CHAT: return 0x4; //UNKNOWN_TYPE
- case BL_MOB: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
- case BL_NPC: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE
- case BL_PET: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
- case BL_HOM: return 0x8; //NPC_HOM_TYPE
- case BL_MER: return 0x9; //NPC_MERSOL_TYPE
- case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
- default: return 0x1; //NPC_TYPE
+ case BL_PC:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+
+ if (clif->isdisguised(bl) && !pc->db_checkid(vd->class))
+ return CLUT_NPC;
+ return CLUT_PC;
+ case BL_ITEM:
+ return CLUT_ITEM;
+ case BL_SKILL:
+ return CLUT_SKILL;
+ case BL_CHAT:
+ return CLUT_UNKNOWN;
+ case BL_MOB:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+ return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_MOB;
+ case BL_NPC:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+#if PACKETVER >= 20170726
+ return CLUT_EVENT;
+#else
+ return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_EVENT;
+#endif
+ case BL_PET:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+ return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_PET;
+ case BL_HOM:
+ return CLUT_HOMNUCLUS;
+ case BL_MER:
+ return CLUT_MERCNARY;
+ case BL_ELEM:
+ return CLUT_ELEMENTAL;
+ default:
+ return CLUT_NPC;
}
-}
#endif
+ return CLUT_UNKNOWN;
+}
/*==========================================
* sub process of clif_send
@@ -294,7 +346,8 @@ static inline unsigned char clif_bl_type(struct block_list *bl) {
* - AREA_WOS (AREA WITHOUT SELF) : Not run for self
* - AREA_CHAT_WOC : Everyone in the area of your chat without a chat
*------------------------------------------*/
-int clif_send_sub(struct block_list *bl, va_list ap) {
+static int clif_send_sub(struct block_list *bl, va_list ap)
+{
struct block_list *src_bl;
struct map_session_data *sd;
void *buf;
@@ -319,17 +372,17 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
return 0;
break;
case AREA_WOC:
- if (sd->chatID || bl == src_bl)
+ if (sd->chat_id != 0 || bl == src_bl)
return 0;
break;
case AREA_WOSC: {
if (src_bl->type == BL_PC) {
const struct map_session_data *ssd = BL_UCCAST(BL_PC, src_bl);
- if (ssd != NULL && sd->chatID != 0 && (sd->chatID == ssd->chatID))
+ if (ssd != NULL && sd->chat_id != 0 && (sd->chat_id == ssd->chat_id))
return 0;
} else if (src_bl->type == BL_NPC) {
const struct npc_data *nd = BL_UCCAST(BL_NPC, src_bl);
- if (nd != NULL && sd->chatID != 0 && (sd->chatID == nd->chat_id))
+ if (nd != NULL && sd->chat_id != 0 && (sd->chat_id == nd->chat_id))
return 0;
}
}
@@ -350,7 +403,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
return clif->send_actual(fd, buf, len);
}
-int clif_send_actual(int fd, void *buf, int len)
+static int clif_send_actual(int fd, void *buf, int len)
{
nullpo_retr(0, buf);
WFIFOHEAD(fd, len);
@@ -374,22 +427,30 @@ int clif_send_actual(int fd, void *buf, int len)
* Packet Delegation (called on all packets that require data to be sent to more than one client)
* functions that are sent solely to one use whose ID it posses use WFIFOSET
*------------------------------------------*/
-bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target type) {
+static bool clif_send(const void *buf, int len, struct block_list *bl, enum send_target type)
+{
+ if (type != ALL_CLIENT)
+ nullpo_retr(false, bl);
+ nullpo_retr(false, buf);
+ Assert_retr(false, len > 0);
+
int i;
- struct map_session_data *sd, *tsd;
+ struct map_session_data *sd = BL_CAST(BL_PC, bl), *tsd;
struct party_data *p = NULL;
struct guild *g = NULL;
struct battleground_data *bgd = NULL;
int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd;
struct s_mapiterator* iter;
+ int area_size;
- if( type != ALL_CLIENT )
- nullpo_ret(bl);
-
- sd = BL_CAST(BL_PC, bl);
+ if (sd != NULL && pc_isinvisible(sd)) {
+ if (type == AREA || type == BG || type == BG_AREA)
+ type = SELF;
+ else if (type == AREA_WOS || type == BG_WOS || type == BG_AREA_WOS)
+ return true;
+ }
switch(type) {
-
case ALL_CLIENT: //All player clients.
iter = mapit_getallusers();
while ((tsd = BL_UCAST(BL_PC, mapit->next(iter))) != NULL) {
@@ -414,19 +475,24 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
case AREA:
case AREA_WOSC:
+ case AREA_DEAD:
if (sd && bl->prev == NULL) //Otherwise source misses the packet.[Skotlex]
clif->send (buf, len, bl, SELF);
/* Fall through */
case AREA_WOC:
case AREA_WOS:
+ if (type == AREA_DEAD)
+ area_size = DEAD_AREA_SIZE;
+ else
+ area_size = AREA_SIZE;
nullpo_retr(true, bl);
- map->foreachinarea(clif->send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE,
+ map->foreachinarea(clif->send_sub, bl->m, bl->x - area_size, bl->y - area_size, bl->x + area_size, bl->y + area_size,
BL_PC, buf, len, bl, type);
break;
case AREA_CHAT_WOC:
nullpo_retr(true, bl);
- map->foreachinarea(clif->send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5),
- bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC);
+ map->foreachinarea(clif->send_sub, bl->m, bl->x-CHAT_AREA_SIZE, bl->y-CHAT_AREA_SIZE,
+ bl->x+CHAT_AREA_SIZE, bl->y+CHAT_AREA_SIZE, BL_PC, buf, len, bl, AREA_WOC);
break;
case CHAT:
@@ -435,7 +501,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
{
const struct chat_data *cd = NULL;
if (sd != NULL) {
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
} else {
cd = BL_CCAST(BL_CHAT, bl);
}
@@ -628,6 +694,22 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
}
break;
+ case CLAN:
+ if (sd && sd->status.clan_id) {
+ struct clan *c = clan->search(sd->status.clan_id);
+
+ nullpo_retr(false, c);
+
+ for (i = 0; i < VECTOR_LENGTH(c->members); i++) {
+ if (VECTOR_INDEX(c->members, i).online == 0 || (sd = VECTOR_INDEX(c->members, i).sd) == NULL || (fd = sd->fd) <= 0)
+ continue;
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd, 0), buf, len);
+ WFIFOSET(fd, len);
+ }
+ }
+ break;
+
default:
ShowError("clif_send: Unrecognized type %u\n", type);
return false;
@@ -639,7 +721,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
/// Notifies the client, that it's connection attempt was accepted.
/// 0073 <start time>.L <position>.3B <x size>.B <y size>.B (ZC_ACCEPT_ENTER)
/// 02eb <start time>.L <position>.3B <x size>.B <y size>.B <font>.W (ZC_ACCEPT_ENTER2)
-void clif_authok(struct map_session_data *sd)
+static void clif_authok(struct map_session_data *sd)
{
struct packet_authok p;
@@ -651,12 +733,14 @@ void clif_authok(struct map_session_data *sd)
#if PACKETVER >= 20080102
p.font = sd->status.font;
#endif
-#if PACKETVER >= 20141016
+// Some clients smaller than 20160330 cant be tested [4144]
+#if PACKETVER >= 20141022 && PACKETVER < 20160330
p.sex = sd->status.sex;
#endif
clif->send(&p,sizeof(p),&sd->bl,SELF);
}
+/// [4144] Packet not using error_code anymore. Works for fixed error only (MsgString: 9 - Rejected from Server)
/// Notifies the client, that it's connection attempt was refused (ZC_REFUSE_ENTER).
/// 0074 <error code>.B
/// error code:
@@ -665,7 +749,7 @@ void clif_authok(struct map_session_data *sd)
/// 2 = mobile - out of available time
/// 3 = mobile - already logged in
/// 4 = mobile - waiting state
-void clif_authrefuse(int fd, uint8 error_code)
+static void clif_authrefuse(int fd, uint8 error_code)
{
WFIFOHEAD(fd,packet_len(0x74));
WFIFOW(fd,0) = 0x74;
@@ -704,9 +788,11 @@ void clif_authrefuse(int fd, uint8 error_code)
/// 108 = BAN_IP_BLOCK
/// 109 = BAN_INVALID_PWD_CNT
/// 110 = BAN_NOT_ALLOWED_JOBCLASS
+/// 113 = access is restricted between the hours of midnight to 6:00am.
+/// 115 = You are in game connection ban period.
/// ? = disconnected -> MsgStringTable[3]
// TODO: type enum
-void clif_authfail_fd(int fd, int type)
+static void clif_authfail_fd(int fd, int type)
{
if (!fd || !sockt->session[fd] || sockt->session[fd]->func_parse != clif->parse) //clif_authfail should only be invoked on players!
return;
@@ -724,7 +810,8 @@ void clif_authfail_fd(int fd, int type)
/// type:
/// 1 = disconnect, char-select
/// ? = nothing
-void clif_charselectok(int id, uint8 ok) {
+static void clif_charselectok(int id, uint8 ok)
+{
struct map_session_data* sd;
int fd;
@@ -741,7 +828,8 @@ void clif_charselectok(int id, uint8 ok) {
/// Makes an item appear on the ground.
/// 009e <id>.L <name id>.W <identified>.B <x>.W <y>.W <subX>.B <subY>.B <amount>.W (ZC_ITEM_FALL_ENTRY)
/// 084b (ZC_ITEM_FALL_ENTRY4)
-void clif_dropflooritem(struct flooritem_data* fitem) {
+static void clif_dropflooritem(struct flooritem_data *fitem)
+{
struct packet_dropflooritem p;
int view;
@@ -762,13 +850,21 @@ void clif_dropflooritem(struct flooritem_data* fitem) {
p.subX = fitem->subx;
p.subY = fitem->suby;
p.count = fitem->item_data.amount;
-
+#if defined(PACKETVER_ZERO) || PACKETVER >= 20180418
+ if (fitem->showdropeffect) {
+ p.showdropeffect = itemdb_showdropeffect(fitem->item_data.nameid);
+ p.dropeffectmode = itemdb_dropeffectmode(fitem->item_data.nameid);
+ } else {
+ p.showdropeffect = 0;
+ p.dropeffectmode = 0;
+ }
+#endif
clif->send(&p, sizeof(p), &fitem->bl, AREA);
}
/// Makes an item disappear from the ground.
/// 00a1 <id>.L (ZC_ITEM_DISAPPEAR)
-void clif_clearflooritem(struct flooritem_data *fitem, int fd)
+static void clif_clearflooritem(struct flooritem_data *fitem, int fd)
{
unsigned char buf[16];
@@ -794,7 +890,7 @@ void clif_clearflooritem(struct flooritem_data *fitem, int fd)
/// 2 = logged out
/// 3 = teleport
/// 4 = trickdead
-void clif_clearunit_single(int id, clr_type type, int fd)
+static void clif_clearunit_single(int id, enum clr_type type, int fd)
{
WFIFOHEAD(fd, packet_len(0x80));
WFIFOW(fd,0) = 0x80;
@@ -811,7 +907,7 @@ void clif_clearunit_single(int id, clr_type type, int fd)
/// 2 = logged out
/// 3 = teleport
/// 4 = trickdead
-void clif_clearunit_area(struct block_list* bl, clr_type type)
+static void clif_clearunit_area(struct block_list *bl, enum clr_type type)
{
unsigned char buf[8];
@@ -821,9 +917,14 @@ void clif_clearunit_area(struct block_list* bl, clr_type type)
WBUFL(buf,2) = bl->id;
WBUFB(buf,6) = type;
- clif->send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS);
+ /**
+ * When monster dies, there's a delay before the packet is sent,
+ * so we send it to a bigger area to avoid clients at the edge
+ * walking out of the area and missing it [KirieZ]
+ */
+ clif->send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA_DEAD : AREA_WOS);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x80), bl, SELF);
}
@@ -832,14 +933,16 @@ void clif_clearunit_area(struct block_list* bl, clr_type type)
/// Used to make monsters with player-sprites disappear after dying
/// like normal monsters, because the client does not remove those
/// automatically.
-int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) {
+static int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl = (struct block_list *)data;
- clif->clearunit_area(bl, (clr_type) id);
+ clif->clearunit_area(bl, (enum clr_type) id);
ers_free(clif->delay_clearunit_ers,bl);
return 0;
}
-void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) {
+static void clif_clearunit_delayed(struct block_list *bl, enum clr_type type, int64 tick)
+{
struct block_list *tbl;
nullpo_retv(bl);
@@ -849,7 +952,7 @@ void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) {
}
/// Gets weapon view info from sd's inventory_data and points (*rhand,*lhand)
-void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand)
+static void clif_get_weapon_view(struct map_session_data *sd, int *rhand, int *lhand)
{
nullpo_retv(sd);
nullpo_retv(rhand);
@@ -860,8 +963,8 @@ void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, un
}
#if PACKETVER < 4
- *rhand = sd->status.weapon;
- *lhand = sd->status.shield;
+ *rhand = sd->status.look.weapon;
+ *lhand = sd->status.look.shield;
#else
if (sd->equip_index[EQI_HAND_R] >= 0 &&
sd->inventory_data[sd->equip_index[EQI_HAND_R]])
@@ -889,7 +992,8 @@ void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, un
}
//To make the assignation of the level based on limits clearer/easier. [Skotlex]
-static int clif_setlevel_sub(int lv) {
+static int clif_setlevel_sub(int lv)
+{
if( lv < battle_config.max_lv ) {
;
} else if( lv < battle_config.aura_lv ) {
@@ -901,7 +1005,8 @@ static int clif_setlevel_sub(int lv) {
return lv;
}
-static int clif_setlevel(struct block_list* bl) {
+static int clif_setlevel(struct block_list *bl)
+{
int lv = status->get_lv(bl);
nullpo_retr(0, bl);
if( battle_config.client_limit_unit_lv&bl->type )
@@ -914,8 +1019,10 @@ static int clif_setlevel(struct block_list* bl) {
}
return lv;
}
+
/* for 'packetver < 20091103' 0x78 non-pc-looking unit handling */
-void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, enum send_target target) {
+static void clif_set_unit_idle2(struct block_list *bl, struct map_session_data *tsd, enum send_target target)
+{
#if PACKETVER < 20091103
struct map_session_data* sd;
struct status_change* sc = status->get_sc(bl);
@@ -928,21 +1035,22 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en
p.PacketType = idle_unit2Type;
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
p.GID = bl->id;
p.speed = status->get_speed(bl);
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- p.job = vd->class_;
+ p.job = vd->class;
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
p.shield = vd->shield;
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
- if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ if (bl->type == BL_NPC && vd->class == FLAG_CLASS) {
+ // The hell, why flags work like this?
p.shield = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
@@ -966,10 +1074,12 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en
return;
#endif
}
+
/*==========================================
* Prepares 'unit standing' packet
*------------------------------------------*/
-void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enum send_target target) {
+static void clif_set_unit_idle(struct block_list *bl, struct map_session_data *tsd, enum send_target target)
+{
struct map_session_data* sd;
struct status_change* sc = status->get_sc(bl);
struct view_data* vd = status->get_viewdata(bl);
@@ -979,7 +1089,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
nullpo_retv(bl);
#if PACKETVER < 20091103
- if( !pc->db_checkid(vd->class_) ) {
+ if (!pc->db_checkid(vd->class)) {
clif->set_unit_idle2(bl,tsd,target);
return;
}
@@ -990,7 +1100,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.PacketType = idle_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
@@ -1002,16 +1112,17 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- p.job = vd->class_;
+ p.job = vd->class;
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
-#if PACKETVER < 7
+#if PACKETVER < 7 || PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
p.shield = vd->shield;
#endif
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
- if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ if (bl->type == BL_NPC && vd->class == FLAG_CLASS) {
+ // The hell, why flags work like this?
p.accessory = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
@@ -1037,27 +1148,36 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
-
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
#if PACKETVER >= 20091103
- p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+ p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20131223
+ p.AID = -bl->id;
+#else
p.GID = -bl->id;
+#endif
#else
p.GID = -bl->id;
#endif
@@ -1065,8 +1185,10 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
}
}
+
/* for 'packetver < 20091103' 0x7c non-pc-looking unit handling */
-void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
+static void clif_spawn_unit2(struct block_list *bl, enum send_target target)
+{
#if PACKETVER < 20091103
struct map_session_data* sd;
struct status_change* sc = status->get_sc(bl);
@@ -1079,7 +1201,7 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
p.PacketType = spawn_unit2Type;
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
p.GID = bl->id;
p.speed = status->get_speed(bl);
@@ -1089,11 +1211,12 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
- p.job = vd->class_;
+ p.job = vd->class;
p.shield = vd->shield;
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
- if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ if (bl->type == BL_NPC && vd->class == FLAG_CLASS) {
+ // The hell, why flags work like this?
p.shield = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
@@ -1111,7 +1234,9 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
return;
#endif
}
-void clif_spawn_unit(struct block_list* bl, enum send_target target) {
+
+static void clif_spawn_unit(struct block_list *bl, enum send_target target)
+{
struct map_session_data* sd;
struct status_change* sc = status->get_sc(bl);
struct view_data* vd = status->get_viewdata(bl);
@@ -1121,7 +1246,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
nullpo_retv(bl);
#if PACKETVER < 20091103
- if( !pc->db_checkid(vd->class_) ) {
+ if (!pc->db_checkid(vd->class)) {
clif->spawn_unit2(bl,target);
return;
}
@@ -1132,7 +1257,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.PacketType = spawn_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
@@ -1144,16 +1269,17 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- p.job = vd->class_;
+ p.job = vd->class;
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
-#if PACKETVER < 7
+#if PACKETVER < 7 || PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
p.shield = vd->shield;
#endif
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
- if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ if (bl->type == BL_NPC && vd->class == FLAG_CLASS) {
+ // The hell, why flags work like this?
p.accessory = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
@@ -1178,27 +1304,37 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
nullpo_retv(sd);
- if( sd->status.class_ != sd->disguise )
+ if (sd->status.class != sd->disguise)
clif->send(&p,sizeof(p),bl,target);
#if PACKETVER >= 20091103
- p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+ p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20131223
+ p.AID = -bl->id;
+#else
p.GID = -bl->id;
+#endif
#else
p.GID = -bl->id;
#endif
@@ -1211,7 +1347,8 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
/*==========================================
* Prepares 'unit walking' packet
*------------------------------------------*/
-void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, struct unit_data* ud, enum send_target target) {
+static void clif_set_unit_walking(struct block_list *bl, struct map_session_data *tsd, struct unit_data *ud, enum send_target target)
+{
struct map_session_data* sd;
struct status_change* sc = status->get_sc(bl);
struct view_data* vd = status->get_viewdata(bl);
@@ -1228,11 +1365,11 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.PacketLength = sizeof(p);
#endif
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
- p.GID = (tsd) ? tsd->status.char_id : 0; // CCODE
+ p.GID = (sd) ? sd->status.char_id : 0; // CCODE
#else
p.GID = bl->id;
#endif
@@ -1240,12 +1377,12 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- p.job = vd->class_;
+ p.job = vd->class;
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
p.moveStartTime = (unsigned int)timer->gettick();
-#if PACKETVER < 7
+#if PACKETVER < 7 || PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
p.shield = vd->shield;
#endif
p.accessory2 = vd->head_top;
@@ -1270,27 +1407,37 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
#if PACKETVER >= 20091103
- p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+ p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20131223
+ p.AID = -bl->id;
+#else
p.GID = -bl->id;
+#endif
#else
p.GID = -bl->id;
#endif
@@ -1302,7 +1449,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
/// 01b0 <id>.L <type>.B <value>.L
/// type:
/// unused
-void clif_class_change(struct block_list *bl, int class_, int type)
+static void clif_class_change(struct block_list *bl, int class_, int type, struct map_session_data *sd)
{
nullpo_retv(bl);
@@ -1313,14 +1460,19 @@ void clif_class_change(struct block_list *bl, int class_, int type)
WBUFL(buf,2)=bl->id;
WBUFB(buf,6)=type;
WBUFL(buf,7)=class_;
- clif->send(buf,packet_len(0x1b0),bl,AREA);
+
+ if (sd == NULL)
+ clif->send(buf, packet_len(0x1b0), bl, AREA);
+ else
+ clif->send(buf, packet_len(0x1b0), &sd->bl, SELF);
}
}
/// Notifies the client of an object's spirits.
/// 01d0 <id>.L <amount>.W (ZC_SPIRITS)
/// 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
-void clif_spiritball_single(int fd, struct map_session_data *sd) {
+static void clif_spiritball_single(int fd, struct map_session_data *sd)
+{
nullpo_retv(sd);
WFIFOHEAD(fd, packet_len(0x1e1));
WFIFOW(fd,0)=0x1e1;
@@ -1332,8 +1484,9 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) {
/*==========================================
* Kagerou/Oboro amulet spirit
*------------------------------------------*/
-void clif_charm_single(int fd, struct map_session_data *sd)
+static void clif_charm_single(int fd, struct map_session_data *sd)
{
+#if PACKETVER >= 20110809
nullpo_retv(sd);
WFIFOHEAD(fd, packet_len(0x08cf));
WFIFOW(fd,0) = 0x08cf;
@@ -1341,13 +1494,15 @@ void clif_charm_single(int fd, struct map_session_data *sd)
WFIFOW(fd,6) = sd->charm_type;
WFIFOW(fd,8) = sd->charm_count;
WFIFOSET(fd, packet_len(0x08cf));
+#endif
}
/*==========================================
* Run when player changes map / refreshes
* Tells its client to display all weather settings being used by this map
*------------------------------------------*/
-void clif_weather_check(struct map_session_data *sd) {
+static void clif_weather_check(struct map_session_data *sd)
+{
int16 m;
int fd;
@@ -1372,10 +1527,11 @@ void clif_weather_check(struct map_session_data *sd) {
if (map->list[m].flag.leaves)
clif->specialeffect_single(&sd->bl, 333, fd);
}
+
/**
* Run when the weather on a map changes, throws all players in map id 'm' to clif_weather_check function
**/
-void clif_weather(int16 m)
+static void clif_weather(int16 m)
{
struct s_mapiterator* iter;
struct map_session_data *sd=NULL;
@@ -1387,10 +1543,11 @@ void clif_weather(int16 m)
}
mapit->free(iter);
}
+
/**
* Main function to spawn a unit on the client (player/mob/pet/etc)
**/
-bool clif_spawn(struct block_list *bl)
+static bool clif_spawn(struct block_list *bl)
{
struct view_data *vd;
@@ -1399,7 +1556,7 @@ bool clif_spawn(struct block_list *bl)
if( !vd )
return false;
- if (vd->class_ == INVISIBLE_CLASS)
+ if (vd->class == INVISIBLE_CLASS)
return true; // Doesn't need to be spawned, so everything is alright
if (bl->type == BL_NPC) {
@@ -1429,12 +1586,14 @@ bool clif_spawn(struct block_list *bl)
if (sd->bg_id != 0 && map->list[sd->bl.m].flag.battleground)
clif->sendbgemblem_area(sd);
for (i = 0; i < sd->sc_display_count; i++) {
- clif->sc_load(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
+ clif->sc_continue(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(sd->sc_display[i]->type), sd->sc_display[i]->val1, sd->sc_display[i]->val2, sd->sc_display[i]->val3);
+
}
if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
clif->spiritcharm(sd);
- if (sd->status.robe)
- clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
+ if (sd->status.look.robe != 0)
+ clif->refreshlook(bl, bl->id, LOOK_ROBE, sd->status.look.robe, AREA);
+ clif->hat_effect(bl, NULL, AREA);
}
break;
case BL_MOB:
@@ -1453,6 +1612,8 @@ bool clif_spawn(struct block_list *bl)
clif->specialeffect(&nd->bl,423,AREA);
else if (nd->size == SZ_MEDIUM)
clif->specialeffect(&nd->bl,421,AREA);
+ if (nd->clan_id > 0)
+ clif->sc_load(&nd->bl, nd->bl.id, AREA, status->get_sc_icon(SC_CLAN_INFO), 0, nd->clan_id, 0);
}
break;
case BL_PET:
@@ -1465,10 +1626,12 @@ bool clif_spawn(struct block_list *bl)
/// Sends information about owned homunculus to the client (ZC_PROPERTY_HOMUN). [orn]
/// 022e <name>.24B <modified>.B <level>.W <hunger>.W <intimacy>.W <equip id>.W <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W <hp>.W <max hp>.W <sp>.W <max sp>.W <exp>.L <max exp>.L <skill points>.W <atk range>.W
-void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) {
+static void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
+{
+#if PACKETVER_MAIN_NUM >= 20101005 || PACKETVER_RE_NUM >= 20080827 || defined(PACKETVER_ZERO)
struct status_data *hstatus;
- unsigned char buf[128];
enum homun_type htype;
+ struct PACKET_ZC_PROPERTY_HOMUN p;
nullpo_retv(sd);
nullpo_retv(hd);
@@ -1476,65 +1639,76 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
hstatus = &hd->battle_status;
htype = homun->class2type(hd->homunculus.class_);
- memset(buf,0,packet_len(0x22e));
- WBUFW(buf,0)=0x22e;
- memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH);
+ memset(&p, 0, sizeof(p));
+ p.packetType = HEADER_ZC_PROPERTY_HOMUN;
+ memcpy(p.name, hd->homunculus.name, NAME_LENGTH);
// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
- WBUFB(buf,26)=(battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0);
- WBUFW(buf,27)=hd->homunculus.level;
- WBUFW(buf,29)=hd->homunculus.hunger;
- WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ;
- WBUFW(buf,33)=0; // equip id
+ p.flags = (!battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0);
+ p.level = hd->homunculus.level;
+ p.hunger = hd->homunculus.hunger;
+ p.intimacy = hd->homunculus.intimacy / 100;
+#if !(PACKETVER_MAIN_NUM >= 20190619 || PACKETVER_RE_NUM >= 20190605 || PACKETVER_ZERO_NUM >= 20190626)
+ p.itemId = 0; // equip id
+#endif
#ifdef RENEWAL
- WBUFW(buf, 35) = cap_value(hstatus->rhw.atk2, 0, INT16_MAX);
+ p.atk2 = cap_value(hstatus->rhw.atk2, 0, INT16_MAX);
#else
- WBUFW(buf,35)=cap_value(hstatus->rhw.atk2+hstatus->batk, 0, INT16_MAX);
+ p.atk2 = cap_value(hstatus->rhw.atk2 + hstatus->batk, 0, INT16_MAX);
#endif
- WBUFW(buf,37)=cap_value(hstatus->matk_max, 0, INT16_MAX);
- WBUFW(buf,39)=hstatus->hit;
+ p.matk = cap_value(hstatus->matk_max, 0, INT16_MAX);
+ p.hit = hstatus->hit;
if (battle_config.hom_setting&0x10)
- WBUFW(buf,41)=hstatus->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious]
+ p.crit = hstatus->luk / 3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious]
else
- WBUFW(buf,41)=hstatus->cri/10;
+ p.crit = hstatus->cri / 10;
#ifdef RENEWAL
- WBUFW(buf, 43) = hstatus->def + hstatus->def2;
- WBUFW(buf, 45) = hstatus->mdef + hstatus->mdef2;
+ p.def = hstatus->def + hstatus->def2;
+ p.mdef = hstatus->mdef + hstatus->mdef2;
#else
- WBUFW(buf,43)=hstatus->def + hstatus->vit ;
- WBUFW(buf, 45) = hstatus->mdef;
+ p.def = hstatus->def + hstatus->vit ;
+ p.mdef = hstatus->mdef;
#endif
- WBUFW(buf,47)=hstatus->flee;
- WBUFW(buf,49)=(flag)?0:hstatus->amotion;
+ p.flee = hstatus->flee;
+ p.amotion = (flag) ? 0 : hstatus->amotion;
+
+// probably can works also for < 20141223, but in 3CeaM packet size defined only for 20150513
+#if PACKETVER < 20150513
if (hstatus->max_hp > INT16_MAX) {
- WBUFW(buf,51) = hstatus->hp/(hstatus->max_hp/100);
- WBUFW(buf,53) = 100;
+ p.hp = hstatus->hp / (hstatus->max_hp / 100);
+ p.maxHp = 100;
} else {
- WBUFW(buf,51)=hstatus->hp;
- WBUFW(buf,53)=hstatus->max_hp;
+ p.hp = hstatus->hp;
+ p.maxHp = hstatus->max_hp;
}
+#else
+ p.hp = hstatus->hp;
+ p.maxHp = hstatus->max_hp;
+#endif
+
if (hstatus->max_sp > INT16_MAX) {
- WBUFW(buf,55) = hstatus->sp/(hstatus->max_sp/100);
- WBUFW(buf,57) = 100;
+ p.sp = hstatus->sp / (hstatus->max_sp / 100);
+ p.maxSp = 100;
} else {
- WBUFW(buf,55)=hstatus->sp;
- WBUFW(buf,57)=hstatus->max_sp;
+ p.sp = hstatus->sp;
+ p.maxSp = hstatus->max_sp;
}
- WBUFL(buf,59)=hd->homunculus.exp;
- WBUFL(buf,63)=hd->exp_next;
- switch( htype ) {
+ p.exp = hd->homunculus.exp;
+ p.expNext = hd->exp_next;
+ switch (htype) {
case HT_REG:
case HT_EVO:
- if( hd->homunculus.level >= battle_config.hom_max_level )
- WBUFL(buf,63)=0;
+ if (hd->homunculus.level >= battle_config.hom_max_level)
+ p.expNext = 0;
break;
case HT_S:
- if( hd->homunculus.level >= battle_config.hom_S_max_level )
- WBUFL(buf,63)=0;
+ if (hd->homunculus.level >= battle_config.hom_S_max_level)
+ p.expNext = 0;
break;
}
- WBUFW(buf,67)=hd->homunculus.skillpts;
- WBUFW(buf,69)=status_get_range(&hd->bl);
- clif->send(buf,packet_len(0x22e),&sd->bl,SELF);
+ p.skillPoints = hd->homunculus.skillpts;
+ p.range = status_get_range(&hd->bl);
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
}
/// Notification about a change in homunuculus' state (ZC_CHANGESTATE_MER).
@@ -1547,7 +1721,7 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
/// 2 = hunger
/// 3 = accessory?
/// ? = ignored
-void clif_send_homdata(struct map_session_data *sd, int state, int param)
+static void clif_send_homdata(struct map_session_data *sd, int state, int param)
{
int fd;
@@ -1568,7 +1742,8 @@ void clif_send_homdata(struct map_session_data *sd, int state, int param)
}
/// Prepares and sends homun related information [orn]
-void clif_homskillinfoblock(struct map_session_data *sd) {
+static void clif_homskillinfoblock(struct map_session_data *sd)
+{
struct homun_data *hd;
int fd;
int i,j;
@@ -1589,8 +1764,7 @@ void clif_homskillinfoblock(struct map_session_data *sd) {
if ( id != 0 ) {
j = id - HM_SKILLBASE;
WFIFOW(fd, len) = id;
- WFIFOW(fd, len + 2) = skill->get_inf(id);
- WFIFOW(fd, len + 4) = 0;
+ WFIFOL(fd, len + 2) = skill->get_inf(id);
WFIFOW(fd, len + 6) = hd->homunculus.hskill[j].lv;
if ( hd->homunculus.hskill[j].lv ) {
WFIFOW(fd, len + 8) = skill->get_sp(id, hd->homunculus.hskill[j].lv);
@@ -1610,7 +1784,9 @@ void clif_homskillinfoblock(struct map_session_data *sd) {
return;
}
-void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn]
+//[orn]
+static void clif_homskillup(struct map_session_data *sd, uint16 skill_id)
+{
struct homun_data *hd;
int fd, idx;
nullpo_retv(sd);
@@ -1630,24 +1806,30 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn]
WFIFOSET(fd,packet_len(0x239));
}
-void clif_hom_food(struct map_session_data *sd,int foodid,int fail)
+/// Result of request to feed a homun/merc (ZC_FEED_MER).
+/// 022f <result>.B <name id>.W
+/// result:
+/// 0 = failure
+/// 1 = success
+static void clif_hom_food(struct map_session_data *sd, int foodid, int fail)
{
int fd;
+ struct PACKET_ZC_FEED_MER p;
+
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x22f));
- WFIFOW(fd,0)=0x22f;
- WFIFOB(fd,2)=fail;
- WFIFOW(fd,3)=foodid;
- WFIFOSET(fd,packet_len(0x22f));
-
- return;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x22f;
+ p.result = fail;
+ p.itemId = foodid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Notifies the client, that it is walking (ZC_NOTIFY_PLAYERMOVE).
/// 0087 <walk start time>.L <walk data>.6B
-void clif_walkok(struct map_session_data *sd)
+static void clif_walkok(struct map_session_data *sd)
{
int fd;
@@ -1660,7 +1842,8 @@ void clif_walkok(struct map_session_data *sd)
WFIFOSET(fd,packet_len(0x87));
}
-void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) {
+static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud)
+{
#ifdef ANTI_MAYAP_CHEAT
struct status_change *sc = NULL;
#endif
@@ -1714,7 +1897,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
/// Notifies clients in an area, that an other visible object is walking (ZC_NOTIFY_PLAYERMOVE).
/// 0086 <id>.L <walk data>.6B <walk start time>.L
/// Note: unit must not be self
-void clif_move(struct unit_data *ud)
+static void clif_move(struct unit_data *ud)
{
unsigned char buf[16];
struct view_data *vd;
@@ -1727,7 +1910,7 @@ void clif_move(struct unit_data *ud)
bl = ud->bl;
nullpo_retv(bl);
vd = status->get_viewdata(bl);
- if (!vd || vd->class_ == INVISIBLE_CLASS)
+ if (vd == NULL || vd->class == INVISIBLE_CLASS)
return; //This performance check is needed to keep GM-hidden objects from being notified to bots.
if (bl->type == BL_NPC) {
@@ -1756,7 +1939,7 @@ void clif_move(struct unit_data *ud)
clif->send(buf, packet_len(0x86), bl, AREA_WOS);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2)=-bl->id;
clif->send(buf, packet_len(0x86), bl, SELF);
}
@@ -1768,7 +1951,8 @@ void clif_move(struct unit_data *ud)
/*==========================================
* Delays the map->quit of a player after they are disconnected. [Skotlex]
*------------------------------------------*/
-int clif_delayquit(int tid, int64 tick, int id, intptr_t data) {
+static int clif_delayquit(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = NULL;
//Remove player from map server
@@ -1780,7 +1964,8 @@ int clif_delayquit(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
*
*------------------------------------------*/
-void clif_quitsave(int fd, struct map_session_data *sd) {
+static void clif_quitsave(int fd, struct map_session_data *sd)
+{
nullpo_retv(sd);
if (!battle_config.prevent_logout ||
DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)
@@ -1796,7 +1981,8 @@ void clif_quitsave(int fd, struct map_session_data *sd) {
/// Notifies the client of a position change to coordinates on given map (ZC_NPCACK_MAPMOVE).
/// 0091 <map name>.16B <x>.W <y>.W
-void clif_changemap(struct map_session_data *sd, short m, int x, int y) {
+static void clif_changemap(struct map_session_data *sd, short m, int x, int y)
+{
int fd;
nullpo_retv(sd);
fd = sd->fd;
@@ -1809,24 +1995,81 @@ void clif_changemap(struct map_session_data *sd, short m, int x, int y) {
WFIFOSET(fd,packet_len(0x91));
}
+/// Notifies the client of a position change (on air ship) to coordinates on given map (ZC_AIRSHIP_MAPMOVE).
+/// 0A4B <map name>.16B <x>.W <y>.W
+static void clif_changemap_airship(struct map_session_data *sd, short m, int x, int y)
+{
+#if PACKETVER_MAIN_NUM >= 20180620 || PACKETVER_RE_NUM >= 20180321 || PACKETVER_ZERO_NUM >= 20171027
+ // [4144] this packet is not used yet by kro, but it here
+ int fd;
+ nullpo_retv(sd);
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, packet_len(0xa4b));
+ WFIFOW(fd, 0) = 0xa4b;
+ mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, WFIFOP(fd,2));
+ WFIFOW(fd, 18) = x;
+ WFIFOW(fd, 20) = y;
+ WFIFOSET(fd, packet_len(0xa4b));
+#endif
+}
+
/// Notifies the client of a position change to coordinates on given map, which is on another map-server (ZC_NPCACK_SERVERMOVE).
/// 0092 <map name>.16B <x>.W <y>.W <ip>.L <port>.W
-void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port) {
+/// 0ac7 <map name>.16B <x>.W <y>.W <ip>.L <port>.W <dns host>.128B
+static void clif_changemapserver(struct map_session_data *sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port, char *dnsHost)
+{
int fd;
+#if PACKETVER >= 20170315
+ const int cmd = 0xac7;
+#else
+ const int cmd = 0x92;
+#endif
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x92));
- WFIFOW(fd,0) = 0x92;
- mapindex->getmapname_ext(mapindex_id2name(map_index), WFIFOP(fd,2));
- WFIFOW(fd,18) = x;
- WFIFOW(fd,20) = y;
- WFIFOL(fd,22) = htonl(ip);
- WFIFOW(fd,26) = sockt->ntows(htons(port)); // [!] LE byte order here [!]
- WFIFOSET(fd,packet_len(0x92));
+ WFIFOHEAD(fd, packet_len(cmd));
+ WFIFOW(fd, 0) = cmd;
+ mapindex->getmapname_ext(mapindex_id2name(map_index), WFIFOP(fd, 2));
+ WFIFOW(fd, 18) = x;
+ WFIFOW(fd, 20) = y;
+ WFIFOL(fd, 22) = htonl(ip);
+ WFIFOW(fd, 26) = sockt->ntows(htons(port)); // [!] LE byte order here [!]
+
+#if PACKETVER >= 20170315
+ if (dnsHost != NULL) {
+ safestrncpy(WFIFOP(fd, 28), dnsHost, 128);
+ } else {
+ memset(WFIFOP(fd, 28), 0, 128);
+ }
+#endif
+
+ WFIFOSET(fd, packet_len(cmd));
+}
+
+/// Notifies the client of a position change (with air ship) to coordinates on given map, which is on another map-server (ZC_NPCACK_SERVERMOVE).
+/// 0a4c <map name>.16B <x>.W <y>.W <ip>.L <port>.W
+static void clif_changemapserver_airship(struct map_session_data *sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port)
+{
+#if (PACKETVER_MAIN_NUM >= 20180620) || (PACKETVER_RE_NUM >= 20180321) || (PACKETVER_ZERO_NUM >= 20171027)
+ // [4144] this packet is not used yet by kro, but it here
+ int fd;
+ const int cmd = 0xa4c;
+ nullpo_retv(sd);
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, packet_len(cmd));
+ WFIFOW(fd, 0) = cmd;
+ mapindex->getmapname_ext(mapindex_id2name(map_index), WFIFOP(fd, 2));
+ WFIFOW(fd, 18) = x;
+ WFIFOW(fd, 20) = y;
+ WFIFOL(fd, 22) = htonl(ip);
+ WFIFOW(fd, 26) = sockt->ntows(htons(port)); // [!] LE byte order here [!]
+ WFIFOSET(fd, packet_len(cmd));
+#endif
}
-void clif_blown(struct block_list *bl)
+static void clif_blown(struct block_list *bl)
{
//Aegis packets says fixpos, but it's unsure whether slide works better or not.
nullpo_retv(bl);
@@ -1838,7 +2081,8 @@ void clif_blown(struct block_list *bl)
/// isn't walkable, the char doesn't move at all. If the char is
/// sitting it will stand up (ZC_STOPMOVE).
/// 0088 <id>.L <x>.W <y>.W
-void clif_fixpos(struct block_list *bl) {
+static void clif_fixpos(struct block_list *bl)
+{
unsigned char buf[10];
nullpo_retv(bl);
@@ -1849,7 +2093,7 @@ void clif_fixpos(struct block_list *bl) {
WBUFW(buf,8) = bl->y;
clif->send(buf, packet_len(0x88), bl, AREA);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x88), bl, SELF);
}
@@ -1857,7 +2101,7 @@ void clif_fixpos(struct block_list *bl) {
/// Displays the buy/sell dialog of an NPC shop (ZC_SELECT_DEALTYPE).
/// 00c4 <shop id>.L
-void clif_npcbuysell(struct map_session_data* sd, int id)
+static void clif_npcbuysell(struct map_session_data *sd, int id)
{
int fd;
@@ -1872,15 +2116,17 @@ void clif_npcbuysell(struct map_session_data* sd, int id)
/// Presents list of items, that can be bought in an NPC shop (ZC_PC_PURCHASE_ITEMLIST).
/// 00c6 <packet len>.W { <price>.L <discount price>.L <item type>.B <name id>.W }*
-void clif_buylist(struct map_session_data *sd, struct npc_data *nd) {
+static void clif_buylist(struct map_session_data *sd, struct npc_data *nd)
+{
struct npc_item_list *shop = NULL;
unsigned short shop_size = 0;
- int fd,i,c;
+ int fd, i, c, len;
+ struct PACKET_ZC_PC_PURCHASE_ITEMLIST *p;
nullpo_retv(sd);
nullpo_retv(nd);
- if( nd->subtype == SCRIPT ) {
+ if (nd->subtype == SCRIPT) {
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
} else {
@@ -1890,46 +2136,52 @@ void clif_buylist(struct map_session_data *sd, struct npc_data *nd) {
fd = sd->fd;
- WFIFOHEAD(fd, 4 + shop_size * 11);
- WFIFOW(fd,0) = 0xc6;
+ len = sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST) + shop_size * sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0xc6;
c = 0;
- for( i = 0; i < shop_size; i++ ) {
- if( shop[i].nameid ) {
+ for (i = 0; i < shop_size; i++) {
+ if (shop[i].nameid) {
struct item_data* id = itemdb->exists(shop[i].nameid);
int val = shop[i].value;
- if( id == NULL )
+ if (id == NULL)
continue;
- WFIFOL(fd, 4+c*11) = val;
- WFIFOL(fd, 8+c*11) = pc->modifybuyvalue(sd,val);
- WFIFOB(fd,12+c*11) = itemtype(id->type);
- WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ p->items[c].price = val;
+ p->items[c].discountPrice = pc->modifybuyvalue(sd, val);
+ p->items[c].itemType = itemtype(id->type);
+ p->items[c].itemId = (id->view_id > 0) ? id->view_id : id->nameid;
c++;
}
}
- WFIFOW(fd,2) = 4 + c*11;
- WFIFOSET(fd,WFIFOW(fd,2));
+ len = sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST) + c * sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
}
/// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST).
/// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }*
-void clif_selllist(struct map_session_data *sd)
+static void clif_selllist(struct map_session_data *sd)
{
- int fd,i,c=0,val;
+ int c = 0, val;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4);
+ int fd = sd->fd;
+ WFIFOHEAD(fd, sd->status.inventorySize * 10 + 4);
WFIFOW(fd,0)=0xc7;
- for( i = 0; i < MAX_INVENTORY; i++ )
+ for (int i = 0; i < sd->status.inventorySize; i++)
{
if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] )
{
if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )
continue;
+ if (sd->status.inventory[i].favorite != 0)
+ continue; // Cannot Sell Favorite item
+
if( sd->status.inventory[i].expire_time )
continue; // Cannot Sell Rental Items
@@ -1957,21 +2209,40 @@ void clif_selllist(struct map_session_data *sd)
/// - set npcid of dialog window (0 by default)
/// - if set to clear on next mes, clear contents
/// - append this text
-void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) {
- int fd = sd->fd;
- size_t slen;
+static void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
+#ifdef SCRIPT_MES_STRIP_LINEBREAK
+ char *stripmes = NULL;
+ int i;
+#endif
nullpo_retv(sd);
nullpo_retv(mes);
- slen = strlen(mes) + 9;
+
+ fd = sd->fd;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
+
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
sd->state.dialog = 1;
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb4;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb4;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
+#ifdef SCRIPT_MES_STRIP_LINEBREAK
+ stripmes = aStrdup(mes);
+ for (i = 0; stripmes[i] != '\0'; ++i) {
+ if (stripmes[i] == '\r')
+ stripmes[i] = ' ';
+ }
+ memcpy(WFIFOP(fd,8), stripmes, slen-8);
+ aFree(stripmes);
+#else // ! SCRIPT_MES_STRIP_LINEBREAK
memcpy(WFIFOP(fd,8), mes, slen-8);
+#endif // SCRIPT_MES_STRIP_LINEBREAK
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -1985,12 +2256,14 @@ void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) {
/// - 00B9 <npcid of dialog window>.L
/// - set to clear on next mes
/// - remove 'next' button
-void clif_scriptnext(struct map_session_data *sd, int npcid)
+static void clif_scriptnext(struct map_session_data *sd, int npcid)
{
int fd;
nullpo_retv(sd);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
+
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0xb5));
WFIFOW(fd,0)=0xb5;
@@ -2013,12 +2286,14 @@ void clif_scriptnext(struct map_session_data *sd, int npcid)
/// - close the dialog window
/// - close the menu window
/// - 0146 <npcid of dialog window>.L
-void clif_scriptclose(struct map_session_data *sd, int npcid)
+static void clif_scriptclose(struct map_session_data *sd, int npcid)
{
int fd;
nullpo_retv(sd);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
+
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0xb6));
WFIFOW(fd,0)=0xb6;
@@ -2029,7 +2304,8 @@ void clif_scriptclose(struct map_session_data *sd, int npcid)
/*==========================================
*
*------------------------------------------*/
-void clif_sendfakenpc(struct map_session_data *sd, int npcid) {
+static void clif_sendfakenpc(struct map_session_data *sd, int npcid)
+{
unsigned char *buf;
int fd;
@@ -2072,24 +2348,29 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) {
/// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window.
/// Which suggests their have intertwined behavior. (probably the mouse targeting)
/// TODO investigate behavior of other windows [FlavioJS]
-void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) {
- int fd;
- size_t slen;
+static void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
struct block_list *bl = NULL;
nullpo_retv(sd);
nullpo_retv(mes);
+
fd = sd->fd;
- slen = strlen(mes) + 9;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
+
if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (bl->m!=sd->bl.m ||
bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
clif->sendfakenpc(sd, npcid);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
+
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb7;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb7;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
memcpy(WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -2105,7 +2386,8 @@ void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) {
/// - if npcid exists in the client:
/// - 0143 <npcid of inputnum window>.L <atoi(text)>.L
/// - close inputnum window
-void clif_scriptinput(struct map_session_data *sd, int npcid) {
+static void clif_scriptinput(struct map_session_data *sd, int npcid)
+{
int fd;
struct block_list *bl = NULL;
@@ -2116,6 +2398,8 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) {
bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
clif->sendfakenpc(sd, npcid);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
+
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0x142));
WFIFOW(fd,0)=0x142;
@@ -2134,7 +2418,8 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) {
/// - if npcid is 0 or npcid exists in the client:
/// - 01d5 <packetlen>.W <npcid of inputstr window>.L <text>.?B
/// - close inputstr window
-void clif_scriptinputstr(struct map_session_data *sd, int npcid) {
+static void clif_scriptinputstr(struct map_session_data *sd, int npcid)
+{
int fd;
struct block_list *bl = NULL;
@@ -2145,6 +2430,8 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) {
bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
clif->sendfakenpc(sd, npcid);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
+
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0x1d4));
WFIFOW(fd,0)=0x1d4;
@@ -2162,7 +2449,7 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) {
/// 2 = remove mark
/// color:
/// 0x00RRGGBB
-void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color)
+static void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color)
{
int fd;
@@ -2189,7 +2476,8 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in
/// 2 = bottom right corner
/// 3 = middle of screen, inside a movable window
/// 4 = middle of screen, movable with a close button, chrome-less
-void clif_cutin(struct map_session_data* sd, const char* image, int type)
+/// 255 = hide
+static void clif_cutin(struct map_session_data *sd, const char *image, int type)
{
int fd;
@@ -2206,124 +2494,89 @@ void clif_cutin(struct map_session_data* sd, const char* image, int type)
/*==========================================
* Fills in card data from the given item and into the buffer. [Skotlex]
*------------------------------------------*/
-void clif_addcards(unsigned char* buf, struct item* item) {
- int i=0,j;
+static void clif_addcards(struct EQUIPSLOTINFO *buf, struct item *item)
+{
+ int i = 0, j;
nullpo_retv(buf);
- if( item == NULL ) { //Blank data
- WBUFW(buf,0) = 0;
- WBUFW(buf,2) = 0;
- WBUFW(buf,4) = 0;
- WBUFW(buf,6) = 0;
- return;
- }
- if( item->card[0] == CARD0_PET ) { //pet eggs
- WBUFW(buf,0) = 0;
- WBUFW(buf,2) = 0;
- WBUFW(buf,4) = 0;
- WBUFW(buf,6) = item->card[3]; //Pet renamed flag.
- return;
- }
- if( item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE ) { //Forged/created items
- WBUFW(buf,0) = item->card[0];
- WBUFW(buf,2) = item->card[1];
- WBUFW(buf,4) = item->card[2];
- WBUFW(buf,6) = item->card[3];
- return;
- }
- //Client only receives four cards.. so randomly send them a set of cards. [Skotlex]
- if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 )
- i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3;
-
- //Normal items.
- if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- WBUFW(buf,0) = j;
- else
- WBUFW(buf,0) = item->card[i];
-
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- WBUFW(buf,2) = j;
- else
- WBUFW(buf,2) = item->card[i];
-
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- WBUFW(buf,4) = j;
- else
- WBUFW(buf,4) = item->card[i];
-
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- WBUFW(buf,6) = j;
- else
- WBUFW(buf,6) = item->card[i];
-}
-
-void clif_addcards2(unsigned short *cards, struct item* item) {
- int i=0,j;
- nullpo_retv(cards);
- if( item == NULL ) { //Blank data
- cards[0] = 0;
- cards[1] = 0;
- cards[2] = 0;
- cards[3] = 0;
+ if (item == NULL) { //Blank data
+ buf->card[0] = 0;
+ buf->card[1] = 0;
+ buf->card[2] = 0;
+ buf->card[3] = 0;
return;
}
- if( item->card[0] == CARD0_PET ) { //pet eggs
- cards[0] = 0;
- cards[1] = 0;
- cards[2] = 0;
- cards[3] = item->card[3]; //Pet renamed flag.
+ if (item->card[0] == CARD0_PET) { //pet eggs
+ buf->card[0] = 0;
+ buf->card[1] = 0;
+ buf->card[2] = 0;
+ buf->card[3] = item->card[3]; //Pet renamed flag.
return;
}
- if( item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE ) { //Forged/created items
- cards[0] = item->card[0];
- cards[1] = item->card[1];
- cards[2] = item->card[2];
- cards[3] = item->card[3];
+ if (item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE) { //Forged/created items
+ buf->card[0] = item->card[0];
+ buf->card[1] = item->card[1];
+ buf->card[2] = item->card[2];
+ buf->card[3] = item->card[3];
return;
}
//Client only receives four cards.. so randomly send them a set of cards. [Skotlex]
- if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 )
- i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3;
+ if (MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4)
+ i = rnd() % (j - 3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3;
//Normal items.
- if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- cards[0] = j;
+ if (item->card[i] > 0 && (j = itemdb_viewid(item->card[i])) > 0)
+ buf->card[0] = j;
else
- cards[0] = item->card[i];
+ buf->card[0] = item->card[i];
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- cards[1] = j;
+ if (item->card[++i] > 0 && (j = itemdb_viewid(item->card[i])) > 0)
+ buf->card[1] = j;
else
- cards[1] = item->card[i];
+ buf->card[1] = item->card[i];
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- cards[2] = j;
+ if (item->card[++i] > 0 && (j = itemdb_viewid(item->card[i])) > 0)
+ buf->card[2] = j;
else
- cards[2] = item->card[i];
+ buf->card[2] = item->card[i];
- if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
- cards[3] = j;
+ if (item->card[++i] > 0 && (j = itemdb_viewid(item->card[i])) > 0)
+ buf->card[3] = j;
else
- cards[3] = item->card[i];
+ buf->card[3] = item->card[i];
}
/**
- * Fills in RandomOptions(Bonuses) of items into the buffer
+ * Fills in ItemOptions(Bonuses) of items into the buffer
*
- * Dummy datais used since this feature isn't supported yet (ITEM_RDM_OPT).
- * A maximum of 5 random options can be supported.
+ * A maximum of 5 item options can be supported.
*
* @param buf[in,out] The buffer to write to. The pointer must be valid and initialized.
* @param item[in] The source item.
*/
-void clif_add_random_options(unsigned char* buf, struct item* item)
+static int clif_add_item_options(struct ItemOptions *buf, const struct item *it)
{
- int i;
- nullpo_retv(buf);
- for (i = 0; i < 5; i++){
- WBUFW(buf,i*5+0) = 0; // OptIndex
- WBUFW(buf,i*5+2) = 0; // Value
- WBUFB(buf,i*5+4) = 0; // Param1
+ int i = 0, j = 0, total_options = 0;
+
+ nullpo_ret(buf);
+
+ // Append the buffer with existing options first.
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ if (it->option[i].index) {
+ WBUFW(buf, j * 5 + 0) = it->option[i].index; // OptIndex
+ WBUFW(buf, j * 5 + 2) = it->option[i].value; // Value
+ WBUFB(buf, j * 5 + 4) = it->option[i].param; // Param1
+ total_options++;
+ j++;
+ }
+ }
+ // Append the remaining buffer with no values;
+ for (; j < MAX_ITEM_OPTIONS || j < 5; j++) {
+ WBUFW(buf, j * 5 + 0) = 0;
+ WBUFW(buf, j * 5 + 2) = 0;
+ WBUFB(buf, j * 5 + 4) = 0;
}
+
+ return total_options;
}
/// Notifies the client, about a received inventory item or the result of a pick-up request.
@@ -2332,7 +2585,9 @@ void clif_add_random_options(unsigned char* buf, struct item* item)
/// 02d4 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK3)
/// 0990 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V5)
/// 0a0c <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V6)
-void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
+/// 0a37 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W <favorite>.B <view id>.W (ZC_ITEM_PICKUP_ACK_V7)
+static void clif_additem(struct map_session_data *sd, int n, int amount, int fail)
+{
struct packet_additem p;
nullpo_retv(sd);
@@ -2347,10 +2602,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.count = amount;
if( !fail ) {
-#if PACKETVER >= 20150226
- int i;
-#endif
- if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL )
+ if (n < 0 || n >= sd->status.inventorySize || sd->status.inventory[n].nameid <= 0 || sd->inventory_data[n] == NULL)
return;
if (sd->inventory_data[n]->view_id > 0)
@@ -2359,9 +2611,9 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.nameid = sd->status.inventory[n].nameid;
p.IsIdentified = sd->status.inventory[n].identify ? 1 : 0;
- p.IsDamaged = sd->status.inventory[n].attribute ? 1 : 0;
+ p.IsDamaged = (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ? 1 : 0;
p.refiningLevel =sd->status.inventory[n].refine;
- clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]);
+ clif->addcards(&p.slot, &sd->status.inventory[n]);
p.location = pc->equippoint(sd,n);
p.type = itemtype(sd->inventory_data[n]->type);
#if PACKETVER >= 20061218
@@ -2374,11 +2626,11 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.bindOnEquipType = sd->status.inventory[n].bound && !itemdb->isstackable2(sd->inventory_data[n]) ? 2 : sd->inventory_data[n]->flag.bindonequip ? 1 : 0;
#endif
#if PACKETVER >= 20150226
- for (i=0; i<5; i++){
- p.option_data[i].index = 0;
- p.option_data[i].value = 0;
- p.option_data[i].param = 0;
- }
+ clif->add_item_options(&p.option_data[0], &sd->status.inventory[n]);
+#endif
+#if PACKETVER >= 20160921
+ p.favorite = sd->status.inventory[n].favorite;
+ p.look = sd->inventory_data[n]->view_sprite;
#endif
}
p.result = (unsigned char)fail;
@@ -2388,7 +2640,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
/// Notifies the client, that an inventory item was deleted or dropped (ZC_ITEM_THROW_ACK).
/// 00af <index>.W <amount>.W
-void clif_dropitem(struct map_session_data *sd,int n,int amount)
+static void clif_dropitem(struct map_session_data *sd, int n, int amount)
{
int fd;
@@ -2402,10 +2654,26 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount)
WFIFOSET(fd,packet_len(0xaf));
}
+static void clif_item_movefailed(struct map_session_data *sd, int n)
+{
+#if PACKETVER_MAIN_NUM >= 20161214 || PACKETVER_RE_NUM >= 20161130 || defined(PACKETVER_ZERO)
+ int fd = sd->fd;
+ const int len = sizeof(struct PACKET_ZC_INVENTORY_MOVE_FAILED);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_INVENTORY_MOVE_FAILED *p = WFIFOP(fd, 0);
+ p->packetType = 0xaa7;
+ p->index = n + 2;
+ p->unknown = 1;
+ WFIFOSET(fd, len);
+#else
+ clif->dropitem(sd, n, 0);
+#endif
+}
+
/// Notifies the client, that an inventory item was deleted (ZC_DELETE_ITEM_FROM_BODY).
/// 07fa <delete type>.W <index>.W <amount>.W
/// delete type: @see enum delitem_reason
-void clif_delitem(struct map_session_data *sd,int n,int amount, short reason)
+static void clif_delitem(struct map_session_data *sd, int n, int amount, short reason)
{
#if PACKETVER < 20091117
clif->dropitem(sd,n,amount);
@@ -2429,7 +2697,8 @@ void clif_delitem(struct map_session_data *sd,int n,int amount, short reason)
// Equip is >= 0 for equippable items (holds the equip-point, is 0 for pet
// armor/egg) -1 for stackable items, -2 for stackable items where arrows must send in the equip-point.
// look like unused, not adding checks
-void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *id, int equip) {
+static void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *id, int equip)
+{
if (id->view_id > 0)
WBUFW(buf,n)=id->view_id;
else
@@ -2451,65 +2720,59 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *
}
-void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) {
-#if PACKETVER >= 20150226
- int j;
-#endif
+static void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *it, struct item_data *id, int eqp_pos)
+{
nullpo_retv(p);
- nullpo_retv(i);
+ nullpo_retv(it);
nullpo_retv(id);
p->index = idx;
if (id->view_id > 0)
p->ITID = id->view_id;
else
- p->ITID = i->nameid;
+ p->ITID = it->nameid;
p->type = itemtype(id->type);
#if PACKETVER < 20120925
- p->IsIdentified = i->identify ? 1 : 0;
+ p->IsIdentified = it->identify ? 1 : 0;
#endif
p->location = eqp_pos;
- p->WearState = i->equip;
+ p->WearState = it->equip;
#if PACKETVER < 20120925
- p->IsDamaged = i->attribute ? 1 : 0;
+ p->IsDamaged = (it->attribute & ATTR_BROKEN) != 0 ? 1 : 0;
#endif
- p->RefiningLevel = i->refine;
+ p->RefiningLevel = it->refine;
- clif->addcards2(&p->slot.card[0], i);
+ clif->addcards(&p->slot, it);
#if PACKETVER >= 20071002
- p->HireExpireDate = i->expire_time;
+ p->HireExpireDate = it->expire_time;
#endif
#if PACKETVER >= 20080102
- p->bindOnEquipType = i->bound ? 2 : id->flag.bindonequip ? 1 : 0;
+ p->bindOnEquipType = it->bound ? 2 : id->flag.bindonequip ? 1 : 0;
#endif
#if PACKETVER >= 20100629
- p->wItemSpriteNumber = (id->equip&EQP_VISIBLE) ? id->look : 0;
+ p->wItemSpriteNumber = (id->equip&EQP_VISIBLE) ? id->view_sprite : 0;
#endif
#if PACKETVER >= 20120925
- p->Flag.IsIdentified = i->identify ? 1 : 0;
- p->Flag.IsDamaged = i->attribute ? 1 : 0;
- p->Flag.PlaceETCTab = i->favorite ? 1 : 0;
+ p->Flag.IsIdentified = it->identify ? 1 : 0;
+ p->Flag.IsDamaged = (it->attribute & ATTR_BROKEN) != 0 ? 1 : 0;
+ p->Flag.PlaceETCTab = it->favorite ? 1 : 0;
p->Flag.SpareBits = 0;
#endif
#if PACKETVER >= 20150226
- p->option_count = 0;
- for (j=0; j<5; j++){
- p->option_data[j].index = 0;
- p->option_data[j].value = 0;
- p->option_data[j].param = 0;
- }
+ p->option_count = clif->add_item_options(p->option_data, it);
#endif
}
-void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id) {
+static void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id)
+{
nullpo_retv(p);
nullpo_retv(i);
nullpo_retv(id);
@@ -2531,7 +2794,7 @@ void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, stru
p->WearState = id->equip;
#if PACKETVER >= 5
- clif->addcards2(&p->slot.card[0], i);
+ clif->addcards(&p->slot, i);
#endif
#if PACKETVER >= 20080102
@@ -2545,11 +2808,23 @@ void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, stru
#endif
}
-void clif_inventorylist(struct map_session_data *sd) {
+static void clif_inventoryList(struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ clif->inventoryStart(sd, INVTYPE_INVENTORY, "");
+#endif
+ clif->inventoryItems(sd, INVTYPE_INVENTORY);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ clif->inventoryEnd(sd, INVTYPE_INVENTORY);
+#endif
+}
+
+static void clif_inventoryItems(struct map_session_data *sd, enum inventory_type type)
+{
int i, normal = 0, equip = 0;
nullpo_retv(sd);
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
@@ -2559,9 +2834,12 @@ void clif_inventorylist(struct map_session_data *sd) {
clif->item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.inventory[i],sd->inventory_data[i]);
}
- if( normal ) {
- itemlist_normal.PacketType = inventorylistnormalType;
- itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal);
+ if (normal) {
+ itemlist_normal.PacketType = inventorylistnormalType;
+ itemlist_normal.PacketLength = (sizeof(itemlist_normal) - sizeof(itemlist_normal.list)) + (sizeof(struct NORMALITEM_INFO) * normal);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ itemlist_normal.invType = type;
+#endif
clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF);
}
@@ -2571,13 +2849,16 @@ void clif_inventorylist(struct map_session_data *sd) {
if( equip ) {
itemlist_equip.PacketType = inventorylistequipType;
- itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
+ itemlist_equip.PacketLength = (sizeof(itemlist_equip) - sizeof(itemlist_equip.list)) + (sizeof(struct EQUIPITEM_INFO) * equip);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ itemlist_equip.invType = type;
+#endif
clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
}
/* on 20120925 onwards this is a field on clif_item_equip/normal */
#if PACKETVER >= 20111122 && PACKETVER < 20120925
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
@@ -2587,12 +2868,25 @@ void clif_inventorylist(struct map_session_data *sd) {
#endif
}
+static void clif_equipList(struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ clif->inventoryStart(sd, INVTYPE_INVENTORY, "");
+ clif->inventoryItems(sd, INVTYPE_INVENTORY);
+ clif->inventoryEnd(sd, INVTYPE_INVENTORY);
+#else
+ // [4144] for old packet version it send only equipment. this is bug?
+ clif->equipItems(sd, INVTYPE_INVENTORY);
+#endif
+}
+
//Required when items break/get-repaired. Only sends equippable item list.
-void clif_equiplist(struct map_session_data *sd) {
+static void clif_equipItems(struct map_session_data *sd, enum inventory_type type)
+{
int i, equip = 0;
nullpo_retv(sd);
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
@@ -2600,16 +2894,19 @@ void clif_equiplist(struct map_session_data *sd) {
clif->item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i));
}
- if( equip ) {
- itemlist_equip.PacketType = inventorylistequipType;
- itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
+ if (equip) {
+ itemlist_equip.PacketType = inventorylistequipType;
+ itemlist_equip.PacketLength = (sizeof(itemlist_equip) - sizeof(itemlist_equip.list)) + (sizeof(struct EQUIPITEM_INFO) * equip);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ itemlist_equip.invType = type;
+#endif
clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
}
/* on 20120925 onwards this is a field on clif_item_equip */
#if PACKETVER >= 20111122 && PACKETVER < 20120925
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
@@ -2619,55 +2916,158 @@ void clif_equiplist(struct map_session_data *sd) {
#endif
}
-void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) {
- int i = 0;
- struct item_data *id;
+static void clif_storageList(struct map_session_data *sd, struct item *items, int items_length)
+{
+ nullpo_retv(sd);
+
+ clif->inventoryStart(sd, INVTYPE_STORAGE, "Storage");
+ if (sd->storage.aggregate > 0)
+ clif->storageItems(sd, INVTYPE_STORAGE, items, items_length);
+ clif->inventoryEnd(sd, INVTYPE_STORAGE);
+}
+static void clif_guildStorageList(struct map_session_data *sd, struct item *items, int items_length)
+{
+ clif->inventoryStart(sd, INVTYPE_GUILD_STORAGE, "Guild storage");
+ clif->storageItems(sd, INVTYPE_GUILD_STORAGE, items, items_length);
+ clif->inventoryEnd(sd, INVTYPE_GUILD_STORAGE);
+}
+
+static void clif_inventoryStart(struct map_session_data *sd, enum inventory_type type, const char *name)
+{
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
nullpo_retv(sd);
- nullpo_retv(items);
- do {
- int normal = 0, equip = 0, k = 0;
+ nullpo_retv(name);
- for( ; i < items_length && k < 500; i++, k++ ) {
+ char buf[sizeof(struct PACKET_ZC_INVENTORY_START) + 24];
+ memset(buf, 0, sizeof(buf));
+ struct PACKET_ZC_INVENTORY_START *p = (struct PACKET_ZC_INVENTORY_START *)buf;
+ p->packetType = HEADER_ZC_INVENTORY_START;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ p->invType = type;
+#endif
+#if PACKETVER_RE_NUM >= 20180919 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ int strLen = (int)safestrnlen(name, 24) + 1;
+ if (strLen > 24)
+ strLen = 24;
+ const int len = sizeof(struct PACKET_ZC_INVENTORY_START) + strLen;
+ p->packetLength = len;
+ safestrncpy(p->name, name, strLen);
+#else
+ const int len = sizeof(struct PACKET_ZC_INVENTORY_START);
+ safestrncpy(p->name, name, NAME_LENGTH);
+#endif
+ clif->send(p, len, &sd->bl, SELF);
+#endif
+}
- if( items[i].nameid <= 0 )
- continue;
+static void clif_inventoryEnd(struct map_session_data *sd, enum inventory_type type)
+{
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ nullpo_retv(sd);
- id = itemdb->search(items[i].nameid);
+ struct PACKET_ZC_INVENTORY_END p;
+ p.packetType = HEADER_ZC_INVENTORY_END;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ p.invType = type;
+#endif
+ p.flag = 0;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
- if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable)
- clif->item_equip(i+1,&storelist_equip.list[equip++],&items[i],id,id->equip);
- else //Stackable (Normal)
- clif->item_normal(i+1,&storelist_normal.list[normal++],&items[i],id);
- }
+static void clif_storageItems(struct map_session_data *sd, enum inventory_type type, struct item *items, int items_length)
+{
+ nullpo_retv(sd);
+ nullpo_retv(items);
+
+ int normal_count = 0, equip_count = 0;
+ for (int i = 0; i < items_length; ++i) {
+ if (items[i].nameid == 0)
+ continue;
- if( normal ) {
- storelist_normal.PacketType = storagelistnormalType;
- storelist_normal.PacketLength = ( sizeof( storelist_normal ) - sizeof( storelist_normal.list ) ) + (sizeof(struct NORMALITEM_INFO) * normal);
+ struct item_data *itd = itemdb->search(items[i].nameid);
-#if PACKETVER >= 20120925
+ if (!itemdb->isstackable2(itd))
+ clif->item_equip(i + 1, &storelist_equip.list[equip_count++], &items[i], itd, itd->equip);
+ else
+ clif->item_normal(i + 1, &storelist_normal.list[normal_count++], &items[i], itd);
+
+ if (normal_count > 0 && (normal_count == MAX_STORAGE_ITEM_PACKET_NORMAL || i + 1 == items_length)) {
+ storelist_normal.PacketType = storageListNormalType;
+ storelist_normal.PacketLength = (sizeof(storelist_normal) - sizeof(storelist_normal.list)) + (sizeof(struct NORMALITEM_INFO) * normal_count);
+
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storelist_normal.invType = type;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
safestrncpy(storelist_normal.name, "Storage", NAME_LENGTH);
#endif
clif->send(&storelist_normal, storelist_normal.PacketLength, &sd->bl, SELF);
+ normal_count = 0;
}
- if( equip ) {
- storelist_equip.PacketType = storagelistequipType;
- storelist_equip.PacketLength = ( sizeof( storelist_equip ) - sizeof( storelist_equip.list ) ) + (sizeof(struct EQUIPITEM_INFO) * equip);
+ if (equip_count > 0 && (equip_count == MAX_STORAGE_ITEM_PACKET_EQUIP || i + 1 == items_length)) {
+ storelist_equip.PacketType = storageListEquipType;
+ storelist_equip.PacketLength = (sizeof(storelist_equip) - sizeof(storelist_equip.list)) + (sizeof(struct EQUIPITEM_INFO) * equip_count);
-#if PACKETVER >= 20120925
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storelist_equip.invType = type;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
safestrncpy(storelist_equip.name, "Storage", NAME_LENGTH);
#endif
clif->send(&storelist_equip, storelist_equip.PacketLength, &sd->bl, SELF);
+ equip_count = 0;
}
+ }
- } while ( i < items_length );
+ if (normal_count > 0) {
+ storelist_normal.PacketType = storageListNormalType;
+ storelist_normal.PacketLength = (sizeof(storelist_normal) - sizeof(storelist_normal.list)) + (sizeof(struct NORMALITEM_INFO) * normal_count);
+
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storelist_normal.invType = type;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
+ safestrncpy(storelist_normal.name, "Storage", NAME_LENGTH);
+#endif
+
+ clif->send(&storelist_normal, storelist_normal.PacketLength, &sd->bl, SELF);
+ normal_count = 0;
+ }
+
+ if (equip_count > 0) {
+ storelist_equip.PacketType = storageListEquipType;
+ storelist_equip.PacketLength = (sizeof(storelist_equip) - sizeof(storelist_equip.list)) + (sizeof(struct EQUIPITEM_INFO) * equip_count);
+
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storelist_equip.invType = type;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
+ safestrncpy(storelist_equip.name, "Storage", NAME_LENGTH);
+#endif
+
+ clif->send(&storelist_equip, storelist_equip.PacketLength, &sd->bl, SELF);
+ equip_count = 0;
+ }
+}
+static void clif_cartList(struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ clif->inventoryStart(sd, INVTYPE_CART, "");
+#endif
+ clif->cartItems(sd, INVTYPE_CART);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ clif->inventoryEnd(sd, INVTYPE_CART);
+#endif
}
-void clif_cartlist(struct map_session_data *sd) {
+static void clif_cartItems(struct map_session_data *sd, enum inventory_type type)
+{
int i, normal = 0, equip = 0;
struct item_data *id;
@@ -2684,27 +3084,148 @@ void clif_cartlist(struct map_session_data *sd) {
clif->item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.cart[i],id);
}
- if( normal ) {
- itemlist_normal.PacketType = cartlistnormalType;
- itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal);
+ if (normal) {
+ itemlist_normal.PacketType = cartlistnormalType;
+ itemlist_normal.PacketLength = (sizeof(itemlist_normal) - sizeof(itemlist_normal.list)) + (sizeof(struct NORMALITEM_INFO) * normal);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ itemlist_normal.invType = type;
+#endif
clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF);
}
- if( equip ) {
- itemlist_equip.PacketType = cartlistequipType;
- itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
+ if (equip) {
+ itemlist_equip.PacketType = cartlistequipType;
+ itemlist_equip.PacketLength = (sizeof(itemlist_equip) - sizeof(itemlist_equip.list)) + (sizeof(struct EQUIPITEM_INFO) * equip);
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ itemlist_equip.invType = type;
+#endif
clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
}
}
+static void clif_inventoryExpansionInfo(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+ nullpo_retv(sd);
+
+ const int fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_INVENTORY_EXPANSION_INFO));
+ struct PACKET_ZC_INVENTORY_EXPANSION_INFO *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_INVENTORY_EXPANSION_INFO;
+ p->expansionSize = sd->status.inventorySize - FIXED_INVENTORY_SIZE;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_INVENTORY_EXPANSION_INFO));
+#endif
+}
+
+static void clif_inventoryExpandAck(struct map_session_data *sd, enum expand_inventory result, int itemId)
+{
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+ nullpo_retv(sd);
+
+ const int fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_ACK_INVENTORY_EXPAND));
+ struct PACKET_ZC_ACK_INVENTORY_EXPAND *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_ACK_INVENTORY_EXPAND;
+ p->result = result;
+ p->itemId = itemId;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_ACK_INVENTORY_EXPAND));
+#endif
+}
+
+static void clif_inventoryExpandResult(struct map_session_data *sd, enum expand_inventory_result result)
+{
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+ nullpo_retv(sd);
+
+ const int fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_ACK_INVENTORY_EXPAND_RESULT));
+ struct PACKET_ZC_ACK_INVENTORY_EXPAND_RESULT *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_ACK_INVENTORY_EXPAND_RESULT;
+ p->result = result;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_ACK_INVENTORY_EXPAND_RESULT));
+#endif
+}
+
+static void clif_parse_inventoryExpansion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_inventoryExpansion(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+ if (pc_isdead(sd) || pc_cant_act(sd)) {
+ clif->inventoryExpandAck(sd, EXPAND_INVENTORY_OTHER_WORK, 0);
+ return;
+ }
+ if (sd->status.inventorySize == MAX_INVENTORY) {
+ clif->inventoryExpandAck(sd, EXPAND_INVENTORY_MAX_SIZE, 0);
+ return;
+ }
+
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+
+ safestrncpy(evname, "inventory_expansion::OnInvExpandRequest", EVENT_NAME_LENGTH);
+ if ((ev = strdb_get(npc->ev_db, evname))) {
+ script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ } else {
+ ShowError("clif_parse_inventoryExpansion: event '%s' not found, operation failed.\n", evname);
+ }
+#endif
+}
+
+static void clif_parse_inventoryExpansionConfirmed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_inventoryExpansionConfirmed(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+ if (pc_isdead(sd) || pc_cant_act(sd)) {
+ clif->inventoryExpandResult(sd, EXPAND_INVENTORY_RESULT_OTHER_WORK);
+ return;
+ }
+ if (sd->status.inventorySize == MAX_INVENTORY) {
+ clif->inventoryExpandResult(sd, EXPAND_INVENTORY_RESULT_MAX_SIZE);
+ return;
+ }
+
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+
+ safestrncpy(evname, "inventory_expansion::OnInvExpandConfirmed", EVENT_NAME_LENGTH);
+ if ((ev = strdb_get(npc->ev_db, evname))) {
+ script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ } else {
+ ShowError("clif_parse_inventoryExpansionConfirmed: event '%s' not found, operation failed.\n", evname);
+ }
+#endif
+}
+
+static void clif_parse_inventoryExpansionRejected(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_inventoryExpansionRejected(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+
+ safestrncpy(evname, "inventory_expansion::OnInvExpandRejected", EVENT_NAME_LENGTH);
+ if ((ev = strdb_get(npc->ev_db, evname))) {
+ script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ } else {
+ ShowError("clif_parse_inventoryExpansionRejected: event '%s' not found, operation failed.\n", evname);
+ }
+#endif
+}
+
+// CZ_REQ_REMAINTIME
+static void clif_parse_reqRemainTime(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_reqRemainTime(int fd, struct map_session_data *sd)
+{
+}
+
/// Removes cart (ZC_CARTOFF).
/// 012b
/// 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)
+static void clif_clearcart(int fd)
{
WFIFOHEAD(fd, packet_len(0x12b));
WFIFOW(fd,0) = 0x12b;
@@ -2714,7 +3235,7 @@ void clif_clearcart(int fd)
/// Guild XY locators (ZC_NOTIFY_POSITION_TO_GUILDM) [Valaris]
/// 01eb <account id>.L <x>.W <y>.W
-void clif_guild_xy(struct map_session_data *sd)
+static void clif_guild_xy(struct map_session_data *sd)
{
unsigned char buf[10];
@@ -2730,7 +3251,7 @@ void clif_guild_xy(struct map_session_data *sd)
/*==========================================
* Sends x/y dot to a single fd. [Skotlex]
*------------------------------------------*/
-void clif_guild_xy_single(int fd, struct map_session_data *sd)
+static void clif_guild_xy_single(int fd, struct map_session_data *sd)
{
if( sd->bg_id )
return;
@@ -2745,7 +3266,7 @@ void clif_guild_xy_single(int fd, struct map_session_data *sd)
}
// Guild XY locators [Valaris]
-void clif_guild_xy_remove(struct map_session_data *sd)
+static void clif_guild_xy_remove(struct map_session_data *sd)
{
unsigned char buf[10];
@@ -2761,7 +3282,7 @@ void clif_guild_xy_remove(struct map_session_data *sd)
/*==========================================
*
*------------------------------------------*/
-int clif_hpmeter_sub(struct block_list *bl, va_list ap)
+static int clif_hpmeter_sub(struct block_list *bl, va_list ap)
{
#if PACKETVER < 20100126
const int cmd = 0x106;
@@ -2803,7 +3324,8 @@ int clif_hpmeter_sub(struct block_list *bl, va_list ap)
* Server tells all players that are allowed to view HP bars
* and are nearby 'sd' that 'sd' hp bar was updated.
*------------------------------------------*/
-int clif_hpmeter(struct map_session_data *sd) {
+static int clif_hpmeter(struct map_session_data *sd)
+{
nullpo_ret(sd);
map->foreachinarea(clif->hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd);
return 0;
@@ -2817,7 +3339,7 @@ int clif_hpmeter(struct map_session_data *sd) {
/// 013a <atk range>.W (ZC_ATTACK_RANGE)
/// 0141 <status id>.L <base status>.L <plus status>.L (ZC_COUPLESTATUS)
/// TODO: Extract individual packets.
-void clif_updatestatus(struct map_session_data *sd,int type)
+static void clif_updatestatus(struct map_session_data *sd, int type)
{
int fd,len;
@@ -2881,14 +3403,12 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOL(fd,4)=sd->battle_status.max_sp;
break;
case SP_HP:
- WFIFOL(fd,4)=sd->battle_status.hp;
- // TODO: Won't these overwrite the current packet?
- if( map->list[sd->bl.m].hpmeter_visible )
- clif->hpmeter(sd);
- if( !battle_config.party_hp_mode && sd->status.party_id )
- clif->party_hp(sd);
- if( sd->bg_id )
- clif->bg_hp(sd);
+ if (sd->battle_status.hp == 0 && battle_config.display_fake_hp_when_dead) {
+ // On official servers, the HP displayed when dead is the HP that the character will have at respawn.
+ WFIFOL(fd, 4) = status->get_restart_hp(sd, &sd->battle_status);
+ } else {
+ WFIFOL(fd, 4) = sd->battle_status.hp;
+ }
break;
case SP_SP:
WFIFOL(fd,4)=sd->battle_status.sp;
@@ -2933,31 +3453,55 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOL(fd,4)=pc_leftside_matk(sd);
break;
case SP_ZENY:
+// [4144] possible send 64 bit value from PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+// but kro sending 0xb1 packet only.
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=sd->status.zeny;
len = packet_len(0xb1);
break;
+#if PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
case SP_BASEEXP:
- WFIFOW(fd,0)=0xb1;
- WFIFOL(fd,4)=sd->status.base_exp;
+ WFIFOW(fd, 0) = 0xacb;
+ WFIFOQ(fd, 4) = sd->status.base_exp;
+ len = packet_len(0xacb);
+ break;
+ case SP_JOBEXP:
+ WFIFOW(fd, 0) = 0xacb;
+ WFIFOQ(fd, 4) = sd->status.job_exp;
+ len = packet_len(0xacb);
+ break;
+ case SP_NEXTBASEEXP:
+ WFIFOW(fd, 0) = 0xacb;
+ WFIFOQ(fd, 4) = pc->nextbaseexp(sd);
+ len = packet_len(0xacb);
+ break;
+ case SP_NEXTJOBEXP:
+ WFIFOW(fd, 0) = 0xacb;
+ WFIFOQ(fd, 4) = pc->nextjobexp(sd);
+ len = packet_len(0xacb);
+ break;
+#else
+ case SP_BASEEXP:
+ WFIFOW(fd, 0) = 0xb1;
+ WFIFOL(fd, 4) = (uint32)(sd->status.base_exp);
len = packet_len(0xb1);
break;
case SP_JOBEXP:
- WFIFOW(fd,0)=0xb1;
- WFIFOL(fd,4)=sd->status.job_exp;
+ WFIFOW(fd, 0) = 0xb1;
+ WFIFOL(fd, 4) = (uint32)(sd->status.job_exp);
len = packet_len(0xb1);
break;
case SP_NEXTBASEEXP:
- WFIFOW(fd,0)=0xb1;
- WFIFOL(fd,4)=pc->nextbaseexp(sd);
+ WFIFOW(fd, 0) = 0xb1;
+ WFIFOL(fd, 4) = (uint32)pc->nextbaseexp(sd);
len = packet_len(0xb1);
break;
case SP_NEXTJOBEXP:
- WFIFOW(fd,0)=0xb1;
- WFIFOL(fd,4)=pc->nextjobexp(sd);
+ WFIFOW(fd, 0) = 0xb1;
+ WFIFOL(fd, 4) = (uint32)pc->nextjobexp(sd);
len = packet_len(0xb1);
break;
-
+#endif
/**
* SP_U<STAT> are used to update the amount of points necessary to increase that stat
**/
@@ -3038,11 +3582,26 @@ void clif_updatestatus(struct map_session_data *sd,int type)
return;
}
WFIFOSET(fd,len);
+
+ // Additional update packets that should be sent right after
+ switch (type) {
+ case SP_BASELEVEL:
+ pc->update_job_and_level(sd);
+ break;
+ case SP_HP:
+ if (map->list[sd->bl.m].hpmeter_visible)
+ clif->hpmeter(sd);
+ if (!battle_config.party_hp_mode && sd->status.party_id)
+ clif->party_hp(sd);
+ if (sd->bg_id)
+ clif->bg_hp(sd);
+ break;
+ }
}
/// Notifies client of a parameter change of an another player (ZC_PAR_CHANGE_USER).
/// 01ab <account id>.L <var id>.W <value>.L
-void clif_changestatus(struct map_session_data* sd,int type,int val)
+static void clif_changestatus(struct map_session_data *sd, int type, int val)
{
unsigned char buf[12];
@@ -3066,13 +3625,15 @@ void clif_changestatus(struct map_session_data* sd,int type,int val)
}
/// Updates sprite/style properties of an object.
-void clif_changelook(struct block_list *bl,int type,int val)
+static void clif_changelook(struct block_list *bl, int type, int val)
{
struct map_session_data* sd;
struct status_change* sc;
struct view_data* vd;
enum send_target target = AREA;
+#if PACKETVER >= 4
int val2 = 0;
+#endif
nullpo_retv(bl);
sd = BL_CAST(BL_PC, bl);
@@ -3098,31 +3659,31 @@ void clif_changelook(struct block_list *bl,int type,int val)
vd->shield = val;
break;
case LOOK_BASE:
- if( !sd ) break;
+ if (sd == NULL)
+ break;
- if ( val == INVISIBLE_CLASS ) /* nothing to change look */
+ if (val == INVISIBLE_CLASS) /* nothing to change look */
return;
- if( sd->sc.option&OPTION_COSTUME )
+ if (sd->sc.option & OPTION_COSTUME)
vd->weapon = vd->shield = 0;
- if( !vd->cloth_color )
+ if (!vd->cloth_color)
break;
- if (sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette)
+ if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true)
+ vd->cloth_color = 0;
+ if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true)
vd->cloth_color = 0;
- if (sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette)
+ if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true)
vd->cloth_color = 0;
- if (sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette)
+ if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true)
vd->cloth_color = 0;
- if (sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette)
+ if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true)
vd->cloth_color = 0;
- if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */)
+ if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true)
vd->cloth_color = 0;
- if (vd->body_style && (
- sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS ||
- sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK ||
- sd->sc.option&OPTION_OKTOBERFEST))
+ if (vd->body_style != 0 && (sd->sc.option & OPTION_COSTUME) != 0)
vd->body_style = 0;
break;
case LOOK_HAIR:
@@ -3141,16 +3702,18 @@ void clif_changelook(struct block_list *bl,int type,int val)
vd->hair_color = val;
break;
case LOOK_CLOTHES_COLOR:
- if( val && sd ) {
- if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette )
+ if (val && sd != NULL) {
+ if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true)
val = 0;
- if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette )
+ if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true)
val = 0;
- if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette )
+ if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true)
val = 0;
- if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette )
+ if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true)
val = 0;
- if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ )
+ if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true)
+ val = 0;
+ if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true)
val = 0;
}
vd->cloth_color = val;
@@ -3182,64 +3745,61 @@ void clif_changelook(struct block_list *bl,int type,int val)
#endif
break;
case LOOK_BODY2:
- if (val && (
- sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS ||
- sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK ||
- sd->sc.option&OPTION_OKTOBERFEST))
+ if (sd != NULL && (sd->sc.option&OPTION_COSTUME) != OPTION_NOTHING)
val = 0;
vd->body_style = val;
break;
}
// prevent leaking the presence of GM-hidden objects
- if( sc && sc->option&OPTION_INVISIBLE && !disguised(bl) )
+ if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl))
target = SELF;
#if PACKETVER < 4
clif->sendlook(bl, bl->id, type, val, 0, target);
#else
- if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
- nullpo_retv(vd);
- type = LOOK_WEAPON;
- val = vd->weapon;
- val2 = vd->shield;
- }
- if( disguised(bl) ) {
- clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
- clif->sendlook(bl, -bl->id, type, val, val2, SELF);
- } else
- clif->sendlook(bl, bl->id, type, val, val2, target);
+ if (bl->type != BL_NPC) {
+ if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
+ nullpo_retv(vd);
+ type = LOOK_WEAPON;
+ val = vd->weapon;
+ val2 = vd->shield;
+ }
+ if (clif->isdisguised(bl)) {
+ clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
+ clif->sendlook(bl, -bl->id, type, val, val2, SELF);
+ } else {
+ clif->sendlook(bl, bl->id, type, val, val2, target);
+ }
+ } else {
+ struct npc_data *nd = BL_UCAST(BL_NPC, bl);
+ npc->refresh(nd);
+ }
#endif
}
//Sends a change-base-look packet required for traps as they are triggered.
-void clif_changetraplook(struct block_list *bl,int val)
+static void clif_changetraplook(struct block_list *bl, int val)
{
clif->sendlook(bl, bl->id, LOOK_BASE, val, 0, AREA);
}
/// 00c3 <id>.L <type>.B <value>.B (ZC_SPRITE_CHANGE)
/// 01d7 <id>.L <type>.B <value>.L (ZC_SPRITE_CHANGE2)
-void clif_sendlook(struct block_list *bl, int id, int type, int val, int val2, enum send_target target)
-{
- unsigned char buf[32];
-#if PACKETVER < 4
- WBUFW(buf,0)=0xc3;
- WBUFL(buf,2)=id;
- WBUFB(buf,6)=type;
- WBUFB(buf,7)=val;
- clif->send(buf,packet_len(0xc3),bl,target);
-#else
- WBUFW(buf,0)=0x1d7;
- WBUFL(buf,2)=id;
- WBUFB(buf,6)=type;
- WBUFW(buf,7)=val;
- WBUFW(buf,9)=val2;
- clif->send(buf,packet_len(0x1d7),bl,target);
+static void clif_sendlook(struct block_list *bl, int id, int type, int val, int val2, enum send_target target)
+{
+ struct PACKET_ZC_SPRITE_CHANGE p;
+ p.packetType = sendLookType;
+ p.AID = id;
+ p.type = type;
+ p.val = val;
+#if PACKETVER >= 4
+ p.val2 = val2;
#endif
+ clif->send(&p, sizeof(p), bl, target);
}
//For the stupid cloth-dye bug. Resends the given view data to the area specified by bl.
-void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target)
+static void clif_refreshlook(struct block_list *bl, int id, int type, int val, enum send_target target)
{
clif->sendlook(bl, id, type, val, 0, target);
}
@@ -3249,7 +3809,8 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta
/// <int>.B <need int>.B <dex>.B <need dex>.B <luk>.B <need luk>.B <atk>.W <atk2>.W
/// <matk min>.W <matk max>.W <def>.W <def2>.W <mdef>.W <mdef2>.W <hit>.W
/// <flee>.W <flee2>.W <crit>.W <aspd>.W <aspd2>.W
-void clif_initialstatus(struct map_session_data *sd) {
+static void clif_initialstatus(struct map_session_data *sd)
+{
int fd, mdef2;
unsigned char *buf;
@@ -3309,14 +3870,14 @@ void clif_initialstatus(struct map_session_data *sd) {
/// Marks an ammunition item in inventory as equipped (ZC_EQUIP_ARROW).
/// 013c <index>.W
-void clif_arrowequip(struct map_session_data *sd,int val)
+static void clif_arrowequip(struct map_session_data *sd, int val)
{
int fd;
nullpo_retv(sd);
#if PACKETVER >= 20121128
- clif->status_change(&sd->bl, SI_CLIENT_ONLY_EQUIP_ARROW, 1, INVALID_TIMER, 0, 0, 0);
+ clif->status_change(&sd->bl, status->get_sc_icon(SC_CLIENT_ONLY_EQUIP_ARROW), status->get_sc_relevant_bl_types(SC_CLIENT_ONLY_EQUIP_ARROW), 1, INVALID_TIMER, 0, 0, 0);
#endif
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0x013c));
@@ -3334,7 +3895,7 @@ void clif_arrowequip(struct map_session_data *sd,int val)
/// 3 = assassin, baby_assassin, assassin_cross => MsgStringTable[1040]="You have equipped throwing daggers."
/// gunslinger => MsgStringTable[1175]="Bullets have been equipped."
/// NOT ninja => MsgStringTable[245]="Ammunition has been equipped."
-void clif_arrow_fail(struct map_session_data *sd,int type)
+static void clif_arrow_fail(struct map_session_data *sd, int type)
{
int fd;
@@ -3349,32 +3910,33 @@ void clif_arrow_fail(struct map_session_data *sd,int type)
/// Presents a list of items, that can be processed by Arrow Crafting (ZC_MAKINGARROW_LIST).
/// 01ad <packet len>.W { <name id>.W }*
-void clif_arrow_create_list(struct map_session_data *sd)
+static void clif_arrow_create_list(struct map_session_data *sd)
{
- int i, c;
- int fd;
-
nullpo_retv(sd);
- fd = sd->fd;
- WFIFOHEAD(fd, MAX_SKILL_ARROW_DB*2+4);
- WFIFOW(fd,0) = 0x1ad;
+ int fd = sd->fd;
+ int len = MAX_SKILL_ARROW_DB * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MAKINGARROW_LIST *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGARROW_LIST;
- for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) {
+ int c = 0;
+ for (int i = 0; i < MAX_SKILL_ARROW_DB; i++) {
int j;
if (skill->dbs->arrow_db[i].nameid > 0
&& (j = pc->search_inventory(sd, skill->dbs->arrow_db[i].nameid)) != INDEX_NOT_FOUND
&& !sd->status.inventory[j].equip && sd->status.inventory[j].identify
) {
if ((j = itemdb_viewid(skill->dbs->arrow_db[i].nameid)) > 0)
- WFIFOW(fd,c*2+4) = j;
+ p->items[c].itemId = j;
else
- WFIFOW(fd,c*2+4) = skill->dbs->arrow_db[i].nameid;
+ p->items[c].itemId = skill->dbs->arrow_db[i].nameid;
c++;
}
}
- WFIFOW(fd,2) = c*2+4;
- WFIFOSET(fd, WFIFOW(fd,2));
+ len = c * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
if (c > 0) {
sd->menuskill_id = AC_MAKINGARROW;
sd->menuskill_val = c;
@@ -3388,25 +3950,25 @@ void clif_arrow_create_list(struct map_session_data *sd)
/// result:
/// 0 = failure
/// 1 = success
-void clif_statusupack(struct map_session_data *sd,int type,int ok,int val)
+static void clif_statusupack(struct map_session_data *sd, int type, int ok, int val)
{
- int fd;
-
nullpo_retv(sd);
+ int fd = sd->fd;
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xbc));
- WFIFOW(fd,0)=0xbc;
- WFIFOW(fd,2)=type;
- WFIFOB(fd,4)=ok;
- WFIFOB(fd,5)=cap_value(val,0,UINT8_MAX);
- WFIFOSET(fd,packet_len(0xbc));
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_STATUS_CHANGE_ACK));
+ struct PACKET_ZC_STATUS_CHANGE_ACK *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_STATUS_CHANGE_ACK;
+ p->sp = type;
+ p->ok = ok;
+ p->value = cap_value(val, 0, UINT8_MAX);
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_STATUS_CHANGE_ACK));
}
/// Notifies the client about the result of a request to equip an item (ZC_REQ_WEAR_EQUIP_ACK).
/// 00aa <index>.W <equip location>.W <result>.B
/// 00aa <index>.W <equip location>.W <view id>.W <result>.B (PACKETVER >= 20100629)
-void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result) {
+static void clif_equipitemack(struct map_session_data *sd, int n, int pos, enum e_EQUIP_ITEM_ACK result)
+{
struct packet_equipitem_ack p;
nullpo_retv(sd);
@@ -3415,8 +3977,9 @@ void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_IT
p.index = n+2;
p.wearLocation = pos;
#if PACKETVER >= 20100629
+ Assert_retv(n >= 0 && n < sd->status.inventorySize);
if (result == EIA_SUCCESS && sd->inventory_data[n]->equip&EQP_VISIBLE)
- p.wItemSpriteNumber = sd->inventory_data[n]->look;
+ p.wItemSpriteNumber = sd->inventory_data[n]->view_sprite;
else
p.wItemSpriteNumber = 0;
#endif
@@ -3427,7 +3990,8 @@ void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_IT
/// Notifies the client about the result of a request to take off an item (ZC_REQ_TAKEOFF_EQUIP_ACK).
/// 00ac <index>.W <equip location>.W <result>.B
-void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result) {
+static void clif_unequipitemack(struct map_session_data *sd, int n, int pos, enum e_UNEQUIP_ITEM_ACK result)
+{
struct packet_unequipitem_ack p;
nullpo_retv(sd);
@@ -3453,7 +4017,7 @@ void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUI
/// 7 = base level up (super novice)
/// 8 = job level up (super novice)
/// 9 = base level up (taekwon)
-void clif_misceffect(struct block_list* bl,int type)
+static void clif_misceffect(struct block_list *bl, int type)
{
unsigned char buf[32];
@@ -3469,56 +4033,66 @@ void clif_misceffect(struct block_list* bl,int type)
/// Notifies clients in the area of a state change.
/// 0119 <id>.L <body state>.W <health state>.W <effect state>.W <pk mode>.B (ZC_STATE_CHANGE)
/// 0229 <id>.L <body state>.W <health state>.W <effect state>.L <pk mode>.B (ZC_STATE_CHANGE3)
-void clif_changeoption(struct block_list* bl)
+static void clif_changeoption(struct block_list *bl)
{
- unsigned char buf[32];
- struct status_change *sc;
- struct map_session_data* sd;
+ nullpo_retv(bl);
+
+ struct status_change *sc = status->get_sc(bl);
+
+ if (sc == NULL && bl->type != BL_NPC) // How can an option change if there's no sc?
+ return;
+
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ struct PACKET_ZC_STATE_CHANGE p;
+ p.packetType = HEADER_ZC_STATE_CHANGE;
+ p.AID = bl->id;
+ p.bodyState = (sc != NULL) ? sc->opt1 : 0;
+ p.healthState = (sc != NULL) ? sc->opt2 : 0;
+ p.effectState = (sc != NULL) ? sc->option : BL_UCCAST(BL_NPC, bl)->option;
+ p.isPKModeON = (sd != NULL) ? sd->status.karma : 0;
+ if (clif->isdisguised(bl)) {
+ clif->send(&p, sizeof(p), bl, AREA_WOS);
+ p.AID = -bl->id;
+ clif->send(&p, sizeof(p), bl, SELF);
+ p.AID = bl->id;
+ p.effectState = OPTION_INVISIBLE;
+ clif->send(&p, sizeof(p), bl, SELF);
+ } else {
+ clif->send(&p, sizeof(p), bl, AREA);
+ }
+}
+static void clif_changeoption_target(struct block_list *bl, struct block_list *target_bl, enum send_target target)
+{
nullpo_retv(bl);
+ nullpo_retv(target_bl);
- if ( !(sc = status->get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc?
+ struct status_change *sc = status->get_sc(bl);
- sd = BL_CAST(BL_PC, bl);
+ if (sc == NULL && bl->type != BL_NPC) // How can an option change if there's no sc?
+ return;
-#if PACKETVER >= 7
- WBUFW(buf,0) = 0x229;
- WBUFL(buf,2) = bl->id;
- WBUFW(buf,6) = (sc) ? sc->opt1 : 0;
- WBUFW(buf,8) = (sc) ? sc->opt2 : 0;
- WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- WBUFB(buf,14) = (sd)? sd->status.karma : 0;
- if(disguised(bl)) {
- clif->send(buf,packet_len(0x229),bl,AREA_WOS);
- WBUFL(buf,2) = -bl->id;
- clif->send(buf,packet_len(0x229),bl,SELF);
- WBUFL(buf,2) = bl->id;
- WBUFL(buf,10) = OPTION_INVISIBLE;
- clif->send(buf,packet_len(0x229),bl,SELF);
- } else
- clif->send(buf,packet_len(0x229),bl,AREA);
-#else
- WBUFW(buf,0) = 0x119;
- WBUFL(buf,2) = bl->id;
- WBUFW(buf,6) = (sc) ? sc->opt1 : 0;
- WBUFW(buf,8) = (sc) ? sc->opt2 : 0;
- WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
- WBUFB(buf,12) = (sd)? sd->status.karma : 0;
- if(disguised(bl)) {
- clif->send(buf,packet_len(0x119),bl,AREA_WOS);
- WBUFL(buf,2) = -bl->id;
- clif->send(buf,packet_len(0x119),bl,SELF);
- WBUFL(buf,2) = bl->id;
- WBUFW(buf,10) = OPTION_INVISIBLE;
- clif->send(buf,packet_len(0x119),bl,SELF);
- } else
- clif->send(buf,packet_len(0x119),bl,AREA);
-#endif
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ struct PACKET_ZC_STATE_CHANGE p;
+ p.packetType = HEADER_ZC_STATE_CHANGE;
+ p.AID = bl->id;
+ p.bodyState = (sc != NULL) ? sc->opt1 : 0;
+ p.healthState = (sc != NULL) ? sc->opt2 : 0;
+ p.effectState = (sc != NULL) ? sc->option : BL_UCCAST(BL_NPC, bl)->option;
+ p.isPKModeON = (sd != NULL) ? sd->status.karma : 0;
+ if (clif->isdisguised(bl)) {
+ p.AID = -bl->id;
+ clif->send(&p, sizeof(p), target_bl, target);
+ p.AID = bl->id;
+ p.effectState = OPTION_INVISIBLE;
+ }
+ clif->send(&p, sizeof(p), target_bl, target);
}
/// Displays status change effects on NPCs/monsters (ZC_NPC_SHOWEFST_UPDATE).
/// 028a <id>.L <effect state>.L <level>.L <showEFST>.L
-void clif_changeoption2(struct block_list* bl) {
+static void clif_changeoption2(struct block_list *bl)
+{
unsigned char buf[20];
struct status_change *sc;
@@ -3530,56 +4104,50 @@ void clif_changeoption2(struct block_list* bl) {
WBUFL(buf,6) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
WBUFL(buf,10) = clif_setlevel(bl);
WBUFL(buf,14) = (sc) ? sc->opt3 : 0;
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
clif->send(buf,packet_len(0x28a),bl,AREA_WOS);
WBUFL(buf,2) = -bl->id;
clif->send(buf,packet_len(0x28a),bl,SELF);
WBUFL(buf,2) = bl->id;
WBUFL(buf,6) = OPTION_INVISIBLE;
clif->send(buf,packet_len(0x28a),bl,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x28a),bl,AREA);
+ }
}
/// Notifies the client about the result of an item use request.
/// 00a8 <index>.W <amount>.W <result>.B (ZC_USE_ITEM_ACK)
/// 01c8 <index>.W <name id>.W <id>.L <amount>.W <result>.B (ZC_USE_ITEM_ACK2)
-void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok)
+static void clif_useitemack(struct map_session_data *sd, int index, int amount, bool ok)
{
+ struct PACKET_ZC_USE_ITEM_ACK p;
+ int fd;
+
nullpo_retv(sd);
- if(!ok) {
- int fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xa8));
- WFIFOW(fd,0)=0xa8;
- WFIFOW(fd,2)=index+2;
- WFIFOW(fd,4)=amount;
- WFIFOB(fd,6)=ok;
- WFIFOSET(fd,packet_len(0xa8));
- }
- else {
-#if PACKETVER < 3
- int fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xa8));
- WFIFOW(fd,0)=0xa8;
- WFIFOW(fd,2)=index+2;
- WFIFOW(fd,4)=amount;
- WFIFOB(fd,6)=ok;
- WFIFOSET(fd,packet_len(0xa8));
-#else
- unsigned char buf[32];
+ if (index < 0 || index >= sd->status.inventorySize)
+ return;
- WBUFW(buf,0)=0x1c8;
- WBUFW(buf,2)=index+2;
- if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0)
- WBUFW(buf,4)=sd->inventory_data[index]->view_id;
- else
- WBUFW(buf,4)=sd->status.inventory[index].nameid;
- WBUFL(buf,6)=sd->bl.id;
- WBUFW(buf,10)=amount;
- WBUFB(buf,12)=ok;
- clif->send(buf,packet_len(0x1c8),&sd->bl,AREA);
+ fd = sd->fd;
+ p.packetType = useItemAckType;
+ p.index = index + 2;
+#if PACKETVER > 3
+ if (sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0)
+ p.itemId = sd->inventory_data[index]->view_id;
+ else
+ p.itemId = sd->status.inventory[index].nameid;
+ p.AID = sd->bl.id;
#endif
+ p.amount = amount;
+ p.result = ok;
+
+ if (!ok) {
+ WFIFOHEAD(fd, sizeof(p));
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
+ } else {
+ clif->send(&p, sizeof(p), &sd->bl, AREA);
}
}
@@ -3590,7 +4158,7 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok)
/// 1 = Room limit exceeded
/// 2 = Same room already exists
// TODO: Flag enum
-void clif_createchat(struct map_session_data* sd, int flag)
+static void clif_createchat(struct map_session_data *sd, int flag)
{
int fd;
@@ -3610,26 +4178,29 @@ void clif_createchat(struct map_session_data* sd, int flag)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_dispchat(struct chat_data* cd, int fd)
+static void clif_dispchat(struct chat_data *cd, int fd)
{
unsigned char buf[128];
uint8 type;
+ int len;
- if( cd == NULL || cd->owner == NULL )
+ if (cd == NULL || cd->owner == NULL)
return;
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xd7;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
if( fd ) {
WFIFOHEAD(fd,WBUFW(buf,2));
@@ -3647,10 +4218,11 @@ void clif_dispchat(struct chat_data* cd, int fd)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_changechatstatus(struct chat_data* cd)
+static void clif_changechatstatus(struct chat_data *cd)
{
unsigned char buf[128];
uint8 type;
+ int len;
if( cd == NULL || cd->usersd[0] == NULL )
return;
@@ -3658,22 +4230,24 @@ void clif_changechatstatus(struct chat_data* cd)
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xdf;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
clif->send(buf,WBUFW(buf,2),cd->owner,CHAT);
}
/// Removes the chatroom (ZC_DESTROY_ROOM).
/// 00d8 <chat id>.L
-void clif_clearchat(struct chat_data *cd,int fd)
+static void clif_clearchat(struct chat_data *cd, int fd)
{
unsigned char buf[32];
@@ -3701,7 +4275,7 @@ void clif_clearchat(struct chat_data *cd,int fd)
/// 5 = too low level
/// 6 = too high level
/// 7 = unsuitable job class
-void clif_joinchatfail(struct map_session_data *sd,int flag)
+static void clif_joinchatfail(struct map_session_data *sd, int flag)
{
int fd;
@@ -3720,7 +4294,7 @@ void clif_joinchatfail(struct map_session_data *sd,int flag)
/// role:
/// 0 = owner (menu)
/// 1 = normal
-void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd)
+static void clif_joinchatok(struct map_session_data *sd, struct chat_data *cd)
{
int fd;
int i,t;
@@ -3756,7 +4330,7 @@ void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd)
/// Notifies clients in a chat about a new member (ZC_MEMBER_NEWENTRY).
/// 00dc <users>.W <name>.24B
-void clif_addchat(struct chat_data* cd,struct map_session_data *sd)
+static void clif_addchat(struct chat_data *cd, struct map_session_data *sd)
{
unsigned char buf[32];
@@ -3774,22 +4348,25 @@ void clif_addchat(struct chat_data* cd,struct map_session_data *sd)
/// role:
/// 0 = owner (menu)
/// 1 = normal
-void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd)
+static void clif_chatRoleChange(struct chat_data *cd, struct map_session_data *sd, struct block_list* bl, int isNotOwner)
{
- unsigned char buf[64];
-
nullpo_retv(sd);
- nullpo_retv(cd);
+ nullpo_retv(bl);
+ struct PACKET_ZC_ROLE_CHANGE p;
- WBUFW(buf, 0) = 0xe1;
- WBUFL(buf, 2) = 1;
- memcpy(WBUFP(buf,6),cd->usersd[0]->status.name,NAME_LENGTH);
+ p.packetType = HEADER_ZC_ROLE_CHANGE;
+ p.flag = isNotOwner;
+ memcpy(&p.name, sd->status.name, NAME_LENGTH);
+ clif->send(&p, sizeof(struct PACKET_ZC_ROLE_CHANGE), bl, CHAT);
+}
- WBUFW(buf,30) = 0xe1;
- WBUFL(buf,32) = 0;
- memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH);
+static void clif_changechatowner(struct chat_data *cd, struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+ nullpo_retv(cd);
- clif->send(buf,packet_len(0xe1)*2,&sd->bl,CHAT);
+ clif->chatRoleChange(cd, cd->usersd[0], &sd->bl, 1);
+ clif->chatRoleChange(cd, sd, &sd->bl, 0);
}
/// Notify about user leaving the chatroom (ZC_MEMBER_EXIT).
@@ -3797,7 +4374,7 @@ void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd)
/// flag:
/// 0 = left
/// 1 = kicked
-void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag)
+static void clif_leavechat(struct chat_data *cd, struct map_session_data *sd, bool flag)
{
unsigned char buf[32];
@@ -3815,7 +4392,7 @@ void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag
/// Opens a trade request window from char 'name'.
/// 00e5 <nick>.24B (ZC_REQ_EXCHANGE_ITEM)
/// 01f4 <nick>.24B <charid>.L <baselvl>.W (ZC_REQ_EXCHANGE_ITEM2)
-void clif_traderequest(struct map_session_data *sd, const char *name)
+static void clif_traderequest(struct map_session_data *sd, const char *name)
{
int fd;
#if PACKETVER >= 6
@@ -3854,16 +4431,16 @@ void clif_traderequest(struct map_session_data *sd, const char *name)
/// 3 = Accept
/// 4 = Cancel
/// 5 = Busy
-void clif_tradestart(struct map_session_data *sd, uint8 type)
+static void clif_tradestart(struct map_session_data *sd, uint8 type)
{
int fd;
-#if PACKETVER >= 6
+#if PACKETVER >= 20090406
struct map_session_data *tsd = NULL;
#endif // PACKETVER >= 6
nullpo_retv(sd);
fd = sd->fd;
-#if PACKETVER >= 6
+#if PACKETVER >= 20090406
tsd = map->id2sd(sd->trade_partner);
if (tsd) {
WFIFOHEAD(fd,packet_len(0x1f5));
@@ -3874,76 +4451,51 @@ void clif_tradestart(struct map_session_data *sd, uint8 type)
WFIFOSET(fd,packet_len(0x1f5));
return;
}
-#endif // PACKETVER >= 6
+#else
WFIFOHEAD(fd,packet_len(0xe7));
WFIFOW(fd,0) = 0xe7;
WFIFOB(fd,2) = type;
WFIFOSET(fd,packet_len(0xe7));
+#endif // PACKETVER >= 6
}
/// Notifies the client about an item from other player in current trade.
/// 00e9 <amount>.L <nameid>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_EXCHANGE_ITEM)
/// 080f <nameid>.W <item type>.B <amount>.L <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_EXCHANGE_ITEM2)
-void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd, int index, int amount)
+static void clif_tradeadditem(struct map_session_data *sd, struct map_session_data *tsd, int index, int amount)
{
int fd;
- unsigned char *buf;
+ struct PACKET_ZC_ADD_EXCHANGE_ITEM p;
+
nullpo_retv(sd);
nullpo_retv(tsd);
fd = tsd->fd;
- buf = WFIFOP(fd,0);
- WFIFOHEAD(fd,packet_len(tradeaddType));
- WBUFW(buf,0) = tradeaddType;
- if( index == 0 )
- {
-#if PACKETVER < 20100223
- WBUFL(buf,2) = amount; //amount
- WBUFW(buf,6) = 0; // type id
-#else
- WBUFW(buf,2) = 0; // type id
- WBUFB(buf,4) = 0; // item type
- WBUFL(buf,5) = amount; // amount
- buf = WBUFP(buf,1); //Advance 1B
-#endif
- WBUFB(buf,8) = 0; //identify flag
- WBUFB(buf,9) = 0; // attribute
- WBUFB(buf,10)= 0; //refine
- WBUFW(buf,11)= 0; //card (4w)
- WBUFW(buf,13)= 0; //card (4w)
- WBUFW(buf,15)= 0; //card (4w)
- WBUFW(buf,17)= 0; //card (4w)
-#if PACKETVER >= 20150226
- clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]);
-#endif
- }
- else
+ WFIFOHEAD(fd, sizeof(p));
+ memset(&p, 0, sizeof(p));
+ p.packetType = tradeaddType;
+ p.amount = amount;
+ if (index != 0)
{
index -= 2; //index fix
-#if PACKETVER < 20100223
- WBUFL(buf,2) = amount; //amount
+ Assert_retv(index >= 0 && index < sd->status.inventorySize);
if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0)
- WBUFW(buf,6) = sd->inventory_data[index]->view_id;
+ p.itemId = sd->inventory_data[index]->view_id;
else
- WBUFW(buf,6) = sd->status.inventory[index].nameid; // type id
-#else
- if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0)
- WBUFW(buf,2) = sd->inventory_data[index]->view_id;
- else
- WBUFW(buf,2) = sd->status.inventory[index].nameid; // type id
- WBUFB(buf,4) = sd->inventory_data[index]->type; // item type
- WBUFL(buf,5) = amount; // amount
- buf = WBUFP(buf,1); //Advance 1B
-#endif
- WBUFB(buf,8) = sd->status.inventory[index].identify; //identify flag
- WBUFB(buf,9) = sd->status.inventory[index].attribute; // attribute
- WBUFB(buf,10)= sd->status.inventory[index].refine; //refine
- clif->addcards(WBUFP(buf, 11), &sd->status.inventory[index]);
+ p.itemId = sd->status.inventory[index].nameid;
+#if PACKETVER >= 20100223
+ p.itemType = sd->inventory_data[index]->type;
+#endif
+ p.identified = sd->status.inventory[index].identify;
+ p.damaged = sd->status.inventory[index].attribute;
+ p.refine = sd->status.inventory[index].refine;
+ clif->addcards(&p.slot, &sd->status.inventory[index]);
#if PACKETVER >= 20150226
- clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]);
+ clif->add_item_options(&p.option_data[0], &sd->status.inventory[index]);
#endif
}
- WFIFOSET(fd,packet_len(tradeaddType));
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Notifies the client about the result of request to add an item to the current trade (ZC_ACK_ADD_EXCHANGE_ITEM).
@@ -3952,7 +4504,9 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd
/// 0 = success
/// 1 = overweight
/// 2 = trade canceled
-void clif_tradeitemok(struct map_session_data* sd, int index, int fail)
+/// 3 = amount is exceeded. message 0x792
+/// 4 = other amount is exceeded. message 0x793
+static void clif_tradeitemok(struct map_session_data *sd, int index, int fail)
{
int fd;
nullpo_retv(sd);
@@ -3970,7 +4524,7 @@ void clif_tradeitemok(struct map_session_data* sd, int index, int fail)
/// who:
/// 0 = self
/// 1 = other player
-void clif_tradedeal_lock(struct map_session_data* sd, int fail)
+static void clif_tradedeal_lock(struct map_session_data *sd, int fail)
{
int fd;
nullpo_retv(sd);
@@ -3984,7 +4538,7 @@ void clif_tradedeal_lock(struct map_session_data* sd, int fail)
/// Notifies the client about the trade being canceled (ZC_CANCEL_EXCHANGE_ITEM).
/// 00ee
-void clif_tradecancelled(struct map_session_data* sd)
+static void clif_tradecancelled(struct map_session_data *sd)
{
int fd;
nullpo_retv(sd);
@@ -4000,7 +4554,7 @@ void clif_tradecancelled(struct map_session_data* sd)
/// result:
/// 0 = success
/// 1 = failure
-void clif_tradecompleted(struct map_session_data* sd, int fail)
+static void clif_tradecompleted(struct map_session_data *sd, int fail)
{
int fd;
nullpo_retv(sd);
@@ -4017,7 +4571,7 @@ void clif_tradecompleted(struct map_session_data* sd, int fail)
/// NOTE: Unknown purpose. Items are not removed until the window is
/// refreshed (ex. by putting another item in there).
/// unused
-void clif_tradeundo(struct map_session_data* sd)
+static void clif_tradeundo(struct map_session_data *sd)
{
int fd;
@@ -4030,7 +4584,7 @@ void clif_tradeundo(struct map_session_data* sd)
/// Updates storage total amount (ZC_NOTIFY_STOREITEM_COUNTINFO).
/// 00f2 <current count>.W <max count>.W
-void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount)
+static void clif_updatestorageamount(struct map_session_data *sd, int amount, int max_amount)
{
int fd;
@@ -4047,54 +4601,56 @@ void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_a
/// Notifies the client of an item being added to the storage.
/// 00f4 <index>.W <amount>.L <nameid>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_STORE)
/// 01c4 <index>.W <amount>.L <nameid>.W <type>.B <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_STORE2)
-void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount)
+static void clif_storageitemadded(struct map_session_data *sd, struct item *i, int index, int amount)
{
- int view,fd;
- int offset = 0;
+ int view, fd;
+ struct PACKET_ZC_ADD_ITEM_TO_STORE p;
nullpo_retv(sd);
nullpo_retv(i);
- fd=sd->fd;
+
+ fd = sd->fd;
view = itemdb_viewid(i->nameid);
- WFIFOHEAD(fd,packet_len(storageaddType));
- WFIFOW(fd, 0) = storageaddType; // Storage item added
- WFIFOW(fd, 2) = index+1; // index
- WFIFOL(fd, 4) = amount; // amount
- WFIFOW(fd, 8) = ( view > 0 ) ? view : i->nameid; // id
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = storageaddType; // Storage item added
+ p.index = index + 1; // index
+ p.amount = amount; // amount
+ p.itemId = (view > 0) ? view : i->nameid; // id
#if PACKETVER >= 5
- WFIFOB(fd,10) = itemtype(itemdb_type(i->nameid)); //type
- offset += 1;
+ p.itemType = itemtype(itemdb_type(i->nameid)); //type
#endif
- WFIFOB(fd,10+offset) = i->identify; //identify flag
- WFIFOB(fd,11+offset) = i->attribute; // attribute
- WFIFOB(fd,12+offset) = i->refine; //refine
- clif->addcards(WFIFOP(fd,13+offset), i);
+ p.identified = i->identify; //identify flag
+ p.damaged = i->attribute; // attribute
+ p.refine = i->refine; //refine
+ clif->addcards(&p.slot, i);
#if PACKETVER >= 20150226
- clif->add_random_options(WFIFOP(fd,21+offset), i);
+ clif->add_item_options(&p.option_data[0], i);
#endif
- WFIFOSET(fd,packet_len(storageaddType));
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Notifies the client of an item being deleted from the storage (ZC_DELETE_ITEM_FROM_STORE).
/// 00f6 <index>.W <amount>.L
-void clif_storageitemremoved(struct map_session_data* sd, int index, int amount)
+static void clif_storageitemremoved(struct map_session_data *sd, int index, int amount)
{
int fd;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xf6));
- WFIFOW(fd,0)=0xf6; // Storage item removed
- WFIFOW(fd,2)=index+1;
- WFIFOL(fd,4)=amount;
- WFIFOSET(fd,packet_len(0xf6));
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, packet_len(0xf6));
+ WFIFOW(fd, 0) = 0xf6; // Storage item removed
+ WFIFOW(fd, 2) = index + 1;
+ WFIFOL(fd, 4) = amount;
+ WFIFOSET(fd, packet_len(0xf6));
}
/// Closes storage (ZC_CLOSE_STORE).
/// 00f8
-void clif_storageclose(struct map_session_data* sd)
+static void clif_storageclose(struct map_session_data *sd)
{
int fd;
@@ -4109,14 +4665,15 @@ void clif_storageclose(struct map_session_data* sd)
/*==========================================
* Server tells 'sd' player client the abouts of 'dstsd' player
*------------------------------------------*/
-void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) {
+static void clif_getareachar_pc(struct map_session_data *sd, struct map_session_data *dstsd)
+{
struct block_list *d_bl;
int i;
nullpo_retv(sd);
nullpo_retv(dstsd);
- if( dstsd->chatID ) {
- struct chat_data *cd = map->id2cd(dstsd->chatID);
+ if (dstsd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(dstsd->chat_id);
if (cd != NULL && cd->usersd[0] == dstsd)
clif->dispchat(cd,sd->fd);
} else if( dstsd->state.vending )
@@ -4130,7 +4687,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
clif->charm_single(sd->fd, dstsd);
for( i = 0; i < dstsd->sc_display_count; i++ ) {
- clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
+ clif->sc_continue(&sd->bl, dstsd->bl.id, SELF, status->get_sc_icon(dstsd->sc_display[i]->type), dstsd->sc_display[i]->val1, dstsd->sc_display[i]->val2, dstsd->sc_display[i]->val3);
}
if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
(sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround
@@ -4149,7 +4706,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
clif->devotion(d_bl, sd);
}
-void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
+static void clif_getareachar_unit(struct map_session_data *sd, struct block_list *bl)
+{
struct unit_data *ud;
struct view_data *vd;
@@ -4157,7 +4715,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
nullpo_retv(bl);
vd = status->get_viewdata(bl);
- if (!vd || vd->class_ == INVISIBLE_CLASS)
+ if (vd == NULL || vd->class == INVISIBLE_CLASS)
return;
if (bl->type == BL_NPC) {
@@ -4188,8 +4746,9 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->specialeffect_single(bl,421,sd->fd);
if (tsd->bg_id != 0 && map->list[tsd->bl.m].flag.battleground)
clif->sendbgemblem_single(sd->fd,tsd);
- if (tsd->status.robe)
- clif->refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF);
+ if (tsd->status.look.robe != 0)
+ clif->refreshlook(&sd->bl, bl->id, LOOK_ROBE, tsd->status.look.robe, SELF);
+ clif->hat_effect(bl, &sd->bl, SELF);
}
break;
case BL_MER: // Devotion Effects
@@ -4208,6 +4767,8 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->specialeffect_single(bl,423,sd->fd);
else if (nd->size == SZ_MEDIUM)
clif->specialeffect_single(bl,421,sd->fd);
+ if (nd->clan_id > 0)
+ clif->sc_load(&nd->bl, nd->bl.id, AREA, status->get_sc_icon(SC_CLAN_INFO), 0, nd->clan_id, 0);
}
break;
case BL_MOB:
@@ -4239,15 +4800,16 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
//Modifies the type of damage according to status changes [Skotlex]
//Aegis data specifies that: 4 endure against single hit sources, 9 against multi-hit.
-static inline int clif_calc_delay(int type, int div, int damage, int delay)
+static inline enum battle_dmg_type clif_calc_delay(enum battle_dmg_type type, int div, int damage, int delay)
{
- return ( delay == 0 && damage > 0 ) ? ( div > 1 ? 9 : 4 ) : type;
+ return ( delay == 0 && damage > 0 ) ? ( div > 1 ? BDT_MULTIENDURE : BDT_ENDURE ) : type;
}
/*==========================================
* Estimates walk delay based on the damage criteria. [Skotlex]
*------------------------------------------*/
-int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, int div_) {
+static int clif_calc_walkdelay(struct block_list *bl, int delay, int type, int damage, int div_)
+{
if (type == 4 || type == 9 || damage <=0)
return 0;
@@ -4271,7 +4833,8 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i
/// 08c8 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <IsSPDamage>.B <div>.W <type>.B <damage2>.L (ZC_NOTIFY_ACT2)
/// type: @see enum battle_dmg_type
/// for BDT_NORMAL: [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ]
-int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type, int64 in_damage2) {
+static int clif_damage(struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, enum battle_dmg_type type, int64 in_damage2)
+{
struct packet_damage p;
struct status_change *sc;
#if PACKETVER < 20071113
@@ -4320,16 +4883,17 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int
p.is_sp_damaged = 0; // TODO: IsSPDamage - Displays blue digits.
#endif
- if(disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(&p,sizeof(p),dst,AREA_WOS);
p.targetGID = -dst->id;
clif->send(&p,sizeof(p),dst,SELF);
- } else
+ } else {
clif->send(&p,sizeof(p),dst,AREA);
+ }
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
p.GID = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
p.targetGID = dst->id;
if(damage > 0) p.damage = -1;
@@ -4339,7 +4903,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int
}
if(src == dst) {
- unit->setdir(src,unit->getdir(src));
+ unit->set_dir(src, unit->getdir(src));
}
//Return adjusted can't walk delay for further processing.
@@ -4349,7 +4913,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int
/*==========================================
* src picks up dst
*------------------------------------------*/
-void clif_takeitem(struct block_list* src, struct block_list* dst)
+static void clif_takeitem(struct block_list *src, struct block_list *dst)
{
//clif->damage(src,dst,0,0,0,0,BDT_PICKUP,0);
unsigned char buf[32];
@@ -4368,7 +4932,7 @@ void clif_takeitem(struct block_list* src, struct block_list* dst)
/*==========================================
* inform clients in area that `bl` is sitting
*------------------------------------------*/
-void clif_sitting(struct block_list* bl)
+static void clif_sitting(struct block_list *bl)
{
unsigned char buf[32];
nullpo_retv(bl);
@@ -4378,7 +4942,7 @@ void clif_sitting(struct block_list* bl)
WBUFB(buf,26) = 2;
clif->send(buf, packet_len(0x8a), bl, AREA);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf, 2) = - bl->id;
clif->send(buf, packet_len(0x8a), bl, SELF);
}
@@ -4387,7 +4951,7 @@ void clif_sitting(struct block_list* bl)
/*==========================================
* inform clients in area that `bl` is standing
*------------------------------------------*/
-void clif_standing(struct block_list* bl)
+static void clif_standing(struct block_list *bl)
{
unsigned char buf[32];
nullpo_retv(bl);
@@ -4397,7 +4961,7 @@ void clif_standing(struct block_list* bl)
WBUFB(buf,26) = 3;
clif->send(buf, packet_len(0x8a), bl, AREA);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf, 2) = - bl->id;
clif->send(buf, packet_len(0x8a), bl, SELF);
}
@@ -4405,7 +4969,8 @@ void clif_standing(struct block_list* bl)
/// Inform client(s) about a map-cell change (ZC_UPDATE_MAPINFO).
/// 0192 <x>.W <y>.W <type>.W <map name>.16B
-void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target) {
+static void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target)
+{
unsigned char buf[32];
WBUFW(buf,0) = 0x192;
@@ -4430,30 +4995,35 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe
/// Notifies the client about an item on floor (ZC_ITEM_ENTRY).
/// 009d <id>.L <name id>.W <identified>.B <x>.W <y>.W <amount>.W <subX>.B <subY>.B
-void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fitem) {
- int view,fd;
+static void clif_getareachar_item(struct map_session_data *sd, struct flooritem_data *fitem)
+{
+ int view, fd;
+ struct PACKET_ZC_ITEM_ENTRY p;
nullpo_retv(sd);
nullpo_retv(fitem);
- fd=sd->fd;
+ fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x9d));
- WFIFOW(fd,0)=0x9d;
- WFIFOL(fd,2)=fitem->bl.id;
- if((view = itemdb_viewid(fitem->item_data.nameid)) > 0)
- WFIFOW(fd,6)=view;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x9d;
+ p.AID = fitem->bl.id;
+ if ((view = itemdb_viewid(fitem->item_data.nameid)) > 0)
+ p.itemId = view;
else
- WFIFOW(fd,6)=fitem->item_data.nameid;
- WFIFOB(fd,8)=fitem->item_data.identify;
- WFIFOW(fd,9)=fitem->bl.x;
- WFIFOW(fd,11)=fitem->bl.y;
- WFIFOW(fd,13)=fitem->item_data.amount;
- WFIFOB(fd,15)=fitem->subx;
- WFIFOB(fd,16)=fitem->suby;
- WFIFOSET(fd,packet_len(0x9d));
+ p.itemId = fitem->item_data.nameid;
+ p.identify = fitem->item_data.identify;
+ p.x = fitem->bl.x;
+ p.y = fitem->bl.y;
+ p.amount = fitem->item_data.amount;
+ p.subX = fitem->subx;
+ p.subY = fitem->suby;
+
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
-void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send_target target) {
+static void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send_target target)
+{
struct packet_graffiti_entry p;
nullpo_retv(bl);
@@ -4477,7 +5047,8 @@ void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send
/// 01c9 <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B <has msg>.B <msg>.80B (ZC_SKILL_ENTRY2)
/// 08c7 <lenght>.W <id> L <creator id>.L <x>.W <y>.W <unit id>.B <range>.W <visible>.B (ZC_SKILL_ENTRY3)
/// 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) {
+static 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);
@@ -4503,9 +5074,8 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en
p.xPos = su->bl.x;
p.yPos = su->bl.y;
- //Use invisible unit id for traps.
- if ((battle_config.traps_setting&1 && skill->get_inf2(su->group->skill_id)&INF2_TRAP) ||
- (skill->get_unit_flag(su->group->skill_id) & UF_RANGEDSINGLEUNIT && !(su->val2 & UF_RANGEDSINGLEUNIT)))
+ // Use invisible unit id for some ground skills.
+ if (skill->get_unit_flag(su->group->skill_id) & UF_RANGEDSINGLEUNIT && !(su->val2 & UF_RANGEDSINGLEUNIT))
p.job = UNT_DUMMYSKILL;
else
p.job = su->group->unit_id;
@@ -4514,7 +5084,7 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en
p.RadiusRange = (unsigned char)su->range;
#endif
- p.isVisible = 1;
+ p.isVisible = su->visible;
#if PACKETVER >= 20130731
p.level = (unsigned char)su->group->skill_lv;
@@ -4531,7 +5101,8 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, en
/*==========================================
* Server tells client to remove unit of id 'unit->bl.id'
*------------------------------------------*/
-void clif_clearchar_skillunit(struct skill_unit *su, int fd) {
+static void clif_clearchar_skillunit(struct skill_unit *su, int fd)
+{
nullpo_retv(su);
WFIFOHEAD(fd,packet_len(0x120));
@@ -4545,7 +5116,8 @@ void clif_clearchar_skillunit(struct skill_unit *su, int fd) {
/// Removes a skill unit (ZC_SKILL_DISAPPEAR).
/// 0120 <id>.L
-void clif_skill_delunit(struct skill_unit *su) {
+static void clif_skill_delunit(struct skill_unit *su)
+{
unsigned char buf[16];
nullpo_retv(su);
@@ -4558,7 +5130,7 @@ void clif_skill_delunit(struct skill_unit *su) {
/// Sent when an object gets ankle-snared (ZC_SKILL_UPDATE).
/// 01ac <id>.L
/// Only affects units with class [139,153] client-side.
-void clif_skillunit_update(struct block_list* bl)
+static void clif_skillunit_update(struct block_list *bl)
{
unsigned char buf[6];
nullpo_retv(bl);
@@ -4572,7 +5144,8 @@ void clif_skillunit_update(struct block_list* bl)
/*==========================================
*
*------------------------------------------*/
-int clif_getareachar(struct block_list* bl,va_list ap) {
+static int clif_getareachar(struct block_list *bl, va_list ap)
+{
struct map_session_data *sd;
nullpo_ret(bl);
@@ -4601,7 +5174,7 @@ int clif_getareachar(struct block_list* bl,va_list ap) {
/*==========================================
* tbl has gone out of view-size of bl
*------------------------------------------*/
-int clif_outsight(struct block_list *bl,va_list ap)
+static int clif_outsight(struct block_list *bl, va_list ap)
{
struct block_list *tbl;
struct view_data *vd;
@@ -4616,11 +5189,11 @@ int clif_outsight(struct block_list *bl,va_list ap)
nullpo_ret(bl);
switch(bl->type){
case BL_PC:
- if (sd->vd.class_ != INVISIBLE_CLASS)
+ if (sd->vd.class != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
- if(cd->usersd[0]==sd)
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
+ if (cd != NULL && cd->usersd[0] == sd)
clif->dispchat(cd,tsd->fd);
}
if( sd->state.vending )
@@ -4639,7 +5212,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
break;
default:
- if ((vd=status->get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS)
+ if ((vd=status->get_viewdata(bl)) && vd->class != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
break;
}
@@ -4648,7 +5221,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
nullpo_ret(tbl);
if (tbl->type == BL_SKILL) //Trap knocked out of sight
clif->clearchar_skillunit(BL_UCAST(BL_SKILL, tbl), sd->fd);
- else if ((vd = status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS
+ else if ((vd = status->get_viewdata(tbl)) != NULL && vd->class != INVISIBLE_CLASS
&& !(tbl->type == BL_NPC && (BL_UCAST(BL_NPC, tbl)->option&OPTION_INVISIBLE)))
clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd);
}
@@ -4658,7 +5231,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
/*==========================================
* tbl has come into view of bl
*------------------------------------------*/
-int clif_insight(struct block_list *bl,va_list ap)
+static int clif_insight(struct block_list *bl, va_list ap)
{
struct block_list *tbl;
struct map_session_data *sd, *tsd;
@@ -4689,101 +5262,107 @@ int clif_insight(struct block_list *bl,va_list ap)
return 0;
}
+static void clif_playerSkillToPacket(struct map_session_data *sd, struct SKILLDATA *skillData, int skillId, int idx, bool newSkill)
+{
+ nullpo_retv(sd);
+ nullpo_retv(skillData);
+ Assert_retv(idx >= 0 && idx < MAX_SKILL_DB);
+
+ int skill_lv = sd->status.skill[idx].lv;
+ skillData->id = skillId;
+ skillData->inf = skill->get_inf(skillId);
+ skillData->level = skill_lv;
+ if (skill_lv > 0) {
+ skillData->sp = skill->get_sp(skillId, skill_lv);
+ skillData->range2 = skill->get_range2(&sd->bl, skillId, skill_lv);
+ } else {
+ skillData->sp = 0;
+ skillData->range2 = 0;
+ }
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+ if (newSkill)
+ skillData->level2 = 0;
+ else
+ skillData->level2 = skill_lv;
+#else
+ safestrncpy(skillData->name, skill->get_name(skillId), NAME_LENGTH);
+#endif
+ if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
+ skillData->upFlag = (skill_lv < skill->tree_get_max(skillId, sd->status.class)) ? 1 : 0;
+ else
+ skillData->upFlag = 0;
+}
+
/// Updates whole skill tree (ZC_SKILLINFO_LIST).
/// 010f <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B }*
-void clif_skillinfoblock(struct map_session_data *sd)
+static void clif_skillinfoblock(struct map_session_data *sd)
{
- int fd;
- int i,len,id;
-
nullpo_retv(sd);
- fd=sd->fd;
- if (!fd) return;
+ int fd = sd->fd;
+ if (!fd)
+ return;
+
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_SKILLINFO_LIST) + MAX_SKILL_DB * sizeof(struct SKILLDATA));
+ struct PACKET_ZC_SKILLINFO_LIST *p = WFIFOP(fd, 0);
- WFIFOHEAD(fd, MAX_SKILL * 37 + 4);
- WFIFOW(fd,0) = 0x10f;
- for ( i = 0, len = 4; i < MAX_SKILL; i++) {
- if( (id = sd->status.skill[i].id) != 0 ) {
- int level;
+ p->packetType = HEADER_ZC_SKILLINFO_LIST;
+ int skillIndex = 0;
+ int len = sizeof(struct PACKET_ZC_SKILLINFO_LIST);
+ int i;
+ for (i = 0; i < MAX_SKILL_DB; i++) {
+ int id = sd->status.skill[i].id;
+ if (id != 0) {
// workaround for bugreport:5348
- if (len + 37 > 8192)
+ if (len + sizeof(struct SKILLDATA) > 8192)
break;
- WFIFOW(fd, len) = id;
- WFIFOL(fd, len + 2) = skill->get_inf(id);
- level = sd->status.skill[i].lv;
- WFIFOW(fd, len + 6) = level;
- if (level) {
- WFIFOW(fd, len + 8) = skill->get_sp(id, level);
- WFIFOW(fd, len + 10)= skill->get_range2(&sd->bl, id, level);
- }
- else {
- WFIFOW(fd, len + 8) = 0;
- WFIFOW(fd, len + 10)= 0;
- }
- safestrncpy(WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH);
- if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
- WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
- else
- WFIFOB(fd,len+36) = 0;
- len += 37;
+ clif->playerSkillToPacket(sd, &p->skills[skillIndex], id, i, false);
+ len += sizeof(struct SKILLDATA);
+ skillIndex++;
}
}
- WFIFOW(fd,2)=len;
- WFIFOSET(fd,len);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
// workaround for bugreport:5348; send the remaining skills one by one to bypass packet size limit
- for ( ; i < MAX_SKILL; i++) {
- if( (id = sd->status.skill[i].id) != 0 ) {
+ for (; i < MAX_SKILL_DB; i++) {
+ int id = sd->status.skill[i].id;
+ if (id != 0) {
clif->addskill(sd, id);
clif->skillinfo(sd, id, 0);
}
}
}
+
/**
* Server tells client 'sd' to add skill of id 'id' to it's skill tree (e.g. with Ice Falcion item)
**/
/// Adds new skill to the skill tree (ZC_ADD_SKILL).
/// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B
-void clif_addskill(struct map_session_data *sd, int id)
+static void clif_addskill(struct map_session_data *sd, int id)
{
- int fd, skill_lv, idx = skill->get_index(id);
-
nullpo_retv(sd);
- fd = sd->fd;
- if (!fd) return;
+ int fd = sd->fd;
+ if (!fd)
+ return;
+ int idx = skill->get_index(id);
if (sd->status.skill[idx].id <= 0)
return;
- skill_lv = sd->status.skill[idx].lv;
-
- WFIFOHEAD(fd, packet_len(0x111));
- WFIFOW(fd,0) = 0x111;
- WFIFOW(fd,2) = id;
- WFIFOL(fd,4) = skill->get_inf(id);
- WFIFOW(fd,8) = skill_lv;
- if (skill_lv > 0) {
- WFIFOW(fd,10) = skill->get_sp(id, skill_lv);
- WFIFOW(fd,12) = skill->get_range2(&sd->bl, id, skill_lv);
- } else {
- WFIFOW(fd,10) = 0;
- WFIFOW(fd,12) = 0;
- }
- safestrncpy(WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH);
- if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
- WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
- else
- WFIFOB(fd,38) = 0;
- WFIFOSET(fd,packet_len(0x111));
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_ADD_SKILL));
+ struct PACKET_ZC_ADD_SKILL *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_ADD_SKILL;
+ clif->playerSkillToPacket(sd, &p->skill, id, idx, true);
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_ADD_SKILL));
}
/// Deletes a skill from the skill tree (ZC_SKILLINFO_DELETE).
/// 0441 <skill id>.W
-void clif_deleteskill(struct map_session_data *sd, int id)
+static void clif_deleteskill(struct map_session_data *sd, int id)
{
#if PACKETVER >= 20081217
int fd;
@@ -4806,7 +5385,7 @@ void clif_deleteskill(struct map_session_data *sd, int id)
/// flag:
/// 0: guild call
/// 1: player call
-void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, int flag)
+static void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, int flag)
{
int fd;
nullpo_retv(sd);
@@ -4820,7 +5399,7 @@ void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, in
WFIFOW(fd, 6) = skill->get_sp(skill_id, skill_lv);
WFIFOW(fd, 8) = (flag)?skill->get_range2(&sd->bl, skill_id, skill_lv) : skill->get_range(skill_id, skill_lv);
if( flag )
- WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_)) ? 1 : 0;
+ WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class)) ? 1 : 0;
else
WFIFOB(fd,10) = 1;
@@ -4829,34 +5408,36 @@ void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, in
/// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE2).
/// 07e1 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <upgradable>.B
-void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf)
+static void clif_skillinfo(struct map_session_data *sd, int skill_id, int inf)
{
- const int fd = sd->fd;
- int idx = skill->get_index(skill_id);
- int skill_lv;
-
nullpo_retv(sd);
- Assert_retv(idx >= 0 && idx < MAX_SKILL);
- skill_lv = sd->status.skill[idx].lv;
-
- WFIFOHEAD(fd,packet_len(0x7e1));
- WFIFOW(fd,0) = 0x7e1;
- WFIFOW(fd,2) = skill_id;
- WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id);
- WFIFOW(fd,8) = skill_lv;
+ const int fd = sd->fd;
+ int idx = skill->get_index(skill_id);
+ Assert_retv(idx >= 0 && idx < MAX_SKILL_DB);
+
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_SKILLINFO_UPDATE2));
+ struct PACKET_ZC_SKILLINFO_UPDATE2 *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_SKILLINFO_UPDATE2;
+ int skill_lv = sd->status.skill[idx].lv;
+ p->id = skill_id;
+ p->inf = skill->get_inf(skill_id);
+ p->level = skill_lv;
if (skill_lv > 0) {
- WFIFOW(fd,10) = skill->get_sp(skill_id, skill_lv);
- WFIFOW(fd,12) = skill->get_range2(&sd->bl, skill_id, skill_lv);
+ p->sp = skill->get_sp(skill_id, skill_lv);
+ p->range2 = skill->get_range2(&sd->bl, skill_id, skill_lv);
} else {
- WFIFOW(fd,10) = 0;
- WFIFOW(fd,12) = 0;
+ p->sp = 0;
+ p->range2 = 0;
}
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+ p->level2 = skill_lv;
+#endif
if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
- WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0;
+ p->upFlag = (skill_lv < skill->tree_get_max(skill_id, sd->status.class)) ? 1 : 0;
else
- WFIFOB(fd,14) = 0;
- WFIFOSET(fd,packet_len(0x7e1));
+ p->upFlag = 0;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_SKILLINFO_UPDATE2));
}
/// Notifies clients in area, that an object is about to use a skill.
@@ -4874,38 +5455,43 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf)
/// is disposable:
/// 0 = yellow chat text "[src name] will use skill [skill name]."
/// 1 = no text
-void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime)
+static void clif_useskill(struct block_list *bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int casttime)
{
-#if PACKETVER < 20091124
- const int cmd = 0x13e;
-#else
- const int cmd = 0x7fb;
+ nullpo_retv(bl);
+
+ const int element = skill->get_ele(skill_id, skill_lv);
+ struct PACKET_ZC_USESKILL_ACK p;
+ p.packetType = HEADER_ZC_USESKILL_ACK;
+ p.srcId = src_id;
+ p.dstId = dst_id;
+ p.x = dst_x;
+ p.y = dst_y;
+ p.skillId = skill_id;
+ p.element = element < 0 ? 0 : element; //Avoid sending negatives as element [Skotlex]
+ p.delayTime = casttime;
+#if PACKETVER_MAIN_NUM >= 20091124 || PACKETVER_RE_NUM >= 20091124 || defined(PACKETVER_ZERO)
+ p.disposable = 0;
+#endif
+#if PACKETVER_MAIN_NUM >= 20181212 || PACKETVER_RE_NUM >= 20181212 || PACKETVER_ZERO_NUM >= 20190130
+ p.unknown = 0;
#endif
- unsigned char buf[32];
- WBUFW(buf,0) = cmd;
- WBUFL(buf,2) = src_id;
- WBUFL(buf,6) = dst_id;
- WBUFW(buf,10) = dst_x;
- WBUFW(buf,12) = dst_y;
- WBUFW(buf,14) = skill_id;
- WBUFL(buf,16) = property<0?0:property; //Avoid sending negatives as element [Skotlex]
- WBUFL(buf,20) = casttime;
-#if PACKETVER >= 20091124
- WBUFB(buf,24) = 0; // isDisposable
-#endif
-
- if (disguised(bl)) {
- clif->send(buf,packet_len(cmd), bl, AREA_WOS);
- WBUFL(buf,2) = -src_id;
- clif->send(buf,packet_len(cmd), bl, SELF);
- } else
- clif->send(buf,packet_len(cmd), bl, AREA);
+ if (clif->isdisguised(bl)) {
+ clif->send(&p, sizeof(p), bl, AREA_WOS);
+ p.srcId = -src_id;
+ clif->send(&p, sizeof(p), bl, SELF);
+ } else {
+ clif->send(&p, sizeof(p), bl, AREA);
+ }
+#if PACKETVER >= 20151223
+ if ((skill->get_inf2(skill_id) & INF2_SHOW_SKILL_SCALE) != 0)
+ clif->skill_scale(bl, src_id, bl->x, bl->y, skill_id, skill_lv, casttime);
+#endif
}
/// Notifies clients in area, that an object canceled casting (ZC_DISPEL).
/// 01b9 <id>.L
-void clif_skillcastcancel(struct block_list* bl)
+static void clif_skillcastcancel(struct block_list *bl)
{
unsigned char buf[16];
@@ -4939,9 +5525,10 @@ void clif_skillcastcancel(struct block_list* bl)
/// if(result!=0) doesn't display any of the previous messages
/// Note: when this packet is received an unknown flag is always set to 0,
/// suggesting this is an ACK packet for the UseSkill packets and should be sent on success too [FlavioJS]
-void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype)
+static void clif_skill_fail(struct map_session_data *sd, uint16 skill_id, enum useskill_fail_cause cause, int btype, int32 item_id)
{
int fd;
+ struct PACKET_ZC_ACK_TOUSESKILL p;
if (!sd) {
//Since this is the most common nullpo....
@@ -4949,33 +5536,36 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f
return;
}
- fd=sd->fd;
+ fd = sd->fd;
if (!fd) return;
- if(battle_config.display_skill_fail&1)
+ if (battle_config.display_skill_fail&1)
return; //Disable all skill failed messages
- if(cause==USESKILL_FAIL_SKILLINTERVAL && !sd->state.showdelay)
+ if (cause == USESKILL_FAIL_SKILLINTERVAL && !sd->state.showdelay)
return; //Disable delay failed messages
- if(skill_id == RG_SNATCHER && battle_config.display_skill_fail&4)
+ if (skill_id == RG_SNATCHER && battle_config.display_skill_fail & 4)
return;
- if(skill_id == TF_POISON && battle_config.display_skill_fail&8)
+ if (skill_id == TF_POISON && battle_config.display_skill_fail & 8)
return;
- WFIFOHEAD(fd,packet_len(0x110));
- WFIFOW(fd,0) = 0x110;
- WFIFOW(fd,2) = skill_id;
- WFIFOL(fd,4) = btype;
- WFIFOB(fd,8) = 0;// success
- WFIFOB(fd,9) = cause;
- WFIFOSET(fd,packet_len(0x110));
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x110;
+ p.skillId = skill_id;
+ p.btype = btype;
+ p.itemId = item_id;
+ p.flag = 0; // 0 - failed
+ p.cause = cause;
+
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Skill cooldown display icon (ZC_SKILL_POSTDELAY).
/// 043d <skill ID>.W <tick>.L
-void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration)
+static void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration)
{
#if PACKETVER>=20081112
int fd;
@@ -4994,7 +5584,8 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned
/// Skill attack effect and damage.
/// 0114 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.W <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL)
/// 01de <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.L <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL2)
-int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, uint16 skill_id, uint16 skill_lv, int type) {
+static int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, uint16 skill_id, uint16 skill_lv, enum battle_dmg_type type)
+{
unsigned char buf[64];
struct status_change *sc;
int damage;
@@ -5030,16 +5621,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
WBUFW(buf, 26) = skill_lv;
WBUFW(buf, 28) = div;
WBUFB(buf, 30) = type;
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(buf, packet_len(0x114), dst, AREA_WOS);
WBUFL(buf, 8) = -dst->id;
clif->send(buf, packet_len(0x114), dst, SELF);
- } else
+ } else {
clif->send(buf, packet_len(0x114), dst, AREA);
+ }
- if (disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf, 4) = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
WBUFL(buf, 8) = dst->id;
if (damage > 0)
WBUFW(buf, 24) = -1;
@@ -5069,16 +5661,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
#else
WBUFB(buf, 32) = (type == BDT_SKILL) ? BDT_MULTIHIT : type;
#endif
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(buf, packet_len(0x1de), dst, AREA_WOS);
WBUFL(buf,8)=-dst->id;
clif->send(buf, packet_len(0x1de), dst, SELF);
- } else
+ } else {
clif->send(buf, packet_len(0x1de), dst, AREA);
+ }
- if (disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf, 4) = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
WBUFL(buf, 8) = dst->id;
if (damage > 0)
WBUFL(buf, 24) = -1;
@@ -5093,7 +5686,8 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
/// Ground skill attack effect and damage (ZC_NOTIFY_SKILL_POSITION).
/// 0115 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <x>.W <y>.W <damage>.W <level>.W <div>.W <type>.B
#if 0
-int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int damage, int div, uint16 skill_id, uint16 skill_lv, int type) {
+static int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int damage, int div, uint16 skill_id, uint16 skill_lv, enum battle_dmg_type type)
+{
unsigned char buf[64];
struct status_change *sc;
@@ -5127,15 +5721,15 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic
WBUFW(buf,32)=div;
WBUFB(buf,34)=type;
clif->send(buf,packet_len(0x115),src,AREA);
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf,4)=-src->id;
if(damage > 0)
WBUFW(buf,28)=-1;
clif->send(buf,packet_len(0x115),src,SELF);
}
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
WBUFL(buf,8)=-dst->id;
- if (disguised(src))
+ if (clif->isdisguised(src))
WBUFL(buf,4)=src->id;
else if(damage > 0)
WBUFW(buf,28)=-1;
@@ -5147,33 +5741,46 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic
}
#endif // 0
-/// Non-damaging skill effect (ZC_USE_SKILL).
-/// 011a <skill id>.W <skill lv>.W <dst id>.L <src id>.L <result>.B
-int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail)
+/// Non-damaging skill effect.
+/// 011a <skill id>.W <skill lv>.W <dst id>.L <src id>.L <result>.B (ZC_USE_SKILL)
+/// 09cb <skill id>.W <skill lv>.L <dst id>.L <src id>.L <result>.B (ZC_USE_SKILL2)
+static int clif_skill_nodamage(struct block_list *src, struct block_list *dst, uint16 skill_id, int heal, int fail)
{
unsigned char buf[32];
+ short offset = 0;
+#if PACKETVER < 20131223
+ short cmd = 0x11a;
+#else
+ short cmd = 0x9cb;
+#endif
+ int len = packet_len(cmd);
nullpo_ret(dst);
- WBUFW(buf,0)=0x11a;
- WBUFW(buf,2)=skill_id;
- WBUFW(buf,4)=min(heal, INT16_MAX);
- WBUFL(buf,6)=dst->id;
- WBUFL(buf,10)=src?src->id:0;
- WBUFB(buf,14)=fail;
-
- if (disguised(dst)) {
- clif->send(buf,packet_len(0x11a),dst,AREA_WOS);
- WBUFL(buf,6)=-dst->id;
- clif->send(buf,packet_len(0x11a),dst,SELF);
+ WBUFW(buf, 0) = cmd;
+ WBUFW(buf, 2) = skill_id;
+#if PACKETVER < 20131223
+ WBUFW(buf, 4) = min(heal, INT16_MAX);
+#else
+ WBUFL(buf, 4) = min(heal, INT_MAX);
+ offset += 2;
+#endif
+ WBUFL(buf, 6 + offset) = dst->id;
+ WBUFL(buf, 10 + offset) = src ? src->id : 0;
+ WBUFB(buf, 14 + offset) = fail;
+
+ if (clif->isdisguised(dst)) {
+ clif->send(buf, len, dst, AREA_WOS);
+ WBUFL(buf, 6 + offset) = -dst->id;
+ clif->send(buf, len, dst, SELF);
} else
- clif->send(buf,packet_len(0x11a),dst,AREA);
+ clif->send(buf, len, dst, AREA);
- if(src && disguised(src)) {
- WBUFL(buf,10)=-src->id;
- if (disguised(dst))
- WBUFL(buf,6)=dst->id;
- clif->send(buf,packet_len(0x11a),src,SELF);
+ if (src && clif->isdisguised(src)) {
+ WBUFL(buf, 10 + offset) = -src->id;
+ if (clif->isdisguised(dst))
+ WBUFL(buf, 6 + offset) = dst->id;
+ clif->send(buf, len, src, SELF);
}
return fail;
@@ -5181,7 +5788,8 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski
/// Non-damaging ground skill effect (ZC_NOTIFY_GROUNDSKILL).
/// 0117 <skill id>.W <src id>.L <level>.W <x>.W <y>.W <tick>.L
-void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick) {
+static void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick)
+{
unsigned char buf[32];
nullpo_retv(src);
@@ -5193,41 +5801,60 @@ void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int
WBUFW(buf,10)=x;
WBUFW(buf,12)=y;
WBUFL(buf,14)=(uint32)tick;
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
clif->send(buf,packet_len(0x117),src,AREA_WOS);
WBUFL(buf,4)=-src->id;
clif->send(buf,packet_len(0x117),src,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x117),src,AREA);
+ }
}
/// Presents a list of available warp destinations (ZC_WARPLIST).
/// 011c <skill id>.W { <map name>.16B }*4
-void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4)
+static void clif_skill_warppoint(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4)
{
int fd;
+ int len;
+ int mapsCount = 0;
+ struct PACKET_ZC_WARPLIST *p;
nullpo_retv(sd);
fd = sd->fd;
+#if PACKETVER_MAIN_NUM >= 20170502 || PACKETVER_RE_NUM >= 20170419 || defined(PACKETVER_ZERO)
+ len = sizeof(struct PACKET_ZC_WARPLIST) + sizeof(struct PACKET_ZC_WARPLIST_sub) * 6;
+#else
+ len = sizeof(struct PACKET_ZC_WARPLIST);
+#endif
- WFIFOHEAD(fd,packet_len(0x11c));
- WFIFOW(fd,0) = 0x11c;
- WFIFOW(fd,2) = skill_id;
- memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT);
- if (map1 == (unsigned short)-1) strcpy(WFIFOP(fd,4), "Random");
- else // normal map name
- if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), WFIFOP(fd,4));
- if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), WFIFOP(fd,20));
- if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), WFIFOP(fd,36));
- if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), WFIFOP(fd,52));
- WFIFOSET(fd,packet_len(0x11c));
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ memset(p, 0, len);
+ p->packetType = skilWarpPointType;
+ p->skillId = skill_id;
+ if (map1 == (unsigned short)-1) {
+ strcpy(p->maps[mapsCount++].map, "Random");
+ } else { // normal map name
+ if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), p->maps[mapsCount++].map);
+ }
+ if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), p->maps[mapsCount++].map);
+ if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), p->maps[mapsCount++].map);
+ if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), p->maps[mapsCount++].map);
+
+#if PACKETVER_MAIN_NUM >= 20170502 || PACKETVER_RE_NUM >= 20170419 || defined(PACKETVER_ZERO)
+ len = sizeof(struct PACKET_ZC_WARPLIST) + sizeof(struct PACKET_ZC_WARPLIST_sub) * mapsCount;
+ p->packetLength = len;
+#endif
+
+ WFIFOSET(fd, len);
sd->menuskill_id = skill_id;
- if (skill_id == AL_WARP){
- sd->menuskill_val = (sd->ud.skillx<<16)|sd->ud.skilly; //Store warp position here.
+ if (skill_id == AL_WARP) {
+ sd->menuskill_val = (sd->ud.skillx << 16) | sd->ud.skilly; //Store warp position here.
sd->state.workinprogress = 3;
- }else
+ } else {
sd->menuskill_val = skill_lv;
+ }
}
/// Memo message (ZC_ACK_REMEMBER_WARPPOINT).
@@ -5236,10 +5863,11 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s
/// 0 = "Saved location as a Memo Point for Warp skill." in color 0xFFFF00 (cyan)
/// 1 = "Skill Level is not high enough." in color 0x0000FF (red)
/// 2 = "You haven't learned Warp." in color 0x0000FF (red)
+/// 3 = "Cannot save location as a Memo Point at current location." in color 0x0000FF (red)
///
/// @param sd Who receives the message
/// @param type What message
-void clif_skill_memomessage(struct map_session_data* sd, int type)
+static void clif_skill_memomessage(struct map_session_data *sd, int type)
{
int fd;
@@ -5258,10 +5886,11 @@ void clif_skill_memomessage(struct map_session_data* sd, int type)
/// 0 = "Unable to Teleport in this area" in color 0xFFFF00 (cyan)
/// 1 = "Saved point cannot be memorized." in color 0x0000FF (red)
/// 2 = "This skill cannot be used within this area." in color 0xFFFF00 (cyan)
+/// 3 = "This item cannot be used within this area." in color 0xFFFF00 (cyan)
///
/// @param sd Who receives the message
/// @param type What message
-void clif_skill_mapinfomessage(struct map_session_data *sd, int type)
+static void clif_skill_mapinfomessage(struct map_session_data *sd, int type)
{
int fd;
@@ -5277,10 +5906,11 @@ void clif_skill_mapinfomessage(struct map_session_data *sd, int type)
/// Displays Sense (WZ_ESTIMATION) information window (ZC_MONSTER_INFO).
/// 018c <class>.W <level>.W <size>.W <hp>.L <def>.W <race>.W <mdef>.W <element>.W
/// <water%>.B <earth%>.B <fire%>.B <wind%>.B <poison%>.B <holy%>.B <shadow%>.B <ghost%>.B <undead%>.B
-void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) {
+static void clif_skill_estimation(struct map_session_data *sd, struct block_list *dst)
+{
struct status_data *dstatus;
unsigned char buf[64];
- int i;//, fix;
+ int i, fix;
nullpo_retv(sd);
nullpo_retv(dst);
@@ -5302,9 +5932,9 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) {
+ ((battle_config.estimation_type&2) ? dstatus->mdef2 : 0);
WBUFW(buf,18) = dstatus->def_ele;
for(i=0;i<9;i++) {
- WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv);
+ // WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv);
// The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex]
- //WBUFB(buf,20+i)= (unsigned char)((fix=battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv))<0?0:fix);
+ WBUFB(buf,20+i)= (unsigned char)((fix=battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv))<0?0:fix);
}
clif->send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF);
@@ -5314,37 +5944,42 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) {
/// 018d <packet len>.W { <name id>.W { <material id>.W }*3 }*
/// material id:
/// unused by the client
-void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int trigger)
+static void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id, int trigger)
{
- int i,c,view,fd;
+ int i, c, view, fd;
+ int len;
+ struct PACKET_ZC_MAKABLEITEMLIST *p;
+
nullpo_retv(sd);
- if(sd->menuskill_id == skill_id)
+ if (sd->menuskill_id == skill_id)
return; //Avoid resending the menu twice or more times...
- if( skill_id == GC_CREATENEWPOISON )
+ if (skill_id == GC_CREATENEWPOISON)
skill_id = GC_RESEARCHNEWPOISON;
- fd=sd->fd;
- WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB * 8 + 8);
- WFIFOW(fd, 0)=0x18d;
-
- for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid, trigger, 1) &&
- ( ( skill_id > 0 && skill->dbs->produce_db[i].req_skill == skill_id ) || skill_id < 0 )
- ){
- if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
- WFIFOW(fd,c*8+ 4)= view;
+ fd = sd->fd;
+ len = MAX_SKILL_PRODUCE_DB * sizeof(struct PACKET_ZC_MAKABLEITEMLIST_sub) + sizeof(struct PACKET_ZC_MAKABLEITEMLIST);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x18d;
+
+ for (i = 0, c = 0; i < MAX_SKILL_PRODUCE_DB; i++) {
+ if (skill->can_produce_mix(sd, skill->dbs->produce_db[i].nameid, trigger, 1) &&
+ ((skill_id > 0 && skill->dbs->produce_db[i].req_skill == skill_id) || skill_id < 0)) {
+ if ((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
+ p->items[c].itemId = view;
else
- WFIFOW(fd,c*8+ 4)= skill->dbs->produce_db[i].nameid;
- WFIFOW(fd,c*8+ 6)= 0;
- WFIFOW(fd,c*8+ 8)= 0;
- WFIFOW(fd,c*8+10)= 0;
+ p->items[c].itemId = skill->dbs->produce_db[i].nameid;
+ p->items[c].material[0] = 0;
+ p->items[c].material[1] = 0;
+ p->items[c].material[2] = 0;
c++;
}
}
- WFIFOW(fd, 2)=c*8+8;
- WFIFOSET(fd,WFIFOW(fd,2));
- if(c > 0) {
+ len = c * sizeof(struct PACKET_ZC_MAKABLEITEMLIST_sub) + sizeof(struct PACKET_ZC_MAKABLEITEMLIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
+ if (c > 0) {
sd->menuskill_id = skill_id;
sd->menuskill_val = trigger;
return;
@@ -5360,61 +5995,65 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
-void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type)
+static void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type)
{
int fd;
int i, c;
int view;
+ int len;
+ struct PACKET_ZC_MAKINGITEM_LIST *p;
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB);
- WFIFOW(fd,0) = 0x25a;
- WFIFOW(fd,4) = list_type; // list type
+ len = sizeof(struct PACKET_ZC_MAKINGITEM_LIST) + MAX_SKILL_PRODUCE_DB * sizeof(struct PACKET_ZC_MAKINGITEM_LIST_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGITEM_LIST;
+ p->makeItem = list_type; // list type
c = 0;
- for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
- if( !skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,trigger, qty) )
+ for (i = 0; i < MAX_SKILL_PRODUCE_DB; i++) {
+ if (!skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,trigger, qty))
continue;
- if( (view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0 )
- WFIFOW(fd, 6 + 2 * c) = view;
+ if ((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
+ p->items[c].itemId = view;
else
- WFIFOW(fd, 6 + 2 * c) = skill->dbs->produce_db[i].nameid;
+ p->items[c].itemId = skill->dbs->produce_db[i].nameid;
c++;
}
- if( skill_id == AM_PHARMACY ) {
+ len = sizeof(struct PACKET_ZC_MAKINGITEM_LIST) + c * sizeof(struct PACKET_ZC_MAKINGITEM_LIST_sub);
+ p->packetLength = len;
+ if (skill_id == AM_PHARMACY) {
// Only send it while Cooking else check for c.
- WFIFOW(fd,2) = 6 + 2 * c;
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
- if( c > 0 ) {
+ if (c > 0) {
sd->menuskill_id = skill_id;
sd->menuskill_val = trigger;
- if( skill_id != AM_PHARMACY ) {
+ if (skill_id != AM_PHARMACY) {
sd->menuskill_val2 = qty; // amount.
- WFIFOW(fd,2) = 6 + 2 * c;
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
} else {
clif_menuskill_clear(sd);
- if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking.
+ if (skill_id != AM_PHARMACY) { // AM_PHARMACY is used to Cooking.
// It fails.
-#if PACKETVER >= 20090922
- clif->msgtable_skill(sd, skill_id, MSG_COOKING_LIST_FAIL);
+#if PACKETVER >= 20091013
+ clif->msgtable_skill(sd, skill_id, MSG_SKILL_MATERIAL_FAIL);
#else
- WFIFOW(fd,2) = 6 + 2 * c;
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
#endif
}
}
}
-void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) {
+static void clif_status_change_notick(struct block_list *bl, int type, int relevant_bl, int flag, int tick, int total_tick, int val1, int val2, int val3)
+{
struct packet_sc_notick p;
struct map_session_data *sd;
@@ -5423,7 +6062,7 @@ void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,
if (type == SI_BLANK) //It shows nothing on the client...
return;
- if (!(status->type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
+ if (!(relevant_bl & bl->type)) // only send status changes that actually matter to the client
return;
sd = BL_CAST(BL_PC, bl);
@@ -5442,7 +6081,8 @@ void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,
/// 08ff <id>.L <index>.W <remain msec>.L { <val>.L }*3 (PACKETVER >= 20111108)
/// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618)
/// 0984 <id>.L <index>.W <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618)
-void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) {
+static void clif_status_change_sub(struct block_list *bl, int type, int relevant_bl, int flag, int tick, int total_tick, int val1, int val2, int val3)
+{
struct packet_status_change p;
struct map_session_data *sd;
@@ -5451,7 +6091,7 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
nullpo_retv(bl);
- if (!(status->type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
+ if (!(relevant_bl & bl->type)) // only send status changes that actually matter to the client
return;
if ( tick < 0 )
@@ -5465,7 +6105,7 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
p.state = (unsigned char)flag;
#if PACKETVER >= 20120618
- p.Total = tick; /* at this stage remain and total are the same value I believe */
+ p.Total = total_tick;
#endif
#if PACKETVER >= 20090121
p.Left = tick;
@@ -5476,25 +6116,33 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
clif->send(&p,sizeof(p), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA);
}
+/// Notifies clients of a status change.
+/// @see clif_status_change_sub
+static void clif_status_change(struct block_list *bl, int type, int relevant_bl, int flag, int total_tick, int val1, int val2, int val3)
+{
+ clif->status_change_sub(bl, type, relevant_bl, flag, total_tick, total_tick, val1, val2, val3);
+}
+
/// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT).
/// 008e <packet len>.W <message>.?B
-void clif_displaymessage(const int fd, const char* mes) {
+static void clif_displaymessage(const int fd, const char *mes)
+{
nullpo_retv(mes);
- if( map->cpsd_active && fd == 0 ) {
+ if (map->cpsd_active && fd == 0) {
ShowInfo("HCP: %s\n",mes);
- } else if ( fd > 0 ) {
+ } else if (fd > 0) {
#if PACKETVER == 20141022
/** for some reason game client crashes depending on message pattern (only for this packet) **/
/** so we redirect to ZC_NPC_CHAT **/
clif->messagecolor_self(fd, COLOR_DEFAULT, mes);
#else
- size_t len;
+ int len = (int)strnlen(mes, 255);
- 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.
+ if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
WFIFOHEAD(fd, 5 + len);
WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NUL terminate
safestrncpy(WFIFOP(fd,4), mes, len + 1);
WFIFOSET(fd, 5 + len);
}
@@ -5502,7 +6150,8 @@ void clif_displaymessage(const int fd, const char* mes) {
}
}
-void clif_displaymessage2(const int fd, const char* mes) {
+static void clif_displaymessage2(const int fd, const char *mes)
+{
nullpo_retv(mes);
//Scrapped, as these are shared by disconnected players =X [Skotlex]
@@ -5516,7 +6165,7 @@ void clif_displaymessage2(const int fd, const char* mes) {
line = strtok(message, "\n");
while(line != NULL) {
// Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client)
- size_t len = strnlen(line, 255);
+ int len = (int)strnlen(line, 255);
if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
if( map->cpsd_active && fd == 0 ) {
@@ -5534,9 +6183,11 @@ void clif_displaymessage2(const int fd, const char* mes) {
aFree(message);
}
}
+
/* oh noo! another version of 0x8e! */
-void clif_displaymessage_sprintf(const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3)));
-void clif_displaymessage_sprintf(const int fd, const char *mes, ...) {
+static void clif_displaymessage_sprintf(const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3)));
+static void clif_displaymessage_sprintf(const int fd, const char *mes, ...)
+{
va_list ap;
nullpo_retv(mes);
@@ -5568,9 +6219,10 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) {
WFIFOSET(fd, 5 + len);
}
}
+
/// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST).
/// 009a <packet len>.W <message>.?B
-void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type, enum send_target target)
+static void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target)
{
int lp = (type&BC_COLOR_MASK) ? 4 : 0;
unsigned char *buf = NULL;
@@ -5594,38 +6246,38 @@ void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type
* Displays a message on a 'bl' to all it's nearby clients
* Used by npc_globalmessage
*------------------------------------------*/
-void clif_GlobalMessage(struct block_list* bl, const char* message) {
+static void clif_GlobalMessage(struct block_list *bl, const char *message)
+{
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8d;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8d;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
-
+ clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT);
}
/// Send broadcast message with font formatting (ZC_BROADCAST2).
/// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
-void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
+static void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
{
unsigned char *buf;
nullpo_retv(mes);
- buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char));
+ buf = aMalloc((16 + len)*sizeof(unsigned char));
WBUFW(buf,0) = 0x1c3;
WBUFW(buf,2) = len + 16;
WBUFL(buf,4) = fontColor;
@@ -5645,20 +6297,31 @@ void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigne
/// 5 = HP (SP_HP)
/// 7 = SP (SP_SP)
/// ? = ignored
-void clif_heal(int fd,int type,int val)
+static void clif_heal(int fd, int type, int val)
{
- WFIFOHEAD(fd,packet_len(0x13d));
- WFIFOW(fd,0)=0x13d;
- WFIFOW(fd,2)=type;
- WFIFOW(fd,4)=cap_value(val,0,INT16_MAX);
- WFIFOSET(fd,packet_len(0x13d));
+#if PACKETVER < 20150513
+ short cmd = 0x13d;
+#else
+ short cmd = 0xa27;
+#endif
+ int len = packet_len(cmd);
+
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = cmd;
+ WFIFOW(fd, 2) = type;
+#if PACKETVER < 20150513
+ WFIFOW(fd, 4) = cap_value(val, 0, INT16_MAX);
+#else
+ WFIFOL(fd, 4) = cap_value(val, 0, INT_MAX);
+#endif
+ WFIFOSET(fd, len);
}
/// Displays resurrection effect (ZC_RESURRECTION).
/// 0148 <id>.L <type>.W
/// type:
/// ignored
-void clif_resurrection(struct block_list *bl,int type)
+static void clif_resurrection(struct block_list *bl, int type)
{
unsigned char buf[16];
@@ -5669,7 +6332,7 @@ void clif_resurrection(struct block_list *bl,int type)
WBUFW(buf,6)=0;
clif->send(buf,packet_len(0x148),bl, type == 1 ? AREA : AREA_WOS);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
if (sd->fontcolor) {
WBUFL(buf,2)=-bl->id;
@@ -5682,7 +6345,7 @@ void clif_resurrection(struct block_list *bl,int type)
/// Sets the map property (ZC_NOTIFY_MAPPROPERTY).
/// 0199 <type>.W
-void clif_map_property(struct map_session_data* sd, enum map_property property)
+static void clif_map_property(struct map_session_data *sd, enum map_property property)
{
int fd;
@@ -5697,7 +6360,8 @@ void clif_map_property(struct map_session_data* sd, enum map_property property)
/// Set the map type (ZC_NOTIFY_MAPPROPERTY2).
/// 01d6 <type>.W
-void clif_map_type(struct map_session_data* sd, enum map_type type) {
+static void clif_map_type(struct map_session_data *sd, enum map_type type)
+{
int fd;
nullpo_retv(sd);
@@ -5712,7 +6376,7 @@ void clif_map_type(struct map_session_data* sd, enum map_type type) {
/// Updates PvP ranking (ZC_NOTIFY_RANKING).
/// 019a <id>.L <ranking>.L <total>.L
// FIXME: missing documentation for the 'type' parameter
-void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
+static void clif_pvpset(struct map_session_data *sd, int pvprank, int pvpnum, int type)
{
nullpo_retv(sd);
@@ -5745,11 +6409,12 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
/*==========================================
*
*------------------------------------------*/
-void clif_map_property_mapall(int mapid, enum map_property property)
+static void clif_map_property_mapall(int mapid, enum map_property property)
{
struct block_list bl;
unsigned char buf[16];
+ memset(&bl, 0, sizeof(bl));
bl.id = 0;
bl.type = BL_NUL;
bl.m = mapid;
@@ -5764,7 +6429,7 @@ void clif_map_property_mapall(int mapid, enum map_property property)
/// 0 = success
/// 1 = failure
/// 2 = downgrade
-void clif_refine(int fd, int fail, int index, int val)
+static void clif_refine(int fd, int fail, int index, int val)
{
WFIFOHEAD(fd,packet_len(0x188));
WFIFOW(fd,0)=0x188;
@@ -5781,19 +6446,21 @@ void clif_refine(int fd, int fail, int index, int val)
/// 1 = "weapon upgraded: %s" MsgStringTable[912] in rgb(0,205,205)
/// 2 = "cannot upgrade %s until you level up the upgrade weapon skill" MsgStringTable[913] in rgb(255,200,200)
/// 3 = "you lack the item %s to upgrade the weapon" MsgStringTable[914] in rgb(255,200,200)
-void clif_upgrademessage(int fd, int result, int item_id)
+static void clif_upgrademessage(int fd, int result, int item_id)
{
- WFIFOHEAD(fd,packet_len(0x223));
- WFIFOW(fd,0)=0x223;
- WFIFOL(fd,2)=result;
- WFIFOW(fd,6)=item_id;
- WFIFOSET(fd,packet_len(0x223));
+ struct PACKET_ZC_ACK_WEAPONREFINE p;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x223;
+ p.result = result;
+ p.itemId = item_id;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Whisper is transmitted to the destination player (ZC_WHISPER).
/// 0097 <packet len>.W <nick>.24B <message>.?B
/// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104)
-void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
+static void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len)
{
#if PACKETVER >= 20091104
struct map_session_data *ssd = NULL;
@@ -5802,21 +6469,21 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
nullpo_retv(mes);
#if PACKETVER < 20091104
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 5);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 5;
safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH);
- safestrncpy(WFIFOP(fd,28), mes, mes_len);
+ safestrncpy(WFIFOP(fd,28), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#else
- ssd = map->nick2sd(nick);
+ ssd = map->nick2sd(nick, false);
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 9);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 9;
safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH);
WFIFOL(fd,28) = (ssd && pc_get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char
- safestrncpy(WFIFOP(fd,32), mes, mes_len);
+ safestrncpy(WFIFOP(fd,32), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#endif
}
@@ -5828,7 +6495,9 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
/// 1 = target character is not logged in
/// 2 = ignored by target
/// 3 = everyone ignored by target
-void clif_wis_end(int fd, int flag) {
+/// other = target character is not logged in
+static void clif_wis_end(int fd, int flag)
+{
struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL;
struct packet_wis_end p;
@@ -5838,7 +6507,7 @@ void clif_wis_end(int fd, int flag) {
p.PacketType = wisendType;
p.result = (char)flag;
#if PACKETVER >= 20131223
- p.unknown = 0;
+ p.AID = sd->bl.id;
#endif
clif->send(&p, sizeof(p), &sd->bl, SELF);
@@ -5846,19 +6515,34 @@ void clif_wis_end(int fd, int flag) {
/// Returns character name requested by char_id (ZC_ACK_REQNAME_BYGID).
/// 0194 <char id>.L <name>.24B
-void clif_solved_charname(int fd, int charid, const char* name)
+/// 0af7 <flag>.W <char id>.L <name>.24B
+static void clif_solved_charname(int fd, int charid, const char *name)
{
nullpo_retv(name);
- WFIFOHEAD(fd,packet_len(0x194));
- WFIFOW(fd,0)=0x194;
- WFIFOL(fd,2)=charid;
- safestrncpy(WFIFOP(fd,6), name, NAME_LENGTH);
- WFIFOSET(fd,packet_len(0x194));
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221 || PACKETVER_ZERO_NUM >= 20180328
+ WFIFOHEAD(fd, packet_len(0x0af7));
+ WFIFOW(fd, 0) = 0xaf7;
+ if (*name == 0) {
+ WFIFOW(fd, 2) = 2;
+ memset(WFIFOP(fd, 8), 0, NAME_LENGTH);
+ } else {
+ WFIFOW(fd, 2) = 3;
+ safestrncpy(WFIFOP(fd, 8), name, NAME_LENGTH);
+ }
+ WFIFOL(fd, 4) = charid;
+ WFIFOSET(fd, packet_len(0x0af7));
+#else
+ WFIFOHEAD(fd, packet_len(0x194));
+ WFIFOW(fd, 0) = 0x194;
+ WFIFOL(fd, 2) = charid;
+ safestrncpy(WFIFOP(fd, 6), name, NAME_LENGTH);
+ WFIFOSET(fd, packet_len(0x194));
+#endif
}
/// Presents a list of items that can be carded/composed (ZC_ITEMCOMPOSITION_LIST).
-/// 017b <packet len>.W { <name id>.W }*
-void clif_use_card(struct map_session_data *sd,int idx)
+/// 017b <packet len>.W { <index>.W }*
+static void clif_use_card(struct map_session_data *sd, int idx)
{
int i, c;
int fd;
@@ -5870,10 +6554,10 @@ void clif_use_card(struct map_session_data *sd,int idx)
if (!pc->can_insert_card(sd, idx))
return;
- WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4);
+ WFIFOHEAD(fd, sd->status.inventorySize * 2 + 4);
WFIFOW(fd, 0) = 0x17b;
- for (i = c = 0; i < MAX_INVENTORY; i++) {
+ for (i = c = 0; i < sd->status.inventorySize; i++) {
if (!pc->can_insert_card_into(sd, idx, i))
continue;
WFIFOW(fd, 4 + c * 2) = i + 2;
@@ -5891,7 +6575,7 @@ void clif_use_card(struct map_session_data *sd,int idx)
/// result:
/// 0 = success
/// 1 = failure
-void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int flag)
+static void clif_insert_card(struct map_session_data *sd, int idx_equip, int idx_card, int flag)
{
int fd;
@@ -5907,8 +6591,8 @@ void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int
}
/// Presents a list of items that can be identified (ZC_ITEMIDENTIFY_LIST).
-/// 0177 <packet len>.W { <name id>.W }*
-void clif_item_identify_list(struct map_session_data *sd)
+/// 0177 <packet len>.W { <index>.W }*
+static void clif_item_identify_list(struct map_session_data *sd)
{
int i,c;
int fd;
@@ -5917,9 +6601,9 @@ void clif_item_identify_list(struct map_session_data *sd)
fd=sd->fd;
- WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4);
+ WFIFOHEAD(fd, sd->status.inventorySize * 2 + 4);
WFIFOW(fd,0)=0x177;
- for(i=c=0;i<MAX_INVENTORY;i++){
+ for (i = c = 0; i < sd->status.inventorySize; i++) {
if(sd->status.inventory[i].nameid > 0 && !sd->status.inventory[i].identify){
WFIFOW(fd,c*2+4)=i+2;
c++;
@@ -5936,7 +6620,7 @@ void clif_item_identify_list(struct map_session_data *sd)
/// Notifies the client about the result of a item identify request (ZC_ACK_ITEMIDENTIFY).
/// 0179 <index>.W <result>.B
-void clif_item_identified(struct map_session_data *sd,int idx,int flag)
+static void clif_item_identified(struct map_session_data *sd, int idx, int flag)
{
int fd;
@@ -5952,36 +6636,42 @@ void clif_item_identified(struct map_session_data *sd,int idx,int flag)
/// Presents a list of items that can be repaired (ZC_REPAIRITEMLIST).
/// 01fc <packet len>.W { <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }*
-void clif_item_repair_list(struct map_session_data *sd,struct map_session_data *dstsd, int lv)
+static void clif_item_repair_list(struct map_session_data *sd, struct map_session_data *dstsd, int lv)
{
int i,c;
int fd;
+ int len;
+ struct PACKET_ZC_REPAIRITEMLIST *p;
nullpo_retv(sd);
nullpo_retv(dstsd);
- fd=sd->fd;
+ fd = sd->fd;
- WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4);
- WFIFOW(fd,0)=0x1fc;
- for (i = c = 0; i < MAX_INVENTORY; i++) {
+ len = dstsd->status.inventorySize * sizeof(struct PACKET_ZC_REPAIRITEMLIST_sub) + sizeof(struct PACKET_ZC_REPAIRITEMLIST);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x1fc;
+ for (i = c = 0; i < sd->status.inventorySize; i++) {
int nameid = dstsd->status.inventory[i].nameid;
- if (nameid > 0 && dstsd->status.inventory[i].attribute != 0) { // && skill_can_repair(sd,nameid)) {
- WFIFOW(fd,c*13+4) = i;
- WFIFOW(fd,c*13+6) = nameid;
- WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine;
- clif->addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]);
+ if (nameid > 0 && (dstsd->status.inventory[i].attribute & ATTR_BROKEN) != 0) { // && skill_can_repair(sd,nameid)) {
+ p->items[c].index = i;
+ p->items[c].itemId = nameid;
+ p->items[c].refine = dstsd->status.inventory[i].refine;
+ clif->addcards(&p->items[c].slot, &dstsd->status.inventory[i]);
c++;
}
}
- if(c > 0) {
- WFIFOW(fd,2)=c*13+4;
- WFIFOSET(fd,WFIFOW(fd,2));
+ if (c > 0) {
+ len = c * sizeof(struct PACKET_ZC_REPAIRITEMLIST_sub) + sizeof(struct PACKET_ZC_REPAIRITEMLIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
sd->menuskill_id = BS_REPAIRWEAPON;
sd->menuskill_val = dstsd->bl.id;
sd->menuskill_val2 = lv;
- }else
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ } else {
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ }
}
/// Notifies the client about the result of a item repair request (ZC_ACK_ITEMREPAIR).
@@ -5991,7 +6681,7 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data *
/// result:
/// 0 = Item repair success.
/// 1 = Item repair failure.
-void clif_item_repaireffect(struct map_session_data *sd,int idx,int flag)
+static void clif_item_repaireffect(struct map_session_data *sd, int idx, int flag)
{
int fd;
@@ -6009,7 +6699,7 @@ void clif_item_repaireffect(struct map_session_data *sd,int idx,int flag)
/// Displays a message, that an equipment got damaged (ZC_EQUIPITEM_DAMAGED).
/// 02bb <equip location>.W <account id>.L
-void clif_item_damaged(struct map_session_data* sd, unsigned short position)
+static void clif_item_damaged(struct map_session_data *sd, unsigned short position)
{
int fd;
@@ -6025,34 +6715,38 @@ void clif_item_damaged(struct map_session_data* sd, unsigned short position)
/// Presents a list of weapon items that can be refined [Taken from jAthena] (ZC_NOTIFY_WEAPONITEMLIST).
/// 0221 <packet len>.W { <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }*
-void clif_item_refine_list(struct map_session_data *sd)
+static void clif_item_refine_list(struct map_session_data *sd)
{
int i,c;
int fd;
+ int len;
+ struct PACKET_ZC_NOTIFY_WEAPONITEMLIST *p;
uint16 skill_lv;
nullpo_retv(sd);
- skill_lv = pc->checkskill(sd,WS_WEAPONREFINE);
+ skill_lv = pc->checkskill(sd, WS_WEAPONREFINE);
- fd=sd->fd;
-
- 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
+ fd = sd->fd;
+ len = sd->status.inventorySize * sizeof(struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub) + sizeof(struct PACKET_ZC_NOTIFY_WEAPONITEMLIST);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x221;
+ for (i = c = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify
&& itemdb_wlv(sd->status.inventory[i].nameid) >= 1
&& !sd->inventory_data[i]->flag.no_refine
- && !(sd->status.inventory[i].equip&EQP_ARMS)){
- WFIFOW(fd,c*13+ 4)=i+2;
- WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid;
- WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine;
- clif->addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]);
+ && !(sd->status.inventory[i].equip & EQP_ARMS)) {
+ p->items[c].index = i + 2;
+ p->items[c].itemId = sd->status.inventory[i].nameid;
+ p->items[c].refine = sd->status.inventory[i].refine;
+ clif->addcards(&p->items[c].slot, &sd->status.inventory[i]);
c++;
}
}
- WFIFOW(fd,2)=c*13+4;
- WFIFOSET(fd,WFIFOW(fd,2));
+ len = c * sizeof(struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub) + sizeof(struct PACKET_ZC_NOTIFY_WEAPONITEMLIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
if (c > 0) {
sd->menuskill_id = WS_WEAPONREFINE;
sd->menuskill_val = skill_lv;
@@ -6061,67 +6755,71 @@ void clif_item_refine_list(struct map_session_data *sd)
/// Notification of an auto-casted skill (ZC_AUTORUN_SKILL).
/// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B
-void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv)
+static void clif_item_skill(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
{
- int fd;
-
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x147));
- WFIFOW(fd, 0)=0x147;
- WFIFOW(fd, 2)=skill_id;
- WFIFOW(fd, 4)=skill->get_inf(skill_id);
- WFIFOW(fd, 6)=0;
- WFIFOW(fd, 8)=skill_lv;
- WFIFOW(fd,10)=skill->get_sp(skill_id,skill_lv);
- WFIFOW(fd,12)=skill->get_range2(&sd->bl, skill_id,skill_lv);
- safestrncpy(WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH);
- WFIFOB(fd,38)=0;
- WFIFOSET(fd,packet_len(0x147));
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_AUTORUN_SKILL));
+
+ struct PACKET_ZC_AUTORUN_SKILL *p = WFIFOP(fd, 0);
+ int type = skill->get_inf(skill_id);
+
+ if (sd->autocast.itemskill_cast_on_self && sd->autocast.type == AUTOCAST_ITEM)
+ type = INF_SELF_SKILL;
+
+ p->packetType = HEADER_ZC_AUTORUN_SKILL;
+ p->skill_id = skill_id;
+ p->skill_type = type;
+ p->skill_lv = skill_lv;
+ p->skill_sp = skill->get_sp(skill_id, skill_lv);
+ p->skill_range = skill->get_range2(&sd->bl, skill_id, skill_lv);
+ safestrncpy(p->skill_name, skill->get_name(skill_id), NAME_LENGTH);
+ p->up_flag = 0;
+
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_AUTORUN_SKILL));
}
/// Adds an item to character's cart.
/// 0124 <index>.W <amount>.L <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_CART)
/// 01c5 <index>.W <amount>.L <name id>.W <type>.B <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_CART2)
-void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail)
+static void clif_cart_additem(struct map_session_data *sd, int n, int amount, int fail)
{
- int view,fd;
- unsigned char *buf;
- int offset = 0;
+ int view, fd;
+ struct PACKET_ZC_ADD_ITEM_TO_CART p;
nullpo_retv(sd);
- fd=sd->fd;
- if(n<0 || n>=MAX_CART || sd->status.cart[n].nameid<=0)
+ fd = sd->fd;
+ if (n < 0 || n >= MAX_CART || sd->status.cart[n].nameid <= 0)
return;
- WFIFOHEAD(fd,packet_len(cartaddType));
- buf=WFIFOP(fd,0);
- WBUFW(buf,0)=cartaddType;
- WBUFW(buf,2)=n+2;
- WBUFL(buf,4)=amount;
- if((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0)
- WBUFW(buf,8)=view;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = cartaddType;
+ p.index = n + 2;
+ p.amount = amount;
+ if ((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0)
+ p.itemId = view;
else
- WBUFW(buf,8)=sd->status.cart[n].nameid;
+ p.itemId = sd->status.cart[n].nameid;
#if PACKETVER >= 5
- WBUFB(buf,10)=itemdb_type(sd->status.cart[n].nameid);
- offset = 1;
+ p.itemType = itemdb_type(sd->status.cart[n].nameid);
#endif
- WBUFB(buf,10+offset)=sd->status.cart[n].identify;
- WBUFB(buf,11+offset)=sd->status.cart[n].attribute;
- WBUFB(buf,12+offset)=sd->status.cart[n].refine;
- clif->addcards(WBUFP(buf,13+offset), &sd->status.cart[n]);
+ p.identified = sd->status.cart[n].identify;
+ p.damaged = sd->status.cart[n].attribute;
+ p.refine = sd->status.cart[n].refine;
+ clif->addcards(&p.slot, &sd->status.cart[n]);
#if PACKETVER >= 20150226
- clif->add_random_options(WBUFP(buf,21+offset), &sd->status.cart[n]);
+ clif->add_item_options(&p.option_data[0], &sd->status.cart[n]);
#endif
- WFIFOSET(fd,packet_len(cartaddType));
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Deletes an item from character's cart (ZC_DELETE_ITEM_FROM_CART).
/// 0125 <index>.W <amount>.L
-void clif_cart_delitem(struct map_session_data *sd,int n,int amount)
+static void clif_cart_delitem(struct map_session_data *sd, int n, int amount)
{
int fd;
@@ -6140,7 +6838,7 @@ void clif_cart_delitem(struct map_session_data *sd,int n,int amount)
/// 012d <num>.W
/// num:
/// number of allowed item slots
-void clif_openvendingreq(struct map_session_data* sd, int num)
+static void clif_openvendingreq(struct map_session_data *sd, int num)
{
int fd;
@@ -6155,7 +6853,7 @@ void clif_openvendingreq(struct map_session_data* sd, int num)
/// Displays a vending board to target/area (ZC_STORE_ENTRY).
/// 0131 <owner id>.L <message>.80B
-void clif_showvendingboard(struct block_list* bl, const char* message, int fd)
+static void clif_showvendingboard(struct block_list *bl, const char *message, int fd)
{
unsigned char buf[128];
@@ -6176,7 +6874,7 @@ void clif_showvendingboard(struct block_list* bl, const char* message, int fd)
/// Removes a vending board from screen (ZC_DISAPPEAR_ENTRY).
/// 0132 <owner id>.L
-void clif_closevendingboard(struct block_list* bl, int fd)
+static void clif_closevendingboard(struct block_list *bl, int fd)
{
unsigned char buf[16];
@@ -6196,23 +6894,13 @@ void clif_closevendingboard(struct block_list* bl, int fd)
/// Sends a list of items in a shop.
/// R 0133 <packet len>.W <owner id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC)
/// R 0800 <packet len>.W <owner id>.L <unique id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC2)
-void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_vending* vending_items) {
- int i,fd;
+static void clif_vendinglist(struct map_session_data *sd, unsigned int id, struct s_vending *vending_items)
+{
+ int i, fd;
int count;
struct map_session_data* vsd;
-#if PACKETVER < 20100105
- const int cmd = 0x133;
- const int offset = 8;
-#else
- const int cmd = 0x800;
- const int offset = 12;
-#endif
-
-#if PACKETVER >= 20150226
- const int item_length = 47;
-#else
- const int item_length = 22;
-#endif
+ int len;
+ struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC *p;
nullpo_retv(sd);
nullpo_retv(vending_items);
@@ -6220,32 +6908,39 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven
fd = sd->fd;
count = vsd->vend_num;
+ len = sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC) + count * sizeof(struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC_sub);
- WFIFOHEAD(fd, offset+count*item_length);
- WFIFOW(fd,0) = cmd;
- WFIFOW(fd,2) = offset+count*item_length;
- WFIFOL(fd,4) = id;
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = vendinglistType;
+ p->packetLength = len;
+ p->AID = id;
#if PACKETVER >= 20100105
- WFIFOL(fd,8) = vsd->vender_id;
+ p->venderId = vsd->vender_id;
#endif
- for( i = 0; i < count; i++ ) {
+ for (i = 0; i < count; i++) {
int index = vending_items[i].index;
struct item_data* data = itemdb->search(vsd->status.cart[index].nameid);
- WFIFOL(fd,offset+ 0+i*item_length) = vending_items[i].value;
- WFIFOW(fd,offset+ 4+i*item_length) = vending_items[i].amount;
- WFIFOW(fd,offset+ 6+i*item_length) = vending_items[i].index + 2;
- WFIFOB(fd,offset+ 8+i*item_length) = itemtype(data->type);
- WFIFOW(fd,offset+ 9+i*item_length) = ( data->view_id > 0 ) ? data->view_id : vsd->status.cart[index].nameid;
- WFIFOB(fd,offset+11+i*item_length) = vsd->status.cart[index].identify;
- WFIFOB(fd,offset+12+i*item_length) = vsd->status.cart[index].attribute;
- WFIFOB(fd,offset+13+i*item_length) = vsd->status.cart[index].refine;
- clif->addcards(WFIFOP(fd,offset+14+i*item_length), &vsd->status.cart[index]);
+ p->items[i].price = vending_items[i].value;
+ p->items[i].amount = vending_items[i].amount;
+ p->items[i].index = vending_items[i].index + 2;
+ p->items[i].itemType = itemtype(data->type);
+ p->items[i].itemId = (data->view_id > 0) ? data->view_id : vsd->status.cart[index].nameid;
+ p->items[i].identified = vsd->status.cart[index].identify;
+ p->items[i].damaged = vsd->status.cart[index].attribute;
+ p->items[i].refine = vsd->status.cart[index].refine;
+ clif->addcards(&p->items[i].slot, &vsd->status.cart[index]);
#if PACKETVER >= 20150226
- clif->add_random_options(WFIFOP(fd,offset+22+i*item_length), &vsd->status.cart[index]);
+ clif->add_item_options(&p->items[i].option_data[0], &vsd->status.cart[index]);
+#endif
+// [4144] date 20160921 not confirmed. Can be bigger or smaller
+#if PACKETVER >= 20160921
+ p->items[i].location = pc->item_equippoint(sd, data);
+ p->items[i].viewSprite = data->view_sprite;
#endif
}
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
/// Shop purchase failure (ZC_PC_PURCHASE_RESULT_FROMMC).
@@ -6258,7 +6953,7 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven
/// 5 = "cannot use an npc shop while in a trade"
/// 6 = Because the store information was incorrect the item was not purchased.
/// 7 = No sales information.
-void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail)
+static void clif_buyvending(struct map_session_data *sd, int index, int amount, int fail)
{
int fd;
@@ -6275,67 +6970,86 @@ void clif_buyvending(struct map_session_data* sd, int index, int amount, int fai
/// Shop creation success (ZC_PC_PURCHASE_MYITEMLIST).
/// 0136 <packet len>.W <owner id>.L { <price>.L <index>.W <amount>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }*
-void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending_items) {
- int i,fd;
+static void clif_openvending(struct map_session_data *sd, int id, struct s_vending *vending_items)
+{
+ int i, fd;
int count;
-#if PACKETVER >= 20150226
- const int item_length = 47;
-#else
- const int item_length = 22;
-#endif
+ struct PACKET_ZC_PC_PURCHASE_MYITEMLIST *p;
+ int len;
nullpo_retv(sd);
nullpo_retv(vending_items);
fd = sd->fd;
count = sd->vend_num;
-
- WFIFOHEAD(fd, 8+count*item_length);
- WFIFOW(fd,0) = 0x136;
- WFIFOW(fd,2) = 8+count*item_length;
- WFIFOL(fd,4) = id;
- for( i = 0; i < count; i++ ) {
+ len = sizeof(struct PACKET_ZC_PC_PURCHASE_MYITEMLIST) + count * sizeof(struct PACKET_ZC_PC_PURCHASE_MYITEMLIST_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x136;
+ p->packetLength = len;
+ p->AID = id;
+ for (i = 0; i < count; i++) {
int index = vending_items[i].index;
struct item_data* data = itemdb->search(sd->status.cart[index].nameid);
- WFIFOL(fd, 8+i*item_length) = vending_items[i].value;
- WFIFOW(fd,12+i*item_length) = vending_items[i].index + 2;
- WFIFOW(fd,14+i*item_length) = vending_items[i].amount;
- WFIFOB(fd,16+i*item_length) = itemtype(data->type);
- WFIFOW(fd,17+i*item_length) = ( data->view_id > 0 ) ? data->view_id : sd->status.cart[index].nameid;
- WFIFOB(fd,19+i*item_length) = sd->status.cart[index].identify;
- WFIFOB(fd,20+i*item_length) = sd->status.cart[index].attribute;
- WFIFOB(fd,21+i*item_length) = sd->status.cart[index].refine;
- clif->addcards(WFIFOP(fd,22+i*item_length), &sd->status.cart[index]);
+ p->items[i].price = vending_items[i].value;
+ p->items[i].index = vending_items[i].index + 2;
+ p->items[i].amount = vending_items[i].amount;
+ p->items[i].itemType = itemtype(data->type);
+ p->items[i].itemId = (data->view_id > 0) ? data->view_id : sd->status.cart[index].nameid;
+ p->items[i].identified = sd->status.cart[index].identify;
+ p->items[i].damaged = sd->status.cart[index].attribute;
+ p->items[i].refine = sd->status.cart[index].refine;
+ clif->addcards(&p->items[i].slot, &sd->status.cart[index]);
#if PACKETVER >= 20150226
- clif->add_random_options(WFIFOP(fd,30+22+i*item_length), &sd->status.cart[index]);
+ clif->add_item_options(&p->items[i].option_data[0], &sd->status.cart[index]);
#endif
}
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
-#if PACKETVER >= 20141022
- /** should go elsewhere perhaps? it has to be bundled with this however. **/
- WFIFOHEAD(fd, 3);
- WFIFOW(fd, 0) = 0xa28;
- WFIFOB(fd, 2) = 0;/** 1 is failure. our current responses to failure are working so not yet implemented **/
- WFIFOSET(fd, 3);
+ clif->openvendingAck(fd, 0);
+}
+
+// 0 - open vending success
+// 1 - message MSG_MERCHANTSHOP_MAKING_FAIL
+// 2 - silent ignore
+// 3 - message MSG_ID_C9D (You can not open a stall at the current location)
+static void clif_openvendingAck(int fd, int result)
+{
+#if PACKETVER >= 20140625
+ WFIFOHEAD(fd, packet_len(0xa28));
+ WFIFOW(fd, 0) = 0xa28; // ZC_ACK_OPENSTORE2
+ WFIFOB(fd, 2) = result;
+ WFIFOSET(fd, packet_len(0xa28));
#endif
}
-/// Inform merchant that someone has bought an item (ZC_DELETEITEM_FROM_MCSTORE).
-/// 0137 <index>.W <amount>.W
-void clif_vendingreport(struct map_session_data* sd, int index, int amount)
+/// Inform merchant that someone has bought an item.
+/// 0137 <index>.W <amount>.W (ZC_DELETEITEM_FROM_MCSTORE).
+/// 09e5 <index>.W <amount>.W <GID>.L <Date>.L <zeny>.L (ZC_DELETEITEM_FROM_MCSTORE2).
+static void clif_vendingreport(struct map_session_data *sd, int index, int amount, uint32 char_id, int zeny)
{
int fd;
+#if PACKETVER < 20141016 // TODO : not sure for client date [Napster]
+ const int cmd = 0x137;
+#else
+ const int cmd = 0x9e5;
+#endif
+ const int len = packet_len(cmd);
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x137));
- WFIFOW(fd,0) = 0x137;
- WFIFOW(fd,2) = index+2;
- WFIFOW(fd,4) = amount;
- WFIFOSET(fd,packet_len(0x137));
+ WFIFOHEAD(fd, len);
+ WFIFOW(fd, 0) = cmd;
+ WFIFOW(fd, 2) = index + 2;
+ WFIFOW(fd, 4) = amount;
+#if PACKETVER >= 20141016
+ WFIFOL(fd,6) = char_id; // GID
+ WFIFOL(fd,10) = (int)time(NULL); // Date
+ WFIFOL(fd,14) = zeny; // zeny
+#endif
+ WFIFOSET(fd, len);
}
/// Result of organizing a party (ZC_ACK_MAKE_GROUP).
@@ -6346,7 +7060,7 @@ void clif_vendingreport(struct map_session_data* sd, int index, int amount)
/// 2 = MsgStringTable[79]="already in a party"
/// 3 = cannot organize parties on this map
/// ? = nothing
-void clif_party_created(struct map_session_data *sd,int result)
+static void clif_party_created(struct map_session_data *sd, int result)
{
int fd;
@@ -6360,105 +7074,144 @@ void clif_party_created(struct map_session_data *sd,int result)
}
/// Adds new member to a party.
-/// 0104 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B (ZC_ADD_MEMBER_TO_GROUP)
-/// 01e9 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B <item pickup rule>.B <item share rule>.B (ZC_ADD_MEMBER_TO_GROUP2)
/// role:
/// 0 = leader
/// 1 = normal
/// state:
/// 0 = connected
/// 1 = disconnected
-void clif_party_member_info(struct party_data *p, struct map_session_data *sd)
+static void clif_party_member_info(struct party_data *p, struct map_session_data *sd)
{
- unsigned char buf[81];
int i;
+ struct PACKET_ZC_ADD_MEMBER_TO_GROUP packet;
nullpo_retv(p);
nullpo_retv(sd);
+
+ memset(&packet, 0, sizeof(packet));
if (!sd) { //Pick any party member (this call is used when changing item share rules)
- ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd != 0 );
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != 0);
} else {
- ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd == sd );
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd);
}
- if (i >= MAX_PARTY) return; //Should never happen...
+ if (i >= MAX_PARTY)
+ return; //Should never happen...
sd = p->data[i].sd;
- WBUFW(buf, 0) = 0x1e9;
- WBUFL(buf, 2) = sd->status.account_id;
- WBUFL(buf, 6) = (p->party.member[i].leader)?0:1;
- WBUFW(buf,10) = sd->bl.x;
- WBUFW(buf,12) = sd->bl.y;
- WBUFB(buf,14) = (p->party.member[i].online)?0:1;
- memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH);
- memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH);
- mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, WBUFP(buf,63));
- WBUFB(buf,79) = (p->party.item&1)?1:0;
- WBUFB(buf,80) = (p->party.item&2)?1:0;
- clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY);
+ packet.packetType = partymemberinfo;
+ packet.AID = sd->status.account_id;
+#if PACKETVER >= 20171207
+ packet.GID = sd->status.char_id;
+#endif
+ packet.leader = (p->party.member[i].leader) ? 0 : 1;
+#if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ packet.class = sd->status.class;
+ packet.baseLevel = sd->status.base_level;
+#endif
+ packet.x = sd->bl.x;
+ packet.y = sd->bl.y;
+ packet.offline = (p->party.member[i].online) ? 0 : 1;
+ memcpy(packet.partyName, p->party.name, NAME_LENGTH);
+ memcpy(packet.playerName, sd->status.name, NAME_LENGTH);
+ mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, packet.mapName);
+ packet.sharePickup = (p->party.item & 1) ? 1 : 0;
+ packet.shareLoot = (p->party.item & 2) ? 1 : 0;
+ clif->send(&packet, sizeof(packet), &sd->bl, PARTY);
}
/// Sends party information (ZC_GROUP_LIST).
-/// 00fb <packet len>.W <party name>.24B { <account id>.L <nick>.24B <map name>.16B <role>.B <state>.B }*
/// role:
/// 0 = leader
/// 1 = normal
/// state:
/// 0 = connected
/// 1 = disconnected
-void clif_party_info(struct party_data* p, struct map_session_data *sd)
+static void clif_party_info(struct party_data *p, struct map_session_data *sd)
{
- unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH_EXT+1+1)*MAX_PARTY];
+ struct PACKET_ZC_GROUP_LIST *packet;
struct map_session_data* party_sd = NULL;
int i, c;
-
+ unsigned char buf[sizeof(*packet) + sizeof(struct PACKET_ZC_GROUP_LIST_SUB) * MAX_PARTY];
nullpo_retv(p);
- WBUFW(buf,0) = 0xfb;
- memcpy(WBUFP(buf,4), p->party.name, NAME_LENGTH);
+ memset(buf, 0, sizeof(buf));
+ packet = (struct PACKET_ZC_GROUP_LIST *)buf;
+ packet->packetType = partyinfo;
+ memcpy(packet->partyName, p->party.name, NAME_LENGTH);
for(i = 0, c = 0; i < MAX_PARTY; i++)
{
- struct party_member* m = &p->party.member[i];
- if(!m->account_id) continue;
+ struct party_member *m = &p->party.member[i];
+ if (!m->account_id)
+ continue;
- if(party_sd == NULL) party_sd = p->data[i].sd;
+ if (party_sd == NULL)
+ party_sd = p->data[i].sd;
- WBUFL(buf,28+c*46) = m->account_id;
- memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH);
- mapindex->getmapname_ext(mapindex_id2name(m->map), WBUFP(buf,28+c*46+28));
- WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1;
- WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1;
+ packet->members[c].AID = m->account_id;
+#if PACKETVER >= 20171207
+ packet->members[c].GID = m->char_id;
+#endif
+ memcpy(packet->members[c].playerName, m->name, NAME_LENGTH);
+ mapindex->getmapname_ext(mapindex_id2name(m->map), packet->members[c].mapName);
+ packet->members[c].leader = (m->leader) ? 0 : 1;
+ packet->members[c].offline = (m->online) ? 0 : 1;
+#if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ packet->members[c].class = m->class;
+ packet->members[c].baseLevel = m->lv;
+#endif
c++;
}
- WBUFW(buf,2) = 28+c*46;
+ packet->packetLen = sizeof(*packet) + c * sizeof(struct PACKET_ZC_GROUP_LIST_SUB);
- if(sd) { // send only to self
- clif->send(buf, WBUFW(buf,2), &sd->bl, SELF);
+ if (sd) { // send only to self
+ clif->send(buf, packet->packetLen, &sd->bl, SELF);
} else if (party_sd) { // send to whole party
- clif->send(buf, WBUFW(buf,2), &party_sd->bl, PARTY);
+ clif->send(buf, packet->packetLen, &party_sd->bl, PARTY);
}
}
+/// Updates the job and level of a party member
+/// 0abd <account id>.L <job>.W <level>.W
+static void clif_party_job_and_level(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170502 || PACKETVER_RE_NUM >= 20170419 || defined(PACKETVER_ZERO)
+ unsigned char buf[10];
+
+ nullpo_retv(sd);
+
+ WBUFW(buf, 0) = 0xabd;
+ WBUFL(buf, 2) = sd->status.account_id;
+ WBUFW(buf, 6) = sd->status.class;
+ WBUFW(buf, 8) = sd->status.base_level;
+
+ clif->send(buf, packet_len(0xabd), &sd->bl, PARTY);
+#endif
+}
+
/// The player's 'party invite' state, sent during login (ZC_PARTY_CONFIG).
/// 02c9 <flag>.B
/// flag:
/// 0 = allow party invites
/// 1 = auto-deny party invites
-void clif_partyinvitationstate(struct map_session_data* sd)
+static void clif_partyinvitationstate(struct map_session_data *sd)
{
+#if PACKETVER_MAIN_NUM >= 20070911 || defined(PACKETVER_RE) || PACKETVER_AD_NUM >= 20070911 || PACKETVER_SAK_NUM >= 20070904 || defined(PACKETVER_ZERO)
int fd;
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd, packet_len(0x2c9));
- WFIFOW(fd, 0) = 0x2c9;
- WFIFOB(fd, 2) = sd->status.allow_party ? 1 : 0;
- WFIFOSET(fd, packet_len(0x2c9));
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_PARTY_CONFIG));
+ struct PACKET_ZC_PARTY_CONFIG *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_PARTY_CONFIG;
+ p->denyPartyInvites = sd->status.allow_party ? 1 : 0;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_PARTY_CONFIG));
+#endif
}
/// Party invitation request.
/// 00fe <party id>.L <party name>.24B (ZC_REQ_JOIN_GROUP)
/// 02c6 <party id>.L <party name>.24B (ZC_PARTY_JOIN_REQ)
-void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd)
+static void clif_party_invite(struct map_session_data *sd, struct map_session_data *tsd)
{
#if PACKETVER < 20070821
const int cmd = 0xfe;
@@ -6486,16 +7239,18 @@ void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd)
/// Party invite result.
/// 00fd <nick>.24S <result>.B (ZC_ACK_REQ_JOIN_GROUP)
/// 02c5 <nick>.24S <result>.L (ZC_PARTY_JOIN_REQ_ACK)
-/// result=0 : char is already in a party -> MsgStringTable[80]
-/// result=1 : party invite was rejected -> MsgStringTable[81]
-/// result=2 : party invite was accepted -> MsgStringTable[82]
-/// result=3 : party is full -> MsgStringTable[83]
-/// result=4 : char of the same account already joined the party -> MsgStringTable[608]
-/// result=5 : char blocked party invite -> MsgStringTable[1324] (since 20070904)
-/// result=7 : char is not online or doesn't exist -> MsgStringTable[71] (since 20070904)
-/// result=8 : (%s) TODO instance related? -> MsgStringTable[1388] (since 20080527)
-/// return=9 : TODO map prohibits party joining? -> MsgStringTable[1871] (since 20110205)
-void clif_party_inviteack(struct map_session_data* sd, const char* nick, int result)
+/// result=0 : char is already in a party -> MsgStringTable[80]
+/// result=1 : party invite was rejected -> MsgStringTable[81]
+/// result=2 : party invite was accepted -> MsgStringTable[82]
+/// result=3 : party is full -> MsgStringTable[83]
+/// result=4 : char of the same account already joined the party -> MsgStringTable[608]
+/// result=5 : char blocked party invite -> MsgStringTable[1324] (since 20070904)
+/// result=7 : char is not online or doesn't exist -> MsgStringTable[71] (since 20070904)
+/// result=8 : (%s) are currently in restricted map to join a party. -> MsgStringTable[1388] (since 20080527)
+/// result=9 : Cannot join a party in this map. -> MsgStringTable[1871] (since 20110215)
+/// result=10 : You cannot invite or withdraw while in memorial dungeon -> message: MSG_ID_BD3 (since 20161130)
+/// result=11 : The character is a level that can not join the party -> message: MSG_ID_C9A (since 20170412)
+static void clif_party_inviteack(struct map_session_data *sd, const char *nick, int result)
{
int fd;
nullpo_retv(sd);
@@ -6504,7 +7259,7 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res
#if PACKETVER < 20070904
if( result == 7 ) {
- clif->message(fd, msg_sd(sd,3));
+ clif->message(fd, msg_sd(sd,3)); // Character not found.
return;
}
#endif
@@ -6535,7 +7290,7 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res
/// flag:
/// 0 = send to party
/// 1 = send to sd
-void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag)
+static void clif_party_option(struct party_data *p, struct map_session_data *sd, int flag)
{
unsigned char buf[16];
#if PACKETVER < 20090603
@@ -6572,7 +7327,7 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag
/// 1 = expel
/// 2 = cannot leave party on this map
/// 3 = cannot expel from party on this map
-void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag)
+static void clif_party_withdraw(struct party_data *p, struct map_session_data *sd, int account_id, const char *name, int flag)
{
unsigned char buf[64];
@@ -6602,7 +7357,7 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int
/// Party chat message (ZC_NOTIFY_CHAT_PARTY).
/// 0109 <packet len>.W <account id>.L <message>.?B
-void clif_party_message(struct party_data* p, int account_id, const char* mes, int len)
+static void clif_party_message(struct party_data *p, int account_id, const char *mes, int len)
{
struct map_session_data *sd;
int i;
@@ -6610,28 +7365,30 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i
nullpo_retv(p);
nullpo_retv(mes);
- for(i=0; i < MAX_PARTY && !p->data[i].sd;i++);
- if(i < MAX_PARTY){
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL);
+
+ if (i < MAX_PARTY) {
unsigned char buf[1024];
+ int maxlen = (int)sizeof(buf) - 9;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%"PRIuS", party_id=%d).\n",
- mes, len, sizeof(buf)-8, p->party.party_id);
- len = sizeof(buf)-8;
+ if (len > maxlen) {
+ ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n",
+ mes, len, maxlen, p->party.party_id);
+ len = maxlen;
}
sd = p->data[i].sd;
- WBUFW(buf,0)=0x109;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=account_id;
- safestrncpy(WBUFP(buf,8), mes, len);
- clif->send(buf,len+8,&sd->bl,PARTY);
+ WBUFW(buf,0) = 0x109;
+ WBUFW(buf,2) = len+9;
+ WBUFL(buf,4) = account_id;
+ safestrncpy(WBUFP(buf,8), mes, len+1);
+ clif->send(buf, len+9, &sd->bl, PARTY);
}
}
/// Updates the position of a party member on the minimap (ZC_NOTIFY_POSITION_TO_GROUPM).
/// 0107 <account id>.L <x>.W <y>.W
-void clif_party_xy(struct map_session_data *sd)
+static void clif_party_xy(struct map_session_data *sd)
{
unsigned char buf[16];
@@ -6647,7 +7404,7 @@ void clif_party_xy(struct map_session_data *sd)
/*==========================================
* Sends x/y dot to a single fd. [Skotlex]
*------------------------------------------*/
-void clif_party_xy_single(int fd, struct map_session_data *sd)
+static void clif_party_xy_single(int fd, struct map_session_data *sd)
{
nullpo_retv(sd);
WFIFOHEAD(fd,packet_len(0x107));
@@ -6661,7 +7418,7 @@ void clif_party_xy_single(int fd, struct map_session_data *sd)
/// Updates HP bar of a party member.
/// 0106 <account id>.L <hp>.W <max hp>.W (ZC_NOTIFY_HP_TO_GROUPM)
/// 080e <account id>.L <hp>.L <max hp>.L (ZC_NOTIFY_HP_TO_GROUPM_R2)
-void clif_party_hp(struct map_session_data *sd)
+static void clif_party_hp(struct map_session_data *sd)
{
unsigned char buf[16];
#if PACKETVER < 20100126
@@ -6692,7 +7449,7 @@ void clif_party_hp(struct map_session_data *sd)
/*==========================================
* Sends HP bar to a single fd. [Skotlex]
*------------------------------------------*/
-void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp)
+static void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp)
{
#if PACKETVER < 20100126
const int cmd = 0x106;
@@ -6720,7 +7477,7 @@ void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp)
/// Notifies the client, that it's attack target is too far (ZC_ATTACK_FAILURE_FOR_DISTANCE).
/// 0139 <target id>.L <target x>.W <target y>.W <x>.W <y>.W <atk range>.W
-void clif_movetoattack(struct map_session_data *sd,struct block_list *bl)
+static void clif_movetoattack(struct map_session_data *sd, struct block_list *bl)
{
int fd;
@@ -6746,27 +7503,33 @@ void clif_movetoattack(struct map_session_data *sd,struct block_list *bl)
/// 1 = failure
/// 2 = success (alchemist)
/// 3 = failure (alchemist)
-void clif_produceeffect(struct map_session_data* sd,int flag,int nameid)
+/// 4 = success (???)
+/// 5 = failure (???)
+/// 6 = failure (???)
+/// 7 = failure (???)
+static void clif_produceeffect(struct map_session_data *sd, int flag, int nameid)
{
- int view,fd;
+ int view, fd;
+ struct PACKET_ZC_ACK_REQMAKINGITEM p;
nullpo_retv(sd);
fd = sd->fd;
clif->solved_charname(fd, sd->status.char_id, sd->status.name);
- WFIFOHEAD(fd,packet_len(0x18f));
- WFIFOW(fd, 0)=0x18f;
- WFIFOW(fd, 2)=flag;
- if((view = itemdb_viewid(nameid)) > 0)
- WFIFOW(fd, 4)=view;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x18f;
+ p.result = flag;
+ if ((view = itemdb_viewid(nameid)) > 0)
+ p.itemId = view;
else
- WFIFOW(fd, 4)=nameid;
- WFIFOSET(fd,packet_len(0x18f));
+ p.itemId = nameid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Initiates the pet taming process (ZC_START_CAPTURE).
/// 019e
-void clif_catch_process(struct map_session_data *sd)
+static void clif_catch_process(struct map_session_data *sd)
{
int fd;
@@ -6782,7 +7545,7 @@ void clif_catch_process(struct map_session_data *sd)
/// 01a0 <result>.B
/// 0 = failure
/// 1 = success
-void clif_pet_roulette(struct map_session_data *sd,int data)
+static void clif_pet_roulette(struct map_session_data *sd, int data)
{
int fd;
@@ -6797,7 +7560,8 @@ void clif_pet_roulette(struct map_session_data *sd,int data)
/// Presents a list of pet eggs that can be hatched (ZC_PETEGG_LIST).
/// 01a6 <packet len>.W { <index>.W }*
-void clif_sendegg(struct map_session_data *sd) {
+static void clif_sendegg(struct map_session_data *sd)
+{
int i, n, fd;
nullpo_retv(sd);
@@ -6808,9 +7572,9 @@ void clif_sendegg(struct map_session_data *sd) {
return;
}
- WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4);
+ WFIFOHEAD(fd, sd->status.inventorySize * 2 + 4);
WFIFOW(fd,0) = 0x1a6;
- for (i = n = 0; i < MAX_INVENTORY; i++) {
+ for (i = n = 0; i < sd->status.inventorySize; i++) {
if (sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL || sd->inventory_data[i]->type!=IT_PETEGG || sd->status.inventory[i].amount <= 0)
continue;
WFIFOW(fd, n * 2 + 4) = i + 2;
@@ -6835,9 +7599,10 @@ void clif_sendegg(struct map_session_data *sd) {
/// 3 = accessory
/// 4 = performance (data = 1~3: normal, 4: special)
/// 5 = hairstyle
+/// 6 = close egg selection ui and update egg in inventory (PACKETVER >= 20180704)
///
/// If sd is null, the update is sent to nearby objects, otherwise it is sent only to that player.
-void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int type, int param)
+static void clif_send_petdata(struct map_session_data *sd, struct pet_data *pd, int type, int param)
{
uint8 buf[16];
nullpo_retv(pd);
@@ -6854,7 +7619,7 @@ void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int typ
/// Pet's base data (ZC_PROPERTY_PET).
/// 01a2 <name>.24B <renamed>.B <level>.W <hunger>.W <intimacy>.W <accessory id>.W <class>.W
-void clif_send_petstatus(struct map_session_data *sd)
+static void clif_send_petstatus(struct map_session_data *sd)
{
int fd;
struct s_pet *p;
@@ -6882,7 +7647,7 @@ void clif_send_petstatus(struct map_session_data *sd)
/// 01aa <id>.L <data>.L
/// data:
/// @see CZ_PET_ACT.
-void clif_pet_emotion(struct pet_data *pd,int param)
+static void clif_pet_emotion(struct pet_data *pd, int param)
{
unsigned char buf[16];
@@ -6911,69 +7676,72 @@ void clif_pet_emotion(struct pet_data *pd,int param)
/// result:
/// 0 = failure
/// 1 = success
-void clif_pet_food(struct map_session_data *sd,int foodid,int fail)
+static void clif_pet_food(struct map_session_data *sd, int foodid, int fail)
{
int fd;
+ struct PACKET_ZC_FEED_PET p;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x1a3));
- WFIFOW(fd,0)=0x1a3;
- WFIFOB(fd,2)=fail;
- WFIFOW(fd,3)=foodid;
- WFIFOSET(fd,packet_len(0x1a3));
+ fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x1a3;
+ p.result = fail;
+ p.itemId = foodid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Presents a list of skills that can be auto-spelled (ZC_AUTOSPELLLIST).
/// 01cd { <skill id>.L }*7
-void clif_autospell(struct map_session_data *sd,uint16 skill_lv)
+static void clif_autospell(struct map_session_data *sd, uint16 skill_lv)
{
- int fd;
-
+#if PACKETVER_MAIN_NUM >= 20090406 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO) || PACKETVER_SAK_NUM >= 20080618
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x1cd));
- WFIFOW(fd, 0)=0x1cd;
+ int fd = sd->fd;
+#if PACKETVER_MAIN_NUM >= 20181128 || PACKETVER_RE_NUM >= 20181031
+ // reserve space for 7 skills
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_AUTOSPELLLIST) + 4 * 7);
+#else
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_AUTOSPELLLIST));
+#endif
+ struct PACKET_ZC_AUTOSPELLLIST *p = WFIFOP(fd, 0);
+ memset(p, 0, sizeof(struct PACKET_ZC_AUTOSPELLLIST));
+ p->packetType = HEADER_ZC_AUTOSPELLLIST;
+ int index = 0;
- if(skill_lv>0 && pc->checkskill(sd,MG_NAPALMBEAT)>0)
- WFIFOL(fd,2)= MG_NAPALMBEAT;
- else
- WFIFOL(fd,2)= 0x00000000;
- if(skill_lv>1 && pc->checkskill(sd,MG_COLDBOLT)>0)
- WFIFOL(fd,6)= MG_COLDBOLT;
- else
- WFIFOL(fd,6)= 0x00000000;
- if(skill_lv>1 && pc->checkskill(sd,MG_FIREBOLT)>0)
- WFIFOL(fd,10)= MG_FIREBOLT;
- else
- WFIFOL(fd,10)= 0x00000000;
- if(skill_lv>1 && pc->checkskill(sd,MG_LIGHTNINGBOLT)>0)
- WFIFOL(fd,14)= MG_LIGHTNINGBOLT;
- else
- WFIFOL(fd,14)= 0x00000000;
- if(skill_lv>4 && pc->checkskill(sd,MG_SOULSTRIKE)>0)
- WFIFOL(fd,18)= MG_SOULSTRIKE;
- else
- WFIFOL(fd,18)= 0x00000000;
- if(skill_lv>7 && pc->checkskill(sd,MG_FIREBALL)>0)
- WFIFOL(fd,22)= MG_FIREBALL;
- else
- WFIFOL(fd,22)= 0x00000000;
- if(skill_lv>9 && pc->checkskill(sd,MG_FROSTDIVER)>0)
- WFIFOL(fd,26)= MG_FROSTDIVER;
- else
- WFIFOL(fd,26)= 0x00000000;
+ if (skill_lv > 0 && pc->checkskill(sd, MG_NAPALMBEAT) > 0)
+ p->skills[index++] = MG_NAPALMBEAT;
+ if (skill_lv > 1 && pc->checkskill(sd, MG_COLDBOLT) > 0)
+ p->skills[index++] = MG_COLDBOLT;
+ if (skill_lv > 1 && pc->checkskill(sd, MG_FIREBOLT) > 0)
+ p->skills[index++] = MG_FIREBOLT;
+ if (skill_lv > 1 && pc->checkskill(sd, MG_LIGHTNINGBOLT) > 0)
+ p->skills[index++] = MG_LIGHTNINGBOLT;
+ if (skill_lv > 4 && pc->checkskill(sd, MG_SOULSTRIKE) > 0)
+ p->skills[index++] = MG_SOULSTRIKE;
+ if (skill_lv > 7 && pc->checkskill(sd, MG_FIREBALL) > 0)
+ p->skills[index++] = MG_FIREBALL;
+ if (skill_lv > 9 && pc->checkskill(sd, MG_FROSTDIVER) > 0)
+ p->skills[index++] = MG_FROSTDIVER;
+
+#if PACKETVER_MAIN_NUM >= 20181128 || PACKETVER_RE_NUM >= 20181031
+ const int len = sizeof(struct PACKET_ZC_AUTOSPELLLIST) + index * 4;
+ p->packetLength = len;
+#else
+ const int len = sizeof(struct PACKET_ZC_AUTOSPELLLIST);
+#endif
+ WFIFOSET(fd, len);
- WFIFOSET(fd,packet_len(0x1cd));
sd->menuskill_id = SA_AUTOSPELL;
sd->menuskill_val = skill_lv;
+#endif
}
/// Devotion's visual effect (ZC_DEVOTIONLIST).
/// 01cf <devoter id>.L { <devotee id>.L }*5 <max distance>.W
-void clif_devotion(struct block_list *src, struct map_session_data *tsd)
+static void clif_devotion(struct block_list *src, struct map_session_data *tsd)
{
unsigned char buf[56];
@@ -6985,21 +7753,31 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
if( src->type == BL_MER )
{
struct mercenary_data *md = BL_CAST(BL_MER,src);
+ int skill_lvl;
if( md && md->master && md->devotion_flag )
WBUFL(buf,6) = md->master->bl.id;
- WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary->checkskill(md, ML_DEVOTION));
+ skill_lvl = mercenary->checkskill(md, ML_DEVOTION);
+ if (skill_lvl > 0)
+ WBUFW(buf, 26) = skill->get_range2(src, ML_DEVOTION, skill_lvl);
+ else
+ WBUFW(buf, 26) = 0;
}
else
{
int i;
struct map_session_data *sd = BL_CAST(BL_PC,src);
+ int skill_lvl;
if( sd == NULL )
return;
for( i = 0; i < MAX_PC_DEVOTION; i++ )
WBUFL(buf,6+4*i) = sd->devotion[i];
- WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc->checkskill(sd, CR_DEVOTION));
+ skill_lvl = pc->checkskill(sd, CR_DEVOTION);
+ if (skill_lvl > 0)
+ WBUFW(buf, 26) = skill->get_range2(src, CR_DEVOTION, skill_lvl);
+ else
+ WBUFW(buf, 26) = 0;
}
if( tsd )
@@ -7014,26 +7792,37 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
* 01d0 <id>.L <amount>.W (ZC_SPIRITS)
* 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
*------------------------------------------*/
-void clif_spiritball(struct block_list *bl) {
+static void clif_spiritball(struct block_list *bl)
+{
unsigned char buf[16];
- struct map_session_data *sd = BL_CAST(BL_PC,bl);
- struct homun_data *hd = BL_CAST(BL_HOM,bl);
nullpo_retv(bl);
WBUFW(buf, 0) = 0x1d0;
WBUFL(buf, 2) = bl->id;
WBUFW(buf, 6) = 0; //init to 0
- switch(bl->type){
- case BL_PC: WBUFW(buf, 6) = sd->spiritball; break;
- case BL_HOM: WBUFW(buf, 6) = hd->homunculus.spiritball; break;
+ switch (bl->type) {
+ case BL_PC:
+ {
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ nullpo_retv(sd);
+ WBUFW(buf, 6) = sd->spiritball;
+ break;
+ }
+ case BL_HOM:
+ {
+ struct homun_data *hd = BL_CAST(BL_HOM, bl);
+ nullpo_retv(hd);
+ WBUFW(buf, 6) = hd->homunculus.spiritball;
+ break;
+ }
}
clif->send(buf, packet_len(0x1d0), bl, AREA);
}
/// Notifies clients in area of a character's combo delay (ZC_COMBODELAY).
/// 01d2 <account id>.L <delay>.L
-void clif_combo_delay(struct block_list *bl,int wait)
+static void clif_combo_delay(struct block_list *bl, int wait)
{
unsigned char buf[32];
@@ -7050,7 +7839,7 @@ void clif_combo_delay(struct block_list *bl,int wait)
/// flag:
/// 0 = inactive
/// 1 = active
-void clif_bladestop(struct block_list *src, int dst_id, int active)
+static void clif_bladestop(struct block_list *src, int dst_id, int active)
{
unsigned char buf[32];
@@ -7066,7 +7855,7 @@ void clif_bladestop(struct block_list *src, int dst_id, int active)
/// MVP effect (ZC_MVP).
/// 010c <account id>.L
-void clif_mvp_effect(struct map_session_data *sd)
+static void clif_mvp_effect(struct map_session_data *sd)
{
unsigned char buf[16];
@@ -7079,35 +7868,40 @@ void clif_mvp_effect(struct map_session_data *sd)
/// MVP item reward message (ZC_MVP_GETTING_ITEM).
/// 010a <name id>.W
-void clif_mvp_item(struct map_session_data *sd,int nameid)
+/// 010a <name id>.L
+static void clif_mvp_item(struct map_session_data *sd, int nameid)
{
- int view,fd;
+ int view, fd;
+ struct PACKET_ZC_MVP_GETTING_ITEM p;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x10a));
- WFIFOW(fd,0)=0x10a;
- if((view = itemdb_viewid(nameid)) > 0)
- WFIFOW(fd,2)=view;
+ fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x10a;
+ if ((view = itemdb_viewid(nameid)) > 0)
+ p.itemId = view;
else
- WFIFOW(fd,2)=nameid;
- WFIFOSET(fd,packet_len(0x10a));
+ p.itemId = nameid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// MVP EXP reward message (ZC_MVP_GETTING_SPECIAL_EXP).
/// 010b <exp>.L
-void clif_mvp_exp(struct map_session_data *sd, unsigned int exp)
+static void clif_mvp_exp(struct map_session_data *sd, unsigned int exp)
{
+#if PACKETVER_RE_NUM >= 20080827 || PACKETVER_MAIN_NUM >= 20090401 || defined(PACKETVER_ZERO)
int fd;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x10b));
- WFIFOW(fd,0)=0x10b;
- WFIFOL(fd,2)=cap_value(exp,0,INT32_MAX);
- WFIFOSET(fd,packet_len(0x10b));
+ fd = sd->fd;
+ WFIFOHEAD(fd, packet_len(0x10b));
+ WFIFOW(fd, 0) = 0x10b;
+ WFIFOL(fd, 2) = cap_value(exp, 0, INT32_MAX);
+ WFIFOSET(fd, packet_len(0x10b));
+#endif
}
/// Dropped MVP item reward message (ZC_THROW_MVPITEM).
@@ -7115,7 +7909,7 @@ void clif_mvp_exp(struct map_session_data *sd, unsigned int exp)
///
/// "You are the MVP, but cannot obtain the reward because
/// you are overweight."
-void clif_mvp_noitem(struct map_session_data* sd)
+static void clif_mvp_noitem(struct map_session_data *sd)
{
int fd = sd->fd;
@@ -7131,7 +7925,8 @@ void clif_mvp_noitem(struct map_session_data* sd)
/// 1 = "You are already in a Guild."
/// 2 = "That Guild Name already exists."
/// 3 = "You need the necessary item to create a Guild."
-void clif_guild_created(struct map_session_data *sd,int flag)
+/// 4 = "Can't create a Guild in this area."
+static void clif_guild_created(struct map_session_data *sd, int flag)
{
int fd;
@@ -7147,14 +7942,15 @@ void clif_guild_created(struct map_session_data *sd,int flag)
/// Notifies the client that it is belonging to a guild (ZC_UPDATE_GDID).
/// 016c <guild id>.L <emblem id>.L <mode>.L <ismaster>.B <inter sid>.L <guild name>.24B
/// mode: @see enum guild_permission
-void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
+static void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
{
- int ps,fd;
nullpo_retv(sd);
nullpo_retv(g);
- fd=sd->fd;
- ps=guild->getposition(g,sd);
+ int fd = sd->fd;
+ int ps = guild->getposition(g, sd);
+ Assert_retv(ps != -1);
+
WFIFOHEAD(fd,packet_len(0x16c));
WFIFOW(fd,0)=0x16c;
WFIFOL(fd,2)=g->guild_id;
@@ -7172,7 +7968,7 @@ void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
/// status:
/// 0 = offline
/// 1 = online
-void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag)
+static void clif_guild_memberlogin_notice(struct guild *g, int idx, int flag)
{
unsigned char buf[64];
struct map_session_data* sd;
@@ -7209,7 +8005,7 @@ void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag)
// At next time the client would always show the message.
// The function sends all the statuses in the single packet
// to economize traffic. [LuzZza]
-void clif_guild_send_onlineinfo(struct map_session_data *sd)
+static void clif_guild_send_onlineinfo(struct map_session_data *sd)
{
struct guild *g;
unsigned char buf[14*128];
@@ -7248,7 +8044,7 @@ void clif_guild_send_onlineinfo(struct map_session_data *sd)
/// &0x10 = Expulsion list
/// &0x40 = Unknown (GMENUFLAG_ALLGUILDLIST)
/// &0x80 = Notice
-void clif_guild_masterormember(struct map_session_data *sd)
+static void clif_guild_masterormember(struct map_session_data *sd)
{
int fd;
@@ -7264,41 +8060,53 @@ void clif_guild_masterormember(struct map_session_data *sd)
/// Guild basic information (Territories [Valaris])
/// 0150 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B (ZC_GUILD_INFO)
/// 01b6 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B <zeny>.L (ZC_GUILD_INFO2)
-void clif_guild_basicinfo(struct map_session_data *sd) {
+static void clif_guild_basicinfo(struct map_session_data *sd)
+{
int fd;
struct guild *g;
+#if PACKETVER < 20160622
+ const int cmd = 0x1b6; //0x150; [4144] this is packet for older versions?
+#else
+ const int cmd = 0xa84;
+#endif
+
nullpo_retv(sd);
fd = sd->fd;
- if( (g = sd->guild) == NULL )
- return;
-
- WFIFOHEAD(fd,packet_len(0x1b6));
- WFIFOW(fd, 0)=0x1b6;//0x150;
- WFIFOL(fd, 2)=g->guild_id;
- WFIFOL(fd, 6)=g->guild_lv;
- WFIFOL(fd,10)=g->connect_member;
- WFIFOL(fd,14)=g->max_member;
- WFIFOL(fd,18)=g->average_lv;
- WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX);
- WFIFOL(fd,26)=g->next_exp;
- WFIFOL(fd,30)=0; // Tax Points
- WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right)
- WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up)
- WFIFOL(fd,42)=g->emblem_id;
- memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH);
- memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH);
-
- safestrncpy(WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles"
- WFIFOL(fd,110) = 0; // zeny
+ if ((g = sd->guild) == NULL)
+ return;
+
+ WFIFOHEAD(fd, packet_len(cmd));
+ WFIFOW(fd, 0) = cmd;
+ WFIFOL(fd, 2) = g->guild_id;
+ WFIFOL(fd, 6) = g->guild_lv;
+ WFIFOL(fd, 10) = g->connect_member;
+ WFIFOL(fd, 14) = g->max_member;
+ WFIFOL(fd, 18) = g->average_lv;
+ WFIFOL(fd, 22) = (uint32)cap_value(g->exp, 0, INT32_MAX);
+ WFIFOL(fd, 26) = g->next_exp;
+ WFIFOL(fd, 30) = 0; // Tax Points
+ WFIFOL(fd, 34) = 0; // Honor: (left) Vulgar [-100,100] Famed (right)
+ WFIFOL(fd, 38) = 0; // Virtue: (down) Wicked [-100,100] Righteous (up)
+ WFIFOL(fd, 42) = g->emblem_id;
+ memcpy(WFIFOP(fd, 46), g->name, NAME_LENGTH);
+#if PACKETVER < 20160622
+ memcpy(WFIFOP(fd, 70), g->master, NAME_LENGTH);
+ safestrncpy(WFIFOP(fd, 94), msg_sd(sd, 300 + guild->checkcastles(g)), 16); // "'N' castles"
+ WFIFOL(fd, 110) = 0; // zeny
+#else
+ safestrncpy(WFIFOP(fd, 70), msg_sd(sd, 300 + guild->checkcastles(g)), 16); // "'N' castles"
+ WFIFOL(fd, 86) = 0; // zeny
+ WFIFOL(fd, 90) = g->member[0].char_id; // leader
+#endif
- WFIFOSET(fd,packet_len(0x1b6));
+ WFIFOSET(fd, packet_len(cmd));
}
/// Guild alliance and opposition list (ZC_MYGUILD_BASIC_INFO).
/// 014c <packet len>.W { <relation>.L <guild id>.L <guild name>.24B }*
-void clif_guild_allianceinfo(struct map_session_data *sd)
+static void clif_guild_allianceinfo(struct map_session_data *sd)
{
int fd,i,c;
struct guild *g;
@@ -7323,6 +8131,54 @@ void clif_guild_allianceinfo(struct map_session_data *sd)
WFIFOSET(fd,WFIFOW(fd,2));
}
+static void clif_guild_castlelist(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+ nullpo_retv(sd);
+
+ struct guild *g = sd->guild;
+ if (g == NULL)
+ return;
+
+ int castle_count = guild->checkcastles(g);
+ if (castle_count > 0) {
+ int len = sizeof(struct PACKET_ZC_GUILD_CASTLE_LIST) + castle_count;
+ struct PACKET_ZC_GUILD_CASTLE_LIST *p = aMalloc(len);
+ p->packetType = HEADER_ZC_GUILD_CASTLE_LIST;
+ p->packetLength = len;
+
+ int i = 0;
+ struct DBIterator *iter = db_iterator(guild->castle_db);
+ for (struct guild_castle *gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) {
+ if (gc->guild_id == g->guild_id) {
+ p->castle_list[i] = gc->castle_id;
+ ++i;
+ }
+ }
+ dbi_destroy(iter);
+
+ clif->send(p, len, &sd->bl, SELF);
+ aFree(p);
+ }
+#endif
+}
+
+static void clif_guild_castleinfo(struct map_session_data *sd, struct guild_castle *gc)
+{
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+
+ nullpo_retv(sd);
+ nullpo_retv(gc);
+
+ struct PACKET_ZC_CASTLE_INFO p = { 0 };
+ p.packetType = HEADER_ZC_CASTLE_INFO;
+ p.castle_id = gc->castle_id;
+ p.economy = gc->economy;
+ p.defense = gc->defense;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
/// Guild member manager information (ZC_MEMBERMGR_INFO).
/// 0154 <packet len>.W { <account>.L <char id>.L <hair style>.W <hair color>.W <gender>.W <class>.W <level>.W <contrib exp>.L <state>.L <position>.L <memo>.50B <name>.24B }*
/// state:
@@ -7330,45 +8186,58 @@ void clif_guild_allianceinfo(struct map_session_data *sd)
/// 1 = online
/// memo:
/// probably member's self-introduction (unused, no client UI/packets for editing it)
-void clif_guild_memberlist(struct map_session_data *sd)
+static void clif_guild_memberlist(struct map_session_data *sd)
{
int fd;
int i,c;
struct guild *g;
+#if PACKETVER < 20161026
+ const int cmd = 0x154;
+ const int size = 104;
+#else
+ const int cmd = 0xaa5;
+ const int size = 34;
+#endif
+
nullpo_retv(sd);
- if( (fd = sd->fd) == 0 )
+ if ((fd = sd->fd) == 0)
return;
- if( (g = sd->guild) == NULL )
+ if ((g = sd->guild) == NULL)
return;
- WFIFOHEAD(fd, g->max_member * 104 + 4);
- WFIFOW(fd, 0)=0x154;
- for(i=0,c=0;i<g->max_member;i++){
- struct guild_member *m=&g->member[i];
- if(m->account_id==0)
+ WFIFOHEAD(fd, g->max_member * size + 4);
+ WFIFOW(fd, 0) = cmd;
+ for (i = 0, c = 0; i < g->max_member; i++) {
+ struct guild_member *m = &g->member[i];
+ if (m->account_id == 0)
continue;
- WFIFOL(fd,c*104+ 4)=m->account_id;
- WFIFOL(fd,c*104+ 8)=m->char_id;
- WFIFOW(fd,c*104+12)=m->hair;
- WFIFOW(fd,c*104+14)=m->hair_color;
- WFIFOW(fd,c*104+16)=m->gender;
- WFIFOW(fd,c*104+18)=m->class_;
- WFIFOW(fd,c*104+20)=m->lv;
- WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX);
- WFIFOL(fd,c*104+26)=m->online;
- WFIFOL(fd,c*104+30)=m->position;
- memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty.
- memcpy(WFIFOP(fd,c*104+84),m->name,NAME_LENGTH);
+ WFIFOL(fd, c * size + 4) = m->account_id;
+ WFIFOL(fd, c * size + 8) = m->char_id;
+ WFIFOW(fd, c * size + 12) = m->hair;
+ WFIFOW(fd, c * size + 14) = m->hair_color;
+ WFIFOW(fd, c * size + 16) = m->gender;
+ WFIFOW(fd, c * size + 18) = m->class;
+ WFIFOW(fd, c * size + 20) = m->lv;
+ WFIFOL(fd, c * size + 22) = (int)cap_value(m->exp, 0, INT32_MAX);
+ WFIFOL(fd, c * size + 26) = m->online;
+ WFIFOL(fd, c * size + 30) = m->position;
+#if PACKETVER < 20161026
+ memset(WFIFOP(fd, c * size + 34), 0, 50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty.
+ memcpy(WFIFOP(fd, c * size + 84), m->name, NAME_LENGTH);
+#else
+ WFIFOL(fd, c * size + 34) = m->last_login; // [Megasantos] - Shows last date online
+#endif
c++;
}
- WFIFOW(fd, 2)=c*104+4;
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOW(fd, 2) = c * size + 4;
+ WFIFOSET(fd, WFIFOW(fd, 2));
}
/// Guild position name information (ZC_POSITION_ID_NAME_INFO).
/// 0166 <packet len>.W { <position id>.L <position name>.24B }*
-void clif_guild_positionnamelist(struct map_session_data *sd) {
+static void clif_guild_positionnamelist(struct map_session_data *sd)
+{
int i,fd;
struct guild *g;
@@ -7392,7 +8261,8 @@ void clif_guild_positionnamelist(struct map_session_data *sd) {
/// mode: @see enum guild_permission
/// ranking:
/// TODO
-void clif_guild_positioninfolist(struct map_session_data *sd) {
+static void clif_guild_positioninfolist(struct map_session_data *sd)
+{
int i,fd;
struct guild *g;
@@ -7419,7 +8289,7 @@ void clif_guild_positioninfolist(struct map_session_data *sd) {
/// mode: @see enum guild_permission
/// ranking:
/// TODO
-void clif_guild_positionchanged(struct guild *g,int idx)
+static void clif_guild_positionchanged(struct guild *g, int idx)
{
// FIXME: This packet is intended to update the clients after a
// commit of position info changes, not sending one packet per
@@ -7444,7 +8314,7 @@ void clif_guild_positionchanged(struct guild *g,int idx)
/// Notifies clients in a guild about updated member position assignments (ZC_ACK_REQ_CHANGE_MEMBERS).
/// 0156 <packet len>.W { <account id>.L <char id>.L <position id>.L }*
-void clif_guild_memberpositionchanged(struct guild *g,int idx)
+static void clif_guild_memberpositionchanged(struct guild *g, int idx)
{
// FIXME: This packet is intended to update the clients after a
// commit of member position assignment changes, not sending one
@@ -7467,7 +8337,7 @@ void clif_guild_memberpositionchanged(struct guild *g,int idx)
/// Sends emblems bitmap data to the client that requested it (ZC_GUILD_EMBLEM_IMG).
/// 0152 <packet len>.W <guild id>.L <emblem id>.L <emblem data>.?B
-void clif_guild_emblem(struct map_session_data *sd,struct guild *g)
+static void clif_guild_emblem(struct map_session_data *sd, struct guild *g)
{
int fd;
nullpo_retv(sd);
@@ -7488,7 +8358,7 @@ void clif_guild_emblem(struct map_session_data *sd,struct guild *g)
/// Sends update of the guild id/emblem id to everyone in the area (ZC_CHANGE_GUILD).
/// 01b4 <id>.L <guild id>.L <emblem id>.W
-void clif_guild_emblem_area(struct block_list* bl)
+static void clif_guild_emblem_area(struct block_list *bl)
{
uint8 buf[12];
@@ -7505,7 +8375,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 <upgradeable>.B }*
-void clif_guild_skillinfo(struct map_session_data* sd)
+static void clif_guild_skillinfo(struct map_session_data *sd)
{
int fd;
struct guild* g;
@@ -7544,7 +8414,7 @@ void clif_guild_skillinfo(struct map_session_data* sd)
/// Sends guild notice to client (ZC_GUILD_NOTICE).
/// 016f <subject>.60B <notice>.120B
-void clif_guild_notice(struct map_session_data* sd, struct guild* g)
+static void clif_guild_notice(struct map_session_data *sd, struct guild *g)
{
int fd;
@@ -7568,7 +8438,7 @@ void clif_guild_notice(struct map_session_data* sd, struct guild* g)
/// Guild invite (ZC_REQ_JOIN_GUILD).
/// 016a <guild id>.L <guild name>.24B
-void clif_guild_invite(struct map_session_data *sd,struct guild *g)
+static void clif_guild_invite(struct map_session_data *sd, struct guild *g)
{
int fd;
@@ -7590,7 +8460,8 @@ void clif_guild_invite(struct map_session_data *sd,struct guild *g)
/// 1 = Offer rejected.
/// 2 = Offer accepted.
/// 3 = Guild full.
-void clif_guild_inviteack(struct map_session_data *sd,int flag)
+/// 4 = Offline or not exists
+static void clif_guild_inviteack(struct map_session_data *sd, int flag)
{
int fd;
@@ -7605,88 +8476,96 @@ void clif_guild_inviteack(struct map_session_data *sd,int flag)
/// Notifies clients of a guild of a leaving member (ZC_ACK_LEAVE_GUILD).
/// 015a <char name>.24B <reason>.40B
-void clif_guild_leave(struct map_session_data *sd,const char *name,const char *mes)
+static void clif_guild_leave(struct map_session_data *sd, const char *name, int char_id, const char *mes)
{
- unsigned char buf[128];
-
nullpo_retv(sd);
+ nullpo_retv(name);
+ nullpo_retv(mes);
- WBUFW(buf, 0)=0x15a;
- memcpy(WBUFP(buf, 2),name,NAME_LENGTH);
- memcpy(WBUFP(buf,26),mes,40);
- clif->send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG);
+ struct PACKET_ZC_ACK_LEAVE_GUILD p;
+ p.packetType = guildLeave;
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+ p.GID = char_id;
+#else
+ safestrncpy(&p.name[0], name, NAME_LENGTH);
+#endif
+ safestrncpy(&p.reason[0], mes, 40);
+ clif->send(&p, sizeof(p), &sd->bl, GUILD_NOBG);
}
/// Notifies clients of a guild of an expelled member.
/// 015c <char name>.24B <reason>.40B <account name>.24B (ZC_ACK_BAN_GUILD)
/// 0839 <char name>.24B <reason>.40B (ZC_ACK_BAN_GUILD_SSO)
-void clif_guild_expulsion(struct map_session_data* sd, const char* name, const char* mes, int account_id)
+static void clif_guild_expulsion(struct map_session_data *sd, const char *name, int char_id, const char *mes, int account_id)
{
- unsigned char buf[128];
-#if PACKETVER < 20100803
- const unsigned short cmd = 0x15c;
-#else
- const unsigned short cmd = 0x839;
-#endif
-
nullpo_retv(sd);
nullpo_retv(name);
nullpo_retv(mes);
- WBUFW(buf,0) = cmd;
- safestrncpy(WBUFP(buf,2), name, NAME_LENGTH);
- safestrncpy(WBUFP(buf,26), mes, 40);
+ struct PACKET_ZC_ACK_BAN_GUILD p;
+ p.packetType = guildExpulsion;
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+ p.GID = char_id;
+#else
+ safestrncpy(&p.name[0], name, NAME_LENGTH);
+#endif
+ safestrncpy(&p.reason[0], mes, 40);
+
+// version unconfirmed
#if PACKETVER < 20100803
- memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons)
+ memset(&p.account_name, 0, NAME_LENGTH); // account name (not used for security reasons)
#endif
- clif->send(buf, packet_len(cmd), &sd->bl, GUILD_NOBG);
+ clif->send(&p, sizeof(p), &sd->bl, GUILD_NOBG);
}
/// Guild expulsion list (ZC_BAN_LIST).
/// 0163 <packet len>.W { <char name>.24B <account name>.24B <reason>.40B }*
/// 0163 <packet len>.W { <char name>.24B <reason>.40B }* (PACKETVER >= 20100803)
-void clif_guild_expulsionlist(struct map_session_data* sd) {
-#if PACKETVER < 20100803
- const int offset = NAME_LENGTH*2+40;
-#else
- const int offset = NAME_LENGTH+40;
-#endif
- int fd, i, c = 0;
- struct guild* g;
-
+static void clif_guild_expulsionlist(struct map_session_data *sd)
+{
nullpo_retv(sd);
- if( (g = sd->guild) == NULL )
+ int c = 0;
+
+ struct guild* g;
+ if ((g = sd->guild) == NULL)
return;
- fd = sd->fd;
+ int fd = sd->fd;
- WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * offset);
- WFIFOW(fd,0) = 0x163;
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_BAN_LIST) + MAX_GUILDEXPULSION * sizeof(struct PACKET_ZC_BAN_LIST_sub));
+ struct PACKET_ZC_BAN_LIST *packet = WFIFOP(fd, 0);
+ packet->packetType = HEADER_ZC_BAN_LIST;
- for( i = 0; i < MAX_GUILDEXPULSION; i++ )
+ for (int i = 0; i < MAX_GUILDEXPULSION; i++)
{
struct guild_expulsion* e = &g->expulsion[i];
- if( e->account_id > 0 )
+ if (e->account_id > 0)
{
- memcpy(WFIFOP(fd,4 + c*offset), e->name, NAME_LENGTH);
-#if PACKETVER < 20100803
- memset(WFIFOP(fd,4 + c*offset+24), 0, NAME_LENGTH); // account name (not used for security reasons)
- memcpy(WFIFOP(fd,4 + c*offset+48), e->mes, 40);
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+ packet->chars[c].char_id = e->char_id;
+// version unconfirmed
+#elif PACKETVER >= 20100803
+ memcpy(packet->chars[c].char_name, e->name, NAME_LENGTH);
+
#else
- memcpy(WFIFOP(fd,4 + c*offset+24), e->mes, 40);
+ memcpy(packet->chars[c].char_name, e->name, NAME_LENGTH);
+ memset(packet->chars[c].account_name, 0, NAME_LENGTH); // account name (not used for security reasons)
+
#endif
- c++;
+ memcpy(packet->chars[c].message, e->mes, 40);
+
+ c ++;
}
}
- WFIFOW(fd,2) = 4 + c*offset;
- WFIFOSET(fd,WFIFOW(fd,2));
+ packet->packetLen = sizeof(struct PACKET_ZC_BAN_LIST) + c * sizeof(struct PACKET_ZC_BAN_LIST_sub);
+ WFIFOSET(fd, packet->packetLen);
}
/// Guild chat message (ZC_GUILD_CHAT).
/// 017f <packet len>.W <message>.?B
-void clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
+static void clif_guild_message(struct guild *g, int account_id, const char *mes, int len)
{// TODO: account_id is not used, candidate for deletion? [Ai4rei]
struct map_session_data *sd;
uint8 buf[256];
@@ -7710,7 +8589,7 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
/// Request for guild alliance (ZC_REQ_ALLY_GUILD).
/// 0171 <inviter account id>.L <guild name>.24B
-void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const char *name)
+static void clif_guild_reqalliance(struct map_session_data *sd, int account_id, const char *name)
{
int fd;
@@ -7734,7 +8613,7 @@ void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const cha
/// 3 = They have too any alliances.
/// 4 = You have too many alliances.
/// 5 = Alliances are disabled.
-void clif_guild_allianceack(struct map_session_data *sd,int flag)
+static void clif_guild_allianceack(struct map_session_data *sd, int flag)
{
int fd;
@@ -7752,7 +8631,7 @@ void clif_guild_allianceack(struct map_session_data *sd,int flag)
/// relation:
/// 0 = Ally
/// 1 = Enemy
-void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag)
+static void clif_guild_delalliance(struct map_session_data *sd, int guild_id, int flag)
{
int fd;
@@ -7775,7 +8654,7 @@ void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag)
/// 1 = Guild has too many Antagonists.
/// 2 = Already set as an Antagonist.
/// 3 = Antagonists are disabled.
-void clif_guild_oppositionack(struct map_session_data *sd,int flag)
+static void clif_guild_oppositionack(struct map_session_data *sd, int flag)
{
int fd;
@@ -7790,8 +8669,8 @@ void clif_guild_oppositionack(struct map_session_data *sd,int flag)
/// Adds alliance or opposition (ZC_ADD_RELATED_GUILD).
/// 0185 <relation>.L <guild id>.L <guild name>.24B
-/*
-void clif_guild_allianceadded(struct guild *g,int idx)
+#if 0
+static void clif_guild_allianceadded(struct guild *g, int idx)
{
unsigned char buf[64];
WBUFW(buf,0)=0x185;
@@ -7800,14 +8679,14 @@ void clif_guild_allianceadded(struct guild *g,int idx)
memcpy(WBUFP(buf,10),g->alliance[idx].name,NAME_LENGTH);
clif->send(buf,packet_len(0x185),guild->getavailablesd(g),GUILD);
}
-*/
+#endif // 0
/// Notifies the client about the result of a guild break (ZC_ACK_DISORGANIZE_GUILD_RESULT).
/// 015e <reason>.L
/// 0 = success
/// 1 = invalid key (guild name, @see clif_parse_GuildBreak)
/// 2 = there are still members in the guild
-void clif_guild_broken(struct map_session_data *sd,int flag)
+static void clif_guild_broken(struct map_session_data *sd, int flag)
{
int fd;
@@ -7820,11 +8699,54 @@ void clif_guild_broken(struct map_session_data *sd,int flag)
WFIFOSET(fd,packet_len(0x15e));
}
+static void clif_guild_position_selected(struct map_session_data *sd)
+{
+#if PACKETVER >= 20180801
+ clif->guild_set_position(sd);
+#else
+ clif->charnameupdate(sd);
+#endif
+}
+
+static void clif_guild_set_position(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ int len = sizeof(struct PACKET_ZC_GUILD_POSITION);
+ const char *name = NULL;
+ if (sd->status.guild_id > 0) {
+ struct guild *g = sd->guild;
+
+ nullpo_retv(g);
+
+ int i = 0;
+ int ps = -1;
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == sd->status.account_id && g->member[i].char_id == sd->status.char_id);
+ if (i < g->max_member)
+ ps = g->member[i].position;
+
+ if (ps >= 0 && ps < MAX_GUILDPOSITION) {
+ len += 24;
+ name = g->position[ps].name;
+ }
+ }
+
+ unsigned char buf[sizeof(struct PACKET_ZC_GUILD_POSITION) + NAME_LENGTH];
+ struct PACKET_ZC_GUILD_POSITION *p = WBUFP(buf, 0);
+ p->packetType = 0xafd;
+ p->packetLength = len;
+ p->AID = sd->bl.id;
+ if (name != NULL)
+ memcpy(&p->position, name, 24);
+
+ clif->send(buf, len, &sd->bl, AREA);
+}
+
/// Displays emotion on an object (ZC_EMOTION).
/// 00c0 <id>.L <type>.B
/// type:
/// enum emotion_type
-void clif_emotion(struct block_list *bl,int type)
+static void clif_emotion(struct block_list *bl, int type)
{
unsigned char buf[8];
@@ -7838,21 +8760,21 @@ void clif_emotion(struct block_list *bl,int type)
/// Displays the contents of a talkiebox trap (ZC_TALKBOX_CHATCONTENTS).
/// 0191 <id>.L <contents>.80B
-void clif_talkiebox(struct block_list* bl, const char* talkie)
+static void clif_talkiebox(struct block_list *bl, const char *talkie)
{
- unsigned char buf[MESSAGE_SIZE+6];
nullpo_retv(bl);
nullpo_retv(talkie);
+ struct PACKET_ZC_TALKBOX_CHATCONTENTS p;
- WBUFW(buf,0) = 0x191;
- WBUFL(buf,2) = bl->id;
- safestrncpy(WBUFP(buf,6),talkie,MESSAGE_SIZE);
- clif->send(buf,packet_len(0x191),bl,AREA);
+ p.PacketType = HEADER_ZC_TALKBOX_CHATCONTENTS;
+ p.aid = bl->id;
+ safestrncpy(&p.message[0], talkie, TALKBOX_MESSAGE_SIZE);
+ clif->send(&p, sizeof(struct PACKET_ZC_TALKBOX_CHATCONTENTS), bl, AREA);
}
/// Displays wedding effect centered on an object (ZC_CONGRATULATION).
/// 01ea <id>.L
-void clif_wedding_effect(struct block_list *bl)
+static void clif_wedding_effect(struct block_list *bl)
{
unsigned char buf[6];
@@ -7865,7 +8787,8 @@ void clif_wedding_effect(struct block_list *bl)
/// Notifies the client of the name of the partner character (ZC_COUPLENAME).
/// 01e6 <partner name>.24B
-void clif_callpartner(struct map_session_data *sd) {
+static void clif_callpartner(struct map_session_data *sd)
+{
unsigned char buf[26];
nullpo_retv(sd);
@@ -7890,8 +8813,8 @@ void clif_callpartner(struct map_session_data *sd) {
/// Initiates the partner "taming" process [DracoRPG] (ZC_START_COUPLE).
/// 01e4
/// This packet while still implemented by the client is no longer being officially used.
-/*
-void clif_marriage_process(struct map_session_data *sd)
+#if 0
+static void clif_marriage_process(struct map_session_data *sd)
{
int fd;
nullpo_retv(sd);
@@ -7901,11 +8824,11 @@ void clif_marriage_process(struct map_session_data *sd)
WFIFOW(fd,0)=0x1e4;
WFIFOSET(fd,packet_len(0x1e4));
}
-*/
+#endif // 0
/// Notice of divorce (ZC_DIVORCE).
/// 0205 <partner name>.24B
-void clif_divorced(struct map_session_data* sd, const char* name)
+static void clif_divorced(struct map_session_data *sd, const char *name)
{
int fd;
nullpo_retv(sd);
@@ -7920,8 +8843,8 @@ void clif_divorced(struct map_session_data* sd, const char* name)
/// Marriage proposal (ZC_REQ_COUPLE).
/// 01e2 <account id>.L <char id>.L <char name>.24B
/// This packet while still implemented by the client is no longer being officially used.
-/*
-void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_session_data* ssd)
+#if 0
+static void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_session_data *ssd)
{
nullpo_retv(sd);
@@ -7932,24 +8855,26 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess
safestrncpy(WFIFOP(fd,10), ssd->status.name, NAME_LENGTH);
WFIFOSET(fd, packet_len(0x1e2));
}
-*/
+#endif // 0
/*==========================================
* Displays a message using the guild-chat colors to the specified targets. [Skotlex]
*------------------------------------------*/
-void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target)
+static void clif_disp_message(struct block_list *src, const char *mes, enum send_target target)
{
unsigned char buf[256];
+ int len;
+
+ nullpo_retv(mes);
+ nullpo_retv(src);
+ len = (int)strlen(mes);
if (len == 0)
return;
- nullpo_retv(src);
- nullpo_retv(mes);
-
- if (len > sizeof(buf)-5) {
- ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
- len = sizeof(buf)-5;
+ if (len > (int)sizeof(buf)-5) {
+ ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
+ len = (int)sizeof(buf)-5;
}
WBUFW(buf, 0) = 0x17f;
@@ -7964,7 +8889,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 result)
+static void clif_GM_kickack(struct map_session_data *sd, int result)
{
int fd;
@@ -7977,7 +8902,8 @@ void clif_GM_kickack(struct map_session_data *sd, int result)
WFIFOSET(fd, packet_len(0xcd));
}
-void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) {
+static void clif_GM_kick(struct map_session_data *sd, struct map_session_data *tsd)
+{
int fd;
nullpo_retv(tsd);
@@ -8001,7 +8927,7 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) {
/// 3 = "Chat Block has been applied by GM due to your ill-mannerous action."
/// 4 = "Automated Chat Block has been applied due to Anti-Spam System."
/// 5 = "You got a good point from %s."
-void clif_manner_message(struct map_session_data* sd, uint32 type)
+static void clif_manner_message(struct map_session_data *sd, uint32 type)
{
int fd;
nullpo_retv(sd);
@@ -8018,7 +8944,7 @@ void clif_manner_message(struct map_session_data* sd, uint32 type)
/// type:
/// 0 = positive (unmute)
/// 1 = negative (mute)
-void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, uint8 type)
+static void clif_GM_silence(struct map_session_data *sd, struct map_session_data *tsd, uint8 type)
{
int fd;
nullpo_retv(sd);
@@ -8041,7 +8967,8 @@ void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd,
/// 0 = success
/// 1 = failure
/// 2 = too many blocks
-void clif_wisexin(struct map_session_data *sd,int type,int flag) {
+static void clif_wisexin(struct map_session_data *sd, int type, int flag)
+{
int fd;
nullpo_retv(sd);
@@ -8062,7 +8989,8 @@ void clif_wisexin(struct map_session_data *sd,int type,int flag) {
/// result:
/// 0 = success
/// 1 = failure
-void clif_wisall(struct map_session_data *sd,int type,int flag) {
+static void clif_wisall(struct map_session_data *sd, int type, int flag)
+{
int fd;
nullpo_retv(sd);
@@ -8077,7 +9005,7 @@ void clif_wisall(struct map_session_data *sd,int type,int flag) {
/// Play a BGM! [Rikter/Yommy] (ZC_PLAY_NPC_BGM).
/// 07fe <bgm>.24B
-void clif_playBGM(struct map_session_data* sd, const char* name)
+static void clif_playBGM(struct map_session_data *sd, const char *name)
{
int fd;
@@ -8103,7 +9031,7 @@ void clif_playBGM(struct map_session_data* sd, const char* name)
/// npc id:
/// 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)
+static void clif_soundeffect(struct map_session_data *sd, struct block_list *bl, const char *name, int type)
{
int fd;
@@ -8121,7 +9049,7 @@ void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const
WFIFOSET(fd,packet_len(0x1d3));
}
-void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum send_target coverage)
+static void clif_soundeffectall(struct block_list *bl, const char *name, int type, enum send_target coverage)
{
unsigned char buf[40];
@@ -8140,7 +9068,7 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum
/// 01f3 <id>.L <effect id>.L
/// effect id:
/// @see doc/effect_list.txt
-void clif_specialeffect(struct block_list* bl, int type, enum send_target target)
+static void clif_specialeffect(struct block_list *bl, int type, enum send_target target)
{
unsigned char buf[24];
@@ -8154,13 +9082,14 @@ void clif_specialeffect(struct block_list* bl, int type, enum send_target target
clif->send(buf, packet_len(0x1f3), bl, target);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x1f3), bl, SELF);
}
}
-void clif_specialeffect_single(struct block_list* bl, int type, int fd) {
+static void clif_specialeffect_single(struct block_list *bl, int type, int fd)
+{
nullpo_retv(bl);
WFIFOHEAD(fd,10);
WFIFOW(fd,0) = 0x1f3;
@@ -8175,23 +9104,84 @@ void clif_specialeffect_single(struct block_list* bl, int type, int fd) {
/// @see doc/effect_list.txt
/// num data:
/// effect-dependent value
-void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, send_target target)
+static void clif_specialeffect_value(struct block_list *bl, int effect_id, uint64 num, send_target target)
+{
+#if PACKETVER_MAIN_NUM >= 20060911 || PACKETVER_AD_NUM >= 20060911 || PACKETVER_SAK_NUM >= 20060911 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO)
+ struct PACKET_ZC_NOTIFY_EFFECT3 packet;
+ packet.packetType = HEADER_ZC_NOTIFY_EFFECT3;
+ packet.aid = bl->id;
+ packet.effectId = effect_id;
+#if PACKETVER >= 20191127
+ packet.num = num;
+#else
+ packet.num = (uint32)num;
+#endif
+
+ clif->send(&packet, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3), bl, target);
+
+ if (clif->isdisguised(bl)) {
+ packet.aid = -bl->id;
+ clif->send(&packet, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3), bl, SELF);
+ }
+#endif
+}
+
+static void clif_specialeffect_value_single(struct block_list *bl, int effect_id, uint64 num, int fd)
{
- uint8 buf[14];
+#if PACKETVER_MAIN_NUM >= 20060911 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO)
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3));
- WBUFW(buf,0) = 0x284;
- WBUFL(buf,2) = bl->id;
- WBUFL(buf,6) = effect_id;
- WBUFL(buf,10) = num;
+ struct PACKET_ZC_NOTIFY_EFFECT3 *packet = WFIFOP(fd, 0);
+ packet->packetType = HEADER_ZC_NOTIFY_EFFECT3;
+ packet->aid = bl->id;
+ packet->effectId = effect_id;
+#if PACKETVER >= 20191127
+ packet->num = num;
+#else
+ packet->num = (uint32)num;
+#endif
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3));
+#endif
+}
- clif->send(buf, packet_len(0x284), bl, target);
+/// Remove special effects (ZC_REMOVE_EFFECT).
+/// 0b0d <id>.L <effect id>.L
+/// effect id:
+/// @see doc/effect_list.txt
+static void clif_removeSpecialEffect(struct block_list *bl, int effectId, enum send_target target)
+{
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+ nullpo_retv(bl);
- if( disguised(bl) )
- {
- WBUFL(buf,2) = -bl->id;
- clif->send(buf, packet_len(0x284), bl, SELF);
+ struct PACKET_ZC_REMOVE_EFFECT p;
+ p.packetType = 0xb0d;
+ p.aid = bl->id;
+ p.effectId = effectId;
+
+ clif->send(&p, sizeof(p), bl, target);
+
+ if (clif->isdisguised(bl)) {
+ p.aid = -bl->id;
+ clif->send(&p, sizeof(p), bl, SELF);
}
+#endif
+}
+
+static void clif_removeSpecialEffect_single(struct block_list *bl, int effectId, struct block_list *targetBl)
+{
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+ nullpo_retv(bl);
+ nullpo_retv(targetBl);
+
+ struct PACKET_ZC_REMOVE_EFFECT p;
+ p.packetType = 0xb0d;
+ p.aid = bl->id;
+ p.effectId = effectId;
+
+ clif->send(&p, sizeof(p), targetBl, SELF);
+#endif
}
+
/**
* Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead).
*
@@ -8201,12 +9191,13 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
* @param color Message color (RGB format: 0xRRGGBB)
* @param msg Message text
*/
-void clif_messagecolor_self(int fd, uint32 color, const char *msg)
+static void clif_messagecolor_self(int fd, uint32 color, const char *msg)
{
- size_t msg_len;
+ int msg_len;
nullpo_retv(msg);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
@@ -8226,17 +9217,19 @@ void clif_messagecolor_self(int fd, uint32 color, const char *msg)
* @param color Message color (RGB format: 0xRRGGBB)
* @param msg Message text
*/
-void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg)
+static void clif_messagecolor(struct block_list *bl, uint32 color, const char *msg)
{
- size_t msg_len = strlen(msg) + 1;
+ int msg_len;
uint8 buf[256];
nullpo_retv(bl);
nullpo_retv(msg);
- if (msg_len > sizeof(buf)-12) {
- ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len);
- msg_len = sizeof(buf)-12;
+ msg_len = (int)strlen(msg) + 1;
+
+ if (msg_len > (int)sizeof(buf)-12) {
+ ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%d).\n", msg, msg_len);
+ msg_len = (int)sizeof(buf)-12;
}
WBUFW(buf,0) = 0x2C1;
@@ -8248,20 +9241,50 @@ void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg)
clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
}
+// Message without owner, not logged in chat
+static void clif_serviceMessageColor(struct map_session_data *sd, uint32 color, const char *msg)
+{
+#if PACKETVER_MAIN_NUM >= 20170830 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+ nullpo_retv(msg);
+
+ int msg_len = (int)strlen(msg) + 1;
+
+ if (msg_len > 512) {
+ ShowWarning("clif_serviceMessageColor: Truncating too long message '%s' (len=%d).\n", msg, msg_len);
+ msg_len = 512;
+ }
+
+ const int len = sizeof(struct PACKET_ZC_SERVICE_MESSAGE_COLOR) + msg_len;
+ const int fd = sd->fd;
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_SERVICE_MESSAGE_COLOR *p = WFIFOP(fd, 0);
+
+ p->packetType = HEADER_ZC_SERVICE_MESSAGE_COLOR;
+ p->packetLength = len;
+ p->color = RGB2BGR(color);
+ safestrncpy(p->message, msg, msg_len);
+
+ WFIFOSET(fd, len);
+#endif
+}
+
/**
* 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)
+static void clif_refresh_storagewindow(struct map_session_data *sd)
{
nullpo_retv(sd);
// Notify the client that the storage is open
if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) {
- storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+ if (sd->storage.aggregate > 0) {
+ storage->sortitem(VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item));
+ }
+ clif->storageList(sd, VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item));
+ clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE);
}
// Notify the client that the gstorage is open otherwise it will
// remain locked forever and nobody will be able to access it
@@ -8272,21 +9295,21 @@ void clif_refresh_storagewindow(struct map_session_data *sd)
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->guildStorageList(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)
+static void clif_refresh(struct map_session_data *sd)
{
nullpo_retv(sd);
clif->changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
- clif->inventorylist(sd);
+ clif->inventoryList(sd);
if(pc_iscarton(sd)) {
- clif->cartlist(sd);
+ clif->cartList(sd);
clif->updatestatus(sd,SP_CARTINFO);
}
clif->updatestatus(sd,SP_WEIGHT);
@@ -8316,7 +9339,7 @@ void clif_refresh(struct map_session_data *sd)
clif->elemental_info(sd);
map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif->weather_check(sd);
- if( sd->chatID )
+ if (sd->chat_id != 0)
chat->leave(sd, false);
if( sd->state.vending )
clif->openvending(sd, sd->bl.id, sd->vending);
@@ -8332,7 +9355,9 @@ void clif_refresh(struct map_session_data *sd)
mail->clear(sd);
- if( disguised(&sd->bl) ) {/* refresh-da */
+ clif->loadConfirm(sd);
+
+ if (clif->isdisguised(&sd->bl)) {/* refresh-da */
short disguise = sd->disguise;
pc->disguise(sd, -1);
pc->disguise(sd, disguise);
@@ -8341,193 +9366,505 @@ void clif_refresh(struct map_session_data *sd)
clif->refresh_storagewindow(sd);
}
+static void clif_send_selforarea(int fd, struct block_list *bl, const void *buf, int len)
+{
+ // if no recipient specified just update nearby clients
+ // if no recipient specified just update nearby clients
+ if (fd == 0) {
+ clif->send(buf, len, bl, AREA);
+ } else {
+ struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL;
+ if (sd != NULL) {
+ clif->send(buf, len, &sd->bl, SELF);
+ } else {
+ clif->send(buf, len, bl, SELF);
+ }
+ }
+}
+
+/**
+ * Updates a character's name on client.
+ *
+ * @code
+ * 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+ * 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+ * 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param bl The related character's block list.
+ *
+ **/
+static void clif_pcname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_PC);
+
+ struct PACKET_ZC_ACK_REQNAMEALL packet = {0};
+ packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+ packet.gid = bl->id;
+
+ const struct map_session_data *ssd = BL_UCCAST(BL_PC, bl);
+
+ if (ssd->fd == fd && ssd->disguise != -1) // Requesting your own "shadow" name.
+ packet.gid = -bl->id;
+
+ if (ssd->fakename[0] != '\0')
+ memcpy(packet.name, ssd->fakename, NAME_LENGTH);
+ else
+ memcpy(packet.name, ssd->status.name, NAME_LENGTH);
+
+ const struct party_data *p = NULL;
+
+ if (ssd->status.party_id != 0)
+ p = party->search(ssd->status.party_id);
+
+ const struct guild *g = NULL;
+ int pos_idx = INDEX_NOT_FOUND;
+
+ if (ssd->status.guild_id != 0 && (g = ssd->guild) != NULL) {
+ int i;
+ int acc_id = ssd->status.account_id;
+ int chr_id = ssd->status.char_id;
+
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == acc_id && g->member[i].char_id == chr_id);
+
+ if (i < g->max_member)
+ pos_idx = g->member[i].position;
+ }
+
+ if (battle_config.display_party_name == 0 && g == NULL)
+ p = NULL; // Do not display party name, unless the character is also in a guild.
+
+ if (p != NULL) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_PARTYNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.party_name, p->party.name, NAME_LENGTH);
+ }
+ }
+
+ if (g != NULL && pos_idx >= 0 && pos_idx < MAX_GUILDPOSITION) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.guild_name, g->name,NAME_LENGTH);
+ }
+
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, g->position[pos_idx].name, NAME_LENGTH);
+ }
+ } else if (ssd->status.clan_id != 0) {
+ struct clan *c = clan->search(ssd->status.clan_id);
+
+ if (c != 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_CLANPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, c->name, NAME_LENGTH);
+ }
+ }
+ }
+
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO) // Title system.
+ if (ssd->status.title_id > 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_TITLE) != 0)
+ || ssd->fakename[0] == '\0') {
+ packet.title_id = ssd->status.title_id;
+ }
+ }
+#endif
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAMEALL));
+}
+
/// Updates the object's (bl) name on client.
/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
-void clif_charnameack (int fd, struct block_list *bl)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_homname_ack(int fd, struct block_list *bl)
{
- unsigned char buf[103];
- int cmd = 0x95;
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_HOM);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ memcpy(packet.name, BL_UCCAST(BL_HOM, bl)->homunculus.name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_mername_ack(int fd, struct block_list *bl)
+{
nullpo_retv(bl);
+ Assert_retv(bl->type == BL_MER);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ memcpy(packet.name, BL_UCCAST(BL_MER, bl)->db->name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
- WBUFW(buf,0) = cmd;
- WBUFL(buf,2) = bl->id;
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
- switch( bl->type ) {
- case BL_PC:
- {
- const struct map_session_data *ssd = BL_UCCAST(BL_PC, bl);
- const struct party_data *p = NULL;
- const struct guild *g = NULL;
- int ps = -1;
-
- //Requesting your own "shadow" name. [Skotlex]
- if (ssd->fd == fd && ssd->disguise != -1)
- WBUFL(buf,2) = -bl->id;
-
- if (ssd->fakename[0] != '\0') {
- WBUFW(buf, 0) = cmd = 0x195;
- memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH);
- WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0;
- break;
- }
- memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_petname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_PET);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ memcpy(packet.name, BL_UCCAST(BL_PET, bl)->pet.name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
- if (ssd->status.party_id != 0) {
- p = party->search(ssd->status.party_id);
- }
- if (ssd->status.guild_id != 0) {
- if ((g = ssd->guild) != NULL) {
- int i;
- ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
- if (i < g->max_member)
- ps = g->member[i].position;
- }
- }
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
- if (!battle_config.display_party_name && g == NULL) {
- // do not display party unless the player is also in a guild
- p = NULL;
- }
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_npcname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_NPC);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ memcpy(packet.name, BL_UCCAST(BL_NPC, bl)->name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
- if (p == NULL && g == NULL)
- break;
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
- WBUFW(buf, 0) = cmd = 0x195;
- if (p != NULL)
- memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH);
- else
- WBUFB(buf,30) = 0;
-
- if (g != NULL && ps >= 0 && ps < MAX_GUILDPOSITION) {
- memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
- memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
- } else { //Assume no guild.
- WBUFB(buf,54) = 0;
- WBUFB(buf,78) = 0;
- }
- }
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_mobname_guardian_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_MOB);
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ Assert_retv(md->guardian_data && md->guardian_data->g);
+
+ struct PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+ packet.gid = bl->id;
+ memcpy(packet.name, md->name, NAME_LENGTH);
+ memcpy(packet.guild_name, md->guardian_data->g->name, NAME_LENGTH);
+ memcpy(packet.position_name, md->guardian_data->castle->castle_name, NAME_LENGTH);
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAMEALL));
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_mobname_normal_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_MOB);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ memcpy(packet.name, md->name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_mobname_additional_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_MOB);
+
+ struct PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+ packet.gid = bl->id;
+
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+
+ memcpy(packet.name, md->name, NAME_LENGTH);
+ char mobhp[100];
+ char *str_p = mobhp;
+ if (battle_config.show_mob_info&4)
+ str_p += sprintf(str_p, "Lv. %d | ", md->level);
+ if (battle_config.show_mob_info&1)
+ str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp);
+ if (battle_config.show_mob_info&2)
+ str_p += sprintf(str_p, "HP: %u%% | ", get_percentage(md->status.hp, md->status.max_hp));
+ //Even thought mobhp ain't a name, we send it as one so the client
+ //can parse it. [Skotlex]
+ if (str_p != mobhp) {
+ *(str_p-3) = '\0'; //Remove trailing space + pipe.
+ memcpy(packet.party_name, mobhp, NAME_LENGTH);
+ }
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAMEALL));
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_mobname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_MOB);
+
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+
+ if (md->guardian_data && md->guardian_data->g) {
+ clif->mobname_guardian_ack(fd, bl);
+ } else if (battle_config.show_mob_info) {
+ clif->mobname_additional_ack(fd, bl);
+ } else {
+ clif->mobname_normal_ack(fd, bl);
+ }
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_chatname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_CHAT);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+
+#if 0 // Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex]
+ memcpy(packet.name, BL_UCCAST(BL_CHAT, bl)->title, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
+#endif
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
+
+/// Updates the object's (bl) name on client.
+/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+static void clif_elemname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ Assert_retv(bl->type == BL_ELEM);
+
+ struct PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+ packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+ packet.gid = bl->id;
+ memcpy(packet.name, BL_UCCAST(BL_ELEM, bl)->db->name, NAME_LENGTH);
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud != NULL) {
+ memcpy(packet.title, ud->title, NAME_LENGTH);
+ packet.groupId = ud->groupId;
+ }
+#endif
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
+}
+
+static void clif_skillname_ack(int fd, struct block_list *bl)
+{
+}
+
+static void clif_itemname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ ShowError("clif_itemname_ack: bad type %u(%d)\n", bl->type, bl->id);
+ Assert_retv(0);
+}
+
+static void clif_unknownname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ ShowError("clif_blname_ack: bad type %u(%d)\n", bl->type, bl->id);
+ Assert_retv(0);
+}
+
+static void clif_blname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+
+ switch(bl->type) {
+ case BL_PC:
+ clif->pcname_ack(fd, bl);
break;
- //[blackhole89]
case BL_HOM:
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_HOM, bl)->homunculus.name, NAME_LENGTH);
+ clif->homname_ack(fd, bl);
break;
case BL_MER:
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_MER, bl)->db->name, NAME_LENGTH);
+ clif->mername_ack(fd, bl);
break;
case BL_PET:
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_PET, bl)->pet.name, NAME_LENGTH);
+ clif->petname_ack(fd, bl);
break;
case BL_NPC:
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_NPC, bl)->name, NAME_LENGTH);
+ clif->npcname_ack(fd, bl);
break;
case BL_MOB:
- {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
-
- memcpy(WBUFP(buf,6), md->name, NAME_LENGTH);
- if (md->guardian_data && md->guardian_data->g) {
- WBUFW(buf, 0) = cmd = 0x195;
- WBUFB(buf,30) = 0;
- 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) {
- char mobhp[50], *str_p = mobhp;
- WBUFW(buf, 0) = cmd = 0x195;
- if (battle_config.show_mob_info&4)
- str_p += sprintf(str_p, "Lv. %d | ", md->level);
- if (battle_config.show_mob_info&1)
- str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp);
- if (battle_config.show_mob_info&2)
- str_p += sprintf(str_p, "HP: %u%% | ", get_percentage(md->status.hp, md->status.max_hp));
- //Even thought mobhp ain't a name, we send it as one so the client
- //can parse it. [Skotlex]
- if (str_p != mobhp) {
- *(str_p-3) = '\0'; //Remove trailing space + pipe.
- memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH);
- WBUFB(buf,54) = 0;
- WBUFB(buf,78) = 0;
- }
- }
- }
+ clif->mobname_ack(fd, bl);
break;
case BL_CHAT:
-#if 0 //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex]
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_CHAT, bl)->title, NAME_LENGTH);
+ clif->chatname_ack(fd, bl);
break;
-#endif
- return;
case BL_ELEM:
- memcpy(WBUFP(buf,6), BL_UCCAST(BL_ELEM, bl)->db->name, NAME_LENGTH);
+ clif->elemname_ack(fd, bl);
+ break;
+ case BL_ITEM:
+ clif->itemname_ack(fd, bl);
+ break;
+ case BL_SKILL:
+ clif->skillname_ack(fd, bl);
break;
default:
- ShowError("clif_charnameack: bad type %u(%d)\n", bl->type, bl->id);
- return;
- }
-
- // if no recipient specified just update nearby clients
- if (fd == 0) {
- clif->send(buf, packet_len(cmd), bl, AREA);
- } else {
- WFIFOHEAD(fd, packet_len(cmd));
- memcpy(WFIFOP(fd, 0), buf, packet_len(cmd));
- WFIFOSET(fd, packet_len(cmd));
+ clif->unknownname_ack(fd, bl);
+ break;
}
}
-//Used to update when a char leaves a party/guild. [Skotlex]
-//Needed because when you send a 0x95 packet, the client will not remove the cached party/guild info that is not sent.
-void clif_charnameupdate (struct map_session_data *ssd)
+/**
+ * Updates a character's name on client when leaving a party/guild.
+ *
+ * @code
+ * 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+ * 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+ * @endcode
+ *
+ * @param ssd The related character.
+ *
+ **/
+static void clif_charnameupdate(struct map_session_data *ssd)
{
- unsigned char buf[103];
- int cmd = 0x195, ps = -1;
+ nullpo_retv(ssd);
+
+ struct PACKET_ZC_ACK_REQNAMEALL packet = {0};
+ packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+ packet.gid = ssd->bl.id;
+
+ if (ssd->fakename[0] != '\0')
+ memcpy(packet.name, ssd->fakename, NAME_LENGTH);
+ else
+ memcpy(packet.name, ssd->status.name, NAME_LENGTH);
+
struct party_data *p = NULL;
- struct guild *g = NULL;
- nullpo_retv(ssd);
+ if (ssd->status.party_id != 0)
+ p = party->search(ssd->status.party_id);
- if( ssd->fakename[0] )
- return; //No need to update as the party/guild was not displayed anyway.
+ struct guild *g = NULL;
+ int pos_idx = INDEX_NOT_FOUND;
- WBUFW(buf,0) = cmd;
- WBUFL(buf,2) = ssd->bl.id;
+ if (ssd->status.guild_id != 0 && (g = ssd->guild) != NULL) {
+ int i;
+ int acc_id = ssd->status.account_id;
+ int chr_id = ssd->status.char_id;
- memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == acc_id && g->member[i].char_id == chr_id);
- if (!battle_config.display_party_name) {
- if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = ssd->guild) != NULL)
- p = party->search(ssd->status.party_id);
- }else{
- if (ssd->status.party_id > 0)
- p = party->search(ssd->status.party_id);
+ if (i < g->max_member)
+ pos_idx = g->member[i].position;
}
- if( ssd->status.guild_id > 0 && (g = ssd->guild) != NULL )
- {
- int i;
- ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
- if( i < g->max_member ) ps = g->member[i].position;
+ if (battle_config.display_party_name == 0 && g == NULL)
+ p = NULL; // Do not display party name, unless the character is also in a guild.
+
+ if (p != NULL) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_PARTYNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.party_name, p->party.name, NAME_LENGTH);
+ }
}
- if( p )
- memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH);
- else
- WBUFB(buf,30) = 0;
+ if (g != NULL && pos_idx >= 0 && pos_idx < MAX_GUILDPOSITION) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.guild_name, g->name,NAME_LENGTH);
+ }
- if( g && ps >= 0 && ps < MAX_GUILDPOSITION )
- {
- memcpy(WBUFP(buf,54), g->name,NAME_LENGTH);
- memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH);
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, g->position[pos_idx].name, NAME_LENGTH);
+ }
+ } else if (ssd->status.clan_id != 0) {
+ struct clan *c = clan->search(ssd->status.clan_id);
+
+ if (c != 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_CLANPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, c->name, NAME_LENGTH);
+ }
+ }
}
- else
- {
- WBUFB(buf,54) = 0;
- WBUFB(buf,78) = 0;
+
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO) // Title system.
+ if (ssd->status.title_id > 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_TITLE) != 0)
+ || ssd->fakename[0] == '\0') {
+ packet.title_id = ssd->status.title_id;
+ }
}
+#endif
- // Update nearby clients
- clif->send(buf, packet_len(cmd), &ssd->bl, AREA);
+ clif->send(&packet, sizeof(packet), &ssd->bl, AREA); // Update nearby clients.
}
/// Taekwon Jump (TK_HIGHJUMP) effect (ZC_HIGHJUMP).
@@ -8536,7 +9873,7 @@ void clif_charnameupdate (struct map_session_data *ssd)
/// Visually moves(instant) a character to x,y. The char moves even
/// when the target cell isn't walkable. If the char is sitting it
/// stays that way.
-void clif_slide(struct block_list *bl, int x, int y)
+static void clif_slide(struct block_list *bl, int x, int y)
{
unsigned char buf[10];
nullpo_retv(bl);
@@ -8547,8 +9884,7 @@ void clif_slide(struct block_list *bl, int x, int y)
WBUFW(buf, 8) = y;
clif->send(buf, packet_len(0x1ff), bl, AREA);
- if( disguised(bl) )
- {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x1ff), bl, SELF);
}
@@ -8556,41 +9892,65 @@ void clif_slide(struct block_list *bl, int x, int y)
/// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well
/// 008d <packet len>.W <id>.L <message>.?B
-void clif_disp_overhead(struct block_list *bl, const char* mes)
+static void clif_disp_overhead(struct block_list *bl, const char *mes, enum send_target target, struct block_list *target_bl)
{
- 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;
+ char buf[CHAT_SIZE_MAX + (int)sizeof(struct PACKET_ZC_NOTIFY_CHAT)];
+ int max_len = CHAT_SIZE_MAX - (int)sizeof(struct PACKET_ZC_NOTIFY_CHAT);
+ struct PACKET_ZC_NOTIFY_CHAT *p = (struct PACKET_ZC_NOTIFY_CHAT *)&buf;
+ int mes_len;
nullpo_retv(bl);
nullpo_retv(mes);
- len_mes = strlen(mes)+1; //Account for \0
- if (len_mes > sizeof(buf)-8) {
- ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes);
- len_mes = sizeof(buf)-8; //Trunk it to avoid problems.
+ mes_len = (int)strlen(mes) + 1; //Account for \0
+ if (mes_len > max_len) {
+ ShowError("clif_disp_overhead: Truncated message '%s' (len=%d, max=%d).\n", mes, mes_len, max_len);
+ mes_len = max_len; //Trunk it to avoid problems.
}
+
// send message to others
- WBUFW(buf,0) = 0x8d;
- WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id)
- WBUFL(buf,4) = bl->id;
- safestrncpy(WBUFP(buf,8), mes, len_mes);
- clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
+ p->PacketType = 0x8d;
+ p->PacketLength = mes_len + (int)sizeof(struct PACKET_ZC_NOTIFY_CHAT); // len of message + 8 (command+len+id)
+ p->GID = bl->id;
+ safestrncpy(p->Message, mes, mes_len);
+ if (target == SELF && target_bl != NULL) {
+ clif->send(p, p->PacketLength, target_bl, SELF);
+ } else {
+ clif->send(p, p->PacketLength, bl, AREA_CHAT_WOC);
- // send back message to the speaker
- if( bl->type == BL_PC ) {
- WBUFW(buf,0) = 0x8e;
- WBUFW(buf, 2) = len_mes + 4;
- safestrncpy(WBUFP(buf,4), mes, len_mes);
- clif->send(buf, WBUFW(buf,2), bl, SELF);
+ // send back message to the speaker
+ if (bl->type == BL_PC)
+ clif->notify_playerchat(bl, mes);
+ }
+}
+
+static void clif_notify_playerchat(struct block_list *bl, const char *mes)
+{
+ char buf[CHAT_SIZE_MAX + (int)sizeof(struct PACKET_ZC_NOTIFY_PLAYERCHAT)];
+ int max_len = CHAT_SIZE_MAX - (int)sizeof(struct PACKET_ZC_NOTIFY_PLAYERCHAT);
+ struct PACKET_ZC_NOTIFY_PLAYERCHAT *p = (struct PACKET_ZC_NOTIFY_PLAYERCHAT *)&buf;
+ int mes_len;
+
+ nullpo_retv(bl);
+ nullpo_retv(mes);
+
+ mes_len = (int)strlen(mes) + 1; // Account for \0
+ if (mes_len > max_len) {
+ ShowError("clif_notify_playerchat: Truncated message '%s' (len=%d, max=%d).\n", mes, mes_len, max_len);
+ mes_len = max_len; // Truncate to avoid problems.
}
+ p->PacketType = 0x8e;
+ p->PacketLength = mes_len + (int)sizeof(struct PACKET_ZC_NOTIFY_PLAYERCHAT);
+ safestrncpy(p->Message, mes, mes_len);
+ clif->send(p, p->PacketLength, bl, SELF);
}
/*==========================
* Minimap fix [Kevin]
* Remove dot from minimap
*--------------------------*/
-void clif_party_xy_remove(struct map_session_data *sd)
+static void clif_party_xy_remove(struct map_session_data *sd)
{
unsigned char buf[16];
nullpo_retv(sd);
@@ -8616,7 +9976,7 @@ void clif_party_xy_remove(struct map_session_data *sd)
/// 0x20 = HIT/Flee +50 (PA_GOSPEL)
/// 0x28 = Full strip failed because of coating (ST_FULLSTRIP)
/// ? = nothing
-void clif_gospel_info(struct map_session_data *sd, int type)
+static void clif_gospel_info(struct map_session_data *sd, int type)
{
int fd;
@@ -8657,7 +10017,7 @@ void clif_gospel_info(struct map_session_data *sd, int type)
/// 22 = [Collector Rank] Target Item : <monster_id used as item id>
/// 30 = [Sun, Moon and Stars Angel] Designed places and monsters have been reset.
/// 40 = Target HP : <monster_id used as HP>
-void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result)
+static void clif_starskill(struct map_session_data *sd, const char *mapname, int monster_id, unsigned char star, unsigned char result)
{
int fd;
@@ -8678,7 +10038,7 @@ void clif_starskill(struct map_session_data* sd, const char* mapname, int monste
* 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)
+static void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type)
{
char mapname[MAP_NAME_LENGTH_EXT];
@@ -8692,7 +10052,7 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig
* 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)
+static void clif_hate_info(struct map_session_data *sd, unsigned char hate_level, int class_, unsigned char type)
{
if( pc->db_checkid(class_) ) {
clif->starskill(sd, pc->job_name(class_), class_, hate_level, type ? 10 : 11);
@@ -8706,7 +10066,7 @@ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int cl
/*==========================================
* Info about TaeKwon Do TK_MISSION mob [Skotlex]
*------------------------------------------*/
-void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress)
+static void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress)
{
clif->starskill(sd, mob->db(mob_id)->jname, mob_id, progress, 20);
}
@@ -8714,19 +10074,20 @@ void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char pr
/*==========================================
* Feel/Hate reset (thanks to Rayce) [Skotlex]
*------------------------------------------*/
-void clif_feel_hate_reset(struct map_session_data *sd)
+static void clif_feel_hate_reset(struct map_session_data *sd)
{
clif->starskill(sd, "", 0, 0, 30);
}
-/// Equip window (un)tick ack (ZC_CONFIG).
+/// Send configurations (ZC_CONFIG).
/// 02d9 <type>.L <value>.L
/// type:
/// 0 = open equip window
+/// 3 = homunculus autofeeding
/// value:
/// 0 = disabled
/// 1 = enabled
-void clif_equiptickack(struct map_session_data* sd, int flag)
+static void clif_zc_config(struct map_session_data *sd, enum CZ_CONFIG type, int flag)
{
int fd;
nullpo_retv(sd);
@@ -8734,7 +10095,7 @@ void clif_equiptickack(struct map_session_data* sd, int flag)
WFIFOHEAD(fd, packet_len(0x2d9));
WFIFOW(fd, 0) = 0x2d9;
- WFIFOL(fd, 2) = 0;
+ WFIFOL(fd, 2) = type;
WFIFOL(fd, 6) = flag;
WFIFOSET(fd, packet_len(0x2d9));
}
@@ -8744,7 +10105,7 @@ void clif_equiptickack(struct map_session_data* sd, int flag)
/// open equip window:
/// 0 = disabled
/// 1 = enabled
-void clif_equpcheckbox(struct map_session_data* sd)
+static void clif_equpcheckbox(struct map_session_data *sd)
{
int fd;
nullpo_retv(sd);
@@ -8761,7 +10122,8 @@ void clif_equpcheckbox(struct map_session_data* sd)
/// 02d7 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE, PACKETVER >= 20100629)
/// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20101124)
/// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <robe>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20110111)
-void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd) {
+static void clif_viewequip_ack(struct map_session_data *sd, struct map_session_data *tsd)
+{
int i, equip = 0;
nullpo_retv(sd);
@@ -8782,7 +10144,7 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
safestrncpy(viewequip_list.characterName, tsd->status.name, NAME_LENGTH);
- viewequip_list.job = tsd->status.class_;
+ viewequip_list.job = tsd->status.class;
viewequip_list.head = tsd->vd.hair_style;
viewequip_list.accessory = tsd->vd.head_bottom;
viewequip_list.accessory2 = tsd->vd.head_mid;
@@ -8792,6 +10154,9 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
#endif
viewequip_list.headpalette = tsd->vd.hair_color;
viewequip_list.bodypalette = tsd->vd.cloth_color;
+#if PACKETVER_MAIN_NUM >= 20180801 || PACKETVER_RE_NUM >= 20180801 || PACKETVER_ZERO_NUM >= 20180808
+ viewequip_list.body2 = tsd->vd.body_style;
+#endif
viewequip_list.sex = tsd->vd.sex;
clif->send(&viewequip_list, viewequip_list.PacketLength, &sd->bl, SELF);
@@ -8805,7 +10170,7 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
* @param sd The target character.
* @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
*/
-void clif_msgtable(struct map_session_data* sd, unsigned short msg_id)
+static void clif_msgtable(struct map_session_data *sd, enum clif_messages msg_id)
{
int fd;
nullpo_retv(sd);
@@ -8826,7 +10191,7 @@ void clif_msgtable(struct map_session_data* sd, unsigned short msg_id)
* @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
* @param value The value to fill %d.
*/
-void clif_msgtable_num(struct map_session_data *sd, unsigned short msg_id, int value)
+static void clif_msgtable_num(struct map_session_data *sd, enum clif_messages msg_id, int value)
{
#if PACKETVER >= 20090805
int fd;
@@ -8853,7 +10218,7 @@ void clif_msgtable_num(struct map_session_data *sd, unsigned short msg_id, int v
* @param skill_id ID of the skill to display.
* @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
*/
-void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_id)
+static void clif_msgtable_skill(struct map_session_data *sd, uint16 skill_id, enum clif_messages msg_id)
{
int fd;
@@ -8867,120 +10232,235 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i
WFIFOSET(fd, packet_len(0x7e6));
}
-/// Validates one global/guild/party/whisper message packet and tries to recognize its components.
-/// Returns true if the packet was parsed successfully.
-/// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00
-/// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00
-bool clif_process_message(struct map_session_data *sd, int format, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_)
+/**
+ * Displays a format string from msgstringtable.txt with a %s value (ZC_FORMATSTRING_MSG).
+ *
+ * @param sd The target character.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ * @param value The value to fill %s.
+ */
+static void clif_msgtable_str(struct map_session_data *sd, enum clif_messages msg_id, const char *value)
{
- const char *text, *name, *message;
- unsigned int packetlen, textlen;
- size_t namelen, messagelen;
- int fd = sd->fd;
+ int message_len;
+ int len;
+ struct PACKET_ZC_FORMATSTRING_MSG *p;
- nullpo_retr(false, sd);
- nullpo_retr(false, name_);
- nullpo_retr(false, namelen_);
- nullpo_retr(false, message_);
- nullpo_retr(false, messagelen_);
-
- *name_ = NULL;
- *namelen_ = 0;
- *message_ = NULL;
- *messagelen_ = 0;
-
- packetlen = RFIFOW(fd,2);
- // basic structure checks
- if (packetlen < 4 + 1) {
+ nullpo_retv(sd);
+ nullpo_retv(value);
+
+ message_len = (int)strlen(value) + 1;
+ len = sizeof(*p) + message_len + 1;
+
+ p = (struct PACKET_ZC_FORMATSTRING_MSG *)aMalloc(len);
+ p->PacketType = 0x2c2;
+ p->PacketLength = len;
+ p->MessageId = msg_id;
+ safestrncpy(p->MessageString, value, message_len);
+ p->MessageString[message_len] = 0;
+
+ clif->send(p, p->PacketLength, &sd->bl, SELF);
+ aFree(p);
+}
+
+/**
+ * Displays a format string from msgstringtable.txt with a %s value and color (ZC_FORMATSTRING_MSG).
+ *
+ * @param sd The target character.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ * @param value The value to fill %s.
+ * @param color The color to use
+ */
+static void clif_msgtable_str_color(struct map_session_data *sd, enum clif_messages msg_id, const char *value, uint32 color)
+{
+#if PACKETVER >= 20160330
+ nullpo_retv(sd);
+ nullpo_retv(value);
+
+ int message_len = (int)strlen(value) + 1;
+ const int len = sizeof(struct PACKET_ZC_FORMATSTRING_MSG_COLOR) + message_len + 1;
+ struct PACKET_ZC_FORMATSTRING_MSG_COLOR *p = (struct PACKET_ZC_FORMATSTRING_MSG_COLOR *)aMalloc(len);
+
+ p->PacketType = 0xa6f;
+ p->PacketLength = len;
+ p->messageId = msg_id;
+#if PACKETVER >= 20160406
+ p->color = color;
+#endif
+ safestrncpy(p->messageString, value, message_len);
+ p->messageString[message_len] = 0;
+
+ clif->send(p, p->PacketLength, &sd->bl, SELF);
+ aFree(p);
+#endif
+}
+
+/**
+ * Displays a format string from msgstringtable.txt with a color (ZC_MSG_COLOR).
+ *
+ * @param sd The target character.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ * @param color The color to use
+ */
+static void clif_msgtable_color(struct map_session_data *sd, enum clif_messages msg_id, uint32 color)
+{
+ struct PACKET_ZC_MSG_COLOR p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0x9cd;
+ p.MessageId = msg_id;
+ p.MessageColor = RGB2BGR(color);
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+}
+
+/**
+ * Validates and processes a global/guild/party message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_buf The output buffer (must be a valid buffer), that will
+ * be filled with "Name : Message".
+ * @param[in] out_buflen The size of out_buf (including the NUL terminator).
+ * @return a pointer to the "Message" part of out_buf.
+ * @retval NULL if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_buf shan't be used.
+ */
+static const char *clif_process_chat_message(struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen)
+{
+ const char *srcname = NULL, *srcmessage = NULL, *message = NULL;
+ int textlen = 0, namelen = 0, messagelen = 0;
+
+ nullpo_ret(sd);
+ nullpo_ret(packet);
+ nullpo_ret(out_buf);
+
+ if (packet->packet_len < 4 + 1) {
// 4-byte header and at least an empty string is expected
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
- return false;
+ ShowWarning("clif_process_chat_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
+ return NULL;
}
- text = RFIFOP(fd,4);
- textlen = packetlen - 4;
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ textlen = packet->packet_len - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ textlen = packet->packet_len - 4 - 1;
+#endif // PACKETVER > 20151001
- // process <name> part of the packet
- if( format == 0 )
- {// name and message are separated by ' : '
- // validate name
- name = text;
- namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
+ // name and message are separated by ' : '
+ srcname = packet->message;
+ namelen = (int)strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
- if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name
- name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : '
- {
- //Hacked message, or infamous "client 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);
- sockt->eof(fd); // Just kick them out to correct it.
- return false;
- }
+ if (strncmp(srcname, sd->status.name, namelen) != 0 // the text must start with the speaker's name
+ || srcname[namelen] != ' ' || srcname[namelen+1] != ':' || srcname[namelen+2] != ' ' // followed by ' : '
+ ) {
+ //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
+ sockt->eof(sd->fd); // Just kick them out to correct it.
+ return NULL;
+ }
+
+ srcmessage = packet->message + namelen + 3; // <name> " : " <message>
+ messagelen = textlen - namelen - 3;
- message = name + namelen + 3;
- messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included)
+ if (messagelen >= CHAT_SIZE_MAX || textlen >= out_buflen) {
+ // messages mustn't be too long
+ // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
+ // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
+ // Neither the official client nor server place any restriction on the length of the data in the packet,
+ // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHATBOX_SIZE-1, srcmessage);
+ return NULL;
}
- else
- {// name has fixed width
- if( textlen < NAME_LENGTH + 1 )
- {
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
- return false;
- }
- // validate name
- name = text;
- namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte)
+ safestrncpy(out_buf, packet->message, textlen+1); // [!] packet->message is not necessarily NUL terminated
+ message = out_buf + namelen + 3;
- if (name[namelen] != '\0') {
- // only restriction is that the name must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name);
- return false;
- }
+ if (!pc->process_chat_message(sd, message))
+ return NULL;
+ return message;
+}
- message = name + NAME_LENGTH;
- messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included)
- }
+/**
+ * Validates and processes a whisper message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_name The parsed target name buffer (must be a valid
+ * buffer of size NAME_LENGTH).
+ * @param[out] out_message The output message buffer (must be a valid buffer).
+ * @param[in] out_messagelen The size of out_message.
+ * @retval true if the validation succeeded and the message is a chat message.
+ * @retval false if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_name and out_message
+ * shan't be used.
+ */
+static bool clif_process_whisper_message(struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen)
+{
+ int namelen = 0, messagelen = 0;
+
+ nullpo_retr(false, sd);
+ nullpo_retr(false, packet);
+ nullpo_retr(false, out_name);
+ nullpo_retr(false, out_message);
- if (messagelen != strnlen(message, messagelen)+1) {
- // the declared length must match real length
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name);
+ if (packet->packet_len < NAME_LENGTH + 4 + 1) {
+ // 4-byte header and at least an empty string is expected
+ ShowWarning("clif_process_whisper_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
return false;
}
- // verify <message> part of the packet
- if (message[messagelen-1] != '\0') {
- // message must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name);
+
+ // validate name
+ namelen = (int)strnlen(packet->name, NAME_LENGTH-1); // name length (w/o zero byte)
+
+ if (packet->name[namelen] != '\0') {
+ // only restriction is that the name must be zero-terminated
+ ShowWarning("clif_process_whisper_message: Player '%s' sent an unterminated name!\n", sd->status.name);
return false;
}
- if (messagelen > CHAT_SIZE_MAX-1) {
+
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4 - 1;
+#endif // PACKETVER > 20151001
+
+ if (messagelen >= CHAT_SIZE_MAX || messagelen >= out_messagelen) {
// messages mustn't be too long
// Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
// Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
// Neither the official client nor server place any restriction on the length of the data in the packet,
// but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
- ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message);
+ ShowWarning("clif_process_whisper_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, packet->message);
return false;
}
- *name_ = name;
- *namelen_ = namelen;
- *message_ = message;
- *messagelen_ = messagelen;
+ safestrncpy(out_name, packet->name, namelen+1); // [!] packet->name is not NUL terminated
+ safestrncpy(out_message, packet->message, messagelen+1); // [!] packet->message is not necessarily NUL terminated
+
+ if (!pc->process_chat_message(sd, out_message))
+ return false;
+
return true;
}
-void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg)
+static void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg)
{
struct DBIterator *iter;
struct map_session_data *user;
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(sd);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WFIFOHEAD(sd->fd,msg_len + 12);
@@ -9003,18 +10483,19 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch
dbi_destroy(iter);
}
-void clif_channel_msg2(struct channel_data *chan, char *msg)
+static void clif_channel_msg2(struct channel_data *chan, char *msg)
{
struct DBIterator *iter;
struct map_session_data *user;
unsigned char buf[210];
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WBUFW(buf,0) = 0x2C1;
@@ -9032,6 +10513,22 @@ void clif_channel_msg2(struct channel_data *chan, char *msg)
dbi_destroy(iter);
}
+// TODO: [4144] same packet with login server. need somehow use one function for both servers
+// 3 - Rejected by server
+static void clif_auth_error(int fd, int errorCode)
+{
+ struct packet_ZC_REFUSE_LOGIN p;
+ const int len = sizeof(p);
+
+ p.PacketType = authError;
+ p.error_code = errorCode;
+ p.block_date[0] = '\0';
+
+ WFIFOHEAD(fd, len);
+ memcpy(WFIFOP(fd, 0), &p, len);
+ WFIFOSET(fd, len);
+}
+
// ------------
// clif_parse_*
// ------------
@@ -9041,7 +10538,8 @@ void clif_channel_msg2(struct channel_data *chan, char *msg)
/// 0072 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER)
/// 0436 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
+static void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
+{
struct block_list* bl;
struct auth_node* node;
int cmd, account_id, char_id, login_id1, sex;
@@ -9070,10 +10568,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
bl = map->id2bl(account_id);
if(bl && bl->type != BL_PC) {
ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_id);
- WFIFOHEAD(fd,packet_len(0x6a));
- WFIFOW(fd,0) = 0x6a;
- WFIFOB(fd,2) = 3; // Rejected by server
- WFIFOSET(fd,packet_len(0x6a));
+ clif->auth_error(fd, 3); // Rejected by server
sockt->eof(fd);
return;
@@ -9112,370 +10607,461 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
chrif->authreq(sd,false);
}
-void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
-/// 007d
-void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) {
- bool first_time = false;
-
- if(sd->bl.prev != NULL)
+/**
+ * Notification from the client, that it has finished map loading and is about to display player's character. (CZ_NOTIFY_ACTORINIT)
+ *
+ * @code
+ * 007d
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ *
+ **/
+static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd)
+{
+ if (sd->bl.prev != NULL)
return;
- if (!sd->state.active) { //Character loading is not complete yet!
- //Let pc->reg_received reinvoke this when ready.
+ if (sd->state.active == 0) { // Character loading is not complete yet! Let pc->reg_received reinvoke this when ready.
sd->state.connect_new = 0;
return;
}
- if (sd->state.rewarp) { //Rewarp player.
+ if (sd->state.rewarp != 0) { // Rewarp character.
sd->state.rewarp = 0;
clif->changemap(sd, sd->bl.m, sd->bl.x, sd->bl.y);
return;
}
sd->state.warping = 0;
- sd->state.dialog = 0;/* reset when warping, client dialog will go missing */
+ sd->state.dialog = 0; // Reset when warping. Client dialog will go missing.
- // look
+ // Character looks.
#if PACKETVER < 4
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ clif->changelook(&sd->bl, LOOK_WEAPON, sd->status.look.weapon);
+ clif->changelook(&sd->bl, LOOK_SHIELD, sd->status.look.shield);
#else
- clif->changelook(&sd->bl,LOOK_WEAPON,0);
+ clif->changelook(&sd->bl, LOOK_WEAPON, 0);
#endif
- if(sd->vd.cloth_color)
- clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
- if (sd->vd.body_style)
- clif->refreshlook(&sd->bl,sd->bl.id,LOOK_BODY2,sd->vd.body_style,SELF);
- // item
- clif->inventorylist(sd); // inventory list first, otherwise deleted items in pc->checkitem show up as 'unknown item'
- pc->checkitem(sd);
+ if (sd->vd.cloth_color != 0)
+ clif->refreshlook(&sd->bl, sd->bl.id, LOOK_CLOTHES_COLOR, sd->vd.cloth_color, SELF);
- // cart
- if(pc_iscarton(sd)) {
- clif->cartlist(sd);
- clif->updatestatus(sd,SP_CARTINFO);
+ if (sd->vd.body_style != 0)
+ clif->refreshlook(&sd->bl, sd->bl.id, LOOK_BODY2, sd->vd.body_style, SELF);
+
+ /**
+ * Send character inventory to the client.
+ * Call this before pc->checkitem() so that the client isn't called to delete a non-existent items.
+ *
+ **/
+ clif->inventoryList(sd);
+
+ // Send the cart inventory, counts & weight to the client.
+ if (pc_iscarton(sd)) {
+ clif->cartList(sd);
+ clif->updatestatus(sd, SP_CARTINFO);
}
- // weight
- clif->updatestatus(sd,SP_WEIGHT);
- clif->updatestatus(sd,SP_MAXWEIGHT);
+ /**
+ * In official servers, an item's unequip script is executed when entering a zone where the item is restricted,
+ * even if the item won't be unequipped.
+ *
+ **/
+ if (map->list[sd->bl.m].zone != NULL && map->list[sd->bl.m].zone->disabled_items_count != 0) {
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
+ int handled_equip = 0x00000000;
+
+ for (int i = 0; i < EQI_MAX; i++) {
+ if (sd->equip_index[i] == INDEX_NOT_FOUND)
+ continue;
+
+ int inv_idx = sd->equip_index[i];
+ struct item_data *equip_data = sd->inventory_data[inv_idx];
+
+ if (equip_data == NULL)
+ continue;
+
+ if ((handled_equip & equip_data->equip) != 0)
+ continue; // Equipment takes multiple slots and was already handled.
+
+ handled_equip |= equip_data->equip;
- // guild
- // (needs to go before clif_spawn() to show guild emblems correctly)
- if(sd->status.guild_id)
- guild->send_memberinfoshort(sd,1);
+ if (equip_data->unequip_script != NULL) {
+ int idx;
- if(battle_config.pc_invincible_time > 0) {
- pc->setinvincibletimer(sd,battle_config.pc_invincible_time);
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx < dis_items_cnt)
+ script->run_item_unequip_script(sd, equip_data, npc->fake_nd->bl.id);
+ }
+
+ if (inv_idx != sd->equip_index[i])
+ continue; // Unequip script execution corrupted the inventory index.
+
+ struct item *equip = &sd->status.inventory[inv_idx];
+
+ if (equip != NULL && !itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
+ continue;
+
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->unequip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx < dis_items_cnt)
+ script->run_item_unequip_script(sd, card_data, npc->fake_nd->bl.id);
+ }
+ }
+ }
+ }
}
- if( map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs )
+ // Check for and delete unavailable/disabled items.
+ pc->checkitem(sd);
+
+ // Send the character's weight to the client.
+ clif->updatestatus(sd, SP_WEIGHT);
+ clif->updatestatus(sd, SP_MAXWEIGHT);
+
+ // Send character's guild info to the client. Call this before clif->spawn() to show guild emblems correctly.
+ if (sd->status.guild_id != 0)
+ guild->send_memberinfoshort(sd, 1);
+
+ if (battle_config.pc_invincible_time > 0)
+ pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
+
+ if (map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs != 0)
map->spawnmobs(sd->bl.m);
- if( map->list[sd->bl.m].instance_id >= 0 ) {
+ if (map->list[sd->bl.m].instance_id >= 0) {
instance->list[map->list[sd->bl.m].instance_id].users++;
instance->check_idle(map->list[sd->bl.m].instance_id);
}
- if( pc_has_permission(sd,PC_PERM_VIEW_HPMETER) ) {
+ if (pc_has_permission(sd, PC_PERM_VIEW_HPMETER)) {
map->list[sd->bl.m].hpmeter_visible++;
sd->state.hpmeter_visible = 1;
}
- if (!pc_isinvisible(sd)) { // increment the number of pvp players on the map
+ if (!pc_isinvisible(sd)) // Increment the number of pvp players on the map.
map->list[sd->bl.m].users_pvp++;
- }
-
- sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS]
- // reset the callshop flag if the player changes map
- sd->state.callshop = 0;
+ sd->state.debug_remove_map = 0; // Temporary state to track double calls of unit->remove_map(). [FlavioJS]
+ sd->state.callshop = 0; // Reset the callshop flag if the character changes map.
+ map->addblock(&sd->bl); // Add the character to the map.
+ clif->spawn(&sd->bl); // Spawn character client side.
- map->addblock(&sd->bl);
- clif->spawn(&sd->bl);
-
- // Party
- // (needs to go after clif_spawn() to show hp bars correctly)
- if(sd->status.party_id) {
+ // Send character's party info to the client. Call this after clif->spawn() to show HP bars correctly.
+ if (sd->status.party_id != 0) {
party->send_movemap(sd);
- clif->party_hp(sd); // Show hp after displacement [LuzZza]
+ clif->party_hp(sd); // Show HP after displacement. [LuzZza]
}
- if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System
+ if (sd->bg_id != 0)
+ clif->bg_hp(sd); // BattleGround system.
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && !pc_isinvisible(sd)) {
+ if (battle_config.pk_mode == 0) { // Remove PVP stuff for pk_mode. [Valaris]
+ if (map->list[sd->bl.m].flag.pvp_nocalcrank == 0)
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
- if (map->list[sd->bl.m].flag.pvp && !pc_isinvisible(sd)) {
- if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
- if (!map->list[sd->bl.m].flag.pvp_nocalcrank)
- sd->pvp_timer = timer->add(timer->gettick()+200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
sd->pvp_won = 0;
sd->pvp_lost = 0;
}
+
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
- } else
- // set flag, if it's a duel [LuzZza]
- if(sd->duel_group)
+ } else if(sd->duel_group != 0) { // Set flag, if it's a duel. [LuzZza]
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
+ }
- if (map->list[sd->bl.m].flag.gvg_dungeon)
+ if (map->list[sd->bl.m].flag.gvg_dungeon != 0)
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here.
- if( map_flag_gvg2(sd->bl.m) )
+ if (map_flag_gvg2(sd->bl.m))
clif->map_property(sd, MAPPROPERTY_AGITZONE);
- // info about nearby objects
- // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange)
- map->foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd);
+ // Info about nearby objects. Must use map->foreachinarea(). (CIRCULAR_AREA interferes with map->foreachinrange().)
+ map->foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
+ sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE, BL_ALL, sd);
- // pet
- if( sd->pd ) {
- if( battle_config.pet_no_gvg && map_flag_gvg2(sd->bl.m) ) { //Return the pet to egg. [Skotlex]
- clif->message(sd->fd, msg_sd(sd,866)); // "Pets are not allowed in Guild Wars."
- pet->menu(sd, 3); //Option 3 is return to egg.
+ // Spawn pet.
+ if (sd->pd != NULL) {
+ if (battle_config.pet_no_gvg != 0 && map_flag_gvg2(sd->bl.m)) { // Return the pet to egg. [Skotlex]
+ clif->message(sd->fd, msg_sd(sd, 866)); // "Pets are not allowed in Guild Wars."
+ pet->menu(sd, 3); // Option 3 is return to egg.
} else {
map->addblock(&sd->pd->bl);
clif->spawn(&sd->pd->bl);
- clif->send_petdata(sd,sd->pd,0,0);
+ clif->send_petdata(sd,sd->pd, 0, 0);
clif->send_petstatus(sd);
- //skill->unit_move(&sd->pd->bl,timer->gettick(),1);
}
}
- //homunculus [blackhole89]
- if( homun_alive(sd->hd) ) {
+ // Spawn homunculus. [blackhole89]
+ if (homun_alive(sd->hd)) {
map->addblock(&sd->hd->bl);
clif->spawn(&sd->hd->bl);
- clif->send_homdata(sd,SP_ACK,0);
- clif->hominfo(sd,sd->hd,1);
- clif->hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice
+ clif->send_homdata(sd, SP_ACK, 0);
+ clif->hominfo(sd,sd->hd, 1);
+ clif->hominfo(sd,sd->hd, 0); // For some reason, at least older clients want this sent twice.
clif->homskillinfoblock(sd);
- if( battle_config.hom_setting&0x8 )
- status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change
- if( !(battle_config.hom_setting&0x2) )
- skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
+
+ if ((battle_config.hom_setting & 0x8) != 0)
+ status_calc_bl(&sd->hd->bl, SCB_SPEED); // Homunculi mimic their master's speed on each map change.
+
+ if ((battle_config.hom_setting & 0x2) == 0)
+ skill->unit_move(&sd->hd->bl, timer->gettick(), 1); // Apply land skills immediately.
}
- if( sd->md ) {
+ // Spawn mercenary.
+ if (sd->md != NULL) {
map->addblock(&sd->md->bl);
clif->spawn(&sd->md->bl);
clif->mercenary_info(sd);
clif->mercenary_skillblock(sd);
- status_calc_bl(&sd->md->bl, SCB_SPEED); // Mercenary mimic their master's speed on each map change
+ status_calc_bl(&sd->md->bl, SCB_SPEED); // Mercenaries mimic their master's speed on each map change.
}
- if( sd->ed ) {
+ // Spawn elemental.
+ if (sd->ed != NULL) {
map->addblock(&sd->ed->bl);
clif->spawn(&sd->ed->bl);
clif->elemental_info(sd);
- clif->elemental_updatestatus(sd,SP_HP);
- clif->hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.max_hp);
- clif->elemental_updatestatus(sd,SP_SP);
- status_calc_bl(&sd->ed->bl, SCB_SPEED); //Elemental mimic their master's speed on each map change
+ clif->elemental_updatestatus(sd, SP_HP);
+ clif->hpmeter_single(sd->fd, sd->ed->bl.id, sd->ed->battle_status.hp, sd->ed->battle_status.max_hp);
+ clif->elemental_updatestatus(sd, SP_SP);
+ status_calc_bl(&sd->ed->bl, SCB_SPEED); // Elementals mimic their master's speed on each map change.
}
- if(sd->state.connect_new) {
- int lv;
+ bool first_time = false;
+
+ if (sd->state.connect_new != 0) {
first_time = true;
sd->state.connect_new = 0;
clif->skillinfoblock(sd);
- clif->hotkeys(sd);
- clif->updatestatus(sd,SP_BASEEXP);
- clif->updatestatus(sd,SP_NEXTBASEEXP);
- clif->updatestatus(sd,SP_JOBEXP);
- clif->updatestatus(sd,SP_NEXTJOBEXP);
- clif->updatestatus(sd,SP_SKILLPOINT);
+ clif->hotkeysAll(sd);
+ clif->updatestatus(sd, SP_BASEEXP);
+ clif->updatestatus(sd, SP_NEXTBASEEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
+ clif->updatestatus(sd, SP_NEXTJOBEXP);
+ clif->updatestatus(sd, SP_SKILLPOINT);
clif->initialstatus(sd);
- if (pc_isfalcon(sd))
- clif->status_change(&sd->bl, SI_FALCON, 1, 0, 0, 0, 0);
- if (pc_isridingpeco(sd) || pc_isridingdragon(sd))
- clif->status_change(&sd->bl, SI_RIDING, 1, 0, 0, 0, 0);
- else if (pc_isridingwug(sd))
- clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0);
+ if (pc_isfalcon(sd)) {
+ int sc_icn = status->get_sc_icon(SC_FALCON);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_FALCON);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
+ }
+
+ if (pc_isridingpeco(sd) || pc_isridingdragon(sd)) {
+ int sc_icn = status->get_sc_icon(SC_RIDING);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_RIDING);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
+ } else if (pc_isridingwug(sd)) {
+ int sc_icn = status->get_sc_icon(SC_WUGRIDER);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_WUGRIDER);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
+ }
- if(sd->status.manner < 0)
- sc_start(NULL,&sd->bl,SC_NOCHAT,100,0,0);
+ if (sd->status.manner < 0)
+ sc_start(NULL, &sd->bl, SC_NOCHAT, 100, 0, 0);
- //Auron reported that This skill only triggers when you logon on the map o.O [Skotlex]
- if ((lv = pc->checkskill(sd,SG_KNOWLEDGE)) > 0) {
- int i;
- for (i = 0; i < MAX_PC_FEELHATE; i++) {
+ int lv = pc->checkskill(sd,SG_KNOWLEDGE);
+
+ // Auron reported that this skill only triggers when you logon on the map. [Skotlex]
+ if (lv > 0) {
+ for (int i = 0; i < MAX_PC_FEELHATE; i++) {
if (sd->bl.m == sd->feel_map[i].m) {
- sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
+ sc_start(NULL, &sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
break;
}
}
}
- if(sd->pd && sd->pd->pet.intimate > 900)
- clif->pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet->hungry_val(sd->pd));
+ if (sd->pd != NULL && sd->pd->pet.intimate > PET_INTIMACY_LOYAL)
+ clif->pet_emotion(sd->pd, (sd->pd->pet.class_ - 100) * 100 + 50 + pet->hungry_val(sd->pd));
- if(homun_alive(sd->hd))
+ if (homun_alive(sd->hd))
homun->init_timers(sd->hd);
- if (map->night_flag && map->list[sd->bl.m].flag.nightenabled) {
+ if (map->night_flag != 0 && map->list[sd->bl.m].flag.nightenabled != 0) {
+ int sc_icn = status->get_sc_icon(SC_SKE);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_SKE);
+
sd->state.night = 1;
- clif->status_change(&sd->bl, SI_SKE, 1, 0, 0, 0, 0);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
}
- // Notify everyone that this char logged in [Skotlex].
+ // Notify everyone that this character logged in. [Skotlex]
map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
- //Login Event
+ // Run OnPCLoginEvent labels.
npc->script_event(sd, NPCE_LOGIN);
} else {
- //For some reason the client "loses" these on warp/map-change.
- clif->updatestatus(sd,SP_STR);
- clif->updatestatus(sd,SP_AGI);
- clif->updatestatus(sd,SP_VIT);
- clif->updatestatus(sd,SP_INT);
- clif->updatestatus(sd,SP_DEX);
- clif->updatestatus(sd,SP_LUK);
-
- if (sd->state.warp_clean) {
- // abort currently running script
+ // For some reason the client "loses" these on warp/map-change.
+ clif->updatestatus(sd, SP_STR);
+ clif->updatestatus(sd, SP_AGI);
+ clif->updatestatus(sd, SP_VIT);
+ clif->updatestatus(sd, SP_INT);
+ clif->updatestatus(sd, SP_DEX);
+ clif->updatestatus(sd, SP_LUK);
+
+ if (sd->state.warp_clean != 0) { // Abort currently running script.
sd->state.using_fake_npc = 0;
sd->state.menu_or_input = 0;
sd->npc_menu = 0;
- if(sd->npc_id)
+
+ if (sd->npc_id != 0)
npc->event_dequeue(sd);
} else {
sd->state.warp_clean = 1;
}
- if( sd->guild && ( battle_config.guild_notice_changemap == 2 || ( battle_config.guild_notice_changemap == 1 && sd->state.changemap ) ) )
- clif->guild_notice(sd,sd->guild);
+
+ if (sd->guild != NULL && ((battle_config.guild_notice_changemap == 1 && sd->state.changemap != 0)
+ || battle_config.guild_notice_changemap == 2)) {
+ clif->guild_notice(sd, sd->guild);
+ }
}
- if( sd->state.changemap ) {// restore information that gets lost on map-change
+ if (sd->state.changemap != 0) { // Restore information that gets lost on map-change.
#if PACKETVER >= 20070918
clif->partyinvitationstate(sd);
clif->equpcheckbox(sd);
#endif
- if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100)
- && (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m)
- || map->list[sd->state.pmap].flag.battleground || map->list[sd->bl.m].flag.battleground) )
- status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
- if( map->night_flag && map->list[sd->bl.m].flag.nightenabled ) {
- //Display night.
- if( !sd->state.night ) {
+#if PACKETVER_MAIN_NUM >= 20171025 || PACKETVER_RE_NUM >= 20170920
+ if (sd->hd != NULL)
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed);
+ else
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false);
+#endif
+
+ bool flee_penalty = (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100);
+ bool is_gvg = (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m));
+ bool is_bg = (map->list[sd->state.pmap].flag.battleground != 0 || map->list[sd->bl.m].flag.battleground != 0);
+
+ if (flee_penalty && (is_gvg || is_bg))
+ status_calc_bl(&sd->bl, SCB_FLEE); // Refresh flee penalty.
+
+ if (map->night_flag != 0 && map->list[sd->bl.m].flag.nightenabled != 0) {
+ if (sd->state.night == 0) { // Display night.
+ int sc_icn = status->get_sc_icon(SC_SKE);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_SKE);
+
sd->state.night = 1;
- clif->status_change(&sd->bl, SI_SKE, 1, 0, 0, 0, 0);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
}
- } else if( sd->state.night ) { //Clear night display.
+ } else if (sd->state.night != 0) { // Clear night display.
sd->state.night = 0;
- clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_SKE);
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SKE));
}
- if( map->list[sd->bl.m].flag.battleground ) {
- clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
- if( map->list[sd->bl.m].flag.battleground == 2 )
+ if (map->list[sd->bl.m].flag.battleground != 0) {
+ clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground mode.
+
+ if (map->list[sd->bl.m].flag.battleground == 2)
clif->bg_updatescore_single(sd);
}
- if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
+ if (map->list[sd->bl.m].flag.allowks != 0 && !map_flag_ks(sd->bl.m)) {
char output[128];
- sprintf(output, "[ Kill Steal Protection Disabled. KS is allowed in this map ]");
- clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF);
+
+ sprintf(output, "%s", msg_sd(sd, 893)); // [ Kill Steal Protection Disabled. KS is allowed in this map ]
+ clif->broadcast(&sd->bl, output, (int)strlen(output) + 1, BC_BLUE, SELF);
}
- map->iwall_get(sd); // Updates Walls Info on this Map to Client
- status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */
+ map->iwall_get(sd); // Updates walls info on this map to client.
+ status_calc_pc(sd, SCO_NONE); // Some conditions are map-dependent so we must recalculate.
sd->state.changemap = false;
- if (channel->config->local && channel->config->local_autojoin) {
+ if (channel->config->local && channel->config->local_autojoin)
channel->map_join(sd);
- }
- if (channel->config->irc && channel->config->irc_autojoin) {
+
+ if (channel->config->irc && channel->config->irc_autojoin)
channel->irc_join(sd);
- }
}
mail->clear(sd);
+ clif->maptypeproperty2(&sd->bl, SELF);
- clif->maptypeproperty2(&sd->bl,SELF);
-
- /* Guild Aura Init */
- if( sd->state.gmaster_flag ) {
- guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->guild,GD_LEADERSHIP));
- guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->guild,GD_GLORYWOUNDS));
- guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->guild,GD_SOULCOLD));
- guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->guild,GD_HAWKEYES));
+ // Init guild aura.
+ if (sd->state.gmaster_flag != 0) {
+ guild->aura_refresh(sd, GD_LEADERSHIP, guild->checkskill(sd->guild, GD_LEADERSHIP));
+ guild->aura_refresh(sd, GD_GLORYWOUNDS, guild->checkskill(sd->guild, GD_GLORYWOUNDS));
+ guild->aura_refresh(sd, GD_SOULCOLD, guild->checkskill(sd->guild, GD_SOULCOLD));
+ guild->aura_refresh(sd, GD_HAWKEYES, guild->checkskill(sd->guild, GD_HAWKEYES));
}
- if( sd->state.vending ) { /* show we have a vending */
- clif->openvending(sd,sd->bl.id,sd->vending);
- clif->showvendingboard(&sd->bl,sd->message,0);
+ if (sd->state.vending != 0) { // Character is vending.
+ clif->openvending(sd, sd->bl.id, sd->vending);
+ clif->showvendingboard(&sd->bl, sd->message, 0);
}
- if(map->list[sd->bl.m].flag.loadevent) // Lance
+ if (map->list[sd->bl.m].flag.loadevent != 0) // Run OnPCLoadMapEvent labels. [Lance]
npc->script_event(sd, NPCE_LOADMAP);
- if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd)) //blindness [Komurka]
- clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1);
+ if (pc->checkskill(sd, SG_DEVIL) > 0 && pc->nextjobexp(sd) == 0) // Blindness. [Komurka]
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_DEVIL1));
- if (sd->sc.opt2) //Client loses these on warp.
+ if (sd->sc.opt2 != 0) // Client loses these on warp.
clif->changeoption(&sd->bl);
- if( sd->sc.data[SC_MONSTER_TRANSFORM] && battle_config.mon_trans_disable_in_gvg && map_flag_gvg2(sd->bl.m) ){
+ if (sd->sc.data[SC_MONSTER_TRANSFORM] != NULL && battle_config.mon_trans_disable_in_gvg != 0
+ && map_flag_gvg2(sd->bl.m)) {
status_change_end(&sd->bl, SC_MONSTER_TRANSFORM, INVALID_TIMER);
- clif->message(sd->fd, msg_sd(sd,1488)); // Transforming into monster is not allowed in Guild Wars.
+ clif->message(sd->fd, msg_sd(sd, 1488)); // Transforming into monster is not allowed in Guild Wars.
}
clif->weather_check(sd);
- // This should be displayed last
- if( sd->guild && first_time )
+ // This should be displayed last.
+ if (sd->guild != NULL && first_time)
clif->guild_notice(sd, sd->guild);
- // For automatic triggering of NPCs after map loading (so you don't need to walk 1 step first)
- if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC))
- npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
+ // For automatic triggering of NPCs after map loading. (So you don't need to walk 1 step first.)
+ if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC) != 0)
+ npc->touch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y);
else
npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y);
- /* it broke at some point (e.g. during a crash), so we make it visibly dead again. */
- if( !sd->status.hp && !pc_isdead(sd) && status->isdead(&sd->bl) )
+ // It broke at some point (e.g. during a crash), so we make it visibly dead again.
+ if (sd->status.hp == 0 && !pc_isdead(sd) && status->isdead(&sd->bl) != 0)
pc_setdead(sd);
- // If player is dead, and is spawned (such as @refresh) send death packet. [Valaris]
- if(pc_isdead(sd))
+ // Send death packet, if character is dead and is spawned (such as @refresh). [Valaris]
+ if (pc_isdead(sd)) {
clif->clearunit_area(&sd->bl, CLR_DEAD);
- else {
+ } else {
skill->usave_trigger(sd);
- sd->ud.dir = 0;/* enforce north-facing (not visually, virtually) */
+
+ if (battle_config.player_warp_keep_direction == 1)
+ clif->changed_dir(&sd->bl, SELF); // Visually updates player facing direction
}
- // Trigger skill effects if you appear standing on them
- if(!battle_config.pc_invincible_time)
- skill->unit_move(&sd->bl,timer->gettick(),1);
+ // Trigger skill effects if you appear standing on them.
+ if (battle_config.pc_invincible_time == 0)
+ skill->unit_move(&sd->bl, timer->gettick(), 1);
- // NPC Quest / Event Icon Check [Kisuka]
#if PACKETVER >= 20090218
- {
- int i;
- for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
- struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
- if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started
- if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class.
- if( sd->class_ == qi->job )
- clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
- } else {
- clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
- }
- }
- }
- }
+ quest->questinfo_refresh(sd); // NPC quest/event icon check. [Kisuka]
#endif
}
/// Server's tick (ZC_NOTIFY_TIME).
/// 007f <time>.L
-void clif_notify_time(struct map_session_data* sd, int64 time) {
+static void clif_notify_time(struct map_session_data *sd, int64 time)
+{
int fd;
nullpo_retv(sd);
@@ -9487,70 +11073,123 @@ void clif_notify_time(struct map_session_data* sd, int64 time) {
WFIFOSET(fd,packet_len(0x7f));
}
-void clif_parse_TickSend(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TickSend(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request for server's tick.
/// 007e <client tick>.L (CZ_REQUEST_TIME)
/// 0360 <client tick>.L (CZ_REQUEST_TIME2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_TickSend(int fd, struct map_session_data *sd)
+static void clif_parse_TickSend(int fd, struct map_session_data *sd)
{
sd->client_tick = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
clif->notify_time(sd, timer->gettick());
}
+static void clif_hotkeysAll_send(struct map_session_data *sd)
+{
+#ifdef HOTKEY_SAVING
+ clif->hotkeys(sd, 0);
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+ // send second tab only if data exists
+ for (int i = MAX_HOTKEYS; i < MAX_HOTKEYS * 2; i++) {
+ if (sd->status.hotkeys[i].type != 0 || sd->status.hotkeys[i].id != 0 || sd->status.hotkeys[i].lv != 0) {
+ clif->hotkeys(sd, 1);
+ return;
+ }
+ }
+#endif
+#endif
+}
+
/// Sends hotkey bar.
/// 02b9 { <is skill>.B <id>.L <count>.W }*27 (ZC_SHORTCUT_KEY_LIST)
/// 07d9 { <is skill>.B <id>.L <count>.W }*36 (ZC_SHORTCUT_KEY_LIST_V2, PACKETVER >= 20090603)
/// 07d9 { <is skill>.B <id>.L <count>.W }*38 (ZC_SHORTCUT_KEY_LIST_V2, PACKETVER >= 20090617)
/// 0a00 <rotate>.B { <is skill>.B <id>.L <count>.W }*38 (ZC_SHORTCUT_KEY_LIST_V3, PACKETVER >= 20141022)
-void clif_hotkeys_send(struct map_session_data *sd) {
+static void clif_hotkeys_send(struct map_session_data *sd, int tab)
+{
#ifdef HOTKEY_SAVING
- struct packet_hotkey p;
- int i;
nullpo_retv(sd);
- p.PacketType = hotkeyType;
-#if PACKETVER >= 20141022
- p.Rotate = sd->status.hotkey_rowshift;
+ struct PACKET_ZC_SHORTCUT_KEY_LIST p;
+ p.packetType = HEADER_ZC_SHORTCUT_KEY_LIST;
+#if PACKETVER_MAIN_NUM >= 20141022 || PACKETVER_RE_NUM >= 20141015 || defined(PACKETVER_ZERO)
+ if (tab == 0)
+ p.rotate = sd->status.hotkey_rowshift;
+ else
+ p.rotate = sd->status.hotkey_rowshift2;
#endif
- for(i = 0; i < ARRAYLENGTH(p.hotkey); i++) {
- p.hotkey[i].isSkill = sd->status.hotkeys[i].type;
- p.hotkey[i].ID = sd->status.hotkeys[i].id;
- p.hotkey[i].count = sd->status.hotkeys[i].lv;
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+ p.tab = tab;
+#endif
+ const int offset = tab * MAX_HOTKEYS;
+ for (int i = 0; i < MAX_HOTKEYS_PACKET; i++) {
+ p.hotkey[i].isSkill = sd->status.hotkeys[i + offset].type;
+ p.hotkey[i].id = sd->status.hotkeys[i + offset].id;
+ p.hotkey[i].count = sd->status.hotkeys[i + offset].lv;
}
- clif->send(&p, sizeof(p), &sd->bl, SELF);
+ clif->send(&p, sizeof(struct PACKET_ZC_SHORTCUT_KEY_LIST), &sd->bl, SELF);
#endif
}
-void clif_parse_HotkeyRowShift(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_HotkeyRowShift(int fd, struct map_session_data *sd)
+static void clif_parse_HotkeyRowShift1(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HotkeyRowShift1(int fd, struct map_session_data *sd)
{
- int cmd = RFIFOW(fd, 0);
- sd->status.hotkey_rowshift = RFIFOB(fd, packet_db[cmd].pos[0]);
+#if PACKETVER_MAIN_NUM >= 20140129 || PACKETVER_RE_NUM >= 20140129 || defined(PACKETVER_ZERO)
+ const struct PACKET_CZ_SHORTCUTKEYBAR_ROTATE1 *p = RFIFOP(fd, 0);
+ sd->status.hotkey_rowshift = p->rowshift;
+#endif
+}
+
+static void clif_parse_HotkeyRowShift2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HotkeyRowShift2(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+ const struct PACKET_CZ_SHORTCUTKEYBAR_ROTATE2 *p = RFIFOP(fd, 0);
+ if (p->tab == 0)
+ sd->status.hotkey_rowshift = p->rowshift;
+ else
+ sd->status.hotkey_rowshift2 = p->rowshift;
+#endif
}
-void clif_parse_Hotkey(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-/// Request to update a position on the hotkey bar (CZ_SHORTCUT_KEY_CHANGE).
+static void clif_parse_Hotkey1(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/// Request to update a position on the hotkey bar (CZ_SHORTCUT_KEY_CHANGE1).
/// 02ba <index>.W <is skill>.B <id>.L <count>.W
-void clif_parse_Hotkey(int fd, struct map_session_data *sd) {
+static void clif_parse_Hotkey1(int fd, struct map_session_data *sd)
+{
#ifdef HOTKEY_SAVING
- unsigned short idx;
- int cmd;
-
- cmd = RFIFOW(fd, 0);
- idx = RFIFOW(fd, packet_db[cmd].pos[0]);
- if (idx >= MAX_HOTKEYS) return;
+#if PACKETVER_MAIN_NUM >= 20070618 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO) || PACKETVER_AD_NUM >= 20070618 || PACKETVER_SAK_NUM >= 20070618
+ const struct PACKET_CZ_SHORTCUT_KEY_CHANGE1 *p = RFIFOP(fd, 0);
+ const unsigned short idx = p->index;
+ Assert_retv(idx < MAX_HOTKEYS);
+
+ sd->status.hotkeys[idx].type = p->hotkey.isSkill;
+ sd->status.hotkeys[idx].id = p->hotkey.id;
+ sd->status.hotkeys[idx].lv = p->hotkey.count;
+#endif
+#endif
+}
- sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[cmd].pos[1]);
- sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[cmd].pos[2]);
- sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[cmd].pos[3]);
+static void clif_parse_Hotkey2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/// Request to update a position on the hotkey bar (CZ_SHORTCUT_KEY_CHANGE2).
+static void clif_parse_Hotkey2(int fd, struct map_session_data *sd)
+{
+#ifdef HOTKEY_SAVING
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+ const struct PACKET_CZ_SHORTCUT_KEY_CHANGE2 *p = RFIFOP(fd, 0);
+ const unsigned short idx = p->index + p->tab * MAX_HOTKEYS;
+ Assert_retv(idx < MAX_HOTKEYS_DB);
+
+ sd->status.hotkeys[idx].type = p->hotkey.isSkill;
+ sd->status.hotkeys[idx].id = p->hotkey.id;
+ sd->status.hotkeys[idx].lv = p->hotkey.count;
+#endif
#endif
}
/// Displays cast-like progress bar (ZC_PROGRESS).
/// 02f0 <color>.L <time>.L
-/* TODO ZC_PROGRESS_ACTOR <account_id>.L */
-void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned int second)
+static void clif_progressbar(struct map_session_data *sd, unsigned int color, unsigned int second)
{
int fd;
@@ -9566,7 +11205,7 @@ void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned
/// Removes an ongoing progress bar (ZC_PROGRESS_CANCEL).
/// 02f2
-void clif_progressbar_abort(struct map_session_data * sd)
+static void clif_progressbar_abort(struct map_session_data *sd)
{
int fd;
@@ -9578,26 +11217,54 @@ void clif_progressbar_abort(struct map_session_data * sd)
WFIFOSET(fd,packet_len(0x2f2));
}
-void clif_parse_progressbar(int fd, struct map_session_data * sd) __attribute__((nonnull (2)));
+/**
+ * Displays cast-like progress bar on a unit.
+ * 09d1 <id>.L <color>.L <time>.L
+ *
+ * @param bl Source block list.
+ * @param color Message color (RGB format: 0xRRGGBB).
+ * @param time Time in seconds.
+ */
+static void clif_progressbar_unit(struct block_list *bl, uint32 color, uint32 time)
+{
+#if PACKETVER >= 20130821
+ struct ZC_PROGRESS_ACTOR p;
+ nullpo_retv(bl);
+
+ p.PacketType = progressbarunit;
+ p.GID = bl->id;
+ p.color = color;
+ p.time = time;
+ clif->send(&p, sizeof(p), bl, AREA);
+#else
+ ShowWarning("clif_progressbar_unit: Using progressbar with units available for PACKETVER >= 20130821 only.");
+#endif
+}
+
+static void clif_parse_progressbar(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Notification from the client, that the progress bar has reached 100% (CZ_PROGRESS).
/// 02f1
-void clif_parse_progressbar(int fd, struct map_session_data * sd)
+static void clif_parse_progressbar(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int npc_id = sd->progressbar.npc_id;
+ Assert_retv(npc_id != 0);
- if( timer->gettick() < sd->progressbar.timeout && sd->st )
+ if (timer->gettick() < sd->progressbar.timeout && sd->st)
sd->st->state = END;
sd->progressbar.timeout = sd->state.workinprogress = sd->progressbar.npc_id = 0;
npc->scriptcont(sd, npc_id, false);
}
-void clif_parse_WalkToXY(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_WalkToXY(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to walk to a certain position on the current map.
/// 0085 <dest>.3B (CZ_REQUEST_MOVE)
/// 035f <dest>.3B (CZ_REQUEST_MOVE2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
+static void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
{
short x, y;
@@ -9610,7 +11277,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
; //You CAN walk on this OPT1 value.
/*else if( sd->progressbar.npc_id )
clif->progressbar_abort(sd);*/
- else if (pc_cant_act(sd))
+ else if (pc_cant_act(sd) || pc_isvending(sd))
return;
if(sd->sc.data[SC_RUN] || sd->sc.data[SC_WUGDASH])
@@ -9623,7 +11290,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
//Set last idle time... [Skotlex]
pc->update_idle_time(sd, BCIDLE_WALK);
- unit->walktoxy(&sd->bl, x, y, 4);
+ unit->walk_toxy(&sd->bl, x, y, 4);
}
/// Notification about the result of a disconnect request (ZC_ACK_REQ_DISCONNECT).
@@ -9632,7 +11299,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
/// 0 = disconnect (quit)
/// 1 = cannot disconnect (wait 10 seconds)
/// ? = ignored
-void clif_disconnect_ack(struct map_session_data* sd, short result)
+static void clif_disconnect_ack(struct map_session_data *sd, short result)
{
int fd;
@@ -9645,31 +11312,32 @@ void clif_disconnect_ack(struct map_session_data* sd, short result)
WFIFOSET(fd,packet_len(0x18b));
}
-void clif_parse_QuitGame(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_QuitGame(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to disconnect from server (CZ_REQ_DISCONNECT).
/// 018a <type>.W
/// type:
/// 0 = quit
-void clif_parse_QuitGame(int fd, struct map_session_data *sd)
+static void clif_parse_QuitGame(int fd, struct map_session_data *sd)
{
/* Rovert's prevent logout option fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
- (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
- {
- sockt->eof(fd);
-
+ if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && !sd->sc.data[SC_SUHIDE] &&
+ (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)) {
clif->disconnect_ack(sd, 0);
+ sockt->flush(fd);
+ if (battle_config.drop_connection_on_quit)
+ sockt->eof(fd);
} else {
clif->disconnect_ack(sd, 1);
}
}
-void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Requesting unit's name.
/// 0094 <id>.L (CZ_REQNAME)
/// 0368 <id>.L (CZ_REQNAME2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
+static void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd)
+{
int id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
struct block_list* bl;
//struct status_change *sc;
@@ -9687,176 +11355,144 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
// 'see people in GM hide' cheat detection
#if 0 /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) */
sc = status->get_sc(bl);
- if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) &&
+ if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl) &&
bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple
- pc_get_group_level(sd) < battle_config.hack_info_GM_level
+ !pc_has_permission(sd, PC_PERM_RECEIVE_HACK_INFO)
) {
char gm_msg[256];
sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id);
ShowWarning(gm_msg);
// information is sent to all online GMs
- intif->wis_message_to_gm(map->wisp_server_name, battle_config.hack_info_GM_level, gm_msg);
+ pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, gm_msg);
return;
}
#endif // 0
- clif->charnameack(fd, bl);
+ clif->blname_ack(fd, bl);
}
-int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) {
+static int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data * sd;
if( (sd = map->id2sd(id)) ) {
sd->fontcolor_tid = INVALID_TIMER;
- if( sd->fontcolor && sd->disguise == sd->status.class_ )
+ if (sd->fontcolor && sd->disguise == sd->status.class)
pc->disguise(sd,-1);
}
return 0;
}
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes global messages
-/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
-/// There are various variants of this packet.
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processed global messages.
+ *
+ * There are various variants of this packet.
+ *
+ * @code
+ * 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+static void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GlobalMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- size_t textlen = RFIFOW(fd,2) - 4;
-
- const char *name = NULL, *message = NULL;
- char *fakename = NULL;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = NULL;
+ char full_message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
+ const char *message = NULL;
+ bool is_fakename = false;
+ int outlen = 0;
- bool is_fake;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ packet = RP2PTR(fd);
+ message = clif->process_chat_message(sd, packet, full_message, sizeof full_message);
+ if (message == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ pc->check_supernovice_call(sd, message);
- if( !pc->can_talk(sd) )
+ if (sd->gcbind != NULL) {
+ channel->send(sd->gcbind, sd, message);
return;
-
- if( battle_config.min_chat_delay ) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) {
- unsigned int next = pc->nextbaseexp(sd);
- if( next == 0 ) next = pc->thisbaseexp(sd);
- if( next ) { // 0%, 10%, 20%, ...
- int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
- if( (battle_config.snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
- switch (sd->state.snovice_call_flag) {
- case 0:
- if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?"
- sd->state.snovice_call_flag = 1;
- break;
- case 1: {
- char buf[256];
- snprintf(buf, 256, msg_txt(1480), sd->status.name);
- if( strstr(message, buf) ) // "I am %s Super Novice~"
- sd->state.snovice_call_flag = 2;
- }
- break;
- case 2:
- if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T"
- sd->state.snovice_call_flag = 3;
- break;
- case 3:
- sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
- clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
- sd->state.snovice_call_flag = 0;
- break;
- }
- }
- }
+ if (sd->fakename[0] != '\0') {
+ is_fakename = true;
+ outlen = (int)strlen(sd->fakename) + (int)strlen(message) + 3 + 1;
+ } else {
+ outlen = (int)strlen(full_message) + 1;
}
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->gcbind ) {
- channel->send(sd->gcbind,sd,message);
- return;
- } else if ( sd->fontcolor && !sd->chatID ) {
- char mout[200];
- unsigned char mylen = 1;
+ if (sd->fontcolor != 0 && sd->chat_id == 0) {
uint32 color = 0;
- if( sd->disguise == -1 ) {
+ if (sd->disguise == -1) {
sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
- pc->disguise(sd,sd->status.class_);
- if( pc_isdead(sd) )
+ pc->disguise(sd,sd->status.class);
+ if (pc_isdead(sd))
clif->clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
- if( unit->is_walking(&sd->bl) )
+ if (unit->is_walking(&sd->bl))
clif->move(&sd->ud);
- } else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) {
+ } else if (sd->disguise == sd->status.class && sd->fontcolor_tid != INVALID_TIMER) {
const struct TimerData *td;
- if( (td = timer->get(sd->fontcolor_tid)) ) {
+ if ((td = timer->get(sd->fontcolor_tid)) != NULL)
timer->settick(sd->fontcolor_tid, td->tick+5000);
- }
}
- mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
-
- color = channel->config->colors[sd->fontcolor - 1];
- WFIFOHEAD(fd,mylen + 12);
+ int fontColor = sd->fontcolor - 1;
+ if (fontColor < 0 || fontColor >= channel->config->colors_count)
+ fontColor = 0;
+ color = channel->config->colors[fontColor];
+ WFIFOHEAD(fd, outlen + 12);
WFIFOW(fd,0) = 0x2C1;
- WFIFOW(fd,2) = mylen + 12;
+ WFIFOW(fd,2) = outlen + 12;
WFIFOL(fd,4) = sd->bl.id;
WFIFOL(fd,8) = RGB2BGR(color);
- safestrncpy(WFIFOP(fd,12), mout, mylen);
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 12), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 12), full_message, outlen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
- WFIFOSET(fd, mylen + 12);
+ WFIFOSET(fd, outlen + 12);
return;
}
- /**
- * Fake Name Design by FatalEror (bug report #9)
- **/
- if( ( is_fake = ( sd->fakename[0] ) ) ) {
- fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3);
- strcpy(fakename, sd->fakename);
- strcat(fakename, " : ");
- strcat(fakename, message);
- textlen = strlen(fakename) + 1;
- }
- // send message to others (using the send buffer for temp. storage)
- WFIFOHEAD(fd, 8 + textlen);
- WFIFOW(fd,0) = 0x8d;
- WFIFOW(fd,2) = 8 + textlen;
- WFIFOL(fd,4) = sd->bl.id;
- safestrncpy(WFIFOP(fd,8), is_fake ? fakename : text, textlen);
- //FIXME: chat has range of 9 only
- clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC);
+ {
+ // send message to others
+ void *buf = aMalloc(8 + outlen);
+ WBUFW(buf, 0) = 0x8d;
+ WBUFW(buf, 2) = 8 + outlen;
+ WBUFL(buf, 4) = sd->bl.id;
+ if (is_fakename)
+ safesnprintf(WBUFP(buf, 8), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WBUFP(buf, 8), full_message, outlen);
+ //FIXME: chat has range of 9 only
+ clif->send(buf, WBUFW(buf, 2), &sd->bl, sd->chat_id != 0 ? CHAT_WOS : AREA_CHAT_WOC);
+ aFree(buf);
+ }
// send back message to the speaker
- if( is_fake ) {
- WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = textlen + 4;
- safestrncpy(WFIFOP(fd,4), fakename, textlen);
- aFree(fakename);
- } else {
- memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2));
- WFIFOW(fd,0) = 0x8e;
- }
+ WFIFOHEAD(fd, 4 + outlen);
+ WFIFOW(fd, 0) = 0x8e;
+ WFIFOW(fd, 2) = 4 + outlen;
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 4), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 4), full_message, outlen);
WFIFOSET(fd, WFIFOW(fd,2));
// Chat logging type 'O' / Global Chat
logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
// trigger listening npcs
- map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
+ map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, full_message, strlen(full_message), &sd->bl);
}
-void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /mm /mapmove (as @rura GM command) (CZ_MOVETO_MAP).
/// Request to warp to a map on given coordinates.
/// 0140 <map name>.16B <x>.W <y>.W
-void clif_parse_MapMove(int fd, struct map_session_data *sd)
+static void clif_parse_MapMove(int fd, struct map_session_data *sd)
{
char command[MAP_NAME_LENGTH_EXT+25];
char map_name[MAP_NAME_LENGTH_EXT];
@@ -9872,16 +11508,8 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd)
/// 0 = straight
/// 1 = turned CW
/// 2 = turned CCW
-/// dir:
-/// 0 = north
-/// 1 = northwest
-/// 2 = west
-/// 3 = southwest
-/// 4 = south
-/// 5 = southeast
-/// 6 = east
-/// 7 = northeast
-void clif_changed_dir(struct block_list *bl, enum send_target target)
+/// dir: @see enum unit_dir
+static void clif_changed_dir(struct block_list *bl, enum send_target target)
{
unsigned char buf[64];
@@ -9893,19 +11521,19 @@ void clif_changed_dir(struct block_list *bl, enum send_target target)
clif->send(buf, packet_len(0x9c), bl, target);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
WBUFW(buf,6) = 0;
clif->send(buf, packet_len(0x9c), bl, SELF);
}
}
-void clif_parse_ChangeDir(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ChangeDir(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change own body and head direction.
/// 009b <head dir>.W <dir>.B (CZ_CHANGE_DIRECTION)
/// 0361 <head dir>.W <dir>.B (CZ_CHANGE_DIRECTION2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_ChangeDir(int fd, struct map_session_data *sd)
+static void clif_parse_ChangeDir(int fd, struct map_session_data *sd)
{
unsigned char headdir, dir;
@@ -9916,24 +11544,24 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd)
clif->changed_dir(&sd->bl, AREA_WOS);
}
-void clif_parse_Emotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Emotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to show an emotion (CZ_REQ_EMOTION).
/// 00bf <type>.B
/// type:
/// @see enum emotion_type
-void clif_parse_Emotion(int fd, struct map_session_data *sd)
+static void clif_parse_Emotion(int fd, struct map_session_data *sd)
{
int emoticon = RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- if (battle_config.basic_skill_check == 0 || pc->checkskill(sd, NV_BASIC) >= 2) {
+ if (battle_config.basic_skill_check == 0 || pc->check_basicskill(sd, 2)) {
if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris]
- clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1);
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1, 0);
return;
}
// fix flood of emotion icon (ro-proxy): flood only the hacker player
if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second
sd->emotionlasttime = time(NULL);
- clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1);
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1, 0);
return;
}
sd->emotionlasttime = time(NULL);
@@ -9946,12 +11574,13 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd)
clif->emotion(&sd->bl, emoticon);
} else
- clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1);
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1, 0);
}
/// Amount of currently online players, reply to /w /who (ZC_USER_COUNT).
/// 00c2 <count>.L
-void clif_user_count(struct map_session_data* sd, int count) {
+static void clif_user_count(struct map_session_data *sd, int count)
+{
int fd;
nullpo_retv(sd);
@@ -9963,15 +11592,16 @@ void clif_user_count(struct map_session_data* sd, int count) {
WFIFOSET(fd,packet_len(0xc2));
}
-void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /w /who (CZ_REQ_USER_COUNT).
/// Request to display amount of currently connected players.
/// 00c1
-void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) {
+static void clif_parse_HowManyConnections(int fd, struct map_session_data *sd)
+{
clif->user_count(sd, map->getusers());
}
-void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, int64 tick)
+static void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, int64 tick)
{
nullpo_retv(sd);
if (pc_isdead(sd)) {
@@ -9985,7 +11615,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
sd->sc.data[SC_TRICKDEAD] ||
(sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
sd->sc.data[SC_BLADESTOP] ||
- sd->sc.data[SC_DEEP_SLEEP] )
+ sd->sc.data[SC_DEEP_SLEEP] ||
+ sd->sc.data[SC_SUHIDE] )
)
return;
@@ -10002,19 +11633,21 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
{
struct npc_data *nd = map->id2nd(target_id);
if (nd != NULL) {
- npc->click(sd, nd);
+ if (sd->block_action.npc == 0) { // *pcblock script command
+ npc->click(sd, nd);
+ }
return;
}
- if( pc_cant_act(sd) || pc_issit(sd) || sd->sc.option&OPTION_HIDE )
+ if (pc_cant_act(sd) || pc_issit(sd) || sd->sc.option&OPTION_HIDE || pc_isvending(sd))
return;
- if( sd->sc.option&OPTION_COSTUME )
+ if (sd->sc.option & OPTION_COSTUME)
return;
- if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) {
+ if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0 && (skill->get_inf2(sd->ud.skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0) {
if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
- clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0);
+ clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
}
@@ -10025,8 +11658,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
}
break;
case 0x02: // sitdown
- if (battle_config.basic_skill_check && pc->checkskill(sd, NV_BASIC) < 3) {
- clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2);
+ if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 3)) {
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2, 0);
break;
}
@@ -10039,6 +11672,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
}
+ if (sd->block_action.sitstand) // *pcblock script command
+ break;
+
if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ))
break;
@@ -10066,6 +11702,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
}
+ if (sd->block_action.sitstand) // *pcblock script command
+ break;
+
pc->update_idle_time(sd, BCIDLE_SIT);
pc->setstand(sd);
@@ -10075,7 +11714,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
}
}
-void clif_parse_ActionRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ActionRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request for an action.
/// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT)
/// 0437 <target id>.L <action>.B (CZ_REQUEST_ACT2)
@@ -10087,7 +11726,7 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) __attribute__
/// 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)
+static void clif_parse_ActionRequest(int fd, struct map_session_data *sd)
{
clif->pActionRequest_sub(sd,
RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[1]),
@@ -10096,13 +11735,14 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd)
);
}
-void clif_parse_Restart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Restart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Response to the death/system menu (CZ_RESTART).
/// 00b2 <type>.B
/// type:
/// 0 = restart (respawn)
/// 1 = char-select (disconnect)
-void clif_parse_Restart(int fd, struct map_session_data *sd) {
+static void clif_parse_Restart(int fd, struct map_session_data *sd)
+{
switch(RFIFOB(fd,2)) {
case 0x00:
pc->respawn(sd,CLR_OUTSIGHT);
@@ -10110,7 +11750,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
case 0x01:
/* Rovert's Prevent logout option - Fixed [Valaris] */
if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK]
- && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY]
+ && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && !sd->sc.data[SC_SUHIDE]
&& (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)
) {
//Send to char-server for character selection.
@@ -10122,37 +11762,28 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
}
}
-void clif_parse_WisMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes whispered messages (CZ_WHISPER).
-/// 0096 <packet len>.W <nick>.24B <message>.?B
-void clif_parse_WisMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes whispered messages (CZ_WHISPER).
+ *
+ * @code
+ * 0096 <packet len>.W <nick>.24B <message>.?B
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+static void clif_parse_WisMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_WisMessage(int fd, struct map_session_data *sd)
{
struct map_session_data* dstsd;
int i;
- const char *target, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) )
- return;
+ char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1];
+ const struct packet_whisper_message *packet = RP2PTR(fd);
- if ( atcommand->exec(fd, sd, message, true) )
+ if (!clif->process_whisper_message(sd, packet, target, message, sizeof message))
return;
- // Statuses that prevent the player from whispering
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
- return;
- }
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
// Chat logging type 'W' / Whisper
logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
@@ -10160,7 +11791,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
// Lordalfa - Paperboy - To whisper NPC commands //
//-------------------------------------------------------//
if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) {
- const char *str = target+4; //Skip the NPC: string part.
+ char *str = target + 4; // Skip the NPC: string part.
struct npc_data *nd;
if ((nd = npc->name2id(str))) {
char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX];
@@ -10189,8 +11820,8 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
script->set_var(sd,output,(char *) split_data[i]);
}
- sprintf(output, "%s::OnWhisperGlobal", nd->exname);
- npc->event(sd,output,0); // Calls the NPC label
+ safesnprintf(output, 255, "%s::OnWhisperGlobal", nd->exname);
+ npc->event(sd,output, 0); // Calls the NPC label
return;
}
@@ -10200,11 +11831,11 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if (chan) {
int k;
- ARR_FIND(0, sd->channel_count, k, sd->channels[k] == chan);
- if (k < sd->channel_count || channel->join(chan, sd, "", true) == HCS_STATUS_OK) {
+ ARR_FIND(0, VECTOR_LENGTH(sd->channels), k, VECTOR_INDEX(sd->channels, k) == chan);
+ if (k < VECTOR_LENGTH(sd->channels) || channel->join(chan, sd, "", true) == HCS_STATUS_OK) {
channel->send(chan,sd,message);
} else {
- clif->message(fd, msg_fd(fd,1402));
+ clif->message(fd, msg_fd(fd,1402)); //You're not in that channel, type '@join <#channel_name>'
}
return;
} else if (strcmpi(&chname[1], channel->config->ally_name) == 0) {
@@ -10214,15 +11845,11 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// searching destination character
- dstsd = map->nick2sd(target);
+ dstsd = map->nick2sd(target, false);
- if (dstsd == NULL || strcmp(dstsd->status.name, target) != 0) {
- // player is not on this map-server
- // At this point, don't send wisp/page if it's not exactly the same name, because (example)
- // if there are 'Test' player on an other map-server and 'test' player on this map-server,
- // and if we ask for 'Test', we must not contact 'test' player
- // so, we send information to inter-server, which is the only one which decide (and copy correct name).
- intif->wis_message(sd, target, message, messagelen);
+ if (dstsd == NULL) {
+ // Character not found (or found through partial match).
+ clif->wis_end(sd->fd, 1);
return;
}
@@ -10236,10 +11863,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// if player is autotrading
- if( dstsd->state.autotrade ) {
+ if (dstsd->state.autotrade) {
char output[256];
- sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name);
- clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1);
+ sprintf(output, msg_fd(fd, 894), dstsd->status.name); // %s is in autotrade mode and cannot receive whispered messages.
+ clif->wis_message(fd, map->wisp_server_name, output, (int)strlen(output));
return;
}
@@ -10256,20 +11883,20 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
clif->wis_end(fd, 0); // 0: success to send wisper
// Normal message
- clif->wis_message(dstsd->fd, sd->status.name, message, messagelen);
+ clif->wis_message(dstsd->fd, sd->status.name, message, (int)strlen(message));
}
-void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /b /nb (CZ_BROADCAST).
/// Request to broadcast a message on whole server.
/// 0099 <packet len>.W <text>.?B 00
-void clif_parse_Broadcast(int fd, struct map_session_data *sd)
+static void clif_parse_Broadcast(int fd, struct map_session_data *sd)
{
const char commandname[] = "kami";
char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' command + ' ' + message + NUL
int len = (int)RFIFOW(fd,2) - 4;
- if (len < 0)
+ if (len <= 0)
return;
sprintf(command, "%c%s ", atcommand->at_symbol, commandname);
@@ -10282,12 +11909,12 @@ void clif_parse_Broadcast(int fd, struct map_session_data *sd)
atcommand->exec(fd, sd, command, true);
}
-void clif_parse_TakeItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TakeItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to pick up an item.
/// 009f <id>.L (CZ_ITEM_PICKUP)
/// 0362 <id>.L (CZ_ITEM_PICKUP2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_TakeItem(int fd, struct map_session_data *sd)
+static void clif_parse_TakeItem(int fd, struct map_session_data *sd)
{
int map_object_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
struct flooritem_data *fitem = map->id2fi(map_object_id);
@@ -10307,6 +11934,7 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd)
sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_BLADESTOP] ||
sd->sc.data[SC_CLOAKINGEXCEED] ||
+ sd->sc.data[SC_SUHIDE] ||
pc_ismuted(&sd->sc, MANNER_NOITEM)
) )
break;
@@ -10323,12 +11951,12 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd)
clif->additem(sd,0,0,6);
}
-void clif_parse_DropItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_DropItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to drop an item.
/// 00a2 <index>.W <amount>.W (CZ_ITEM_THROW)
/// 0363 <index>.W <amount>.W (CZ_ITEM_THROW2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_DropItem(int fd, struct map_session_data *sd)
+static void clif_parse_DropItem(int fd, struct map_session_data *sd)
{
int item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2;
int item_amount = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]);
@@ -10359,49 +11987,54 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd)
clif->dropitem(sd, item_index, 0);
}
-void clif_parse_UseItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_UseItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to use an item.
/// 00a7 <index>.W <account id>.L (CZ_USE_ITEM)
/// 0439 <index>.W <account id>.L (CZ_USE_ITEM2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_UseItem(int fd, struct map_session_data *sd)
+static void clif_parse_UseItem(int fd, struct map_session_data *sd)
{
int n;
+ if (pc_isvending(sd))
+ return;
+
if (pc_isdead(sd)) {
clif->clearunit_area(&sd->bl, CLR_DEAD);
return;
}
- if ( (!sd->npc_id && pc_istrading(sd)) || sd->chatID )
+ if ((!sd->npc_id && pc_istrading(sd)) || sd->chat_id != 0)
return;
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
pc->update_idle_time(sd, BCIDLE_USEITEM);
n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2;
- if (n < 0 || n >= MAX_INVENTORY)
+ if (n < 0 || n >= sd->status.inventorySize)
return;
if (!pc->useitem(sd,n))
clif->useitemack(sd,n,0,false); //Send an empty ack packet or the client gets stuck.
}
-void clif_parse_EquipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_EquipItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to equip an item (CZ_REQ_WEAR_EQUIP).
/// 00a9 <index>.W <position>.W
/// 0998 <index>.W <position>.L
-void clif_parse_EquipItem(int fd,struct map_session_data *sd)
+static void clif_parse_EquipItem(int fd, struct map_session_data *sd)
{
const struct packet_equip_item *p = RP2PTR(fd);
- int index = 0;
- if(pc_isdead(sd)) {
+ if (pc_isvending(sd))
+ return;
+
+ if (pc_isdead(sd)) {
clif->clearunit_area(&sd->bl,CLR_DEAD);
return;
}
- index = p->index - 2;
- if (index >= MAX_INVENTORY)
+ int index = p->index - 2;
+ if (index < 0 || index >= sd->status.inventorySize)
return; //Out of bounds check.
if( sd->npc_id ) {
@@ -10412,15 +12045,15 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
else if ( pc_cant_act2(sd) || sd->state.prerefining )
return;
- if(!sd->status.inventory[index].identify) {
- clif->equipitemack(sd, index, 0, EIA_FAIL);// fail
+ if (!sd->status.inventory[index].identify) {
+ clif->equipitemack(sd, index, 0, EIA_FAIL); // fail
return;
}
- if(!sd->inventory_data[index])
+ if (!sd->inventory_data[index])
return;
- if(sd->inventory_data[index]->type == IT_PETARMOR){
+ if (sd->inventory_data[index]->type == IT_PETARMOR) {
pet->equipitem(sd, index);
return;
}
@@ -10428,19 +12061,22 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
pc->update_idle_time(sd, BCIDLE_USEITEM);
//Client doesn't send the position for ammo.
- if(sd->inventory_data[index]->type == IT_AMMO)
+ if (sd->inventory_data[index]->type == IT_AMMO)
pc->equipitem(sd, index, EQP_AMMO);
else
pc->equipitem(sd, index, p->wearLocation);
}
-void clif_parse_UnequipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_UnequipItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to take off an equip (CZ_REQ_TAKEOFF_EQUIP).
/// 00ab <index>.W
-void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
+static void clif_parse_UnequipItem(int fd, struct map_session_data *sd)
{
int index;
+ if (pc_isvending(sd))
+ return;
+
if(pc_isdead(sd)) {
clif->clearunit_area(&sd->bl,CLR_DEAD);
return;
@@ -10461,12 +12097,12 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
pc->unequipitem(sd,index, PCUNEQUIPITEM_RECALC);
}
-void clif_parse_NpcClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcClicked(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to start a conversation with an NPC (CZ_CONTACTNPC).
/// 0090 <id>.L <type>.B
/// type:
/// 1 = click
-void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
+static void clif_parse_NpcClicked(int fd, struct map_session_data *sd)
{
struct block_list *bl;
@@ -10474,13 +12110,15 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
clif->clearunit_area(&sd->bl,CLR_DEAD);
return;
}
- if( sd->npc_id || sd->state.workinprogress&2 ){
-#ifdef RENEWAL
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
+ if (sd->npc_id > 0 || (sd->state.workinprogress & 2) == 2 || sd->block_action.npc == 1) { // *pcblock script command
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48));
#endif
return;
}
- if ( pc_cant_act2(sd) || !(bl = map->id2bl(RFIFOL(fd,2))) || sd->state.vending )
+ if (pc_cant_act2(sd) || !(bl = map->id2bl(RFIFOL(fd,2))) || sd->state.vending || sd->state.prevend)
return;
switch (bl->type) {
@@ -10489,9 +12127,11 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
clif->pActionRequest_sub(sd, 0x07, bl->id, timer->gettick());
break;
case BL_NPC:
- if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills
-#ifdef RENEWAL
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS);
+ if (sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER) { // TODO: should only work with none 3rd job skills
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48));
#endif
break;
}
@@ -10501,15 +12141,15 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
}
}
-void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Selection between buy/sell was made (CZ_ACK_SELECT_DEALTYPE).
/// 00c5 <id>.L <type>.B
/// type:
/// 0 = buy
/// 1 = sell
-void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd)
+static void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd)
{
- if (sd->state.trading)
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
return;
npc->buysellsel(sd, RFIFOL(fd,2), RFIFOB(fd,6));
}
@@ -10521,10 +12161,18 @@ void clif_parse_NpcBuySellSelected(int fd, struct map_session_data *sd)
/// 1 = "You do not have enough zeny."
/// 2 = "You are over your Weight Limit."
/// 3 = "Out of the maximum capacity, you have too many items."
-void clif_npc_buy_result(struct map_session_data* sd, unsigned char result) {
+/// 9 = "Amounts are exceeded the possession of the item is not available for purchase."
+/// 10 = "Props open-air store sales will be traded in RODEX"
+/// 11 = "The exchange failed."
+/// 12 = "The exchange was well done."
+/// 13 = "The item is already sold and out of stock."
+/// 14 = "There is not enough goods to exchange."
+static void clif_npc_buy_result(struct map_session_data *sd, unsigned char result)
+{
int fd;
nullpo_retv(sd);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0xca));
WFIFOW(fd,0) = 0xca;
@@ -10532,17 +12180,21 @@ void clif_npc_buy_result(struct map_session_data* sd, unsigned char result) {
WFIFOSET(fd,packet_len(0xca));
}
-void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcBuyListSend(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to buy chosen items from npc shop (CZ_PC_PURCHASE_ITEMLIST).
/// 00c8 <packet len>.W { <amount>.W <name id>.W }*
-void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
+static void clif_parse_NpcBuyListSend(int fd, struct map_session_data *sd)
{
- int n = ((int)RFIFOW(fd,2)-4) / 4;
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_PC_PURCHASE_ITEMLIST *p = RFIFOP(fd, 0);
+ int n = ((int)p->packetLength - sizeof(struct PACKET_CZ_PC_PURCHASE_ITEMLIST)) / sizeof(struct PACKET_CZ_PC_PURCHASE_ITEMLIST_sub);
int result;
Assert_retv(n >= 0);
- if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) {
+ if (sd->state.trading || !sd->npc_shopid || pc_has_permission(sd, PC_PERM_DISABLE_STORE)) {
result = 1;
} else {
struct itemlist item_list = { 0 };
@@ -10553,8 +12205,8 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
for (i = 0; i < n; i++) {
struct itemlist_entry entry = { 0 };
- entry.amount = RFIFOW(fd, 4 + 4 * i);
- entry.id = RFIFOW(fd, 4 + 4 * i + 2);
+ entry.amount = p->items[i].amount;
+ entry.id = p->items[i].itemId;
VECTOR_PUSH(item_list, entry);
}
@@ -10572,10 +12224,12 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
/// result:
/// 0 = "The deal has successfully completed."
/// 1 = "The deal has failed."
-void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) {
+static void clif_npc_sell_result(struct map_session_data *sd, unsigned char result)
+{
int fd;
nullpo_retv(sd);
+ pc->update_idle_time(sd, BCIDLE_SCRIPT);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0xcb));
WFIFOW(fd,0) = 0xcb;
@@ -10583,10 +12237,10 @@ void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) {
WFIFOSET(fd,packet_len(0xcb));
}
-void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcSellListSend(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to sell chosen items to npc shop (CZ_PC_SELL_ITEMLIST).
/// 00c9 <packet len>.W { <index>.W <amount>.W }*
-void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
+static void clif_parse_NpcSellListSend(int fd, struct map_session_data *sd)
{
int fail=0,n;
@@ -10594,7 +12248,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
Assert_retv(n >= 0);
- if (sd->state.trading || !sd->npc_shopid) {
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd) || !sd->npc_shopid) {
fail = 1;
} else {
struct itemlist item_list = { 0 };
@@ -10621,26 +12275,40 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
clif->npc_sell_result(sd, fail);
}
-void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_CreateChatRoom(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Chatroom creation request (CZ_CREATE_CHATROOM).
/// 00d5 <packet len>.W <limit>.W <type>.B <passwd>.8B <title>.?B
/// type:
/// 0 = private
/// 1 = public
-void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd)
+static void clif_parse_CreateChatRoom(int fd, struct map_session_data *sd)
{
- int len = RFIFOW(fd,2)-15;
- int limit = RFIFOW(fd,4);
- bool pub = (RFIFOB(fd,6) != 0);
- const char *password = RFIFOP(fd,7); //not zero-terminated
- const char *title = RFIFOP(fd,15); // not zero-terminated
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = (int)RFIFOW(fd, 2) - 15;
+ int limit;
+ bool pub;
+ const char *password; //not zero-terminated
+ const char *title; // not zero-terminated
char s_password[CHATROOM_PASS_SIZE];
char s_title[CHATROOM_TITLE_SIZE];
+ if (len < 1)
+ return;
+
+ limit = RFIFOW(fd, 4);
+ pub = (RFIFOB(fd, 6) != 0);
+ password = RFIFOP(fd, 7); //not zero-terminated
+ title = RFIFOP(fd, 15); // not zero-terminated
+
+ if (limit < 0)
+ return;
+
if (pc_ismuted(&sd->sc, MANNER_NOROOM))
return;
- if(battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 4) {
- clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,3);
+ if(battle_config.basic_skill_check && !pc->check_basicskill(sd, 4)) {
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 3, 0);
return;
}
if( npc->isnear(&sd->bl) ) {
@@ -10648,48 +12316,58 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd)
//char output[150];
//sprintf(output, msg_txt(862), battle_config.min_npc_vendchat_distance); // "You're too close to a NPC, you must be at least %d cells away from any NPC."
//clif_displaymessage(sd->fd, output);
- clif->skill_fail(sd,1,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0);
+ clif->skill_fail(sd, 1, USESKILL_FAIL_THERE_ARE_NPC_AROUND, 0, 0);
return;
}
- if( len <= 0 )
- return; // invalid input
-
safestrncpy(s_password, password, CHATROOM_PASS_SIZE);
safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte
chat->create_pc_chat(sd, s_title, s_password, limit, pub);
}
-void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ChatAddMember(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Chatroom join request (CZ_REQ_ENTER_ROOM).
/// 00d9 <chat ID>.L <passwd>.8B
-void clif_parse_ChatAddMember(int fd, struct map_session_data* sd)
+static void clif_parse_ChatAddMember(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int chatid = RFIFOL(fd,2);
const char *password = RFIFOP(fd,6); // not zero-terminated
chat->join(sd,chatid,password);
}
-void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Chatroom properties adjustment request (CZ_CHANGE_CHATROOM).
/// 00de <packet len>.W <limit>.W <type>.B <passwd>.8B <title>.?B
/// type:
/// 0 = private
/// 1 = public
-void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd)
+static void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd)
{
- int len = RFIFOW(fd,2)-15;
- int limit = RFIFOW(fd,4);
- bool pub = (RFIFOB(fd,6) != 0);
- const char *password = RFIFOP(fd,7); // not zero-terminated
- const char *title = RFIFOP(fd,15); // not zero-terminated
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = (int)RFIFOW(fd, 2) - 15;
+ int limit;
+ bool pub;
+ const char *password; // not zero-terminated
+ const char *title; // not zero-terminated
char s_password[CHATROOM_PASS_SIZE];
char s_title[CHATROOM_TITLE_SIZE];
- if( len <= 0 )
- return; // invalid input
+ if (len < 1)
+ return;
+
+ limit = RFIFOW(fd, 4);
+ if (limit < 0)
+ return;
+ pub = (RFIFOB(fd, 6) != 0);
+ password = RFIFOP(fd, 7); // not zero-terminated
+ title = RFIFOP(fd, 15); // not zero-terminated
safestrncpy(s_password, password, CHATROOM_PASS_SIZE);
safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte
@@ -10697,57 +12375,69 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd)
chat->change_status(sd, s_title, s_password, limit, pub);
}
-void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change the chat room ownership (CZ_REQ_ROLE_CHANGE).
/// 00e0 <role>.L <nick>.24B
/// role:
/// 0 = owner
/// 1 = normal
-void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd)
+static void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd)
{
- chat->change_owner(sd, RFIFOP(fd,6));
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ chat->change_owner(sd, RFIFOP(fd,6)); // non null terminated
}
-void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_KickFromChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to expel a player from chat room (CZ_REQ_EXPEL_MEMBER).
/// 00e2 <name>.24B
-void clif_parse_KickFromChat(int fd,struct map_session_data *sd)
+static void clif_parse_KickFromChat(int fd, struct map_session_data *sd)
{
- chat->kick(sd, RFIFOP(fd,2));
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ chat->kick(sd, RFIFOP(fd,2)); // non null terminated
}
-void clif_parse_ChatLeave(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ChatLeave(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to leave the current chatroom (CZ_EXIT_ROOM).
/// 00e3
-void clif_parse_ChatLeave(int fd, struct map_session_data* sd)
+static void clif_parse_ChatLeave(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
chat->leave(sd, false);
}
//Handles notifying asker and rejecter of what has just occurred.
//Type is used to determine the correct msg_txt to use:
//0:
-void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) {
+static void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type)
+{
const char* msg;
char output[256];
nullpo_retv(src);
// Your request has been rejected by autoreject option.
msg = msg_sd(src,392);
- clif_disp_onlyself(src, msg, strlen(msg));
+ clif_disp_onlyself(src, msg);
//Notice that a request was rejected.
snprintf(output, 256, msg_sd(target,393+type), src->status.name, 256);
- clif_disp_onlyself(target, output, strlen(output));
+ clif_disp_onlyself(target, output);
}
-void clif_parse_TradeRequest(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeRequest(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to begin a trade (CZ_REQ_EXCHANGE_ITEM).
/// 00e4 <account id>.L
-void clif_parse_TradeRequest(int fd,struct map_session_data *sd) {
- struct map_session_data *t_sd;
+static void clif_parse_TradeRequest(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- t_sd = map->id2sd(RFIFOL(fd,2));
+ struct map_session_data *t_sd = map->id2sd(RFIFOL(fd, 2));
- if(!sd->chatID && pc_cant_act(sd))
+ if (sd->chat_id == 0 && pc_cant_act(sd))
return; //You can trade while in a chatroom.
// @noask [LuzZza]
@@ -10756,30 +12446,36 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) {
return;
}
- if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 1) {
- clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,0);
+ if( battle_config.basic_skill_check && !pc->check_basicskill(sd, 1)) {
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
trade->request(sd,t_sd);
}
-void clif_parse_TradeAck(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to a trade request (CZ_ACK_EXCHANGE_ITEM).
/// 00e6 <result>.B
/// result:
/// 3 = accepted
/// 4 = rejected
-void clif_parse_TradeAck(int fd,struct map_session_data *sd)
+static void clif_parse_TradeAck(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
trade->ack(sd,RFIFOB(fd,2));
}
-void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeAddItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add an item to current trade (CZ_ADD_EXCHANGE_ITEM).
/// 00e8 <index>.W <amount>.L
-void clif_parse_TradeAddItem(int fd,struct map_session_data *sd)
+static void clif_parse_TradeAddItem(int fd, struct map_session_data *sd)
{
+ if (!sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
short index = RFIFOW(fd,2);
int amount = RFIFOL(fd,4);
@@ -10789,67 +12485,78 @@ void clif_parse_TradeAddItem(int fd,struct map_session_data *sd)
trade->additem(sd, index, (short)amount);
}
-void clif_parse_TradeOk(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeOk(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to lock items in current trade (CZ_CONCLUDE_EXCHANGE_ITEM).
/// 00eb
-void clif_parse_TradeOk(int fd,struct map_session_data *sd)
+static void clif_parse_TradeOk(int fd, struct map_session_data *sd)
{
+ if (pc_isdead(sd) || pc_isvending(sd))
+ return;
trade->ok(sd);
}
-void clif_parse_TradeCancel(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeCancel(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to cancel current trade (CZ_CANCEL_EXCHANGE_ITEM).
/// 00ed
-void clif_parse_TradeCancel(int fd,struct map_session_data *sd)
+static void clif_parse_TradeCancel(int fd, struct map_session_data *sd)
{
+ if (pc_isdead(sd) || pc_isvending(sd))
+ return;
+
trade->cancel(sd);
}
-void clif_parse_TradeCommit(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_TradeCommit(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to commit current trade (CZ_EXEC_EXCHANGE_ITEM).
/// 00ef
-void clif_parse_TradeCommit(int fd,struct map_session_data *sd)
+static void clif_parse_TradeCommit(int fd, struct map_session_data *sd)
{
+ if (pc_isdead(sd) || pc_isvending(sd))
+ return;
+
trade->commit(sd);
}
-void clif_parse_StopAttack(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_StopAttack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to stop chasing/attacking an unit (CZ_CANCEL_LOCKON).
/// 0118
-void clif_parse_StopAttack(int fd,struct map_session_data *sd)
+static void clif_parse_StopAttack(int fd, struct map_session_data *sd)
{
pc_stop_attack(sd);
}
-void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PutItemToCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from inventory to cart (CZ_MOVE_ITEM_FROM_BODY_TO_CART).
/// 0126 <index>.W <amount>.L
-void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) {
+static void clif_parse_PutItemToCart(int fd, struct map_session_data *sd)
+{
int flag = 0;
- if (pc_istrading(sd))
+ if (pc_istrading(sd) || sd->state.prevend)
return;
if (!pc_iscarton(sd))
return;
if ( (flag = pc->putitemtocart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4))) ) {
- clif->dropitem(sd, RFIFOW(fd,2)-2,0);
+ clif->item_movefailed(sd, RFIFOW(fd,2)-2);
clif->cart_additem_ack(sd,flag == 1?0x0:0x1);
}
}
-void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GetItemFromCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from cart to inventory (CZ_MOVE_ITEM_FROM_CART_TO_BODY).
/// 0127 <index>.W <amount>.L
-void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd)
+static void clif_parse_GetItemFromCart(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || sd->state.prevend)
+ return;
if (!pc_iscarton(sd))
return;
pc->getitemfromcart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4));
}
-void clif_parse_RemoveOption(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RemoveOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to remove cart/falcon/peco/dragon (CZ_REQ_CARTOFF).
/// 012a
-void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
+static void clif_parse_RemoveOption(int fd, struct map_session_data *sd)
{
if (pc_isridingpeco(sd) || pc_isfalcon(sd) || pc_isridingdragon(sd) || pc_ismadogear(sd)) {
// priority to remove this option before we can clear cart
@@ -10864,47 +12571,82 @@ void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
}
}
-void clif_parse_ChangeCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_reqGearOff(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_reqGearOff(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190703 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190709
+ const struct PACKET_CZ_REQ_MOUNTOFF *p = RFIFOP(fd, 0);
+ switch (p->action) {
+ case REMOVE_MOUNT_DRAGON:
+ if (pc_isridingdragon(sd))
+ pc->setoption(sd, sd->sc.option &~ OPTION_DRAGON);
+ break;
+ case REMOVE_MOUNT_MADO:
+ if (pc_ismadogear(sd))
+ pc->setoption(sd, sd->sc.option &~ OPTION_MADOGEAR);
+ break;
+ case REMOVE_MOUNT_PECO:
+ if (pc_isridingpeco(sd))
+ pc->setoption(sd, sd->sc.option &~ OPTION_RIDING);
+ break;
+ case REMOVE_MOUNT_FALCON:
+ if (pc_isfalcon(sd))
+ pc->setoption(sd, sd->sc.option &~ OPTION_FALCON);
+ break;
+ case REMOVE_MOUNT_CART:
+ // this packet exists in clients with only new carts [4144]
+ if (sd->sc.data[SC_PUSH_CART])
+ pc->setcart(sd, 0);
+ break;
+ case REMOVE_MOUNT_0:
+ case REMOVE_MOUNT_2:
+ default:
+ ShowError("Unknown action in remove mount packet: %d\n", p->action);
+ break;
+ }
+#endif
+}
+
+static void clif_parse_ChangeCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change cart's visual look (CZ_REQ_CHANGECART).
/// 01af <num>.W
-void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
+static void clif_parse_ChangeCart(int fd, struct map_session_data *sd)
{// TODO: State tracking?
int type;
- if( pc->checkskill(sd, MC_CHANGECART) < 1 )
+ if (pc->checkskill(sd, MC_CHANGECART) == 0)
return;
-#ifdef RENEWAL
- if( sd->npc_id || sd->state.workinprogress&1 ){
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS);
+ if (sd->npc_id || sd->state.workinprogress & 1) {
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48));
+#endif
return;
}
-#endif
- type = RFIFOW(fd,2);
+ type = RFIFOW(fd, 2);
+
+ if (
#ifdef NEW_CARTS
- if( (type == 9 && sd->status.base_level > 131) ||
- (type == 8 && sd->status.base_level > 121) ||
- (type == 7 && sd->status.base_level > 111) ||
- (type == 6 && sd->status.base_level > 101) ||
+ (type == 9 && sd->status.base_level > 130) ||
+ (type == 8 && sd->status.base_level > 120) ||
+ (type == 7 && sd->status.base_level > 110) ||
+ (type == 6 && sd->status.base_level > 100) ||
+#endif
(type == 5 && sd->status.base_level > 90) ||
(type == 4 && sd->status.base_level > 80) ||
(type == 3 && sd->status.base_level > 65) ||
(type == 2 && sd->status.base_level > 40) ||
(type == 1))
-#else
- if( (type == 5 && sd->status.base_level > 90) ||
- (type == 4 && sd->status.base_level > 80) ||
- (type == 3 && sd->status.base_level > 65) ||
- (type == 2 && sd->status.base_level > 40) ||
- (type == 1))
-#endif
- pc->setcart(sd,type);
+
+ pc->setcart(sd, type);
}
/// Request to select cart's visual look for new cart design (CZ_SELECTCART).
/// 0980 <identity>.L <type>.B
-void clif_parse_SelectCart(int fd, struct map_session_data *sd)
+static void clif_parse_SelectCart(int fd, struct map_session_data *sd)
{
#if PACKETVER >= 20150805 // RagexeRE
int type;
@@ -10921,7 +12663,7 @@ void clif_parse_SelectCart(int fd, struct map_session_data *sd)
#endif
}
-void clif_parse_StatusUp(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_StatusUp(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to increase status (CZ_STATUS_CHANGE).
/// 00bb <status id>.W <amount>.B
/// status id:
@@ -10929,7 +12671,8 @@ void clif_parse_StatusUp(int fd,struct map_session_data *sd) __attribute__((nonn
/// amount:
/// Old clients send always 1 for this, even when using /str+ and the like.
/// Newer clients (2013-12-23 and newer) send the correct amount.
-void clif_parse_StatusUp(int fd,struct map_session_data *sd) {
+static void clif_parse_StatusUp(int fd, struct map_session_data *sd)
+{
int increase_amount;
increase_amount = RFIFOB(fd,4);
@@ -10941,15 +12684,16 @@ void clif_parse_StatusUp(int fd,struct map_session_data *sd) {
pc->statusup(sd, RFIFOW(fd,2), increase_amount);
}
-void clif_parse_SkillUp(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SkillUp(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to increase level of a skill (CZ_UPGRADE_SKILLLEVEL).
/// 0112 <skill id>.W
-void clif_parse_SkillUp(int fd,struct map_session_data *sd)
+static void clif_parse_SkillUp(int fd, struct map_session_data *sd)
{
pc->skillup(sd,RFIFOW(fd,2));
}
-void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) {
+static void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id)
+{
int lv;
nullpo_retv(sd);
@@ -10967,7 +12711,7 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat
else if (DIFF_TICK(tick, hd->ud.canact_tick) < 0){
clif->emotion(&hd->bl, E_DOTS);
if (hd->master)
- clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -10979,7 +12723,8 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat
unit->skilluse_id(&hd->bl, target_id, skill_id, skill_lv);
}
-void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) {
+static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo)
+{
int lv;
nullpo_retv(sd);
if( !hd )
@@ -10994,7 +12739,7 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da
} else if ( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) {
clif->emotion(&hd->bl, E_DOTS);
if ( hd->master )
- clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -11007,7 +12752,8 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da
unit->skilluse_pos(&hd->bl, x, y, skill_id, skill_lv);
}
-void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) {
+static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id)
+{
int lv;
nullpo_retv(sd);
@@ -11029,7 +12775,8 @@ void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_ses
unit->skilluse_id(&md->bl, target_id, skill_id, skill_lv);
}
-void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) {
+static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo)
+{
int lv;
nullpo_retv(sd);
if( !md )
@@ -11039,7 +12786,7 @@ void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_se
if( md->ud.skilltimer != INVALID_TIMER )
return;
if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) {
- clif->skill_fail(md->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ clif->skill_fail(md->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -11052,33 +12799,32 @@ void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_se
unit->skilluse_pos(&md->bl, x, y, skill_id, skill_lv);
}
-void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-/// Request to use a targeted skill.
-/// 0113 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL)
-/// 0438 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL2)
-/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
+static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill_id, int skill_lv, int target_id) __attribute__((nonnull (2)));
+static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill_id, int skill_lv, int target_id)
{
- uint16 skill_id, skill_lv;
- int tmp, target_id;
int64 tick = timer->gettick();
- skill_lv = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- skill_id = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]);
- target_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[2]);
+ /**
+ * According to Skotlex' comment below, the client sometimes passes 0 for the skill level.
+ * Even though this seems to only affect guild skills, sd->autocast.skill_lv is used
+ * for the auto-cast data validation if skill_lv is 0.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
- if( skill_lv < 1 ) skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
+ if (skill_lv < 1)
+ skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
- tmp = skill->get_inf(skill_id);
- if (tmp&INF_GROUND_SKILL || !tmp)
+ int tmp = skill->get_inf(skill_id);
+ if (tmp & INF_GROUND_SKILL || !tmp)
return; //Using a ground/passive skill on a target? WRONG.
- if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) {
+ if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL) {
clif->pUseSkillToId_homun(sd->hd, sd, tick, skill_id, skill_lv, target_id);
return;
}
- if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) {
+ if (skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL) {
clif->pUseSkillToId_mercenary(sd->md, sd, tick, skill_id, skill_lv, target_id);
return;
}
@@ -11086,90 +12832,137 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
pc->update_idle_time(sd, BCIDLE_USESKILLTOID);
- if( sd->npc_id || sd->state.workinprogress&1 ){
-#ifdef RENEWAL
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
+ if (sd->npc_id || sd->state.workinprogress & 1) {
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48));
#endif
return;
}
- if( pc_cant_act(sd)
- && skill_id != RK_REFRESH
- && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN))
- && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027
- )
+ if (pc_cant_act(sd)
+ && skill_id != RK_REFRESH
+ && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN))
+ && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027
+ ) {
return;
+ }
- if( pc_issit(sd) )
+ if (pc_issit(sd))
return;
- if( skill->not_ok(skill_id, sd) )
+ if (skill->not_ok(skill_id, sd))
return;
- if( sd->bl.id != target_id && tmp&INF_SELF_SKILL )
+ if (sd->bl.id != target_id && tmp & INF_SELF_SKILL)
target_id = sd->bl.id; // never trust the client
- if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris]
+ if (target_id < 0 && -target_id == sd->bl.id) // for disguises [Valaris]
target_id = sd->bl.id;
- if( sd->ud.skilltimer != INVALID_TIMER ) {
- if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST )
+ if (sd->ud.skilltimer != INVALID_TIMER) {
+ if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST)
return;
- } else if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
- if( sd->skillitem != skill_id ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ } else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
+ if (sd->autocast.type == AUTOCAST_NONE) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
}
- if( sd->sc.option&OPTION_COSTUME )
+ if (sd->sc.option & OPTION_COSTUME)
return;
- if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
+ if (sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id))
return; // On basilica only caster can use Basilica again to stop it.
- if( sd->menuskill_id ) {
- if( sd->menuskill_id == SA_TAMINGMONSTER ) {
+ if (sd->menuskill_id) {
+ if (sd->menuskill_id == SA_TAMINGMONSTER) {
clif_menuskill_clear(sd); //Cancel pet capture.
- } else if( sd->menuskill_id != SA_AUTOSPELL )
+ } else if (sd->menuskill_id != SA_AUTOSPELL)
return; //Can't use skills while a menu is open.
}
- if( sd->skillitem == skill_id ) {
- if( skill_lv != sd->skillitemlv )
- skill_lv = sd->skillitemlv;
- if( !(tmp&INF_SELF_SKILL) )
+ if (sd->autocast.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->autocast.skill_lv)
+ skill_lv = sd->autocast.skill_lv;
+ if (!(tmp&INF_SELF_SKILL))
pc->delinvincibletimer(sd); // Target skills through items cancel invincibility. [Inkfish]
unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
return;
}
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
- if( skill_id >= GD_SKILLBASE ) {
- if( sd->state.gmaster_flag )
+ if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) {
+ if (sd->state.gmaster_flag)
skill_lv = guild->checkskill(sd->guild, skill_id);
else
skill_lv = 0;
} else {
tmp = pc->checkskill(sd, skill_id);
- if( skill_lv > tmp )
+ if (skill_lv > tmp)
skill_lv = tmp;
}
pc->delinvincibletimer(sd);
- if( skill_lv )
+ if (skill_lv)
unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
}
+static void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/// Request to use a targeted skill.
+/// 0113 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL)
+/// 0438 <skill lv>.W <skill id>.W <target id>.L (CZ_USE_SKILL2)
+/// There are various variants of this packet, some of them have padding between fields.
+static void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
+{
+ clif->useSkillToIdReal(fd,
+ sd,
+ RFIFOW(fd, packet_db[RFIFOW(fd, 0)].pos[1]),
+ RFIFOW(fd, packet_db[RFIFOW(fd, 0)].pos[0]),
+ RFIFOL(fd, packet_db[RFIFOW(fd, 0)].pos[2]));
+}
+
+static void clif_parse_startUseSkillToId(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_startUseSkillToId(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+ const struct PACKET_CZ_START_USE_SKILL *p = RFIFOP(fd, 0);
+ clif->useSkillToIdReal(fd, sd, p->skillId, p->skillLv, p->targetId);
+#endif
+}
+
+static void clif_parse_stopUseSkillToId(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_stopUseSkillToId(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+ const struct PACKET_CZ_STOP_USE_SKILL *p = RFIFOP(fd, 0);
+ if (p->skillId != GC_ROLLINGCUTTER) {
+ ShowWarning("Packet CZ_STOP_USE_SKILL usage for unknown skill: %d\n", p->skillId);
+ }
+#endif
+}
+
/*==========================================
* Client tells server he'd like to use AoE skill id 'skill_id' of level 'skill_lv' on 'x','y' location
*------------------------------------------*/
-void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo)
+static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo)
{
int64 tick = timer->gettick();
nullpo_retv(sd);
+
+ /**
+ * When using clif_item_skill() to initiate the execution of ground skills,
+ * the client sometimes passes 0 for the skill level in packet 0x0af4.
+ * In that case sd->autocast.skill_lv is used for the auto-cast data validation,
+ * since clif_item_skill() is only used for auto-cast skills.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
+
if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) )
return; //Using a target skill on the ground? WRONG.
@@ -11183,12 +12976,14 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
return;
}
-#ifdef RENEWAL
- if( sd->state.workinprogress&1 ){
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
+ if (sd->state.workinprogress & 1) {
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48));
+#endif
return;
}
-#endif
//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
pc->update_idle_time(sd, BCIDLE_USESKILLTOPOS);
@@ -11197,19 +12992,19 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
return;
if( skillmoreinfo != -1 ) {
if( pc_issit(sd) ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
//You can't use Graffiti/TalkieBox AND have a vending open, so this is safe.
- safestrncpy(sd->message, RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE);
+ safestrncpy(sd->message, RFIFOP(fd, skillmoreinfo), TALKBOX_MESSAGE_SIZE);
}
if( sd->ud.skilltimer != INVALID_TIMER )
return;
if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
- if( sd->skillitem != skill_id ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ if (sd->autocast.type == AUTOCAST_NONE) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
}
@@ -11229,13 +13024,13 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
pc->delinvincibletimer(sd);
- if( sd->skillitem == skill_id ) {
- if( skill_lv != sd->skillitemlv )
- skill_lv = sd->skillitemlv;
+ if (sd->autocast.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->autocast.skill_lv)
+ skill_lv = sd->autocast.skill_lv;
unit->skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
} else {
int lv;
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
if( (lv = pc->checkskill(sd, skill_id)) > 0 ) {
if( skill_lv > lv )
skill_lv = lv;
@@ -11244,12 +13039,12 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
}
}
-void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to use a ground skill.
/// 0116 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND)
/// 0366 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
+static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
{
if (pc_cant_act(sd))
return;
@@ -11265,12 +13060,12 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
);
}
-void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to use a ground skill with text.
/// 0190 <skill lv>.W <skill id>.W <x>.W <y>.W <contents>.80B (CZ_USE_SKILL_TOGROUND_WITHTALKBOX)
/// 0367 <skill lv>.W <skill id>.W <x>.W <y>.W <contents>.80B (CZ_USE_SKILL_TOGROUND_WITHTALKBOX2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd)
+static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd)
{
if (pc_cant_act(sd))
return;
@@ -11286,10 +13081,10 @@ void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd)
);
}
-void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to map selection dialog (CZ_SELECT_WARPPOINT).
/// 011b <skill id>.W <map name>.16B
-void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
+static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd)
{
uint16 skill_id = RFIFOW(fd,2);
char map_name[MAP_NAME_LENGTH];
@@ -11306,25 +13101,34 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
return;
}
+ /**
+ * Since no skill level was passed use 0 to notify skill_validate_autocast_data() of this special case.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, 0);
+
pc->delinvincibletimer(sd);
skill->castend_map(sd,skill_id,map_name);
+ pc->autocast_clear(sd);
}
-void clif_parse_RequestMemo(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RequestMemo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to set a memo on current map (CZ_REMEMBER_WARPPOINT).
/// 011d
-void clif_parse_RequestMemo(int fd,struct map_session_data *sd)
+static void clif_parse_RequestMemo(int fd, struct map_session_data *sd)
{
if (!pc_isdead(sd))
pc->memo(sd,-1);
}
-void clif_parse_ProduceMix(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ProduceMix(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to pharmacy item selection dialog (CZ_REQMAKINGITEM).
/// 018e <name id>.W { <material id>.W }*3
-void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
+static void clif_parse_ProduceMix(int fd, struct map_session_data *sd)
{
- switch( sd->menuskill_id ) {
+ const struct PACKET_CZ_REQMAKINGITEM *p = RFIFOP(fd, 0);
+
+ switch (sd->menuskill_id) {
case -1:
case AM_PHARMACY:
case RK_RUNEMASTERY:
@@ -11333,18 +13137,19 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
default:
return;
}
- if (pc_istrading(sd)) {
+ if (pc_istrading(sd) || pc_isdead(sd) || pc_isvending(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif_menuskill_clear(sd);
return;
}
- if( skill->can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) )
- skill->produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1);
+
+ if (skill->can_produce_mix(sd, p->itemId, sd->menuskill_val, 1))
+ skill->produce_mix(sd, 0, p->itemId, p->material[0], p->material[1], p->material[2], 1);
clif_menuskill_clear(sd);
}
-void clif_parse_Cooking(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Cooking(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to mixing item selection dialog (CZ_REQ_MAKINGITEM).
/// 025b <mk type>.W <name id>.W
/// mk type:
@@ -11354,64 +13159,66 @@ void clif_parse_Cooking(int fd,struct map_session_data *sd) __attribute__((nonnu
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
-void clif_parse_Cooking(int fd,struct map_session_data *sd) {
- int type = RFIFOW(fd,2);
- int nameid = RFIFOW(fd,4);
- int amount = sd->menuskill_val2?sd->menuskill_val2:1;
- if( type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY )
+static void clif_parse_Cooking(int fd, struct map_session_data *sd)
+{
+ const struct PACKET_CZ_REQ_MAKINGITEM *p = RFIFOP(fd, 0);
+ int type = p->type;
+ int nameid = p->itemId;
+ int amount = sd->menuskill_val2 ? sd->menuskill_val2 : 1;
+ if (type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY)
return;
- if (pc_istrading(sd)) {
+ if (pc_istrading(sd) || pc_isdead(sd) || pc_isvending(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif_menuskill_clear(sd);
return;
}
- if( skill->can_produce_mix(sd,nameid,sd->menuskill_val, amount) )
- skill->produce_mix(sd,(type>1?sd->menuskill_id:0),nameid,0,0,0,amount);
+ if (skill->can_produce_mix(sd, nameid, sd->menuskill_val, amount))
+ skill->produce_mix(sd, (type > 1 ? sd->menuskill_id : 0), nameid, 0, 0, 0, amount);
clif_menuskill_clear(sd);
}
-void clif_parse_RepairItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RepairItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to repair weapon item selection dialog (CZ_REQ_ITEMREPAIR).
/// 01fd <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W
-void clif_parse_RepairItem(int fd, struct map_session_data *sd)
+static void clif_parse_RepairItem(int fd, struct map_session_data *sd)
{
+ const struct PACKET_CZ_REQ_ITEMREPAIR *p = RFIFOP(fd, 0);
+
if (sd->menuskill_id != BS_REPAIRWEAPON)
return;
- if (pc_istrading(sd)) {
+ if (pc_istrading(sd) || pc_isdead(sd) || pc_isvending(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif_menuskill_clear(sd);
return;
}
- skill->repairweapon(sd,RFIFOW(fd,2));
+ skill->repairweapon(sd, p->index);
clif_menuskill_clear(sd);
}
-void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to refine weapon item selection dialog (CZ_REQ_WEAPONREFINE).
/// 0222 <index>.L
-void clif_parse_WeaponRefine(int fd, struct map_session_data *sd)
+static void clif_parse_WeaponRefine(int fd, struct map_session_data *sd)
{
- int idx;
-
sd->state.prerefining = 0;
if (sd->menuskill_id != WS_WEAPONREFINE) //Packet exploit?
return;
- if (pc_istrading(sd)) {
+ if (pc_istrading(sd) || pc_isdead(sd) || pc_isvending(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif_menuskill_clear(sd);
return;
}
- idx = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
+ int idx = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
skill->weaponrefine(sd, idx-2);
clif_menuskill_clear(sd);
}
-void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcSelectMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to script menu dialog (CZ_CHOOSE_MENU).
/// 00b8 <npc id>.L <choice>.B
/// choice:
@@ -11419,12 +13226,15 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) __attribute__(
/// 255 = cancel
/// NOTE: If there were more than 254 items in the list, choice
/// overflows to choice%256.
-void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
+static void clif_parse_NpcSelectMenu(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int npc_id = RFIFOL(fd,2);
uint8 select = RFIFOB(fd,6);
- if( (select > sd->npc_menu && select != 0xff) || select == 0 ) {
+ if( (select > sd->npc_menu && select != MAX_MENU_OPTIONS) || select == 0 ) {
#ifdef SECURE_NPCTIMEOUT
if( sd->npc_idle_timer != INVALID_TIMER ) {
#endif
@@ -11441,63 +13251,95 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
npc->scriptcont(sd,npc_id, false);
}
-void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcNextClicked(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// NPC dialog 'next' click (CZ_REQ_NEXT_SCRIPT).
/// 00b9 <npc id>.L
-void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd)
+static void clif_parse_NpcNextClicked(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
npc->scriptcont(sd,RFIFOL(fd,2), false);
}
-void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcAmountInput(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// NPC numeric input dialog value (CZ_INPUT_EDITDLG).
/// 0143 <npc id>.L <value>.L
-void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd)
+static void clif_parse_NpcAmountInput(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int npcid = RFIFOL(fd,2);
int amount = RFIFOL(fd,6);
- if (amount >= 0)
+ if (amount < sd->npc_amount_min) {
+ sd->npc_amount = sd->npc_amount_min;
+ sd->npc_input_capped_range = -1;
+ }
+ else if (amount > sd->npc_amount_max) {
+ sd->npc_amount = sd->npc_amount_max;
+ sd->npc_input_capped_range = 1;
+ }
+ else {
sd->npc_amount = amount;
- else
- sd->npc_amount = 0;
+ sd->npc_input_capped_range = 0;
+ }
+
npc->scriptcont(sd, npcid, false);
}
-void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcStringInput(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// NPC text input dialog value (CZ_INPUT_EDITDLGSTR).
/// 01d5 <packet len>.W <npc id>.L <string>.?B
-void clif_parse_NpcStringInput(int fd, struct map_session_data* sd)
+static void clif_parse_NpcStringInput(int fd, struct map_session_data *sd)
{
- int message_len = RFIFOW(fd,2)-8;
- int npcid = RFIFOL(fd,4);
- const char *message = RFIFOP(fd,8);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = RFIFOW(fd, 2);
+// [4144] can't confirm exact client version. At least >= correct for 20150513
+#if PACKETVER >= 20151029
+ int message_len = len - 7;
+#else
+ int message_len = len - 8;
+#endif
+ int npcid;
+ const char *message;
- if( message_len <= 0 )
- return; // invalid input
+ if (len < 9)
+ return;
+
+ npcid = RFIFOL(fd, 4);
+ message = RFIFOP(fd, 8);
safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE));
npc->scriptcont(sd, npcid, false);
}
-void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NpcCloseClicked(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// NPC dialog 'close' click (CZ_CLOSE_DIALOG).
/// 0146 <npc id>.L
-void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd)
+static void clif_parse_NpcCloseClicked(int fd, struct map_session_data *sd)
{
if (!sd->npc_id) //Avoid parsing anything when the script was done with. [Skotlex]
return;
+ if (sd->state.trading || pc_isvending(sd))
+ return;
sd->state.dialog = 0;
npc->scriptcont(sd, RFIFOL(fd,2), true);
}
-void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ItemIdentify(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to identify item selection dialog (CZ_REQ_ITEMIDENTIFY).
/// 0178 <index>.W
/// index:
/// -1 = cancel
-void clif_parse_ItemIdentify(int fd,struct map_session_data *sd)
+static void clif_parse_ItemIdentify(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
short idx = RFIFOW(fd,2);
if (sd->menuskill_id != MC_IDENTIFY)
@@ -11512,59 +13354,71 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd)
clif_menuskill_clear(sd);
}
-/// Identifying item with right-click (CZ_REQ_ONECLICK_ITEMIDENTIFY).
-/// 0A35 <index>.W
-void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd)
+/// Identifying item with right-click (CZ_REQ_ONECLICK_ITEMIDENTIFY).
+/// 0A35 <index>.W
+static void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int cmd = RFIFOW(fd,0);
short idx = RFIFOW(fd, packet_db[cmd].pos[0]) - 2;
int n;
-
- if (idx < 0 || idx >= MAX_INVENTORY || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].nameid <= 0)
+
+ if (idx < 0 || idx >= sd->status.inventorySize || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].nameid <= 0)
return;
-
- if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND &&
+
+ if ((n = pc->have_magnifier(sd)) != INDEX_NOT_FOUND &&
pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0)
skill->identify(sd, idx);
}
-void clif_parse_SelectArrow(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SelectArrow(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to arrow crafting item selection dialog (CZ_REQ_MAKINGARROW).
/// 01ae <name id>.W
-void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
+static void clif_parse_SelectArrow(int fd, struct map_session_data *sd)
{
- if (pc_istrading(sd)) {
- //Make it fail to avoid shop exploits where you sell something different than you see.
- clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
+ int itemId;
+ if (pc_istrading(sd) || pc_isdead(sd) || pc_isvending(sd)) {
+ //Make it fail to avoid shop exploits where you sell something different than you see.
+ clif->skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif_menuskill_clear(sd);
return;
}
- switch( sd->menuskill_id ) {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ itemId = RFIFOL(fd, 2);
+#else
+ itemId = RFIFOW(fd, 2);
+#endif
+ switch (sd->menuskill_id) {
case AC_MAKINGARROW:
- skill->arrow_create(sd,RFIFOW(fd,2));
+ skill->arrow_create(sd, itemId);
break;
case SA_CREATECON:
- skill->produce_mix(sd,SA_CREATECON,RFIFOW(fd,2),0,0,0, 1);
+ skill->produce_mix(sd, SA_CREATECON, itemId, 0, 0, 0, 1);
break;
case WL_READING_SB:
- skill->spellbook(sd,RFIFOW(fd,2));
+ skill->spellbook(sd, itemId);
break;
case GC_POISONINGWEAPON:
- skill->poisoningweapon(sd,RFIFOW(fd,2));
+ skill->poisoningweapon(sd, itemId);
break;
case NC_MAGICDECOY:
- skill->magicdecoy(sd,RFIFOW(fd,2));
+ skill->magicdecoy(sd, itemId);
break;
}
clif_menuskill_clear(sd);
}
-void clif_parse_AutoSpell(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_AutoSpell(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to SA_AUTOSPELL skill selection dialog (CZ_SELECTAUTOSPELL).
/// 01ce <skill id>.L
-void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
+static void clif_parse_AutoSpell(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
uint16 skill_id = RFIFOL(fd,2);
sd->state.workinprogress = 0;
@@ -11579,42 +13433,53 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
clif_menuskill_clear(sd);
}
-void clif_parse_UseCard(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_UseCard(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to display item carding/composition list (CZ_REQ_ITEMCOMPOSITION_LIST).
/// 017a <card index>.W
-void clif_parse_UseCard(int fd,struct map_session_data *sd)
+static void clif_parse_UseCard(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
clif->use_card(sd,RFIFOW(fd,2)-2);
}
-void clif_parse_InsertCard(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_InsertCard(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to carding/composing item selection dialog (CZ_REQ_ITEMCOMPOSITION).
/// 017c <card index>.W <equip index>.W
-void clif_parse_InsertCard(int fd,struct map_session_data *sd)
+static void clif_parse_InsertCard(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
pc->insert_card(sd,RFIFOW(fd,2)-2,RFIFOW(fd,4)-2);
}
-void clif_parse_SolveCharName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SolveCharName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request of character's name by char ID.
/// 0193 <char id>.L (CZ_REQNAME_BYGID)
/// 0369 <char id>.L (CZ_REQNAME_BYGID2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_SolveCharName(int fd, struct map_session_data *sd) {
+static void clif_parse_SolveCharName(int fd, struct map_session_data *sd)
+{
int charid;
charid = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
map->reqnickdb(sd, charid);
}
-void clif_parse_ResetChar(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ResetChar(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /resetskill /resetstate (CZ_RESET).
/// Request to reset stats or skills.
/// 0197 <type>.W
/// type:
/// 0 = state
/// 1 = skill
-void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
+static void clif_parse_ResetChar(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
char cmd[15];
if( RFIFOW(fd,2) )
@@ -11625,11 +13490,11 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
atcommand->exec(fd, sd, cmd, true);
}
-void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /lb /nlb (CZ_LOCALBROADCAST).
/// Request to broadcast a message on current map.
/// 019c <packet len>.W <text>.?B
-void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd)
+static void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd)
{
const char commandname[] = "lkami";
char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' + command + ' ' + message + NUL
@@ -11648,21 +13513,21 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd)
atcommand->exec(fd, sd, command, true);
}
-void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from inventory to storage.
/// 00f3 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_BODY_TO_STORE)
/// 0364 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_BODY_TO_STORE2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
+static void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
{
int item_index, item_amount;
- if (pc_istrading(sd))
+ if (pc_istrading(sd) || sd->state.prevend)
return;
item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2;
item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]);
- if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1)
+ if (item_index < 0 || item_index >= sd->status.inventorySize || item_amount < 1)
return;
if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
@@ -11671,13 +13536,16 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
gstorage->add(sd, item_index, item_amount);
}
-void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MoveFromKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from storage to inventory.
/// 00f5 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_STORE_TO_BODY)
/// 0365 <index>.W <amount>.L (CZ_MOVE_ITEM_FROM_STORE_TO_BODY2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
+static void clif_parse_MoveFromKafra(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || sd->state.prevend)
+ return;
+
int item_index, item_amount;
item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1;
@@ -11689,12 +13557,12 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
gstorage->get(sd, item_index, item_amount);
}
-void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from cart to storage (CZ_MOVE_ITEM_FROM_CART_TO_STORE).
/// 0129 <index>.W <amount>.L
-void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
+static void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
{
- if( sd->state.vending )
+ if (pc_istrading(sd) || sd->state.prevend)
return;
if (!pc_iscarton(sd))
return;
@@ -11705,12 +13573,12 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
}
-void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move an item from storage to cart (CZ_MOVE_ITEM_FROM_STORE_TO_CART).
/// 0128 <index>.W <amount>.L
-void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
+static void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
{
- if( sd->state.vending )
+ if (pc_istrading(sd) || sd->state.prevend)
return;
if (!pc_iscarton(sd))
return;
@@ -11721,10 +13589,10 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
}
-void clif_parse_CloseKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_CloseKafra(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to close storage (CZ_CLOSE_STORE).
/// 00f7
-void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
+static void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
{
if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
storage->close(sd);
@@ -11732,6 +13600,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
gstorage->close(sd);
}
+#if 0 // Unused function
/// Displays kafra storage password dialog (ZC_REQ_STORE_PASSWORD).
/// 023a <info>.W
/// info:
@@ -11740,7 +13609,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
/// 8 = too many wrong passwords
/// ? = ignored
/// NOTE: This packet is only available on certain non-kRO clients.
-void clif_storagepassword(struct map_session_data* sd, short info)
+static void clif_storagepassword(struct map_session_data *sd, short info)
{
int fd;
@@ -11751,19 +13620,21 @@ void clif_storagepassword(struct map_session_data* sd, short info)
WFIFOW(fd,2) = info;
WFIFOSET(fd,packet_len(0x23a));
}
+#endif // 0
-void clif_parse_StoragePassword(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_StoragePassword(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to the kafra storage password dialog (CZ_ACK_STORE_PASSWORD).
/// 023b <type>.W <password>.16B <new password>.16B
/// type:
/// 2 = change password
/// 3 = check password
/// NOTE: This packet is only available on certain non-kRO clients.
-void clif_parse_StoragePassword(int fd, struct map_session_data *sd)
+static void clif_parse_StoragePassword(int fd, struct map_session_data *sd)
{
//TODO
}
+#if 0 // Unused function
/// Result of kafra storage password validation (ZC_RESULT_STORE_PASSWORD).
/// 023c <result>.W <error count>.W
/// result:
@@ -11774,7 +13645,7 @@ void clif_parse_StoragePassword(int fd, struct map_session_data *sd)
/// 8 = too many wrong passwords
/// ? = ignored
/// NOTE: This packet is only available on certain non-kRO clients.
-void clif_storagepassword_result(struct map_session_data* sd, short result, short error_count)
+static void clif_storagepassword_result(struct map_session_data *sd, short result, short error_count)
{
int fd;
@@ -11786,33 +13657,40 @@ void clif_storagepassword_result(struct map_session_data* sd, short result, shor
WFIFOW(fd,4) = error_count;
WFIFOSET(fd,packet_len(0x23c));
}
+#endif // 0
-void clif_parse_CreateParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_CreateParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Party creation request
/// 00f9 <party name>.24B (CZ_MAKE_GROUP)
/// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2)
-void clif_parse_CreateParty(int fd, struct map_session_data *sd)
+static void clif_parse_CreateParty(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
char name[NAME_LENGTH];
safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH);
if( map->list[sd->bl.m].flag.partylock ) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
- if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 7 ) {
- clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4);
+ if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 7)) {
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 4, 0);
return;
}
party->create(sd,name,0,0);
}
-void clif_parse_CreateParty2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_CreateParty2(int fd, struct map_session_data *sd)
+static void clif_parse_CreateParty2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_CreateParty2(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
char name[NAME_LENGTH];
int item1 = RFIFOB(fd,26);
int item2 = RFIFOB(fd,27);
@@ -11821,27 +13699,31 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd)
if( map->list[sd->bl.m].flag.partylock ) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
- if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 7 ) {
- clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4);
+ if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 7)) {
+ clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 4, 0);
return;
}
party->create(sd,name,item1,item2);
}
-void clif_parse_PartyInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Party invitation request
/// 00fc <account id>.L (CZ_REQ_JOIN_GROUP)
/// 02c4 <char name>.24B (CZ_PARTY_JOIN_REQ)
-void clif_parse_PartyInvite(int fd, struct map_session_data *sd) {
+static void clif_parse_PartyInvite(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *t_sd;
if(map->list[sd->bl.m].flag.partylock) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
@@ -11855,9 +13737,12 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) {
party->invite(sd, t_sd);
}
-void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
+static void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *t_sd;
char name[NAME_LENGTH];
@@ -11865,11 +13750,11 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
if(map->list[sd->bl.m].flag.partylock) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
- t_sd = map->nick2sd(name);
+ t_sd = map->nick2sd(name, true);
if(t_sd && t_sd->state.noask) { // @noask [LuzZza]
clif->noask_sub(sd, t_sd, 1);
@@ -11879,54 +13764,75 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
party->invite(sd, t_sd);
}
-void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ReplyPartyInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Party invitation reply
/// 00ff <party id>.L <flag>.L (CZ_JOIN_GROUP)
/// 02c7 <party id>.L <flag>.B (CZ_PARTY_JOIN_REQ_ACK)
/// flag:
/// 0 = reject
/// 1 = accept
-void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd)
+static void clif_parse_ReplyPartyInvite(int fd, struct map_session_data *sd)
{
- party->reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6));
+ if (pc_istrading(sd) || pc_isvending(sd)) {
+ party->reply_invite(sd, RFIFOL(fd, 2), 0);
+ return;
+ }
+
+ party->reply_invite(sd, RFIFOL(fd, 2), RFIFOL(fd, 6));
}
-void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
+static void clif_parse_ReplyPartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ReplyPartyInvite2(int fd, struct map_session_data *sd)
{
- party->reply_invite(sd,RFIFOL(fd,2),RFIFOB(fd,6));
+ if (pc_istrading(sd) || pc_isvending(sd)) {
+ party->reply_invite(sd, RFIFOL(fd, 2), 0);
+ return;
+ }
+
+ party->reply_invite(sd, RFIFOL(fd, 2), RFIFOB(fd, 6));
}
-void clif_parse_LeaveParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_LeaveParty(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to leave party (CZ_REQ_LEAVE_GROUP).
/// 0100
-void clif_parse_LeaveParty(int fd, struct map_session_data *sd) {
- if(map->list[sd->bl.m].flag.partylock) {
+static void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ if (map->list[sd->bl.m].flag.partylock) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
party->leave(sd);
}
-void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to expel a party member (CZ_REQ_EXPEL_GROUP_MEMBER).
/// 0103 <account id>.L <char name>.24B
-void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) {
- if(map->list[sd->bl.m].flag.partylock) {
+static void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ if (map->list[sd->bl.m].flag.partylock) {
// Party locked.
- clif->message(fd, msg_fd(fd,227));
+ clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map.
return;
}
- party->removemember(sd, RFIFOL(fd,2), RFIFOP(fd,6));
+ party->removemember(sd, RFIFOL(fd, 2), RFIFOP(fd, 6));
}
-void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change party options.
/// 0102 <exp share rule>.L (CZ_CHANGE_GROUPEXPOPTION)
/// 07d7 <exp share rule>.L <item pickup rule>.B <item share rule>.B (CZ_GROUPINFO_CHANGE_V2)
-void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd)
+static void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
struct party_data *p;
int i;
@@ -11952,54 +13858,51 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd)
#endif
}
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
-/// 0108 <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
+ *
+ * @code
+ * 0108 <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+static void clif_parse_PartyMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
-
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- if( !pc->can_talk(sd) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- party->send_message(sd, text, textlen);
+ party->send_message(sd, message);
}
-void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyChangeLeader(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Changes Party Leader (CZ_CHANGE_GROUP_MASTER).
/// 07da <account id>.L
-void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) {
+static void clif_parse_PartyChangeLeader(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
party->changeleader(sd, map->id2sd(RFIFOL(fd,2)));
}
-void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Party Booking in KRO [Spiria]
///
/// 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)
+static void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data *sd)
{
#ifndef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
short level = RFIFOW(fd,2);
short mapid = RFIFOW(fd,4);
short job[PARTY_BOOKING_JOBS];
@@ -12020,7 +13923,7 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
/// 0 = success
/// 1 = failure
/// 2 = already registered
-void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag)
+static void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag)
{
#ifndef PARTY_RECRUIT
int fd;
@@ -12036,12 +13939,15 @@ void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag)
#endif
}
-void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to search for party booking advertisement (CZ_PARTY_BOOKING_REQ_SEARCH).
/// 0804 <level>.W <map id>.W <job>.W <last index>.L <result count>.W
-void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
+static void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data *sd)
{
#ifndef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
short level = RFIFOW(fd,2);
short mapid = RFIFOW(fd,4);
short job = RFIFOW(fd,6);
@@ -12059,7 +13965,7 @@ void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
/// more results:
/// 0 = no
/// 1 = yes
-void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result)
+static void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info **results, int count, bool more_result)
{
#ifndef PARTY_RECRUIT
int i, j;
@@ -12087,13 +13993,16 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results,
#endif
}
-void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete own party booking advertisement (CZ_PARTY_BOOKING_REQ_DELETE).
/// 0806
-void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd)
+static void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data *sd)
{
#ifndef PARTY_RECRUIT
- if(party->booking_delete(sd))
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ if (party->booking_delete(sd))
clif->PartyBookingDeleteAck(sd, 0);
#else
return;
@@ -12107,7 +14016,7 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd)
/// 1 = success (auto-removed expired ad)
/// 2 = failure
/// 3 = nothing registered
-void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag)
+static void clif_PartyBookingDeleteAck(struct map_session_data *sd, int flag)
{
#ifndef PARTY_RECRUIT
int fd;
@@ -12123,17 +14032,19 @@ void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag)
#endif
}
-void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to update party booking advertisement (CZ_PARTY_BOOKING_REQ_UPDATE).
/// 0808 { <job>.W }*6
-void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd)
+static void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data *sd)
{
#ifndef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
short job[PARTY_BOOKING_JOBS];
- int i;
- for(i=0; i<PARTY_BOOKING_JOBS; i++)
- job[i] = RFIFOW(fd,2+i*2);
+ for (int i = 0; i < PARTY_BOOKING_JOBS; i++)
+ job[i] = RFIFOW(fd, 2 + i * 2);
party->booking_update(sd, job);
#else
@@ -12143,11 +14054,14 @@ void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd)
/// 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)
+static void clif_PartyBookingInsertNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad)
{
#ifndef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
int i;
- uint8 buf[38+PARTY_BOOKING_JOBS*2];
+ uint8 buf[38 + PARTY_BOOKING_JOBS * 2];
nullpo_retv(sd);
if(pb_ad == NULL) return;
@@ -12169,7 +14083,7 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo
/// 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)
+static void clif_PartyBookingUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad)
{
#ifndef PARTY_RECRUIT
int i;
@@ -12190,7 +14104,7 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo
/// Notification about deleted party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_DELETE).
/// 080b <index>.L
-void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index)
+static void clif_PartyBookingDeleteNotify(struct map_session_data *sd, int index)
{
#ifndef PARTY_RECRUIT
uint8 buf[6];
@@ -12205,16 +14119,19 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index)
#endif
}
-void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Modified version of Party Booking System for 2012-04-10 or 2012-04-18 (RagexeRE).
/// Code written by mkbu95, Spiria, Yommy and Ind
/// 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)
+static void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
- short level = RFIFOW(fd,2);
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ short level = RFIFOW(fd, 2);
const char *notice = RFIFOP(fd, 4);
party->recruit_register(sd, level, notice);
@@ -12228,7 +14145,7 @@ void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd)
/// more results:
/// 0 = no
/// 1 = yes
-void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result)
+static void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info **results, int count, bool more_result)
{
#ifdef PARTY_RECRUIT
int i;
@@ -12263,7 +14180,7 @@ void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results,
/// 0 = success
/// 1 = failure
/// 2 = already registered
-void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag)
+static void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag)
{
#ifdef PARTY_RECRUIT
int fd;
@@ -12279,12 +14196,15 @@ void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag)
#endif
}
-void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to search for party booking advertisement (CZ_PARTY_RECRUIT_REQ_SEARCH).
/// 08e7 <level>.W <map id>.W <last index>.L <result count>.W
-void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd)
+static void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
short level = RFIFOW(fd, 2);
short mapid = RFIFOW(fd, 4);
unsigned long lastindex = RFIFOL(fd, 6);
@@ -12296,13 +14216,16 @@ void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd)
#endif
}
-void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete own party booking advertisement (CZ_PARTY_RECRUIT_REQ_DELETE).
/// 08e9
-void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd)
+static void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
- if(party->booking_delete(sd))
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ if (party->booking_delete(sd))
clif->PartyRecruitDeleteAck(sd, 0);
#else
return;
@@ -12316,7 +14239,7 @@ void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd)
/// 1 = success (auto-removed expired ad)
/// 2 = failure
/// 3 = nothing registered
-void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag)
+static void clif_PartyRecruitDeleteAck(struct map_session_data *sd, int flag)
{
#ifdef PARTY_RECRUIT
int fd;
@@ -12332,12 +14255,15 @@ void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag)
#endif
}
-void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to update party booking advertisement (CZ_PARTY_RECRUIT_REQ_UPDATE).
/// 08eb <notice>.37B
-void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd)
+static void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
const char *notice = RFIFOP(fd, 2);
party->recruit_update(sd, notice);
@@ -12348,7 +14274,7 @@ void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd)
/// 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)
+static void clif_PartyRecruitInsertNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+6+24+4+37+1];
@@ -12371,7 +14297,7 @@ void clif_PartyRecruitInsertNotify(struct map_session_data* sd, struct party_boo
/// 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)
+static void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+37+1];
@@ -12390,7 +14316,7 @@ void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_boo
/// Notification about deleted party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_DELETE).
/// 08ee <index>.L
-void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index)
+static void clif_PartyRecruitDeleteNotify(struct map_session_data *sd, int index)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+1];
@@ -12405,12 +14331,15 @@ void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index)
#endif
}
-void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add to filtering list (PARTY_RECRUIT_ADD_FILTERLINGLIST).
/// 08ef <index>.L
-void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
int index = RFIFOL(fd, 2);
clif->PartyBookingAddFilteringList(index, sd);
@@ -12419,12 +14348,15 @@ void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd
#endif
}
-void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to remove from filtering list (PARTY_RECRUIT_SUB_FILTERLINGLIST).
/// 08f0 <GID>.L
-void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
int gid = RFIFOL(fd, 2);
clif->PartyBookingSubFilteringList(gid, sd);
@@ -12433,12 +14365,15 @@ void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd
#endif
}
-void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to recruit volunteer (PARTY_RECRUIT_REQ_VOLUNTEER).
/// 08f1 <index>.L
-void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
int index = RFIFOL(fd, 2);
clif->PartyBookingVolunteerInfo(index, sd);
@@ -12449,7 +14384,7 @@ void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd)
/// Request volunteer information (PARTY_RECRUIT_VOLUNTEER_INFO).
/// 08f2 <AID>.L <job>.L <level>.W <char name>.24B
-void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd)
+static void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+4+4+2+24+1];
@@ -12457,7 +14392,7 @@ void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd)
nullpo_retv(sd);
WBUFW(buf, 0) = 0x8f2;
WBUFL(buf, 2) = sd->status.account_id;
- WBUFL(buf, 6) = sd->status.class_;
+ WBUFL(buf, 6) = sd->status.class;
WBUFW(buf, 10) = sd->status.base_level;
memcpy(WBUFP(buf, 12), sd->status.name, NAME_LENGTH);
@@ -12469,31 +14404,31 @@ void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd)
#if 0 //Disabled for now. Needs more info.
/// 08f3 <packet type>.W <cost>.L
-void clif_PartyBookingPersonalSetting(int fd, struct map_session_data *sd)
+static void clif_PartyBookingPersonalSetting(int fd, struct map_session_data *sd)
{
}
-void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08f4 <target GID>.L
-void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingShowEquipment(int fd, struct map_session_data *sd)
{
}
-void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08f5 <packet len>.W
-void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingReqRecall(int fd, struct map_session_data *sd)
{
}
-void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08f6 <money>.L <map name>.16B
-void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd)
+static void clif_PartyBookingRecallCost(int fd, struct map_session_data *sd)
{
}
-void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08f7 <result>.B
-void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd)
{
}
@@ -12504,17 +14439,20 @@ void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd)
/// REASON_REFUSE = 0x2
/// REASON_NOT_PARTY_MEMBER = 0x3
/// REASON_ETC = 0x4
-void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd)
+static void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd)
{
}
#endif //if 0
-void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08f9 <refuse AID>.L
-void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
unsigned int aid = RFIFOL(fd, 2);
clif->PartyBookingRefuseVolunteer(aid, sd);
@@ -12523,9 +14461,9 @@ void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd)
#endif
}
-void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08fa <index>.L
-void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd)
+static void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6];
@@ -12539,11 +14477,14 @@ void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data
#endif
}
-void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// 08fb <index>.L
-void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd)
+static void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
int index = RFIFOL(fd, 2);
clif->PartyBookingCancelVolunteer(index, sd);
@@ -12553,7 +14494,7 @@ void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd)
}
/// 0909 <index>.L
-void clif_PartyBookingCancelVolunteer(int index, struct map_session_data *sd)
+static void clif_PartyBookingCancelVolunteer(int index, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+1];
@@ -12569,7 +14510,7 @@ void clif_PartyBookingCancelVolunteer(int index, struct map_session_data *sd)
}
/// 090b <gid>.L <char name>.24B
-void clif_PartyBookingAddFilteringList(int index, struct map_session_data *sd)
+static void clif_PartyBookingAddFilteringList(int index, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+24+1];
@@ -12586,7 +14527,7 @@ void clif_PartyBookingAddFilteringList(int index, struct map_session_data *sd)
}
/// 090c <gid>.L <char name>.24B
-void clif_PartyBookingSubFilteringList(int gid, struct map_session_data *sd)
+static void clif_PartyBookingSubFilteringList(int gid, struct map_session_data *sd)
{
#ifdef PARTY_RECRUIT
unsigned char buf[2+6+24+1];
@@ -12604,43 +14545,58 @@ void clif_PartyBookingSubFilteringList(int gid, struct map_session_data *sd)
#if 0
/// 091c <aid>.L
-void clif_PartyBookingCancelVolunteerToPM(struct map_session_data *sd)
+static void clif_PartyBookingCancelVolunteerToPM(struct map_session_data *sd)
{
}
/// 0971 <pm_aid>.L
-void clif_PartyBookingRefuseVolunteerToPM(struct map_session_data *sd)
+static void clif_PartyBookingRefuseVolunteerToPM(struct map_session_data *sd)
{
}
#endif //if 0
-void clif_parse_CloseVending(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_CloseVending(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to close own vending (CZ_REQ_CLOSESTORE).
/// 012e
-void clif_parse_CloseVending(int fd, struct map_session_data* sd)
+static void clif_parse_CloseVending(int fd, struct map_session_data *sd)
{
+ if (sd->npc_id || sd->state.buyingstore || sd->state.trading)
+ return;
+
vending->close(sd);
}
-void clif_parse_VendingListReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_VendingListReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to open a vending shop (CZ_REQ_BUY_FROMMC).
/// 0130 <account id>.L
-void clif_parse_VendingListReq(int fd, struct map_session_data* sd)
+static void clif_parse_VendingListReq(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isdead(sd))
+ return;
+
if( sd->npc_id ) {// using an NPC
return;
}
vending->list(sd,RFIFOL(fd,2));
}
-void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PurchaseReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC).
/// 0134 <packet len>.W <account id>.L { <amount>.W <index>.W }*
-void clif_parse_PurchaseReq(int fd, struct map_session_data* sd)
+static void clif_parse_PurchaseReq(int fd, struct map_session_data *sd)
{
- int len = (int)RFIFOW(fd,2) - 8;
- int id = RFIFOL(fd,4);
- const uint8 *data = RFIFOP(fd,8);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = (int)RFIFOW(fd, 2) - 8;
+ int id;
+ const uint8 *data;
+
+ if (len < 1)
+ return;
+
+ id = RFIFOL(fd, 4);
+ data = RFIFOP(fd, 8);
vending->purchase(sd, id, sd->vended_id, data, len/4);
@@ -12648,15 +14604,24 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd)
sd->vended_id = 0;
}
-void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PurchaseReq2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC2).
/// 0801 <packet len>.W <account id>.L <unique id>.L { <amount>.W <index>.W }*
-void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd)
+static void clif_parse_PurchaseReq2(int fd, struct map_session_data *sd)
{
- int len = (int)RFIFOW(fd,2) - 12;
- int aid = RFIFOL(fd,4);
- int uid = RFIFOL(fd,8);
- const uint8 *data = RFIFOP(fd,12);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = (int)RFIFOW(fd, 2) - 12;
+ int aid;
+ int uid;
+ const uint8 *data;
+
+ if (len < 1)
+ return;
+ aid = RFIFOL(fd, 4);
+ uid = RFIFOL(fd, 8);
+ data = RFIFOP(fd, 12);
vending->purchase(sd, aid, uid, data, len/4);
@@ -12664,26 +14629,34 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd)
sd->vended_id = 0;
}
-void clif_parse_OpenVending(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_OpenVending(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Confirm or cancel the shop preparation window.
/// 012f <packet len>.W <shop name>.80B { <index>.W <amount>.W <price>.L }* (CZ_REQ_OPENSTORE)
/// 01b2 <packet len>.W <shop name>.80B <result>.B { <index>.W <amount>.W <price>.L }* (CZ_REQ_OPENSTORE2)
/// result:
/// 0 = canceled
/// 1 = open
-void clif_parse_OpenVending(int fd, struct map_session_data* sd) {
- short len = (short)RFIFOW(fd,2) - 85;
- const char *message = RFIFOP(fd,4);
- bool flag = (RFIFOB(fd,84) != 0) ? true : false;
- const uint8 *data = RFIFOP(fd,85);
+static void clif_parse_OpenVending(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isdead(sd) || sd->state.vending || sd->state.buyingstore)
+ return;
- if( !flag )
+ int len = (int)RFIFOW(fd, 2) - 85;
+
+ if (len < 0)
+ return;
+
+ const char *message = RFIFOP(fd, 4);
+ bool flag = (RFIFOB(fd, 84) != 0) ? true : false;
+ const uint8 *data = RFIFOP(fd, 85);
+
+ if (!flag)
sd->state.prevend = sd->state.workinprogress = 0;
- if(pc_ismuted(&sd->sc, MANNER_NOROOM))
+ if (pc_ismuted(&sd->sc, MANNER_NOROOM))
return;
- if( map->list[sd->bl.m].flag.novending ) {
- clif->message (sd->fd, msg_sd(sd,276)); // "You can't open a shop on this map"
+ if (map->list[sd->bl.m].flag.novending) {
+ clif->message (sd->fd, msg_sd(sd, 276)); // "You can't open a shop on this map"
return;
}
if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) {
@@ -12697,32 +14670,34 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) {
vending->open(sd, message, data, len/8);
}
-void clif_parse_CreateGuild(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_CreateGuild(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Guild creation request (CZ_REQ_MAKE_GUILD).
/// 0165 <char id>.L <guild name>.24B
-void clif_parse_CreateGuild(int fd,struct map_session_data *sd)
+static void clif_parse_CreateGuild(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
char name[NAME_LENGTH];
safestrncpy(name, RFIFOP(fd,6), NAME_LENGTH);
- if(map->list[sd->bl.m].flag.guildlock) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ if (map->list[sd->bl.m].flag.guildlock) {
+ clif->message(fd, msg_fd(fd, 228)); // Guild modification is disabled in this map.
return;
}
guild->create(sd, name);
}
-void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request for guild window interface permissions (CZ_REQ_GUILD_MENUINTERFACE).
/// 014d
-void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd)
+static void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd)
{
clif->guild_masterormember(sd);
}
-void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request for guild window information (CZ_REQ_GUILD_MENU).
/// 014f <type>.L
/// type:
@@ -12733,7 +14708,7 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) __attribut
/// 4 = expulsion list
/// 5 = unknown (GM_ALLGUILDLIST)
/// 6 = notice
-void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
+static void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
{
if( !sd->status.guild_id && !sd->bg_id )
return;
@@ -12742,6 +14717,7 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
case 0: // Basic Information Guild, hostile alliance information
clif->guild_basicinfo(sd);
clif->guild_allianceinfo(sd);
+ clif->guild_castlelist(sd);
break;
case 1: // Members list, list job title
clif->guild_positionnamelist(sd);
@@ -12763,41 +14739,60 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
}
}
-void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to update guild positions (CZ_REG_CHANGE_GUILD_POSITIONINFO).
/// 0161 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L <name>.24B }*
-void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd)
+static void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int i;
+ int count = (RFIFOW(fd, 2) - 4) / 40;
- if(!sd->state.gmaster_flag)
+ if (!sd->state.gmaster_flag)
return;
- for(i = 4; i < RFIFOW(fd,2); i += 40 ){
- guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), RFIFOP(fd,i+16));
+ for (i = 0; i < count; i ++ ) {
+ int idx = i * 40 + 4;
+ guild->change_position(sd->status.guild_id, RFIFOL(fd, idx), RFIFOL(fd, idx + 4), RFIFOL(fd, idx + 12), RFIFOP(fd, idx + 16));
}
}
-void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to update the position of guild members (CZ_REQ_CHANGE_MEMBERPOS).
/// 0155 <packet len>.W { <account id>.L <char id>.L <position id>.L }*
-void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd)
+static void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int i;
+ int len = RFIFOW(fd, 2);
+ int count = (len - 4) / 12;
if(!sd->state.gmaster_flag)
return;
- for(i=4;i<RFIFOW(fd,2);i+=12){
- guild->change_memberposition(sd->status.guild_id,
- RFIFOL(fd,i),RFIFOL(fd,i+4),RFIFOL(fd,i+8));
+ // Guild leadership change
+ if (len == 16 && RFIFOL(fd, 12) == 0) {
+ guild->gm_change(sd->status.guild_id, RFIFOL(fd, 8));
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ int idx = i * 12 + 4;
+ int position = RFIFOL(fd, idx + 8);
+ if (position > 0 && position < MAX_GUILDPOSITION) {
+ guild->change_memberposition(sd->status.guild_id, RFIFOL(fd, idx), RFIFOL(fd, idx + 4), position);
+ }
}
}
-void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildRequestEmblem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request for guild emblem data (CZ_REQ_GUILD_EMBLEM_IMG).
/// 0151 <guild id>.L
-void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd)
+static void clif_parse_GuildRequestEmblem(int fd, struct map_session_data *sd)
{
struct guild* g;
int guild_id = RFIFOL(fd,2);
@@ -12807,7 +14802,8 @@ void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd)
}
/// Validates data of a guild emblem (compressed bitmap)
-bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
+static bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len)
+{
enum e_bitmapconst {
RGBTRIPLE_SIZE = 3, // sizeof(RGBTRIPLE)
RGBQUAD_SIZE = 4, // sizeof(RGBQUAD)
@@ -12823,7 +14819,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
//uint8 b;
//uint8 g;
//uint8 r;
- unsigned int rgb:24;
+ uint32 rgb:24;
} __attribute__((packed));
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
@@ -12833,7 +14829,8 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
int header = 0, bitmap = 0, offbits = 0, palettesize = 0;
nullpo_retr(false, emblem);
- if( decode_zip(buf, &buf_len, emblem, emblem_len) != 0 || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE
+ if (grfio->decode_zip(buf, &buf_len, emblem, emblem_len) != 0
+ || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE
|| RBUFW(buf,0) != 0x4d42 // BITMAPFILEHEADER.bfType (signature)
|| RBUFL(buf,2) != buf_len // BITMAPFILEHEADER.bfSize (file size)
|| RBUFL(buf,14) != BITMAPINFOHEADER_SIZE // BITMAPINFOHEADER.biSize (other headers are not supported)
@@ -12930,15 +14927,18 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
return true;
}
-void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildChangeEmblem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to update the guild emblem (CZ_REGISTER_GUILD_EMBLEM_IMG).
/// 0153 <packet len>.W <emblem data>.?B
-void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd)
+static void clif_parse_GuildChangeEmblem(int fd, struct map_session_data *sd)
{
- unsigned int emblem_len = RFIFOW(fd,2)-4;
- const uint8* emblem = RFIFOP(fd,4);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- if( !emblem_len || !sd->state.gmaster_flag )
+ unsigned int emblem_len = RFIFOW(fd, 2) - 4;
+ const uint8* emblem = RFIFOP(fd, 4);
+
+ if (!emblem_len || !sd->state.gmaster_flag)
return;
if (!clif->validate_emblem(emblem, emblem_len)) {
@@ -12950,12 +14950,15 @@ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd)
guild->change_emblem(sd, emblem_len, (const char*)emblem);
}
-void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildChangeNotice(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Guild notice update request (CZ_GUILD_NOTICE).
/// 016e <guild id>.L <msg1>.60B <msg2>.120B
-void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd)
+static void clif_parse_GuildChangeNotice(int fd, struct map_session_data *sd)
{
- int guild_id = RFIFOL(fd,2);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int guild_id = RFIFOL(fd, 2);
char *msg1 = NULL, *msg2 = NULL;
if (!sd->state.gmaster_flag)
@@ -12975,15 +14978,15 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd)
}
// Helper function for guild invite functions
-bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) {
+static bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd)
+{
if ( t_sd == NULL )// not online or does not exist
return false;
nullpo_retr(false, sd);
nullpo_retr(false, t_sd);
if ( map->list[sd->bl.m].flag.guildlock ) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return false;
}
@@ -12992,121 +14995,130 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi
return false;
}
+ // Players in a clan can't join a guild
+ if (t_sd->clan != NULL) {
+ clif->message(fd, msg_fd(fd, 140)); // You can't join in a clan if you're in a guild.
+ return false;
+ }
+
guild->invite(sd,t_sd);
return true;
}
-void clif_parse_GuildInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Guild invite request (CZ_REQ_JOIN_GUILD).
/// 0168 <account id>.L <inviter account id>.L <inviter char id>.L
-void clif_parse_GuildInvite(int fd,struct map_session_data *sd) {
+static void clif_parse_GuildInvite(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *t_sd = map->id2sd(RFIFOL(fd,2));
if (!clif_sub_guild_invite(fd, sd, t_sd))
return;
}
-void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2).
/// 0916 <char name>.24B
-void clif_parse_GuildInvite2(int fd, struct map_session_data *sd)
+static void clif_parse_GuildInvite2(int fd, struct map_session_data *sd)
{
char nick[NAME_LENGTH];
struct map_session_data *t_sd = NULL;
safestrncpy(nick, RFIFOP(fd, 2), NAME_LENGTH);
- t_sd = map->nick2sd(nick);
+ t_sd = map->nick2sd(nick, true);
clif_sub_guild_invite(fd, sd, t_sd);
}
-void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildReplyInvite(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to guild invitation (CZ_JOIN_GUILD).
/// 016b <guild id>.L <answer>.L
/// answer:
/// 0 = refuse
/// 1 = accept
-void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd)
+static void clif_parse_GuildReplyInvite(int fd, struct map_session_data *sd)
{
- guild->reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6));
+ guild->reply_invite(sd, RFIFOL(fd, 2), RFIFOL(fd, 6));
}
-void clif_parse_GuildLeave(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildLeave(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to leave guild (CZ_REQ_LEAVE_GUILD).
/// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B
-void clif_parse_GuildLeave(int fd,struct map_session_data *sd) {
- if(map->list[sd->bl.m].flag.guildlock) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+static void clif_parse_GuildLeave(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (map->list[sd->bl.m].flag.guildlock) {
+ clif->message(fd, msg_fd(fd, 228)); // Guild modification is disabled in this map.
return;
}
- if( sd->bg_id ) {
- clif->message(fd, msg_fd(fd,870)); //"You can't leave battleground guilds."
+ if (sd->bg_id) {
+ clif->message(fd, msg_fd(fd, 870)); //"You can't leave battleground guilds."
return;
}
- guild->leave(sd,RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14));
+ guild->leave(sd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10), RFIFOP(fd, 14));
}
-void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildExpulsion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to expel a member of a guild (CZ_REQ_BAN_GUILD).
/// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B
-void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) {
- if( map->list[sd->bl.m].flag.guildlock || sd->bg_id ) {
- // Guild locked.
- clif->message(fd, msg_fd(fd,228));
+static void clif_parse_GuildExpulsion(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (map->list[sd->bl.m].flag.guildlock || sd->bg_id) {
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return;
}
- guild->expulsion(sd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14));
+ guild->expulsion(sd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10), RFIFOP(fd, 14));
}
-void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes guild messages (CZ_GUILD_CHAT).
-/// 017e <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes guild messages (CZ_GUILD_CHAT).
+ *
+ * @code
+ * 017e <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+static void clif_parse_GuildMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- if( atcommand->exec(fd, sd, message, true) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->bg_id )
- bg->send_message(sd, text, textlen);
+ if (sd->bg_id)
+ bg->send_message(sd, message);
else
- guild->send_message(sd, text, textlen);
+ guild->send_message(sd, message);
}
-void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Guild alliance request (CZ_REQ_ALLY_GUILD).
/// 0170 <account id>.L <inviter account id>.L <inviter char id>.L
-void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) {
+static void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *t_sd;
if(!sd->state.gmaster_flag)
return;
if(map->list[sd->bl.m].flag.guildlock) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return;
}
@@ -13121,47 +15133,53 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) {
guild->reqalliance(sd,t_sd);
}
-void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to a guild alliance request (CZ_ALLY_GUILD).
/// 0172 <inviter account id>.L <answer>.L
/// answer:
/// 0 = refuse
/// 1 = accept
-void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd)
+static void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd)
{
guild->reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6));
}
-void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete a guild alliance or opposition (CZ_REQ_DELETE_RELATED_GUILD).
/// 0183 <opponent guild id>.L <relation>.L
/// relation:
/// 0 = Ally
/// 1 = Enemy
-void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) {
+static void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
if(!sd->state.gmaster_flag)
return;
if(map->list[sd->bl.m].flag.guildlock) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return;
}
guild->delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6));
}
-void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to set a guild as opposition (CZ_REQ_HOSTILE_GUILD).
/// 0180 <account id>.L
-void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) {
+static void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *t_sd;
if(!sd->state.gmaster_flag)
return;
if(map->list[sd->bl.m].flag.guildlock) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return;
}
@@ -13176,25 +15194,30 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) {
guild->opposition(sd,t_sd);
}
-void clif_parse_GuildBreak(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GuildBreak(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete own guild (CZ_REQ_DISORGANIZE_GUILD).
/// 015d <key>.40B
/// key:
/// now guild name; might have been (intended) email, since the
/// field name and size is same as the one in CH_DELETE_CHAR.
-void clif_parse_GuildBreak(int fd, struct map_session_data *sd) {
+static void clif_parse_GuildBreak(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ char key[40];
if( map->list[sd->bl.m].flag.guildlock ) {
- //Guild locked.
- clif->message(fd, msg_fd(fd,228));
+ clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map.
return;
}
- guild->dobreak(sd, RFIFOP(fd,2));
+ safestrncpy(key, RFIFOP(fd, 2), 40);
+ guild->dobreak(sd, key);
}
/// Pet
///
-void clif_parse_PetMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PetMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke a pet menu action (CZ_COMMAND_PET).
/// 01a1 <type>.B
/// type:
@@ -13203,32 +15226,41 @@ void clif_parse_PetMenu(int fd, struct map_session_data *sd) __attribute__((nonn
/// 2 = performance
/// 3 = return to egg
/// 4 = unequip accessory
-void clif_parse_PetMenu(int fd, struct map_session_data *sd)
+static void clif_parse_PetMenu(int fd, struct map_session_data *sd)
{
- pet->menu(sd,RFIFOB(fd,2));
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ pet->menu(sd, RFIFOB(fd, 2));
}
-void clif_parse_CatchPet(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_CatchPet(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Attempt to tame a monster (CZ_TRYCAPTURE_MONSTER).
/// 019f <id>.L
-void clif_parse_CatchPet(int fd, struct map_session_data *sd)
+static void clif_parse_CatchPet(int fd, struct map_session_data *sd)
{
- pet->catch_process2(sd,RFIFOL(fd,2));
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ pet->catch_process2(sd, RFIFOL(fd, 2));
}
-void clif_parse_SelectEgg(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SelectEgg(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to pet incubator egg selection dialog (CZ_SELECT_PETEGG).
/// 01a7 <index>.W
-void clif_parse_SelectEgg(int fd, struct map_session_data *sd)
+static void clif_parse_SelectEgg(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) {
return;
}
- pet->select_egg(sd,RFIFOW(fd,2)-2);
+ pet->select_egg(sd, RFIFOW(fd, 2) - 2);
clif_menuskill_clear(sd);
}
-void clif_parse_SendEmotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SendEmotion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to display pet's emotion/talk (CZ_PET_ACT).
/// 01a9 <data>.L
/// data:
@@ -13253,26 +15285,152 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd) __attribute__((
/// 2 = satisfied (noting)
/// 3 = stuffed (full)
/// 4 = full (so_full)
-void clif_parse_SendEmotion(int fd, struct map_session_data *sd)
+static void clif_parse_SendEmotion(int fd, struct map_session_data *sd)
{
if(sd->pd)
clif->pet_emotion(sd->pd,RFIFOL(fd,2));
}
-void clif_parse_ChangePetName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ChangePetName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change pet's name (CZ_RENAME_PET).
/// 01a5 <name>.24B
-void clif_parse_ChangePetName(int fd, struct map_session_data *sd)
+static void clif_parse_ChangePetName(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
pet->change_name(sd, RFIFOP(fd,2));
}
-void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/**
+ * Request to evolve the pet. (CZ_PET_EVOLUTION)
+ *
+ * @code
+ * 09fb <Length>.W <EvolvedPetEggID>.W {<index>.W <amount>.W}*items
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ *
+ **/
+static void clif_parse_pet_evolution(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_pet_evolution(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading != 0 || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (sd->pd == NULL || sd->status.pet_id == 0) { // No pet.
+ clif->petEvolutionResult(fd, PET_EVOL_NO_CALLPET);
+ return;
+ }
+
+ int inv_index;
+
+ ARR_FIND(0, sd->status.inventorySize, inv_index, sd->status.inventory[inv_index].card[0] == CARD0_PET
+ && sd->status.pet_id == MakeDWord(sd->status.inventory[inv_index].card[1],
+ sd->status.inventory[inv_index].card[2]));
+
+ if (inv_index == sd->status.inventorySize) { // No pet egg.
+ clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG);
+ return;
+ }
+
+ if (sd->pd->pet.intimate < PET_INTIMACY_LOYAL) { // Pet isn't loyal.
+ clif->petEvolutionResult(fd, PET_EVOL_RG_FAMILIAR);
+ return;
+ }
+
+ int pet_index;
+
+ ARR_FIND(0, MAX_PET_DB, pet_index, pet->db[pet_index].class_ == sd->pd->pet.class_);
+
+ if (pet_index == MAX_PET_DB) {
+ clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); // Which error?
+ return;
+ }
+
+ const struct PACKET_CZ_PET_EVOLUTION *p = RP2PTR(fd);
+
+ Assert_retv(p->PacketLength >= (uint16)sizeof(struct PACKET_CZ_PET_EVOLUTION));
+
+ // Client side validation is not done as it is insecure.
+ for (int i = 0; i < VECTOR_LENGTH(pet->db[pet_index].evolve_data); i++) {
+ struct pet_evolve_data *ped = &VECTOR_INDEX(pet->db[pet_index].evolve_data, i);
+
+ if (ped->petEggId == p->EvolvedPetEggID) {
+ if (VECTOR_LENGTH(ped->items) == 0) {
+ clif->petEvolutionResult(fd, PET_EVOL_NO_RECIPE);
+ return;
+ }
+
+ for (int j = 0; j < VECTOR_LENGTH(ped->items); j++) {
+ struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j);
+ int n = pc->search_inventory(sd, list->id);
+
+ if (n == INDEX_NOT_FOUND) {
+ clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL);
+ return;
+ }
+ }
+
+ for (int j = 0; j < VECTOR_LENGTH(ped->items); j++) {
+ struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j);
+ int n = pc->search_inventory(sd, list->id);
+
+ if (pc->delitem(sd, n, list->amount, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) {
+ clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL);
+ return;
+ }
+ }
+
+ pet->return_egg(sd, sd->pd); // Return pet to egg.
+
+ if (pc->delitem(sd, inv_index, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) {
+ clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG);
+ return;
+ }
+
+ int pet_id = pet->search_petDB_index(ped->petEggId, PET_EGG);
+
+ if (pet_id >= 0) {
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID,
+ 0, (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1, pet->db[pet_id].jname);
+ clif->petEvolutionResult(fd, PET_EVOL_SUCCESS);
+ } else {
+ clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN);
+ }
+
+ return;
+ }
+ }
+
+ clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN);
+}
+
+/**
+ * Result of Pet Evolution (ZC_PET_EVOLUTION_RESULT)
+ * 0x9fc <Result>.L
+ */
+static void clif_pet_evolution_result(int fd, enum pet_evolution_result result)
+{
+#if PACKETVER >= 20140122
+ WFIFOHEAD(fd, packet_len(0x9fc));
+ WFIFOW(fd, 0) = 0x9fc;
+ WFIFOL(fd, 2) = result;
+ WFIFOSET(fd, packet_len(0x9fc));
+#endif
+}
+
+static void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /kill (CZ_DISCONNECT_CHARACTER).
/// Request to disconnect a character.
/// 00cc <account id>.L
/// NOTE: Also sent when using GM right click menu "(name) force to quit"
-void clif_parse_GMKick(int fd, struct map_session_data *sd) {
+static void clif_parse_GMKick(int fd, struct map_session_data *sd)
+{
struct block_list *target;
int tid;
@@ -13315,8 +15473,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) {
clif->GM_kickack(sd, 0);
return;
}
- npc->unload_duplicates(nd);
- npc->unload(nd,true);
+ npc->unload_duplicates(nd, true);
+ npc->unload(nd, true, true);
npc->read_event_script();
}
break;
@@ -13326,17 +15484,18 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) {
}
}
-void clif_parse_GMKickAll(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_GMKickAll(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /killall (CZ_DISCONNECT_ALL_CHARACTER).
/// Request to disconnect all characters.
/// 00ce
-void clif_parse_GMKickAll(int fd, struct map_session_data* sd) {
+static void clif_parse_GMKickAll(int fd, struct map_session_data *sd)
+{
char cmd[15];
sprintf(cmd,"%ckickall",atcommand->at_symbol);
atcommand->exec(fd, sd, cmd, true);
}
-void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /remove (CZ_REMOVE_AID).
/// Request to warp to a character with given login ID.
/// 01ba <account name>.24B
@@ -13344,11 +15503,11 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonn
/// /shift (CZ_SHIFT).
/// Request to warp to a character with given name.
/// 01bb <char name>.24B
-void clif_parse_GMShift(int fd, struct map_session_data *sd)
+static void clif_parse_GMShift(int fd, struct map_session_data *sd)
{
// FIXME: remove is supposed to receive account name for clients prior 20100803RE
char player_name[NAME_LENGTH];
- char command[NAME_LENGTH+8];
+ char command[NAME_LENGTH + 20];
safestrncpy(player_name, RFIFOP(fd,2), NAME_LENGTH);
@@ -13356,23 +15515,24 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd)
atcommand->exec(fd, sd, command, true);
}
-void clif_parse_GMRemove2(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_GMRemove2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /remove (CZ_REMOVE_AID_SSO).
/// Request to warp to a character with given account ID.
/// 0843 <account id>.L
-void clif_parse_GMRemove2(int fd, struct map_session_data* sd) {
+static void clif_parse_GMRemove2(int fd, struct map_session_data *sd)
+{
int account_id;
struct map_session_data* pl_sd;
account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
if( (pl_sd = map->id2sd(account_id)) != NULL ) {
- char command[NAME_LENGTH+8];
+ char command[NAME_LENGTH + 20];
sprintf(command, "%cjumpto %s", atcommand->at_symbol, pl_sd->status.name);
atcommand->exec(fd, sd, command, true);
}
}
-void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /recall (CZ_RECALL).
/// Request to summon a player with given login ID to own position.
/// 01bc <account name>.24B
@@ -13380,7 +15540,7 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((non
/// /summon (CZ_RECALL_GID).
/// Request to summon a player with given name to own position.
/// 01bd <char name>.24B
-void clif_parse_GMRecall(int fd, struct map_session_data *sd)
+static void clif_parse_GMRecall(int fd, struct map_session_data *sd)
{
// FIXME: recall is supposed to receive account name for clients prior 20100803RE
char player_name[NAME_LENGTH];
@@ -13392,23 +15552,24 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd)
atcommand->exec(fd, sd, command, true);
}
-void clif_parse_GMRecall2(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_GMRecall2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /recall (CZ_RECALL_SSO).
/// Request to summon a player with given account ID to own position.
/// 0842 <account id>.L
-void clif_parse_GMRecall2(int fd, struct map_session_data* sd) {
+static void clif_parse_GMRecall2(int fd, struct map_session_data *sd)
+{
int account_id;
struct map_session_data* pl_sd;
account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
if( (pl_sd = map->id2sd(account_id)) != NULL ) {
- char command[NAME_LENGTH+8];
+ char command[NAME_LENGTH + 20];
sprintf(command, "%crecall %s", atcommand->at_symbol, pl_sd->status.name);
atcommand->exec(fd, sd, command, true);
}
}
-void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /item /monster (CZ_ITEM_CREATE).
/// Request to execute GM commands.
/// usage:
@@ -13422,7 +15583,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute
/// /item agitinvest - reset current global agit investments.(not yet implemented)
/// 013f <item/mob name>.24B
/// 09ce <item/mob name>.100B [Ind/Yommy<3]
-void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
+static void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
{
const struct packet_gm_monster_item *p = RP2PTR(fd);
int i, count;
@@ -13433,7 +15594,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
safestrncpy(item_monster_name, p->str, sizeof(item_monster_name));
- if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) {
+ if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, IT_SEARCH_NAME_EXACT)) > 0 ) {
for(i = 0; i < count; i++) {
if( !item_array[i] )
continue;
@@ -13478,12 +15639,13 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
}
}
-void clif_parse_GMHide(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMHide(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /hide (CZ_CHANGE_EFFECTSTATE).
/// 019d <effect state>.L
/// effect state:
/// TODO: Any OPTION_* ?
-void clif_parse_GMHide(int fd, struct map_session_data *sd) {
+static void clif_parse_GMHide(int fd, struct map_session_data *sd)
+{
char cmd[6];
sprintf(cmd,"%chide",atcommand->at_symbol);
@@ -13491,14 +15653,15 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) {
atcommand->exec(fd, sd, cmd, true);
}
-void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMReqNoChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to adjust player's manner points (CZ_REQ_GIVE_MANNER_POINT).
/// 0149 <account id>.L <type>.B <value>.W
/// type:
/// 0 = positive points
/// 1 = negative points
/// 2 = self mute (+10 minutes)
-void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) {
+static void clif_parse_GMReqNoChat(int fd, struct map_session_data *sd)
+{
int id, type, value;
struct map_session_data *dstsd;
char command[NAME_LENGTH+15];
@@ -13545,11 +15708,11 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) {
atcommand->exec(fd, sd, command, true);
}
-void clif_parse_GMRc(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_GMRc(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /rc (CZ_REQ_GIVE_MANNER_BYNAME).
/// GM adjustment of a player's manner value by -60.
/// 0212 <char name>.24B
-void clif_parse_GMRc(int fd, struct map_session_data* sd)
+static void clif_parse_GMRc(int fd, struct map_session_data *sd)
{
char command[NAME_LENGTH+15];
char name[NAME_LENGTH];
@@ -13562,7 +15725,8 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd)
/// Result of request to resolve account name (ZC_ACK_ACCOUNTNAME).
/// 01e0 <account id>.L <account name>.24B
-void clif_account_name(struct map_session_data* sd, int account_id, const char* accname) {
+static void clif_account_name(struct map_session_data *sd, int account_id, const char *accname)
+{
int fd;
nullpo_retv(sd);
@@ -13574,10 +15738,10 @@ void clif_account_name(struct map_session_data* sd, int account_id, const char*
WFIFOSET(fd,packet_len(0x1e0));
}
-void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// GM requesting account name (for right-click gm menu) (CZ_REQ_ACCOUNTNAME).
/// 01df <account id>.L
-void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
+static void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
{
int account_id = RFIFOL(fd,2);
@@ -13585,14 +15749,15 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
clif->account_name(sd, account_id, ""); // insert account name here >_<
}
-void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /changemaptype <x> <y> <type> (CZ_CHANGE_MAPTYPE).
/// GM single cell type change request.
/// 0198 <x>.W <y>.W <type>.W
/// type:
/// 0 = not walkable
/// 1 = walkable
-void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) {
+static void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd)
+{
int x,y,type;
if (!pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE))
@@ -13607,14 +15772,14 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) {
//FIXME: once players leave the map, the client 'forgets' this information.
}
-void clif_parse_PMIgnore(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PMIgnore(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /in /ex (CZ_SETTING_WHISPER_PC).
/// Request to allow/deny whispers from a nick.
/// 00cf <nick>.24B <type>.B
/// type:
/// 0 = (/ex nick) deny speech from nick
/// 1 = (/in nick) allow speech from nick
-void clif_parse_PMIgnore(int fd, struct map_session_data* sd)
+static void clif_parse_PMIgnore(int fd, struct map_session_data *sd)
{
char nick[NAME_LENGTH];
uint8 type;
@@ -13661,14 +15826,14 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd)
clif->wisexin(sd, type, 0); // success
}
-void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /inall /exall (CZ_SETTING_WHISPER_STATE).
/// Request to allow/deny all whispers.
/// 00d0 <type>.B
/// type:
/// 0 = (/exall) deny all speech
/// 1 = (/inall) allow all speech
-void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd)
+static void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd)
{
int type = RFIFOB(fd,2), flag;
@@ -13699,7 +15864,8 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd)
/// Whisper ignore list (ZC_WHISPER_LIST).
/// 00d4 <packet len>.W { <char name>.24B }*
-void clif_PMIgnoreList(struct map_session_data* sd) {
+static void clif_PMIgnoreList(struct map_session_data *sd)
+{
int i, fd;
nullpo_retv(sd);
@@ -13715,34 +15881,38 @@ void clif_PMIgnoreList(struct map_session_data* sd) {
WFIFOSET(fd,WFIFOW(fd,2));
}
-void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PMIgnoreList(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Whisper ignore list request (CZ_REQ_WHISPER_LIST).
/// 00d3
-void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd)
+static void clif_parse_PMIgnoreList(int fd, struct map_session_data *sd)
{
clif->PMIgnoreList(sd);
}
-void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke the /doridori recovery bonus (CZ_DORIDORI).
/// 01e7
-void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd)
+static void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
if (sd->state.doridori) return;
- switch (sd->class_&MAPID_UPPERMASK) {
+ switch (sd->job & MAPID_UPPERMASK) {
case MAPID_SOUL_LINKER:
case MAPID_STAR_GLADIATOR:
case MAPID_TAEKWON:
if (!sd->state.rest)
break;
+ FALLTHROUGH
case MAPID_SUPER_NOVICE:
sd->state.doridori=1;
break;
}
}
-void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke the effect of super novice's guardian angel prayer (CZ_CHOPOKGI).
/// 01ed
/// Note: This packet is caused by 7 lines of any text, followed by
@@ -13751,14 +15921,17 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) __at
/// "Dear angel, can you hear my voice?"
/// "I am" (space separated player name) "Super Novice~"
/// "Help me out~ Please~ T_T"
-void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
+static void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
/* [Ind/Hercules] */
/* game client is currently broken on this (not sure the packetver range) */
/* it sends the request when the criteria doesn't match (and of course we let it fail) */
/* so restoring the old parse_globalmes method. */
- if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) {
- unsigned int next = pc->nextbaseexp(sd);
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
+ uint64 next = pc->nextbaseexp(sd);
if( next == 0 ) next = pc->thisbaseexp(sd);
if( next ) {
int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
@@ -13776,10 +15949,12 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
/// Toggles a single friend online/offline [Skotlex] (ZC_FRIENDS_STATE).
/// 0206 <account id>.L <char id>.L <state>.B
+/// 0206 <account id>.L <char id>.L <state>.B <name>.24B
/// state:
/// 0 = online
/// 1 = offline
-void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int char_id, int online) {
+static void clif_friendslist_toggle(struct map_session_data *sd, int account_id, int char_id, int online)
+{
int i, fd;
nullpo_retv(sd);
@@ -13795,12 +15970,16 @@ void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int cha
WFIFOW(fd, 0) = 0x206;
WFIFOL(fd, 2) = sd->status.friends[i].account_id;
WFIFOL(fd, 6) = sd->status.friends[i].char_id;
- WFIFOB(fd,10) = !online; //Yeah, a 1 here means "logged off", go figure...
+ WFIFOB(fd, 10) = !online; //Yeah, a 1 here means "logged off", go figure...
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221
+ memcpy(WFIFOP(fd, 11), sd->status.friends[i].name, NAME_LENGTH);
+#endif // PACKETVER_ZERO
+
WFIFOSET(fd, packet_len(0x206));
}
//Sub-function called from clif_foreachclient to toggle friends on/off [Skotlex]
-int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap)
+static int clif_friendslist_toggle_sub(struct map_session_data *sd, va_list ap)
{
int account_id, char_id, online;
account_id = va_arg(ap, int);
@@ -13812,22 +15991,30 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap)
/// Sends the whole friends list (ZC_FRIENDS_LIST).
/// 0201 <packet len>.W { <account id>.L <char id>.L <name>.24B }*
-void clif_friendslist_send(struct map_session_data *sd)
+/// 0201 <packet len>.W { <account id>.L <char id>.L }*
+static void clif_friendslist_send(struct map_session_data *sd)
{
int i = 0, n, fd = sd->fd;
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221
+ const int offset = 8;
+#else
+ const int offset = 32;
+#endif
nullpo_retv(sd);
// Send friends list
- WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4);
+ WFIFOHEAD(fd, MAX_FRIENDS * offset + 4);
WFIFOW(fd, 0) = 0x201;
for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) {
- WFIFOL(fd, 4 + 32 * i + 0) = sd->status.friends[i].account_id;
- WFIFOL(fd, 4 + 32 * i + 4) = sd->status.friends[i].char_id;
- memcpy(WFIFOP(fd, 4 + 32 * i + 8), &sd->status.friends[i].name, NAME_LENGTH);
+ WFIFOL(fd, 4 + offset * i + 0) = sd->status.friends[i].account_id;
+ WFIFOL(fd, 4 + offset * i + 4) = sd->status.friends[i].char_id;
+#if !(PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221)
+ memcpy(WFIFOP(fd, 4 + offset * i + 8), &sd->status.friends[i].name, NAME_LENGTH);
+#endif
}
if (i) {
- WFIFOW(fd,2) = 4 + 32 * i;
+ WFIFOW(fd,2) = 4 + offset * i;
WFIFOSET(fd, WFIFOW(fd,2));
}
@@ -13844,7 +16031,7 @@ void clif_friendslist_send(struct map_session_data *sd)
/// 1 = MsgStringTable[822]="(%s) does not want to be friends with you."
/// 2 = MsgStringTable[819]="Your Friend List is full."
/// 3 = MsgStringTable[820]="(%s)'s Friend List is full."
-void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type)
+static void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type)
{
int fd;
nullpo_retv(sd);
@@ -13863,7 +16050,8 @@ void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_dat
/// Asks a player for permission to be added as friend (ZC_REQ_ADD_FRIENDS).
/// 0207 <req account id>.L <req char id>.L <req char name>.24B
-void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_id, const char* name) {
+static void clif_friendlist_req(struct map_session_data *sd, int account_id, int char_id, const char *name)
+{
int fd;
nullpo_retv(sd);
@@ -13876,18 +16064,21 @@ void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_i
WFIFOSET(fd,packet_len(0x207));
}
-void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add a player as friend (CZ_ADD_FRIENDS).
/// 0202 <name>.24B
-void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
+static void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *f_sd;
int i;
char nick[NAME_LENGTH];
safestrncpy(nick, RFIFOP(fd,2), NAME_LENGTH);
- f_sd = map->nick2sd(nick);
+ f_sd = map->nick2sd(nick, true);
// ensure that the request player's friend list is not full
ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0);
@@ -13899,7 +16090,7 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
// Friend doesn't exist (no player with this name)
if (f_sd == NULL) {
- clif->message(fd, msg_fd(fd,3));
+ clif->message(fd, msg_fd(fd,3)); // "Character not found."
return;
}
@@ -13927,14 +16118,14 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
clif->friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name);
}
-void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to a friend add request (CZ_ACK_REQ_ADD_FRIENDS).
/// 0208 <inviter account id>.L <inviter char id>.L <result>.B
/// 0208 <inviter account id>.L <inviter char id>.L <result>.L (PACKETVER >= 6)
/// result:
/// 0 = rejected
/// 1 = accepted
-void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
+static void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
{
struct map_session_data *f_sd;
int account_id;
@@ -13973,6 +16164,7 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
f_sd->status.friends[i].char_id = sd->status.char_id;
memcpy(f_sd->status.friends[i].name, sd->status.name, NAME_LENGTH);
clif->friendslist_reqack(f_sd, sd, 0);
+ achievement->validate_friend_add(f_sd); // Achievements [Smokexyz/Hercules]
if (battle_config.friend_auto_add) {
// Also add f_sd to sd's friendlist.
@@ -13991,15 +16183,19 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
sd->status.friends[i].char_id = f_sd->status.char_id;
memcpy(sd->status.friends[i].name, f_sd->status.name, NAME_LENGTH);
clif->friendslist_reqack(sd, f_sd, 0);
+ achievement->validate_friend_add(sd); // Achievements [Smokexyz/Hercules]
}
}
}
-void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete a friend (CZ_DELETE_FRIENDS).
/// 0203 <account id>.L <char id>.L
-void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
+static void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *f_sd = NULL;
int account_id, char_id;
int i, j;
@@ -14061,7 +16257,8 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
/// /pvpinfo list (ZC_ACK_PVPPOINT).
/// 0210 <char id>.L <account id>.L <win point>.L <lose point>.L <point>.L
-void clif_PVPInfo(struct map_session_data* sd) {
+static void clif_PVPInfo(struct map_session_data *sd)
+{
int fd;
nullpo_retv(sd);
@@ -14076,10 +16273,10 @@ void clif_PVPInfo(struct map_session_data* sd) {
WFIFOSET(fd, packet_len(0x210));
}
-void clif_parse_PVPInfo(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_PVPInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /pvpinfo (CZ_REQ_PVPPOINT).
/// 020f <char id>.L <account id>.L
-void clif_parse_PVPInfo(int fd,struct map_session_data *sd)
+static void clif_parse_PVPInfo(int fd, struct map_session_data *sd)
{
// TODO: Is there a way to use this on an another player (char/acc id)?
clif->PVPInfo(sd);
@@ -14088,70 +16285,107 @@ void clif_parse_PVPInfo(int fd,struct map_session_data *sd)
/// Ranking list
/// ranking pointlist { <name>.24B <point>.L }*10
-void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) {
- const char* name;
- struct fame_list* list;
- int i;
+static void clif_ranklist_sub(struct PACKET_ZC_ACK_RANKING_sub *ranks, enum fame_list_type type)
+{
+#if !(PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190724)
+ nullpo_retv(ranks);
- nullpo_retv(buf);
- switch( type ) {
+ struct fame_list* list;
+ switch (type) {
case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break;
case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break;
case RANKTYPE_TAEKWON: list = pc->taekwon_fame_list; break;
default: return; // Unsupported
}
+ int i;
// Packet size limits this list to 10 elements. [Skotlex]
- for( i = 0; i < 10 && i < MAX_FAME_LIST; i++ ) {
- if( list[i].id > 0 ) {
- if( strcmp(list[i].name, "-") == 0 && (name = map->charid2nick(list[i].id)) != NULL ) {
- strncpy(WBUFP(buf, 24 * i), name, NAME_LENGTH);
+ for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) {
+ if (list[i].id > 0) {
+ const char* name;
+ if (strcmp(list[i].name, "-") == 0 && (name = map->charid2nick(list[i].id)) != NULL) {
+ strncpy(ranks->names[i].name, name, NAME_LENGTH);
} else {
- strncpy(WBUFP(buf, 24 * i), list[i].name, NAME_LENGTH);
+ strncpy(ranks->names[i].name, list[i].name, NAME_LENGTH);
}
} else {
- strncpy(WBUFP(buf, 24 * i), "None", 5);
+ strncpy(ranks->names[i].name, "None", 5);
}
- WBUFL(buf, 24 * 10 + i * 4) = list[i].fame; //points
+ ranks->points[i].points = list[i].fame; //points
}
- for( ;i < 10; i++ ) { // In case the MAX is less than 10.
- strncpy(WBUFP(buf, 24 * i), "Unavailable", 12);
- WBUFL(buf, 24 * 10 + i * 4) = 0;
+ for (;i < 10; i++) { // In case the MAX is less than 10.
+ strncpy(ranks->names[i].name, "Unavailable", 12);
+ ranks->points[i].points = 0;
}
+#endif
}
-/// 097d <RankingType>.W {<CharName>.24B <point>L}*10 <mypoint>L (ZC_ACK_RANKING)
-void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) {
- int fd;
- int mypoint = 0;
- int upperMask;
+static void clif_ranklist_sub2(uint32 *chars, uint32 *points, enum fame_list_type type)
+{
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190724
+ nullpo_retv(chars);
+ nullpo_retv(points);
+
+ struct fame_list* list;
+ switch (type) {
+ case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break;
+ case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break;
+ case RANKTYPE_TAEKWON: list = pc->taekwon_fame_list; break;
+ default: return; // Unsupported
+ }
+
+ int i;
+ // Packet size limits this list to 10 elements. [Skotlex]
+ for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) {
+ if (list[i].id > 0) {
+ chars[i] = list[i].id;
+ } else {
+ chars[i] = 0;
+ }
+ points[i] = list[i].fame; //points
+ }
+ for (;i < 10; i++) { // In case the MAX is less than 10.
+ chars[i] = 0;
+ points[i] = 0;
+ }
+#endif
+}
+/// 097d <RankingType>.W {<CharName>.24B <point>L}*10 <mypoint>L (ZC_ACK_RANKING)
+static void clif_ranklist(struct map_session_data *sd, enum fame_list_type type)
+{
+#if PACKETVER_MAIN_NUM >= 20130605 || PACKETVER_RE_NUM >= 20130529 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
- fd = sd->fd;
- upperMask = sd->class_&MAPID_UPPERMASK;
- WFIFOHEAD(fd, 288);
- WFIFOW(fd, 0) = 0x97d;
- WFIFOW(fd, 2) = type;
- clif_ranklist_sub(WFIFOP(fd,4), type);
+ int fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_ACK_RANKING));
+ struct PACKET_ZC_ACK_RANKING *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_ACK_RANKING;
+ p->rankType = type;
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190724
+PRAGMA_GCC9(GCC diagnostic push)
+PRAGMA_GCC9(GCC diagnostic ignored "-Waddress-of-packed-member")
+ clif->ranklist_sub2(p->chars, p->points, type);
+PRAGMA_GCC9(GCC diagnostic pop)
+#else
+ clif->ranklist_sub(&p->ranks, type);
+#endif
- if( (upperMask == MAPID_BLACKSMITH && type == RANKTYPE_BLACKSMITH)
- || (upperMask == MAPID_ALCHEMIST && type == RANKTYPE_ALCHEMIST)
- || (upperMask == MAPID_TAEKWON && type == RANKTYPE_TAEKWON)
- ) {
- mypoint = sd->status.fame;
+ if (pc->famelist_type(sd->job) == type) {
+ p->myPoints = sd->status.fame; //mypoint
} else {
- mypoint = 0;
+ p->myPoints = 0; //mypoint
}
- WFIFOL(fd, 284) = mypoint; //mypoint
- WFIFOSET(fd, 288);
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_ACK_RANKING));
+#endif
}
-void clif_parse_ranklist(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ranklist(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/*
* 097c <type> (CZ_REQ_RANKING)
* */
-void clif_parse_ranklist(int fd, struct map_session_data *sd) {
+static void clif_parse_ranklist(int fd, struct map_session_data *sd)
+{
int16 type = RFIFOW(fd, 2); //type
switch( type ) {
@@ -14164,8 +16398,9 @@ void clif_parse_ranklist(int fd, struct map_session_data *sd) {
}
// 097e <RankingType>.W <point>.L <TotalPoint>.L (ZC_UPDATE_RANKING_POINT)
-void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type type, int points) {
-#if PACKETVER < 20130710
+static void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type type, int points)
+{
+#if PACKETVER < 20120502
switch( type ) {
case RANKTYPE_BLACKSMITH: clif->fame_blacksmith(sd,points); break;
case RANKTYPE_ALCHEMIST: clif->fame_alchemist(sd,points); break;
@@ -14174,41 +16409,47 @@ void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type t
#else
int fd;
+ int len = packet_len(0x97e);
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd, 12);
+ WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x97e;
WFIFOW(fd, 2) = type;
WFIFOL(fd, 4) = points;
WFIFOL(fd, 8) = sd->status.fame;
- WFIFOSET(fd, 12);
+ WFIFOSET(fd, len);
#endif
}
/// /blacksmith list (ZC_BLACKSMITH_RANK).
/// 0219 { <name>.24B }*10 { <point>.L }*10
-void clif_blacksmith(struct map_session_data* sd) {
+static void clif_blacksmith(struct map_session_data *sd)
+{
+#if !(PACKETVER_MAIN_NUM >= 20130605 || PACKETVER_RE_NUM >= 20130529 || defined(PACKETVER_ZERO))
int fd;
nullpo_retv(sd);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x219));
WFIFOW(fd,0) = 0x219;
- clif_ranklist_sub(WFIFOP(fd, 2), RANKTYPE_BLACKSMITH);
+ clif->ranklist_sub(WFIFOP(fd, 2), RANKTYPE_BLACKSMITH);
WFIFOSET(fd, packet_len(0x219));
+#endif
}
-void clif_parse_Blacksmith(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Blacksmith(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /blacksmith (CZ_BLACKSMITH_RANK).
/// 0217
-void clif_parse_Blacksmith(int fd,struct map_session_data *sd) {
+static void clif_parse_Blacksmith(int fd, struct map_session_data *sd)
+{
clif->blacksmith(sd);
}
/// Notification about backsmith points (ZC_BLACKSMITH_POINT).
/// 021b <points>.L <total points>.L
-void clif_fame_blacksmith(struct map_session_data *sd, int points) {
+static void clif_fame_blacksmith(struct map_session_data *sd, int points)
+{
int fd;
nullpo_retv(sd);
@@ -14222,27 +16463,32 @@ void clif_fame_blacksmith(struct map_session_data *sd, int points) {
/// /alchemist list (ZC_ALCHEMIST_RANK).
/// 021a { <name>.24B }*10 { <point>.L }*10
-void clif_alchemist(struct map_session_data* sd) {
+static void clif_alchemist(struct map_session_data *sd)
+{
+#if !(PACKETVER_MAIN_NUM >= 20130605 || PACKETVER_RE_NUM >= 20130529 || defined(PACKETVER_ZERO))
int fd;
nullpo_retv(sd);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x21a));
WFIFOW(fd,0) = 0x21a;
- clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_ALCHEMIST);
+ clif->ranklist_sub(WFIFOP(fd,2), RANKTYPE_ALCHEMIST);
WFIFOSET(fd, packet_len(0x21a));
+#endif
}
-void clif_parse_Alchemist(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Alchemist(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /alchemist (CZ_ALCHEMIST_RANK).
/// 0218
-void clif_parse_Alchemist(int fd,struct map_session_data *sd) {
+static void clif_parse_Alchemist(int fd, struct map_session_data *sd)
+{
clif->alchemist(sd);
}
/// Notification about alchemist points (ZC_ALCHEMIST_POINT).
/// 021c <points>.L <total points>.L
-void clif_fame_alchemist(struct map_session_data *sd, int points) {
+static void clif_fame_alchemist(struct map_session_data *sd, int points)
+{
int fd;
nullpo_retv(sd);
@@ -14256,27 +16502,32 @@ void clif_fame_alchemist(struct map_session_data *sd, int points) {
/// /taekwon list (ZC_TAEKWON_RANK).
/// 0226 { <name>.24B }*10 { <point>.L }*10
-void clif_taekwon(struct map_session_data* sd) {
+static void clif_taekwon(struct map_session_data *sd)
+{
+#if !(PACKETVER_MAIN_NUM >= 20130605 || PACKETVER_RE_NUM >= 20130529 || defined(PACKETVER_ZERO))
int fd;
nullpo_retv(sd);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x226));
WFIFOW(fd,0) = 0x226;
- clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_TAEKWON);
+ clif->ranklist_sub(WFIFOP(fd,2), RANKTYPE_TAEKWON);
WFIFOSET(fd, packet_len(0x226));
+#endif
}
-void clif_parse_Taekwon(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Taekwon(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /taekwon (CZ_TAEKWON_RANK).
/// 0225
-void clif_parse_Taekwon(int fd,struct map_session_data *sd) {
+static void clif_parse_Taekwon(int fd, struct map_session_data *sd)
+{
clif->taekwon(sd);
}
/// Notification about taekwon points (ZC_TAEKWON_POINT).
/// 0224 <points>.L <total points>.L
-void clif_fame_taekwon(struct map_session_data *sd, int points) {
+static void clif_fame_taekwon(struct map_session_data *sd, int points)
+{
int fd;
nullpo_retv(sd);
@@ -14290,7 +16541,8 @@ void clif_fame_taekwon(struct map_session_data *sd, int points) {
/// /pk list (ZC_KILLER_RANK).
/// 0238 { <name>.24B }*10 { <point>.L }*10
-void clif_ranking_pk(struct map_session_data* sd) {
+static void clif_ranking_pk(struct map_session_data *sd)
+{
int i, fd;
nullpo_retv(sd);
@@ -14304,22 +16556,26 @@ void clif_ranking_pk(struct map_session_data* sd) {
WFIFOSET(fd, packet_len(0x238));
}
-void clif_parse_RankingPk(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RankingPk(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /pk (CZ_KILLER_RANK).
/// 0237
-void clif_parse_RankingPk(int fd,struct map_session_data *sd) {
+static void clif_parse_RankingPk(int fd, struct map_session_data *sd)
+{
clif->ranking_pk(sd);
}
-void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_FeelSaveOk(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// SG Feel save OK [Komurka] (CZ_AGREE_STARPLACE).
/// 0254 <which>.B
/// which:
/// 0 = sun
/// 1 = moon
/// 2 = star
-void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
+static void clif_parse_FeelSaveOk(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int i;
if (sd->menuskill_id != SG_FEEL)
return;
@@ -14328,7 +16584,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
sd->feel_map[i].index = map_id2index(sd->bl.m);
sd->feel_map[i].m = sd->bl.m;
- pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),sd->feel_map[i].index);
+ pc_setglobalreg(sd,script->add_variable(pc->sg_info[i].feel_var),sd->feel_map[i].index);
#if 0 // Are these really needed? Shouldn't they show up automatically from the feel save packet?
clif_misceffect2(&sd->bl, 0x1b0);
@@ -14344,7 +16600,8 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
/// 0 = sun
/// 1 = moon
/// 2 = star
-void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv)
+/// 10 = Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+static void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv)
{
nullpo_retv(sd);
WFIFOHEAD(fd,packet_len(0x253));
@@ -14355,19 +16612,25 @@ void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv)
sd->menuskill_val = skill_lv;
}
-void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change homunculus' name (CZ_RENAME_MER).
/// 0231 <name>.24B
-void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd)
+static void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
homun->change_name(sd, RFIFOP(fd,2));
}
-void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to warp/move homunculus/mercenary to it's owner (CZ_REQUEST_MOVETOOWNER).
/// 0234 <id>.L
-void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
+static void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int id = RFIFOL(fd,2); // Mercenary or Homunculus
struct block_list *bl = NULL;
struct unit_data *ud = NULL;
@@ -14381,14 +16644,17 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
unit->calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir);
ud = unit->bl2ud(bl);
- unit->walktoxy(bl, ud->to_x, ud->to_y, 4);
+ unit->walk_toxy(bl, ud->to_x, ud->to_y, 4);
}
-void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to move homunculus/mercenary (CZ_REQUEST_MOVENPC).
/// 0232 <id>.L <position data>.3B
-void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
+static void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int id = RFIFOL(fd,2); // Mercenary or Homunculus
struct block_list *bl = NULL;
short x, y;
@@ -14402,16 +16668,19 @@ void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
else
return;
- unit->walktoxy(bl, x, y, 4);
+ unit->walk_toxy(bl, x, y, 4);
}
-void clif_parse_HomAttack(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HomAttack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to do an action with homunculus/mercenary (CZ_REQUEST_ACTNPC).
/// 0233 <id>.L <target id>.L <action>.B
/// action:
/// always 0
-void clif_parse_HomAttack(int fd,struct map_session_data *sd)
+static void clif_parse_HomAttack(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct block_list *bl = NULL;
int id = RFIFOL(fd,2),
target_id = RFIFOL(fd,6),
@@ -14427,7 +16696,7 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd)
unit->attack(bl, target_id, action_type != 0);
}
-void clif_parse_HomMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_HomMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke a homunculus menu action (CZ_COMMAND_MER).
/// 022d <type>.W <command>.B
/// type:
@@ -14436,7 +16705,11 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) __attribute__((nonn
/// 0 = homunculus information
/// 1 = feed
/// 2 = delete
-void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn]
+static void clif_parse_HomMenu(int fd, struct map_session_data *sd)
+{ //[orn]
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int cmd;
cmd = RFIFOW(fd,0);
@@ -14447,11 +16720,21 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn]
homun->menu(sd,RFIFOB(fd,packet_db[cmd].pos[1]));
}
-void clif_parse_AutoRevive(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_AutoRevive(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to resurrect oneself using Token of Siegfried (CZ_STANDING_RESURRECTION).
/// 0292
-void clif_parse_AutoRevive(int fd, struct map_session_data *sd) {
- int item_position = pc->search_inventory(sd, ITEMID_TOKEN_OF_SIEGFRIED);
+static void clif_parse_AutoRevive(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
+ if (!pc_isdead(sd))
+ return;
+
+ if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER.
+ return;
+
+ int item_position = pc->have_item_chain(sd, ECC_SIEGFRIED);
int hpsp = 100;
if (item_position == INDEX_NOT_FOUND) {
@@ -14461,18 +16744,15 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) {
return;
}
- if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER.
- return;
-
if (!status->revive(&sd->bl, hpsp, hpsp))
return;
if (item_position == INDEX_NOT_FOUND)
- status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
+ status_change_end(&sd->bl, SC_LIGHT_OF_REGENE, INVALID_TIMER);
else
pc->delitem(sd, item_position, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME);
- clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
+ clif->skill_nodamage(&sd->bl, &sd->bl, ALL_RESURRECTION, 4, 1);
}
/// Information about character's status values (ZC_ACK_STATUS_GM).
@@ -14482,7 +16762,8 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) {
/// <itemdefPower>.W <plusdefPower>.W <mdefPower>.W <plusmdefPower>.W
/// <hitSuccessValue>.W <avoidSuccessValue>.W <plusAvoidSuccessValue>.W
/// <criticalSuccessValue>.W <ASPD>.W <plusASPD>.W
-void clif_check(int fd, struct map_session_data* pl_sd) {
+static void clif_check(int fd, struct map_session_data *pl_sd)
+{
nullpo_retv(pl_sd);
WFIFOHEAD(fd,packet_len(0x214));
WFIFOW(fd, 0) = 0x214;
@@ -14515,12 +16796,15 @@ void clif_check(int fd, struct map_session_data* pl_sd) {
WFIFOSET(fd,packet_len(0x214));
}
-void clif_parse_Check(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Check(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// /check (CZ_REQ_STATUS_GM).
/// Request character's status values.
/// 0213 <char name>.24B
-void clif_parse_Check(int fd, struct map_session_data *sd)
+static void clif_parse_Check(int fd, struct map_session_data *sd)
{
+ if (pc_istrading(sd) || pc_isvending(sd))
+ return;
+
char charname[NAME_LENGTH];
struct map_session_data* pl_sd;
@@ -14529,7 +16813,7 @@ void clif_parse_Check(int fd, struct map_session_data *sd)
safestrncpy(charname, RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname));
- if( ( pl_sd = map->nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) {
+ if ((pl_sd = map->nick2sd(charname, true)) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd)) {
return;
}
@@ -14545,7 +16829,7 @@ void clif_parse_Check(int fd, struct map_session_data *sd)
/// result:
/// 0 = success
/// 1 = failure
-void clif_Mail_setattachment(int fd, int index, uint8 flag)
+static void clif_Mail_setattachment(int fd, int index, uint8 flag)
{
WFIFOHEAD(fd,packet_len(0x255));
WFIFOW(fd,0) = 0x255;
@@ -14560,7 +16844,7 @@ void clif_Mail_setattachment(int fd, int index, uint8 flag)
/// 0 = success
/// 1 = failure
/// 2 = too many items
-void clif_Mail_getattachment(int fd, uint8 flag)
+static void clif_Mail_getattachment(int fd, uint8 flag)
{
WFIFOHEAD(fd,packet_len(0x245));
WFIFOW(fd,0) = 0x245;
@@ -14573,7 +16857,7 @@ void clif_Mail_getattachment(int fd, uint8 flag)
/// result:
/// 0 = success
/// 1 = recipient does not exist
-void clif_Mail_send(int fd, bool fail)
+static void clif_Mail_send(int fd, bool fail)
{
WFIFOHEAD(fd,packet_len(0x249));
WFIFOW(fd,0) = 0x249;
@@ -14586,7 +16870,7 @@ void clif_Mail_send(int fd, bool fail)
/// result:
/// 0 = success
/// 1 = failure
-void clif_Mail_delete(int fd, int mail_id, short fail)
+static void clif_Mail_delete(int fd, int mail_id, short fail)
{
WFIFOHEAD(fd, packet_len(0x257));
WFIFOW(fd,0) = 0x257;
@@ -14600,7 +16884,7 @@ void clif_Mail_delete(int fd, int mail_id, short fail)
/// result:
/// 0 = success
/// 1 = failure
-void clif_Mail_return(int fd, int mail_id, short fail)
+static void clif_Mail_return(int fd, int mail_id, short fail)
{
WFIFOHEAD(fd,packet_len(0x274));
WFIFOW(fd,0) = 0x274;
@@ -14611,7 +16895,7 @@ void clif_Mail_return(int fd, int mail_id, short fail)
/// Notification about new mail (ZC_MAIL_RECEIVE).
/// 024a <mail id>.L <title>.40B <sender>.24B
-void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title)
+static void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title)
{
nullpo_retv(sender);
nullpo_retv(title);
@@ -14628,7 +16912,7 @@ void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title)
/// type:
/// 0 = open
/// 1 = close
-void clif_Mail_window(int fd, int flag)
+static void clif_Mail_window(int fd, int flag)
{
WFIFOHEAD(fd,packet_len(0x260));
WFIFOW(fd,0) = 0x260;
@@ -14641,7 +16925,7 @@ void clif_Mail_window(int fd, int flag)
/// read:
/// 0 = unread
/// 1 = read
-void clif_Mail_refreshinbox(struct map_session_data *sd)
+static void clif_Mail_refreshinbox(struct map_session_data *sd)
{
int fd = sd->fd;
struct mail_data *md;
@@ -14673,16 +16957,19 @@ void clif_Mail_refreshinbox(struct map_session_data *sd)
if( md->full ) {// TODO: is this official?
char output[100];
- sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX);
- clif_disp_onlyself(sd, output, strlen(output));
+ sprintf(output, msg_sd(sd, 511), MAIL_MAX_INBOX); // Inbox is full (Max %d). Delete some mails.
+ clif_disp_onlyself(sd, output);
}
}
-void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Mail inbox list request (CZ_MAIL_GET_LIST).
/// 023f
-void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct mail_data* md = &sd->mail.inbox;
if( md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed) )
@@ -14698,7 +16985,7 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd)
/// 0242 <packet len>.W <mail id>.L <title>.40B <sender>.24B <time>.L <zeny>.L
/// <amount>.L <name id>.W <item type>.W <identified>.B <damaged>.B <refine>.B
/// <card1>.W <card2>.W <card3>.W <card4>.W <message>.?B
-void clif_Mail_read(struct map_session_data *sd, int mail_id)
+static void clif_Mail_read(struct map_session_data *sd, int mail_id)
{
int i, fd = sd->fd;
@@ -14712,11 +16999,16 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item = &msg->item;
struct item_data *data;
- size_t msg_len = strlen(msg->body), len;
+ int msg_len = (int)strlen(msg->body), len;
- if( msg_len == 0 ) {
+ if (msg_len == 0) {
strcpy(msg->body, "(no message)");
- msg_len = strlen(msg->body);
+ msg_len = (int)strlen(msg->body);
+ }
+
+ if (msg_len > UINT8_MAX) {
+ Assert_report(msg_len > UINT8_MAX);
+ msg_len = UINT8_MAX;
}
len = 101 + msg_len;
@@ -14744,7 +17036,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
} else // no item, set all to zero
memset(WFIFOP(fd,80), 0x00, 19);
- WFIFOB(fd,99) = (unsigned char)msg_len;
+ WFIFOB(fd,99) = (uint8)msg_len;
safestrncpy(WFIFOP(fd,100), msg->body, msg_len + 1);
WFIFOSET(fd,len);
@@ -14756,11 +17048,14 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
}
}
-void clif_parse_Mail_read(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_read(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to open a mail (CZ_MAIL_OPEN).
/// 0241 <mail id>.L
-void clif_parse_Mail_read(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_read(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int mail_id = RFIFOL(fd,2);
if( mail_id <= 0 )
@@ -14771,14 +17066,16 @@ void clif_parse_Mail_read(int fd, struct map_session_data *sd)
clif->mail_read(sd, RFIFOL(fd,2));
}
-void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to receive mail's attachment (CZ_MAIL_GET_ITEM).
/// 0244 <mail id>.L
-void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int mail_id = RFIFOL(fd,2);
int i;
- bool fail = false;
if( !chrif->isconnected() )
return;
@@ -14794,7 +17091,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
if( sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1) )
return;
- if( sd->mail.inbox.msg[i].zeny + sd->status.zeny > MAX_ZENY ) {
+ if( sd->mail.inbox.msg[i].zeny > MAX_ZENY - sd->status.zeny ) {
clif->mail_getattachment(fd, 1);
return;
}
@@ -14802,6 +17099,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
if( sd->mail.inbox.msg[i].item.nameid > 0 ) {
struct item_data *data;
unsigned int weight;
+ bool fail = false;
if ((data = itemdb->exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
@@ -14839,11 +17137,14 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
intif->Mail_getattach(sd->status.char_id, mail_id);
}
-void clif_parse_Mail_delete(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_delete(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to delete a mail (CZ_MAIL_DELETE).
/// 0243 <mail id>.L
-void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int mail_id = RFIFOL(fd,2);
int i;
@@ -14870,11 +17171,14 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
}
}
-void clif_parse_Mail_return(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_return(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to return a mail (CZ_REQ_MAIL_RETURN).
/// 0273 <mail id>.L <receive name>.24B
-void clif_parse_Mail_return(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_return(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int mail_id = RFIFOL(fd,2);
int i;
@@ -14894,11 +17198,14 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd)
}
}
-void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add an item or Zeny to mail (CZ_MAIL_ADD_ITEM).
/// 0247 <index>.W <amount>.L
-void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int idx = RFIFOW(fd,2);
int amount = RFIFOL(fd,4);
unsigned char flag;
@@ -14912,15 +17219,18 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
clif->mail_setattachment(fd,idx,flag);
}
-void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to reset mail item and/or Zeny (CZ_MAIL_RESET_ITEM).
/// 0246 <type>.W
/// type:
/// 0 = reset all
/// 1 = remove item
/// 2 = remove zeny
-void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
+static void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int flag = RFIFOW(fd,2);
if (flag == 0 || flag == 1)
@@ -14929,20 +17239,25 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
mail->removezeny(sd, 0);
}
-void clif_parse_Mail_send(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Mail_send(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to send mail (CZ_MAIL_SEND).
/// 0248 <packet len>.W <recipient>.24B <title>.40B <body len>.B <body>.?B
-void clif_parse_Mail_send(int fd, struct map_session_data *sd)
+
+static void clif_parse_Mail_send(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct mail_message msg;
int body_len;
+ int len = RFIFOW(fd, 2);
if( !chrif->isconnected() )
return;
if( sd->state.trading )
return;
- if( RFIFOW(fd,2) < 69 ) {
+ if (len < 69) {
ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id);
return;
}
@@ -14958,6 +17273,11 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
if (body_len > MAIL_BODY_LENGTH)
body_len = MAIL_BODY_LENGTH;
+ if (body_len + 69 > len) {
+ ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id);
+ return;
+ }
+
memset(&msg, 0, sizeof(msg));
if (!mail->setattachment(sd, &msg)) { // Invalid Append condition
clif->mail_send(sd->fd, true); // fail
@@ -14998,13 +17318,13 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
/// type:
/// 0 = open
/// 1 = close
-void clif_Auction_openwindow(struct map_session_data *sd)
+static void clif_Auction_openwindow(struct map_session_data *sd)
{
int fd;
nullpo_retv(sd);
fd = sd->fd;
- if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading)
+ if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.trading)
return;
if( !battle_config.feature_auction )
@@ -15018,7 +17338,7 @@ void clif_Auction_openwindow(struct map_session_data *sd)
/// Returns auction item search results (ZC_AUCTION_ITEM_REQ_SEARCH).
/// 0252 <packet len>.W <pages>.L <count>.L { <auction id>.L <seller name>.24B <name id>.W <type>.L <amount>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <now price>.L <max price>.L <buyer name>.24B <delete time>.L }*
-void clif_Auction_results(struct map_session_data *sd, short count, short pages, const uint8 *buf)
+static void clif_Auction_results(struct map_session_data *sd, short count, short pages, const uint8 *buf)
{
int i, fd, len = sizeof(struct auction_data);
struct auction_data auction;
@@ -15066,7 +17386,8 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
/// result:
/// 0 = success
/// 1 = failure
-void clif_Auction_setitem(int fd, int index, bool fail) {
+static void clif_Auction_setitem(int fd, int index, bool fail)
+{
WFIFOHEAD(fd,packet_len(0x256));
WFIFOW(fd,0) = 0x256;
WFIFOW(fd,2) = index;
@@ -15074,28 +17395,34 @@ void clif_Auction_setitem(int fd, int index, bool fail) {
WFIFOSET(fd,packet_len(0x256));
}
-void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to initialize 'new auction' data (CZ_AUCTION_CREATE).
/// 024b <type>.W
/// type:
/// 0 = create (any other action in auction window)
/// 1 = cancel (cancel pressed on register tab)
/// ? = junk, uninitialized value (ex. when switching between list filters)
-void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd)
{
- if( sd->auction.amount > 0 )
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (sd->auction.amount > 0)
clif->additem(sd, sd->auction.index, sd->auction.amount, 0);
sd->auction.amount = 0;
}
-void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add an item to the action (CZ_AUCTION_ADD_ITEM).
/// 024c <index>.W <count>.L
-void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
{
- int idx = RFIFOW(fd,2) - 2;
- int amount = RFIFOL(fd,4); // Always 1
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int idx = RFIFOW(fd, 2) - 2;
+ int amount = RFIFOL(fd, 4); // Always 1
struct item_data *item;
if( !battle_config.feature_auction )
@@ -15104,7 +17431,7 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
if( sd->auction.amount > 0 )
sd->auction.amount = 0;
- if( idx < 0 || idx >= MAX_INVENTORY ) {
+ if (idx < 0 || idx >= sd->status.inventorySize) {
ShowWarning("Character %s trying to set invalid item index in auctions.\n", sd->status.name);
return;
}
@@ -15146,7 +17473,7 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
/// 7 = You have failed to win the auction
/// 8 = You do not have enough Zeny
/// 9 = You cannot place more than 5 bids at a time
-void clif_Auction_message(int fd, unsigned char flag)
+static void clif_Auction_message(int fd, unsigned char flag)
{
WFIFOHEAD(fd,packet_len(0x250));
WFIFOW(fd,0) = 0x250;
@@ -15160,26 +17487,29 @@ void clif_Auction_message(int fd, unsigned char flag)
/// 0 = You have ended the auction
/// 1 = You cannot end the auction
/// 2 = Auction ID is incorrect
-void clif_Auction_close(int fd, unsigned char flag)
+static void clif_Auction_close(int fd, unsigned char flag)
{
- WFIFOHEAD(fd,packet_len(0x25e));
+ WFIFOHEAD(fd, 4);
WFIFOW(fd,0) = 0x25d; // BUG: The client identifies this packet as 0x25d (CZ_AUCTION_REQ_MY_SELL_STOP)
WFIFOW(fd,2) = flag;
- WFIFOSET(fd,packet_len(0x25e));
+ WFIFOSET(fd, 4);
}
-void clif_parse_Auction_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to add an auction (CZ_AUCTION_ADD).
/// 024d <now money>.L <max money>.L <delete hour>.W
-void clif_parse_Auction_register(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_register(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct auction_data auction;
struct item_data *item;
if (!battle_config.feature_auction)
return;
- Assert_retv(sd->auction.index >= 0 && sd->auction.index < MAX_INVENTORY);
+ Assert_retv(sd->auction.index >= 0 && sd->auction.index < sd->status.inventorySize);
memset(&auction, 0, sizeof(auction));
auction.price = RFIFOL(fd,2);
@@ -15239,7 +17569,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
// Auction checks...
if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bound_items(sd) ) {
- clif->message(sd->fd, msg_sd(sd,293));
+ clif->message(sd->fd, msg_sd(sd,293)); // This bound item cannot be traded to that character.
clif->auction_message(fd, 2); // The auction has been canceled
return;
}
@@ -15263,36 +17593,45 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
}
}
-void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Cancels an auction (CZ_AUCTION_ADD_CANCEL).
/// 024e <auction id>.L
-void clif_parse_Auction_cancel(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_cancel(int fd, struct map_session_data *sd)
{
- unsigned int auction_id = RFIFOL(fd,2);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ unsigned int auction_id = RFIFOL(fd, 2);
intif->Auction_cancel(sd->status.char_id, auction_id);
}
-void clif_parse_Auction_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Closes an auction (CZ_AUCTION_REQ_MY_SELL_STOP).
/// 025d <auction id>.L
-void clif_parse_Auction_close(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_close(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
unsigned int auction_id = RFIFOL(fd,2);
intif->Auction_close(sd->status.char_id, auction_id);
}
-void clif_parse_Auction_bid(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_bid(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Places a bid on an auction (CZ_AUCTION_BUY).
/// 024f <auction id>.L <money>.L
-void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
+static void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
{
- unsigned int auction_id = RFIFOL(fd,2);
- int bid = RFIFOL(fd,6);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ unsigned int auction_id = RFIFOL(fd, 2);
+ int bid = RFIFOL(fd, 6);
if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish]
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
return;
}
@@ -15308,7 +17647,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
}
}
-void clif_parse_Auction_search(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_search(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Auction Search (CZ_AUCTION_ITEM_SEARCH).
/// 0251 <search type>.W <auction id>.L <search text>.24B <page number>.W
/// search type:
@@ -15318,11 +17657,14 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) __attribute_
/// 3 = misc
/// 4 = name search
/// 5 = auction id search
-void clif_parse_Auction_search(int fd, struct map_session_data* sd)
+static void clif_parse_Auction_search(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
char search_text[NAME_LENGTH];
- short type = RFIFOW(fd,2), page = RFIFOW(fd,32);
- int price = RFIFOL(fd,4); // FIXME: bug #5071
+ short type = RFIFOW(fd, 2), page = RFIFOW(fd, 32);
+ int price = RFIFOL(fd, 4); // FIXME: bug #5071
if( !battle_config.feature_auction )
return;
@@ -15333,15 +17675,18 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd)
intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page);
}
-void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_Auction_buysell(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Requests list of own currently active bids or auctions (CZ_AUCTION_REQ_MY_INFO).
/// 025c <type>.W
/// type:
/// 0 = sell (own auctions)
/// 1 = buy (own bids)
-void clif_parse_Auction_buysell(int fd, struct map_session_data* sd)
+static void clif_parse_Auction_buysell(int fd, struct map_session_data *sd)
{
- short type = RFIFOW(fd,2) + 6;
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ short type = RFIFOW(fd, 2) + 6;
if( !battle_config.feature_auction )
return;
@@ -15357,16 +17702,14 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data* sd)
/// List of items offered in a cash shop (ZC_PC_CASH_POINT_ITEMLIST).
/// 0287 <packet len>.W <cash point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }*
/// 0287 <packet len>.W <cash point>.L <kafra point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* (PACKETVER >= 20070711)
-void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) {
+static void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd)
+{
struct npc_item_list *shop = NULL;
unsigned short shop_size = 0;
- int fd,i, c = 0;
+ int fd, i, c = 0;
int currency[2] = { 0,0 };
-#if PACKETVER < 20070711
- const int offset = 8;
-#else
- const int offset = 12;
-#endif
+ int len;
+ struct PACKET_ZC_PC_CASH_POINT_ITEMLIST *p;
nullpo_retv(sd);
nullpo_retv(nd);
@@ -15389,33 +17732,36 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) {
fd = sd->fd;
sd->npc_shopid = nd->bl.id;
- WFIFOHEAD(fd,offset+shop_size*11);
- WFIFOW(fd,0) = 0x287;
- /* 0x2 = length, set after parsing */
- WFIFOL(fd,4) = currency[0]; // Cash Points
+ len = sizeof(struct PACKET_ZC_PC_CASH_POINT_ITEMLIST) + shop_size * sizeof(struct PACKET_ZC_PC_CASH_POINT_ITEMLIST_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x287;
+ p->cashPoints = currency[0];
#if PACKETVER >= 20070711
- WFIFOL(fd,8) = currency[1]; // Kafra Points
+ p->kafraPoints = currency[1];
#endif
- for( i = 0; i < shop_size; i++ ) {
- if( shop[i].nameid ) {
+ for (i = 0; i < shop_size; i++) {
+ if (shop[i].nameid) {
struct item_data* id = itemdb->search(shop[i].nameid);
- WFIFOL(fd,offset+0+i*11) = shop[i].value;
- WFIFOL(fd,offset+4+i*11) = shop[i].value; // Discount Price
- WFIFOB(fd,offset+8+i*11) = itemtype(id->type);
- WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ p->items[c].price = shop[i].value;
+ p->items[c].discountPrice = shop[i].value;
+ p->items[c].itemType = itemtype(id->type);
+ p->items[c].itemId = (id->view_id > 0) ? id->view_id : id->nameid;
c++;
}
}
- WFIFOW(fd,2) = offset+c*11;
- WFIFOSET(fd,WFIFOW(fd,2));
+ len = sizeof(struct PACKET_ZC_PC_CASH_POINT_ITEMLIST) + c * sizeof(struct PACKET_ZC_PC_CASH_POINT_ITEMLIST_sub);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
}
/// 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)
/// For error return codes see enum cashshop_error@clif.h
-void clif_cashshop_ack(struct map_session_data* sd, int error) {
+static void clif_cashshop_ack(struct map_session_data *sd, int error)
+{
struct npc_data *nd;
int fd;
int currency[2] = { 0,0 };
@@ -15443,42 +17789,54 @@ void clif_cashshop_ack(struct map_session_data* sd, int error) {
WFIFOSET(fd, packet_len(0x289));
}
-void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to buy item(s) from cash shop (CZ_PC_BUY_CASH_POINT_ITEM).
/// 0288 <name id>.W <amount>.W
/// 0288 <name id>.W <amount>.W <kafra points>.L (PACKETVER >= 20070711)
/// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803)
-void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
+static void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int fail = 0;
+ const struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM *p = RFIFOP(fd, 0);
- if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) )
+ if (sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE)) {
fail = 1;
- else {
-#if PACKETVER < 20101116
- short nameid = RFIFOW(fd,2);
- short amount = RFIFOW(fd,4);
- int points = RFIFOL(fd,6);
-
- fail = npc->cashshop_buy(sd, nameid, amount, points);
+ } else {
+#if PACKETVER < 20070711
+ fail = npc->cashshop_buy(sd, p->itemId, p->amount, 0);
+#elif PACKETVER < 20101116
+ fail = npc->cashshop_buy(sd, p->itemId, p->amount, p->kafraPoints);
#else
- int len = RFIFOW(fd,2);
- int points = RFIFOL(fd,4);
- int count = RFIFOW(fd,8);
+ int len = p->packetLength;
+ int needLen;
+ int points;
+ int count;
struct itemlist item_list = { 0 };
int i;
- if( len < 10 || len != 10 + count * 4) {
- ShowWarning("Player %d sent incorrect cash shop buy packet (len %d:%d)!\n", sd->status.char_id, len, 10 + count * 4);
+ if (len < sizeof(struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM)) {
+ ShowWarning("Player %d sent incorrect cash shop buy packet (len %d)!\n", sd->status.char_id, len);
return;
}
+
+ points = p->kafraPoints;
+ count = p->count;
+ needLen = sizeof(struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM) + count * sizeof(struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub);
+ if (len != needLen) {
+ ShowWarning("Player %d sent incorrect cash shop buy packet (len %d:%d)!\n", sd->status.char_id, len, needLen);
+ return;
+ }
+
VECTOR_INIT(item_list);
VECTOR_ENSURE(item_list, count, 1);
for (i = 0; i < count; i++) {
struct itemlist_entry entry = { 0 };
- entry.amount = RFIFOW(fd, 10 + 4 * i);
- entry.id = RFIFOW(fd, 10 + 4 * i + 2); // Nameid
+ entry.amount = p->items[i].amount;
+ entry.id = p->items[i].itemId;
VECTOR_PUSH(item_list, entry);
}
@@ -15499,7 +17857,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
/// 0 = "You cannot adopt more than 1 child."
/// 1 = "You must be at least character level 70 in order to adopt someone."
/// 2 = "You cannot adopt a married person."
-void clif_Adopt_reply(struct map_session_data *sd, int type)
+static void clif_Adopt_reply(struct map_session_data *sd, int type)
{
int fd;
@@ -15513,7 +17871,8 @@ void clif_Adopt_reply(struct map_session_data *sd, int type)
/// Adoption confirmation (ZC_REQ_BABY).
/// 01f6 <account id>.L <char id>.L <name>.B
-void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id) {
+static void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id)
+{
int fd;
nullpo_retv(sd);
@@ -15527,10 +17886,14 @@ void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *sr
WFIFOSET(fd,34);
}
-void clif_parse_Adopt_request(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Adopt_request(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to adopt a player (CZ_REQ_JOIN_BABY).
/// 01f9 <account id>.L
-void clif_parse_Adopt_request(int fd, struct map_session_data *sd) {
+static void clif_parse_Adopt_request(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct map_session_data *tsd = map->id2sd(RFIFOL(fd,2)), *p_sd = map->charid2sd(sd->status.partner_id);
if( pc->can_Adopt(sd, p_sd, tsd) ) {
@@ -15539,13 +17902,17 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd) {
}
}
-void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Answer to adopt confirmation (CZ_JOIN_BABY).
/// 01f7 <account id>.L <char id>.L <answer>.L
/// answer:
/// 0 = rejected
/// 1 = accepted
-void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) {
+static void clif_parse_Adopt_reply(int fd, struct map_session_data *sd)
+{
+ if (pc_isdead(sd))
+ return;
+
int p1_id = RFIFOL(fd,2);
int p2_id = RFIFOL(fd,6);
int result = RFIFOL(fd,10);
@@ -15574,7 +17941,7 @@ void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) {
/// 1 = Boss is alive (position update) (BOSS_INFO_ALIVE).
/// 2 = Boss is alive (initial announce) (BOSS_INFO_ALIVE_WITHMSG).
/// 3 = Boss is dead (BOSS_INFO_DEAD).
-void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
+static void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
{
WFIFOHEAD(fd,70);
memset(WFIFOP(fd,0),0,70);
@@ -15608,47 +17975,94 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
WFIFOSET(fd,70);
}
-void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ViewPlayerEquip(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Requesting equip of a player (CZ_EQUIPWIN_MICROSCOPE).
/// 02d6 <account id>.L
-void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) {
+static void clif_parse_ViewPlayerEquip(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int charid = RFIFOL(fd, 2);
struct map_session_data* tsd = map->id2sd(charid);
if (!tsd)
return;
- if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) )
+ if (tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT)) {
clif->viewequip_ack(sd, tsd);
- else
- clif->msgtable(sd, MSG_EQUIP_NOT_PUBLIC);
+ } else {
+#if PACKETVER >= 20070918
+ clif->msgtable(sd, MSG_OPEN_EQUIPEDITEM_REFUSED);
+#endif
+ }
}
-void clif_parse_EquipTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Request to change equip window tick (CZ_CONFIG).
+static void clif_parse_cz_config(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/// Receive configurations (CZ_CONFIG).
/// 02d8 <type>.L <value>.L
/// type:
/// 0 = open equip window
+/// 2 = pet autofeeding
+/// 3 = homunculus autofeeding
/// value:
/// 0 = disabled
/// 1 = enabled
-void clif_parse_EquipTick(int fd, struct map_session_data* sd)
+static void clif_parse_cz_config(int fd, struct map_session_data *sd)
{
- bool flag = (RFIFOL(fd,6) != 0) ? true : false;
- sd->status.show_equip = flag;
- clif->equiptickack(sd, flag);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ enum CZ_CONFIG type = RFIFOL(fd, 2);
+ int flag = RFIFOL(fd, 6);
+
+ switch (type) {
+ case CZ_CONFIG_OPEN_EQUIPMENT_WINDOW:
+ sd->status.show_equip = flag;
+ break;
+ case CZ_CONFIG_PET_AUTOFEEDING: {
+ struct pet_data *pd = sd->pd;
+ nullpo_retv(pd);
+ if (pd->petDB->autofeed == 0) {
+ clif->message(fd, "Autofeed is disabled for this pet.");
+ return;
+ }
+ pd->pet.autofeed = flag;
+ break;
+ }
+ case CZ_CONFIG_HOMUNCULUS_AUTOFEEDING: {
+ struct homun_data *hd = sd->hd;
+ nullpo_retv(hd);
+ hd->homunculus.autofeed = flag;
+ break;
+ }
+ case CZ_CONFIG_CALL:
+ sd->status.allow_call = flag;
+ break;
+ default:
+ ShowWarning("clif_parse_cz_config: Unsupported type has been received (%u).\n", type);
+ return;
+ }
+ clif->zc_config(sd, type, flag);
}
-void clif_parse_PartyTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_PartyTick(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change party invitation tick.
/// value:
-/// 0 = disabled
-/// 1 = enabled
-void clif_parse_PartyTick(int fd, struct map_session_data* sd)
-{
- bool flag = RFIFOB(fd,6)?true:false;
- sd->status.allow_party = flag;
- clif->partytickack(sd, flag);
+/// 0 = enabled
+/// 1 = disabled
+static void clif_parse_PartyTick(int fd, struct map_session_data *sd)
+{
+ const struct PACKET_CZ_PARTY_CONFIG *const p = RFIFOP(fd, 0);
+ const bool newAllowParty = p->refuseInvite ? true : false;
+ if (newAllowParty != sd->status.allow_party) {
+ sd->status.allow_party = newAllowParty;
+ if ((map->save_settings & 512) != 0)
+ chrif->save(sd, 0); // send to char server
+ } else {
+ sd->status.allow_party = newAllowParty;
+ }
+ clif->partytickack(sd, sd->status.allow_party);
}
/// Questlog System [Kevin] [Inkfish]
@@ -15657,7 +18071,8 @@ void clif_parse_PartyTick(int fd, struct map_session_data* sd)
/// Sends list of all quest states (ZC_ALL_QUEST_LIST).
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num
/// 097a <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <mob_id>.L <killed>.W <total>.W <mob name>.24B }*count }*num
-void clif_quest_send_list(struct map_session_data *sd)
+/// 09f8 <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <hunt identification>.L <mob type>.L <mob_id>.L <min level>.L <max level>.L <killed>.W <total>.W <mob name>.24B }*count }*num
+static void clif_quest_send_list(struct map_session_data *sd)
{
int i, len, real_len;
uint8 *buf = NULL;
@@ -15695,8 +18110,20 @@ void clif_quest_send_list(struct map_session_data *sd)
real_len += sizeof(info->objectives[j]);
mob_data = mob->db(qi->objectives[j].mob);
-
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ info->objectives[j].huntIdent = sd->quest_log[i].quest_id;
+ info->objectives[j].huntIdent2 = j;
+ info->objectives[j].mobType = 0; // Info Needed
+#elif PACKETVER >= 20150513
+ info->objectives[j].huntIdent = (sd->quest_log[i].quest_id * 1000) + j;
+ info->objectives[j].mobType = 0; // Info Needed
+#endif
info->objectives[j].mob_id = qi->objectives[j].mob;
+#if PACKETVER >= 20150513
+ // Info Needed
+ info->objectives[j].levelMin = 0;
+ info->objectives[j].levelMax = 0;
+#endif
info->objectives[j].huntCount = sd->quest_log[i].count[j];
info->objectives[j].maxCount = qi->objectives[j].count;
safestrncpy(info->objectives[j].mobName, mob_data->jname, sizeof(info->objectives[j].mobName));
@@ -15710,7 +18137,7 @@ void clif_quest_send_list(struct map_session_data *sd)
/// Sends list of all quest missions (ZC_ALL_QUEST_MISSION).
/// 02b2 <packet len>.W <num>.L { <quest id>.L <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3 }*num
-void clif_quest_send_mission(struct map_session_data *sd)
+static void clif_quest_send_mission(struct map_session_data *sd)
{
int fd = sd->fd;
int i, j;
@@ -15744,38 +18171,63 @@ void clif_quest_send_mission(struct map_session_data *sd)
/// Notification about a new quest (ZC_ADD_QUEST).
/// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3
-void clif_quest_add(struct map_session_data *sd, struct quest *qd)
+/// 09f9 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <hunt identification>.L <mob type>.L <mob id>.L <min level>.L <max level>.L <mob count>.W <mob name>.24B }*3
+static void clif_quest_add(struct map_session_data *sd, struct quest *qd)
{
- int fd;
- int i;
+ int i, len;
+ uint8 *buf = NULL;
+ struct packet_quest_add_header *packet = NULL;
struct quest_db *qi;
nullpo_retv(sd);
nullpo_retv(qd);
- fd = sd->fd;
+
qi = quest->db(qd->quest_id);
- WFIFOHEAD(fd, packet_len(0x2b3));
- WFIFOW(fd, 0) = 0x2b3;
- WFIFOL(fd, 2) = qd->quest_id;
- WFIFOB(fd, 6) = qd->state;
- WFIFOB(fd, 7) = qd->time - qi->time;
- WFIFOL(fd, 11) = qd->time;
- WFIFOW(fd, 15) = qi->objectives_count;
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
+
+ len = sizeof(struct packet_quest_add_header)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_hunt_sub); // >= than the actual length
+
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_add_header *)WBUFP(buf, 0);
+
+ packet->PacketType = questAddType;
+ packet->questID = qd->quest_id;
+ packet->active = qd->state;
+ packet->quest_svrTime = qd->time - qi->time;
+ packet->quest_endTime = qd->time;
+ packet->count = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
struct mob_db *monster;
- WFIFOL(fd, i*30+17) = qi->objectives[i].mob;
- WFIFOW(fd, i*30+21) = qd->count[i];
+
monster = mob->db(qi->objectives[i].mob);
- memcpy(WFIFOP(fd, i*30+23), monster->jname, NAME_LENGTH);
- }
- WFIFOSET(fd, packet_len(0x2b3));
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ packet->objectives[i].huntIdent = qd->quest_id;
+ packet->objectives[i].huntIdent2 = i;
+ packet->objectives[i].mobType = 0; // Info Needed
+#elif PACKETVER >= 20150513
+ packet->objectives[i].huntIdent = (qd->quest_id * 1000) + i;
+ packet->objectives[i].mobType = 0; // Info Needed
+#endif
+ packet->objectives[i].mob_id = qi->objectives[i].mob;
+#if PACKETVER >= 20150513
+ // Info Needed
+ packet->objectives[i].levelMin = 0;
+ packet->objectives[i].levelMax = 0;
+#endif
+ packet->objectives[i].huntCount = qd->count[i];
+ memcpy(packet->objectives[i].mobName, monster->jname, NAME_LENGTH);
+ }
+ clif->send(buf, len, &sd->bl, SELF);
+ aFree(buf);
}
/// Notification about a quest being removed (ZC_DEL_QUEST).
/// 02b4 <quest id>.L
-void clif_quest_delete(struct map_session_data *sd, int quest_id) {
+static void clif_quest_delete(struct map_session_data *sd, int quest_id)
+{
int fd;
nullpo_retv(sd);
@@ -15788,44 +18240,104 @@ void clif_quest_delete(struct map_session_data *sd, int quest_id) {
/// Notification of an update to the hunting mission counter (ZC_UPDATE_MISSION_HUNT).
/// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
-void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd)
+/// 09fa <packet len>.W <mobs>.W { <quest id>.L <hunt identification>.L <total count>.W <current count>.W }*3
+static void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd)
{
- int fd;
- int i;
+ int i, len, real_len;
+ uint8 *buf = NULL;
+ struct packet_quest_update_header *packet = NULL;
struct quest_db *qi;
- int len;
nullpo_retv(sd);
nullpo_retv(qd);
- fd = sd->fd;
+
qi = quest->db(qd->quest_id);
- len = qi->objectives_count * 12 + 6;
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
- WFIFOHEAD(fd, len);
- WFIFOW(fd, 0) = 0x2b5;
- WFIFOW(fd, 2) = len;
- WFIFOW(fd, 4) = qi->objectives_count;
+ len = sizeof(struct packet_quest_update_header)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_update_hunt); // >= than the actual length
+
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_update_header *)WBUFP(buf, 0);
+ real_len = sizeof(*packet);
+
+ packet->PacketType = questUpdateType;
+ packet->count = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
- WFIFOL(fd, i*12+6) = qd->quest_id;
- WFIFOL(fd, i*12+10) = qi->objectives[i].mob;
- WFIFOW(fd, i*12+14) = qi->objectives[i].count;
- WFIFOW(fd, i*12+16) = qd->count[i];
+ real_len += sizeof(packet->objectives[i]);
+
+ packet->objectives[i].questID = qd->quest_id;
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ packet->objectives[i].huntIdent = qd->quest_id;
+ packet->objectives[i].huntIdent2 = i;
+#elif PACKETVER >= 20150513
+ packet->objectives[i].huntIdent = (qd->quest_id * 1000) + i;
+#else
+ packet->objectives[i].mob_id = qi->objectives[i].mob;
+#endif
+ packet->objectives[i].maxCount = qi->objectives[i].count;
+ packet->objectives[i].count = qd->count[i];
}
+ packet->PacketLength = real_len;
+ clif->send(buf, real_len, &sd->bl, SELF);
+ aFree(buf);
+}
- WFIFOSET(fd, len);
+/// Notification of an hunting mission counter just after quest is added (ZC_HUNTING_QUEST_INFO).
+/// 08fe <packet len>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
+static void clif_quest_notify_objective(struct map_session_data *sd, struct quest *qd)
+{
+#if PACKETVER >= 20150513
+ int i, len, real_len;
+ uint8 *buf = NULL;
+ struct packet_quest_hunt_info *packet = NULL;
+ struct quest_db *qi;
+
+ nullpo_retv(sd);
+ nullpo_retv(qd);
+
+ qi = quest->db(qd->quest_id);
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
+
+ len = sizeof(struct packet_quest_hunt_info)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_hunt_info_sub); // >= than the actual length
+
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_hunt_info *)WBUFP(buf, 0);
+ real_len = sizeof(*packet);
+
+ packet->PacketType = questUpdateType2;
+
+ for (i = 0; i < qi->objectives_count; i++) {
+ real_len += sizeof(packet->info[i]);
+
+ packet->info[i].questID = qd->quest_id;
+ packet->info[i].mob_id = qi->objectives[i].mob;
+ packet->info[i].maxCount = qi->objectives[i].count;
+ packet->info[i].count = qd->count[i];
+ }
+ packet->PacketLength = real_len;
+ clif->send(buf, real_len, &sd->bl, SELF);
+ aFree(buf);
+#endif
}
-void clif_parse_questStateAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_questStateAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to change the state of a quest (CZ_ACTIVE_QUEST).
/// 02b6 <quest id>.L <active>.B
-void clif_parse_questStateAck(int fd, struct map_session_data *sd) {
+static void clif_parse_questStateAck(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
quest->update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE);
}
/// Notification about the change of a quest state (ZC_ACTIVE_QUEST).
/// 02b7 <quest id>.L <active>.B
-void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool active) {
+static void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool active)
+{
int fd;
nullpo_retv(sd);
@@ -15848,7 +18360,7 @@ void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool ac
/// 1 = orange
/// 2 = green
/// 3 = purple
-void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color)
+static void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color)
{
#if PACKETVER >= 20090218
int fd;
@@ -15872,7 +18384,8 @@ void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, s
/// Notification about a mercenary status parameter change (ZC_MER_PAR_CHANGE).
/// 02a2 <var id>.W <value>.L
-void clif_mercenary_updatestatus(struct map_session_data *sd, int type) {
+static void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
+{
struct mercenary_data *md;
struct status_data *mstatus;
int fd;
@@ -15938,7 +18451,8 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) {
/// 029b <id>.L <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W
/// <name>.24B <level>.W <hp>.L <maxhp>.L <sp>.L <maxsp>.L <expire time>.L <faith>.W
/// <calls>.L <kills>.L <atk range>.W
-void clif_mercenary_info(struct map_session_data *sd) {
+static void clif_mercenary_info(struct map_session_data *sd)
+{
int fd;
struct mercenary_data *md;
struct status_data *mstatus;
@@ -15994,7 +18508,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 <upgradeable>.B }*
-void clif_mercenary_skillblock(struct map_session_data *sd)
+static void clif_mercenary_skillblock(struct map_session_data *sd)
{
struct mercenary_data *md;
int fd, i, len = 4, j;
@@ -16029,13 +18543,16 @@ void clif_mercenary_skillblock(struct map_session_data *sd)
WFIFOSET(fd,len);
}
-void clif_parse_mercenary_action(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_mercenary_action(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke a mercenary menu action (CZ_MER_COMMAND).
/// 029f <command>.B
/// 1 = mercenary information
/// 2 = delete
-void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
+static void clif_parse_mercenary_action(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int option = RFIFOB(fd,2);
if (sd->md == NULL)
return;
@@ -16050,36 +18567,42 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
/// 1 = Your mercenary soldier has been killed.
/// 2 = Your mercenary soldier has been fired.
/// 3 = Your mercenary soldier has ran away.
-void clif_mercenary_message(struct map_session_data* sd, int message)
+static void clif_mercenary_message(struct map_session_data *sd, int message)
{
- clif->msgtable(sd, MSG_MERCENARY_EXPIRED + message);
+#if PACKETVER >= 20070227
+ clif->msgtable(sd, MSG_MER_FINISH + message);
+#endif
}
/// Notification about the remaining time of a rental item (ZC_CASH_TIME_COUNTER).
/// 0298 <name id>.W <seconds>.L
-void clif_rental_time(int fd, int nameid, int seconds)
+static void clif_rental_time(int fd, int nameid, int seconds)
{ // '<ItemName>' item will disappear in <seconds/60> minutes.
- WFIFOHEAD(fd,packet_len(0x298));
- WFIFOW(fd,0) = 0x298;
- WFIFOW(fd,2) = nameid;
- WFIFOL(fd,4) = seconds;
- WFIFOSET(fd,packet_len(0x298));
+ struct PACKET_ZC_CASH_TIME_COUNTER p;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x298;
+ p.itemId = nameid;
+ p.seconds = seconds;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Deletes a rental item from client's inventory (ZC_CASH_ITEM_DELETE).
/// 0299 <index>.W <name id>.W
-void clif_rental_expired(int fd, int index, int nameid)
+static void clif_rental_expired(int fd, int index, int nameid)
{ // '<ItemName>' item has been deleted from the Inventory
- WFIFOHEAD(fd,packet_len(0x299));
- WFIFOW(fd,0) = 0x299;
- WFIFOW(fd,2) = index+2;
- WFIFOW(fd,4) = nameid;
- WFIFOSET(fd,packet_len(0x299));
+ struct PACKET_ZC_CASH_ITEM_DELETE p;
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x299;
+ p.index = index + 2;
+ p.itemId = nameid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Book Reading (ZC_READ_BOOK).
/// 0294 <book id>.L <page>.L
-void clif_readbook(int fd, int book_id, int page)
+static void clif_readbook(int fd, int book_id, int page)
{
WFIFOHEAD(fd,packet_len(0x294));
WFIFOW(fd,0) = 0x294;
@@ -16091,35 +18614,53 @@ void clif_readbook(int fd, int book_id, int page)
/// Battlegrounds
///
-/// Updates HP bar of a camp member (ZC_BATTLEFIELD_NOTIFY_HP).
-/// 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W
-void clif_bg_hp(struct map_session_data *sd)
+/// Updates HP bar of a camp member.
+/// 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W (ZC_BATTLEFIELD_NOTIFY_HP).
+/// 0a0e <account id>.L <hp>.L <max hp>.L (ZC_BATTLEFIELD_NOTIFY_HP2)
+static void clif_bg_hp(struct map_session_data *sd)
{
unsigned char buf[34];
+
+// packet version can be wrong, because inconsistend data in other servers. From packets table it start from 20140312 [4144]
+#if PACKETVER < 20140613
const int cmd = 0x2e0;
nullpo_retv(sd);
- WBUFW(buf,0) = cmd;
- WBUFL(buf,2) = sd->status.account_id;
- memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH);
+ WBUFW(buf, 0) = cmd;
+ WBUFL(buf, 2) = sd->status.account_id;
+ memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH);
- if( sd->battle_status.max_hp > INT16_MAX )
+ if (sd->battle_status.max_hp > INT16_MAX)
{ // To correctly display the %hp bar. [Skotlex]
- WBUFW(buf,30) = sd->battle_status.hp/(sd->battle_status.max_hp/100);
- WBUFW(buf,32) = 100;
+ WBUFW(buf, 30) = sd->battle_status.hp / (sd->battle_status.max_hp / 100);
+ WBUFW(buf, 32) = 100;
}
else
{
- WBUFW(buf,30) = sd->battle_status.hp;
- WBUFW(buf,32) = sd->battle_status.max_hp;
+ WBUFW(buf, 30) = sd->battle_status.hp;
+ WBUFW(buf, 32) = sd->battle_status.max_hp;
+ }
+#else
+ const int cmd = 0xa0e;
+ nullpo_retv(sd);
+
+ WBUFW(buf, 0) = cmd;
+ WBUFL(buf, 2) = sd->status.account_id;
+ if (sd->battle_status.max_hp > INT32_MAX) {
+ WBUFL(buf, 6) = sd->battle_status.hp / (sd->battle_status.max_hp / 100);
+ WBUFL(buf, 10) = 100;
+ } else {
+ WBUFL(buf, 6) = sd->battle_status.hp;
+ WBUFL(buf, 10) = sd->battle_status.max_hp;
}
+#endif
clif->send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS);
}
/// Updates the position of a camp member on the minimap (ZC_BATTLEFIELD_NOTIFY_POSITION).
/// 02df <account id>.L <name>.24B <class>.W <x>.W <y>.W
-void clif_bg_xy(struct map_session_data *sd)
+static void clif_bg_xy(struct map_session_data *sd)
{
unsigned char buf[36];
nullpo_retv(sd);
@@ -16127,14 +18668,14 @@ void clif_bg_xy(struct map_session_data *sd)
WBUFW(buf,0)=0x2df;
WBUFL(buf,2)=sd->status.account_id;
memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH);
- WBUFW(buf,30)=sd->status.class_;
+ WBUFW(buf,30)=sd->status.class;
WBUFW(buf,32)=sd->bl.x;
WBUFW(buf,34)=sd->bl.y;
clif->send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS);
}
-void clif_bg_xy_remove(struct map_session_data *sd)
+static void clif_bg_xy_remove(struct map_session_data *sd)
{
unsigned char buf[36];
nullpo_retv(sd);
@@ -16151,67 +18692,63 @@ void clif_bg_xy_remove(struct map_session_data *sd)
/// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT).
/// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B
-void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len)
+static void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes)
{
struct map_session_data *sd;
unsigned char *buf;
+ int len;
nullpo_retv(bgd);
nullpo_retv(name);
nullpo_retv(mes);
- if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL )
+
+ if (!bgd->count || (sd = bg->getavailablesd(bgd)) == NULL)
return;
- buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char));
+ len = (int)strlen(mes);
+ Assert_retv(len <= INT16_MAX - NAME_LENGTH - 9);
+ buf = (unsigned char *)aCalloc(len + NAME_LENGTH + 9, sizeof(unsigned char));
- WBUFW(buf,0) = 0x2dc;
- WBUFW(buf,2) = len + NAME_LENGTH + 8;
- WBUFL(buf,4) = src_id;
- memcpy(WBUFP(buf,8), name, NAME_LENGTH);
- memcpy(WBUFP(buf,32), mes, len);
- clif->send(buf,WBUFW(buf,2), &sd->bl, BG);
+ WBUFW(buf, 0) = 0x2dc;
+ WBUFW(buf, 2) = len + NAME_LENGTH + 9;
+ WBUFL(buf, 4) = src_id;
+ safestrncpy(WBUFP(buf, 8), name, NAME_LENGTH);
+ safestrncpy(WBUFP(buf, 32), mes, len + 1);
+ clif->send(buf, WBUFW(buf, 2), &sd->bl, BG);
aFree(buf);
}
-void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
-/// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_BattleChat(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
+ *
+ * @code
+ * 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+static void clif_parse_BattleChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BattleChat(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
-
- if( !pc->can_talk(sd) )
- return;
-
- if( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- bg->send_message(sd, text, textlen);
+ bg->send_message(sd, message);
}
/// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT).
/// 02de <camp A points>.W <camp B points>.W
-void clif_bg_updatescore(int16 m) {
+static void clif_bg_updatescore(int16 m)
+{
struct block_list bl;
unsigned char buf[6];
- bl.id = 0;
+ memset(&bl, 0, sizeof(bl));
bl.type = BL_NUL;
bl.m = m;
@@ -16221,7 +18758,8 @@ void clif_bg_updatescore(int16 m) {
clif->send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP);
}
-void clif_bg_updatescore_single(struct map_session_data *sd) {
+static void clif_bg_updatescore_single(struct map_session_data *sd)
+{
int fd;
nullpo_retv(sd);
fd = sd->fd;
@@ -16235,7 +18773,7 @@ void clif_bg_updatescore_single(struct map_session_data *sd) {
/// Battleground camp belong-information (ZC_BATTLEFIELD_NOTIFY_CAMPINFO).
/// 02dd <account id>.L <name>.24B <camp>.W
-void clif_sendbgemblem_area(struct map_session_data *sd)
+static void clif_sendbgemblem_area(struct map_session_data *sd)
{
unsigned char buf[33];
nullpo_retv(sd);
@@ -16247,7 +18785,7 @@ void clif_sendbgemblem_area(struct map_session_data *sd)
clif->send(buf,packet_len(0x2dd), &sd->bl, AREA);
}
-void clif_sendbgemblem_single(int fd, struct map_session_data *sd)
+static void clif_sendbgemblem_single(int fd, struct map_session_data *sd)
{
nullpo_retv(sd);
WFIFOHEAD(fd,32);
@@ -16260,7 +18798,7 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd)
/// Custom Fonts (ZC_NOTIFY_FONT).
/// 02ef <account_id>.L <font id>.W
-void clif_font(struct map_session_data *sd)
+static void clif_font(struct map_session_data *sd)
{
#if PACKETVER >= 20080102
unsigned char buf[8];
@@ -16275,7 +18813,8 @@ void clif_font(struct map_session_data *sd)
/*==========================================
* Instancing Window
*------------------------------------------*/
-int clif_instance(int instance_id, int type, int flag) {
+static int clif_instance(int instance_id, int type, int flag)
+{
struct map_session_data *sd = NULL;
unsigned char buf[255];
enum send_target target = PARTY;
@@ -16313,6 +18852,7 @@ int clif_instance(int instance_id, int type, int flag) {
case 2:
// S 0x2cc <Standby Position>.W
// To announce Instancing queue creation if no maps available
+ // flag is priority, negative value mean cancel reservation
WBUFW(buf,0) = 0x02CC;
WBUFW(buf,2) = flag;
clif->send(buf,packet_len(0x02CC),&sd->bl,target);
@@ -16347,7 +18887,7 @@ int clif_instance(int instance_id, int type, int flag) {
return 0;
}
-void clif_instance_join(int fd, int instance_id)
+static void clif_instance_join(int fd, int instance_id)
{
if( instance->list[instance_id].idle_timer != INVALID_TIMER ) {
WFIFOHEAD(fd,packet_len(0x02CD));
@@ -16372,7 +18912,7 @@ void clif_instance_join(int fd, int instance_id)
}
}
-void clif_instance_leave(int fd)
+static void clif_instance_leave(int fd)
{
WFIFOHEAD(fd,packet_len(0x02CE));
WFIFOW(fd,0) = 0x02ce;
@@ -16382,25 +18922,25 @@ void clif_instance_leave(int fd)
/// Notifies clients about item picked up by a party member (ZC_ITEM_PICKUP_PARTY).
/// 02b8 <account id>.L <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B
-void clif_party_show_picker(struct map_session_data * sd, struct item * item_data)
+static void clif_party_show_picker(struct map_session_data *sd, struct item *item_data)
{
#if PACKETVER >= 20071002
- unsigned char buf[22];
struct item_data* id;
+ struct PACKET_ZC_ITEM_PICKUP_PARTY p;
nullpo_retv(sd);
nullpo_retv(item_data);
id = itemdb->search(item_data->nameid);
- WBUFW(buf,0) = 0x2b8;
- WBUFL(buf,2) = sd->status.account_id;
- WBUFW(buf,6) = item_data->nameid;
- WBUFB(buf,8) = item_data->identify;
- WBUFB(buf,9) = item_data->attribute;
- WBUFB(buf,10) = item_data->refine;
- clif->addcards(WBUFP(buf,11), item_data);
- WBUFW(buf,19) = id->equip; // equip location
- WBUFB(buf,21) = itemtype(id->type); // item type
- clif->send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS);
+ p.packetType = 0x2b8;
+ p.AID = sd->status.account_id;
+ p.itemId = item_data->nameid;
+ p.identified = item_data->identify;
+ p.damaged = item_data->attribute;
+ p.refine = item_data->refine;
+ clif->addcards(&p.slot, item_data);
+ p.location = id->equip; // equip location
+ p.itemType = itemtype(id->type); // item type
+ clif->send(&p, sizeof(p), &sd->bl, PARTY_SAMEMAP_WOS);
#endif
}
@@ -16411,20 +18951,32 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
/// exp type:
/// 0 = normal exp gain/loss
/// 1 = quest exp gain/loss
-void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool is_quest) {
+static void clif_displayexp(struct map_session_data *sd, uint64 exp, char type, bool is_quest)
+{
int fd;
+#if PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+ const int cmd = 0xacc;
+#else
+ const int cmd = 0x7f6;
+#endif
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd, packet_len(0x7f6));
- WFIFOW(fd,0) = 0x7f6;
- WFIFOL(fd,2) = sd->bl.id;
- WFIFOL(fd,6) = exp;
- WFIFOW(fd,10) = type;
- WFIFOW(fd,12) = is_quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple.
- WFIFOSET(fd,packet_len(0x7f6));
+ WFIFOHEAD(fd, packet_len(cmd));
+ WFIFOW(fd, 0) = cmd;
+ WFIFOL(fd, 2) = sd->bl.id;
+#if PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+ WFIFOQ(fd, 6) = exp;
+ WFIFOW(fd, 14) = type;
+ WFIFOW(fd, 16) = is_quest ? 1 : 0; // Normal exp is shown in yellow, quest exp is shown in purple.
+#else
+ WFIFOL(fd, 6) = (uint32)exp;
+ WFIFOW(fd, 10) = type;
+ WFIFOW(fd, 12) = is_quest ? 1 : 0; // Normal exp is shown in yellow, quest exp is shown in purple.
+#endif
+ WFIFOSET(fd, packet_len(cmd));
}
/// Displays digital clock digits on top of the screen (ZC_SHOWDIGIT).
@@ -16435,7 +18987,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b
/// 3 = Decremental counter (1 tick/second), 'value' specifies start value (stops when reaching 0, displays at most 2 digits).
/// value:
/// Except for type 3 it is interpreted as seconds for displaying as DD:HH:MM:SS, HH:MM:SS, MM:SS or SS (leftmost '00' is not displayed).
-void clif_showdigit(struct map_session_data* sd, unsigned char type, int value)
+static void clif_showdigit(struct map_session_data *sd, unsigned char type, int value)
{
nullpo_retv(sd);
WFIFOHEAD(sd->fd, packet_len(0x1b1));
@@ -16445,7 +18997,7 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value)
WFIFOSET(sd->fd, packet_len(0x1b1));
}
-void clif_parse_LessEffect(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_LessEffect(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Notification of the state of client command /effect (CZ_LESSEFFECT).
/// 021d <state>.L
/// state:
@@ -16458,18 +19010,21 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd) __attribute__((n
/// constructed, this state tracking was rendered useless,
/// as the only skill unit, that is sent with 0x1c9 is
/// Graffiti.
-void clif_parse_LessEffect(int fd, struct map_session_data* sd)
+static void clif_parse_LessEffect(int fd, struct map_session_data *sd)
{
int isLess = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
sd->state.lesseffect = ( isLess != 0 );
}
-void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b*
-void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd)
+static void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd)
{
- int n = ((int)RFIFOW(fd,2) - 12) / 4;
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int n = ((int)RFIFOW(fd, 2) - 12) / 4;
int type = RFIFOL(fd,4);
int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK
struct itemlist item_list = { 0 };
@@ -16483,8 +19038,8 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd)
return; // Canceled by player.
}
- if (n > MAX_INVENTORY)
- n = MAX_INVENTORY; // It should be impossible to have more than that.
+ if (n > sd->status.inventorySize)
+ n = sd->status.inventorySize; // It should be impossible to have more than that.
if (sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL) {
clif_menuskill_clear(sd);
@@ -16518,7 +19073,8 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd)
/*==========================================
* Elemental System
*==========================================*/
-void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
+static void clif_elemental_updatestatus(struct map_session_data *sd, int type)
+{
struct elemental_data *ed;
struct status_data *estatus;
int fd;
@@ -16548,7 +19104,8 @@ void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
WFIFOSET(fd,8);
}
-void clif_elemental_info(struct map_session_data *sd) {
+static void clif_elemental_info(struct map_session_data *sd)
+{
int fd;
struct elemental_data *ed;
struct status_data *estatus;
@@ -16574,8 +19131,9 @@ void clif_elemental_info(struct map_session_data *sd) {
/// Opens preparation window for buying store (ZC_OPEN_BUYING_STORE).
/// 0810 <slots>.B
-void clif_buyingstore_open(struct map_session_data* sd)
+static void clif_buyingstore_open(struct map_session_data *sd)
{
+#if PACKETVER >= 20100303
int fd;
nullpo_retv(sd);
@@ -16584,46 +19142,54 @@ void clif_buyingstore_open(struct map_session_data* sd)
WFIFOW(fd,0) = 0x810;
WFIFOB(fd,2) = sd->buyingstore.slots;
WFIFOSET(fd,packet_len(0x810));
+#endif
}
-void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to create a buying store (CZ_REQ_OPEN_BUYING_STORE).
/// 0811 <packet len>.W <limit zeny>.L <result>.B <store name>.80B { <name id>.W <amount>.W <price>.L }*
/// result:
/// 0 = cancel
/// 1 = open
-void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) {
- const unsigned int blocksize = 8;
- const uint8 *itemlist;
+static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data *sd)
+{
+ if (pc_istrading(sd) || pc_isdead(sd))
+ return;
+
+ const unsigned int blocksize = sizeof(struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub);
+ const struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub *itemlist;
char storename[MESSAGE_SIZE];
unsigned char result;
int zenylimit;
- unsigned int count, packet_len;
- struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
+ int count, packet_len;
+ const struct PACKET_CZ_REQ_OPEN_BUYING_STORE *p = RFIFOP(fd, 0);
- packet_len = RFIFOW(fd,info->pos[0]);
+ packet_len = p->packetLength;
// TODO: Make this check global for all variable length packets.
- if( packet_len < 89 )
+ if (packet_len < sizeof(struct PACKET_CZ_REQ_OPEN_BUYING_STORE))
{// minimum packet length
- ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89U, packet_len, sd->bl.id);
+ ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%d, account_id=%d).\n", (uint32)sizeof(struct PACKET_CZ_REQ_OPEN_BUYING_STORE), packet_len, sd->bl.id);
return;
}
- zenylimit = RFIFOL(fd,info->pos[1]);
- result = RFIFOL(fd,info->pos[2]);
- safestrncpy(storename, RFIFOP(fd,info->pos[3]), sizeof(storename));
- itemlist = RFIFOP(fd,info->pos[4]);
+ zenylimit = p->zenyLimit;
+ result = p->result;
+ safestrncpy(storename, p->storeName, sizeof(storename));
+ itemlist = &p->items[0];
// so that buyingstore_create knows, how many elements it has access to
- packet_len-= info->pos[4];
+ packet_len -= sizeof(struct PACKET_CZ_REQ_OPEN_BUYING_STORE);
- if( packet_len%blocksize )
+ if (packet_len < 0)
+ return;
+
+ if (packet_len % blocksize)
{
- ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
+ ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %d (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
return;
}
- count = packet_len/blocksize;
+ count = packet_len / blocksize;
buyingstore->create(sd, zenylimit, result, storename, itemlist, count);
}
@@ -16633,10 +19199,12 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) {
/// result:
/// 1 = "Failed to open buying store." (0x6cd, MSI_BUYINGSTORE_OPEN_FAILED)
/// 2 = "Total amount of then possessed items exceeds the weight limit by <weight/10-maxweight*90%>. Please re-enter." (0x6ce, MSI_BUYINGSTORE_OVERWEIGHT)
-/// 8 = "No sale (purchase) information available." (0x705)
+/// 9 = "No sale (purchase) information available." (0x705)
+/// 10 = "Cant open store at this location." (0xC9D)
/// ? = nothing
-void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight)
+static void clif_buyingstore_open_failed(struct map_session_data *sd, unsigned short result, unsigned int weight)
{
+#if PACKETVER >= 20100420
int fd;
nullpo_retv(sd);
@@ -16646,38 +19214,44 @@ void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short re
WFIFOW(fd,2) = result;
WFIFOL(fd,4) = weight;
WFIFOSET(fd,packet_len(0x812));
+#endif
}
/// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE).
/// 0813 <packet len>.W <account id>.L <limit zeny>.L { <price>.L <count>.W <type>.B <name id>.W }*
-void clif_buyingstore_myitemlist(struct map_session_data* sd)
+static void clif_buyingstore_myitemlist(struct map_session_data *sd)
{
int fd;
unsigned int i;
+ struct PACKET_ZC_MYITEMLIST_BUYING_STORE *p;
+ int len;
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd,12+sd->buyingstore.slots*9);
- WFIFOW(fd,0) = 0x813;
- WFIFOW(fd,2) = 12+sd->buyingstore.slots*9;
- WFIFOL(fd,4) = sd->bl.id;
- WFIFOL(fd,8) = sd->buyingstore.zenylimit;
+ len = sizeof(struct PACKET_ZC_MYITEMLIST_BUYING_STORE) + sd->buyingstore.slots * sizeof(struct PACKET_ZC_MYITEMLIST_BUYING_STORE_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x813;
+ p->packetLength = len;
+ p->AID = sd->bl.id;
+ p->zenyLimit = sd->buyingstore.zenylimit;
- for( i = 0; i < sd->buyingstore.slots; i++ )
+ for (i = 0; i < sd->buyingstore.slots; i++)
{
- WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price;
- WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount;
- WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid));
- WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid;
+ p->items[i].price = sd->buyingstore.items[i].price;
+ p->items[i].amount = sd->buyingstore.items[i].amount;
+ p->items[i].itemType = itemtype(itemdb_type(sd->buyingstore.items[i].nameid));
+ p->items[i].itemId = sd->buyingstore.items[i].nameid;
}
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
/// Notifies clients in area of a buying store (ZC_BUYING_STORE_ENTRY).
/// 0814 <account id>.L <store name>.80B
-void clif_buyingstore_entry(struct map_session_data* sd)
+static void clif_buyingstore_entry(struct map_session_data *sd)
{
+#if PACKETVER >= 20100420
uint8 buf[86];
nullpo_retv(sd);
@@ -16686,9 +19260,11 @@ void clif_buyingstore_entry(struct map_session_data* sd)
memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE);
clif->send(buf, packet_len(0x814), &sd->bl, AREA_WOS);
+#endif
}
-void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
+static void clif_buyingstore_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd)
{
+#if PACKETVER >= 20100420
int fd;
nullpo_retv(sd);
@@ -16698,19 +19274,22 @@ void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_sessi
WFIFOL(fd,2) = pl_sd->bl.id;
memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE);
WFIFOSET(fd,packet_len(0x814));
+#endif
}
-void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE).
/// 0815
-void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) {
+static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data *sd)
+{
buyingstore->close(sd);
}
/// Notifies clients in area that a buying store was closed (ZC_DISAPPEAR_BUYING_STORE_ENTRY).
/// 0816 <account id>.L
-void clif_buyingstore_disappear_entry(struct map_session_data* sd)
+static void clif_buyingstore_disappear_entry(struct map_session_data *sd)
{
+#if PACKETVER >= 20100309
uint8 buf[6];
nullpo_retv(sd);
@@ -16718,9 +19297,12 @@ void clif_buyingstore_disappear_entry(struct map_session_data* sd)
WBUFL(buf,2) = sd->bl.id;
clif->send(buf, packet_len(0x816), &sd->bl, AREA_WOS);
+#endif
}
-void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd)
+
+static void clif_buyingstore_disappear_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd)
{
+#if PACKETVER >= 20100309
int fd;
nullpo_retv(sd);
@@ -16730,12 +19312,16 @@ void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct
WFIFOW(fd,0) = 0x816;
WFIFOL(fd,2) = pl_sd->bl.id;
WFIFOSET(fd,packet_len(0x816));
+#endif
}
/// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE).
/// 0817 <account id>.L
-void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd)
+static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
int account_id;
account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
@@ -16745,63 +19331,73 @@ void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd)
/// Sends buying store item list (ZC_ACK_ITEMLIST_BUYING_STORE).
/// 0818 <packet len>.W <account id>.L <store id>.L <limit zeny>.L { <price>.L <amount>.W <type>.B <name id>.W }*
-void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd)
+static void clif_buyingstore_itemlist(struct map_session_data *sd, struct map_session_data *pl_sd)
{
int fd;
unsigned int i;
+ struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE *p;
+ int len;
nullpo_retv(sd);
nullpo_retv(pl_sd);
fd = sd->fd;
- WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9);
- WFIFOW(fd,0) = 0x818;
- WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9;
- WFIFOL(fd,4) = pl_sd->bl.id;
- WFIFOL(fd,8) = pl_sd->buyer_id;
- WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit;
-
- for( i = 0; i < pl_sd->buyingstore.slots; i++ )
+ len = sizeof(struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE) + pl_sd->buyingstore.slots * sizeof(struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE_sub);
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x818;
+ p->packetLength = len;
+ p->AID = pl_sd->bl.id;
+ p->storeId = pl_sd->buyer_id;
+ p->zenyLimit = pl_sd->buyingstore.zenylimit;
+
+ for (i = 0; i < pl_sd->buyingstore.slots; i++)
{
- WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price;
- WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official.
- WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid));
- WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid;
+ p->items[i].price = pl_sd->buyingstore.items[i].price;
+ p->items[i].amount = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official.
+ p->items[i].itemType = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid));
+ p->items[i].itemId = pl_sd->buyingstore.items[i].nameid;
}
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
-void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE).
/// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }*
-void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) {
- const unsigned int blocksize = 6;
- const uint8 *itemlist;
- int account_id;
- unsigned int count, packet_len, buyer_id;
- struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
+static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- packet_len = RFIFOW(fd,info->pos[0]);
+ const unsigned int blocksize = sizeof(struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub);
+ const struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub *itemlist;
+ int account_id;
+ unsigned int buyer_id;
+ int count, packet_len;
+ const struct PACKET_CZ_REQ_TRADE_BUYING_STORE *p = RFIFOP(fd, 0);
+ packet_len = p->packetLength;
- if( packet_len < 12 )
+ if (packet_len < sizeof(struct PACKET_CZ_REQ_TRADE_BUYING_STORE))
{// minimum packet length
- ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12U, packet_len, sd->bl.id);
+ ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%d, account_id=%d).\n", (uint32)sizeof(struct PACKET_CZ_REQ_TRADE_BUYING_STORE), packet_len, sd->bl.id);
return;
}
- account_id = RFIFOL(fd,info->pos[1]);
- buyer_id = RFIFOL(fd,info->pos[2]);
- itemlist = RFIFOP(fd,info->pos[3]);
+ account_id = p->AID;
+ buyer_id = p->storeId;
+ itemlist = &p->items[0];
// so that buyingstore_trade knows, how many elements it has access to
- packet_len-= info->pos[3];
+ packet_len -= sizeof(struct PACKET_CZ_REQ_TRADE_BUYING_STORE);
+ if (packet_len < 0)
+ return;
- if( packet_len%blocksize )
+ if (packet_len % blocksize)
{
- ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize);
+ ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %d (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize);
return;
}
- count = packet_len/blocksize;
+ count = packet_len / blocksize;
buyingstore->trade(sd, account_id, buyer_id, itemlist, count);
}
@@ -16812,8 +19408,9 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) {
/// 3 = "All items within the buy limit were purchased." (0x6cf, MSI_BUYINGSTORE_TRADE_OVERLIMITZENY)
/// 4 = "All items were purchased." (0x6d0, MSI_BUYINGSTORE_TRADE_BUYCOMPLETE)
/// ? = nothing
-void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result)
+static void clif_buyingstore_trade_failed_buyer(struct map_session_data *sd, short result)
{
+#if PACKETVER >= 20100420
int fd;
nullpo_retv(sd);
@@ -16822,22 +19419,31 @@ void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short resu
WFIFOW(fd,0) = 0x81a;
WFIFOW(fd,2) = result;
WFIFOSET(fd,packet_len(0x81a));
+#endif
}
/// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE).
/// 081b <name id>.W <amount>.W <limit zeny>.L
-void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount)
+static void clif_buyingstore_update_item(struct map_session_data *sd, int nameid, unsigned short amount, uint32 char_id, int zeny)
{
int fd;
+ struct PACKET_ZC_UPDATE_ITEM_FROM_BUYING_STORE p;
nullpo_retv(sd);
+
fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x81b));
- WFIFOW(fd,0) = 0x81b;
- WFIFOW(fd,2) = nameid;
- WFIFOW(fd,4) = amount; // amount of nameid received
- WFIFOL(fd,6) = sd->buyingstore.zenylimit;
- WFIFOSET(fd,packet_len(0x81b));
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = buyingStoreUpdateItemType;
+ p.itemId = nameid;
+ p.amount = amount;
+ p.zenyLimit = sd->buyingstore.zenylimit;
+#if PACKETVER >= 20141016
+ p.zeny = zeny;
+ p.charId = char_id; // GID
+ p.updateTime = (int)time(NULL);
+#endif
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
}
/// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE).
@@ -16846,8 +19452,9 @@ void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short na
/// "%s (%d) were sold at %dz." (0x6d2, MSI_BUYINGSTORE_TRADE_SELLCOMPLETE)
///
/// NOTE: This function has to be called _instead_ of clif_delitem/clif_dropitem.
-void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price)
+static void clif_buyingstore_delete_item(struct map_session_data *sd, short index, unsigned short amount, int price)
{
+#if PACKETVER >= 20100420
int fd;
nullpo_retv(sd);
@@ -16858,6 +19465,7 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi
WFIFOW(fd,4) = amount;
WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself
WFIFOSET(fd,packet_len(0x81c));
+#endif
}
/// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER).
@@ -16867,20 +19475,24 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi
/// 6 = "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." (0x6d3, MSI_BUYINGSTORE_TRADE_OVERCOUNT)
/// 7 = "The trade failed, because the buyer is lacking required balance." (0x6d1, MSI_BUYINGSTORE_TRADE_LACKBUYERZENY)
/// ? = nothing
-void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid)
+static void clif_buyingstore_trade_failed_seller(struct map_session_data *sd, short result, int nameid)
{
+#if PACKETVER >= 20100420
int fd;
+ struct PACKET_ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER p;
nullpo_retv(sd);
fd = sd->fd;
- WFIFOHEAD(fd,packet_len(0x824));
- WFIFOW(fd,0) = 0x824;
- WFIFOW(fd,2) = result;
- WFIFOW(fd,4) = nameid;
- WFIFOSET(fd,packet_len(0x824));
+ WFIFOHEAD(fd, sizeof(p));
+ p.packetType = 0x824;
+ p.result = result;
+ p.itemId = nameid;
+ memcpy(WFIFOP(fd, 0), &p, sizeof(p));
+ WFIFOSET(fd, sizeof(p));
+#endif
}
-void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_SearchStoreInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Search Store Info System
///
@@ -16893,47 +19505,70 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) __attribute
/// NOTE: The client determines the item ids by specifying a name and optionally,
/// amount of card slots. If the client does not know about the item it
/// cannot be searched.
-void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) {
- const unsigned int blocksize = 2;
- const uint8* itemlist;
- const uint8* cardlist;
+static void clif_parse_SearchStoreInfo(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const unsigned int blocksize = sizeof(struct PACKET_CZ_SEARCH_STORE_INFO_item);
+ const struct PACKET_CZ_SEARCH_STORE_INFO_item* itemlist;
+ const struct PACKET_CZ_SEARCH_STORE_INFO_item* cardlist;
unsigned char type;
- unsigned int min_price, max_price, packet_len, count, item_count, card_count;
- struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
+ unsigned int min_price, max_price;
+ int packet_len, count, item_count, card_count;
+ int i;
+ const struct PACKET_CZ_SEARCH_STORE_INFO *p = RFIFOP(fd, 0);
+ uint32 *items_list;
+ uint32 *cards_list;
- packet_len = RFIFOW(fd,info->pos[0]);
+ packet_len = p->packetLength;
- if( packet_len < 15 )
+ if (packet_len < sizeof(struct PACKET_CZ_SEARCH_STORE_INFO))
{// minimum packet length
- ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15U, packet_len, sd->bl.id);
+ ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%d, account_id=%d).\n", (uint32)sizeof(struct PACKET_CZ_SEARCH_STORE_INFO), packet_len, sd->bl.id);
return;
}
- type = RFIFOB(fd,info->pos[1]);
- max_price = RFIFOL(fd,info->pos[2]);
- min_price = RFIFOL(fd,info->pos[3]);
- item_count = RFIFOB(fd,info->pos[4]);
- card_count = RFIFOB(fd,info->pos[5]);
- itemlist = RFIFOP(fd,info->pos[6]);
- cardlist = RFIFOP(fd,info->pos[6]+blocksize*item_count);
+ type = p->searchType;
+ max_price = p->maxPrice;
+ min_price = p->minPrice;
+ item_count = p->itemsCount;
+ card_count = p->cardsCount;
+ itemlist = &p->items[0];
// check, if there is enough data for the claimed count of items
- packet_len-= info->pos[6];
+ packet_len -= sizeof(struct PACKET_CZ_SEARCH_STORE_INFO);
- if( packet_len%blocksize )
+ if (packet_len < 0)
+ return;
+
+ if (packet_len % blocksize)
{
- ShowError("clif_parse_SearchStoreInfo: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
+ ShowError("clif_parse_SearchStoreInfo: Unexpected item list size %d (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize);
return;
}
- count = packet_len/blocksize;
+ count = packet_len / blocksize;
- if( count < item_count+card_count )
+ if (count < item_count + card_count)
{
- ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected count=%u, count=%u, account_id=%d).\n", item_count+card_count, count, sd->bl.id);
+ ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected count=%d, count=%d, account_id=%d).\n", item_count + card_count, count, sd->bl.id);
return;
}
- searchstore->query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count);
+ cardlist = RFIFOP(fd, sizeof(struct PACKET_CZ_SEARCH_STORE_INFO) + blocksize * item_count);
+
+ items_list = aMalloc(sizeof(uint32) * item_count);
+ cards_list = aMalloc(sizeof(uint32) * card_count);
+ for (i = 0; i < item_count; i ++) {
+ items_list[i] = itemlist[i].itemId;
+ }
+ for (i = 0; i < card_count; i ++) {
+ cards_list[i] = cardlist[i].itemId;
+ }
+ // TODO: add search by item options.
+ searchstore->query(sd, type, min_price, max_price, items_list, item_count, cards_list, card_count);
+ aFree(items_list);
+ aFree(cards_list);
}
/// Results for a store search request (ZC_SEARCH_STORE_INFO_ACK).
@@ -16944,36 +19579,40 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) {
/// is next page:
/// 0 = no "next" label
/// 1 = "next" label to retrieve more results
-void clif_search_store_info_ack(struct map_session_data* sd)
+static void clif_search_store_info_ack(struct map_session_data *sd)
{
- const unsigned int blocksize = MESSAGE_SIZE+26;
+ const unsigned int blocksize = sizeof(struct PACKET_ZC_SEARCH_STORE_INFO_ACK_sub);
int fd;
unsigned int i, start, end;
+ struct PACKET_ZC_SEARCH_STORE_INFO_ACK *p;
+ int len;
nullpo_retv(sd);
fd = sd->fd;
- start = sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE;
- end = min(sd->searchstore.count, start+SEARCHSTORE_RESULTS_PER_PAGE);
-
- WFIFOHEAD(fd,7+(end-start)*blocksize);
- WFIFOW(fd,0) = 0x836;
- WFIFOW(fd,2) = 7+(end-start)*blocksize;
- WFIFOB(fd,4) = !sd->searchstore.pages;
- WFIFOB(fd,5) = searchstore->querynext(sd);
- WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX);
+ start = sd->searchstore.pages * SEARCHSTORE_RESULTS_PER_PAGE;
+ end = min(sd->searchstore.count, start + SEARCHSTORE_RESULTS_PER_PAGE);
- for( i = start; i < end; i++ ) {
+ len = sizeof(struct PACKET_ZC_SEARCH_STORE_INFO_ACK) + (end - start) * blocksize;
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x836;
+ p->packetLength = len;
+ p->firstPage = !sd->searchstore.pages;
+ p->nextPage = searchstore->querynext(sd);
+ p->usesCount = (unsigned char)min(sd->searchstore.uses, UINT8_MAX);
+
+ for (i = start; i < end; i++) {
struct s_search_store_info_item* ssitem = &sd->searchstore.items[i];
struct item it;
- WFIFOL(fd,i*blocksize+ 7) = ssitem->store_id;
- WFIFOL(fd,i*blocksize+11) = ssitem->account_id;
- memcpy(WFIFOP(fd,i*blocksize+15), ssitem->store_name, MESSAGE_SIZE);
- WFIFOW(fd,i*blocksize+15+MESSAGE_SIZE) = ssitem->nameid;
- WFIFOB(fd,i*blocksize+17+MESSAGE_SIZE) = itemtype(itemdb_type(ssitem->nameid));
- WFIFOL(fd,i*blocksize+18+MESSAGE_SIZE) = ssitem->price;
- WFIFOW(fd,i*blocksize+22+MESSAGE_SIZE) = ssitem->amount;
- WFIFOB(fd,i*blocksize+24+MESSAGE_SIZE) = ssitem->refine;
+ p->items[i].storeId = ssitem->store_id;
+ p->items[i].AID = ssitem->account_id;
+ memcpy(&p->items[i].shopName, ssitem->store_name, MESSAGE_SIZE);
+ p->items[i].itemId = ssitem->nameid;
+ p->items[i].itemType = itemtype(itemdb_type(ssitem->nameid));
+ p->items[i].price = ssitem->price;
+ p->items[i].amount = ssitem->amount;
+ p->items[i].refine = ssitem->refine;
// make-up an item for clif_addcards
memset(&it, 0, sizeof(it));
@@ -16981,10 +19620,14 @@ void clif_search_store_info_ack(struct map_session_data* sd)
it.nameid = ssitem->nameid;
it.amount = ssitem->amount;
- clif->addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it);
+ clif->addcards(&p->items[i].slot, &it);
+#if PACKETVER >= 20150226
+ memcpy(&it.option, &ssitem->option, sizeof(it.option));
+ clif->add_item_options(&p->items[i].option_data[0], &it);
+#endif
}
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOSET(fd, len);
}
/// Notification of failure when searching for stores (ZC_SEARCH_STORE_INFO_FAILED).
@@ -16995,8 +19638,10 @@ void clif_search_store_info_ack(struct map_session_data* sd)
/// 2 = "You cannot search anymore." (0x706)
/// 3 = "You cannot search yet." (0x708)
/// 4 = "No sale (purchase) information available." (0x705)
-void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason)
+/// 362 = silent error
+static void clif_search_store_info_failed(struct map_session_data *sd, unsigned char reason)
{
+#if PACKETVER >= 20100601
int fd;
nullpo_retv(sd);
@@ -17005,13 +19650,17 @@ void clif_search_store_info_failed(struct map_session_data* sd, unsigned char re
WFIFOW(fd,0) = 0x837;
WFIFOB(fd,2) = reason;
WFIFOSET(fd,packet_len(0x837));
+#endif
}
-void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to display next page of results (CZ_SEARCH_STORE_INFO_NEXT_PAGE).
/// 0838
-void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd)
+static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
searchstore->next(sd);
}
@@ -17020,8 +19669,9 @@ void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd)
/// type:
/// 0 = Search Stores
/// 1 = Search Stores (Cash), asks for confirmation, when clicking a store
-void clif_open_search_store_info(struct map_session_data* sd)
+static void clif_open_search_store_info(struct map_session_data *sd)
{
+#if PACKETVER >= 20100608
int fd;
nullpo_retv(sd);
@@ -17033,36 +19683,34 @@ void clif_open_search_store_info(struct map_session_data* sd)
WFIFOB(fd,4) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX);
#endif
WFIFOSET(fd,packet_len(0x83a));
+#endif
}
-void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to close the store search window (CZ_CLOSE_SEARCH_STORE_INFO).
/// 083b
-void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd)
+static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data *sd)
{
searchstore->close(sd);
}
-void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Request to invoke catalog effect on a store from search results (CZ_SSILIST_ITEM_CLICK).
/// 083c <account id>.L <store id>.L <nameid>.W
-void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd)
+static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data *sd)
{
- unsigned short nameid;
- int account_id, store_id;
- struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
-
- account_id = RFIFOL(fd,info->pos[0]);
- store_id = RFIFOL(fd,info->pos[1]);
- nameid = RFIFOW(fd,info->pos[2]);
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- searchstore->click(sd, account_id, store_id, nameid);
+ const struct PACKET_CZ_SSILIST_ITEM_CLICK *p = RFIFOP(fd, 0);
+ searchstore->click(sd, p->AID, p->storeId, p->itemId);
}
/// Notification of the store position on current map (ZC_SSILIST_ITEM_CLICK_ACK).
/// 083d <xPos>.W <yPos>.W
-void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y)
+static void clif_search_store_info_click_ack(struct map_session_data *sd, short x, short y)
{
+#if PACKETVER >= 20100608
int fd;
nullpo_retv(sd);
@@ -17072,17 +19720,19 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor
WFIFOW(fd,2) = x;
WFIFOW(fd,4) = y;
WFIFOSET(fd,packet_len(0x83d));
+#endif
}
/// Parse function for packet debugging.
-void clif_parse_debug(int fd,struct map_session_data *sd) {
+static void clif_parse_debug(int fd, struct map_session_data *sd)
+{
int cmd, packet_len;
// clif_parse ensures, that there is at least 2 bytes of data
cmd = RFIFOW(fd,0);
if( sd ) {
- packet_len = packet_db[cmd].len;
+ packet_len = packets->db[cmd];
if( packet_len == -1 ) {// variable length
packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received
@@ -17099,28 +19749,32 @@ 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 available elemental converter options according to player's inventory
*------------------------------------------*/
-int clif_elementalconverter_list(struct map_session_data *sd) {
- int i,c,view,fd;
-
+static int clif_elementalconverter_list(struct map_session_data *sd)
+{
nullpo_ret(sd);
/// Main client packet processing function
- fd=sd->fd;
- WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB *2+4);
- WFIFOW(fd, 0)=0x1ad;
-
- for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,23, 1) ){
- if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
- WFIFOW(fd,c*2+ 4)= view;
+ int fd = sd->fd;
+ int len = MAX_SKILL_ARROW_DB * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MAKINGARROW_LIST *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGARROW_LIST;
+
+ int c = 0;
+ for (int i = 0; i < MAX_SKILL_PRODUCE_DB; i++) {
+ if (skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,23, 1) ) {
+ int view = itemdb_viewid(skill->dbs->produce_db[i].nameid);
+ if (view > 0)
+ p->items[c].itemId = view;
else
- WFIFOW(fd,c*2+ 4)= skill->dbs->produce_db[i].nameid;
+ p->items[c].itemId = skill->dbs->produce_db[i].nameid;
c++;
}
}
- WFIFOW(fd,2) = c*2+4;
- WFIFOSET(fd, WFIFOW(fd,2));
if (c > 0) {
+ len = c * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
sd->menuskill_id = SA_CREATECON;
sd->menuskill_val = c;
}
@@ -17130,7 +19784,8 @@ int clif_elementalconverter_list(struct map_session_data *sd) {
/**
* Rune Knight
**/
-void clif_millenniumshield(struct block_list *bl, short shields ) {
+static void clif_millenniumshield(struct block_list *bl, short shields)
+{
#if PACKETVER >= 20081217
unsigned char buf[10];
@@ -17148,36 +19803,36 @@ void clif_millenniumshield(struct block_list *bl, short shields ) {
/*==========================================
* Spellbook list [LimitLine/3CeAM]
*------------------------------------------*/
-int clif_spellbook_list(struct map_session_data *sd)
+static int clif_spellbook_list(struct map_session_data *sd)
{
- int i, c;
- int fd;
-
nullpo_ret(sd);
- fd = sd->fd;
- WFIFOHEAD(fd, 8 * 8 + 8);
- WFIFOW(fd,0) = 0x1ad;
+ int fd = sd->fd;
+ int len = MAX_SKILL_ARROW_DB * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MAKINGARROW_LIST *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGARROW_LIST;
- for( i = 0, c = 0; i < MAX_INVENTORY; i ++ )
+ int c = 0;
+ for (int i = 0; i < sd->status.inventorySize; i ++ )
{
- if( itemdb_is_spellbook(sd->status.inventory[i].nameid) )
+ if (itemdb_is_spellbook(sd->status.inventory[i].nameid))
{
- WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid;
+ p->items[c].itemId = sd->status.inventory[i].nameid;
c++;
}
}
- if( c > 0 )
+ if (c > 0)
{
- WFIFOW(fd,2) = c * 2 + 4;
- WFIFOSET(fd, WFIFOW(fd, 2));
+ len = c * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
sd->menuskill_id = WL_READING_SB;
sd->menuskill_val = c;
- }
- else{
- status_change_end(&sd->bl,SC_STOP,INVALID_TIMER);
- clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0);
+ } else {
+ status_change_end(&sd->bl, SC_STOP, INVALID_TIMER);
+ clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0, 0);
}
return 1;
@@ -17188,19 +19843,21 @@ int clif_spellbook_list(struct map_session_data *sd)
/*==========================================
* Magic Decoy Material List
*------------------------------------------*/
-int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, short y) {
+static int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, short y)
+{
int i, c;
- int fd;
nullpo_ret(sd);
- fd = sd->fd;
- WFIFOHEAD(fd, 8 * 8 + 8);
- WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil]
+ int fd = sd->fd;
+ int len = MAX_SKILL_ARROW_DB * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MAKINGARROW_LIST *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGARROW_LIST;
- for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) {
- if( itemdb_is_element(sd->status.inventory[i].nameid) ) {
- WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid;
+ for (i = 0, c = 0; i < sd->status.inventorySize; i ++) {
+ if (itemdb_is_element(sd->status.inventory[i].nameid)) {
+ p->items[c].itemId = sd->status.inventory[i].nameid;
c ++;
}
}
@@ -17209,10 +19866,12 @@ int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x,
sd->menuskill_val = skill_lv;
sd->sc.comet_x = x;
sd->sc.comet_y = y;
- WFIFOW(fd,2) = c * 2 + 4;
- WFIFOSET(fd, WFIFOW(fd, 2));
+
+ len = c * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
} else {
- clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, NC_MAGICDECOY, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
@@ -17224,35 +19883,40 @@ int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x,
/*==========================================
* Guillotine Cross Poisons List
*------------------------------------------*/
-int clif_poison_list(struct map_session_data *sd, uint16 skill_lv) {
+static int clif_poison_list(struct map_session_data *sd, uint16 skill_lv)
+{
int i, c;
- int fd;
nullpo_ret(sd);
- fd = sd->fd;
- WFIFOHEAD(fd, 8 * 8 + 8);
- WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil]
+ int fd = sd->fd;
+ int len = MAX_SKILL_ARROW_DB * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MAKINGARROW_LIST *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MAKINGARROW_LIST;
- for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) {
+ for (i = 0, c = 0; i < sd->status.inventorySize; i ++) {
if( itemdb_is_poison(sd->status.inventory[i].nameid) ) {
- WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid;
+ p->items[c].itemId = sd->status.inventory[i].nameid;
c ++;
}
}
- if( c > 0 ) {
+ if (c > 0) {
sd->menuskill_id = GC_POISONINGWEAPON;
sd->menuskill_val = skill_lv;
- WFIFOW(fd,2) = c * 2 + 4;
- WFIFOSET(fd, WFIFOW(fd, 2));
+
+ len = c * sizeof(struct PACKET_ZC_MAKINGARROW_LIST_sub) + sizeof(struct PACKET_ZC_MAKINGARROW_LIST);
+ p->packetLength = len;
+ WFIFOSET(fd, len);
} else {
- clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_GUILLONTINE_POISON,0);
+ clif->skill_fail(sd, GC_POISONINGWEAPON, USESKILL_FAIL_GUILLONTINE_POISON, 0, 0);
return 0;
}
return 1;
}
-int clif_autoshadowspell_list(struct map_session_data *sd) {
+static int clif_autoshadowspell_list(struct map_session_data *sd)
+{
int fd, i, c;
nullpo_ret(sd);
fd = sd->fd;
@@ -17263,7 +19927,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
WFIFOHEAD(fd, 2 * 6 + 4);
WFIFOW(fd,0) = 0x442;
- for( i = 0, c = 0; i < MAX_SKILL; i++ )
+ for (i = 0, c = 0; i < MAX_SKILL_DB; i++)
if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 &&
sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id) == BF_MAGIC )
{ // Can't auto cast both Extended class and 3rd class skills.
@@ -17279,7 +19943,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
sd->menuskill_val = c;
} else {
status_change_end(&sd->bl,SC_STOP,INVALID_TIMER);
- clif->skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_IMITATION_SKILL_NONE,0);
+ clif->skill_fail(sd, SC_AUTOSHADOWSPELL, USESKILL_FAIL_IMITATION_SKILL_NONE, 0, 0);
}
return 1;
@@ -17288,7 +19952,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
* Skill list for Four Elemental Analysis
* and Change Material skills.
*------------------------------------------*/
-int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv )
+static int clif_skill_itemlistwindow(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
{
#if PACKETVER >= 20090922
int fd;
@@ -17314,18 +19978,21 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin
}
-void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/*==========================================
* used by SC_AUTOSHADOWSPELL
* RFIFOL(fd,2) - flag (currently not used)
*------------------------------------------*/
-void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
+static void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- if( sd->menuskill_id != SC_AUTOSHADOWSPELL )
+ if (sd->menuskill_id != SC_AUTOSHADOWSPELL)
return;
- if( pc_istrading(sd) ) {
- clif->skill_fail(sd,sd->ud.skill_id,0,0);
+ if (pc_istrading(sd) || sd->state.prevend) {
+ clif->skill_fail(sd, sd->ud.skill_id, 0, 0, 0);
clif_menuskill_clear(sd);
return;
}
@@ -17338,8 +20005,9 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
/*==========================================
* Kagerou/Oboro amulet spirit
*------------------------------------------*/
-void clif_charm(struct map_session_data *sd)
+static void clif_charm(struct map_session_data *sd)
{
+#if PACKETVER >= 20110809
unsigned char buf[10];
nullpo_retv(sd);
@@ -17349,9 +20017,10 @@ void clif_charm(struct map_session_data *sd)
WBUFW(buf,6) = sd->charm_type;
WBUFW(buf,8) = sd->charm_count;
clif->send(buf,packet_len(0x08cf),&sd->bl,AREA);
+#endif
}
-void clif_parse_MoveItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_MoveItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE]
/// 0907 <index>.W
///
@@ -17359,18 +20028,18 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) __attribute__((non
/// type:
/// 0 = move item to personal tab
/// 1 = move item to normal tab
-void clif_parse_MoveItem(int fd, struct map_session_data *sd) {
+static void clif_parse_MoveItem(int fd, struct map_session_data *sd)
+{
#if PACKETVER >= 20111122
int index;
/* can't move while dead. */
- if(pc_isdead(sd)) {
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
return;
- }
index = RFIFOW(fd,2)-2;
- if (index < 0 || index >= MAX_INVENTORY)
+ if (index < 0 || index >= sd->status.inventorySize)
return;
if ( sd->status.inventory[index].favorite && RFIFOB(fd, 4) == 1 )
@@ -17385,10 +20054,12 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) {
}
/* [Ind/Hercules] */
-void clif_cashshop_db(void) {
+static void clif_cashshop_db(void)
+{
struct config_t cashshop_conf;
struct config_setting_t *cashshop = NULL, *cats = NULL;
- const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name
+ char config_filename[256];
+ libconfig->format_db_path("cashshop_db.conf", config_filename, sizeof(config_filename));
int i, item_count_t = 0;
for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) {
CREATE(clif->cs.data[i], struct hCSData *, 1);
@@ -17403,7 +20074,7 @@ void clif_cashshop_db(void) {
if( cashshop != NULL && (cats = libconfig->setting_get_elem(cashshop, 0)) != NULL ) {
for(i = 0; i < CASHSHOP_TAB_MAX; i++) {
struct config_setting_t *cat;
- char entry_name[10];
+ char entry_name[15];
sprintf(entry_name,"cat_%d",i);
@@ -17421,7 +20092,7 @@ void clif_cashshop_db(void) {
continue;
}
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
+ if (name[0] == 'I' && name[1] == 'D' && strlen(name) <= 12) {
if( !( data = itemdb->exists(atoi(name+2))) ) {
ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name);
continue;
@@ -17449,7 +20120,9 @@ void clif_cashshop_db(void) {
}
/// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE).
/// 0900 <index>.W <favorite>.B
-void clif_favorite_item(struct map_session_data* sd, unsigned short index) {
+static void clif_favorite_item(struct map_session_data *sd, unsigned short index)
+{
+#if PACKETVER >= 20120410
int fd;
nullpo_retv(sd);
@@ -17459,9 +20132,12 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) {
WFIFOW(fd,2) = index+2;
WFIFOB(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1;
WFIFOSET(fd,packet_len(0x908));
+#endif
}
-void clif_snap( struct block_list *bl, short x, short y ) {
+static void clif_snap(struct block_list *bl, short x, short y)
+{
+#if PACKETVER >= 20110809
unsigned char buf[10];
nullpo_retv(bl);
@@ -17471,9 +20147,12 @@ void clif_snap( struct block_list *bl, short x, short y ) {
WBUFW(buf,8) = y;
clif->send(buf,packet_len(0x8d2),bl,AREA);
+#endif
}
-void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) {
+static void clif_monster_hp_bar(struct mob_data *md, struct map_session_data *sd)
+{
+#if PACKETVER >= 20120228
struct packet_monster_hp p;
nullpo_retv(md);
@@ -17484,97 +20163,188 @@ void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) {
p.MaxHP = md->status.max_hp;
clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
}
/* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */
-void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd) {
+static void clif_parse_dull(int fd, struct map_session_data *sd)
+{
+ const int cmd = clif->cmd;
+ Assert_retv(cmd <= MAX_PACKET_DB && cmd >= MIN_PACKET_DB);
+
+ int packet_len = packets->db[cmd];
+ if (packet_len == -1) { // variable-length packet
+ packet_len = RFIFOW(fd, 2);
+ }
+ if (sd) {
+ ShowWarning("Unhandled packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", (uint32)cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
+ } else {
+ ShowWarning("Unhandled packet 0x%04X (length %d), session #%d\n", (uint32)cmd, packet_len, fd);
+ }
return;
}
-void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) {
+static void clif_parse_cashShopOpen1(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopOpen1(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
if (map->list[sd->bl.m].flag.nocashshop) {
- clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd, 1489)); //Cash Shop is disabled in this map
return;
}
- WFIFOHEAD(fd, 10);
- WFIFOW(fd, 0) = 0x845;
- WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values
- WFIFOL(fd, 6) = sd->kafraPoints;
- WFIFOSET(fd, 10);
+ clif->cashShopOpen(fd, sd, 0);
}
-void clif_parse_CashShopClose(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_CashShopClose(int fd, struct map_session_data *sd) {
+static void clif_parse_cashShopLimitedReq(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopLimitedReq(int fd, struct map_session_data *sd)
+{
+}
+
+static void clif_parse_cashShopOpen2(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopOpen2(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading != 0 || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (map->list[sd->bl.m].flag.nocashshop != 0) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd, 1489)); //Cash Shop is disabled in this map
+ return;
+ }
+
+#if PACKETVER >= 20191224
+ const struct PACKET_CZ_SE_CASHSHOP_OPEN2 *p = RFIFOP(fd, 0);
+ clif->cashShopOpen(fd, sd, p->tab);
+#endif
+}
+
+static void clif_cashShopOpen(int fd, struct map_session_data *sd, int tab)
+{
+#if PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_SE_CASHSHOP_OPEN));
+ struct PACKET_ZC_SE_CASHSHOP_OPEN *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_SE_CASHSHOP_OPEN;
+ p->cashPoints = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values
+ p->kafraPoints = sd->kafraPoints;
+#if PACKETVER_MAIN_NUM >= 20200129 || PACKETVER_RE_NUM >= 20200205 || PACKETVER_ZERO_NUM >= 20191224
+ p->tab = tab;
+#endif
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_SE_CASHSHOP_OPEN));
+#endif
+}
+
+static void clif_parse_cashShopClose(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopClose(int fd, struct map_session_data *sd)
+{
/* TODO apply some state tracking */
}
-void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) {
- int i, j = 0;
+static void clif_parse_cashShopSchedule(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopSchedule(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
- for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) {
- if( clif->cs.item_count[i] == 0 )
+ clif->cashShopSchedule(fd, sd);
+}
+
+void clif_cashShopSchedule(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20110614
+ int i = 0;
+
+ nullpo_retv(sd);
+ for (i = 0; i < CASHSHOP_TAB_MAX; i++) {
+ const int len = sizeof(struct PACKET_ZC_ACK_SCHEDULER_CASHITEM) + (clif->cs.item_count[i] * sizeof(struct PACKET_ZC_ACK_SCHEDULER_CASHITEM_sub));
+ int j = 0;
+ struct PACKET_ZC_ACK_SCHEDULER_CASHITEM *p;
+ if (clif->cs.item_count[i] == 0)
continue; // Skip empty tabs, the client only expects filled ones
- WFIFOHEAD(fd, 8 + ( clif->cs.item_count[i] * 6 ) );
- WFIFOW(fd, 0) = 0x8ca;
- WFIFOW(fd, 2) = 8 + ( clif->cs.item_count[i] * 6 );
- WFIFOW(fd, 4) = clif->cs.item_count[i];
- WFIFOW(fd, 6) = i;
+ WFIFOHEAD(fd, len);
+ p = WFIFOP(fd, 0);
+ p->packetType = 0x8ca;
+ p->packetLength = len;
+ p->count = clif->cs.item_count[i];
+ p->tabNum = i;
- for( j = 0; j < clif->cs.item_count[i]; j++ ) {
- WFIFOW(fd, 8 + ( 6 * j ) ) = clif->cs.data[i][j]->id;
- WFIFOL(fd, 10 + ( 6 * j ) ) = clif->cs.data[i][j]->price;
+ for (j = 0; j < clif->cs.item_count[i]; j++) {
+ p->items[j].itemId = clif->cs.data[i][j]->id;
+ p->items[j].price = clif->cs.data[i][j]->price;
}
- WFIFOSET(fd, 8 + ( clif->cs.item_count[i] * 6 ));
+ WFIFOSET(fd, len);
}
+#endif
}
-void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
- unsigned short limit = RFIFOW(fd, 4), i, j;
- unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing)
+/// R 0848 <len>.W <limit>.W <kafra pay>.L (<item id>.L <amount>.L <tab>.W)*
+static void clif_parse_cashShopBuy(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cashShopBuy(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int len = RFIFOW(fd, 2);
+ unsigned short limit, i, j;
+ unsigned int kafra_pay;
+ int count;
if (map->list[sd->bl.m].flag.nocashshop) {
clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map
return;
}
+ if (len < 10)
+ return;
+
+ limit = RFIFOW(fd, 4);
+ kafra_pay = RFIFOL(fd, 6); // [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing)
+ count = (len - 10) / 10;
+ if (count != limit) {
+ ShowError("Wrong cash shop limit: %d\n", limit);
+ return;
+ }
+
for(i = 0; i < limit; i++) {
int qty = RFIFOL(fd, 14 + ( i * 10 ));
int id = RFIFOL(fd, 10 + ( i * 10 ));
short tab = RFIFOW(fd, 18 + ( i * 10 ));
enum CASH_SHOP_BUY_RESULT result = CSBR_UNKNOWN;
- if( tab < 0 || tab >= CASHSHOP_TAB_MAX )
+ if(tab < 0 || tab >= CASHSHOP_TAB_MAX)
continue;
- for( j = 0; j < clif->cs.item_count[tab]; j++ ) {
+ for(j = 0; j < clif->cs.item_count[tab]; j++) {
if( clif->cs.data[tab][j]->id == id )
break;
}
- if( j < clif->cs.item_count[tab] ) {
+ if(j < clif->cs.item_count[tab]) {
struct item_data *data;
- if( sd->kafraPoints < kafra_pay ) {
+ if(sd->kafraPoints < kafra_pay) {
result = CSBR_SHORTTAGE_CASH;
- } else if( (sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty) ) {
+ } else if((sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty)) {
result = CSBR_SHORTTAGE_CASH;
- } else if ( !( data = itemdb->exists(clif->cs.data[tab][j]->id) ) ) {
+ } else if (!(data = itemdb->exists(clif->cs.data[tab][j]->id))) {
result = CSBR_UNKONWN_ITEM;
} else {
struct item item_tmp;
int k, get_count;
+ int ret = 0;
get_count = qty;
if (!itemdb->isstackable2(data))
get_count = 1;
- pc->paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki]
+ ret = pc->paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki] //changed Kafrapoints calculation. [Normynator]
+ if (ret < 0) {
+ ShowError("clif_parse_cashShopBuy: The return from pc->paycash was negative which is not allowed.\n");
+ break; //This should never happen.
+ }
+ kafra_pay = ret;
for (k = 0; k < qty; k += get_count) {
if (!pet->create_egg(sd, data->nameid)) {
memset(&item_tmp, 0, sizeof(item_tmp));
@@ -17611,21 +20381,35 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
} else {
result = CSBR_UNKONWN_ITEM;
}
-
- WFIFOHEAD(fd, 16);
- WFIFOW(fd, 0) = 0x849;
- WFIFOL(fd, 2) = id;
- WFIFOW(fd, 6) = result;/* result */
- WFIFOL(fd, 8) = sd->cashPoints;/* current cash point */
- WFIFOL(fd, 12) = sd->kafraPoints;// [Ryuuzaki]
- WFIFOSET(fd, 16);
+ clif->cashShopBuyAck(fd, sd, id, result);
}
}
-void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_cashShopBuyAck(int fd, struct map_session_data *sd, int itemId, enum CASH_SHOP_BUY_RESULT result)
+{
+#if PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_SE_PC_BUY_CASHITEM_RESULT));
+ struct PACKET_ZC_SE_PC_BUY_CASHITEM_RESULT *p = WFIFOP(fd, 0);
+ p->packetType = 0x849;
+ p->itemId = itemId;
+ p->result = result;
+ p->cashPoints = sd->cashPoints;
+ p->kafraPoints = sd->kafraPoints;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_SE_PC_BUY_CASHITEM_RESULT));
+#endif
+}
+
+static void clif_parse_cashShopReqTab(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/* [Ind/Hercules] */
-void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
+static void clif_parse_cashShopReqTab(int fd, struct map_session_data *sd)
+{
+// [4144] packet exists only in 2011 and was dropped after
+#if PACKETVER >= 20110222 && PACKETVER < 20120000
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
short tab = RFIFOW(fd, 2);
int j;
@@ -17644,9 +20428,12 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
}
WFIFOSET(fd, 10 + ( clif->cs.item_count[tab] * 6 ));
+#endif
}
+
/* [Ind/Hercules] */
-void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
+static void clif_maptypeproperty2(struct block_list *bl, enum send_target t)
+{
#if PACKETVER >= 20121010
struct packet_maptypeproperty2 p;
struct map_session_data *sd = NULL;
@@ -17673,7 +20460,8 @@ void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
#endif
}
-void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3) {
+static void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3)
+{
struct packet_status_change2 p;
p.PacketType = status_change2Type;
@@ -17688,38 +20476,46 @@ void clif_status_change2(struct block_list *bl, int tid, enum send_target target
clif->send(&p,sizeof(p), bl, target);
}
-void clif_partytickack(struct map_session_data* sd, bool flag) {
+static void clif_partytickack(struct map_session_data *sd, bool flag)
+{
+#if PACKETVER_MAIN_NUM >= 20070911 || defined(PACKETVER_RE) || PACKETVER_AD_NUM >= 20070911 || PACKETVER_SAK_NUM >= 20070904 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
- WFIFOHEAD(sd->fd, packet_len(0x2c9));
- WFIFOW(sd->fd, 0) = 0x2c9;
- WFIFOB(sd->fd, 2) = flag;
- WFIFOSET(sd->fd, packet_len(0x2c9));
+ WFIFOHEAD(sd->fd, sizeof(struct PACKET_ZC_PARTY_CONFIG));
+ struct PACKET_ZC_PARTY_CONFIG *p = WFIFOP(sd->fd, 0);
+ p->packetType = HEADER_ZC_PARTY_CONFIG;
+ p->denyPartyInvites = flag;
+ WFIFOSET(sd->fd, sizeof(struct PACKET_ZC_PARTY_CONFIG));
+#endif
}
-void clif_ShowScript(struct block_list* bl, const char* message) {
+static void clif_ShowScript(struct block_list *bl, const char *message, enum send_target target)
+{
+#if PACKETVER >= 20110111
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8b3;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8b3;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
+ clif->send(buf, WBUFW(buf,2), bl, target);
+#endif
}
-void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) {
+static void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type)
+{
struct packet_status_change_end p;
nullpo_retv(bl);
@@ -17735,7 +20531,8 @@ void clif_status_change_end(struct block_list *bl, int tid, enum send_target tar
clif->send(&p,sizeof(p), bl, target);
}
-void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id) {
+static void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id)
+{
switch (response) {
case BGQA_FAIL_COOLDOWN:
case BGQA_FAIL_DESERTER:
@@ -17755,7 +20552,7 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK
}
}
-void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, const char *name)
+static void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, const char *name)
{
struct packet_bgqueue_notice_delete p;
@@ -17767,9 +20564,12 @@ void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
-void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_bgqueue_register(int fd, struct map_session_data *sd)
+static void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_bgqueue_register(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_bgqueue_register *p = RP2PTR(fd);
struct bg_arena *arena = NULL;
if( !bg->queue_on ) return; /* temp, until feature is complete */
@@ -17792,7 +20592,8 @@ void clif_parse_bgqueue_register(int fd, struct map_session_data *sd)
bg->queue_add(sd, arena, (enum bg_queue_types)p->type);
}
-void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_id, int position) {
+static void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_id, int position)
+{
struct packet_bgqueue_update_info p;
nullpo_retv(sd);
@@ -17806,12 +20607,14 @@ void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_i
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
-void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd)
+static void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_bgqueue_checkstate *p = RP2PTR(fd);
- nullpo_retv(sd);
if (sd->bg_queue.arena && sd->bg_queue.type) {
clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id));
} else {
@@ -17819,9 +20622,12 @@ void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd)
}
}
-void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd)
+static void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_bgqueue_revoke_req *p = RP2PTR(fd);
if( sd->bg_queue.arena )
@@ -17830,9 +20636,12 @@ void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd)
clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name);
}
-void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd)
+static void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_bgqueue_battlebegin_ack *p = RP2PTR(fd);
struct bg_arena *arena;
@@ -17845,7 +20654,8 @@ void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd)
}
}
-void clif_bgqueue_joined(struct map_session_data *sd, int pos) {
+static void clif_bgqueue_joined(struct map_session_data *sd, int pos)
+{
struct packet_bgqueue_notify_entry p;
nullpo_retv(sd);
@@ -17856,13 +20666,15 @@ void clif_bgqueue_joined(struct map_session_data *sd, int pos) {
clif->send(&p,sizeof(p), &sd->bl, BG_QUEUE);
}
-void clif_bgqueue_pcleft(struct map_session_data *sd) {
+static void clif_bgqueue_pcleft(struct map_session_data *sd)
+{
/* no idea */
return;
}
// Sends BG ready req to all with same bg arena/type as sd
-void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_id, enum send_target target) {
+static void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_id, enum send_target target)
+{
struct packet_bgqueue_battlebegins p;
nullpo_retv(sd);
@@ -17874,23 +20686,31 @@ void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_
clif->send(&p,sizeof(p), &sd->bl, target);
}
-void clif_scriptclear(struct map_session_data *sd, int npcid) {
+static void clif_scriptclear(struct map_session_data *sd, int npcid)
+{
+#if PACKETVER >= 20110928
struct packet_script_clear p;
nullpo_retv(sd);
p.PacketType = script_clearType;
p.NpcID = npcid;
- clif->send(&p,sizeof(p), &sd->bl, SELF);
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
}
/* Made Possible Thanks to Yommy! */
-void clif_package_item_announce(struct map_session_data *sd, unsigned short nameid, unsigned short containerid) {
+static void clif_package_item_announce(struct map_session_data *sd, int nameid, int containerid)
+{
struct packet_package_item_announce p;
nullpo_retv(sd);
p.PacketType = package_item_announceType;
- p.PacketLength = 11+NAME_LENGTH;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ p.PacketLength = 7 + 4 + 4 + NAME_LENGTH;
+#else
+ p.PacketLength = 7 + 2 + 2 + NAME_LENGTH;
+#endif
p.type = 0x0;
p.ItemID = nameid;
p.len = NAME_LENGTH;
@@ -17898,28 +20718,36 @@ void clif_package_item_announce(struct map_session_data *sd, unsigned short name
p.unknown = 0x2; // some strange byte, IDA shows.. BYTE3(BoxItemIDLength) = 2;
p.BoxItemID = containerid;
- clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT);
+ clif->send(&p, p.PacketLength, &sd->bl, ALL_CLIENT);
}
/* Made Possible Thanks to Yommy! */
-void clif_item_drop_announce(struct map_session_data *sd, unsigned short nameid, char *monsterName) {
+static void clif_item_drop_announce(struct map_session_data *sd, int nameid, char *monsterName)
+{
struct packet_item_drop_announce p;
nullpo_retv(sd);
p.PacketType = item_drop_announceType;
p.PacketLength = sizeof(p);
- p.type = 0x1;
p.ItemID = nameid;
+ p.monsterNameLen = NAME_LENGTH;
p.len = NAME_LENGTH;
safestrncpy(p.Name, sd->status.name, sizeof(p.Name));
- p.monsterNameLen = NAME_LENGTH;
- safestrncpy(p.monsterName, monsterName, sizeof(p.monsterName));
-
- clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT);
+ if (monsterName == NULL) {
+ // message: MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN2
+ p.type = 0x2;
+ p.PacketLength -= NAME_LENGTH;
+ } else {
+ // message: MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN
+ p.type = 0x1;
+ safestrncpy(p.monsterName, monsterName, sizeof(p.monsterName));
+ }
+ clif->send(&p, p.PacketLength, &sd->bl, ALL_CLIENT);
}
/* [Ind/Hercules] special thanks to Yommy~! */
-void clif_skill_cooldown_list(int fd, struct skill_cd* cd) {
+static void clif_skill_cooldown_list(int fd, struct skill_cd *cd)
+{
#if PACKETVER >= 20120604
const int offset = 10;
#else
@@ -17959,7 +20787,8 @@ void clif_skill_cooldown_list(int fd, struct skill_cd* cd) {
* - ADDITEM_TO_CART_FAIL_WEIGHT = 0x0
* - ADDITEM_TO_CART_FAIL_COUNT = 0x1
*/
-void clif_cart_additem_ack(struct map_session_data *sd, int flag) {
+static void clif_cart_additem_ack(struct map_session_data *sd, int flag)
+{
struct packet_cart_additem_ack p;
nullpo_retv(sd);
@@ -17970,9 +20799,12 @@ void clif_cart_additem_ack(struct map_session_data *sd, int flag) {
}
/* Bank System [Yommy/Hercules] */
-void clif_parse_BankDeposit(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_BankDeposit(int fd, struct map_session_data *sd)
+static void clif_parse_BankDeposit(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BankDeposit(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_banking_deposit_req *p = RP2PTR(fd);
int money;
@@ -17986,9 +20818,12 @@ void clif_parse_BankDeposit(int fd, struct map_session_data *sd)
pc->bank_deposit(sd,money);
}
-void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_BankWithdraw(int fd, struct map_session_data *sd)
+static void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BankWithdraw(int fd, struct map_session_data *sd)
{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_banking_withdraw_req *p = RP2PTR(fd);
int money;
@@ -18002,33 +20837,43 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data *sd)
pc->bank_withdraw(sd,money);
}
-void clif_parse_BankCheck(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_BankCheck(int fd, struct map_session_data* sd) {
+static void clif_parse_BankCheck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BankCheck(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20130320
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct packet_banking_check p;
+ p.PacketType = banking_checkType;
if (!battle_config.feature_banking) {
- clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483));
- return;
+ p.Money = 0;
+ p.Reason = (short)1;
+ } else {
+ p.Money = (int)sd->status.bank_vault;
+ p.Reason = (short)0;
}
- p.PacketType = banking_checkType;
- p.Money = (int)sd->status.bank_vault;
- p.Reason = (short)0;
-
- clif->send(&p,sizeof(p), &sd->bl, SELF);
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
}
-void clif_parse_BankOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_BankOpen(int fd, struct map_session_data* sd) {
+static void clif_parse_BankOpen(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BankOpen(int fd, struct map_session_data *sd)
+{
return;
}
-void clif_parse_BankClose(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_BankClose(int fd, struct map_session_data* sd) {
+static void clif_parse_BankClose(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_BankClose(int fd, struct map_session_data *sd)
+{
return;
}
-void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) {
+static void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason)
+{
+#if PACKETVER >= 20130313
struct packet_banking_deposit_ack p;
nullpo_retv(sd);
@@ -18038,9 +20883,12 @@ void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK r
p.Reason = (short)reason;
clif->send(&p,sizeof(p), &sd->bl, SELF);
+#endif
}
-void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) {
+static void clif_bank_withdraw(struct map_session_data *sd, enum e_BANKING_WITHDRAW_ACK reason)
+{
+#if PACKETVER >= 20130313
struct packet_banking_withdraw_ack p;
nullpo_retv(sd);
@@ -18050,24 +20898,27 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK
p.Reason = (short)reason;
clif->send(&p,sizeof(p), &sd->bl, SELF);
+#endif
}
/* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */
/* currently mimicing */
-void clif_show_modifiers (struct map_session_data *sd) {
+static void clif_show_modifiers(struct map_session_data *sd)
+{
nullpo_retv(sd);
if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) {
char output[128];
- snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
+ snprintf(output,128, msg_sd(sd, 896), // Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%
sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
- clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ clif->broadcast2(&sd->bl, output, (int)strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
}
}
-void clif_notify_bounditem(struct map_session_data *sd, unsigned short index) {
+static void clif_notify_bounditem(struct map_session_data *sd, unsigned short index)
+{
struct packet_notify_bounditem p;
nullpo_retv(sd);
@@ -18077,11 +20928,12 @@ void clif_notify_bounditem(struct map_session_data *sd, unsigned short index) {
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
-void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/**
* Parses the (GM) right click option 'remove all equipment'
**/
-void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
+static void clif_parse_GMFullStrip(int fd, struct map_session_data *sd)
+{
struct map_session_data *tsd = map->id2sd(RFIFOL(fd,2));
int i;
@@ -18098,7 +20950,8 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
/**
* clif_delay_damage timer, sends the stored data and clears the memory afterwards
**/
-int clif_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
+static int clif_delay_damage_sub(int tid, int64 tick, int id, intptr_t data)
+{
struct cdelayed_damage *dd = (struct cdelayed_damage *)data;
clif->send(&dd->p,sizeof(struct packet_damage),&dd->bl,AREA_WOS);
@@ -18122,7 +20975,8 @@ int clif_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
*
* @return clif->calc_walkdelay used in further processing
**/
-int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type) {
+static int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, enum battle_dmg_type type)
+{
struct cdelayed_damage *dd;
struct status_change *sc;
#if PACKETVER < 20071113
@@ -18181,101 +21035,115 @@ int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst
return clif->calc_walkdelay(dst,ddelay,type,damage,div);
}
-void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/* Thanks to Yommy */
-void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) {
+static void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd)
+{
/* TODO track the state <3~ */
sd->npc_shopid = 0;
}
/* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */
-void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
-#if PACKETVER >= 20131223
- struct npc_item_list *shop;
- unsigned short shop_size, i, c;
-
+static void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd)
+{
+#if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20131106 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
nullpo_retv(nd);
- shop = nd->u.scr.shop->item;
- shop_size = nd->u.scr.shop->items;
- npcmarket_open.PacketType = npcmarketopenType;
+ struct npc_item_list *shop = nd->u.scr.shop->item;
+ const int shop_size = nd->u.scr.shop->items;
- for(i = 0, c = 0; i < shop_size; i++) {
+ int c = 0;
+ int maxCount = (sizeof(packet_buf) - sizeof(struct PACKET_ZC_NPC_MARKET_OPEN)) / sizeof(struct PACKET_ZC_NPC_MARKET_OPEN_sub);
+ struct PACKET_ZC_NPC_MARKET_OPEN *packet = (struct PACKET_ZC_NPC_MARKET_OPEN*)&packet_buf[0];
+ packet->packetType = HEADER_ZC_NPC_MARKET_OPEN;
+
+ for (int i = 0; i < shop_size && c < maxCount; i++) {
struct item_data *id = NULL;
if (shop[i].nameid && (id = itemdb->exists(shop[i].nameid)) != NULL) {
- npcmarket_open.list[c].nameid = shop[i].nameid;
- npcmarket_open.list[c].price = shop[i].value;
- npcmarket_open.list[c].qty = shop[i].qty;
- npcmarket_open.list[c].type = itemtype(id->type);
- npcmarket_open.list[c].view = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ packet->list[c].nameid = shop[i].nameid;
+ packet->list[c].price = shop[i].value;
+ packet->list[c].qty = shop[i].qty;
+ packet->list[c].type = itemtype(id->type);
+ packet->list[c].weight = id->weight * 10;
c++;
}
}
- npcmarket_open.PacketLength = 4 + ( sizeof(npcmarket_open.list[0]) * c );
-
- clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF);
+ packet->packetLength = sizeof(struct PACKET_ZC_NPC_MARKET_OPEN) + sizeof(struct PACKET_ZC_NPC_MARKET_OPEN_sub) * c;
+ clif->send(packet, packet->packetLength, &sd->bl, SELF);
#endif
}
-void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) {
+static void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static 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, const struct itemlist *item_list, unsigned char response)
+static void clif_parse_NPCBarterClosed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NPCBarterClosed(int fd, struct map_session_data *sd)
{
-#if PACKETVER >= 20131223
- unsigned short c = 0;
+ sd->npc_shopid = 0;
+}
+static void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, enum market_buy_result response)
+{
+#if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20130911 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
nullpo_retv(item_list);
- npcmarket_result.PacketType = npcmarketresultackType;
- npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */
+ struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *p = (struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT *)packet_buf;
+ p->PacketType = HEADER_ZC_NPC_MARKET_PURCHASE_RESULT;
+ p->result = response;
- if (npcmarket_result.result) {
+ unsigned short c = 0;
+ if (response == MARKET_BUY_RESULT_SUCCESS) {
+ int vectorLen = VECTOR_LENGTH(*item_list);
+ int maxCount = (sizeof(packet_buf) - sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT)) / sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub);
+ if (maxCount > vectorLen)
+ maxCount = vectorLen;
struct npc_data *nd = map->id2nd(sd->npc_shopid);
struct npc_item_list *shop = nd->u.scr.shop->item;
unsigned short shop_size = nd->u.scr.shop->items;
- int i;
- for (i = 0; i < VECTOR_LENGTH(*item_list); i++) {
+ for (int i = 0; i < maxCount; i++) {
const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
int j;
- npcmarket_result.list[i].ITID = entry->id;
- npcmarket_result.list[i].qty = entry->amount;
+ p->list[i].ITID = entry->id;
+ p->list[i].qty = entry->amount;
- ARR_FIND( 0, shop_size, j, entry->id == shop[j].nameid);
+ ARR_FIND(0, shop_size, j, entry->id == shop[j].nameid);
- npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0;
+ p->list[i].price = (j != shop_size) ? shop[j].value : 0;
c++;
}
}
- npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );;
+ p->PacketLength = sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT) + (sizeof(struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub) * c);
- clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF);
+ clif->send(p, p->PacketLength, &sd->bl, SELF);
#endif
}
-void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd)
+static void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd)
{
#if PACKETVER >= 20131223
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
const struct packet_npc_market_purchase *p = RP2PTR(fd);
- int response = 0, i;
int count = (p->PacketLength - 4) / sizeof p->list[0];
struct itemlist item_list;
- Assert_retv(count >= 0 && count <= MAX_INVENTORY);
+ Assert_retv(count >= 0 && count <= sd->status.inventorySize);
VECTOR_INIT(item_list);
VECTOR_ENSURE(item_list, count, 1);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
struct itemlist_entry entry = { 0 };
entry.id = p->list[i].ITID;
@@ -18284,14 +21152,15 @@ void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd)
VECTOR_PUSH(item_list, entry);
}
- response = npc->market_buylist(sd, &item_list);
+ enum market_buy_result response = npc->market_buylist(sd, &item_list);
clif->npc_market_purchase_ack(sd, &item_list, response);
VECTOR_CLEAR(item_list);
#endif
}
-void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid) {
+static void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid)
+{
struct packet_party_leader_changed p;
nullpo_retv(sd);
@@ -18303,41 +21172,52 @@ void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, i
clif->send(&p,sizeof(p),&sd->bl,PARTY);
}
-void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_RouletteOpen(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/* Roulette System [Yommy/Hercules] */
-void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) {
+static void clif_parse_RouletteOpen(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20140612
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct packet_roulette_open_ack p;
if( !battle_config.feature_roulette ) {
- clif->message(fd,"Roulette is disabled");
+ clif->message(fd, msg_fd(fd,82)); // Roulette is disabled
return;
}
p.PacketType = 0xa1a;
- p.Result = 0;
+ p.Result = OPEN_ROULETTE_SUCCESS;
p.Serial = 0;
p.Step = sd->roulette.stage - 1;
p.Idx = (char)sd->roulette.prizeIdx;
p.AdditionItemID = -1; /** TODO **/
- p.BronzePoint = pc_readglobalreg(sd, script->add_str("TmpRouletteBronze"));
- p.GoldPoint = pc_readglobalreg(sd, script->add_str("TmpRouletteGold"));
- p.SilverPoint = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver"));
+ p.BronzePoint = pc_readglobalreg(sd, script->add_variable("TmpRouletteBronze"));
+ p.GoldPoint = pc_readglobalreg(sd, script->add_variable("TmpRouletteGold"));
+ p.SilverPoint = pc_readglobalreg(sd, script->add_variable("TmpRouletteSilver"));
clif->send(&p,sizeof(p), &sd->bl, SELF);
+#endif
}
-void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) {
+static void clif_parse_RouletteInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RouletteInfo(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20140612
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
struct packet_roulette_info_ack p;
unsigned short i, j, count = 0;
if( !battle_config.feature_roulette ) {
- clif->message(fd,"Roulette is disabled");
+ clif->message(fd, msg_fd(fd,82)); // Roulette is disabled
return;
}
p.PacketType = rouletteinfoackType;
- p.PacketLength = 8 + (42 * 8);
+ p.PacketLength = sizeof(p);
p.RouletteSerial = 1;
for(i = 0; i < MAX_ROULETTE_LEVEL; i++) {
@@ -18346,17 +21226,21 @@ void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) {
p.ItemInfo[count].Position = j;
p.ItemInfo[count].ItemId = clif->rd.nameid[i][j];
p.ItemInfo[count].Count = clif->rd.qty[i][j];
+#if PACKETVER >= 20180511
+ p.ItemInfo[count].unused = 0;
+#endif
count++;
}
}
clif->send(&p,sizeof(p), &sd->bl, SELF);
- return;
+#endif
}
-void clif_parse_RouletteClose(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_RouletteClose(int fd, struct map_session_data* sd) {
+static void clif_parse_RouletteClose(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RouletteClose(int fd, struct map_session_data *sd)
+{
if( !battle_config.feature_roulette ) {
- clif->message(fd,"Roulette is disabled");
+ clif->message(fd, msg_fd(fd,82)); // Roulette is disabled
return;
}
@@ -18366,13 +21250,17 @@ void clif_parse_RouletteClose(int fd, struct map_session_data* sd) {
return;
}
-void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) {
+static void clif_parse_RouletteGenerate(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_RouletteGenerate(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
unsigned char result = GENERATE_ROULETTE_SUCCESS;
short stage = sd->roulette.stage;
if( !battle_config.feature_roulette ) {
- clif->message(fd,"Roulette is disabled");
+ clif->message(fd, msg_fd(fd,82)); // Roulette is disabled
return;
}
@@ -18380,21 +21268,21 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) {
stage = sd->roulette.stage = 0;
if( stage == 0 ) {
- if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) <= 0 &&
- pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) < 10 &&
- pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) < 10 )
+ if( pc_readglobalreg(sd, script->add_variable("TmpRouletteBronze")) <= 0 &&
+ pc_readglobalreg(sd, script->add_variable("TmpRouletteSilver")) < 10 &&
+ pc_readglobalreg(sd, script->add_variable("TmpRouletteGold")) < 10 )
result = GENERATE_ROULETTE_NO_ENOUGH_POINT;
}
if( result == GENERATE_ROULETTE_SUCCESS ) {
if( stage == 0 ) {
- if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) > 0 ) {
- pc_setglobalreg(sd, script->add_str("TmpRouletteBronze"), pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) - 1);
- } else if( pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) > 9 ) {
- pc_setglobalreg(sd, script->add_str("TmpRouletteSilver"), pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) - 10);
+ if( pc_readglobalreg(sd, script->add_variable("TmpRouletteBronze")) > 0 ) {
+ pc_setglobalreg(sd, script->add_variable("TmpRouletteBronze"), pc_readglobalreg(sd, script->add_variable("TmpRouletteBronze")) - 1);
+ } else if( pc_readglobalreg(sd, script->add_variable("TmpRouletteSilver")) > 9 ) {
+ pc_setglobalreg(sd, script->add_variable("TmpRouletteSilver"), pc_readglobalreg(sd, script->add_variable("TmpRouletteSilver")) - 10);
stage = sd->roulette.stage = 2;
- } else if( pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) > 9 ) {
- pc_setglobalreg(sd, script->add_str("TmpRouletteGold"), pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) - 10);
+ } else if( pc_readglobalreg(sd, script->add_variable("TmpRouletteGold")) > 9 ) {
+ pc_setglobalreg(sd, script->add_variable("TmpRouletteGold"), pc_readglobalreg(sd, script->add_variable("TmpRouletteGold")) - 10);
stage = sd->roulette.stage = 4;
}
}
@@ -18420,15 +21308,19 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) {
sd->roulette.stage++;
}
-void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
+static void clif_parse_RouletteRecvItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
/**
* Request to cash in!
**/
-void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) {
+static void clif_parse_RouletteRecvItem(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20140612
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
struct packet_roulette_itemrecv_ack p;
if( !battle_config.feature_roulette ) {
- clif->message(fd,"Roulette is disabled");
+ clif->message(fd, msg_fd(fd,82)); // Roulette is disabled
return;
}
@@ -18467,13 +21359,15 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) {
p.Result = RECV_ITEM_FAILED;
clif->send(&p,sizeof(p), &sd->bl, SELF);
- return;
+#endif
}
-bool clif_parse_roulette_db(void) {
+static bool clif_parse_roulette_db(void)
+{
struct config_t roulette_conf;
struct config_setting_t *roulette = NULL, *levels = NULL;
- const char *config_filename = "db/roulette_db.conf"; // FIXME hardcoded name
+ char config_filename[256];
+ libconfig->format_db_path("roulette_db.conf", config_filename, sizeof(config_filename));
int i, j, item_count_t = 0;
for( i = 0; i < MAX_ROULETTE_LEVEL; i++ ) {
@@ -18505,7 +21399,7 @@ bool clif_parse_roulette_db(void) {
continue;
}
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
+ if (name[0] == 'I' && name[1] == 'D' && strlen(name) <= 12) {
if( !( data = itemdb->exists(atoi(name+2))) ) {
ShowWarning("roulette_db: unknown item id '%s' in category '%s'\n", name+2, entry_name);
continue;
@@ -18562,7 +21456,9 @@ bool clif_parse_roulette_db(void) {
/**
*
**/
-void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) {
+static void clif_roulette_generate_ack(struct map_session_data *sd, enum GENERATE_ROULETTE_ACK result, short stage, short prizeIdx, int bonusItemID)
+{
+#if PACKETVER >= 20140612
struct packet_roulette_generate_ack p;
nullpo_retv(sd);
@@ -18571,26 +21467,42 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul
p.Step = stage;
p.Idx = prizeIdx;
p.AdditionItemID = bonusItemID;
- p.RemainBronze = pc_readglobalreg(sd, script->add_str("TmpRouletteBronze"));
- p.RemainGold = pc_readglobalreg(sd, script->add_str("TmpRouletteGold"));
- p.RemainSilver = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver"));
+ p.RemainBronze = pc_readglobalreg(sd, script->add_variable("TmpRouletteBronze"));
+ p.RemainGold = pc_readglobalreg(sd, script->add_variable("TmpRouletteGold"));
+ p.RemainSilver = pc_readglobalreg(sd, script->add_variable("TmpRouletteSilver"));
clif->send(&p,sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static void clif_roulette_close(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20141008 || PACKETVER_RE_NUM >= 20140903 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+
+ struct PACKET_ZC_ACK_CLOSE_ROULETTE p;
+ p.packetType = HEADER_ZC_ACK_CLOSE_ROULETTE;
+ p.result = 0; // close window
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
}
/**
* Stackable items merger
*/
-void clif_openmergeitem(int fd, struct map_session_data *sd)
+static void clif_openmergeitem(int fd, struct map_session_data *sd)
{
- int i = 0, n = 0, j = 0;
+#if PACKETVER_MAIN_NUM >= 20120314 || PACKETVER_RE_NUM >= 20120221 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+
+ int n = 0, j = 0;
struct merge_item merge_items[MAX_INVENTORY];
struct merge_item *merge_items_[MAX_INVENTORY] = {0};
- nullpo_retv(sd);
- memset(&merge_items,'\0',sizeof(merge_items));
+ memset(&merge_items, '\0', sizeof(merge_items));
- for (i = 0; i < MAX_INVENTORY; i++) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
struct item *item_data = &sd->status.inventory[i];
if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid) || item_data->bound != IBT_NONE)
@@ -18601,17 +21513,18 @@ void clif_openmergeitem(int fd, struct map_session_data *sd)
n++;
}
- qsort(merge_items,n,sizeof(struct merge_item),clif->comparemergeitem);
+ qsort(merge_items, n, sizeof(struct merge_item), clif->comparemergeitem);
- for (i = 0, j = 0; i < n; i++) {
- if (i > 0 && merge_items[i].nameid == merge_items[i-1].nameid)
+ j = 0;
+ for (int i = 0; i < n; i++) {
+ if (i > 0 && merge_items[i].nameid == merge_items[i - 1].nameid)
{
merge_items_[j] = &merge_items[i];
j++;
continue;
}
- if (i < n - 1 && merge_items[i].nameid == merge_items[i+1].nameid)
+ if (i < n - 1 && merge_items[i].nameid == merge_items[i + 1].nameid)
{
merge_items_[j] = &merge_items[i];
j++;
@@ -18619,15 +21532,18 @@ void clif_openmergeitem(int fd, struct map_session_data *sd)
}
}
- WFIFOHEAD(fd,2*j+4);
- WFIFOW(fd,0) = 0x96d;
- WFIFOW(fd,2) = 2*j+4;
- for ( i = 0; i < j; i++ )
- WFIFOW(fd,i*2+4) = merge_items_[i]->position;
- WFIFOSET(fd,2*j+4);
+ const int len = sizeof(struct PACKET_ZC_MERGE_ITEM_OPEN) + j * sizeof(struct PACKET_ZC_MERGE_ITEM_OPEN_sub);
+ WFIFOHEAD(fd, len);
+ struct PACKET_ZC_MERGE_ITEM_OPEN *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_MERGE_ITEM_OPEN;
+ p->packetLen = len;
+ for (int i = 0; i < j; i++)
+ p->items[i].index = merge_items_[i]->position;
+ WFIFOSET(fd, len);
+#endif
}
-int clif_comparemergeitem(const void *a, const void *b)
+static int clif_comparemergeitem(const void *a, const void *b)
{
const struct merge_item *a_ = a;
const struct merge_item *b_ = b;
@@ -18639,33 +21555,42 @@ int clif_comparemergeitem(const void *a, const void *b)
return a_->nameid > b_->nameid ? -1 : 1;
}
-void clif_ackmergeitems(int fd, struct map_session_data *sd)
+static void clif_mergeitems(int fd, struct map_session_data *sd, int index, int amount, enum mergeitem_reason reason)
{
- int i = 0, n = 0, length = 0, count = 0;
- int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0};
- struct item item_data;
+#if PACKETVER_MAIN_NUM >= 20120314 || PACKETVER_RE_NUM >= 20120221 || defined(PACKETVER_ZERO)
+ WFIFOHEAD(fd, sizeof(struct PACKET_ZC_ACK_MERGE_ITEM));
+ struct PACKET_ZC_ACK_MERGE_ITEM *p = WFIFOP(fd, 0);
+ p->packetType = HEADER_ZC_ACK_MERGE_ITEM;
+ p->index = index + 2;
+ p->amount = amount;
+ p->reason = reason;
+ WFIFOSET(fd, sizeof(struct PACKET_ZC_ACK_MERGE_ITEM));
+#endif
+}
+static void clif_ackmergeitems(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20120314 || PACKETVER_RE_NUM >= 20120221 || defined(PACKETVER_ZERO)
nullpo_retv(sd);
- length = (RFIFOW(fd,2) - 4)/2;
- if (length >= MAX_INVENTORY || length < 2) {
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x96f;
- WFIFOW(fd,2) = 0;
- WFIFOW(fd,4) = 0;
- WFIFOB(fd,6) = MERGEITEM_FAILD;
- WFIFOSET(fd,7);
+ int i = 0, n = 0, count = 0;
+ int nameid = 0;
+ int16 indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0};
+
+ int length = (RFIFOW(fd, 2) - 4) / 2;
+
+ if (length >= sd->status.inventorySize || length < 2) {
+ clif->mergeitems(fd, sd, 0, 0, MERGEITEM_FAILD);
return;
}
for (i = 0, n = 0; i < length; i++) {
- int16 idx = RFIFOW(fd,i*2+4) - 2;
- struct item *it = NULL;
+ int16 idx = RFIFOW(fd, i * 2 + 4) - 2;
- if (idx < 0 || idx >= MAX_INVENTORY)
+ if (idx < 0 || idx >= sd->status.inventorySize)
continue;
- it = &sd->status.inventory[idx];
+ struct item *it = &sd->status.inventory[idx];
if (it->nameid == 0 || !itemdb->isstackable(it->nameid) || it->bound != IBT_NONE)
continue;
@@ -18683,53 +21608,41 @@ void clif_ackmergeitems(int fd, struct map_session_data *sd)
}
if (n < 2 || count == 0) {
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x96f;
- WFIFOW(fd,2) = 0;
- WFIFOW(fd,4) = 0;
- WFIFOB(fd,6) = MERGEITEM_FAILD;
- WFIFOSET(fd,7);
+ clif->mergeitems(fd, sd, 0, 0, MERGEITEM_FAILD);
return;
}
if (count > MAX_AMOUNT) {
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x96f;
- WFIFOW(fd,2) = 0;
- WFIFOW(fd,4) = 0;
- WFIFOB(fd,6) = MERGEITEM_MAXCOUNTFAILD;
- WFIFOSET(fd,7);
+ clif->mergeitems(fd, sd, 0, 0, MERGEITEM_MAXCOUNTFAILD);
return;
}
for (i = 0; i < n; i++)
- pc->delitem(sd,indexes[i],amounts[i],0,DELITEM_NORMAL,LOG_TYPE_NPC);
+ pc->delitem(sd, indexes[i], amounts[i], 0, DELITEM_NORMAL, LOG_TYPE_NPC);
- memset(&item_data,'\0',sizeof(item_data));
+ struct item item_data;
+ memset(&item_data, '\0', sizeof(item_data));
item_data.nameid = nameid;
item_data.identify = 1;
item_data.unique_id = itemdb->unique_id(sd);
- pc->additem(sd,&item_data,count,LOG_TYPE_NPC);
+ pc->additem(sd, &item_data, count, LOG_TYPE_NPC);
- ARR_FIND(0,MAX_INVENTORY,i,item_data.unique_id == sd->status.inventory[i].unique_id);
+ ARR_FIND(0, sd->status.inventorySize, i, item_data.unique_id == sd->status.inventory[i].unique_id);
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x96f;
- WFIFOW(fd,2) = i+2;
- WFIFOW(fd,4) = count;
- WFIFOB(fd,6) = MERGEITEM_SUCCESS;
- WFIFOSET(fd,7);
+ clif->mergeitems(fd, sd, i, count, MERGEITEM_SUCCESS);
+#endif
}
-void clif_cancelmergeitem (int fd, struct map_session_data *sd)
+static void clif_cancelmergeitem(int fd, struct map_session_data *sd)
{
//Track The merge item cancelation ?
return;
}
-void clif_dressroom_open(struct map_session_data *sd, int view)
+static void clif_dressroom_open(struct map_session_data *sd, int view)
{
+#if PACKETVER >= 20150513
int fd;
nullpo_retv(sd);
@@ -18739,11 +21652,12 @@ void clif_dressroom_open(struct map_session_data *sd, int view)
WFIFOW(fd,0)=0xa02;
WFIFOW(fd,2)=view;
WFIFOSET(fd,packet_len(0xa02));
+#endif
}
/// Request to select cart's visual look for new cart design (ZC_SELECTCART).
/// 097f <Length>.W <identity>.L <type>.B
-void clif_selectcart(struct map_session_data *sd)
+static void clif_selectcart(struct map_session_data *sd)
{
#if PACKETVER >= 20150805
int i = 0, fd;
@@ -18763,13 +21677,55 @@ void clif_selectcart(struct map_session_data *sd)
#endif
}
+/// Starts navigation to the given target on client side
+static void clif_navigate_to(struct map_session_data *sd, const char *mapname, uint16 x, uint16 y, uint8 flag, bool hideWindow, uint16 mob_id)
+{
+// probably this packet with other fields present in older packet versions
+#if PACKETVER >= 20120307
+ int fd;
+
+ nullpo_retv(sd);
+ nullpo_retv(mapname);
+ fd = sd->fd;
+ WFIFOHEAD(fd, packet_len(0x8e2));
+ WFIFOW(fd, 0) = 0x8e2;
+
+ // How detailed will our navigation be?
+ if (mob_id > 0) {
+ x = 0;
+ y = 0;
+ WFIFOB(fd, 2) = 3; // monster with destination field
+ } else if (x > 0 && y > 0) {
+ WFIFOB(fd, 2) = 0; // with coordinates
+ } else {
+ x = 0;
+ y = 0;
+ WFIFOB(fd, 2) = 1; // without coordinates(will fail if you are already on the map)
+ }
+
+ // Which services can be used for transportation?
+ WFIFOB(fd, 3) = flag;
+ // If this flag is set, the navigation window will not be opened up
+ WFIFOB(fd, 4) = hideWindow;
+ // Target map
+ safestrncpy((char*)WFIFOP(fd, 5), mapname, MAP_NAME_LENGTH_EXT);
+ // Target x
+ WFIFOW(fd, 21) = x;
+ // Target y
+ WFIFOW(fd, 23) = y;
+ // Target monster ID
+ WFIFOW(fd, 25) = mob_id;
+ WFIFOSET(fd, packet_len(0x8e2));
+#endif
+}
+
/**
* Returns the name of the given bl, in a client-friendly format.
*
* @param bl The requested bl.
* @return The bl's name (guaranteed to be non-NULL).
*/
-const char *clif_get_bl_name(const struct block_list *bl)
+static const char *clif_get_bl_name(const struct block_list *bl)
{
const char *name = status->get_name(bl);
@@ -18779,21 +21735,177 @@ const char *clif_get_bl_name(const struct block_list *bl)
return name;
}
+/**
+ * Clan System: Sends the basic clan informations to client.
+ * 098a <length>.W <clan id>.L <clan name>.24B <clan master>.24B <clan map>.16B <alliance count>.B
+ * <antagonist count>.B { <alliance>.24B } * alliance count { <antagonist>.24B } * antagonist count (ZC_CLANINFO)
+ */
+static void clif_clan_basicinfo(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20130626 || PACKETVER_RE_NUM >= 20130605 || defined(PACKETVER_ZERO)
+ int len, i, fd;
+ struct clan *c, *ally, *antagonist;
+ struct PACKET_ZC_CLANINFO *packet = NULL;
+ nullpo_retv(sd);
+ nullpo_retv(c = sd->clan);
+
+ len = sizeof(struct PACKET_ZC_CLANINFO);
+ fd = sd->fd;
+
+ const int maxEntries = 100; // max entries with clan names
+ WFIFOHEAD(fd, len + maxEntries * 24);
+ packet = WFIFOP(fd, 0);
+
+ packet->PacketType = HEADER_ZC_CLANINFO;
+ packet->ClanID = c->clan_id;
+
+ safestrncpy(packet->ClanName, c->name, NAME_LENGTH);
+ safestrncpy(packet->MasterName, c->master, NAME_LENGTH);
+
+ mapindex->getmapname_ext(c->map, packet->Map);
+
+ packet->AllyCount = VECTOR_LENGTH(c->allies);
+ packet->AntagonistCount = VECTOR_LENGTH(c->antagonists);
+
+ int cnt = 0;
+ // All allies and antagonists are assumed as valid entries
+ // since it only gets inside the vector after the validation
+ // on clan->config_read
+ for (i = 0; i < VECTOR_LENGTH(c->allies) && cnt < maxEntries; i++) {
+ struct clan_relationship *al = &VECTOR_INDEX(c->allies, i);
+
+ if ((ally = clan->search(al->clan_id)) != NULL) {
+ safestrncpy(WFIFOP(fd, len), ally->name, NAME_LENGTH);
+ len += NAME_LENGTH;
+ cnt ++;
+ }
+ }
+
+ for (i = 0; i < VECTOR_LENGTH(c->antagonists) && cnt < maxEntries; i++) {
+ struct clan_relationship *an = &VECTOR_INDEX(c->antagonists, i);
+
+ if ((antagonist = clan->search(an->clan_id)) != NULL) {
+ safestrncpy(WFIFOP(fd, len), antagonist->name, NAME_LENGTH);
+ len += NAME_LENGTH;
+ cnt ++;
+ }
+ }
+
+ packet->PacketLength = len;
+ WFIFOSET(fd, len);
+#endif
+}
+
+/**
+ * Clan System: Updates the online and maximum player count of a clan.
+ * 0988 <online count>.W <maximum member amount>.W (ZC_NOTIFY_CLAN_CONNECTINFO)
+ */
+static void clif_clan_onlinecount(struct clan *c)
+{
+#if PACKETVER >= 20120716
+ struct map_session_data *sd;
+ struct PACKET_ZC_NOTIFY_CLAN_CONNECTINFO p;
+
+ nullpo_retv(c);
+
+ p.PacketType = clanOnlineCount;
+ p.NumConnect = c->connect_member;
+ p.NumTotal = c->max_member;
+
+ if ((sd = clan->getonlinesd(c)) != NULL) {
+ clif->send(&p, sizeof(p), &sd->bl, CLAN);
+ }
+#endif
+}
+
+/**
+ * Clan System: Notifies the client that the player has left his clan.
+ * 0989 (ZC_ACK_CLAN_LEAVE)
+ */
+static void clif_clan_leave(struct map_session_data *sd)
+{
+#if PACKETVER >= 20131223
+ struct PACKET_ZC_ACK_CLAN_LEAVE p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = clanLeave;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+/**
+ * Clan System: Sends a clan message to a player
+ * 098e <length>.W <name>.24B <message>.?B (ZC_NOTIFY_CLAN_CHAT)
+ */
+static void clif_clan_message(struct clan *c, const char *mes, int len)
+{
+#if PACKETVER >= 20120716
+ struct map_session_data *sd;
+ struct PACKET_ZC_NOTIFY_CLAN_CHAT *p;
+ unsigned int max_len = CHAT_SIZE_MAX - 5 - NAME_LENGTH;
+ int packet_length;
+
+ nullpo_retv(c);
+ nullpo_retv(mes);
+
+ if (len == 0) {
+ return;
+ } else if (len > max_len) {
+ ShowWarning("clif_clan_message: Truncated message '%s' (len=%d, max=%u, clan_id=%d).\n", mes, len, max_len, c->clan_id);
+ len = max_len;
+ }
+
+ packet_length = sizeof(*p) + len + 1;
+ p = (struct PACKET_ZC_NOTIFY_CLAN_CHAT *)aMalloc(packet_length);
+ p->PacketType = clanMessage;
+ p->PacketLength = packet_length;
+ // p->MemberName is being ignored on the client side.
+ safestrncpy(p->Message, mes, len + 1);
+
+ if ((sd = clan->getonlinesd(c)) != NULL)
+ clif->send(p, packet_length, &sd->bl, CLAN);
+ aFree(p);
+#endif
+}
+
+static void clif_parse_ClanMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/**
+ * Clan System: Parses a clan message from a player.
+ * 098d <length>.W <text>.?B (<name> : <message>) (CZ_CLAN_CHAT)
+ */
+static void clif_parse_ClanMessage(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20120716
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
+
+ if (clif->process_chat_message(sd, packet, message, sizeof(message)) == NULL)
+ return;
+
+ clan->send_message(sd, message);
+#endif
+}
+
/* */
-unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
+static unsigned short clif_decrypt_cmd(int cmd, struct map_session_data *sd)
+{
if( sd ) {
return (cmd ^ ((sd->cryptKey >> 16) & 0x7FFF));
}
return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF));
}
-unsigned short clif_parse_cmd_normal( int fd, struct map_session_data *sd ) {
+static unsigned short clif_parse_cmd_normal(int fd, struct map_session_data *sd)
+{
unsigned short cmd = RFIFOW(fd,0);
return cmd;
}
-unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) {
+static unsigned short clif_parse_cmd_decrypt(int fd, struct map_session_data *sd)
+{
unsigned short cmd = RFIFOW(fd,0);
cmd = clif->decrypt_cmd(cmd, sd);
@@ -18801,11 +21913,12 @@ unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) {
return cmd;
}
-unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) {
+static unsigned short clif_parse_cmd_optional(int fd, struct map_session_data *sd)
+{
unsigned short cmd = RFIFOW(fd,0);
// filter out invalid / unsupported packets
- if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) {
+ if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packets->db[cmd] == 0 ) {
if( sd )
sd->parse_cmd_func = clif_parse_cmd_decrypt;
return clif_parse_cmd_decrypt(fd, sd);
@@ -18816,10 +21929,1997 @@ unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) {
return cmd;
}
+/**
+ * Send all of a session's achievement information to client.
+ * Called only once on login/char-loading. (PACKET_ZC_ALL_ACH_LIST)
+ * @packet [out] 0x0A23 <ID>.W <Length>.W <ach_count>.L <total_points>.L <rank>.W <current_rank_points>.L <next_rank_points>.L <struct ach_list_info *[]>.P
+ * @param fd socket descriptor
+ * @param sd pointer to map_session_data
+ */
+static void clif_achievement_send_list(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
+ int i = 0, count = 0, curr_exp_tmp = 0;
+ struct packet_achievement_list p = { 0 };
+
+ nullpo_retv(sd);
+
+ /* Browse through the session's achievement list and gather their values. */
+ for (i = 0; i < VECTOR_LENGTH(sd->achievement); i++) {
+ int j = 0;
+ struct achievement *a = &VECTOR_INDEX(sd->achievement, i);
+ const struct achievement_data *ad = NULL;
+
+ /* Sanity check for nonull pointers. */
+ if (a == NULL || (ad = achievement->get(a->id)) == NULL)
+ continue;
+
+ p.ach[count].ach_id = a->id;
+
+ for (j = 0; j < VECTOR_LENGTH(ad->objective); j++)
+ p.ach[count].objective[j] = a->objective[j];
+
+ if (a->completed_at) {
+ p.ach[count].completed = 1;
+ p.ach[count].completed_at = (uint32) a->completed_at;
+ p.ach[count].reward = a->rewarded_at ? 1 : 0;
+ p.total_points += ad->points;
+ }
+
+ count++;
+ }
+
+ p.packet_id = achievementListType;
+ p.packet_len = sizeof(struct ach_list_info) * count + 22;
+ p.total_achievements = count;
+ /* Determine Achievement Rank and current exp */
+ curr_exp_tmp = p.total_points;
+ for (i = 0; curr_exp_tmp && i < MAX_ACHIEVEMENT_RANKS && i < VECTOR_LENGTH(achievement->rank_exp); i++) {
+ if (curr_exp_tmp >= VECTOR_INDEX(achievement->rank_exp, i)) {
+ curr_exp_tmp -= VECTOR_INDEX(achievement->rank_exp, i);
+ p.rank++;
+
+ // Validate achievement rank type achievements.
+ achievement->validate_achievement_rank(sd, p.rank);
+ }
+ }
+ /* Determine Achievement Rank Exp */
+ p.current_rank_points = curr_exp_tmp;
+ p.next_rank_points = VECTOR_INDEX(achievement->rank_exp, p.rank);
+ /* Send payload */
+ clif->send(&p, p.packet_len, &sd->bl, SELF);
+#endif // PACKETVER >= 20141016
+}
+
+/**
+ * Sends achievement information for a single achievement.
+ * Called on objective progress updates/completion. (PACKET_ZC_ACH_UPDATE)
+ * @packet [out] 0x0A24 <ID>.W <total_points>.L <rank>.W <current_rank_points>.L <next_rank_points>.L <struct ach_list_info *>.P
+ * @param fd socket descriptor
+ * @param sd pointer to struct map_session_data
+ * @param ad const pointer to struct achievement_data from the achievement db.
+ */
+static void clif_achievement_send_update(int fd, struct map_session_data *sd, const struct achievement_data *ad)
+{
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
+ struct packet_achievement_update p = { 0 };
+ struct achievement *a = NULL;
+ int i = 0, points = 0, rank = 0, curr_rank_points = 0;
+
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ /* Get Session Achievement Data */
+ if ((a = achievement->ensure(sd, ad)) == NULL)
+ return;
+
+ /* Get total points, current rank and current rank points from the session. */
+ achievement->calculate_totals(sd, &points, NULL, &rank, &curr_rank_points);
+
+ p.packet_id = achievementUpdateType;
+
+ /* Determine Total Achievement Points */
+ p.total_points = points;
+
+ /* Determine Achievement Rank */
+ p.rank = rank;
+
+ /* Determine Achievement Rank Exp */
+ p.current_rank_points = curr_rank_points;
+ p.next_rank_points = VECTOR_INDEX(achievement->rank_exp, p.rank);
+
+ p.ach.ach_id = ad->id;
+ p.ach.completed = (uint8) achievement->check_complete(sd, ad);
+
+ for (i = 0; i < VECTOR_LENGTH(ad->objective); i++)
+ p.ach.objective[i] = a->objective[i];
+
+ p.ach.completed_at = (uint32) a->completed_at;
+
+ p.ach.reward = a->rewarded_at ? 1 : 0;
+
+ clif->send(&p, packet_len(achievementUpdateType), &sd->bl, SELF);
+
+ /* Validate rank-related achievements */
+ achievement->validate_achievement_rank(sd, rank);
+
+#endif // PACKETVER >= 20141016
+}
+
+/**
+ * Parses achievement reward packet from session.
+ * @packet [in] 0x0A25 <ach_id>.L
+ * @param fd socket descriptor.
+ * @param sd ptr to session data.
+ */
+static void clif_parse_achievement_get_reward(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_achievement_get_reward(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int ach_id = RFIFOL(fd, 2);
+ const struct achievement_data *ad = NULL;
+ struct achievement *ach = NULL;
+
+ if (ach_id <= 0 || (ad = achievement->get(ach_id)) == NULL)
+ return;
+
+ if ((ach = achievement->ensure(sd, ad)) == NULL)
+ return;
+
+ if (achievement->check_complete(sd, ad) && ach->completed_at && ach->rewarded_at == 0) {
+ achievement->get_rewards(sd, ad);
+ }
+}
+
+/**
+ * Sends achievement reward collection acknowledgement to the client.
+ * @packet [out] 0x0A26 <packet_id>.W <received
+ */
+static void clif_achievement_reward_ack(int fd, struct map_session_data *sd, const struct achievement_data *ad)
+{
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
+ struct packet_achievement_reward_ack p = { 0 };
+
+ nullpo_retv(sd);
+ nullpo_retv(ad);
+
+ p.packet_id = achievementRewardAckType;
+ p.failed = 0;
+ p.ach_id = ad->id;
+
+ clif->send(&p, packet_len(achievementRewardAckType), &sd->bl, SELF);
+#endif // PACKETVER >= 20141016
+}
+
+/**
+ * Sends achievement reward collection acknowledgement to the client.
+ * @packet[in] 0x0A2E <packet_id>.W <title_id>.L
+ */
+static void clif_parse_change_title(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_change_title(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ int title_id = RFIFOL(fd, 2);
+
+ if (title_id == sd->status.title_id) { // Same Title
+ return;
+ } else if (title_id < 0) {
+ title_id = 0;
+ }
+
+ clif->change_title_ack(fd, sd, title_id);
+}
+
+/**
+ * [clif_change_title_ack description]
+ * @packet [out] 0x0A2F <packet_id>.W <Result>.B <title_id>.L
+ */
+static void clif_change_title_ack(int fd, struct map_session_data *sd, int title_id)
+{
+#if PACKETVER >= 20141016
+ unsigned char failed = 0;
+
+ if (!achievement->check_title(sd, title_id)) {
+ clif->message(fd, "Title is not yet earned.");
+ failed = 1;
+ }
+
+ sd->status.title_id = title_id;
+
+ WFIFOHEAD(fd, packet_len(0xa2f));
+ WFIFOW(fd, 0) = 0xa2f;
+ WFIFOB(fd, 2) = failed;
+ WFIFOL(fd, 3) = sd->status.title_id;
+ WFIFOSET(fd, packet_len(0xa2f));
+
+ // Update names
+ clif->blname_ack(fd, &sd->bl);
+ clif->blname_ack(0, &sd->bl);
+#endif
+}
+// End of Achievement System
+
+/*==========================================
+ * RoDEX
+ *------------------------------------------*/
+
+static void clif_parse_rodex_open_write_mail(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_open_write_mail(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_OPEN_WRITE_MAIL *rPacket = RFIFOP(fd, 0);
+ int8 result = (rodex->isenabled() == true && sd->npc_id == 0) ? 1 : 0;
+
+ clif->rodex_open_write_mail(fd, rPacket->receiveName, result);
+}
+
+static void clif_rodex_open_write_mail(int fd, const char *receiver_name, int8 result)
+{
+#if PACKETVER >= 20140416
+ struct PACKET_ZC_ACK_OPEN_WRITE_MAIL *sPacket = NULL;
+
+ nullpo_retv(receiver_name);
+
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexopenwrite;
+ safestrncpy(sPacket->receiveName, receiver_name, NAME_LENGTH);
+ sPacket->result = result;
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_parse_rodex_add_item(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_add_item(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_ADD_ITEM_TO_MAIL *rPacket = RFIFOP(fd, 0);
+ int16 idx = rPacket->index - 2;
+
+ rodex->add_item(sd, idx, (int16)rPacket->count);
+}
+
+static void clif_rodex_add_item_result(struct map_session_data *sd, int16 idx, int16 amount, enum rodex_add_item result)
+{
+#if PACKETVER >= 20141119
+ struct PACKET_ZC_ADD_ITEM_TO_MAIL *packet;
+ int fd, j;
+
+ nullpo_retv(sd);
+ if (idx < 0 || idx >= sd->status.inventorySize)
+ return;
+
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(*packet));
+ packet = WFIFOP(fd, 0);
+ memset(packet, 0x0, sizeof(*packet));
+ packet->PacketType = rodexadditem;
+ packet->result = result;
+
+ if (result != RODEX_ADD_ITEM_SUCCESS) { //No need to continue building the packet if it failed
+ WFIFOSET(fd, sizeof(*packet));
+ return;
+ }
+
+ packet->index = idx + 2;
+ packet->count = amount;
+ packet->itemId = sd->status.inventory[idx].nameid;
+ packet->type = itemtype(sd->inventory_data[idx]->type);
+ packet->IsIdentified = sd->status.inventory[idx].identify ? 1 : 0;
+ packet->IsDamaged = (sd->status.inventory[idx].attribute & ATTR_BROKEN) != 0 ? 1 : 0;
+ packet->refiningLevel = sd->status.inventory[idx].refine;
+ for (j = 0; j < ARRAYLENGTH(packet->slot.card); ++j)
+ packet->slot.card[j] = sd->status.inventory[idx].card[j];
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j) {
+ packet->optionData[j].index = sd->status.inventory[idx].option[j].index;
+ packet->optionData[j].param = sd->status.inventory[idx].option[j].param;
+ packet->optionData[j].value = sd->status.inventory[idx].option[j].value;
+ }
+ packet->weight = sd->rodex.tmp.weight / 10;
+ packet->favorite = sd->status.inventory[idx].favorite;
+ packet->location = pc->equippoint(sd, idx);
+ WFIFOSET(fd, sizeof(*packet));
+#endif
+}
+
+static void clif_parse_rodex_remove_item(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_remove_item(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_REMOVE_ITEM_MAIL *rPacket = RFIFOP(fd, 0);
+ int16 idx = rPacket->index - 2;
+
+ rodex->remove_item(sd, idx, (int16)rPacket->cnt);
+}
+
+static void clif_rodex_remove_item_result(struct map_session_data *sd, int16 idx, int16 amount)
+{
+#if PACKETVER >= 20140521
+ struct PACKET_ZC_ACK_REMOVE_ITEM_MAIL *packet;
+ int fd;
+
+ nullpo_retv(sd);
+ Assert_retv(idx >= 0 && idx < sd->status.inventorySize);
+
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(*packet));
+ packet = WFIFOP(fd, 0);
+ packet->PacketType = rodexremoveitem;
+ packet->result = (amount < 0) ? 0 : 1;
+ packet->cnt = (amount < 0) ? 0 : sd->status.inventory[idx].amount - amount;
+ packet->index = idx + 2;
+ packet->weight = sd->rodex.tmp.weight / 10;
+ WFIFOSET(fd, sizeof(*packet));
+#endif
+}
+
+static void clif_parse_rodex_checkname(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_checkname(int fd, struct map_session_data *sd)
+{
+ const struct PACKET_CZ_CHECKNAME *rPacket = RFIFOP(fd, 0);
+ int char_id = 0, base_level = 0;
+ int class = 0;
+ char name[NAME_LENGTH];
+
+ safestrncpy(name, rPacket->Name, NAME_LENGTH);
+
+ rodex->check_player(sd, name, &base_level, &char_id, &class);
+}
+
+static void clif_rodex_checkname_result(struct map_session_data *sd, int char_id, int class_, int base_level, const char *name)
+{
+#if PACKETVER >= 20140521
+ struct PACKET_ZC_CHECKNAME *sPacket;
+ int fd;
+
+ nullpo_retv(sd);
+ nullpo_retv(name);
+
+ fd = sd->fd;
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexcheckplayer;
+ if (char_id == 0) {
+ sPacket->CharId = 0;
+ WFIFOSET(fd, sizeof(*sPacket));
+ return;
+ }
+ sPacket->CharId = char_id;
+ sPacket->Class = class_;
+ sPacket->BaseLevel = base_level;
+#if PACKETVER >= 20160316
+ strncpy(sPacket->Name, name, NAME_LENGTH);
+#endif
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_parse_rodex_send_mail(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_send_mail(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_SEND_MAIL *rPacket = RFIFOP(fd, 0);
+ int8 result;
+
+ if (rPacket->TextcontentsLength + rPacket->Titlelength > rPacket->PacketLength - sizeof(*rPacket)) {
+ result = RODEX_SEND_MAIL_FATAL_ERROR;
+ } else if (rPacket->TextcontentsLength > RODEX_BODY_LENGTH || rPacket->Titlelength > RODEX_TITLE_LENGTH) {
+ result = RODEX_SEND_MAIL_FATAL_ERROR;
+ } else {
+ char rname[NAME_LENGTH] = "";
+ char title[RODEX_TITLE_LENGTH] = "";
+ char body[RODEX_BODY_LENGTH] = "";
+
+ safestrncpy(rname, rPacket->receiveName, NAME_LENGTH);
+ safestrncpy(title, rPacket->string, RODEX_TITLE_LENGTH);
+ safestrncpy(body, &rPacket->string[rPacket->Titlelength], RODEX_BODY_LENGTH);
+
+ result = rodex->send_mail(sd, rname, body, title, rPacket->zeny);
+ }
+
+ if (result != RODEX_SEND_MAIL_SUCCESS)
+ clif->rodex_send_mail_result(fd, sd, result);
+ rodex->clean(sd, 1);
+}
+
+static void clif_rodex_send_mail_result(int fd, struct map_session_data *sd, int8 result)
+{
+#if PACKETVER >= 20131230
+ struct PACKET_ZC_WRITE_MAIL_RESULT *sPacket;
+
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexwriteresult;
+ sPacket->result = result;
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_rodex_send_maillist(int fd, struct map_session_data *sd, int8 open_type, int64 page_start)
+{
+#if PACKETVER >= 20131218
+ struct PACKET_ZC_MAIL_LIST *packet;
+ struct maillistinfo *inner;
+ int16 size = sizeof(*packet);
+ int8 count = 0;
+
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, sizeof(*packet) + (sizeof(*inner) + RODEX_TITLE_LENGTH) * RODEX_MAIL_PER_PAGE);
+ packet = WFIFOP(fd, 0);
+ packet->PacketType = ((page_start == (VECTOR_LENGTH(sd->rodex.messages) - 1)) ? rodexmailList : rodexnextpage);
+#if PACKETVER < 20170419
+ packet->opentype = open_type;
+#endif
+ inner = WFIFOP(fd, size);
+
+ while (page_start >= 0 && count < RODEX_MAIL_PER_PAGE) {
+ struct rodex_message *msg = &VECTOR_INDEX(sd->rodex.messages, page_start);
+ --page_start;
+
+ if (msg->is_deleted)
+ continue;
+
+ inner->MailID = msg->id;
+ inner->Isread = (msg->is_read == true || msg->sender_read == true) ? 1 : 0;
+ inner->type = msg->type;
+#if PACKETVER >= 20170419
+ inner->openType = msg->opentype;
+#else
+ inner->regDateTime = (int)time(NULL) - msg->send_date;
+#endif
+ inner->expireDateTime = msg->expire_date - (int)time(NULL);
+ if (open_type == RODEX_OPENTYPE_RETURN) {
+ inner->expireDateTime += RODEX_EXPIRE;
+ }
+ inner->Titlelength = (int16)strlen(msg->title) + 1;
+ if (open_type != RODEX_OPENTYPE_RETURN) {
+ strncpy(inner->SenderName, msg->sender_name, sizeof(inner->SenderName));
+ } else {
+ strncpy(inner->SenderName, msg->receiver_name, sizeof(inner->SenderName));
+ }
+ strncpy(inner->title, msg->title, inner->Titlelength);
+ size += sizeof(*inner) + inner->Titlelength;
+ inner = WFIFOP(fd, size);
+ ++count;
+ }
+
+ packet->PacketLength = size;
+#if PACKETVER < 20170419
+ packet->cnt = count;
+#endif
+ packet->IsEnd = page_start > 0 ? 0 : 1;
+ WFIFOSET(fd, size);
+#endif
+}
+
+static void clif_rodex_send_mails_all(int fd, struct map_session_data *sd, int64 mail_id)
+{
+#if PACKETVER >= 20170419
+ struct PACKET_ZC_MAIL_LIST *packet;
+ struct maillistinfo *inner;
+ int16 size = sizeof(*packet);
+ int packetMailCount = 0;
+ int mailListCount = 0;
+ int mailsSize, i;
+ int j = -1;
+
+ nullpo_retv(sd);
+
+ mailsSize = VECTOR_LENGTH(sd->rodex.messages);
+
+ if (mail_id > 0)
+ ARR_FIND(0, VECTOR_LENGTH(sd->rodex.messages), j, (VECTOR_INDEX(sd->rodex.messages, j)).id == mail_id);
+
+ WFIFOHEAD(fd, sizeof(*packet) + (sizeof(*inner) + RODEX_TITLE_LENGTH) * RODEX_MAIL_PER_PAGE);
+ packet = WFIFOP(fd, 0);
+ packet->PacketType = rodexmailList;
+ inner = WFIFOP(fd, size);
+
+ i = mailsSize - 1;
+ mailsSize -= (j + 1);
+ while (i > j) {
+ struct rodex_message *msg = &VECTOR_INDEX(sd->rodex.messages, i);
+ --i;
+
+ if (msg->is_deleted)
+ continue;
+
+ inner->MailID = msg->id;
+ inner->Isread = (msg->is_read == true || msg->sender_read == true) ? 1 : 0;
+ inner->type = msg->type;
+ inner->openType = msg->opentype;
+ inner->expireDateTime = msg->expire_date - (int)time(NULL);
+ if (msg->opentype == RODEX_OPENTYPE_RETURN) {
+ inner->expireDateTime += RODEX_EXPIRE;
+ }
+ inner->Titlelength = (int16)strlen(msg->title) + 1;
+ if (msg->opentype != RODEX_OPENTYPE_RETURN) {
+ strncpy(inner->SenderName, msg->sender_name, sizeof(inner->SenderName));
+ } else {
+ strncpy(inner->SenderName, msg->receiver_name, sizeof(inner->SenderName));
+ }
+ strncpy(inner->title, msg->title, inner->Titlelength);
+ size += sizeof(*inner) + inner->Titlelength;
+ inner = WFIFOP(fd, size);
+ packetMailCount ++;
+ mailListCount ++;
+ if (packetMailCount == RODEX_MAIL_PER_PAGE) {
+ packet->PacketLength = size;
+ packet->IsEnd = mailListCount > mailsSize ? 1 : 0;
+ WFIFOSET(fd, size);
+ WFIFOHEAD(fd, sizeof(*packet) + (sizeof(*inner) + RODEX_TITLE_LENGTH) * RODEX_MAIL_PER_PAGE);
+ packet = WFIFOP(fd, 0);
+ packet->PacketType = rodexmailList;
+ size = sizeof(*packet);
+ inner = WFIFOP(fd, size);
+ packetMailCount = 0;
+ }
+ }
+
+ if (packetMailCount > 0 || mailListCount == 0) {
+ packet->PacketLength = size;
+ packet->IsEnd = 1;
+ WFIFOSET(fd, size);
+ }
+#endif
+}
+
+static void clif_rodex_send_refresh(int fd, struct map_session_data *sd, int8 open_type, int count)
+{
+#if PACKETVER >= 20131218
+ struct PACKET_ZC_MAIL_LIST *packet;
+ struct maillistinfo *inner;
+ int16 size = sizeof(*packet);
+ int i, j;
+
+ nullpo_retv(sd);
+
+ WFIFOHEAD(fd, sizeof(*packet) + (sizeof(*inner) + RODEX_TITLE_LENGTH) * RODEX_MAIL_PER_PAGE);
+ packet = WFIFOP(fd, 0);
+ packet->PacketType = rodexmailList;
+#if PACKETVER < 20170419
+ packet->opentype = open_type;
+#endif
+ inner = WFIFOP(fd, size);
+
+ i = VECTOR_LENGTH(sd->rodex.messages) - 1;
+ j = count;
+ while (i >= 0 && j > 0) {
+ struct rodex_message *msg = &VECTOR_INDEX(sd->rodex.messages, i);
+ --i;
+
+ if (msg->is_deleted)
+ continue;
+
+ inner->MailID = msg->id;
+ inner->Isread = (msg->is_read == true || msg->sender_read == true) ? 1 : 0;
+ inner->type = msg->type;
+#if PACKETVER >= 20170419
+ inner->openType = msg->opentype;
+#else
+ inner->regDateTime = (int)time(NULL) - msg->send_date;
+#endif
+ inner->expireDateTime = msg->expire_date - (int)time(NULL);
+ if (open_type == RODEX_OPENTYPE_RETURN) {
+ inner->expireDateTime += RODEX_EXPIRE;
+ }
+ inner->Titlelength = (int16)strlen(msg->title) + 1;
+ if (open_type != RODEX_OPENTYPE_RETURN) {
+ strncpy(inner->SenderName, msg->sender_name, sizeof(inner->SenderName));
+ } else {
+ strncpy(inner->SenderName, msg->receiver_name, sizeof(inner->SenderName));
+ }
+ strncpy(inner->title, msg->title, inner->Titlelength);
+ size += sizeof(*inner) + inner->Titlelength;
+ inner = WFIFOP(fd, size);
+ --j;
+ }
+
+ packet->PacketLength = size;
+#if PACKETVER < 20170419
+ packet->cnt = count;
+#endif
+ packet->IsEnd = 1;
+ WFIFOSET(fd, size);
+#endif
+}
+
+static void clif_parse_rodex_next_maillist(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_next_maillist(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_NEXT_MAIL_LIST *packet = RFIFOP(fd, 0);
+
+ rodex->next_page(sd, packet->opentype, packet->Lower_MailID);
+}
+
+static void clif_parse_rodex_read_mail(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_read_mail(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_READ_MAIL *rPacket = RFIFOP(fd, 0);
+
+ rodex->read_mail(sd, rPacket->MailID);
+}
+
+static void clif_rodex_read_mail(struct map_session_data *sd, int8 opentype, struct rodex_message *msg)
+{
+#if PACKETVER >= 20140115
+ struct PACKET_ZC_READ_MAIL *sPacket;
+ struct mail_item *item;
+ int fd, i, body_len, size;
+
+ nullpo_retv(sd);
+ nullpo_retv(msg);
+
+ fd = sd->fd;
+ body_len = (int)strlen(msg->body) + 1;
+ size = sizeof(*sPacket);
+
+ WFIFOHEAD(fd, sizeof(*sPacket) + body_len + (sizeof(*item) * RODEX_MAX_ITEM));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexread;
+ sPacket->opentype = opentype;
+ sPacket->MailID = msg->id;
+ sPacket->TextcontentsLength = body_len;
+ sPacket->zeny = msg->zeny;
+ sPacket->ItemCnt = msg->items_count;
+ strncpy(WFIFOP(fd, size), msg->body, body_len);
+ size += body_len;
+ for (i = 0; i < RODEX_MAX_ITEM; ++i) {
+ struct item *it = &msg->items[i].item;
+ struct item_data *data;
+ int j, k;
+
+ if (it->nameid == 0)
+ continue;
+ data = itemdb->search(it->nameid);
+ if (data == NULL)
+ continue;
+
+ item = WFIFOP(fd, size);
+ memset(item, 0x0, sizeof(*item));
+ item->ITID = it->nameid;
+ item->count = it->amount;
+ item->type = itemtype(itemdb->search(it->nameid)->type);
+ item->IsIdentified = it->identify ? 1 : 0;
+ item->IsDamaged = (it->attribute & ATTR_BROKEN) != 0 ? 1 : 0;
+ item->refiningLevel = it->refine;
+ item->location = pc->item_equippoint(sd, data);
+ item->viewSprite = data->view_sprite;
+ item->bindOnEquip = it->bound ? 2 : data->flag.bindonequip ? 1 : 0;
+ for (k = 0; k < MAX_SLOTS; ++k) {
+ item->slot.card[k] = it->card[k];
+ }
+ for (j = 0; j < MAX_ITEM_OPTIONS; ++j) {
+ item->optionData[j].index = it->option[j].index;
+ item->optionData[j].value = it->option[j].value;
+ }
+
+ size += sizeof(*item);
+ }
+ sPacket->PacketLength = size;
+ WFIFOSET(fd, size);
+#endif
+}
+
+static void clif_parse_rodex_delete_mail(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_delete_mail(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_DELETE_MAIL *rPacket = RFIFOP(fd, 0);
+
+ rodex->delete_mail(sd, rPacket->MailID);
+}
+
+static void clif_rodex_delete_mail(struct map_session_data *sd, int8 opentype, int64 mail_id)
+{
+#if PACKETVER >= 20131218
+ struct PACKET_ZC_ACK_DELETE_MAIL *sPacket;
+ int fd;
+
+ nullpo_retv(sd);
+
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexdelete;
+ sPacket->opentype = opentype;
+ sPacket->MailID = mail_id;
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_parse_rodex_request_zeny(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_request_zeny(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_ZENY_FROM_MAIL *rPacket = RFIFOP(fd, 0);
+
+ rodex->get_zeny(sd, rPacket->opentype, rPacket->MailID);
+}
+
+static void clif_rodex_request_zeny(struct map_session_data *sd, int8 opentype, int64 mail_id, enum rodex_get_zeny result)
+{
+#if PACKETVER >= 20140409
+ struct PACKET_ZC_ACK_ZENY_FROM_MAIL *sPacket;
+ int fd;
+
+ nullpo_retv(sd);
+
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexgetzeny;
+ sPacket->MailID = mail_id;
+ sPacket->opentype = opentype;
+ sPacket->result = result;
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_parse_rodex_request_items(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_request_items(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_ITEM_FROM_MAIL *rPacket = RFIFOP(fd, 0);
+
+ rodex->get_items(sd, rPacket->opentype, rPacket->MailID);
+}
+
+static void clif_rodex_request_items(struct map_session_data *sd, int8 opentype, int64 mail_id, enum rodex_get_items result)
+{
+#if PACKETVER >= 20140409
+ struct PACKET_ZC_ACK_ITEM_FROM_MAIL *sPacket;
+ int fd;
+
+ nullpo_retv(sd);
+
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, sizeof(*sPacket));
+ sPacket = WFIFOP(fd, 0);
+ sPacket->PacketType = rodexgetitem;
+ sPacket->MailID = mail_id;
+ sPacket->opentype = opentype;
+ sPacket->result = result;
+ WFIFOSET(fd, sizeof(*sPacket));
+#endif
+}
+
+static void clif_rodex_icon(int fd, bool show)
+{
+// packet add date is 20140716, but from players reports it wrong. Using closer known correct version.
+#if PACKETVER >= 20141112
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = rodexicon;
+ WFIFOB(fd, 2) = (show == true ? 1 : 0);
+ WFIFOSET(fd, 3);
+#endif
+}
+
+static void clif_parse_rodex_refresh_maillist(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_refresh_maillist(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_REFRESH_MAIL_LIST *packet = RFIFOP(fd, 0);
+#if PACKETVER >= 20170419
+ rodex->refresh(sd, RODEX_OPENTYPE_UNSET, packet->Upper_MailID);
+#else
+ rodex->refresh(sd, packet->opentype, packet->Upper_MailID);
+#endif
+}
+
+static void clif_parse_rodex_open_mailbox(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_open_mailbox(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_OPEN_MAIL *packet = RFIFOP(fd, 0);
+#if PACKETVER >= 20170419
+ rodex->open(sd, RODEX_OPENTYPE_UNSET, packet->char_Upper_MailID);
+#else
+ rodex->open(sd, packet->opentype, packet->Upper_MailID);
+#endif
+ rodex->clean(sd, 1);
+}
+
+static void clif_parse_rodex_close_mailbox(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_close_mailbox(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ rodex->clean(sd, 0);
+ intif->rodex_checkhasnew(sd);
+}
+
+static void clif_parse_rodex_cancel_write_mail(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_rodex_cancel_write_mail(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ rodex->clean(sd, 1);
+}
+
+static void clif_skill_scale(struct block_list *bl, int src_id, int x, int y, uint16 skill_id, uint16 skill_lv, int casttime)
+{
+#if PACKETVER >= 20151223
+ struct PACKET_ZC_SKILL_SCALE p;
+
+ p.PacketType = skillscale;
+ p.AID = src_id;
+ p.skill_id = skill_id;
+ p.skill_lv = skill_lv;
+ p.x = x;
+ p.y = y;
+ p.casttime = casttime;
+
+ if (clif->isdisguised(bl)) {
+ clif->send(&p, sizeof(p), bl, AREA_WOS);
+ p.AID = -src_id;
+ clif->send(&p, sizeof(p), bl, SELF);
+ } else {
+ clif->send(&p, sizeof(p), bl, AREA);
+ }
+#else
+ ShowWarning("clif_skill_scale: showing skill scale available only for clients >= 20151223.");
+ return;
+#endif
+}
+
+/// Send hat effects to the client (ZC_HAT_EFFECT).
+/// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W }
+static void clif_hat_effect(struct block_list *bl, struct block_list *tbl, enum send_target target)
+{
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+ nullpo_retv(bl);
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ nullpo_retv(sd);
+
+ const int len = sizeof(struct PACKET_ZC_HAT_EFFECT) + VECTOR_LENGTH(sd->hatEffectId) * 2;
+ struct PACKET_ZC_HAT_EFFECT *p = aMalloc(len);
+
+ p->packetType = HEADER_ZC_HAT_EFFECT;
+ p->packetLength = len;
+ p->aid = bl->id;
+ p->status = 1;
+
+ for (int i = 0; i < VECTOR_LENGTH(sd->hatEffectId); i++) {
+ p->effects[i] = VECTOR_INDEX(sd->hatEffectId, i);
+ }
+
+ if (tbl != NULL) {
+ clif->send(p, len, tbl, target);
+ } else {
+ clif->send(p, len, bl, target);
+ }
+ aFree(p);
+#endif
+}
+
+static void clif_hat_effect_single(struct block_list *bl, uint16 effectId, bool enable){
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+ nullpo_retv(bl);
+
+ const int len = sizeof(struct PACKET_ZC_HAT_EFFECT) + 2;
+ struct PACKET_ZC_HAT_EFFECT *p = aMalloc(len);
+
+ p->packetType = HEADER_ZC_HAT_EFFECT;
+ p->packetLength = len;
+ p->aid = bl->id;
+ p->status = enable;
+ p->effects[0] = effectId;
+
+ clif->send(p, len, bl, AREA);
+ aFree(p);
+#endif
+}
+
+static bool clif_parse_attendance_db(void)
+{
+ struct config_t attendance_conf;
+ struct config_setting_t *attendance = NULL, *it = NULL;
+ char config_filename[256];
+ libconfig->format_db_path("attendance_db.conf", config_filename, sizeof(config_filename));
+ int i = 0;
+
+ if (!libconfig->load_file(&attendance_conf, config_filename))
+ return false;
+ attendance = libconfig->lookup(&attendance_conf, "attendance_db");
+
+ VECTOR_CLEAR(clif->attendance_data);
+
+ while ((it = libconfig->setting_get_elem(attendance, i++))) {
+ clif->attendancedb_libconfig_sub(it, i, config_filename);
+ }
+
+ libconfig->destroy(&attendance_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename);
+ return true;
+}
+
+static bool clif_attendancedb_libconfig_sub(struct config_setting_t *it, int n, const char *source)
+{
+ struct attendance_entry entry = { 0 };
+ int i32 = 0;
+
+ nullpo_ret(it);
+ nullpo_ret(source);
+
+ if (!itemdb->lookup_const(it, "ItemID", &i32) || i32 < 0) {
+ ShowWarning("clif_attendancedb_libconfig_sub: unknown item %d, entry #%d, skipping.\n", i32, n);
+ return false;
+ }
+ entry.nameid = i32;
+
+ if (!libconfig->setting_lookup_int(it, "Amount", &i32) || i32 < 1) {
+ ShowWarning("clif_attendancedb_libconfig_sub: invalid amount %d, entry #%d, skipping.\n", i32, n);
+ return false;
+ }
+ entry.qty = i32;
+
+ VECTOR_ENSURE(clif->attendance_data, 1, 1);
+ VECTOR_PUSH(clif->attendance_data, entry);
+ return true;
+}
+
+static bool clif_attendance_timediff(struct map_session_data *sd)
+{
+ int64 timediff;
+
+ nullpo_retr(false, sd);
+
+ timediff = (time(NULL) / (60 * 60 * 24)) - (sd->status.attendance_timer / (60 * 60 * 24));
+
+ if (timediff <= 0)
+ return false;
+ return true;
+}
+static time_t clif_attendance_getendtime(void)
+{
+ time_t timestamp;
+ struct tm tmtime = { 0 };
+ int year = 0, month = 0, day = 0;
+ char timestring[9];
+
+ sprintf(timestring, "%8d", battle_config.feature_attendance_endtime);
+ sscanf(timestring, "%4d%2d%2d", &year, &month, &day);
+
+ tmtime.tm_year = year - 1900;
+ tmtime.tm_mon = month - 1;
+ tmtime.tm_mday = day;
+
+ timestamp = mktime(&tmtime);
+
+ return timestamp;
+}
+
+static void clif_parse_open_ui_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_open_ui_request(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_OPEN_UI *p = RP2PTR(fd);
+
+ clif->open_ui(sd, p->UIType);
+}
+
+static void clif_open_ui(struct map_session_data *sd, enum cz_ui_types uiType)
+{
+#if PACKETVER >= 20150128
+ struct PACKET_ZC_OPEN_UI p;
+#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411
+ int claimed = 0;
+#endif
+
+ nullpo_retv(sd);
+
+ p.PacketType = openUiType;
+ switch (uiType) {
+ case CZ_STYLIST_UI:
+ p.UIType = ZC_STYLIST_UI;
+#if PACKETVER >= 20171122
+ p.data = 0;
+#endif
+ break;
+ case CZ_MACRO_REGISTER_UI:
+ p.UIType = ZC_CAPTCHA_UI;
+#if PACKETVER >= 20171122
+ p.data = 0;
+#endif
+ break;
+ case CZ_MACRO_DETECTOR_UI:
+ p.UIType = ZC_MACRO_UI;
+#if PACKETVER >= 20171122
+ p.data = 0;
+#endif
+ break;
+ case CZ_ATTENDANCE_UI:
+ {
+ if (clif->attendance_getendtime() < time(NULL)) {
+#if PACKETVER >= 20180207
+ clif->msgtable_color(sd, MSG_ATTENDANCE_UNAVAILABLE, COLOR_RED);
+#endif
+ return;
+ }
+ if (battle_config.feature_enable_attendance_system != 1)
+ return;
+#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411
+ if (clif->attendance_timediff(sd) != true)
+ ++claimed;
+ else if (sd->status.attendance_count >= VECTOR_LENGTH(clif->attendance_data))
+ sd->status.attendance_count = 0;
+ p.UIType = ZC_ATTENDANCE_UI;
+ p.data = sd->status.attendance_count * 10 + claimed;
+#else
+ ShowWarning("Attendance System available only for PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411.\n");
+ return;
+#endif
+ break;
+ }
+ default:
+ ShowWarning("clif_open_ui: Requested UI (%u) is not implemented yet.\n", uiType);
+ return;
+ }
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ struct rodex_message msg = { 0 };
+ struct attendance_entry *entry;
+ int attendance_count;
+ char title[RODEX_TITLE_LENGTH], body[MAIL_BODY_LENGTH];
+
+ if (clif->attendance_getendtime() < time(NULL)) {
+ clif->msgtable_color(sd, MSG_ATTENDANCE_UNAVAILABLE, COLOR_RED);
+ return;
+ }
+
+ if (battle_config.feature_enable_attendance_system != 1)
+ return;
+
+ if (clif->attendance_timediff(sd) != true)
+ return;
+
+ if (sd->status.attendance_count >= VECTOR_LENGTH(clif->attendance_data))
+ sd->status.attendance_count = 0;
+
+ attendance_count = sd->status.attendance_count;
+ ++sd->status.attendance_count;
+ sd->status.attendance_timer = time(NULL);
+
+ msg.receiver_id = sd->status.char_id;
+ sprintf(title, msg_txt(545), attendance_count + 1);
+ sprintf(body, msg_txt(545), attendance_count + 1);
+
+ entry = &VECTOR_INDEX(clif->attendance_data, attendance_count);
+ msg.items[0].item.nameid = entry->nameid;
+ msg.items[0].item.amount = entry->qty;
+ msg.items[0].item.identify = 1;
+ msg.type = MAIL_TYPE_NPC | MAIL_TYPE_ITEM;
+
+ safestrncpy(msg.sender_name, msg_txt(544), NAME_LENGTH);
+ safestrncpy(msg.title, title, RODEX_TITLE_LENGTH);
+ safestrncpy(msg.body, body, MAIL_BODY_LENGTH);
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+ clif->ui_action(sd, 0, sd->status.attendance_count);
+#else
+ ShowWarning("Attendance System available only for PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404 || PACKETVER_ZERO_NUM >= 20180411.\n");
+#endif
+}
+
+static void clif_parse_cz_blocking_play_cancel(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_cz_blocking_play_cancel(int fd, struct map_session_data *sd)
+{
+ clif->loadConfirm(sd);
+}
+
+static void clif_loadConfirm(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320 || PACKETVER_ZERO_NUM >= 20190410
+ nullpo_retv(sd);
+ struct PACKET_ZC_LOAD_CONFIRM p;
+ p.packetType = HEADER_ZC_LOAD_CONFIRM;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static void clif_ui_action(struct map_session_data *sd, int32 UIType, int32 data)
+{
+
+ struct PACKET_ZC_UI_ACTION p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0xAF0;
+ p.UIType = UIType;
+ p.data = data;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+}
+
+static void clif_parse_private_airship_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_private_airship_request(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180321 || PACKETVER_MAIN_NUM >= 20180620 || defined(PACKETVER_ZERO)
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+ const struct PACKET_CZ_PRIVATE_AIRSHIP_REQUEST *p = RP2PTR(fd);
+
+ safestrncpy(evname, "private_airship::OnAirShipRequest", EVENT_NAME_LENGTH);
+ if ((ev = strdb_get(npc->ev_db, evname))) {
+ pc->setregstr(sd, script->add_variable("@mapname$"), p->mapName);
+ pc->setreg(sd, script->add_variable("@itemid"), p->ItemID);
+ script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ } else {
+ ShowError("clif_parse_private_airship_request: event '%s' not found, operation failed.\n", evname);
+ }
+#else
+ ShowWarning("clif_parse_private_airship_request: private airship is not supported in this client version, possible packet manipulation.\n");
+#endif
+}
+
+static void clif_private_airship_response(struct map_session_data *sd, uint32 flag)
+{
+#if PACKETVER_RE_NUM >= 20180321 || PACKETVER_MAIN_NUM >= 20180620 || defined(PACKETVER_ZERO)
+ struct PACKET_ZC_PRIVATE_AIRSHIP_RESPONSE p;
+
+ nullpo_retv(sd);
+
+ if (flag > P_AIRSHIP_ITEM_INVALID) {
+ ShowError("clif_private_airship_response: invalid flag given '%u', defaulting to 0.\n", flag);
+ flag = 0;
+ }
+
+ p.PacketType = 0xA4A;
+ p.flag = flag;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#else
+ ShowWarning("clif_private_airship_response: private airship works only for clients PACKETVER_RE_NUM >= 20180321 || PACKETVER_MAIN_NUM >= 20180620.\n");
+#endif
+}
+
+static void clif_parse_cz_req_style_change(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_cz_req_style_change(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_STYLE_CHANGE *p = RP2PTR(fd);
+
+ if (p->HeadStyle > 0)
+ stylist->request_style_change(sd, LOOK_HAIR, p->HeadStyle, false);
+ if (p->HeadPalette > 0)
+ stylist->request_style_change(sd, LOOK_HAIR_COLOR, p->HeadPalette, false);
+ if (p->BodyPalette > 0)
+ stylist->request_style_change(sd, LOOK_CLOTHES_COLOR, p->BodyPalette, false);
+ if (p->TopAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_TOP, p->TopAccessory, true);
+ if (p->MidAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_MID, p->MidAccessory, true);
+ if (p->BottomAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_BOTTOM, p->BottomAccessory, true);
+ clif->style_change_response(sd, STYLIST_SHOP_SUCCESS);
+ return;
+}
+
+static void clif_parse_cz_req_style_change2(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_cz_req_style_change2(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_REQ_STYLE_CHANGE2 *p = RP2PTR(fd);
+
+ if (p->HeadStyle > 0)
+ stylist->request_style_change(sd, LOOK_HAIR, p->HeadStyle, false);
+ if (p->HeadPalette > 0)
+ stylist->request_style_change(sd, LOOK_HAIR_COLOR, p->HeadPalette, false);
+ if (p->BodyPalette > 0)
+ stylist->request_style_change(sd, LOOK_CLOTHES_COLOR, p->BodyPalette, false);
+ if (p->TopAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_TOP, p->TopAccessory, true);
+ if (p->MidAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_MID, p->MidAccessory, true);
+ if (p->BottomAccessory > 0)
+ stylist->request_style_change(sd, LOOK_HEAD_BOTTOM, p->BottomAccessory, true);
+ if (p->BodyStyle > 0) {
+ if (pc->has_second_costume(sd)) {
+ stylist->request_style_change(sd, LOOK_BODY2, p->BodyStyle, false);
+ }
+ }
+ clif->style_change_response(sd, STYLIST_SHOP_SUCCESS);
+ return;
+}
+
+static void clif_parse_cz_style_close(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_cz_style_close(int fd, struct map_session_data *sd)
+{
+ // do nothing
+}
+
+static void clif_style_change_response(struct map_session_data *sd, enum stylist_shop flag)
+{
+#if PACKETVER >= 20151104
+ struct PACKET_ZC_STYLE_CHANGE_RES p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0x0a47;
+ p.flag = flag;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#else
+ ShowWarning("clif_style_change_response: unsupported client version is being used.");
+#endif
+}
+
+static void clif_overweight_percent(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20171108 || PACKETVER_RE_NUM >= 20171025 || PACKETVER_ZERO_NUM >= 20171019
+ struct PACKET_ZC_OVERWEIGHT_PERCENT p;
+
+ nullpo_retv(sd);
+
+ p.packetType = 0xade;
+ p.percent = battle_config.natural_heal_weight_rate;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static void clif_parse_changeDress(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+/// 0ae8 <packet len>.W
+static void clif_parse_changeDress(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const char commandname[] = "changedress";
+ char command[sizeof commandname + 3] = ""; // '@' command + ' ' + NUL
+
+ sprintf(command, "%c%s ", atcommand->at_symbol, commandname);
+ atcommand->exec(fd, sd, command, true);
+}
+
+static void clif_party_dead_notification(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ struct PACKET_ZC_GROUP_ISALIVE p;
+
+ nullpo_retv(sd);
+
+ p.packetType = 0xab2;
+ p.AID = sd->bl.id;
+ p.isDead = pc_isdead(sd);
+ clif->send(&p, sizeof(p), &sd->bl, PARTY_WOS);
+#endif
+}
+
+static void clif_parse_memorial_dungeon_command(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_memorial_dungeon_command(int fd, struct map_session_data *sd)
+{
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_MEMORIALDUNGEON_COMMAND *p = RP2PTR(fd);
+
+ switch (p->command) {
+ case COMMAND_MEMORIALDUNGEON_DESTROY_FORCE:
+ instance->force_destroy(sd);
+ }
+}
+
+static void clif_camera_showWindow(struct map_session_data *sd)
+{
+#if PACKETVER >= 20160525
+ nullpo_retv(sd);
+ struct PACKET_ZC_CAMERA_INFO p;
+ p.packetType = HEADER_ZC_CAMERA_INFO;
+ p.action = 1;
+ p.range = 0;
+ p.rotation = 0;
+ p.latitude = 0;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static void clif_camera_change(struct map_session_data *sd, float range, float rotation, float latitude, enum send_target target)
+{
+#if PACKETVER >= 20160525
+ nullpo_retv(sd);
+ struct PACKET_ZC_CAMERA_INFO p;
+ p.packetType = HEADER_ZC_CAMERA_INFO;
+ p.action = 0;
+ p.range = range;
+ p.rotation = rotation;
+ p.latitude = latitude;
+ clif->send(&p, sizeof(p), &sd->bl, target);
+#endif
+}
+
+static void clif_parse_cameraInfo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_cameraInfo(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20160525
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_CAMERA_INFO *const p = RFIFOP(fd, 0);
+ char command[100];
+ if (p->action == 1) {
+ sprintf(command, "%ccamerainfo", atcommand->at_symbol);
+ } else {
+ sprintf(command, "%ccamerainfo %15f %15f %15f", atcommand->at_symbol, p->range, p->rotation, p->latitude);
+ }
+ atcommand->exec(fd, sd, command, true);
+#endif
+}
+
+// show item preview in already opened preview window
+static void clif_item_preview(struct map_session_data *sd, int n)
+{
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+ Assert_retv(n >= 0 && n < sd->status.inventorySize);
+
+ struct PACKET_ZC_ITEM_PREVIEW p;
+ p.packetType = HEADER_ZC_ITEM_PREVIEW;
+ p.index = n + 2;
+#if PACKETVER_MAIN_NUM >= 20181017 || PACKETVER_RE_NUM >= 20181017 || PACKETVER_ZERO_NUM >= 20181024
+ p.isDamaged = (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ? 1 : 0;
+#endif
+ p.refiningLevel = sd->status.inventory[n].refine;
+ clif->addcards(&p.slot, &sd->status.inventory[n]);
+ clif->add_item_options(&p.option_data[0], &sd->status.inventory[n]);
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+// insert cardId into equipped item in pos equipment slot into slot cardSlot.
+static bool clif_enchant_equipment(struct map_session_data *sd, enum equip_pos pos, int cardSlot, int cardId)
+{
+#if PACKETVER_MAIN_NUM >= 20160831 || PACKETVER_RE_NUM >= 20151118 || defined(PACKETVER_ZERO)
+ nullpo_ret(sd);
+ Assert_ret(cardSlot >= 0 && cardSlot < MAX_SLOTS);
+ struct PACKET_ZC_ENCHANT_EQUIPMENT p;
+ p.packetType = HEADER_ZC_ENCHANT_EQUIPMENT;
+ p.wearState = pos;
+ p.cardSlot = cardSlot;
+ p.itemId = cardId;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+ return true;
+#else
+ return false;
+#endif
+}
+
+static void clif_npc_barter_open(struct map_session_data *sd, struct npc_data *nd)
+{
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+ nullpo_retv(sd);
+ nullpo_retv(nd);
+ struct npc_item_list *shop = nd->u.scr.shop->item;
+ const int shop_size = nd->u.scr.shop->items;
+
+ int c = 0;
+ int maxCount = (sizeof(packet_buf) - sizeof(struct PACKET_ZC_NPC_BARTER_OPEN)) / sizeof(struct PACKET_ZC_NPC_BARTER_OPEN_sub);
+ struct PACKET_ZC_NPC_BARTER_OPEN *packet = (struct PACKET_ZC_NPC_BARTER_OPEN*)&packet_buf[0];
+ packet->packetType = HEADER_ZC_NPC_BARTER_OPEN;
+
+ for (int i = 0; i < shop_size && c < maxCount; i++) {
+ if (shop[i].nameid) {
+ struct item_data *id = itemdb->exists(shop[i].nameid);
+ if (id == NULL)
+ continue;
+
+ packet->list[c].nameid = shop[i].nameid;
+ packet->list[c].type = itemtype(id->type);
+ packet->list[c].amount = shop[i].qty;
+ packet->list[c].currencyNameid = shop[i].value;
+ packet->list[c].currencyAmount = shop[i].value2;
+ packet->list[c].weight = id->weight * 10;
+ packet->list[c].index = i;
+ c++;
+ }
+ }
+
+ packet->packetLength = sizeof(struct PACKET_ZC_NPC_BARTER_OPEN) + sizeof(struct PACKET_ZC_NPC_BARTER_OPEN_sub) * c;
+ clif->send(packet, packet->packetLength, &sd->bl, SELF);
+#endif
+}
+
+static void clif_parse_NPCBarterPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_NPCBarterPurchase(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_NPC_BARTER_PURCHASE *p = RP2PTR(fd);
+ int count = (p->packetLength - sizeof(struct PACKET_CZ_NPC_BARTER_PURCHASE)) / sizeof p->list[0];
+ struct barteritemlist item_list;
+
+ Assert_retv(count >= 0 && count <= sd->status.inventorySize);
+
+ VECTOR_INIT(item_list);
+ VECTOR_ENSURE(item_list, count, 1);
+
+ for (int i = 0; i < count; i++) {
+ struct barter_itemlist_entry entry = { 0 };
+ entry.addId = p->list[i].itemId;
+ entry.addAmount = p->list[i].amount;
+ entry.removeIndex = p->list[i].invIndex - 2;
+ entry.shopIndex = p->list[i].shopIndex;
+
+ VECTOR_PUSH(item_list, entry);
+ }
+
+ int response = npc->barter_buylist(sd, &item_list);
+ clif->npc_buy_result(sd, response);
+
+ VECTOR_CLEAR(item_list);
+#endif
+}
+
+static void clif_parse_npc_expanded_barter_closed(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_npc_expanded_barter_closed(int fd, struct map_session_data *sd)
+{
+}
+
+#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
+#define NEXT_EXPANDED_BARTER_ITEM(var, count) \
+ var = (struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub *)((char*)item + \
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) - \
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) + \
+ count * sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2))
+#endif
+
+static void clif_npc_expanded_barter_open(struct map_session_data *sd, struct npc_data *nd)
+{
+#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
+ nullpo_retv(sd);
+ nullpo_retv(nd);
+ struct npc_item_list *shop = nd->u.scr.shop->item;
+ const int shop_size = nd->u.scr.shop->items;
+
+ int items_count = 0;
+ int currencies_count = 0;
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN *packet = (struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN*)&packet_buf[0];
+ STATIC_ASSERT(sizeof(packet_buf) > sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN), "packet_buf size too small");
+ int buf_left = sizeof(packet_buf) - sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN);
+ packet->packetType = HEADER_ZC_NPC_EXPANDED_BARTER_OPEN;
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub *item = &packet->items[0];
+
+ // Workaround for fix Visual Studio bug (error C2233)
+ // Here should be sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub)
+ const int ptr_size = sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) -
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2);
+ for (int i = 0; i < shop_size && buf_left >= ptr_size; i++) {
+ if (shop[i].nameid) {
+ struct item_data *id = itemdb->exists(shop[i].nameid);
+ if (id == NULL)
+ continue;
+
+ item->nameid = shop[i].nameid;
+ item->type = itemtype(id->type);
+ item->amount = shop[i].qty;
+ item->weight = id->weight * 10;
+ item->index = i;
+ item->zeny = shop[i].value;
+ item->currency_count = 0;
+ buf_left -= ptr_size;
+ items_count ++;
+ int count = shop[i].value2;
+ if (buf_left < sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) * count) {
+ NEXT_EXPANDED_BARTER_ITEM(item, 0);
+ break;
+ }
+ for (int j = 0; j < count; j ++) {
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 *packet_currency = &item->currencies[j];
+ struct npc_barter_currency *currency = &shop[i].currency[j];
+ struct item_data *id2 = itemdb->exists(currency->nameid);
+ if (id2 == NULL)
+ continue;
+ packet_currency->nameid = currency->nameid;
+ if (currency->refine == -1)
+ packet_currency->refine_level = 0;
+ else
+ packet_currency->refine_level = currency->refine;
+ packet_currency->amount = currency->amount;
+ packet_currency->type = itemtype(id2->type);
+ currencies_count ++;
+ item->currency_count ++;
+ }
+ NEXT_EXPANDED_BARTER_ITEM(item, item->currency_count);
+ }
+ }
+
+ packet->items_count = items_count;
+ packet->packetLength = sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN) +
+ ptr_size * items_count +
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) * currencies_count;
+ clif->send(packet, packet->packetLength, &sd->bl, SELF);
+#endif
+}
+
+#undef NEXT_EXPANDED_BARTER_ITEM
+
+static void clif_parse_npc_expanded_barter_purchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_npc_expanded_barter_purchase(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ const struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE *const p = RP2PTR(fd);
+ int count = (p->packetLength - sizeof(struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE)) / sizeof p->list[0];
+ struct barteritemlist item_list;
+
+ Assert_retv(count >= 0 && count <= sd->status.inventorySize);
+
+ VECTOR_INIT(item_list);
+ VECTOR_ENSURE(item_list, count, 1);
+
+ for (int i = 0; i < count; i++) {
+ struct barter_itemlist_entry entry = { 0 };
+ entry.addId = p->list[i].itemId;
+ entry.addAmount = p->list[i].amount;
+ entry.removeIndex = -1;
+ entry.shopIndex = p->list[i].shopIndex;
+ VECTOR_PUSH(item_list, entry);
+ }
+
+ int response = npc->expanded_barter_buylist(sd, &item_list);
+ clif->npc_buy_result(sd, response);
+
+ VECTOR_CLEAR(item_list);
+#endif
+}
+
+static void clif_parse_clientVersion(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_clientVersion(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20090406 || PACKETVER_RE_NUM >= 20090408 || PACKETVER_SAK_NUM >= 20090408 || defined(PACKETVER_ZERO)
+ // TODO: show or store client version
+#endif
+}
+
+static void clif_parse_ping(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ping(int fd, struct map_session_data *sd)
+{
+ // do nothing, any packet update client tick
+}
+
+static void clif_ping(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190227 || PACKETVER_RE_NUM >= 20190220 || PACKETVER_ZERO_NUM >= 20190220
+ nullpo_retv(sd);
+ struct PACKET_ZC_PING p;
+ p.packetType = HEADER_ZC_PING;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+
+static int clif_pingTimer(int tid, int64 tick, int id, intptr_t data)
+{
+ map->foreachpc(clif->pingTimerSub, time(NULL));
+ return 0;
+}
+
+static int clif_pingTimerSub(struct map_session_data *sd, va_list ap)
+{
+ nullpo_ret(sd);
+ const int fd = sd->fd;
+
+ if (!sockt->session_is_active(fd))
+ {
+ return 0;
+ }
+
+ time_t tick = va_arg(ap, time_t);
+
+ if (sockt->session[fd]->wdata_tick + battle_config.ping_time < tick)
+ {
+ clif->ping(sd);
+ }
+ return 0;
+}
+
+static void clif_parse_ResetCooldown(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_ResetCooldown(int fd, struct map_session_data *sd)
+{
+ char cmd[15];
+ sprintf(cmd,"%ccddebug reset", atcommand->at_symbol);
+ atcommand->exec(fd, sd, cmd, true);
+}
+
+static void clif_OpenRefineryUI(struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+
+ if (battle_config.enable_refinery_ui == 0)
+ return;
+
+ struct PACKET_ZC_REFINE_OPEN_WINDOW p;
+ p.packetType = HEADER_ZC_REFINE_OPEN_WINDOW;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ sd->state.refine_ui = 1;
+#endif
+}
+
+static void clif_parse_AddItemRefineryUI(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_AddItemRefineryUI(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20161005 || PACKETVER_RE_NUM >= 20161005 || defined(PACKETVER_ZERO)
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (battle_config.enable_refinery_ui == 0)
+ return;
+
+ const struct PACKET_CZ_REFINE_ADD_ITEM *p = RFIFO2PTR(fd);
+ refine->refinery_add_item(sd, p->index - 2);
+#endif
+}
+
+static void clif_AddItemRefineryUIAck(struct map_session_data *sd, int item_index, struct s_refine_requirement *req)
+{
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+ nullpo_retv(req);
+ Assert_retv(item_index >= 0 && item_index < sd->status.inventorySize);
+
+ if (battle_config.enable_refinery_ui == 0)
+ return;
+
+ char buf[sizeof(struct PACKET_ZC_REFINE_ADD_ITEM) + sizeof(struct PACKET_ZC_REFINE_ADD_ITEM_SUB) * MAX_REFINE_REQUIREMENTS];
+ struct PACKET_ZC_REFINE_ADD_ITEM *p = (struct PACKET_ZC_REFINE_ADD_ITEM *)buf;
+
+ p->packetType = HEADER_ZC_REFINE_ADD_ITEM;
+ p->packtLength = sizeof(*p) + sizeof(p->req[0]) * req->req_count;
+ p->itemIndex = item_index + 2;
+ p->blacksmithBlessing = req->blacksmith_blessing;
+
+ int weapon_level = itemdb_wlv(sd->status.inventory[item_index].nameid);
+ for (int i = 0; i < req->req_count; ++i) {
+ p->req[i].chance = refine->get_refine_chance(weapon_level, sd->status.inventory[item_index].refine, req->req[i].type);
+ p->req[i].itemId = req->req[i].nameid;
+ p->req[i].zeny = req->req[i].cost;
+ }
+
+ clif->send(p, p->packtLength, &sd->bl, SELF);
+#endif
+}
+
+static void clif_parse_RefineryUIRefine(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_RefineryUIRefine(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20161005 || PACKETVER_RE_NUM >= 20161005 || defined(PACKETVER_ZERO)
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (battle_config.enable_refinery_ui == 0)
+ return;
+
+ const struct PACKET_CZ_REFINE_ITEM_REQUEST *p = RFIFO2PTR(fd);
+ refine->refinery_refine_request(sd, p->index - 2, p->itemId, (p->blacksmithBlessing == 1) ? true : false);
+#endif
+}
+
+static void clif_parse_RefineryUIClose(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_RefineryUIClose(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+ if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ return;
+
+ if (battle_config.enable_refinery_ui == 0)
+ return;
+
+ sd->state.refine_ui = 0;
+ return;
+#endif
+}
+
+static void clif_announce_refine_status(struct map_session_data *sd, int item_id, int refine_level, bool success, enum send_target target)
+{
+#if PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+ nullpo_retv(sd);
+
+ Assert_retv(refine_level > 0 && refine_level <= INT8_MAX);
+
+ struct PACKET_ZC_REFINE_STATUS p;
+ p.packetType = HEADER_ZC_REFINE_STATUS;
+ safestrncpy(p.name, sd->status.name, NAME_LENGTH);
+ p.itemId = item_id;
+ p.refine_level = refine_level;
+ p.status = (success) ? true : false;
+ clif->send(&p, sizeof(p), &sd->bl, target);
+#endif
+}
+
+static void clif_parse_GuildCastleTeleportRequest(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_GuildCastleTeleportRequest(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+ const struct PACKET_CZ_CASTLE_TELEPORT_REQUEST *p = RFIFO2PTR(fd);
+ struct guild *g = sd->guild;
+
+ if (g == NULL)
+ return;
+
+ struct guild_castle *gc = guild->castle_search(p->castle_id);
+ if (gc == NULL)
+ return;
+ if (gc->enable_client_warp == false)
+ return;
+ if (gc->guild_id != g->guild_id)
+ return;
+
+ if (map->list[sd->bl.m].flag.gvg_castle == 1)
+ return;
+
+ int zeny = gc->client_warp.zeny;
+ if (gc->siege_type == SIEGE_TYPE_FE && map->agit_flag == 1) {
+ zeny = gc->client_warp.zeny_siege;
+ } else if (gc->siege_type == SIEGE_TYPE_SE && map->agit2_flag == 1) {
+ zeny = gc->client_warp.zeny_siege;
+ } else if (gc->siege_type == SIEGE_TYPE_TE) {
+ clif->guild_castleteleport_res(sd, SIEGE_TP_INVALID_MODE);
+ return;
+ }
+
+ if (sd->status.zeny < zeny) {
+ clif->guild_castleteleport_res(sd, SIEGE_TP_NOT_ENOUGH_ZENY);
+ return;
+ }
+ sd->status.zeny -= zeny;
+ clif->updatestatus(sd, SP_ZENY);
+ pc->setpos(sd, gc->mapindex, gc->client_warp.x, gc->client_warp.y, CLR_OUTSIGHT);
+#endif
+}
+
+static void clif_guild_castleteleport_res(struct map_session_data *sd, enum siege_teleport_result result)
+{
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+
+ nullpo_retv(sd);
+
+ struct PACKET_ZC_CASTLE_TELEPORT_RESPONSE p = { 0 };
+ p.packetType = HEADER_ZC_CASTLE_TELEPORT_RESPONSE;
+ p.result = (int16)result;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#endif
+}
+static void clif_parse_GuildCastleInfoRequest(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+static void clif_parse_GuildCastleInfoRequest(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+ const struct PACKET_CZ_CASTLE_INFO_REQUEST *p = RFIFO2PTR(fd);
+ struct guild *g = sd->guild;
+
+ if (g == NULL)
+ return;
+
+ struct guild_castle *gc = guild->castle_search(p->castle_id);
+ if (gc == NULL)
+ return;
+ if (gc->guild_id != g->guild_id)
+ return;
+ clif->guild_castleinfo(sd, gc);
+#endif
+}
+
+static bool clif_lapineDdukDdak_open(struct map_session_data *sd, int item_id)
+{
+#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ nullpo_retr(false, itemdb->exists(item_id));
+ struct PACKET_ZC_LAPINEDDUKDDAK_OPEN p;
+
+ p.packetType = HEADER_ZC_LAPINEDDUKDDAK_OPEN;
+ p.itemId = item_id;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ sd->state.lapine_ui = 1;
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+}
+
+static bool clif_lapineDdukDdak_result(struct map_session_data *sd, enum lapineddukddak_result result)
+{
+#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ struct PACKET_ZC_LAPINEDDUKDDAK_RESULT p;
+
+ p.packetType = HEADER_ZC_LAPINEDDUKDDAK_RESULT;
+ p.result = result;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+}
+
+static void clif_parse_lapineDdukDdak_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineDdukDdak_ack(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20160302
+ if (sd->state.lapine_ui == 0)
+ return;
+
+ const struct PACKET_CZ_LAPINEDDUKDDAK_ACK *p = RP2PTR(fd);
+ struct item_data *it = itemdb->exists(p->itemId);
+
+ if (it == NULL || it->lapineddukddak == NULL)
+ return;
+ if (pc_cant_act_except_lapine(sd))
+ return;
+ if (pc->search_inventory(sd, it->nameid) == INDEX_NOT_FOUND)
+ return;
+
+ if (((p->packetLength - sizeof(struct PACKET_CZ_LAPINEDDUKDDAK_ACK)) / sizeof(struct PACKET_CZ_LAPINEDDUKDDAK_ACK_sub)) != it->lapineddukddak->NeedCount)
+ return;
+
+ for (int i = 0; i < it->lapineddukddak->NeedCount; ++i) {
+ int16 idx = p->items[i].index - 2;
+ Assert_retv(idx >= 0 && idx < sd->status.inventorySize);
+
+ struct item itr = sd->status.inventory[idx];
+ int j = 0;
+ for (j = 0; j < VECTOR_LENGTH(it->lapineddukddak->SourceItems); ++j) {
+ if (itr.nameid == VECTOR_INDEX(it->lapineddukddak->SourceItems, j).id) {
+ // Validate that the amount sent in the packet is matching the database
+ if (p->items[i].count != VECTOR_INDEX(it->lapineddukddak->SourceItems, j).amount) {
+ clif->lapineDdukDdak_result(sd, LAPINEDDKUKDDAK_INSUFFICIENT_AMOUNT);
+ return;
+ }
+
+ // Validate that the player have enough of the item
+ if (itr.amount < VECTOR_INDEX(it->lapineddukddak->SourceItems, j).amount) {
+ clif->lapineDdukDdak_result(sd, LAPINEDDKUKDDAK_INSUFFICIENT_AMOUNT);
+ return;
+ }
+
+ // Validate refine rate requirement
+ if ((itemdb_type(itr.nameid) == IT_ARMOR || itemdb_type(itr.nameid) == IT_WEAPON)
+ && (itr.refine < it->lapineddukddak->NeedRefineMin || itr.refine > it->lapineddukddak->NeedRefineMax))
+ return;
+
+ // All requirements are met, move to the next one
+ break;
+ }
+ }
+ // The item is not in sources list
+ if (j == VECTOR_LENGTH(it->lapineddukddak->SourceItems)) {
+ clif->lapineDdukDdak_result(sd, LAPINEDDKUKDDAK_INVALID_ITEM);
+ return;
+ }
+ }
+
+ for (int i = 0; i < it->lapineddukddak->NeedCount; ++i)
+ pc->delitem(sd, p->items[i].index - 2, p->items[i].count, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT);
+ if (it->lapineddukddak->script != NULL)
+ script->run_item_lapineddukddak_script(sd, it, npc->fake_nd->bl.id);
+ clif->lapineDdukDdak_result(sd, LAPINEDDKUKDDAK_SUCCESS);
+ return;
+#endif // PACKETVER >= 20160302
+}
+
+static void clif_parse_lapineDdukDdak_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineDdukDdak_close(int fd, struct map_session_data *sd)
+{
+#if PACKETVER >= 20160504
+ sd->state.lapine_ui = 0;
+#endif // PACKETVER >= 20160504
+}
+
+static bool clif_lapineUpgrade_open(struct map_session_data *sd, int item_id)
+{
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ nullpo_retr(false, itemdb->exists(item_id));
+ struct PACKET_ZC_LAPINEUPGRADE_OPEN p;
+
+ p.packetType = HEADER_ZC_LAPINEUPGRADE_OPEN;
+ p.itemId = item_id;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+}
+
+static void clif_parse_lapineUpgrade_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineUpgrade_close(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+}
+
+static void clif_parse_lapineUpgrade_makeItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineUpgrade_makeItem(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+ ShowError("Lapin upgrade not implimented yet");
+ clif->lapineUpgrade_result(sd, LAPINE_UPGRADE_FAILED);
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+}
+
+static bool clif_lapineUpgrade_result(struct map_session_data *sd, enum lapineUpgrade_result result)
+{
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ struct PACKET_ZC_LAPINEUPGRADE_RESULT p;
+
+ p.packetType = HEADER_ZC_LAPINEUPGRADE_RESULT;
+ p.result = result;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+}
+
/*==========================================
* Main client packet processing function
*------------------------------------------*/
-int clif_parse(int fd) {
+static int clif_parse(int fd)
+{
int cmd, packet_len;
struct map_session_data *sd;
int pnum;
@@ -18866,6 +23966,7 @@ int clif_parse(int fd) {
parse_cmd_func = clif->parse_cmd;
cmd = parse_cmd_func(fd,sd);
+ clif->cmd = cmd;
if (VECTOR_LENGTH(HPM->packets[hpClif_Parse]) > 0) {
int result = HPM->parse_packets(fd,cmd,hpClif_Parse);
@@ -18876,7 +23977,7 @@ int clif_parse(int fd) {
}
// filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0) {
+ if (cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packets->db[cmd] == 0) {
ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %"PRIuS" bytes received), disconnecting session #%d.\n",
(unsigned int)cmd, RFIFOW(fd,0), RFIFOREST(fd), fd);
#ifdef DUMP_INVALID_PACKET
@@ -18887,7 +23988,7 @@ int clif_parse(int fd) {
}
// determine real packet length
- if ( ( packet_len = packet_db[cmd].len ) == -1) { // variable-length packet
+ if ((packet_len = packets->db[cmd]) == -1) { // variable-length packet
if (RFIFOREST(fd) < 4)
return 0;
@@ -18929,8 +24030,8 @@ int clif_parse(int fd) {
else
packet_db[cmd].func(fd, sd);
}
-#ifdef DUMP_UNKNOWN_PACKET
else {
+#ifdef DUMP_UNKNOWN_PACKET
const char* packet_txt = "save/packet.txt";
FILE* fp;
@@ -18956,8 +24057,10 @@ int clif_parse(int fd) {
ShowDump(RFIFOP(fd,0), packet_len);
}
- }
+#else
+ clif->pDull(fd, sd);
#endif
+ }
RFIFOSKIP(fd, packet_len);
@@ -18972,14 +24075,15 @@ int clif_parse(int fd) {
* @param packet_id The packet ID.
* @return The corresponding packet_db entry, if any.
*/
-const struct s_packet_db *clif_packet(int packet_id)
+static const struct s_packet_db *clif_packet(int packet_id)
{
- if (packet_id < MIN_PACKET_DB || packet_id > MAX_PACKET_DB || packet_db[packet_id].len == 0)
+ if (packet_id < MIN_PACKET_DB || packet_id > MAX_PACKET_DB || packets->db[packet_id] == 0)
return NULL;
return &packet_db[packet_id];
}
-static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) {
+static void __attribute__ ((unused)) packetdb_addpacket(int cmd, ...)
+{
va_list va;
int i;
int pos;
@@ -18995,21 +24099,19 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...)
return;
}
- packet_db[cmd].len = len;
-
- va_start(va,len);
+ va_start(va, cmd);
pos = va_arg(va, int);
va_end(va);
- if( pos == 0xFFFF ) { /* nothing more to do */
+ if (pos == 0xFFFF) { /* nothing more to do */
return;
}
- va_start(va,len);
+ va_start(va, cmd);
- func = va_arg(va,pFunc);
+ func = va_arg(va, pFunc);
packet_db[cmd].func = func;
@@ -19023,20 +24125,40 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...)
}
va_end(va);
}
-void packetdb_loaddb(void) {
+
+static void packetdb_loaddb(void)
+{
memset(packet_db,0,sizeof(packet_db));
-#define packet(id, size, ...) packetdb_addpacket((id), (size), ##__VA_ARGS__, 0xFFFF)
-#define packetKeys(a,b,c) do { clif->cryptKey[0] = (a); clif->cryptKey[1] = (b); clif->cryptKey[2] = (c); } while(0)
-#include "packets.h" /* load structure data */
+#define packet(id, ...) packetdb_addpacket((id), ##__VA_ARGS__, 0xFFFF)
+#include "map/packets.h" /* load structure data */
+#ifdef PACKETVER_ZERO
+#include "map/packets_shuffle_zero.h"
+#elif defined(PACKETVER_RE)
+#include "map/packets_shuffle_re.h"
+#else // PACKETVER_ZERO
+#include "map/packets_shuffle_main.h"
+#endif // PACKETVER_ZERO
#undef packet
+#define packetKeys(a,b,c) do { clif->cryptKey[0] = (a); clif->cryptKey[1] = (b); clif->cryptKey[2] = (c); } while(0)
+#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
+ packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
+#else // defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
+#ifdef PACKETVER_ZERO
+#include "map/packets_keys_zero.h"
+#else // PACKETVER_ZERO
+#include "map/packets_keys_main.h"
+#endif // PACKETVER_ZERO
+#endif // defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
#undef packetKeys
}
-void clif_bc_ready(void) {
+
+static void clif_bc_ready(void)
+{
if( battle_config.display_status_timers )
- clif->status_change = clif_status_change;
+ clif->status_change_sub = clif_status_change_sub;
else
- clif->status_change = clif_status_change_notick;
+ clif->status_change_sub = clif_status_change_notick;
switch( battle_config.packet_obfuscation ) {
case 0:
@@ -19054,7 +24176,7 @@ void clif_bc_ready(void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_clif(bool minimal)
+static int do_init_clif(bool minimal)
{
if (minimal)
return 0;
@@ -19062,6 +24184,7 @@ int do_init_clif(bool minimal)
packetdb_loaddb();
sockt->set_defaultparse(clif->parse);
+ sockt->validate = true;
if (sockt->make_listen_bind(clif->bind_ip,clif->map_port) == -1) {
ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",clif->map_port);
exit(EXIT_FAILURE);
@@ -19073,10 +24196,16 @@ int do_init_clif(bool minimal)
clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR);
clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR);
+#if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320
+ timer->add_func_list(clif->pingTimer, "clif_pingTimer");
+ if (battle_config.ping_timer_interval != 0)
+ timer->add_interval(timer->gettick() + battle_config.ping_timer_interval * 1000, clif->pingTimer, 0, 0, battle_config.ping_timer_interval * 1000);
+#endif
+
return 0;
}
-void do_final_clif(void)
+static void do_final_clif(void)
{
unsigned char i;
@@ -19099,13 +24228,16 @@ void do_final_clif(void)
}
}
-void clif_defaults(void) {
+
+void clif_defaults(void)
+{
clif = &clif_s;
/* vars */
clif->bind_ip = INADDR_ANY;
clif->map_port = 5121;
clif->ally_only = false;
clif->delayed_damage_ers = NULL;
+ clif->cmd = -1;
/* core */
clif->init = do_init_clif;
clif->final = do_final_clif;
@@ -19122,6 +24254,7 @@ void clif_defaults(void) {
clif->packet = clif_packet;
/* auth */
clif->authok = clif_authok;
+ clif->auth_error = clif_auth_error;
clif->authrefuse = clif_authrefuse;
clif->authfail_fd = clif_authfail_fd;
clif->charselectok = clif_charselectok;
@@ -19132,6 +24265,7 @@ void clif_defaults(void) {
clif->dropitem = clif_dropitem;
clif->delitem = clif_delitem;
clif->takeitem = clif_takeitem;
+ clif->item_movefailed = clif_item_movefailed;
clif->item_equip = clif_item_equip;
clif->item_normal = clif_item_normal;
clif->arrowequip = clif_arrowequip;
@@ -19143,11 +24277,11 @@ void clif_defaults(void) {
clif->unequipitemack = clif_unequipitemack;
clif->useitemack = clif_useitemack;
clif->addcards = clif_addcards;
- clif->addcards2 = clif_addcards2;
clif->item_sub = clif_item_sub; // look like unused
clif->getareachar_item = clif_getareachar_item;
clif->cart_additem_ack = clif_cart_additem_ack;
clif->cashshop_load = clif_cashshop_db;
+ clif->cashShopSchedule = clif_cashShopSchedule;
clif->package_announce = clif_package_item_announce;
clif->item_drop_announce = clif_item_drop_announce;
/* unit-related */
@@ -19183,6 +24317,7 @@ void clif_defaults(void) {
clif->spawn = clif_spawn;
/* map-related */
clif->changemap = clif_changemap;
+ clif->changemap_airship = clif_changemap_airship;
clif->changemapcell = clif_changemapcell;
clif->map_property = clif_map_property;
clif->pvpset = clif_pvpset;
@@ -19192,6 +24327,7 @@ void clif_defaults(void) {
clif->maptypeproperty2 = clif_maptypeproperty2;
/* multi-map-server */
clif->changemapserver = clif_changemapserver;
+ clif->changemapserver_airship = clif_changemapserver_airship;
/* npc-shop-related */
clif->npcbuysell = clif_npcbuysell;
clif->buylist = clif_buylist;
@@ -19222,9 +24358,12 @@ void clif_defaults(void) {
clif->fame_alchemist = clif_fame_alchemist;
clif->fame_taekwon = clif_fame_taekwon;
clif->ranklist = clif_ranklist;
+ clif->ranklist_sub = clif_ranklist_sub;
+ clif->ranklist_sub2 = clif_ranklist_sub2;
clif->pRanklist = clif_parse_ranklist;
clif->update_rankingpoint = clif_update_rankingpoint;
clif->hotkeys = clif_hotkeys_send;
+ clif->hotkeysAll = clif_hotkeysAll_send;
clif->insight = clif_insight;
clif->outsight = clif_outsight;
clif->skillcastcancel = clif_skillcastcancel;
@@ -19237,10 +24376,20 @@ void clif_defaults(void) {
clif->autospell = clif_autospell;
clif->combo_delay = clif_combo_delay;
clif->status_change = clif_status_change;
+ clif->status_change_sub = clif_status_change_sub;
clif->insert_card = clif_insert_card;
- clif->inventorylist = clif_inventorylist;
- clif->equiplist = clif_equiplist;
- clif->cartlist = clif_cartlist;
+ clif->inventoryList = clif_inventoryList;
+ clif->inventoryItems = clif_inventoryItems;
+ clif->equipList = clif_equipList;
+ clif->equipItems = clif_equipItems;
+ clif->cartList = clif_cartList;
+ clif->cartItems = clif_cartItems;
+ clif->inventoryExpansionInfo = clif_inventoryExpansionInfo;
+ clif->inventoryExpandAck = clif_inventoryExpandAck;
+ clif->inventoryExpandResult = clif_inventoryExpandResult;
+ clif->pInventoryExpansion = clif_parse_inventoryExpansion;
+ clif->pInventoryExpansionConfirmed = clif_parse_inventoryExpansionConfirmed;
+ clif->pInventoryExpansionRejected = clif_parse_inventoryExpansionRejected;
clif->favorite_item = clif_favorite_item;
clif->clearcart = clif_clearcart;
clif->item_identify_list = clif_item_identify_list;
@@ -19254,7 +24403,21 @@ void clif_defaults(void) {
clif->mvp_exp = clif_mvp_exp;
clif->mvp_noitem = clif_mvp_noitem;
clif->changed_dir = clif_changed_dir;
- clif->charnameack = clif_charnameack;
+ clif->blname_ack = clif_blname_ack;
+ clif->pcname_ack = clif_pcname_ack;
+ clif->homname_ack = clif_homname_ack;
+ clif->mername_ack = clif_mername_ack;
+ clif->petname_ack = clif_petname_ack;
+ clif->npcname_ack = clif_npcname_ack;
+ clif->mobname_ack = clif_mobname_ack;
+ clif->mobname_guardian_ack = clif_mobname_guardian_ack;
+ clif->mobname_additional_ack = clif_mobname_additional_ack;
+ clif->mobname_normal_ack = clif_mobname_normal_ack;
+ clif->chatname_ack = clif_chatname_ack;
+ clif->elemname_ack = clif_elemname_ack;
+ clif->skillname_ack = clif_skillname_ack;
+ clif->itemname_ack = clif_itemname_ack;
+ clif->unknownname_ack = clif_unknownname_ack;
clif->monster_hp_bar = clif_monster_hp_bar;
clif->hpmeter = clif_hpmeter;
clif->hpmeter_single = clif_hpmeter_single;
@@ -19269,13 +24432,14 @@ void clif_defaults(void) {
clif->mission_info = clif_mission_info;
clif->feel_hate_reset = clif_feel_hate_reset;
clif->partytickack = clif_partytickack;
- clif->equiptickack = clif_equiptickack;
+ clif->zc_config = clif_zc_config;
clif->viewequip_ack = clif_viewequip_ack;
clif->equpcheckbox = clif_equpcheckbox;
clif->displayexp = clif_displayexp;
clif->font = clif_font;
clif->progressbar = clif_progressbar;
clif->progressbar_abort = clif_progressbar_abort;
+ clif->progressbar_unit = clif_progressbar_unit;
clif->showdigit = clif_showdigit;
clif->elementalconverter_list = clif_elementalconverter_list;
clif->spellbook_list = clif_spellbook_list;
@@ -19284,6 +24448,7 @@ void clif_defaults(void) {
clif->autoshadowspell_list = clif_autoshadowspell_list;
clif->skill_itemlistwindow = clif_skill_itemlistwindow;
clif->sc_load = clif_status_change2;
+ clif->sc_continue = clif_status_change2;
clif->sc_end = clif_status_change_end;
clif->initialstatus = clif_initialstatus;
clif->cooldown_list = clif_skill_cooldown_list;
@@ -19306,6 +24471,7 @@ void clif_defaults(void) {
/* visual effects client-side */
clif->misceffect = clif_misceffect;
clif->changeoption = clif_changeoption;
+ clif->changeoption_target = clif_changeoption_target;
clif->changeoption2 = clif_changeoption2;
clif->emotion = clif_emotion;
clif->talkiebox = clif_talkiebox;
@@ -19317,7 +24483,7 @@ void clif_defaults(void) {
clif->skill_poseffect = clif_skill_poseffect;
clif->skill_estimation = clif_skill_estimation;
clif->skill_warppoint = clif_skill_warppoint;
- clif->skillcasting = clif_skillcasting;
+ clif->useskill = clif_useskill;
clif->produce_effect = clif_produceeffect;
clif->devotion = clif_devotion;
clif->spiritball = clif_spiritball;
@@ -19331,6 +24497,9 @@ void clif_defaults(void) {
clif->specialeffect = clif_specialeffect;
clif->specialeffect_single = clif_specialeffect_single;
clif->specialeffect_value = clif_specialeffect_value;
+ clif->specialeffect_value_single = clif_specialeffect_value_single;
+ clif->removeSpecialEffect = clif_removeSpecialEffect;
+ clif->removeSpecialEffect_single = clif_removeSpecialEffect_single;
clif->millenniumshield = clif_millenniumshield;
clif->spiritcharm = clif_charm;
clif->charm_single = clif_charm_single;
@@ -19348,6 +24517,7 @@ void clif_defaults(void) {
clif->joinchatok = clif_joinchatok;
clif->addchat = clif_addchat;
clif->changechatowner = clif_changechatowner;
+ clif->chatRoleChange = clif_chatRoleChange;
clif->clearchat = clif_clearchat;
clif->leavechat = clif_leavechat;
clif->changechatstatus = clif_changechatstatus;
@@ -19358,14 +24528,20 @@ void clif_defaults(void) {
clif->broadcast2 = clif_broadcast2;
clif->messagecolor_self = clif_messagecolor_self;
clif->messagecolor = clif_messagecolor;
+ clif->serviceMessageColor = clif_serviceMessageColor;
clif->disp_overhead = clif_disp_overhead;
+ clif->notify_playerchat = clif_notify_playerchat;
clif->msgtable_skill = clif_msgtable_skill;
clif->msgtable = clif_msgtable;
clif->msgtable_num = clif_msgtable_num;
+ clif->msgtable_str = clif_msgtable_str;
+ clif->msgtable_str_color = clif_msgtable_str_color;
+ clif->msgtable_color = clif_msgtable_color;
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
clif->messages = clif_displaymessage_sprintf;
- clif->process_message = clif_process_message;
+ clif->process_chat_message = clif_process_chat_message;
+ clif->process_whisper_message = clif_process_whisper_message;
clif->wisexin = clif_wisexin;
clif->wisall = clif_wisall;
clif->PMIgnoreList = clif_PMIgnoreList;
@@ -19386,9 +24562,14 @@ void clif_defaults(void) {
clif->vendinglist = clif_vendinglist;
clif->buyvending = clif_buyvending;
clif->openvending = clif_openvending;
+ clif->openvendingAck = clif_openvendingAck;
clif->vendingreport = clif_vendingreport;
/* storage handling */
- clif->storagelist = clif_storagelist;
+ clif->storageList = clif_storageList;
+ clif->guildStorageList = clif_guildStorageList;
+ clif->storageItems = clif_storageItems;
+ clif->inventoryStart = clif_inventoryStart;
+ clif->inventoryEnd = clif_inventoryEnd;
clif->updatestorageamount = clif_updatestorageamount;
clif->storageitemadded = clif_storageitemadded;
clif->storageitemremoved = clif_storageitemremoved;
@@ -19399,10 +24580,12 @@ void clif_defaults(void) {
clif->skillinfo = clif_skillinfo;
clif->addskill = clif_addskill;
clif->deleteskill = clif_deleteskill;
+ clif->playerSkillToPacket = clif_playerSkillToPacket;
/* party-specific */
clif->party_created = clif_party_created;
clif->party_member_info = clif_party_member_info;
clif->party_info = clif_party_info;
+ clif->party_job_and_level = clif_party_job_and_level;
clif->party_invite = clif_party_invite;
clif->party_inviteack = clif_party_inviteack;
clif->party_option = clif_party_option;
@@ -19421,6 +24604,8 @@ void clif_defaults(void) {
clif->guild_masterormember = clif_guild_masterormember;
clif->guild_basicinfo = clif_guild_basicinfo;
clif->guild_allianceinfo = clif_guild_allianceinfo;
+ clif->guild_castlelist = clif_guild_castlelist;
+ clif->guild_castleinfo = clif_guild_castleinfo;
clif->guild_memberlist = clif_guild_memberlist;
clif->guild_skillinfo = clif_guild_skillinfo;
clif->guild_send_onlineinfo = clif_guild_send_onlineinfo;
@@ -19446,6 +24631,8 @@ void clif_defaults(void) {
clif->guild_positionnamelist = clif_guild_positionnamelist;
clif->guild_positioninfolist = clif_guild_positioninfolist;
clif->guild_expulsionlist = clif_guild_expulsionlist;
+ clif->guild_set_position = clif_guild_set_position;
+ clif->guild_position_selected = clif_guild_position_selected;
clif->validate_emblem = clif_validate_emblem;
/* battleground-specific */
clif->bg_hp = clif_bg_hp;
@@ -19494,6 +24681,7 @@ void clif_defaults(void) {
clif->quest_delete = clif_quest_delete;
clif->quest_update_status = clif_quest_update_status;
clif->quest_update_objective = clif_quest_update_objective;
+ clif->quest_notify_objective = clif_quest_notify_objective;
clif->quest_show_event = clif_quest_show_event;
/* mail-related */
clif->mail_window = clif_Mail_window;
@@ -19595,13 +24783,27 @@ void clif_defaults(void) {
/* */
clif->parse_roulette_db = clif_parse_roulette_db;
clif->roulette_generate_ack = clif_roulette_generate_ack;
+ clif->roulette_close = clif_roulette_close;
/* Merge Items */
clif->openmergeitem = clif_openmergeitem;
clif->cancelmergeitem = clif_cancelmergeitem;
clif->comparemergeitem = clif_comparemergeitem;
clif->ackmergeitems = clif_ackmergeitems;
+ clif->mergeitems = clif_mergeitems;
/* Cart Deco */
clif->selectcart = clif_selectcart;
+ /* */
+ clif->isdisguised = clif_isdisguised;
+ clif->navigate_to = clif_navigate_to;
+ clif->bl_type = clif_bl_type;
+ /* Achievement System */
+ clif->achievement_send_list = clif_achievement_send_list;
+ clif->achievement_send_update = clif_achievement_send_update;
+ clif->pAchievementGetReward = clif_parse_achievement_get_reward;
+ clif->achievement_reward_ack = clif_achievement_reward_ack;
+ /* Title */
+ clif->change_title_ack = clif_change_title_ack;
+ clif->pChangeTitle = clif_parse_change_title;
/*------------------------
*- Parse Incoming Packet
@@ -19609,7 +24811,8 @@ void clif_defaults(void) {
clif->pWantToConnection = clif_parse_WantToConnection;
clif->pLoadEndAck = clif_parse_LoadEndAck;
clif->pTickSend = clif_parse_TickSend;
- clif->pHotkey = clif_parse_Hotkey;
+ clif->pHotkey1 = clif_parse_Hotkey1;
+ clif->pHotkey2 = clif_parse_Hotkey2;
clif->pProgressbar = clif_parse_progressbar;
clif->pWalkToXY = clif_parse_WalkToXY;
clif->pQuitGame = clif_parse_QuitGame;
@@ -19656,6 +24859,9 @@ void clif_defaults(void) {
clif->pUseSkillToId = clif_parse_UseSkillToId;
clif->pUseSkillToId_homun = clif_parse_UseSkillToId_homun;
clif->pUseSkillToId_mercenary = clif_parse_UseSkillToId_mercenary;
+ clif->pStartUseSkillToId = clif_parse_startUseSkillToId;
+ clif->pStopUseSkillToId = clif_parse_stopUseSkillToId;
+ clif->useSkillToIdReal = clif_useSkillToIdReal;
clif->pUseSkillToPos = clif_parse_UseSkillToPos;
clif->pUseSkillToPosSub = clif_parse_UseSkillToPosSub;
clif->pUseSkillToPos_homun = clif_parse_UseSkillToPos_homun;
@@ -19787,7 +24993,7 @@ void clif_defaults(void) {
clif->pAdopt_request = clif_parse_Adopt_request;
clif->pAdopt_reply = clif_parse_Adopt_reply;
clif->pViewPlayerEquip = clif_parse_ViewPlayerEquip;
- clif->pEquipTick = clif_parse_EquipTick;
+ clif->p_cz_config = clif_parse_cz_config;
clif->pquestStateAck = clif_parse_questStateAck;
clif->pmercenary_action = clif_parse_mercenary_action;
clif->pBattleChat = clif_parse_BattleChat;
@@ -19804,6 +25010,9 @@ void clif_defaults(void) {
clif->pDebug = clif_parse_debug;
clif->pSkillSelectMenu = clif_parse_SkillSelectMenu;
clif->pMoveItem = clif_parse_MoveItem;
+ clif->p_cz_blocking_play_cancel = clif_parse_cz_blocking_play_cancel;
+ clif->overweight_percent = clif_overweight_percent;
+ clif->pChangeDress = clif_parse_changeDress;
/* dull */
clif->pDull = clif_parse_dull;
/* BGQueue */
@@ -19812,11 +25021,15 @@ void clif_defaults(void) {
clif->pBGQueueRevokeReq = clif_parse_bgqueue_revoke_req;
clif->pBGQueueBattleBeginAck = clif_parse_bgqueue_battlebegin_ack;
/* RagExe Cash Shop [Ind/Hercules] */
- clif->pCashShopOpen = clif_parse_CashShopOpen;
- clif->pCashShopClose = clif_parse_CashShopClose;
- clif->pCashShopReqTab = clif_parse_CashShopReqTab;
- clif->pCashShopSchedule = clif_parse_CashShopSchedule;
- clif->pCashShopBuy = clif_parse_CashShopBuy;
+ clif->pCashShopOpen1 = clif_parse_cashShopOpen1;
+ clif->pCashShopOpen2 = clif_parse_cashShopOpen2;
+ clif->pCashShopLimitedReq = clif_parse_cashShopLimitedReq;
+ clif->pCashShopClose = clif_parse_cashShopClose;
+ clif->pCashShopReqTab = clif_parse_cashShopReqTab;
+ clif->pCashShopSchedule = clif_parse_cashShopSchedule;
+ clif->pCashShopBuy = clif_parse_cashShopBuy;
+ clif->cashShopBuyAck = clif_cashShopBuyAck;
+ clif->cashShopOpen = clif_cashShopOpen;
/* */
clif->pPartyTick = clif_parse_PartyTick;
clif->pGuildInvite2 = clif_parse_GuildInvite2;
@@ -19844,9 +25057,112 @@ void clif_defaults(void) {
clif->pNPCMarketClosed = clif_parse_NPCMarketClosed;
clif->pNPCMarketPurchase = clif_parse_NPCMarketPurchase;
/* */
- clif->add_random_options = clif_add_random_options;
- clif->pHotkeyRowShift = clif_parse_HotkeyRowShift;
+ clif->add_item_options = clif_add_item_options;
+ clif->pHotkeyRowShift1 = clif_parse_HotkeyRowShift1;
+ clif->pHotkeyRowShift2 = clif_parse_HotkeyRowShift2;
clif->dressroom_open = clif_dressroom_open;
clif->pOneClick_ItemIdentify = clif_parse_OneClick_ItemIdentify;
+ /* Achievements [Smokexyz/Hercules] */
clif->get_bl_name = clif_get_bl_name;
+ /* RODEX */
+ clif->pRodexOpenWriteMail = clif_parse_rodex_open_write_mail;
+ clif->rodex_open_write_mail = clif_rodex_open_write_mail;
+ clif->pRodexAddItem = clif_parse_rodex_add_item;
+ clif->rodex_add_item_result = clif_rodex_add_item_result;
+ clif->pRodexRemoveItem = clif_parse_rodex_remove_item;
+ clif->rodex_remove_item_result = clif_rodex_remove_item_result;
+ clif->pRodexSendMail = clif_parse_rodex_send_mail;
+ clif->rodex_send_mail_result = clif_rodex_send_mail_result;
+ clif->rodex_send_maillist = clif_rodex_send_maillist;
+ clif->rodex_send_refresh = clif_rodex_send_refresh;
+ clif->pRodexReadMail = clif_parse_rodex_read_mail;
+ clif->rodex_read_mail = clif_rodex_read_mail;
+ clif->pRodexNextMaillist = clif_parse_rodex_next_maillist;
+ clif->pRodexCloseMailbox = clif_parse_rodex_close_mailbox;
+ clif->pRodexCancelWriteMail = clif_parse_rodex_cancel_write_mail;
+ clif->pRodexOpenMailbox = clif_parse_rodex_open_mailbox;
+ clif->pRodexCheckName = clif_parse_rodex_checkname;
+ clif->rodex_checkname_result = clif_rodex_checkname_result;
+ clif->pRodexDeleteMail = clif_parse_rodex_delete_mail;
+ clif->rodex_delete_mail = clif_rodex_delete_mail;
+ clif->pRodexRefreshMaillist = clif_parse_rodex_refresh_maillist;
+ clif->pRodexRequestZeny = clif_parse_rodex_request_zeny;
+ clif->rodex_request_zeny = clif_rodex_request_zeny;
+ clif->pRodexRequestItems = clif_parse_rodex_request_items;
+ clif->rodex_request_items = clif_rodex_request_items;
+ clif->rodex_icon = clif_rodex_icon;
+ clif->rodex_send_mails_all = clif_rodex_send_mails_all;
+ clif->skill_scale = clif_skill_scale;
+ // -- Clan system
+ clif->clan_basicinfo = clif_clan_basicinfo;
+ clif->clan_onlinecount = clif_clan_onlinecount;
+ clif->clan_leave = clif_clan_leave;
+ clif->clan_message = clif_clan_message;
+ clif->pClanMessage = clif_parse_ClanMessage;
+ // -- Hat Effect
+ clif->hat_effect = clif_hat_effect;
+ clif->hat_effect_single = clif_hat_effect_single;
+ clif->party_dead_notification = clif_party_dead_notification;
+
+ clif->pAttendanceDB = clif_parse_attendance_db;
+ clif->attendancedb_libconfig_sub = clif_attendancedb_libconfig_sub;
+ clif->attendance_timediff = clif_attendance_timediff;
+ clif->attendance_getendtime = clif_attendance_getendtime;
+ clif->pOpenUIRequest = clif_parse_open_ui_request;
+ clif->open_ui = clif_open_ui;
+ clif->pAttendanceRewardRequest = clif_parse_attendance_reward_request;
+ clif->ui_action = clif_ui_action;
+ clif->pPrivateAirshipRequest = clif_parse_private_airship_request;
+ clif->PrivateAirshipResponse = clif_private_airship_response;
+
+ clif->pReqStyleChange = clif_parse_cz_req_style_change;
+ clif->pReqStyleChange2 = clif_parse_cz_req_style_change2;
+ clif->pStyleClose = clif_parse_cz_style_close;
+ clif->style_change_response = clif_style_change_response;
+
+ clif->camera_showWindow = clif_camera_showWindow;
+ clif->camera_change = clif_camera_change;
+ clif->pCameraInfo = clif_parse_cameraInfo;
+ clif->item_preview = clif_item_preview;
+ clif->enchant_equipment = clif_enchant_equipment;
+
+ // -- Pet Evolution
+ clif->pPetEvolution = clif_parse_pet_evolution;
+ clif->petEvolutionResult = clif_pet_evolution_result;
+
+ clif->pMemorialDungeonCommand = clif_parse_memorial_dungeon_command;
+ clif->pReqRemainTime = clif_parse_reqRemainTime;
+
+ clif->npc_barter_open = clif_npc_barter_open;
+ clif->pNPCBarterClosed = clif_parse_NPCBarterClosed;
+ clif->pNPCBarterPurchase = clif_parse_NPCBarterPurchase;
+ clif->npc_expanded_barter_open = clif_npc_expanded_barter_open;
+ clif->pNPCExpandedBarterPurchase = clif_parse_npc_expanded_barter_purchase;
+ clif->pNPCExpandedBarterClosed = clif_parse_npc_expanded_barter_closed;
+ clif->pClientVersion = clif_parse_clientVersion;
+ clif->pPing = clif_parse_ping;
+ clif->ping = clif_ping;
+ clif->pingTimer = clif_pingTimer;
+ clif->pingTimerSub = clif_pingTimerSub;
+ clif->pResetCooldown = clif_parse_ResetCooldown;
+ clif->loadConfirm = clif_loadConfirm;
+ clif->send_selforarea = clif_send_selforarea;
+ clif->OpenRefineryUI = clif_OpenRefineryUI;
+ clif->pAddItemRefineryUI = clif_parse_AddItemRefineryUI;
+ clif->AddItemRefineryUIAck = clif_AddItemRefineryUIAck;
+ clif->pRefineryUIClose = clif_parse_RefineryUIClose;
+ clif->pRefineryUIRefine = clif_parse_RefineryUIRefine;
+ clif->announce_refine_status = clif_announce_refine_status;
+ clif->pGuildCastleTeleportRequest = clif_parse_GuildCastleTeleportRequest;
+ clif->pGuildCastleInfoRequest = clif_parse_GuildCastleInfoRequest;
+ clif->guild_castleteleport_res = clif_guild_castleteleport_res;
+ clif->lapineDdukDdak_open = clif_lapineDdukDdak_open;
+ clif->lapineDdukDdak_result = clif_lapineDdukDdak_result;
+ clif->plapineDdukDdak_ack = clif_parse_lapineDdukDdak_ack;
+ clif->plapineDdukDdak_close = clif_parse_lapineDdukDdak_close;
+ clif->lapineUpgrade_open = clif_lapineUpgrade_open;
+ clif->lapineUpgrade_result = clif_lapineUpgrade_result;
+ clif->pLapineUpgrade_close = clif_parse_lapineUpgrade_close;
+ clif->pLapineUpgrade_makeItem = clif_parse_lapineUpgrade_makeItem;
+ clif->pReqGearOff = clif_parse_reqGearOff;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index f930e4ca1..fdaaf85e3 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,22 +54,39 @@ struct skill_cd;
struct skill_unit;
struct unit_data;
struct view_data;
+struct achievement_data; // map/achievement.h
+struct s_refine_requirement;
+struct PACKET_ZC_ACK_RANKING_sub;
+struct SKILLDATA;
+
+enum battle_dmg_type;
+enum clif_messages;
+enum rodex_add_item;
+enum rodex_get_zeny;
+enum rodex_get_items;
/**
* Defines
**/
-#define packet_len(cmd) packet_db[cmd].len
+#define packet_len(cmd) packets->db[cmd]
#define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0)
-#define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF )
+#define clif_disp_onlyself(sd, mes) clif->disp_message(&(sd)->bl, (mes), SELF)
#define MAX_ROULETTE_LEVEL 7 /** client-defined value **/
#define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/
#define RGB2BGR(c) (((c) & 0x0000FF) << 16 | ((c) & 0x00FF00) | ((c) & 0xFF0000) >> 16)
+#define COLOR_CYAN 0x00ffffU
#define COLOR_RED 0xff0000U
#define COLOR_GREEN 0x00ff00U
#define COLOR_WHITE 0xffffffU
+#define COLOR_YELLOW 0xffff00U
#define COLOR_DEFAULT COLOR_GREEN
+#define MAX_STORAGE_ITEM_PACKET_NORMAL ((INT16_MAX - (sizeof(struct ZC_STORE_ITEMLIST_NORMAL) - (sizeof(struct NORMALITEM_INFO) * MAX_ITEMLIST))) / sizeof(struct NORMALITEM_INFO))
+#define MAX_STORAGE_ITEM_PACKET_EQUIP ((INT16_MAX - (sizeof(struct ZC_STORE_ITEMLIST_EQUIP) - (sizeof(struct EQUIPITEM_INFO) * MAX_ITEMLIST))) / sizeof(struct EQUIPITEM_INFO))
+STATIC_ASSERT(MAX_STORAGE_ITEM_PACKET_NORMAL > 0, "Max items per storage item packet for normal items is less than 1, it's most likely to be a bug and shall not be ignored.");
+STATIC_ASSERT(MAX_STORAGE_ITEM_PACKET_EQUIP > 0, "Max items per storage item packet for equip items is less than 1, it's most likely to be a bug and shall not be ignored.");
+
/**
* Enumerations
**/
@@ -81,6 +98,7 @@ typedef enum send_target {
AREA_WOC, // area, without chatrooms
AREA_WOSC, // area, without own chatrooms
AREA_CHAT_WOC, // hearable area, without chatrooms
+ AREA_DEAD, // area, for clear unit (monster death)
CHAT, // current chatroom
CHAT_WOS, // current chatroom, without self
PARTY,
@@ -108,6 +126,8 @@ typedef enum send_target {
BG_AREA_WOS,
BG_QUEUE,
+
+ CLAN, // Clan System
} send_target;
typedef enum broadcast_flags {
@@ -222,13 +242,13 @@ typedef enum emotion_type {
E_MAX
} emotion_type;
-typedef enum clr_type {
+enum clr_type {
CLR_OUTSIGHT = 0,
CLR_DEAD,
CLR_RESPAWN,
CLR_TELEPORT,
CLR_TRICKDEAD,
-} clr_type;
+};
enum map_property { // clif_map_property
MAPPROPERTY_NOTHING = 0,
@@ -354,34 +374,8 @@ typedef enum useskill_fail_cause { // clif_skill_fail
USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82,
USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83,
USESKILL_FAIL_NEED_MORE_BULLET = 84,
-}useskill_fail_cause;
-
-enum clif_messages {
- MSG_ITEM_CANT_OBTAIN_WEIGHT = 0x034, ///< You cannot carry more items because you are overweight.
- MSG_ITEM_NEED_STANDING = 0x297, ///< You cannot use this item while sitting.
- MSG_MERCENARY_EXPIRED = 0x4f2, ///< The mercenary contract has expired.
- MSG_MERCENARY_DIED = 0x4f3, ///< The mercenary has died.
- MSG_MERCENARY_RELEASED = 0x4f4, ///< You have released the mercenary.
- MSG_MERCENARY_ESCAPED = 0x4f5, ///< The mercenary has run away.
- MSG_SKILL_CANT_USE_AREA = 0x536, ///< This skill cannot be used within this area
- MSG_ITEM_CANT_USE_AREA = 0x537, ///< This item cannot be used within this area.
- MSG_EQUIP_NOT_PUBLIC = 0x54d, ///< This character's equipment information is not open to the public.
- MSG_ITEM_NEED_MADO = 0x59b, ///< Item can only be used when Mado Gear is mounted.
- MSG_ITEM_NEED_CART = 0x5ef, ///< Usable only when cart is put on
- MSG_RUNE_STONE_MAX_AMOUNT = 0x61b, ///< Cannot create Rune stone more than the maximum amount.
- MSG_SKILL_POINTS_LEFT_JOB1 = 0x61e, ///< You must consume all '%d' remaining points in your 1st Job tab.
- MSG_SKILL_POINTS_LEFT_JOB2 = 0x61f, ///< You must consume all '%d' remaining points in your 2nd Job tab. 1st Tab is already done.
- MSG_SKILL_ITEM_NOT_FOUND = 0x623, // FIXME[Haru]: This seems to be 0x622 in the msgstringtable files I found.
- MSG_SKILL_SUCCESS = 0x627, // FIXME[Haru]: This seems to be 0x626 in the msgstringtable files I found.
- MSG_SKILL_FAILURE = 0x628, // FIXME[Haru]: This seems to be 0x627 in the msgstringtable files I found.
- MSG_SKILL_ITEM_NEED_IDENTIFY = 0x62d, ///< Unable to use unchecked items as materials.
- MSG_ITEM_CANT_EQUIP_LVL = 0x6ed, // FIXME[Haru]: This seems to be 0x6ee in the msgstringtable files I found.
- MSG_ITEM_CANT_USE_LVL = 0x6ee, // FIXME[Haru]: This seems to be 0x6ef in the msgstringtable files I found.
- MSG_COOKING_LIST_FAIL = 0x625, // FIXME[Haru]: This might be a wrong message ID. Not sure what it should be.
- MSG_SECONDS_UNTIL_USE = 0x746, ///< %d seconds left until you can use
- MSG_NPC_WORK_IN_PROGRESS = 0x783, // FIXME[Haru]: This seems to be 0x784 in the msgstringtable files I found.
- MSG_REINS_CANT_USE_MOUNTED = 0x78b, // FIXME[Haru]: This seems to be 0x785 in the msgstringtalbe files I found.
-};
+ // max known value 96
+} useskill_fail_cause;
/**
* Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy)
@@ -420,23 +414,26 @@ enum CASH_SHOP_BUY_RESULT {
CSBR_RUNE_OVERCOUNT = 0x9,
CSBR_EACHITEM_OVERCOUNT = 0xa,
CSBR_UNKNOWN = 0xb,
+ CSBR_BUSY = 0xc,
};
enum BATTLEGROUNDS_QUEUE_ACK {
- BGQA_SUCCESS = 1,
- BGQA_FAIL_QUEUING_FINISHED,
- BGQA_FAIL_BGNAME_INVALID,
- BGQA_FAIL_TYPE_INVALID,
- BGQA_FAIL_PPL_OVERAMOUNT,
- BGQA_FAIL_LEVEL_INCORRECT,
- BGQA_DUPLICATE_REQUEST,
- BGQA_PLEASE_RELOGIN,
- BGQA_NOT_PARTY_GUILD_LEADER,
- BGQA_FAIL_CLASS_INVALID,
+ BGQA_SUCCESS = 1,
+ BGQA_FAIL_QUEUING_FINISHED = 2,
+ BGQA_FAIL_BGNAME_INVALID = 3,
+ BGQA_FAIL_TYPE_INVALID = 4,
+ BGQA_FAIL_PPL_OVERAMOUNT = 5,
+ BGQA_FAIL_LEVEL_INCORRECT = 6,
+ BGQA_DUPLICATE_REQUEST = 7,
+ BGQA_PLEASE_RELOGIN = 8,
+ BGQA_NOT_PARTY_GUILD_LEADER = 9,
+ BGQA_FAIL_CLASS_INVALID = 10,
/* not official way to respond (gotta find packet?) */
- BGQA_FAIL_DESERTER,
- BGQA_FAIL_COOLDOWN,
- BGQA_FAIL_TEAM_COUNT,
+ BGQA_FAIL_DESERTER = 11,
+ BGQA_FAIL_COOLDOWN = 12,
+ BGQA_FAIL_TEAM_COUNT = 13,
+ // official continue
+ BGQA_FAIL_TEAM_IN_BG_ALREADY = 15
};
enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED {
@@ -450,11 +447,13 @@ enum e_BANKING_DEPOSIT_ACK {
BDA_ERROR = 0x1,
BDA_NO_MONEY = 0x2,
BDA_OVERFLOW = 0x3,
+ BDA_PROHIBIT = 0x4,
};
enum e_BANKING_WITHDRAW_ACK {
BWA_SUCCESS = 0x0,
BWA_NO_MONEY = 0x1,
BWA_UNKNOWN_ERROR = 0x2,
+ BWA_PROHIBIT = 0x3,
};
/* because the client devs were replaced by monkeys. */
@@ -502,13 +501,17 @@ enum RECV_ROULETTE_ITEM_ACK {
};
enum GENERATE_ROULETTE_ACK {
- GENERATE_ROULETTE_SUCCESS = 0x0,
- GENERATE_ROULETTE_FAILED = 0x1,
- GENERATE_ROULETTE_NO_ENOUGH_POINT = 0x2,
- GENERATE_ROULETTE_LOSING = 0x3,
+ GENERATE_ROULETTE_SUCCESS = 0x0,
+ GENERATE_ROULETTE_FAILED = 0x1,
+ GENERATE_ROULETTE_NO_ENOUGH_POINT = 0x2,
+ GENERATE_ROULETTE_LOSING = 0x3,
+ GENERATE_ROULETTE_NO_ENOUGH_INVENTORY_SPACE = 0x4,
+#if PACKETVER >= 20141001
+ GENERATE_ROULETTE_CANT_PLAY = 0x5,
+#endif
};
-enum OPEN_ROULETTE_ACK{
+enum OPEN_ROULETTE_ACK {
OPEN_ROULETTE_SUCCESS = 0x0,
OPEN_ROULETTE_FAILED = 0x1,
};
@@ -520,7 +523,7 @@ enum CLOSE_ROULETTE_ACK {
/**
* Reason for item deletion (clif->delitem)
- */
+ **/
enum delitem_reason {
DELITEM_NORMAL = 0, /// Normal
DELITEM_SKILLUSE = 1, /// Item used for a skill
@@ -532,9 +535,9 @@ enum delitem_reason {
DELITEM_ANALYSIS = 7, /// Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill
};
-/*
-* Merge items reasons
-*/
+/**
+ * Merge items reasons
+ **/
enum mergeitem_reason {
MERGEITEM_SUCCESS = 0x0,
@@ -543,17 +546,111 @@ enum mergeitem_reason {
};
/**
+ * Clif Unit Type
+ **/
+enum clif_unittype {
+ CLUT_PC = 0x0,
+ CLUT_NPC = 0x1,
+ CLUT_ITEM = 0x2,
+ CLUT_SKILL = 0x3,
+ CLUT_UNKNOWN = 0x4,
+ CLUT_MOB = 0x5,
+ CLUT_EVENT = 0x6,
+ CLUT_PET = 0x7,
+ CLUT_HOMNUCLUS = 0x8,
+ CLUT_MERCNARY = 0x9,
+ CLUT_ELEMENTAL = 0xa,
+};
+/**
+* Receive configuration types
+**/
+enum CZ_CONFIG {
+ CZ_CONFIG_OPEN_EQUIPMENT_WINDOW = 0,
+ CZ_CONFIG_CALL = 1,
+ CZ_CONFIG_PET_AUTOFEEDING = 2,
+ CZ_CONFIG_HOMUNCULUS_AUTOFEEDING = 3,
+};
+
+/**
+* Client UI types
+* used with packet 0xAE2 to request the client to open a specific ui
+**/
+enum zc_ui_types {
+#if PACKETVER >= 20150128
+ ZC_BANK_UI = 0,
+ ZC_STYLIST_UI = 1,
+ ZC_CAPTCHA_UI = 2,
+ ZC_MACRO_UI = 3,
+#endif
+ zc_ui_unused = 4, // for avoid compilation errors
+#if PACKETVER >= 20171122
+ ZC_TIPBOX_UI = 5,
+ ZC_RENEWQUEST_UI = 6,
+ ZC_ATTENDANCE_UI = 7
+#endif
+};
+
+/**
+* Client to server open ui request types (packet 0x0a68)
+**/
+enum cz_ui_types {
+ CZ_STYLIST_UI = 1,
+ CZ_MACRO_REGISTER_UI = 2,
+ CZ_MACRO_DETECTOR_UI = 3,
+ CZ_ATTENDANCE_UI = 5
+};
+
+/**
+* Private Airship Responds
+**/
+enum private_airship {
+ P_AIRSHIP_NONE,
+ P_AIRSHIP_RETRY,
+ P_AIRSHIP_ITEM_NOT_ENOUGH,
+ P_AIRSHIP_INVALID_END_MAP,
+ P_AIRSHIP_INVALID_START_MAP,
+ P_AIRSHIP_ITEM_INVALID
+};
+
+/** Pet Evolution Results */
+enum pet_evolution_result {
+ PET_EVOL_UNKNOWN = 0x0,
+ PET_EVOL_NO_CALLPET = 0x1,
+ PET_EVOL_NO_PETEGG = 0x2,
+ PET_EVOL_NO_RECIPE = 0x3,
+ PET_EVOL_NO_MATERIAL = 0x4,
+ PET_EVOL_RG_FAMILIAR = 0x5,
+ PET_EVOL_SUCCESS = 0x6,
+};
+
+/**
+ * Inventory type for clients 2018-09-12 RE +
+ **/
+enum inventory_type {
+ INVTYPE_INVENTORY = 0,
+ INVTYPE_CART = 1,
+ INVTYPE_STORAGE = 2,
+ INVTYPE_GUILD_STORAGE = 3,
+};
+
+/** Guild Teleport Results */
+enum siege_teleport_result {
+ SIEGE_TP_SUCCESS = 0x0,
+ SIEGE_TP_NOT_ENOUGH_ZENY = 0x1,
+ SIEGE_TP_INVALID_MODE = 0x2
+};
+
+/**
* Structures
**/
typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first
struct s_packet_db {
- short len;
pFunc func;
short pos[MAX_PACKET_POS];
};
struct hCSData {
- unsigned short id;
+ int id;
unsigned int price;
};
@@ -563,8 +660,92 @@ struct cdelayed_damage {
};
struct merge_item {
- int16 position;
- int16 nameid;
+ int16 position;
+ int nameid;
+};
+
+/* attendance data */
+struct attendance_entry {
+ int nameid;
+ int qty;
+};
+
+struct barter_itemlist_entry {
+ int addId;
+ int addAmount;
+ int removeIndex;
+ int shopIndex;
+};
+
+VECTOR_STRUCT_DECL(barteritemlist, struct barter_itemlist_entry);
+
+/**
+* Stylist Shop Responds
+**/
+enum stylist_shop {
+ STYLIST_SHOP_SUCCESS,
+ STYLIST_SHOP_FAILURE
+};
+
+enum memorial_dungeon_command {
+ COMMAND_MEMORIALDUNGEON_DESTROY_FORCE = 0x3,
+};
+
+enum expand_inventory {
+ EXPAND_INVENTORY_ASK_CONFIRMATION = 0,
+ EXPAND_INVENTORY_FAILED = 1,
+ EXPAND_INVENTORY_OTHER_WORK = 2,
+ EXPAND_INVENTORY_MISSING_ITEM = 3,
+ EXPAND_INVENTORY_MAX_SIZE = 4
+};
+
+enum expand_inventory_result {
+ EXPAND_INVENTORY_RESULT_SUCCESS = 0,
+ EXPAND_INVENTORY_RESULT_FAILED = 1,
+ EXPAND_INVENTORY_RESULT_OTHER_WORK = 2,
+ EXPAND_INVENTORY_RESULT_MISSING_ITEM = 3,
+ EXPAND_INVENTORY_RESULT_MAX_SIZE = 4
+};
+
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190814
+enum market_buy_result {
+ MARKET_BUY_RESULT_ERROR = 0xffff, // -1
+ MARKET_BUY_RESULT_SUCCESS = 0,
+ MARKET_BUY_RESULT_NO_ZENY = 1,
+ MARKET_BUY_RESULT_OVER_WEIGHT = 2,
+ MARKET_BUY_RESULT_OUT_OF_SPACE = 3,
+ MARKET_BUY_RESULT_AMOUNT_TOO_BIG = 9
+};
+#else
+enum market_buy_result {
+ MARKET_BUY_RESULT_ERROR = 0,
+ MARKET_BUY_RESULT_SUCCESS = 1,
+ MARKET_BUY_RESULT_NO_ZENY = 0,
+ MARKET_BUY_RESULT_OVER_WEIGHT = 0,
+ MARKET_BUY_RESULT_OUT_OF_SPACE = 0,
+ MARKET_BUY_RESULT_AMOUNT_TOO_BIG = 0
+};
+#endif
+
+enum lapineddukddak_result {
+ LAPINEDDKUKDDAK_SUCCESS = 0,
+ LAPINEDDKUKDDAK_INSUFFICIENT_AMOUNT = 5,
+ LAPINEDDKUKDDAK_INVALID_ITEM = 7,
+};
+
+enum lapineUpgrade_result {
+ LAPINE_UPGRADE_SUCCESS = 0,
+ LAPINE_UPGRADE_FAILED = 1
+};
+
+enum removeGear_flag {
+ REMOVE_MOUNT_0 = 0, // unused
+ REMOVE_MOUNT_DRAGON = 1,
+ REMOVE_MOUNT_2 = 2, // unused
+ REMOVE_MOUNT_MADO = 3,
+ REMOVE_MOUNT_PECO = 4,
+ REMOVE_MOUNT_FALCON = 5,
+ REMOVE_MOUNT_CART = 6,
};
/**
@@ -577,6 +758,7 @@ struct clif_interface {
uint16 map_port;
char map_ip_str[128];
int map_fd;
+ int cmd;
/* for clif_clearunit_delayed */
struct eri *delay_clearunit_ers;
/* Cash Shop [Ind/Hercules] */
@@ -596,6 +778,8 @@ struct clif_interface {
bool ally_only;
/* */
struct eri *delayed_damage_ers;
+ /* */
+ VECTOR_DECL(struct attendance_entry) attendance_data;
/* core */
int (*init) (bool minimal);
void (*final) (void);
@@ -612,6 +796,7 @@ struct clif_interface {
unsigned short (*decrypt_cmd) ( int cmd, struct map_session_data *sd );
/* auth */
void (*authok) (struct map_session_data *sd);
+ void (*auth_error) (int fd, int errorCode);
void (*authrefuse) (int fd, uint8 error_code);
void (*authfail_fd) (int fd, int type);
void (*charselectok) (int id, uint8 ok);
@@ -622,6 +807,7 @@ struct clif_interface {
void (*dropitem) (struct map_session_data *sd,int n,int amount);
void (*delitem) (struct map_session_data *sd,int n,int amount, short reason);
void (*takeitem) (struct block_list* src, struct block_list* dst);
+ void (*item_movefailed) (struct map_session_data *sd, int n);
void (*item_equip) (short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos);
void (*item_normal) (short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id);
void (*arrowequip) (struct map_session_data *sd,int val);
@@ -632,18 +818,18 @@ struct clif_interface {
void (*equipitemack) (struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result);
void (*unequipitemack) (struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result);
void (*useitemack) (struct map_session_data *sd,int index,int amount,bool ok);
- void (*addcards) (unsigned char* buf, struct item* item);
- void (*addcards2) (unsigned short *cards, struct item* item);
+ void (*addcards) (struct EQUIPSLOTINFO *buf, struct item* item);
void (*item_sub) (unsigned char *buf, int n, struct item *i, struct item_data *id, int equip);
void (*getareachar_item) (struct map_session_data* sd,struct flooritem_data* fitem);
void (*cart_additem_ack) (struct map_session_data *sd, int flag);
void (*cashshop_load) (void);
- void (*package_announce) (struct map_session_data *sd, unsigned short nameid, unsigned short containerid);
- void (*item_drop_announce) (struct map_session_data *sd, unsigned short nameid, char *monsterName);
+ void (*cashShopSchedule) (int fd, struct map_session_data *sd);
+ void (*package_announce) (struct map_session_data *sd, int nameid, int containerid);
+ void (*item_drop_announce) (struct map_session_data *sd, int nameid, char *monsterName);
/* unit-related */
- void (*clearunit_single) (int id, clr_type type, int fd);
- void (*clearunit_area) (struct block_list* bl, clr_type type);
- void (*clearunit_delayed) (struct block_list* bl, clr_type type, int64 tick);
+ void (*clearunit_single) (int id, enum clr_type type, int fd);
+ void (*clearunit_area) (struct block_list* bl, enum clr_type type);
+ void (*clearunit_delayed) (struct block_list* bl, enum clr_type type, int64 tick);
void (*walkok) (struct map_session_data *sd);
void (*move) (struct unit_data *ud);
void (*move2) (struct block_list *bl, struct view_data *vd, struct unit_data *ud);
@@ -654,7 +840,7 @@ struct clif_interface {
void (*changetraplook) (struct block_list *bl,int val);
void (*refreshlook) (struct block_list *bl,int id,int type,int val,enum send_target target);
void (*sendlook) (struct block_list *bl, int id, int type, int val, int val2, enum send_target target);
- void (*class_change) (struct block_list *bl,int class_,int type);
+ void (*class_change) (struct block_list *bl,int class_,int type, struct map_session_data *sd);
void (*skill_delunit) (struct skill_unit *su);
void (*skillunit_update) (struct block_list* bl);
int (*clearunit_delayed_sub) (int tid, int64 tick, int id, intptr_t data);
@@ -673,6 +859,7 @@ struct clif_interface {
bool (*spawn) (struct block_list *bl);
/* map-related */
void (*changemap) (struct map_session_data *sd, short m, int x, int y);
+ void (*changemap_airship) (struct map_session_data *sd, short m, int x, int y);
void (*changemapcell) (int fd, int16 m, int x, int y, int type, enum send_target target);
void (*map_property) (struct map_session_data* sd, enum map_property property);
void (*pvpset) (struct map_session_data *sd, int pvprank, int pvpnum,int type);
@@ -681,7 +868,8 @@ struct clif_interface {
void (*map_type) (struct map_session_data* sd, enum map_type type);
void (*maptypeproperty2) (struct block_list *bl,enum send_target t);
/* multi-map-server */
- void (*changemapserver) (struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port);
+ void (*changemapserver) (struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port, char *dnsHost);
+ void (*changemapserver_airship) (struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port);
/* npc-shop-related */
void (*npcbuysell) (struct map_session_data* sd, int id);
void (*buylist) (struct map_session_data *sd, struct npc_data *nd);
@@ -702,7 +890,7 @@ struct clif_interface {
void (*scriptclear) (struct map_session_data *sd, int npcid);
/* client-user-interface-related */
void (*viewpoint) (struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color);
- int (*damage) (struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2);
+ int (*damage) (struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 damage, short div, enum battle_dmg_type type, int64 damage2);
void (*sitting) (struct block_list* bl);
void (*standing) (struct block_list* bl);
void (*arrow_create_list) (struct map_session_data *sd);
@@ -712,13 +900,16 @@ struct clif_interface {
void (*fame_alchemist) (struct map_session_data *sd, int points);
void (*fame_taekwon) (struct map_session_data *sd, int points);
void (*ranklist) (struct map_session_data *sd, enum fame_list_type type);
+ void (*ranklist_sub) (struct PACKET_ZC_ACK_RANKING_sub *ranks, enum fame_list_type type);
+ void (*ranklist_sub2) (uint32 *chars, uint32 *points, enum fame_list_type type);
void (*update_rankingpoint) (struct map_session_data *sd, enum fame_list_type type, int points);
void (*pRanklist) (int fd, struct map_session_data *sd);
- void (*hotkeys) (struct map_session_data *sd);
+ void (*hotkeys) (struct map_session_data *sd, int tab);
+ void (*hotkeysAll) (struct map_session_data *sd);
int (*insight) (struct block_list *bl,va_list ap);
int (*outsight) (struct block_list *bl,va_list ap);
void (*skillcastcancel) (struct block_list* bl);
- void (*skill_fail) (struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype);
+ void (*skill_fail) (struct map_session_data *sd, uint16 skill_id, enum useskill_fail_cause cause, int btype, int32 item_id);
void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int duration);
void (*skill_memomessage) (struct map_session_data* sd, int type);
void (*skill_mapinfomessage) (struct map_session_data *sd, int type);
@@ -726,11 +917,21 @@ struct clif_interface {
void (*cooking_list) (struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type);
void (*autospell) (struct map_session_data *sd,uint16 skill_lv);
void (*combo_delay) (struct block_list *bl,int wait);
- void (*status_change) (struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3);
+ void (*status_change) (struct block_list *bl, int relevant_bl, int type, int flag, int total_tick, int val1, int val2, int val3);
+ void (*status_change_sub) (struct block_list *bl, int type, int relevant_bl, int flag, int tick, int total_tick, int val1, int val2, int val3);
void (*insert_card) (struct map_session_data *sd,int idx_equip,int idx_card,int flag);
- void (*inventorylist) (struct map_session_data *sd);
- void (*equiplist) (struct map_session_data *sd);
- void (*cartlist) (struct map_session_data *sd);
+ void (*inventoryList) (struct map_session_data *sd);
+ void (*inventoryItems) (struct map_session_data *sd, enum inventory_type type);
+ void (*equipList) (struct map_session_data *sd);
+ void (*equipItems) (struct map_session_data *sd, enum inventory_type type);
+ void (*cartList) (struct map_session_data *sd);
+ void (*cartItems) (struct map_session_data *sd, enum inventory_type type);
+ void (*inventoryExpansionInfo) (struct map_session_data *sd);
+ void (*inventoryExpandAck) (struct map_session_data *sd, enum expand_inventory result, int itemId);
+ void (*inventoryExpandResult) (struct map_session_data *sd, enum expand_inventory_result result);
+ void (*pInventoryExpansion) (int fd, struct map_session_data *sd);
+ void (*pInventoryExpansionConfirmed) (int fd, struct map_session_data *sd);
+ void (*pInventoryExpansionRejected) (int fd, struct map_session_data *sd);
void (*favorite_item) (struct map_session_data* sd, unsigned short index);
void (*clearcart) (int fd);
void (*item_identify_list) (struct map_session_data *sd);
@@ -744,13 +945,27 @@ struct clif_interface {
void (*mvp_exp) (struct map_session_data *sd, unsigned int exp);
void (*mvp_noitem) (struct map_session_data* sd);
void (*changed_dir) (struct block_list *bl, enum send_target target);
- void (*charnameack) (int fd, struct block_list *bl);
+ void (*blname_ack) (int fd, struct block_list *bl);
+ void (*pcname_ack) (int fd, struct block_list *bl);
+ void (*homname_ack) (int fd, struct block_list *bl);
+ void (*mername_ack) (int fd, struct block_list *bl);
+ void (*petname_ack) (int fd, struct block_list *bl);
+ void (*npcname_ack) (int fd, struct block_list *bl);
+ void (*mobname_ack) (int fd, struct block_list *bl);
+ void (*mobname_guardian_ack) (int fd, struct block_list *bl);
+ void (*mobname_additional_ack) (int fd, struct block_list *bl);
+ void (*mobname_normal_ack) (int fd, struct block_list *bl);
+ void (*chatname_ack) (int fd, struct block_list *bl);
+ void (*elemname_ack) (int fd, struct block_list *bl);
+ void (*skillname_ack) (int fd, struct block_list *bl);
+ void (*itemname_ack) (int fd, struct block_list *bl);
+ void (*unknownname_ack) (int fd, struct block_list *bl);
void (*monster_hp_bar) ( struct mob_data* md, struct map_session_data *sd );
int (*hpmeter) (struct map_session_data *sd);
void (*hpmeter_single) (int fd, int id, unsigned int hp, unsigned int maxhp);
int (*hpmeter_sub) (struct block_list *bl, va_list ap);
void (*upgrademessage) (int fd, int result, int item_id);
- void (*get_weapon_view) (struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand);
+ void (*get_weapon_view) (struct map_session_data* sd, int *rhand, int *lhand);
void (*gospel_info) (struct map_session_data *sd, int type);
void (*feel_req) (int fd, struct map_session_data *sd, uint16 skill_lv);
void (*starskill) (struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result);
@@ -759,13 +974,14 @@ struct clif_interface {
void (*mission_info) (struct map_session_data *sd, int mob_id, unsigned char progress);
void (*feel_hate_reset) (struct map_session_data *sd);
void (*partytickack) (struct map_session_data* sd, bool flag);
- void (*equiptickack) (struct map_session_data* sd, int flag);
+ void (*zc_config) (struct map_session_data *sd, enum CZ_CONFIG type, int flag);
void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd);
void (*equpcheckbox) (struct map_session_data* sd);
- void (*displayexp) (struct map_session_data *sd, unsigned int exp, char type, bool is_quest);
+ void (*displayexp) (struct map_session_data *sd, uint64 exp, char type, bool is_quest);
void (*font) (struct map_session_data *sd);
void (*progressbar) (struct map_session_data * sd, unsigned int color, unsigned int second);
void (*progressbar_abort) (struct map_session_data * sd);
+ void (*progressbar_unit) (struct block_list *bl, uint32 color, uint32 time);
void (*showdigit) (struct map_session_data* sd, unsigned char type, int value);
int (*elementalconverter_list) (struct map_session_data *sd);
int (*spellbook_list) (struct map_session_data *sd);
@@ -774,6 +990,7 @@ struct clif_interface {
int (*autoshadowspell_list) (struct map_session_data *sd);
int (*skill_itemlistwindow) ( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv );
void (*sc_load) (struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3);
+ void (*sc_continue) (struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3);
void (*sc_end) (struct block_list *bl, int tid, enum send_target target, int type);
void (*initialstatus) (struct map_session_data *sd);
void (*cooldown_list) (int fd, struct skill_cd* cd);
@@ -796,18 +1013,19 @@ struct clif_interface {
/* visual effects client-side */
void (*misceffect) (struct block_list* bl,int type);
void (*changeoption) (struct block_list* bl);
+ void (*changeoption_target) (struct block_list *bl, struct block_list *target_bl, enum send_target target);
void (*changeoption2) (struct block_list* bl);
void (*emotion) (struct block_list *bl,int type);
void (*talkiebox) (struct block_list* bl, const char* talkie);
void (*wedding_effect) (struct block_list *bl);
void (*divorced) (struct map_session_data* sd, const char* name);
void (*callpartner) (struct map_session_data *sd);
- int (*skill_damage) (struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 damage, int div, uint16 skill_id, uint16 skill_lv, int type);
+ int (*skill_damage) (struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 damage, int div, uint16 skill_id, uint16 skill_lv, enum battle_dmg_type type);
int (*skill_nodamage) (struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail);
void (*skill_poseffect) (struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick);
void (*skill_estimation) (struct map_session_data *sd,struct block_list *dst);
void (*skill_warppoint) (struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4);
- void (*skillcasting) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime);
+ void (*useskill) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int casttime);
void (*produce_effect) (struct map_session_data* sd,int flag,int nameid);
void (*devotion) (struct block_list *src, struct map_session_data *tsd);
void (*spiritball) (struct block_list *bl);
@@ -820,7 +1038,10 @@ struct clif_interface {
void (*weather) (int16 m);
void (*specialeffect) (struct block_list* bl, int type, enum send_target target);
void (*specialeffect_single) (struct block_list* bl, int type, int fd);
- void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target);
+ void (*specialeffect_value) (struct block_list* bl, int effect_id, uint64 num, send_target target);
+ void (*specialeffect_value_single) (struct block_list *bl, int effect_id, uint64 num, int fd);
+ void (*removeSpecialEffect) (struct block_list *bl, int effectId, enum send_target target);
+ void (*removeSpecialEffect_single) (struct block_list *bl, int effectId, struct block_list *targetBl);
void (*millenniumshield) (struct block_list *bl, short shields );
void (*spiritcharm) (struct map_session_data *sd);
void (*charm_single) (int fd, struct map_session_data *sd);
@@ -838,29 +1059,36 @@ struct clif_interface {
void (*joinchatok) (struct map_session_data *sd,struct chat_data* cd);
void (*addchat) (struct chat_data* cd,struct map_session_data *sd);
void (*changechatowner) (struct chat_data* cd, struct map_session_data* sd);
+ void (*chatRoleChange) (struct chat_data *cd, struct map_session_data *sd, struct block_list* bl, int isNotOwner);
void (*clearchat) (struct chat_data *cd,int fd);
void (*leavechat) (struct chat_data* cd, struct map_session_data* sd, bool flag);
void (*changechatstatus) (struct chat_data* cd);
- void (*wis_message) (int fd, const char* nick, const char* mes, size_t mes_len);
+ void (*wis_message) (int fd, const char *nick, const char *mes, int mes_len);
void (*wis_end) (int fd, int flag);
- void (*disp_message) (struct block_list* src, const char* mes, size_t len, enum send_target target);
- void (*broadcast) (struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
- void (*broadcast2) (struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
+ void (*disp_message) (struct block_list *src, const char *mes, enum send_target target);
+ void (*broadcast) (struct block_list *bl, const char *mes, int len, int type, enum send_target target);
+ void (*broadcast2) (struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
void (*messagecolor_self) (int fd, uint32 color, const char *msg);
void (*messagecolor) (struct block_list* bl, uint32 color, const char* msg);
- void (*disp_overhead) (struct block_list *bl, const char* mes);
- void (*msgtable) (struct map_session_data* sd, unsigned short msg_id);
- void (*msgtable_num) (struct map_session_data *sd, unsigned short msg_id, int value);
- void (*msgtable_skill) (struct map_session_data *sd, uint16 skill_id, int msg_id);
+ void (*serviceMessageColor) (struct map_session_data *sd, uint32 color, const char *msg);
+ void (*disp_overhead) (struct block_list *bl, const char *mes, enum send_target target, struct block_list *target_bl);
+ void (*notify_playerchat) (struct block_list *bl, const char *mes);
+ void (*msgtable) (struct map_session_data* sd, enum clif_messages msg_id);
+ void (*msgtable_num) (struct map_session_data *sd, enum clif_messages msg_id, int value);
+ void (*msgtable_skill) (struct map_session_data *sd, uint16 skill_id, enum clif_messages msg_id);
+ void (*msgtable_str) (struct map_session_data *sd, enum clif_messages, const char *value);
+ void (*msgtable_str_color) (struct map_session_data *sd, enum clif_messages, const char *value, uint32 color);
+ void (*msgtable_color) (struct map_session_data *sd, enum clif_messages, uint32 color);
void (*message) (const int fd, const char* mes);
void (*messageln) (const int fd, const char* mes);
/* message+s(printf) */
void (*messages) (const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3)));
- bool (*process_message) (struct map_session_data *sd, int format, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_);
+ const char *(*process_chat_message) (struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen);
+ bool (*process_whisper_message) (struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen);
void (*wisexin) (struct map_session_data *sd,int type,int flag);
void (*wisall) (struct map_session_data *sd,int type,int flag);
void (*PMIgnoreList) (struct map_session_data* sd);
- void (*ShowScript) (struct block_list* bl, const char* message);
+ void (*ShowScript) (struct block_list* bl, const char* message, enum send_target target);
/* trade handling */
void (*traderequest) (struct map_session_data* sd, const char* name);
void (*tradestart) (struct map_session_data* sd, uint8 type);
@@ -877,9 +1105,14 @@ struct clif_interface {
void (*vendinglist) (struct map_session_data* sd, unsigned int id, struct s_vending* vending_list);
void (*buyvending) (struct map_session_data* sd, int index, int amount, int fail);
void (*openvending) (struct map_session_data* sd, int id, struct s_vending* vending_list);
- void (*vendingreport) (struct map_session_data* sd, int index, int amount);
+ void (*openvendingAck) (int fd, int result);
+ void (*vendingreport) (struct map_session_data* sd, int index, int amount, uint32 char_id, int zeny);
/* storage handling */
- void (*storagelist) (struct map_session_data* sd, struct item* items, int items_length);
+ void (*storageList) (struct map_session_data* sd, struct item* items, int items_length);
+ void (*guildStorageList) (struct map_session_data* sd, struct item* items, int items_length);
+ void (*storageItems) (struct map_session_data* sd, enum inventory_type type, struct item* items, int items_length);
+ void (*inventoryStart) (struct map_session_data* sd, enum inventory_type type, const char* name);
+ void (*inventoryEnd) (struct map_session_data* sd, enum inventory_type type);
void (*updatestorageamount) (struct map_session_data* sd, int amount, int max_amount);
void (*storageitemadded) (struct map_session_data* sd, struct item* i, int index, int amount);
void (*storageitemremoved) (struct map_session_data* sd, int index, int amount);
@@ -890,10 +1123,12 @@ struct clif_interface {
void (*skillinfo) (struct map_session_data *sd,int skill_id, int inf);
void (*addskill) (struct map_session_data *sd, int id);
void (*deleteskill) (struct map_session_data *sd, int id);
+ void (*playerSkillToPacket) (struct map_session_data *sd, struct SKILLDATA *skillData, int skillId, int idx, bool newSkill);
/* party-specific */
void (*party_created) (struct map_session_data *sd,int result);
void (*party_member_info) (struct party_data *p, struct map_session_data *sd);
void (*party_info) (struct party_data* p, struct map_session_data *sd);
+ void (*party_job_and_level) (struct map_session_data *sd);
void (*party_invite) (struct map_session_data *sd,struct map_session_data *tsd);
void (*party_inviteack) (struct map_session_data* sd, const char* nick, int result);
void (*party_option) (struct party_data *p,struct map_session_data *sd,int flag);
@@ -912,14 +1147,16 @@ struct clif_interface {
void (*guild_masterormember) (struct map_session_data *sd);
void (*guild_basicinfo) (struct map_session_data *sd);
void (*guild_allianceinfo) (struct map_session_data *sd);
+ void (*guild_castlelist) (struct map_session_data *sd);
+ void (*guild_castleinfo) (struct map_session_data *sd, struct guild_castle *gc);
void (*guild_memberlist) (struct map_session_data *sd);
void (*guild_skillinfo) (struct map_session_data* sd);
void (*guild_send_onlineinfo) (struct map_session_data *sd); //[LuzZza]
void (*guild_memberlogin_notice) (struct guild *g,int idx,int flag);
void (*guild_invite) (struct map_session_data *sd,struct guild *g);
void (*guild_inviteack) (struct map_session_data *sd,int flag);
- void (*guild_leave) (struct map_session_data *sd,const char *name,const char *mes);
- void (*guild_expulsion) (struct map_session_data* sd, const char* name, const char* mes, int account_id);
+ void (*guild_leave) (struct map_session_data *sd, const char *name, int char_id, const char *mes);
+ void (*guild_expulsion) (struct map_session_data* sd, const char* name, int char_id, const char* mes, int account_id);
void (*guild_positionchanged) (struct guild *g,int idx);
void (*guild_memberpositionchanged) (struct guild *g,int idx);
void (*guild_emblem) (struct map_session_data *sd,struct guild *g);
@@ -937,12 +1174,15 @@ struct clif_interface {
void (*guild_positionnamelist) (struct map_session_data *sd);
void (*guild_positioninfolist) (struct map_session_data *sd);
void (*guild_expulsionlist) (struct map_session_data* sd);
+ void (*guild_set_position) (struct map_session_data *sd);
+ void (*guild_position_selected) (struct map_session_data *sd);
+
bool (*validate_emblem) (const uint8* emblem, unsigned long emblem_len);
/* battleground-specific */
void (*bg_hp) (struct map_session_data *sd);
void (*bg_xy) (struct map_session_data *sd);
void (*bg_xy_remove) (struct map_session_data *sd);
- void (*bg_message) (struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len);
+ void (*bg_message) (struct battleground_data *bgd, int src_id, const char *name, const char *mes);
void (*bg_updatescore) (int16 m);
void (*bg_updatescore_single) (struct map_session_data *sd);
void (*sendbgemblem_area) (struct map_session_data *sd);
@@ -985,6 +1225,7 @@ struct clif_interface {
void (*quest_delete) (struct map_session_data *sd, int quest_id);
void (*quest_update_status) (struct map_session_data *sd, int quest_id, bool active);
void (*quest_update_objective) (struct map_session_data *sd, struct quest *qd);
+ void (*quest_notify_objective) (struct map_session_data *sd, struct quest *qd);
void (*quest_show_event) (struct map_session_data *sd, struct block_list *bl, short state, short color);
/* mail-related */
void (*mail_window) (int fd, int flag);
@@ -1039,9 +1280,9 @@ struct clif_interface {
void (*buyingstore_disappear_entry_single) (struct map_session_data* sd, struct map_session_data* pl_sd);
void (*buyingstore_itemlist) (struct map_session_data* sd, struct map_session_data* pl_sd);
void (*buyingstore_trade_failed_buyer) (struct map_session_data* sd, short result);
- void (*buyingstore_update_item) (struct map_session_data* sd, unsigned short nameid, unsigned short amount);
+ void (*buyingstore_update_item) (struct map_session_data* sd, int nameid, unsigned short amount, uint32 char_id, int zeny);
void (*buyingstore_delete_item) (struct map_session_data* sd, short index, unsigned short amount, int price);
- void (*buyingstore_trade_failed_seller) (struct map_session_data* sd, short result, unsigned short nameid);
+ void (*buyingstore_trade_failed_seller) (struct map_session_data* sd, short result, int nameid);
/* search store-related */
void (*search_store_info_ack) (struct map_session_data* sd);
void (*search_store_info_failed) (struct map_session_data* sd, unsigned char reason);
@@ -1077,27 +1318,40 @@ struct clif_interface {
/* */
void (*notify_bounditem) (struct map_session_data *sd, unsigned short index);
/* */
- int (*delay_damage) (int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type);
+ int (*delay_damage) (int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, enum battle_dmg_type type);
int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data);
/* NPC Market */
void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd);
- void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, unsigned char response);
+ void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, enum market_buy_result response);
/* */
bool (*parse_roulette_db) (void);
- void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID);
+ void (*roulette_generate_ack) (struct map_session_data *sd, enum GENERATE_ROULETTE_ACK result, short stage, short prizeIdx, int bonusItemID);
+ void (*roulette_close) (struct map_session_data *sd);
/* Merge Items */
void (*openmergeitem) (int fd, struct map_session_data *sd);
void (*cancelmergeitem) (int fd, struct map_session_data *sd);
int (*comparemergeitem) (const void *a, const void *b);
void (*ackmergeitems) (int fd, struct map_session_data *sd);
-
+ void (*mergeitems) (int fd, struct map_session_data *sd, int index, int amount, enum mergeitem_reason reason);
+ /* */
+ bool (*isdisguised) (struct block_list* bl);
+ void (*navigate_to) (struct map_session_data *sd, const char* mapname, uint16 x, uint16 y, uint8 flag, bool hideWindow, uint16 mob_id);
+ unsigned char (*bl_type) (struct block_list *bl);
+ /* Achievement System */
+ void (*achievement_send_list) (int fd, struct map_session_data *sd);
+ void (*achievement_send_update) (int fd, struct map_session_data *sd, const struct achievement_data *ad);
+ void (*pAchievementGetReward) (int fd, struct map_session_data *sd);
+ void (*achievement_reward_ack) (int fd, struct map_session_data *sd, const struct achievement_data *ad);
+ void (*change_title_ack) (int fd, struct map_session_data *sd, int title_id);
+ void (*pChangeTitle) (int fd, struct map_session_data *sd);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
void (*pWantToConnection) (int fd, struct map_session_data *sd);
void (*pLoadEndAck) (int fd,struct map_session_data *sd);
void (*pTickSend) (int fd, struct map_session_data *sd);
- void (*pHotkey) (int fd, struct map_session_data *sd);
+ void (*pHotkey1) (int fd, struct map_session_data *sd);
+ void (*pHotkey2) (int fd, struct map_session_data *sd);
void (*pProgressbar) (int fd, struct map_session_data * sd);
void (*pWalkToXY) (int fd, struct map_session_data *sd);
void (*pQuitGame) (int fd, struct map_session_data *sd);
@@ -1140,7 +1394,10 @@ struct clif_interface {
void (*pChangeCart) (int fd,struct map_session_data *sd);
void (*pStatusUp) (int fd,struct map_session_data *sd);
void (*pSkillUp) (int fd,struct map_session_data *sd);
+ void (*useSkillToIdReal) (int fd, struct map_session_data *sd, int skill_id, int skill_lv, int target_id);
void (*pUseSkillToId) (int fd, struct map_session_data *sd);
+ void (*pStartUseSkillToId) (int fd, struct map_session_data *sd);
+ void (*pStopUseSkillToId) (int fd, struct map_session_data *sd);
void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id);
void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id);
void (*pUseSkillToPos) (int fd, struct map_session_data *sd);
@@ -1274,7 +1531,7 @@ struct clif_interface {
void (*pAdopt_request) (int fd, struct map_session_data *sd);
void (*pAdopt_reply) (int fd, struct map_session_data *sd);
void (*pViewPlayerEquip) (int fd, struct map_session_data* sd);
- void (*pEquipTick) (int fd, struct map_session_data* sd);
+ void (*p_cz_config) (int fd, struct map_session_data *sd);
void (*pquestStateAck) (int fd, struct map_session_data * sd);
void (*pmercenary_action) (int fd, struct map_session_data* sd);
void (*pBattleChat) (int fd, struct map_session_data* sd);
@@ -1292,19 +1549,24 @@ struct clif_interface {
void (*pSkillSelectMenu) (int fd, struct map_session_data *sd);
void (*pMoveItem) (int fd, struct map_session_data *sd);
void (*pDull) (int fd, struct map_session_data *sd);
+ void (*p_cz_blocking_play_cancel) (int fd, struct map_session_data *sd);
/* BGQueue */
void (*pBGQueueRegister) (int fd, struct map_session_data *sd);
void (*pBGQueueCheckState) (int fd, struct map_session_data *sd);
void (*pBGQueueRevokeReq) (int fd, struct map_session_data *sd);
void (*pBGQueueBattleBeginAck) (int fd, struct map_session_data *sd);
/* RagExe Cash Shop [Ind/Hercules] */
- void (*pCashShopOpen) (int fd, struct map_session_data *sd);
+ void (*pCashShopOpen1) (int fd, struct map_session_data *sd);
+ void (*pCashShopOpen2) (int fd, struct map_session_data *sd);
+ void (*pCashShopLimitedReq) (int fd, struct map_session_data *sd);
void (*pCashShopClose) (int fd, struct map_session_data *sd);
void (*pCashShopReqTab) (int fd, struct map_session_data *sd);
void (*pCashShopSchedule) (int fd, struct map_session_data *sd);
void (*pCashShopBuy) (int fd, struct map_session_data *sd);
void (*pPartyTick) (int fd, struct map_session_data *sd);
void (*pGuildInvite2) (int fd, struct map_session_data *sd);
+ void (*cashShopBuyAck) (int fd, struct map_session_data *sd, int itemId, enum CASH_SHOP_BUY_RESULT result);
+ void (*cashShopOpen) (int fd, struct map_session_data *sd, int tab);
/* Group Search System Update */
void (*pPartyBookingAddFilter) (int fd, struct map_session_data *sd);
void (*pPartyBookingSubFilter) (int fd, struct map_session_data *sd);
@@ -1329,8 +1591,9 @@ struct clif_interface {
void (*pNPCMarketClosed) (int fd, struct map_session_data *sd);
void (*pNPCMarketPurchase) (int fd, struct map_session_data *sd);
/* */
- void (*add_random_options) (unsigned char* buf, struct item* item);
- void (*pHotkeyRowShift) (int fd, struct map_session_data *sd);
+ int (*add_item_options) (struct ItemOptions *buf, const struct item *it);
+ void (*pHotkeyRowShift1) (int fd, struct map_session_data *sd);
+ void (*pHotkeyRowShift2) (int fd, struct map_session_data *sd);
void (*dressroom_open) (struct map_session_data *sd, int view);
void (*pOneClick_ItemIdentify) (int fd,struct map_session_data *sd);
/* Cart Deco */
@@ -1338,6 +1601,105 @@ struct clif_interface {
void (*pSelectCart) (int fd, struct map_session_data *sd);
const char *(*get_bl_name) (const struct block_list *bl);
+
+ /* RoDEX */
+ void (*pRodexOpenWriteMail) (int fd, struct map_session_data *sd);
+ void (*rodex_open_write_mail) (int fd, const char *receiver_name, int8 result);
+ void (*pRodexAddItem) (int fd, struct map_session_data *sd);
+ void (*rodex_add_item_result) (struct map_session_data *sd, int16 idx, int16 amount, enum rodex_add_item result);
+ void (*pRodexRemoveItem) (int fd, struct map_session_data *sd);
+ void (*rodex_remove_item_result) (struct map_session_data *sd, int16 idx, int16 amount);
+ void (*pRodexSendMail) (int fd, struct map_session_data *sd);
+ void (*rodex_send_mail_result) (int fd, struct map_session_data *sd, int8 result);
+ void (*rodex_send_maillist) (int fd, struct map_session_data *sd, int8 open_type, int64 page_start);
+ void (*rodex_send_refresh) (int fd, struct map_session_data *sd, int8 open_type, int count);
+ void (*rodex_send_mails_all) (int fd, struct map_session_data *sd, int64 mail_id);
+ void (*pRodexReadMail) (int fd, struct map_session_data *sd);
+ void (*rodex_read_mail) (struct map_session_data *sd, int8 opentype, struct rodex_message *msg);
+ void (*pRodexNextMaillist) (int fd, struct map_session_data *sd);
+ void (*pRodexCloseMailbox) (int fd, struct map_session_data *sd);
+ void (*pRodexCancelWriteMail) (int fd, struct map_session_data *sd);
+ void (*pRodexOpenMailbox) (int fd, struct map_session_data *sd);
+ void (*pRodexCheckName) (int fd, struct map_session_data *sd);
+ void (*rodex_checkname_result) (struct map_session_data *sd, int char_id, int class_, int base_level, const char *name);
+ void (*pRodexDeleteMail) (int fd, struct map_session_data *sd);
+ void (*rodex_delete_mail) (struct map_session_data *sd, int8 opentype, int64 mail_id);
+ void (*pRodexRefreshMaillist) (int fd, struct map_session_data *sd);
+ void (*pRodexRequestZeny) (int fd, struct map_session_data *sd);
+ void (*rodex_request_zeny) (struct map_session_data *sd, int8 opentype, int64 mail_id, enum rodex_get_zeny result);
+ void (*pRodexRequestItems) (int fd, struct map_session_data *sd);
+ void (*rodex_request_items) (struct map_session_data *sd, int8 opentype, int64 mail_id, enum rodex_get_items result);
+ void (*rodex_icon) (int fd, bool show);
+ void (*skill_scale) (struct block_list *bl, int src_id, int x, int y, uint16 skill_id, uint16 skill_lv, int casttime);
+ /* Clan System */
+ void (*clan_basicinfo) (struct map_session_data *sd);
+ void (*clan_onlinecount) (struct clan *c);
+ void (*clan_leave) (struct map_session_data *sd);
+ void (*clan_message) (struct clan *c, const char *mes, int len);
+ void (*pClanMessage) (int fd, struct map_session_data* sd);
+ /* Hat Effect */
+ void (*hat_effect) (struct block_list *bl, struct block_list *tbl, enum send_target target);
+ void (*hat_effect_single) (struct block_list *bl, uint16 effectId, bool enable);
+ void (*overweight_percent) (struct map_session_data *sd);
+ void (*pChangeDress) (int fd, struct map_session_data *sd);
+
+ bool (*pAttendanceDB) (void);
+ bool (*attendancedb_libconfig_sub) (struct config_setting_t *it, int n, const char *source);
+ bool (*attendance_timediff) (struct map_session_data *sd);
+ time_t (*attendance_getendtime) (void);
+ void (*pOpenUIRequest) (int fd, struct map_session_data *sd);
+ void (*open_ui) (struct map_session_data *sd, enum cz_ui_types uiType);
+ void (*pAttendanceRewardRequest) (int fd, struct map_session_data *sd);
+ void (*ui_action) (struct map_session_data *sd, int32 UIType, int32 data);
+ void (*pPrivateAirshipRequest) (int fd, struct map_session_data *sd);
+ void (*PrivateAirshipResponse) (struct map_session_data *sd, uint32 flag);
+
+ void (*pReqStyleChange) (int fd, struct map_session_data *sd);
+ void (*pReqStyleChange2) (int fd, struct map_session_data *sd);
+ void (*pStyleClose) (int fd, struct map_session_data *sd);
+ void (*style_change_response) (struct map_session_data *sd, enum stylist_shop flag);
+ void (*pPetEvolution) (int fd, struct map_session_data *sd);
+ void (*petEvolutionResult) (int fd, enum pet_evolution_result result);
+ void (*party_dead_notification) (struct map_session_data *sd);
+ void (*pMemorialDungeonCommand) (int fd, struct map_session_data *sd);
+ void (*camera_showWindow) (struct map_session_data *sd);
+ void (*camera_change) (struct map_session_data *sd, float range, float rotation, float latitude, enum send_target target);
+ void (*pCameraInfo) (int fd, struct map_session_data *sd);
+ void (*item_preview) (struct map_session_data *sd, int n);
+ bool (*enchant_equipment) (struct map_session_data *sd, enum equip_pos pos, int cardSlot, int cardId);
+ void (*pReqRemainTime) (int fd, struct map_session_data *sd);
+ void (*npc_barter_open) (struct map_session_data *sd, struct npc_data *nd);
+ void (*pNPCBarterClosed) (int fd, struct map_session_data *sd);
+ void (*pNPCBarterPurchase) (int fd, struct map_session_data *sd);
+ void (*pNPCExpandedBarterClosed) (int fd, struct map_session_data *sd);
+ void (*pNPCExpandedBarterPurchase) (int fd, struct map_session_data *sd);
+ void (*npc_expanded_barter_open) (struct map_session_data *sd, struct npc_data *nd);
+ void (*pClientVersion) (int fd, struct map_session_data *sd);
+ void (*pPing) (int fd, struct map_session_data *sd);
+ void (*ping) (struct map_session_data *sd);
+ int (*pingTimer) (int tid, int64 tick, int id, intptr_t data);
+ int (*pingTimerSub) (struct map_session_data *sd, va_list ap);
+ void (*pResetCooldown) (int fd, struct map_session_data *sd);
+ void (*loadConfirm) (struct map_session_data *sd);
+ void (*send_selforarea) (int fd, struct block_list *bl, const void *buf, int len);
+ void (*OpenRefineryUI) (struct map_session_data *sd);
+ void (*pAddItemRefineryUI) (int fd, struct map_session_data *sd);
+ void (*AddItemRefineryUIAck) (struct map_session_data *sd, int item_index, struct s_refine_requirement *req);
+ void (*pRefineryUIClose) (int fd, struct map_session_data *sd);
+ void (*pRefineryUIRefine) (int fd, struct map_session_data *sd);
+ void (*announce_refine_status) (struct map_session_data *sd, int item_id, int refine_level, bool success, enum send_target target);
+ void (*pGuildCastleTeleportRequest) (int fd, struct map_session_data *sd);
+ void (*pGuildCastleInfoRequest) (int fd, struct map_session_data *sd);
+ void (*guild_castleteleport_res) (struct map_session_data *sd, enum siege_teleport_result result);
+ bool (*lapineDdukDdak_open) (struct map_session_data *sd, int item_id);
+ bool (*lapineDdukDdak_result) (struct map_session_data *sd, enum lapineddukddak_result result);
+ void (*plapineDdukDdak_ack) (int fd, struct map_session_data *sd);
+ void (*plapineDdukDdak_close) (int fd, struct map_session_data *sd);
+ bool (*lapineUpgrade_open) (struct map_session_data *sd, int item_id);
+ bool (*lapineUpgrade_result) (struct map_session_data *sd, enum lapineUpgrade_result result);
+ void (*pLapineUpgrade_close) (int fd, struct map_session_data *sd);
+ void (*pLapineUpgrade_makeItem) (int fd, struct map_session_data *sd);
+ void (*pReqGearOff) (int fd, struct map_session_data *sd);
};
#ifdef HERCULES_CORE
diff --git a/src/map/date.c b/src/map/date.c
index 5579962bf..9db7155ab 100644
--- a/src/map/date.c
+++ b/src/map/date.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -77,6 +77,27 @@ int date_get_sec(void)
return lt->tm_sec;
}
+int date_get_dayofweek(void)
+{
+ time_t t = time(NULL);
+ struct tm *lt = localtime(&t);
+ return lt->tm_wday;
+}
+
+// Returns YYYYMMDD of now
+int date_get_date(void)
+{
+ time_t t;
+ struct tm * lt;
+ t = time(NULL);
+ lt = localtime(&t);
+
+ return
+ (lt->tm_year + 1900) * 10000 +
+ (lt->tm_mon + 1) * 100 +
+ (lt->tm_mday);
+}
+
/*==========================================
* Star gladiator related checks
*------------------------------------------*/
diff --git a/src/map/date.h b/src/map/date.h
index 831539e3c..1673b8c6d 100644
--- a/src/map/date.h
+++ b/src/map/date.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,6 +31,8 @@ int date_get_day(void);
int date_get_hour(void);
int date_get_min(void);
int date_get_sec(void);
+int date_get_dayofweek(void);
+int date_get_date(void);
bool is_day_of_sun(void);
bool is_day_of_moon(void);
diff --git a/src/map/duel.c b/src/map/duel.c
index c658ea3e3..c66fd6fc2 100644
--- a/src/map/duel.c
+++ b/src/map/duel.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,36 +33,23 @@
#include <string.h>
#include <time.h>
-struct duel_interface duel_s;
+static struct duel_interface duel_s;
struct duel_interface *duel;
/*==========================================
* Duel organizing functions [LuzZza]
*------------------------------------------*/
-void duel_savetime(struct map_session_data* sd) {
- time_t clock;
- struct tm *t;
-
- time(&clock);
- t = localtime(&clock);
-
- pc_setglobalreg(sd, script->add_str("PC_LAST_DUEL_TIME"), t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);
+static void duel_savetime(struct map_session_data *sd)
+{
+ pc_setglobalreg(sd, script->add_variable("PC_LAST_DUEL_TIME"), (int)time(NULL));
}
-int duel_checktime(struct map_session_data* sd) {
- int diff;
- time_t clock;
- struct tm *t;
-
- time(&clock);
- t = localtime(&clock);
-
- diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, script->add_str("PC_LAST_DUEL_TIME") );
-
- return !(diff >= 0 && diff < battle_config.duel_time_interval);
+static int64 duel_difftime(struct map_session_data *sd)
+{
+ return (pc_readglobalreg(sd, script->add_variable("PC_LAST_DUEL_TIME")) + battle_config.duel_time_interval - (int)time(NULL));
}
-static int duel_showinfo_sub(struct map_session_data* sd, va_list va)
+static int duel_showinfo_sub(struct map_session_data *sd, va_list va)
{
struct map_session_data *ssd = va_arg(va, struct map_session_data*);
int *p = va_arg(va, int*);
@@ -73,11 +60,12 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va)
if (sd->duel_group != ssd->duel_group) return 0;
sprintf(output, " %d. %s", ++(*p), sd->status.name);
- clif_disp_onlyself(ssd, output, strlen(output));
+ clif_disp_onlyself(ssd, output);
return 1;
}
-void duel_showinfo(const unsigned int did, struct map_session_data* sd) {
+static void duel_showinfo(const unsigned int did, struct map_session_data *sd)
+{
int p=0;
char output[256];
@@ -93,11 +81,12 @@ void duel_showinfo(const unsigned int did, struct map_session_data* sd) {
duel->list[did].members_count,
duel->list[did].members_count + duel->list[did].invites_count);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
map->foreachpc(duel_showinfo_sub, sd, &p);
}
-int duel_create(struct map_session_data* sd, const unsigned int maxpl) {
+static int duel_create(struct map_session_data *sd, const unsigned int maxpl)
+{
int i=1;
char output[256];
@@ -113,31 +102,32 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl) {
duel->list[i].max_players_limit = maxpl;
safestrncpy(output, msg_sd(sd,372), sizeof(output)); // " -- Duel has been created (@invite/@leave) --"
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,SELF);
return i;
}
-void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) {
+static void duel_invite(const unsigned int did, struct map_session_data *sd, struct map_session_data *target_sd)
+{
char output[256];
nullpo_retv(sd);
nullpo_retv(target_sd);
// " -- Player %s invites %s to duel --"
sprintf(output, msg_sd(sd,373), sd->status.name, target_sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
target_sd->duel_invite = did;
duel->list[did].invites_count++;
// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
sprintf(output, msg_sd(target_sd,374), sd->status.name);
- clif->broadcast(&target_sd->bl, output, strlen(output)+1, BC_BLUE, SELF);
+ clif->broadcast(&target_sd->bl, output, (int)strlen(output)+1, BC_BLUE, SELF);
}
-static int duel_leave_sub(struct map_session_data* sd, va_list va)
+static int duel_leave_sub(struct map_session_data *sd, va_list va)
{
int did = va_arg(va, int);
nullpo_ret(sd);
@@ -146,13 +136,14 @@ static int duel_leave_sub(struct map_session_data* sd, va_list va)
return 0;
}
-void duel_leave(const unsigned int did, struct map_session_data* sd) {
+static void duel_leave(const unsigned int did, struct map_session_data *sd)
+{
char output[256];
nullpo_retv(sd);
// " <- Player %s has left duel --"
sprintf(output, msg_sd(sd,375), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
duel->list[did].members_count--;
if(duel->list[did].members_count == 0) {
@@ -166,7 +157,8 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) {
clif->maptypeproperty2(&sd->bl,SELF);
}
-void duel_accept(const unsigned int did, struct map_session_data* sd) {
+static void duel_accept(const unsigned int did, struct map_session_data *sd)
+{
char output[256];
nullpo_retv(sd);
@@ -177,28 +169,31 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) {
// " -> Player %s has accepted duel --"
sprintf(output, msg_sd(sd,376), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,SELF);
}
-void duel_reject(const unsigned int did, struct map_session_data* sd) {
+static void duel_reject(const unsigned int did, struct map_session_data *sd)
+{
char output[256];
nullpo_retv(sd);
// " -- Player %s has rejected duel --"
sprintf(output, msg_sd(sd,377), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
duel->list[did].invites_count--;
sd->duel_invite = 0;
}
-void do_final_duel(void) {
+static void do_final_duel(void)
+{
}
-void do_init_duel(bool minimal) {
+static void do_init_duel(bool minimal)
+{
if (minimal)
return;
@@ -206,11 +201,12 @@ void do_init_duel(bool minimal) {
}
/*=====================================
-* Default Functions : duel.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void duel_defaults(void) {
+ * Default Functions : duel.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void duel_defaults(void)
+{
duel = &duel_s;
/* vars */
duel->count = 0;
@@ -222,7 +218,7 @@ void duel_defaults(void) {
duel->reject = duel_reject;
duel->leave = duel_leave;
duel->showinfo = duel_showinfo;
- duel->checktime = duel_checktime;
+ duel->difftime = duel_difftime;
duel->init = do_init_duel;
duel->final = do_final_duel;
diff --git a/src/map/duel.h b/src/map/duel.h
index 60b5b09ab..1620ca891 100644
--- a/src/map/duel.h
+++ b/src/map/duel.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ struct duel_interface {
void (*reject) (const unsigned int did, struct map_session_data* sd);
void (*leave) (const unsigned int did, struct map_session_data* sd);
void (*showinfo) (const unsigned int did, struct map_session_data* sd);
- int (*checktime) (struct map_session_data* sd);
+ int64 (*difftime) (struct map_session_data* sd);
void (*init) (bool minimal);
void (*final) (void);
diff --git a/src/map/elemental.c b/src/map/elemental.c
index b6297c2cf..f176bb9e2 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,20 +57,23 @@
#include <stdlib.h>
#include <string.h>
-struct elemental_interface elemental_s;
+static struct elemental_interface elemental_s;
struct elemental_interface *elemental;
-int elemental_search_index(int class_) {
+static int elemental_search_index(int class_)
+{
int i;
ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental->db[i].class_ == class_);
return (i == MAX_ELEMENTAL_CLASS)?-1:i;
}
-bool elemental_class(int class_) {
+static bool elemental_class(int class_)
+{
return (bool)(elemental->search_index(class_) > -1);
}
-struct view_data * elemental_get_viewdata(int class_) {
+static struct view_data *elemental_get_viewdata(int class_)
+{
int i = elemental->search_index(class_);
if( i < 0 )
return 0;
@@ -78,7 +81,8 @@ struct view_data * elemental_get_viewdata(int class_) {
return &elemental->db[i].vd;
}
-int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) {
+static int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime)
+{
struct s_elemental ele;
struct s_elemental_db *db;
int i, summon_level, skill_level;
@@ -169,7 +173,8 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet
return 1;
}
-int elemental_get_lifetime(struct elemental_data *ed) {
+static int elemental_get_lifetime(struct elemental_data *ed)
+{
const struct TimerData * td;
if( ed == NULL || ed->summon_timer == INVALID_TIMER )
return 0;
@@ -178,7 +183,8 @@ int elemental_get_lifetime(struct elemental_data *ed) {
return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0;
}
-int elemental_save(struct elemental_data *ed) {
+static int elemental_save(struct elemental_data *ed)
+{
nullpo_retr(1, ed);
ed->elemental.mode = ed->battle_status.mode;
ed->elemental.hp = ed->battle_status.hp;
@@ -197,7 +203,8 @@ int elemental_save(struct elemental_data *ed) {
return 1;
}
-int elemental_summon_end_timer(int tid, int64 tick, int id, intptr_t data) {
+static int elemental_summon_end_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
struct elemental_data *ed;
@@ -217,14 +224,16 @@ int elemental_summon_end_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void elemental_summon_stop(struct elemental_data *ed) {
+static void elemental_summon_stop(struct elemental_data *ed)
+{
nullpo_retv(ed);
if( ed->summon_timer != INVALID_TIMER )
timer->delete(ed->summon_timer, elemental->summon_end_timer);
ed->summon_timer = INVALID_TIMER;
}
-int elemental_delete(struct elemental_data *ed, int reply) {
+static int elemental_delete(struct elemental_data *ed, int reply)
+{
struct map_session_data *sd;
nullpo_ret(ed);
@@ -246,7 +255,8 @@ int elemental_delete(struct elemental_data *ed, int reply) {
return unit->remove_map(&ed->bl, 0, ALC_MARK);
}
-void elemental_summon_init(struct elemental_data *ed) {
+static void elemental_summon_init(struct elemental_data *ed)
+{
nullpo_retv(ed);
if (ed->summon_timer == INVALID_TIMER)
ed->summon_timer = timer->add(timer->gettick() + ed->elemental.life_time, elemental->summon_end_timer, ed->master->bl.id, 0);
@@ -254,7 +264,7 @@ void elemental_summon_init(struct elemental_data *ed) {
ed->regen.state.block = 0;
}
-int elemental_data_received(const struct s_elemental *ele, bool flag)
+static int elemental_data_received(const struct s_elemental *ele, bool flag)
{
struct map_session_data *sd;
struct elemental_data *ed;
@@ -318,7 +328,8 @@ int elemental_data_received(const struct s_elemental *ele, bool flag)
return 1;
}
-int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) {
+static int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id)
+{
struct block_list *bl;
sc_type type = status->skill2sc(skill_id);
@@ -365,7 +376,8 @@ int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) {
return 1;
}
-int elemental_clean_effect(struct elemental_data *ed) {
+static int elemental_clean_effect(struct elemental_data *ed)
+{
struct map_session_data *sd;
nullpo_ret(ed);
@@ -425,7 +437,8 @@ int elemental_clean_effect(struct elemental_data *ed) {
return 1;
}
-int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tick) {
+static int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tick)
+{
struct skill_condition req;
uint16 skill_id, skill_lv;
int i;
@@ -506,7 +519,8 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tic
* Action that elemental perform after changing mode.
* Activates one of the skills of the new mode.
*-------------------------------------------------------------*/
-int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
+static int elemental_change_mode_ack(struct elemental_data *ed, int mode)
+{
struct block_list *bl = &ed->master->bl;
uint16 skill_id, skill_lv;
int i;
@@ -552,7 +566,7 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
* @param mode The new mode.
* @retval 1 in case of success.
*/
-int elemental_change_mode(struct elemental_data *ed, uint32 mode)
+static int elemental_change_mode(struct elemental_data *ed, uint32 mode)
{
int skillmode = EL_SKILLMODE_PASIVE;
nullpo_ret(ed);
@@ -580,7 +594,8 @@ int elemental_change_mode(struct elemental_data *ed, uint32 mode)
return 1;
}
-void elemental_heal(struct elemental_data *ed, int hp, int sp) {
+static void elemental_heal(struct elemental_data *ed, int hp, int sp)
+{
nullpo_retv(ed);
if( hp )
clif->elemental_updatestatus(ed->master, SP_HP);
@@ -588,12 +603,14 @@ void elemental_heal(struct elemental_data *ed, int hp, int sp) {
clif->elemental_updatestatus(ed->master, SP_SP);
}
-int elemental_dead(struct elemental_data *ed) {
+static int elemental_dead(struct elemental_data *ed)
+{
elemental->delete(ed, 1);
return 0;
}
-int elemental_unlocktarget(struct elemental_data *ed) {
+static int elemental_unlocktarget(struct elemental_data *ed)
+{
nullpo_ret(ed);
ed->target_id = 0;
@@ -602,7 +619,8 @@ int elemental_unlocktarget(struct elemental_data *ed) {
return 0;
}
-int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
+static int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed)
+{
int idx = skill->get_index(skill_id);
nullpo_retr(1,ed);
@@ -612,7 +630,8 @@ int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
return skill->not_ok(skill_id, ed->master);
}
-struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){
+static struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv)
+{
struct skill_condition req;
int idx = skill->get_index(skill_id);
@@ -630,7 +649,8 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16
return req;
}
-int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) {
+static int elemental_set_target(struct map_session_data *sd, struct block_list *bl)
+{
struct elemental_data *ed;
nullpo_ret(sd);
@@ -650,7 +670,8 @@ int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) {
return 1;
}
-int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) {
+static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap)
+{
struct elemental_data *ed;
struct block_list **target;
int dist;
@@ -689,7 +710,8 @@ int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) {
return 0;
}
-int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, int64 tick) {
+static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, int64 tick)
+{
struct block_list *target = NULL;
int master_dist, view_range;
uint32 mode;
@@ -704,7 +726,7 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s
if( DIFF_TICK(tick,ed->last_spdrain_time) >= 10000 ){// Drain SP every 10 seconds
int sp = 5;
- switch (ed->vd->class_) {
+ switch (ed->vd->class) {
case ELEID_EL_AGNI_M:
case ELEID_EL_AQUA_M:
case ELEID_EL_VENTUS_M:
@@ -766,8 +788,8 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s
return 0; //Already walking to him
if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 )
return 0; //Can't move yet.
- if( map->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1)
- && unit->walktoxy(&ed->bl, x, y, 0) )
+ if (map->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) != 0
+ && unit->walk_toxy(&ed->bl, x, y, 0) == 0)
return 0;
}
@@ -805,7 +827,8 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s
return 0;
}
-int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
+static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap)
+{
int64 tick = va_arg(ap,int64);
nullpo_ret(sd);
if(sd->status.ele_id && sd->ed)
@@ -814,12 +837,14 @@ int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
return 0;
}
-int elemental_ai_timer(int tid, int64 tick, int id, intptr_t data) {
+static int elemental_ai_timer(int tid, int64 tick, int id, intptr_t data)
+{
map->foreachpc(elemental->ai_sub_foreachclient,tick);
return 0;
}
-int read_elementaldb(void) {
+static int read_elementaldb(void)
+{
FILE *fp;
char line[1024], *p;
char *str[26];
@@ -864,7 +889,7 @@ int read_elementaldb(void) {
db->lv = atoi(str[3]);
estatus = &db->status;
- db->vd.class_ = db->class_;
+ db->vd.class = db->class_;
estatus->max_hp = atoi(str[4]);
estatus->max_sp = atoi(str[5]);
@@ -885,7 +910,7 @@ int read_elementaldb(void) {
estatus->race = atoi(str[20]);
ele = atoi(str[21]);
- estatus->def_ele = ele%10;
+ estatus->def_ele = ele % ELE_MAX;
estatus->ele_lv = ele/20;
if( estatus->def_ele >= ELE_MAX ) {
ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, estatus->def_ele, ELE_MAX - 1);
@@ -911,7 +936,8 @@ int read_elementaldb(void) {
return 0;
}
-int read_elemental_skilldb(void) {
+static int read_elemental_skilldb(void)
+{
FILE *fp;
char line[1024], *p;
char *str[4];
@@ -983,16 +1009,19 @@ int read_elemental_skilldb(void) {
return 0;
}
-void reload_elementaldb(void) {
+static void reload_elementaldb(void)
+{
elemental->read_db();
elemental->reload_skilldb();
}
-void reload_elemental_skilldb(void) {
+static void reload_elemental_skilldb(void)
+{
elemental->read_skilldb();
}
-int do_init_elemental(bool minimal) {
+static int do_init_elemental(bool minimal)
+{
if (minimal)
return 0;
@@ -1005,16 +1034,18 @@ int do_init_elemental(bool minimal) {
return 0;
}
-void do_final_elemental(void) {
+static void do_final_elemental(void)
+{
return;
}
/*=====================================
-* Default Functions : elemental.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void elemental_defaults(void) {
+ * Default Functions : elemental.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void elemental_defaults(void)
+{
elemental = &elemental_s;
/* */
diff --git a/src/map/elemental.h b/src/map/elemental.h
index cdd83fd21..71c991268 100644
--- a/src/map/elemental.h
+++ b/src/map/elemental.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/guild.c b/src/map/guild.c
index 39d580bb7..f344878e1 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@
#include "map/storage.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/ers.h"
#include "common/memmgr.h"
#include "common/mapindex.h"
@@ -51,13 +52,13 @@
#include <stdlib.h>
#include <string.h>
-struct guild_interface guild_s;
+static struct guild_interface guild_s;
struct guild_interface *guild;
/*==========================================
* Retrieves and validates the sd pointer for this guild member [Skotlex]
*------------------------------------------*/
-struct map_session_data *guild_sd_check(int guild_id, int account_id, int char_id)
+static struct map_session_data *guild_sd_check(int guild_id, int account_id, int char_id)
{
struct map_session_data *sd = map->id2sd(account_id);
@@ -74,14 +75,16 @@ struct map_session_data *guild_sd_check(int guild_id, int account_id, int char_i
}
// Modified [Komurka]
-int guild_skill_get_max (int id) {
+static int guild_skill_get_max(int id)
+{
if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL)
return 0;
return guild->skill_tree[id-GD_SKILLBASE].max;
}
// Retrieve skill_lv learned by guild
-int guild_checkskill(struct guild *g, int id) {
+static int guild_checkskill(struct guild *g, int id)
+{
int idx = id - GD_SKILLBASE;
nullpo_ret(g);
if (idx < 0 || idx >= MAX_GUILDSKILL)
@@ -92,7 +95,7 @@ int guild_checkskill(struct guild *g, int id) {
/*==========================================
* guild_skill_tree.txt reading - from jA [Komurka]
*------------------------------------------*/
-bool guild_read_guildskill_tree_db(char* split[], int columns, int current)
+static bool guild_read_guildskill_tree_db(char *split[], int columns, int current)
{// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
int k, id, skill_id;
@@ -125,7 +128,7 @@ bool guild_read_guildskill_tree_db(char* split[], int columns, int current)
/*==========================================
* Guild skill check - from jA [Komurka]
*------------------------------------------*/
-int guild_check_skill_require(struct guild *g,int id)
+static int guild_check_skill_require(struct guild *g, int id)
{
int i;
int idx = id-GD_SKILLBASE;
@@ -145,37 +148,137 @@ int guild_check_skill_require(struct guild *g,int id)
return 1;
}
-bool guild_read_castledb(char* str[], int columns, int current)
-{// <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>]
- struct guild_castle *gc;
- int index;
+static bool guild_read_castledb_libconfig(void)
+{
+ struct config_t castle_conf;
+ struct config_setting_t *castle_db = NULL, *it = NULL;
+ char config_filename[256];
+ libconfig->format_db_path("castle_db.conf", config_filename, sizeof(config_filename));
+ int i = 0;
- nullpo_retr(false, str);
- index = mapindex->name2id(str[1]);
- if (map->mapindex2mapid(index) < 0) // Map not found or on another map-server
+ if (libconfig->load_file(&castle_conf, config_filename) == 0)
return false;
+ if ((castle_db = libconfig->setting_get_member(castle_conf.root, "castle_db")) == NULL) {
+ libconfig->destroy(&castle_conf);
+ ShowError("guild_read_castledb_libconfig: can't read %s\n", config_filename);
+ return false;
+ }
+
+ while ((it = libconfig->setting_get_elem(castle_db, i++)) != NULL) {
+ guild->read_castledb_libconfig_sub(it, i - 1, config_filename);
+ }
+
+ libconfig->destroy(&castle_conf);
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(guild->castle_db), config_filename);
+ return true;
+}
+
+static bool guild_read_castledb_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ nullpo_ret(it);
+ nullpo_ret(source);
+
+ struct guild_castle *gc = NULL;
+ const char *name = NULL;
+ int i32 = 0;
CREATE(gc, struct guild_castle, 1);
- gc->castle_id = atoi(str[0]);
+
+ if (libconfig->setting_lookup_int(it, "CastleID", &i32) == CONFIG_FALSE) {
+ aFree(gc);
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid or missing CastleID (%d) in \"%s\", entry #%d, skipping.\n", i32, source, idx);
+ return false;
+ }
+ gc->castle_id = i32;
+
+ if (libconfig->setting_lookup_string(it, "MapName", &name) == CONFIG_FALSE) {
+ aFree(gc);
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid or missing MapName in \"%s\", entry #%d, skipping.\n", source, idx);
+ return false;
+ }
+ int index = mapindex->name2id(name);
+ if (map->mapindex2mapid(index) < 0) {
+ aFree(gc);
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid MapName (%s) in \"%s\", entry #%d, skipping.\n", name, source, idx);
+ return false;
+ }
gc->mapindex = index;
- safestrncpy(gc->castle_name, str[2], sizeof(gc->castle_name));
- safestrncpy(gc->castle_event, str[3], sizeof(gc->castle_event));
- idb_put(guild->castle_db,gc->castle_id,gc);
+ if (libconfig->setting_lookup_string(it, "CastleName", &name) == CONFIG_FALSE) {
+ aFree(gc);
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid CastleName in \"%s\", entry #%d, skipping.\n", source, idx);
+ return false;
+ }
+ safestrncpy(gc->castle_name, name, sizeof(gc->castle_name));
- //intif->guild_castle_info(gc->castle_id);
+ if (libconfig->setting_lookup_string(it, "OnGuildBreakEventName", &name) == CONFIG_FALSE){
+ aFree(gc);
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid OnGuildBreakEventName in \"%s\", entry #%d, skipping.\n", source, idx);
+ return false;
+ }
+ safestrncpy(gc->castle_event, name, sizeof(gc->castle_event));
+ if (itemdb->lookup_const(it, "SiegeType", &i32) && (i32 >= SIEGE_TYPE_MAX || i32 < 0)) {
+ ShowWarning("guild_read_castledb_libconfig_sub: Invalid SiegeType in \"%s\", entry #%d, defaulting to SIEGE_TYPE_FE.\n", source, idx);
+ gc->siege_type = SIEGE_TYPE_FE;
+ } else {
+ gc->siege_type = i32;
+ }
+
+ libconfig->setting_lookup_bool_real(it, "EnableClientWarp", &gc->enable_client_warp);
+ if (gc->enable_client_warp == true) {
+ struct config_setting_t *wd = libconfig->setting_get_member(it, "ClientWarp");
+ guild->read_castledb_libconfig_sub_warp(wd, source, gc);
+ }
+ idb_put(guild->castle_db, gc->castle_id, gc);
+ return true;
+}
+
+static bool guild_read_castledb_libconfig_sub_warp(struct config_setting_t *wd, const char *source, struct guild_castle *gc)
+{
+ nullpo_retr(false, wd);
+ nullpo_retr(false, gc);
+ nullpo_retr(false, source);
+
+ int64 i64 = 0;
+ struct config_setting_t *it = libconfig->setting_get_member(wd, "Position");
+ if (config_setting_is_list(it)) {
+ int m = map->mapindex2mapid(gc->mapindex);
+
+ gc->client_warp.x = libconfig->setting_get_int_elem(it, 0);
+ gc->client_warp.y = libconfig->setting_get_int_elem(it, 1);
+ if (gc->client_warp.x < 0 || gc->client_warp.x >= map->list[m].xs || gc->client_warp.y < 0 || gc->client_warp.y >= map->list[m].ys) {
+ ShowWarning("guild_read_castledb_libconfig_sub_warp: Invalid Position in \"%s\", for castle (%d).\n", source, gc->castle_id);
+ return false;
+ }
+ } else {
+ ShowWarning("guild_read_castledb_libconfig_sub_warp: Invalid format for Position in \"%s\", for castle (%d).\n", source, gc->castle_id);
+ return false;
+ }
+
+ if (libconfig->setting_lookup_int64(wd, "ZenyCost", &i64)) {
+ if (i64 > MAX_ZENY) {
+ ShowWarning("guild_read_castledb_libconfig_sub_warp: ZenyCost is too big in \"%s\", for castle (%d), capping to MAX_ZENY.\n", source, gc->castle_id);
+ }
+ gc->client_warp.zeny = cap_value((int)i64, 0, MAX_ZENY);
+ }
+ if (libconfig->setting_lookup_int64(wd, "ZenyCostSiegeTime", &i64)) {
+ if (i64 > MAX_ZENY) {
+ ShowWarning("guild_read_castledb_libconfig_sub_warp: ZenyCostSiegeTime is too big in \"%s\", for castle (%d), capping to MAX_ZENY.\n", source, gc->castle_id);
+ }
+ gc->client_warp.zeny_siege = cap_value((int)i64, 0, MAX_ZENY);
+ }
return true;
}
/// lookup: guild id -> guild*
-struct guild* guild_search(int guild_id)
+static struct guild *guild_search(int guild_id)
{
return (struct guild*)idb_get(guild->db,guild_id);
}
/// lookup: guild name -> guild*
-struct guild* guild_searchname(char* str)
+static struct guild *guild_searchname(const char *str)
{
struct guild* g;
struct DBIterator *iter = db_iterator(guild->db);
@@ -192,13 +295,13 @@ struct guild* guild_searchname(char* str)
}
/// lookup: castle id -> castle*
-struct guild_castle* guild_castle_search(int gcid)
+static struct guild_castle *guild_castle_search(int gcid)
{
return (struct guild_castle*)idb_get(guild->castle_db,gcid);
}
/// lookup: map index -> castle*
-struct guild_castle* guild_mapindex2gc(short map_index)
+static struct guild_castle *guild_mapindex2gc(short map_index)
{
struct guild_castle* gc;
struct DBIterator *iter = db_iterator(guild->castle_db);
@@ -214,12 +317,12 @@ struct guild_castle* guild_mapindex2gc(short map_index)
}
/// lookup: map name -> castle*
-struct guild_castle* guild_mapname2gc(const char* mapname)
+static struct guild_castle *guild_mapname2gc(const char *mapname)
{
return guild->mapindex2gc(mapindex->name2id(mapname));
}
-struct map_session_data* guild_getavailablesd(struct guild* g)
+static struct map_session_data *guild_getavailablesd(struct guild *g)
{
int i;
@@ -230,7 +333,7 @@ struct map_session_data* guild_getavailablesd(struct guild* g)
}
/// lookup: player AID/CID -> member index
-int guild_getindex(const struct guild *g, int account_id, int char_id)
+static int guild_getindex(const struct guild *g, int account_id, int char_id)
{
int i;
@@ -245,7 +348,7 @@ int guild_getindex(const struct guild *g, int account_id, int char_id)
}
/// lookup: player sd -> member position
-int guild_getposition(struct guild* g, struct map_session_data* sd)
+static int guild_getposition(struct guild *g, struct map_session_data *sd)
{
int i;
@@ -257,7 +360,7 @@ int guild_getposition(struct guild* g, struct map_session_data* sd)
}
//Creation of member information
-void guild_makemember(struct guild_member *m,struct map_session_data *sd)
+static void guild_makemember(struct guild_member *m, struct map_session_data *sd)
{
nullpo_retv(sd);
nullpo_retv(m);
@@ -268,13 +371,14 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
m->hair = sd->status.hair;
m->hair_color = sd->status.hair_color;
m->gender = sd->status.sex;
- m->class_ = sd->status.class_;
+ m->class = sd->status.class;
m->lv = sd->status.base_level;
//m->exp = 0;
//m->exp_payper = 0;
m->online = 1;
m->position = MAX_GUILDPOSITION-1;
memcpy(m->name,sd->status.name,NAME_LENGTH);
+ m->last_login = (uint32)time(NULL); // When player create or join a guild the date is updated
return;
}
@@ -282,7 +386,7 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
* Server cache to be flushed to inter the Guild EXP
* @see DBApply
*/
-int guild_payexp_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+static int guild_payexp_timer_sub(union DBKey key, struct DBData *data, va_list ap)
{
int i;
struct guild_expcache *c;
@@ -310,7 +414,8 @@ int guild_payexp_timer_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data) {
+static int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data)
+{
guild->expcache_db->clear(guild->expcache_db,guild->payexp_timer_sub);
return 0;
}
@@ -319,7 +424,7 @@ int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data) {
* Taken from party_send_xy_timer_sub. [Skotlex]
* @see DBApply
*/
-int guild_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+static int guild_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild *g = DB->data2ptr(data);
int i;
@@ -344,12 +449,13 @@ int guild_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
}
//Code from party_send_xy_timer [Skotlex]
-int guild_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
+static int guild_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
+{
guild->db->foreach(guild->db,guild->send_xy_timer_sub,tick);
return 0;
}
-int guild_send_dot_remove(struct map_session_data *sd)
+static int guild_send_dot_remove(struct map_session_data *sd)
{
nullpo_ret(sd);
if (sd->status.guild_id)
@@ -358,13 +464,18 @@ int guild_send_dot_remove(struct map_session_data *sd)
}
//------------------------------------------------------------------------
-int guild_create(struct map_session_data *sd, const char *name)
+static int guild_create(struct map_session_data *sd, const char *name)
{
char tname[NAME_LENGTH];
struct guild_member m;
nullpo_ret(sd);
nullpo_ret(name);
+ if (sd->clan != NULL) {
+ clif->messagecolor_self(sd->fd, COLOR_RED, "You cannot create a guild because you are in a clan.");
+ return 0;
+ }
+
safestrncpy(tname, name, NAME_LENGTH);
trim(tname);
@@ -387,7 +498,8 @@ int guild_create(struct map_session_data *sd, const char *name)
}
//Whether or not to create guild
-int guild_created(int account_id,int guild_id) {
+static int guild_created(int account_id, int guild_id)
+{
struct map_session_data *sd=map->id2sd(account_id);
if(sd==NULL)
@@ -399,34 +511,35 @@ int guild_created(int account_id,int guild_id) {
//struct guild *g;
sd->status.guild_id=guild_id;
clif->guild_created(sd,0); // Success
- if(battle_config.guild_emperium_check)
- pc->delitem(sd, pc->search_inventory(sd, ITEMID_EMPERIUM), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption
+ if (battle_config.guild_emperium_check) {
+ int n = pc->search_inventory(sd, ITEMID_EMPERIUM);
+ if (n != INDEX_NOT_FOUND)
+ pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption
+ }
return 0;
}
//Information request
-int guild_request_info(int guild_id)
+static int guild_request_info(int guild_id)
{
return intif->guild_request_info(guild_id);
}
//Information request with event
-int guild_npc_request_info(int guild_id,const char *event)
+static int guild_npc_request_info(int guild_id, const char *event)
{
- if( guild->search(guild_id) )
- {
- if( event && *event )
+ if (guild->search(guild_id) != NULL) {
+ if (event != NULL && *event != '\0')
npc->event_do(event);
return 0;
}
- if( event && *event )
- {
+ if (event != NULL && *event != '\0') {
struct eventlist *ev;
struct DBData prev;
- ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
- memcpy(ev->name,event,strlen(event));
+ CREATE(ev, struct eventlist, 1);
+ safestrncpy(ev->name, event, sizeof(ev->name));
//The one in the db (if present) becomes the next event from this.
if (guild->infoevent_db->put(guild->infoevent_db, DB->i2key(guild_id), DB->ptr2data(ev), &prev))
ev->next = DB->data2ptr(&prev);
@@ -436,7 +549,7 @@ int guild_npc_request_info(int guild_id,const char *event)
}
//Confirmation of the character belongs to guild
-int guild_check_member(const struct guild *g)
+static int guild_check_member(const struct guild *g)
{
int i;
struct map_session_data *sd;
@@ -453,6 +566,7 @@ int guild_check_member(const struct guild *g)
if (i == INDEX_NOT_FOUND) {
sd->status.guild_id=0;
sd->guild_emblem_id=0;
+ sd->guild = NULL;
ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name);
}
}
@@ -462,15 +576,18 @@ int guild_check_member(const struct guild *g)
}
//Delete association with guild_id for all characters
-int guild_recv_noinfo(int guild_id)
+static int guild_recv_noinfo(int guild_id)
{
struct map_session_data *sd;
struct s_mapiterator* iter;
iter = mapit_getallusers();
for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if( sd->status.guild_id == guild_id )
+ if (sd->status.guild_id == guild_id) {
sd->status.guild_id = 0; // erase guild
+ sd->guild_emblem_id = 0;
+ sd->guild = NULL;
+ }
}
mapit->free(iter);
@@ -478,7 +595,7 @@ int guild_recv_noinfo(int guild_id)
}
//Get and display information for all member
-int guild_recv_info(const struct guild *sg)
+static int guild_recv_info(const struct guild *sg)
{
struct guild *g,before;
int i,bm,m;
@@ -542,10 +659,10 @@ int guild_recv_info(const struct guild *sg)
before=*sg;
//Perform the check on the user because the first load
guild->check_member(sg);
- if ((sd = map->nick2sd(sg->master)) != NULL) {
+ if ((sd = map->nick2sd(sg->master, false)) != NULL) {
//If the guild master is online the first time the guild_info is received,
//that means he was the first to join, so apply guild skill blocking here.
- if( battle_config.guild_skill_relog_delay )
+ if( battle_config.guild_skill_relog_delay == 1)
guild->block_skill(sd, 300000);
//Also set the guild master flag.
@@ -627,7 +744,8 @@ int guild_recv_info(const struct guild *sg)
/*=============================================
* Player sd send a guild invatation to player tsd to join his guild
*--------------------------------------------*/
-int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
+static int guild_invite(struct map_session_data *sd, struct map_session_data *tsd)
+{
struct guild *g;
int i;
@@ -681,7 +799,8 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
/// Guild invitation reply.
/// flag: 0:rejected, 1:accepted
-int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) {
+static int guild_reply_invite(struct map_session_data *sd, int guild_id, int flag)
+{
struct map_session_data* tsd;
nullpo_ret(sd);
@@ -707,7 +826,6 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) {
}
else
{// accepted
- struct guild_member m;
struct guild* g;
int i;
@@ -727,8 +845,8 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) {
return 0;
}
- guild->makemember(&m,sd);
- intif->guild_addmember(guild_id, &m);
+ guild->makemember(&g->member[i], sd);
+ intif->guild_addmember(guild_id, &g->member[i]);
//TODO: send a minimap update to this player
}
@@ -739,7 +857,7 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) {
//- If guild is not in memory, it is requested
//- Otherwise sd pointer is set up.
//- Player must be authed and must belong to a guild before invoking this method
-void guild_member_joined(struct map_session_data *sd)
+static void guild_member_joined(struct map_session_data *sd)
{
struct guild* g;
int i;
@@ -753,12 +871,14 @@ void guild_member_joined(struct map_session_data *sd)
// set the Guild Master flag
sd->state.gmaster_flag = 1;
// prevent Guild Skills from being used directly after relog
- if( battle_config.guild_skill_relog_delay )
+ if( battle_config.guild_skill_relog_delay == 1 )
guild->block_skill(sd, 300000);
}
i = guild->getindex(g, sd->status.account_id, sd->status.char_id);
if (i == INDEX_NOT_FOUND) {
sd->status.guild_id = 0;
+ sd->guild_emblem_id = 0;
+ sd->guild = NULL;
} else {
g->member[i].sd = sd;
sd->guild = g;
@@ -773,7 +893,8 @@ void guild_member_joined(struct map_session_data *sd)
/*==========================================
* Add a player to a given guild_id
*----------------------------------------*/
-int guild_member_added(int guild_id,int account_id,int char_id,int flag) {
+static int guild_member_added(int guild_id, int account_id, int char_id, int flag)
+{
struct map_session_data *sd = map->id2sd(account_id),*sd2;
struct guild *g;
@@ -814,6 +935,11 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) {
//Next line commented because it do nothing, look at guild_recv_info [LuzZza]
//clif->charnameupdate(sd); //Update display name [Skotlex]
+ // Makes the character join their respective guild's channel for #ally chat
+ if (channel->config->ally && channel->config->ally_autojoin) {
+ channel->join(g->channel, sd, "", true);
+ }
+
return 0;
}
@@ -821,7 +947,7 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) {
* Player request leaving a given guild_id
* mes - non null terminated string
*----------------------------------------*/
-int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes)
+static int guild_leave(struct map_session_data *sd, int guild_id, int account_id, int char_id, const char *mes)
{
struct guild *g;
@@ -850,7 +976,8 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c
* Request remove a player to a given guild_id
* mes - non null terminated string
*----------------------------------------*/
-int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes) {
+static int guild_expulsion(struct map_session_data *sd, int guild_id, int account_id, int char_id, const char *mes)
+{
struct map_session_data *tsd;
struct guild *g;
int i,ps;
@@ -885,7 +1012,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i
return 0;
}
-int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, const char* name, const char* mes)
+static int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, const char *name, const char *mes)
{
int i;
struct guild* g = guild->search(guild_id);
@@ -909,9 +1036,9 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
#endif
if(!flag)
- clif->guild_leave(online_member_sd, name, mes);
+ clif->guild_leave(online_member_sd, name, char_id, mes);
else
- clif->guild_expulsion(online_member_sd, name, mes, account_id);
+ clif->guild_expulsion(online_member_sd, name, char_id, mes, account_id);
// remove member from guild
memset(&g->member[i],0,sizeof(struct guild_member));
@@ -941,7 +1068,8 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
return 0;
}
-void guild_retrieveitembound(int char_id,int aid,int guild_id) {
+static void guild_retrieveitembound(int char_id, int aid, int guild_id)
+{
#ifdef GP_BOUND_ITEMS
struct map_session_data *sd = map->charid2sd(char_id);
if (sd != NULL) { //Character is online
@@ -963,8 +1091,9 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id) {
#endif
}
-int guild_send_memberinfoshort(struct map_session_data *sd,int online)
-{ // cleaned up [LuzZza]
+// cleaned up [LuzZza]
+static int guild_send_memberinfoshort(struct map_session_data *sd, int online)
+{
struct guild *g;
nullpo_ret(sd);
@@ -976,7 +1105,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
intif->guild_memberinfoshort(g->guild_id,
- sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_);
+ sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class);
if(!online){
int i = guild->getindex(g,sd->status.account_id,sd->status.char_id);
@@ -995,8 +1124,9 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
}
-int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
-{ // cleaned up [LuzZza]
+// cleaned up [LuzZza]
+static int guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class, uint32 last_login)
+{
int i, alv, c, idx = INDEX_NOT_FOUND, om = 0, oldonline = -1;
struct guild *g = guild->search(guild_id);
@@ -1010,7 +1140,8 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
oldonline=m->online;
m->online=online;
m->lv=lv;
- m->class_=class_;
+ m->class = class;
+ m->last_login = last_login;
idx=i;
}
alv+=m->lv;
@@ -1060,14 +1191,16 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
/*====================================================
* Send a message to whole guild
*---------------------------------------------------*/
-int guild_send_message(struct map_session_data *sd,const char *mes,int len)
+static int guild_send_message(struct map_session_data *sd, const char *mes)
{
nullpo_ret(sd);
- if(sd->status.guild_id==0)
+ if (sd->status.guild_id == 0 || sd->guild == NULL)
return 0;
- intif->guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
- guild->recv_message(sd->status.guild_id,sd->status.account_id,mes,len);
+
+ int len = (int)strlen(mes);
+
+ clif->guild_message(sd->guild, sd->status.account_id, mes, len);
// Chat logging type 'G' / Guild Chat
logs->chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
@@ -1076,21 +1209,9 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len)
}
/*====================================================
- * Guild receive a message, will be displayed to whole member
- *---------------------------------------------------*/
-int guild_recv_message(int guild_id,int account_id,const char *mes,int len)
-{
- struct guild *g;
- if( (g=guild->search(guild_id))==NULL)
- return 0;
- clif->guild_message(g,account_id,mes,len);
- return 0;
-}
-
-/*====================================================
* Member changing position in guild
*---------------------------------------------------*/
-int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx)
+static int guild_change_memberposition(int guild_id, int account_id, int char_id, short idx)
{
return intif->guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx));
}
@@ -1098,7 +1219,7 @@ int guild_change_memberposition(int guild_id,int account_id,int char_id,short id
/*====================================================
* Notification of new position for member
*---------------------------------------------------*/
-int guild_memberposition_changed(struct guild *g,int idx,int pos)
+static int guild_memberposition_changed(struct guild *g, int idx, int pos)
{
nullpo_ret(g);
Assert_ret(idx >= 0 && idx < MAX_GUILD);
@@ -1108,14 +1229,14 @@ int guild_memberposition_changed(struct guild *g,int idx,int pos)
// Update char position in client [LuzZza]
if(g->member[idx].sd != NULL)
- clif->charnameupdate(g->member[idx].sd);
+ clif->guild_position_selected(g->member[idx].sd);
return 0;
}
/*====================================================
* Change guild title or member
*---------------------------------------------------*/
-int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char *name)
+static int guild_change_position(int guild_id, int idx, int mode, int exp_mode, const char *name)
{
struct guild_position p;
nullpo_ret(name);
@@ -1130,7 +1251,7 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char
/*====================================================
* Notification of member has changed his guild title
*---------------------------------------------------*/
-int guild_position_changed(int guild_id, int idx, const struct guild_position *p)
+static int guild_position_changed(int guild_id, int idx, const struct guild_position *p)
{
struct guild *g=guild->search(guild_id);
int i;
@@ -1144,14 +1265,14 @@ int guild_position_changed(int guild_id, int idx, const struct guild_position *p
// Update char name in client [LuzZza]
for(i=0;i<g->max_member;i++)
if(g->member[i].position == idx && g->member[i].sd != NULL)
- clif->charnameupdate(g->member[i].sd);
+ clif->guild_position_selected(g->member[i].sd);
return 0;
}
/*====================================================
* Change guild notice
*---------------------------------------------------*/
-int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2)
+static int guild_change_notice(struct map_session_data *sd, int guild_id, const char *mes1, const char *mes2)
{
nullpo_ret(sd);
@@ -1163,7 +1284,7 @@ int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes
/*====================================================
* Notification of guild has changed his notice
*---------------------------------------------------*/
-int guild_notice_changed(int guild_id,const char *mes1,const char *mes2)
+static int guild_notice_changed(int guild_id, const char *mes1, const char *mes2)
{
int i;
struct guild *g=guild->search(guild_id);
@@ -1186,14 +1307,14 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2)
/*====================================================
* Change guild emblem
*---------------------------------------------------*/
-int guild_change_emblem(struct map_session_data *sd,int len,const char *data)
+static int guild_change_emblem(struct map_session_data *sd, int len, const char *data)
{
struct guild *g;
nullpo_ret(sd);
if (battle_config.require_glory_guild &&
!((g = sd->guild) && guild->checkskill(g, GD_GLORYGUILD)>0)) {
- clif->skill_fail(sd,GD_GLORYGUILD,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, GD_GLORYGUILD, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
@@ -1203,7 +1324,7 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data)
/*====================================================
* Notification of guild emblem changed
*---------------------------------------------------*/
-int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
+static int guild_emblem_changed(int len, int guild_id, int emblem_id, const char *data)
{
int i;
struct map_session_data *sd;
@@ -1263,7 +1384,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
/**
* @see DBCreateData
*/
-struct DBData create_expcache(union DBKey key, va_list args)
+static struct DBData create_expcache(union DBKey key, va_list args)
{
struct guild_expcache *c;
struct map_session_data *sd = va_arg(args, struct map_session_data*);
@@ -1280,7 +1401,8 @@ struct DBData create_expcache(union DBKey key, va_list args)
/*====================================================
* Return taxed experience from player sd to guild
*---------------------------------------------------*/
-unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) {
+static uint64 guild_payexp(struct map_session_data *sd, uint64 exp)
+{
struct guild *g;
struct guild_expcache *c;
int per;
@@ -1313,7 +1435,7 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) {
* Add this experience to guild exp
* [Celest]
*---------------------------------------------------*/
-int guild_getexp(struct map_session_data *sd,int exp)
+static int guild_getexp(struct map_session_data *sd, int exp)
{
struct guild_expcache *c;
nullpo_ret(sd);
@@ -1332,7 +1454,7 @@ int guild_getexp(struct map_session_data *sd,int exp)
/*====================================================
* Ask to increase guildskill skill_id
*---------------------------------------------------*/
-int guild_skillup(struct map_session_data *sd, uint16 skill_id)
+static int guild_skillup(struct map_session_data *sd, uint16 skill_id)
{
struct guild* g;
int idx = skill_id - GD_SKILLBASE;
@@ -1356,7 +1478,8 @@ int guild_skillup(struct map_session_data *sd, uint16 skill_id)
/*====================================================
* Notification of guildskill skill_id increase request
*---------------------------------------------------*/
-int guild_skillupack(int guild_id,uint16 skill_id,int account_id) {
+static int guild_skillupack(int guild_id, uint16 skill_id, int account_id)
+{
struct map_session_data *sd=map->id2sd(account_id);
struct guild *g=guild->search(guild_id);
int i;
@@ -1385,7 +1508,8 @@ int guild_skillupack(int guild_id,uint16 skill_id,int account_id) {
return 0;
}
-void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
+static void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
+{
struct skill_unit_group* group = NULL;
int type = status->skill2sc(skill_id);
nullpo_retv(sd);
@@ -1411,7 +1535,7 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1
* 0 = allied
* 1 = enemy
*---------------------------------------------------*/
-int guild_get_alliance_count(struct guild *g,int flag)
+static int guild_get_alliance_count(struct guild *g, int flag)
{
int i,c;
@@ -1425,7 +1549,7 @@ int guild_get_alliance_count(struct guild *g,int flag)
}
// Blocks all guild skills which have a common delay time.
-void guild_block_skill(struct map_session_data *sd, int time)
+static void guild_block_skill(struct map_session_data *sd, int time)
{
uint16 skill_id[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL };
int i;
@@ -1440,7 +1564,7 @@ void guild_block_skill(struct map_session_data *sd, int time)
* 1 = enemy
* Returns true if yes.
*---------------------------------------------------*/
-int guild_check_alliance(int guild_id1, int guild_id2, int flag)
+static int guild_check_alliance(int guild_id1, int guild_id2, int flag)
{
struct guild *g;
int i;
@@ -1456,7 +1580,8 @@ int guild_check_alliance(int guild_id1, int guild_id2, int flag)
/*====================================================
* Player sd, asking player tsd an alliance between their 2 guilds
*---------------------------------------------------*/
-int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) {
+static int guild_reqalliance(struct map_session_data *sd, struct map_session_data *tsd)
+{
struct guild *g[2];
int i;
@@ -1512,7 +1637,8 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
/*====================================================
* Player sd, answer to player tsd (account_id) for an alliance request
*---------------------------------------------------*/
-int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) {
+static int guild_reply_reqalliance(struct map_session_data *sd, int account_id, int flag)
+{
struct map_session_data *tsd;
nullpo_ret(sd);
@@ -1572,7 +1698,8 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
/*====================================================
* Player sd asking to break alliance with guild guild_id
*---------------------------------------------------*/
-int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) {
+static int guild_delalliance(struct map_session_data *sd, int guild_id, int flag)
+{
nullpo_ret(sd);
if(map->agit_flag || map->agit2_flag) {
@@ -1588,7 +1715,7 @@ int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) {
/*====================================================
* Player sd, asking player tsd a formal enemy relation between their 2 guilds
*---------------------------------------------------*/
-int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
+static int guild_opposition(struct map_session_data *sd, struct map_session_data *tsd)
{
struct guild *g;
int i;
@@ -1631,7 +1758,8 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
/*====================================================
* Notification of a relationship between 2 guilds
*---------------------------------------------------*/
-int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2) {
+static int guild_allianceack(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag, const char *name1, const char *name2)
+{
struct guild *g[2] = { NULL };
int guild_id[2] = { 0 };
const char *guild_name[2] = { NULL };
@@ -1721,7 +1849,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
* Notification for the guild disbanded
* @see DBApply
*/
-int guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
+static int guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild *g = DB->data2ptr(data);
int guild_id=va_arg(ap,int);
@@ -1747,7 +1875,7 @@ int guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
* Invoked on Castles when a guild is broken. [Skotlex]
* @see DBApply
*/
-int castle_guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
+static int castle_guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild_castle *gc = DB->data2ptr(data);
int guild_id = va_arg(ap, int);
@@ -1768,7 +1896,7 @@ int castle_guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
}
//Invoked on /breakguild "Guild name"
-int guild_broken(int guild_id,int flag)
+static int guild_broken(int guild_id, int flag)
{
struct guild *g = guild->search(guild_id);
struct map_session_data *sd = NULL;
@@ -1812,28 +1940,33 @@ int guild_broken(int guild_id,int flag)
}
//Changes the Guild Master to the specified player. [Skotlex]
-int guild_gm_change(int guild_id, struct map_session_data *sd)
+static int guild_gm_change(int guild_id, int char_id)
{
- struct guild *g;
- nullpo_ret(sd);
+ struct guild *g = guild->search(guild_id);
+ char *name;
+ int i;
- if (sd->status.guild_id != guild_id)
- return 0;
+ nullpo_ret(g);
- g=guild->search(guild_id);
+ ARR_FIND(0, MAX_GUILD, i, g->member[i].char_id == char_id);
- nullpo_ret(g);
+ if (i == MAX_GUILD ) {
+ // Not part of the guild
+ return 0;
+ }
+
+ name = g->member[i].name;
- if (strcmp(g->master, sd->status.name) == 0) //Nothing to change.
+ if (strcmp(g->master, name) == 0) //Nothing to change.
return 0;
//Notify servers that master has changed.
- intif->guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1);
+ intif->guild_change_gm(guild_id, name, (int)strlen(name) + 1);
return 1;
}
//Notification from Char server that a guild's master has changed. [Skotlex]
-int guild_gm_changed(int guild_id, int account_id, int char_id)
+static int guild_gm_changed(int guild_id, int account_id, int char_id)
{
struct guild *g;
struct guild_member gm;
@@ -1862,6 +1995,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
if (g->member[pos].sd && g->member[pos].sd->fd) {
clif->message(g->member[pos].sd->fd, msg_sd(g->member[pos].sd,878)); //"You no longer are the Guild Master."
g->member[pos].sd->state.gmaster_flag = 0;
+ clif->blname_ack(0, &g->member[pos].sd->bl);
}
if (g->member[0].sd && g->member[0].sd->fd) {
@@ -1869,6 +2003,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
g->member[0].sd->state.gmaster_flag = 1;
//Block his skills for 5 minutes to prevent abuse.
guild->block_skill(g->member[0].sd, 300000);
+ clif->blname_ack(0, &g->member[pos].sd->bl);
}
// announce the change to all guild members
@@ -1878,6 +2013,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
{
clif->guild_basicinfo(g->member[i].sd);
clif->guild_memberlist(g->member[i].sd);
+ clif->guild_belonginfo(g->member[i].sd, g); // Update clientside guildmaster flag
}
}
@@ -1887,7 +2023,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
/*====================================================
* Guild disbanded
*---------------------------------------------------*/
-int guild_break(struct map_session_data *sd, const char *name)
+static int guild_break(struct map_session_data *sd, const char *name)
{
struct guild *g;
struct unit_data *ud;
@@ -1949,7 +2085,7 @@ int guild_break(struct map_session_data *sd, const char *name)
* Creates a list of guild castle IDs to be requested
* from char-server.
*/
-void guild_castle_map_init(void)
+static void guild_castle_map_init(void)
{
int num = db_size(guild->castle_db);
@@ -1979,7 +2115,7 @@ void guild_castle_map_init(void)
* @param index Type of data to change
* @param value New value
*/
-int guild_castledatasave(int castle_id, int index, int value)
+static int guild_castledatasave(int castle_id, int index, int value)
{
struct guild_castle *gc = guild->castle_search(castle_id);
@@ -2040,7 +2176,7 @@ int guild_castledatasave(int castle_id, int index, int value)
return 0;
}
-void guild_castle_reconnect_sub(void *key, void *data, va_list ap)
+static void guild_castle_reconnect_sub(void *key, void *data, va_list ap)
{
int castle_id = GetWord((int)h64BPTRSIZE(key), 0);
int index = GetWord((int)h64BPTRSIZE(key), 1);
@@ -2053,7 +2189,7 @@ void guild_castle_reconnect_sub(void *key, void *data, va_list ap)
* disconnected.
* On reconnect pushes all changes to char-server for saving.
*/
-void guild_castle_reconnect(int castle_id, int index, int value)
+static void guild_castle_reconnect(int castle_id, int index, int value)
{
static struct linkdb_node *gc_save_pending = NULL;
@@ -2069,7 +2205,7 @@ void guild_castle_reconnect(int castle_id, int index, int value)
}
// Load castle data then invoke OnAgitInit* on last
-int guild_castledataloadack(int len, const struct guild_castle *gc)
+static int guild_castledataloadack(int len, const struct guild_castle *gc)
{
int i;
int n = (len-4) / sizeof(struct guild_castle);
@@ -2112,7 +2248,7 @@ int guild_castledataloadack(int len, const struct guild_castle *gc)
/*====================================================
* Start normal woe and triggers all npc OnAgitStart
*---------------------------------------------------*/
-void guild_agit_start(void)
+static void guild_agit_start(void)
{
// Run All NPC_Event[OnAgitStart]
int c = npc->event_doall("OnAgitStart");
@@ -2122,7 +2258,7 @@ void guild_agit_start(void)
/*====================================================
* End normal woe and triggers all npc OnAgitEnd
*---------------------------------------------------*/
-void guild_agit_end(void)
+static void guild_agit_end(void)
{
// Run All NPC_Event[OnAgitEnd]
int c = npc->event_doall("OnAgitEnd");
@@ -2132,7 +2268,7 @@ void guild_agit_end(void)
/*====================================================
* Start woe2 and triggers all npc OnAgitStart2
*---------------------------------------------------*/
-void guild_agit2_start(void)
+static void guild_agit2_start(void)
{
// Run All NPC_Event[OnAgitStart2]
int c = npc->event_doall("OnAgitStart2");
@@ -2142,7 +2278,7 @@ void guild_agit2_start(void)
/*====================================================
* End woe2 and triggers all npc OnAgitEnd2
*---------------------------------------------------*/
-void guild_agit2_end(void)
+static void guild_agit2_end(void)
{
// Run All NPC_Event[OnAgitEnd2]
int c = npc->event_doall("OnAgitEnd2");
@@ -2150,7 +2286,7 @@ void guild_agit2_end(void)
}
// How many castles does this guild have?
-int guild_checkcastles(struct guild *g)
+static int guild_checkcastles(struct guild *g)
{
int nb_cas = 0;
struct guild_castle* gc = NULL;
@@ -2166,7 +2302,7 @@ int guild_checkcastles(struct guild *g)
}
// Are these two guilds allied?
-bool guild_isallied(int guild_id, int guild_id2)
+static bool guild_isallied(int guild_id, int guild_id2)
{
int i;
struct guild* g = guild->search(guild_id);
@@ -2176,7 +2312,8 @@ bool guild_isallied(int guild_id, int guild_id2)
return( i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0 );
}
-void guild_flag_add(struct npc_data *nd) {
+static void guild_flag_add(struct npc_data *nd)
+{
int i;
nullpo_retv(nd);
@@ -2194,7 +2331,8 @@ void guild_flag_add(struct npc_data *nd) {
guild->flags[i] = nd;
}
-void guild_flag_remove(struct npc_data *nd) {
+static void guild_flag_remove(struct npc_data *nd)
+{
int i, cursor;
nullpo_retv(nd);
if( guild->flags_count == 0 )
@@ -2223,7 +2361,7 @@ void guild_flag_remove(struct npc_data *nd) {
/**
* @see DBApply
*/
-int eventlist_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int eventlist_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct eventlist *next = NULL;
struct eventlist *current = DB->data2ptr(data);
@@ -2238,7 +2376,7 @@ int eventlist_db_final(union DBKey key, struct DBData *data, va_list ap)
/**
* @see DBApply
*/
-int guild_expcache_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int guild_expcache_db_final(union DBKey key, struct DBData *data, va_list ap)
{
ers_free(guild->expcache_ers, DB->data2ptr(data));
return 0;
@@ -2247,7 +2385,7 @@ int guild_expcache_db_final(union DBKey key, struct DBData *data, va_list ap)
/**
* @see DBApply
*/
-int guild_castle_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int guild_castle_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct guild_castle* gc = DB->data2ptr(data);
if( gc->temp_guardians )
@@ -2257,7 +2395,8 @@ int guild_castle_db_final(union DBKey key, struct DBData *data, va_list ap)
}
/* called when scripts are reloaded/unloaded */
-void guild_flags_clear(void) {
+static void guild_flags_clear(void)
+{
int i;
for( i = 0; i < guild->flags_count; i++ ) {
if( guild->flags[i] )
@@ -2267,7 +2406,8 @@ void guild_flags_clear(void) {
guild->flags_count = 0;
}
-void do_init_guild(bool minimal) {
+static void do_init_guild(bool minimal)
+{
if (minimal)
return;
@@ -2277,8 +2417,7 @@ void do_init_guild(bool minimal) {
guild->infoevent_db = idb_alloc(DB_OPT_BASE);
guild->expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
- sv->readdb(map->db_path, "castle_db.txt", ',', 4, 5, -1, guild->read_castledb);
-
+ guild->read_castledb_libconfig();
sv->readdb(map->db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, guild->read_guildskill_tree_db); //guild skill tree [Komurka]
timer->add_func_list(guild->payexp_timer,"guild_payexp_timer");
@@ -2287,7 +2426,7 @@ void do_init_guild(bool minimal) {
timer->add_interval(timer->gettick()+GUILD_SEND_XY_INVERVAL,guild->send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL);
}
-void do_final_guild(void)
+static void do_final_guild(void)
{
struct DBIterator *iter = db_iterator(guild->db);
struct guild *g;
@@ -2313,7 +2452,9 @@ void do_final_guild(void)
if( guild->flags )
aFree(guild->flags);
}
-void guild_defaults(void) {
+
+void guild_defaults(void)
+{
guild = &guild_s;
guild->init = do_init_guild;
@@ -2384,7 +2525,6 @@ void guild_defaults(void) {
guild->change_emblem = guild_change_emblem;
guild->emblem_changed = guild_emblem_changed;
guild->send_message = guild_send_message;
- guild->recv_message = guild_recv_message;
guild->send_dot_remove = guild_send_dot_remove;
guild->skillupack = guild_skillupack;
guild->dobreak = guild_break;
@@ -2411,7 +2551,9 @@ void guild_defaults(void) {
guild->payexp_timer = guild_payexp_timer;
guild->sd_check = guild_sd_check;
guild->read_guildskill_tree_db = guild_read_guildskill_tree_db;
- guild->read_castledb = guild_read_castledb;
+ guild->read_castledb_libconfig = guild_read_castledb_libconfig;
+ guild->read_castledb_libconfig_sub = guild_read_castledb_libconfig_sub;
+ guild->read_castledb_libconfig_sub_warp = guild_read_castledb_libconfig_sub_warp;
guild->payexp_timer_sub = guild_payexp_timer_sub;
guild->send_xy_timer_sub = guild_send_xy_timer_sub;
guild->send_xy_timer = guild_send_xy_timer;
diff --git a/src/map/guild.h b/src/map/guild.h
index 1f3b74543..82582a864 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -91,7 +91,7 @@ struct guild_interface {
bool (*isallied) (int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex]
/* */
struct guild *(*search) (int guild_id);
- struct guild *(*searchname) (char *str);
+ struct guild *(*searchname) (const char *str);
struct guild_castle *(*castle_search) (int gcid);
/* */
struct guild_castle *(*mapname2gc) (const char* mapname);
@@ -100,7 +100,7 @@ struct guild_interface {
struct map_session_data *(*getavailablesd) (struct guild *g);
int (*getindex) (const struct guild *g, int account_id, int char_id);
int (*getposition) (struct guild *g, struct map_session_data *sd);
- unsigned int (*payexp) (struct map_session_data *sd,unsigned int exp);
+ uint64 (*payexp) (struct map_session_data *sd, uint64 exp);
int (*getexp) (struct map_session_data *sd,int exp); // [Celest]
/* */
int (*create) (struct map_session_data *sd, const char *name);
@@ -126,7 +126,7 @@ struct guild_interface {
int (*check_alliance) (int guild_id1, int guild_id2, int flag);
/* */
int (*send_memberinfoshort) (struct map_session_data *sd,int online);
- int (*recv_memberinfoshort) (int guild_id,int account_id,int char_id,int online,int lv,int class_);
+ int (*recv_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class, uint32 last_login);
int (*change_memberposition) (int guild_id,int account_id,int char_id,short idx);
int (*memberposition_changed) (struct guild *g,int idx,int pos);
int (*change_position) (int guild_id,int idx,int mode,int exp_mode,const char *name);
@@ -135,13 +135,12 @@ struct guild_interface {
int (*notice_changed) (int guild_id,const char *mes1,const char *mes2);
int (*change_emblem) (struct map_session_data *sd,int len,const char *data);
int (*emblem_changed) (int len,int guild_id,int emblem_id,const char *data);
- int (*send_message) (struct map_session_data *sd,const char *mes,int len);
- int (*recv_message) (int guild_id,int account_id,const char *mes,int len);
+ int (*send_message) (struct map_session_data *sd, const char *mes);
int (*send_dot_remove) (struct map_session_data *sd);
int (*skillupack) (int guild_id,uint16 skill_id,int account_id);
int (*dobreak) (struct map_session_data *sd, const char *name);
int (*broken) (int guild_id,int flag);
- int (*gm_change) (int guild_id, struct map_session_data *sd);
+ int (*gm_change) (int guild_id, int char_id);
int (*gm_changed) (int guild_id, int account_id, int char_id);
/* */
void (*castle_map_init) (void);
@@ -165,7 +164,9 @@ struct guild_interface {
int (*payexp_timer) (int tid, int64 tick, int id, intptr_t data);
struct map_session_data *(*sd_check) (int guild_id, int account_id, int char_id);
bool (*read_guildskill_tree_db) (char* split[], int columns, int current);
- bool (*read_castledb) (char* str[], int columns, int current);
+ bool (*read_castledb_libconfig) (void);
+ bool (*read_castledb_libconfig_sub) (struct config_setting_t *it, int idx, const char *source);
+ bool (*read_castledb_libconfig_sub_warp) (struct config_setting_t *wd, const char *source, struct guild_castle *gc);
int (*payexp_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
int (*send_xy_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index bda8fd9e6..65c457283 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@
#include "map/party.h"
#include "map/pc.h"
#include "map/pet.h"
+#include "map/quest.h"
#include "map/script.h"
#include "map/skill.h"
#include "map/status.h"
@@ -58,19 +59,21 @@
#include <stdlib.h>
#include <string.h>
-struct homunculus_interface homunculus_s;
-struct homun_dbs homundbs;
+static struct homunculus_interface homunculus_s;
+static struct homun_dbs homundbs;
struct homunculus_interface *homun;
//Returns the viewdata for homunculus
-struct view_data* homunculus_get_viewdata(int class_) {
+static struct view_data *homunculus_get_viewdata(int class_)
+{
Assert_retr(NULL, homdb_checkid(class_));
return &homun->dbs->viewdb[class_-HM_CLASS_BASE];
}
-enum homun_type homunculus_class2type(int class_) {
+static enum homun_type homunculus_class2type(int class_)
+{
switch(class_) {
// Normal Homunculus
case HOMID_LIF:
@@ -104,7 +107,8 @@ enum homun_type homunculus_class2type(int class_) {
}
}
-void homunculus_addspiritball(struct homun_data *hd, int max) {
+static void homunculus_addspiritball(struct homun_data *hd, int max)
+{
nullpo_retv(hd);
if (max > MAX_SKILL_LEVEL)
@@ -121,7 +125,8 @@ void homunculus_addspiritball(struct homun_data *hd, int max) {
clif->spiritball(&hd->bl);
}
-void homunculus_delspiritball(struct homun_data *hd, int count, int type) {
+static void homunculus_delspiritball(struct homun_data *hd, int count, int type)
+{
nullpo_retv(hd);
if (hd->homunculus.spiritball <= 0) {
@@ -140,11 +145,13 @@ void homunculus_delspiritball(struct homun_data *hd, int count, int type) {
clif->spiritball(&hd->bl);
}
-void homunculus_damaged(struct homun_data *hd) {
+static void homunculus_damaged(struct homun_data *hd)
+{
clif->hominfo(hd->master,hd,0);
}
-int homunculus_dead(struct homun_data *hd) {
+static int homunculus_dead(struct homun_data *hd)
+{
//There's no intimacy penalties on death (from Tharis)
struct map_session_data *sd;
@@ -165,25 +172,26 @@ int homunculus_dead(struct homun_data *hd) {
}
//Vaporize a character's homun. If flag, HP needs to be 80% or above.
-int homunculus_vaporize(struct map_session_data *sd, enum homun_state flag) {
+static int homunculus_vaporize(struct map_session_data *sd, enum homun_state state, bool force)
+{
struct homun_data *hd;
nullpo_ret(sd);
hd = sd->hd;
- if (!hd || hd->homunculus.vaporize != HOM_ST_ACTIVE)
+ if (hd == NULL || hd->bl.prev == NULL || hd->homunculus.vaporize != HOM_ST_ACTIVE)
return 0;
if (status->isdead(&hd->bl))
return 0; //Can't vaporize a dead homun.
- if (flag == HOM_ST_REST && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
+ if (!force && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
return 0;
hd->regen.state.block = 3; //Block regen while vaporized.
//Delete timers when vaporized.
homun->hunger_timer_delete(hd);
- hd->homunculus.vaporize = flag;
+ hd->homunculus.vaporize = state;
if(battle_config.hom_setting&0x40)
memset(hd->blockskill, 0, sizeof(hd->blockskill));
clif->hominfo(sd, sd->hd, 0);
@@ -193,7 +201,8 @@ int homunculus_vaporize(struct map_session_data *sd, enum homun_state flag) {
//delete a homunculus, completely "killing it".
//Emote is the emotion the master should use, send negative to disable.
-int homunculus_delete(struct homun_data *hd, int emote) {
+static int homunculus_delete(struct homun_data *hd, int emote)
+{
struct map_session_data *sd;
nullpo_ret(hd);
sd = hd->master;
@@ -212,7 +221,8 @@ int homunculus_delete(struct homun_data *hd, int emote) {
return unit->remove_map(&hd->bl,CLR_OUTSIGHT, ALC_MARK);
}
-int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) {
+static int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve)
+{
int i, id = 0;
int j, f = 1;
int c = 0;
@@ -248,7 +258,7 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) {
for( i = 0; i < MAX_SKILL_TREE && ( id = homun->dbs->skill_tree[c][i].id ) > 0; i++ ) {
if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id )
continue; //Skill already known.
- j = ( flag_evolve ) ? 10 : hd->homunculus.intimacy;
+ j = ( flag_evolve ) ? 1000 : hd->homunculus.intimacy;
if( j < homun->dbs->skill_tree[c][i].intimacylv )
continue;
if(!battle_config.skillfree) {
@@ -269,7 +279,8 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) {
return 0;
}
-int homunculus_checkskill(struct homun_data *hd,uint16 skill_id) {
+static int homunculus_checkskill(struct homun_data *hd, uint16 skill_id)
+{
int i = skill_id - HM_SKILLBASE;
if(!hd)
return 0;
@@ -281,7 +292,8 @@ int homunculus_checkskill(struct homun_data *hd,uint16 skill_id) {
return 0;
}
-int homunculus_skill_tree_get_max(int id, int b_class) {
+static int homunculus_skill_tree_get_max(int id, int b_class)
+{
int i, skill_id;
b_class -= HM_CLASS_BASE;
Assert_ret(b_class >= 0 && b_class < MAX_HOMUNCULUS_CLASS);
@@ -291,7 +303,8 @@ int homunculus_skill_tree_get_max(int id, int b_class) {
return skill->get_max(id);
}
-void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
+static void homunculus_skillup(struct homun_data *hd, uint16 skill_id)
+{
int i = 0 ;
nullpo_retv(hd);
@@ -317,7 +330,8 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
}
}
-bool homunculus_levelup(struct homun_data *hd) {
+static bool homunculus_levelup(struct homun_data *hd)
+{
struct s_homunculus *hom;
struct h_stats *min, *max;
int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ;
@@ -356,14 +370,14 @@ bool homunculus_levelup(struct homun_data *hd) {
max = &hd->homunculusDB->gmax;
min = &hd->homunculusDB->gmin;
- growth_max_hp = rnd_value(min->HP, max->HP);
- growth_max_sp = rnd_value(min->SP, max->SP);
- growth_str = rnd_value(min->str, max->str);
- growth_agi = rnd_value(min->agi, max->agi);
- growth_vit = rnd_value(min->vit, max->vit);
- growth_dex = rnd_value(min->dex, max->dex);
- growth_int = rnd_value(min->int_,max->int_);
- growth_luk = rnd_value(min->luk, max->luk);
+ growth_max_hp = rnd->value(min->HP, max->HP);
+ growth_max_sp = rnd->value(min->SP, max->SP);
+ growth_str = rnd->value(min->str, max->str);
+ growth_agi = rnd->value(min->agi, max->agi);
+ growth_vit = rnd->value(min->vit, max->vit);
+ growth_dex = rnd->value(min->dex, max->dex);
+ growth_int = rnd->value(min->int_,max->int_);
+ growth_luk = rnd->value(min->luk, max->luk);
//Aegis discards the decimals in the stat growth values!
growth_str-=growth_str%10;
@@ -387,16 +401,18 @@ bool homunculus_levelup(struct homun_data *hd) {
if ( battle_config.homunculus_show_growth ) {
char output[256] ;
sprintf(output,
- "Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ",
+ msg_sd(hd->master, 892), // Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f)
growth_max_hp, growth_max_sp,
growth_str/10.0, growth_agi/10.0, growth_vit/10.0,
growth_int/10.0, growth_dex/10.0, growth_luk/10.0);
- clif_disp_onlyself(hd->master,output,strlen(output));
+ clif_disp_onlyself(hd->master, output);
}
+ quest->questinfo_refresh(hd->master);
return true;
}
-int homunculus_change_class(struct homun_data *hd, short class_) {
+static int homunculus_change_class(struct homun_data *hd, int class_)
+{
int i = homun->db_search(class_,HOMUNCULUS_CLASS);
nullpo_retr(0, hd);
if (i == INDEX_NOT_FOUND)
@@ -405,10 +421,12 @@ int homunculus_change_class(struct homun_data *hd, short class_) {
hd->homunculus.class_ = class_;
status->set_viewdata(&hd->bl, class_);
homun->calc_skilltree(hd, 1);
+ quest->questinfo_refresh(hd->master);
return 1;
}
-bool homunculus_evolve(struct homun_data *hd) {
+static bool homunculus_evolve(struct homun_data *hd)
+{
struct s_homunculus *hom;
struct h_stats *max, *min;
struct map_session_data *sd;
@@ -432,14 +450,14 @@ bool homunculus_evolve(struct homun_data *hd) {
hom = &hd->homunculus;
max = &hd->homunculusDB->emax;
min = &hd->homunculusDB->emin;
- hom->max_hp += rnd_value(min->HP, max->HP);
- hom->max_sp += rnd_value(min->SP, max->SP);
- hom->str += 10*rnd_value(min->str, max->str);
- hom->agi += 10*rnd_value(min->agi, max->agi);
- hom->vit += 10*rnd_value(min->vit, max->vit);
- hom->int_+= 10*rnd_value(min->int_,max->int_);
- hom->dex += 10*rnd_value(min->dex, max->dex);
- hom->luk += 10*rnd_value(min->luk, max->luk);
+ hom->max_hp += rnd->value(min->HP, max->HP);
+ hom->max_sp += rnd->value(min->SP, max->SP);
+ hom->str += 10*rnd->value(min->str, max->str);
+ hom->agi += 10*rnd->value(min->agi, max->agi);
+ hom->vit += 10*rnd->value(min->vit, max->vit);
+ hom->int_+= 10*rnd->value(min->int_,max->int_);
+ hom->dex += 10*rnd->value(min->dex, max->dex);
+ hom->luk += 10*rnd->value(min->luk, max->luk);
hom->intimacy = 500;
unit->remove_map(&hd->bl, CLR_OUTSIGHT, ALC_MARK);
@@ -456,11 +474,12 @@ bool homunculus_evolve(struct homun_data *hd) {
if (!(battle_config.hom_setting&0x2))
skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
-
+ quest->questinfo_refresh(sd);
return true;
}
-bool homunculus_mutate(struct homun_data *hd, int homun_id) {
+static bool homunculus_mutate(struct homun_data *hd, int homun_id)
+{
struct s_homunculus *hom;
struct map_session_data *sd;
int prev_class = 0;
@@ -506,7 +525,23 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
return true;
}
-int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
+static int homunculus_gainexp_real(struct homun_data *hd, unsigned int exp)
+{
+ nullpo_ret(hd);
+ nullpo_ret(hd->master);
+
+ hd->homunculus.exp += exp;
+
+ if (hd->master->state.showexp && hd->exp_next > 0) {
+ char output[256];
+ sprintf(output, msg_fd(hd->master->fd, 449), exp, ((float)exp / (float)hd->exp_next * (float)100));
+ clif_disp_onlyself(hd->master, output);
+ }
+ return 1;
+}
+
+static int homunculus_gainexp(struct homun_data *hd, unsigned int exp)
+{
enum homun_type htype;
nullpo_ret(hd);
@@ -530,10 +565,10 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
break;
}
- hd->homunculus.exp += exp;
+ homun->gainexp_real(hd, exp);
- if(hd->homunculus.exp < hd->exp_next) {
- clif->hominfo(hd->master,hd,0);
+ if (hd->homunculus.exp < hd->exp_next) {
+ clif->hominfo(hd->master, hd, 0);
return 0;
}
@@ -550,7 +585,8 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
}
// Return the new value
-unsigned int homunculus_add_intimacy(struct homun_data *hd, unsigned int value) {
+static unsigned int homunculus_add_intimacy(struct homun_data *hd, unsigned int value)
+{
nullpo_ret(hd);
if (battle_config.homunculus_friendly_rate != 100)
value = (value * battle_config.homunculus_friendly_rate) / 100;
@@ -563,7 +599,8 @@ unsigned int homunculus_add_intimacy(struct homun_data *hd, unsigned int value)
}
// Return 0 if decrease fails or intimacy became 0 else the new value
-unsigned int homunculus_consume_intimacy(struct homun_data *hd, unsigned int value) {
+static unsigned int homunculus_consume_intimacy(struct homun_data *hd, unsigned int value)
+{
nullpo_ret(hd);
if (hd->homunculus.intimacy >= value)
hd->homunculus.intimacy -= value;
@@ -573,12 +610,14 @@ unsigned int homunculus_consume_intimacy(struct homun_data *hd, unsigned int val
return hd->homunculus.intimacy;
}
-void homunculus_healed (struct homun_data *hd) {
+static void homunculus_healed(struct homun_data *hd)
+{
nullpo_retv(hd);
clif->hominfo(hd->master,hd,0);
}
-void homunculus_save(struct homun_data *hd) {
+static void homunculus_save(struct homun_data *hd)
+{
// copy data that must be saved in homunculus struct ( hp / sp )
struct map_session_data *sd = NULL;
//Do not check for max_hp/max_sp caps as current could be higher to max due
@@ -592,7 +631,8 @@ void homunculus_save(struct homun_data *hd) {
intif->homunculus_requestsave(sd->status.account_id, &hd->homunculus);
}
-unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num) {
+static unsigned char homunculus_menu(struct map_session_data *sd, unsigned char menu_num)
+{
nullpo_ret(sd);
if (sd->hd == NULL)
return 1;
@@ -613,7 +653,8 @@ unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num
return 0;
}
-bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
+static bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd)
+{
int i, foodID, emotion;
nullpo_retr(false, hd);
@@ -661,7 +702,8 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
return true;
}
-int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) {
+static int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
struct homun_data *hd;
@@ -683,7 +725,12 @@ int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) {
} else if(hd->homunculus.hunger == 75) {
clif->emotion(&hd->bl, E_OK);
}
-
+ if (battle_config.feature_enable_homun_autofeed != 0) {
+ if (hd->homunculus.autofeed) {
+ if (hd->homunculus.hunger < 30)
+ homun->feed(sd, hd);
+ }
+ }
if(hd->homunculus.hunger < 0) {
hd->homunculus.hunger = 0;
// Delete the homunculus if intimacy <= 100
@@ -697,7 +744,8 @@ int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void homunculus_hunger_timer_delete(struct homun_data *hd) {
+static void homunculus_hunger_timer_delete(struct homun_data *hd)
+{
nullpo_retv(hd);
if(hd->hungry_timer != INVALID_TIMER) {
timer->delete(hd->hungry_timer,homun->hunger_timer);
@@ -705,7 +753,7 @@ void homunculus_hunger_timer_delete(struct homun_data *hd) {
}
}
-int homunculus_change_name(struct map_session_data *sd, const char *name)
+static int homunculus_change_name(struct map_session_data *sd, const char *name)
{
int i;
struct homun_data *hd;
@@ -726,7 +774,7 @@ int homunculus_change_name(struct map_session_data *sd, const char *name)
return intif_rename_hom(sd, name);
}
-bool homunculus_change_name_ack(struct map_session_data *sd, const char *name, int flag)
+static bool homunculus_change_name_ack(struct map_session_data *sd, const char *name, int flag)
{
struct homun_data *hd;
char *newname = NULL;
@@ -746,13 +794,14 @@ bool homunculus_change_name_ack(struct map_session_data *sd, const char *name, i
}
safestrncpy(hd->homunculus.name, newname, NAME_LENGTH);
aFree(newname);
- clif->charnameack (0,&hd->bl);
+ clif->blname_ack(0,&hd->bl);
hd->homunculus.rename_flag = 1;
clif->hominfo(sd,hd,0);
return true;
}
-int homunculus_db_search(int key,int type) {
+static int homunculus_db_search(int key, int type)
+{
int i;
for(i=0;i<MAX_HOMUNCULUS_CLASS;i++) {
@@ -786,7 +835,7 @@ int homunculus_db_search(int key,int type) {
* @param hom The homunculus source data.
* @retval false in case of errors.
*/
-bool homunculus_create(struct map_session_data *sd, const struct s_homunculus *hom)
+static bool homunculus_create(struct map_session_data *sd, const struct s_homunculus *hom, bool is_new)
{
struct homun_data *hd;
int i = 0;
@@ -830,25 +879,29 @@ bool homunculus_create(struct map_session_data *sd, const struct s_homunculus *h
map->addiddb(&hd->bl);
status_calc_homunculus(hd,SCO_FIRST);
- status_percent_heal(&hd->bl, 100, 100);
+ if (is_new) {
+ status_percent_heal(&hd->bl, 100, 100);
+ }
hd->hungry_timer = INVALID_TIMER;
return true;
}
-void homunculus_init_timers(struct homun_data * hd) {
+static void homunculus_init_timers(struct homun_data *hd)
+{
nullpo_retv(hd);
if (hd->hungry_timer == INVALID_TIMER)
hd->hungry_timer = timer->add(timer->gettick()+hd->homunculusDB->hungryDelay,homun->hunger_timer,hd->master->bl.id,0);
hd->regen.state.block = 0; //Restore HP/SP block.
}
-bool homunculus_call(struct map_session_data *sd) {
+static bool homunculus_call(struct map_session_data *sd)
+{
struct homun_data *hd;
nullpo_retr(false, sd);
if (!sd->status.hom_id) //Create a new homun.
- return homun->creation_request(sd, HM_CLASS_BASE + rnd_value(0, 7));
+ return homun->creation_request(sd, HM_CLASS_BASE + rnd->value(0, 7));
// If homunc not yet loaded, load it
if (!sd->hd)
@@ -881,10 +934,11 @@ bool homunculus_call(struct map_session_data *sd) {
}
// Receive homunculus data from char server
-bool homunculus_recv_data(int account_id, const struct s_homunculus *sh, int flag)
+static bool homunculus_recv_data(int account_id, const struct s_homunculus *sh, int flag)
{
struct map_session_data *sd;
struct homun_data *hd;
+ bool is_new = false;
nullpo_retr(false, sh);
@@ -900,15 +954,17 @@ bool homunculus_recv_data(int account_id, const struct s_homunculus *sh, int fla
if (sd->status.char_id != sh->char_id && sd->status.hom_id != sh->hom_id)
return false;
- if (sd->status.hom_id == 0) //Hom just created.
+ if (sd->status.hom_id == 0) { // Hom just created.
sd->status.hom_id = sh->hom_id;
+ is_new = true;
+ }
if (sd->hd != NULL) {
//uh? Overwrite the data.
memcpy(&sd->hd->homunculus, sh, sizeof sd->hd->homunculus);
sd->hd->homunculus.char_id = sd->status.char_id; // Correct char id if necessary.
} else {
- homun->create(sd, sh);
+ homun->create(sd, sh, is_new);
}
hd = sd->hd;
@@ -940,7 +996,8 @@ bool homunculus_recv_data(int account_id, const struct s_homunculus *sh, int fla
}
// Ask homunculus creation to char server
-bool homunculus_creation_request(struct map_session_data *sd, int class_) {
+static bool homunculus_creation_request(struct map_session_data *sd, int class_)
+{
struct s_homunculus hom;
struct h_stats *base;
int i;
@@ -976,7 +1033,8 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) {
return true;
}
-bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short x, short y) {
+static bool homunculus_ressurect(struct map_session_data *sd, unsigned char per, short x, short y)
+{
struct homun_data* hd;
nullpo_retr(false,sd);
@@ -1009,7 +1067,8 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short
return true;
}
-void homunculus_revive(struct homun_data *hd, unsigned int hp, unsigned int sp) {
+static void homunculus_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
+{
struct map_session_data *sd;
nullpo_retv(hd);
@@ -1023,7 +1082,8 @@ void homunculus_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
clif->homskillinfoblock(sd);
}
//Resets a homunc stats back to zero (but doesn't touches hunger or intimacy)
-void homunculus_stat_reset(struct homun_data *hd) {
+static void homunculus_stat_reset(struct homun_data *hd)
+{
struct s_homunculus_db *db;
struct s_homunculus *hom;
struct h_stats *base;
@@ -1047,7 +1107,8 @@ void homunculus_stat_reset(struct homun_data *hd) {
hd->homunculus.skillpts = 0;
}
-bool homunculus_shuffle(struct homun_data *hd) {
+static bool homunculus_shuffle(struct homun_data *hd)
+{
struct map_session_data *sd;
int lv, skillpts;
unsigned int exp;
@@ -1075,14 +1136,14 @@ bool homunculus_shuffle(struct homun_data *hd) {
//Evolved bonuses
struct s_homunculus *hom = &hd->homunculus;
struct h_stats *max = &hd->homunculusDB->emax, *min = &hd->homunculusDB->emin;
- hom->max_hp += rnd_value(min->HP, max->HP);
- hom->max_sp += rnd_value(min->SP, max->SP);
- hom->str += 10*rnd_value(min->str, max->str);
- hom->agi += 10*rnd_value(min->agi, max->agi);
- hom->vit += 10*rnd_value(min->vit, max->vit);
- hom->int_+= 10*rnd_value(min->int_,max->int_);
- hom->dex += 10*rnd_value(min->dex, max->dex);
- hom->luk += 10*rnd_value(min->luk, max->luk);
+ hom->max_hp += rnd->value(min->HP, max->HP);
+ hom->max_sp += rnd->value(min->SP, max->SP);
+ hom->str += 10*rnd->value(min->str, max->str);
+ hom->agi += 10*rnd->value(min->agi, max->agi);
+ hom->vit += 10*rnd->value(min->vit, max->vit);
+ hom->int_+= 10*rnd->value(min->int_,max->int_);
+ hom->dex += 10*rnd->value(min->dex, max->dex);
+ hom->luk += 10*rnd->value(min->luk, max->luk);
}
hd->homunculus.exp = exp;
@@ -1096,7 +1157,8 @@ bool homunculus_shuffle(struct homun_data *hd) {
return true;
}
-bool homunculus_read_db_sub(char* str[], int columns, int current) {
+static bool homunculus_read_db_sub(char *str[], int columns, int current)
+{
int classid;
struct s_homunculus_db *db;
@@ -1207,7 +1269,8 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) {
return true;
}
-void homunculus_read_db(void) {
+static void homunculus_read_db(void)
+{
int i;
const char *filename[]={DBPATH"homunculus_db.txt","homunculus_db2.txt"};
memset(homun->dbs->db, 0, sizeof(homun->dbs->db));
@@ -1215,7 +1278,7 @@ void homunculus_read_db(void) {
if( i > 0 ) {
char filepath[256];
- sprintf(filepath, "%s/%s", map->db_path, filename[i]);
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, filename[i]);
if( !exists(filepath) ) {
continue;
@@ -1227,7 +1290,8 @@ void homunculus_read_db(void) {
}
// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req>
-bool homunculus_read_skill_db_sub(char* split[], int columns, int current) {
+static bool homunculus_read_skill_db_sub(char *split[], int columns, int current)
+{
int k, classid;
int j;
int minJobLevelPresent = 0;
@@ -1262,12 +1326,13 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) {
homun->dbs->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]);
}
- homun->dbs->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]);
+ homun->dbs->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]) * 100;
return true;
}
-int8 homunculus_get_intimacy_grade(struct homun_data *hd) {
+static int8 homunculus_get_intimacy_grade(struct homun_data *hd)
+{
unsigned int val;
nullpo_ret(hd);
val = hd->homunculus.intimacy / 100;
@@ -1287,12 +1352,14 @@ int8 homunculus_get_intimacy_grade(struct homun_data *hd) {
return 0;
}
-void homunculus_skill_db_read(void) {
+static void homunculus_skill_db_read(void)
+{
memset(homun->dbs->skill_tree, 0, sizeof(homun->dbs->skill_tree));
sv->readdb(map->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub);
}
-void homunculus_exp_db_read(void) {
+static void homunculus_exp_db_read(void)
+{
char line[1024];
int i, j=0;
char *filename[]={
@@ -1322,20 +1389,23 @@ void homunculus_exp_db_read(void) {
homun->dbs->exptable[MAX_LEVEL - 1] = 0;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s/%s"CL_RESET"'.\n", j, map->db_path, filename[i]);
}
}
-void homunculus_reload(void) {
+static void homunculus_reload(void)
+{
homun->read_db();
homun->exp_db_read();
}
-void homunculus_skill_reload(void) {
+static void homunculus_skill_reload(void)
+{
homun->skill_db_read();
}
-void do_init_homunculus(bool minimal) {
+static void do_init_homunculus(bool minimal)
+{
int class_;
if (minimal)
@@ -1350,14 +1420,16 @@ void do_init_homunculus(bool minimal) {
//Stock view data for homuncs
memset(homun->dbs->viewdb, 0, sizeof(homun->dbs->viewdb));
for (class_ = 0; class_ < MAX_HOMUNCULUS_CLASS; class_++)
- homun->dbs->viewdb[class_].class_ = HM_CLASS_BASE+class_;
+ homun->dbs->viewdb[class_].class = HM_CLASS_BASE + class_;
}
-void do_final_homunculus(void) {
+static void do_final_homunculus(void)
+{
}
-void homunculus_defaults(void) {
+void homunculus_defaults(void)
+{
homun = &homunculus_s;
homun->dbs = &homundbs;
@@ -1381,6 +1453,7 @@ void homunculus_defaults(void) {
homun->evolve = homunculus_evolve;
homun->mutate = homunculus_mutate;
homun->gainexp = homunculus_gainexp;
+ homun->gainexp_real = homunculus_gainexp_real;
homun->add_intimacy = homunculus_add_intimacy;
homun->consume_intimacy = homunculus_consume_intimacy;
homun->healed = homunculus_healed;
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index 3dd9e4772..c12629f46 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -124,7 +124,7 @@ struct homun_data {
struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn]
unsigned int exp_next;
- char blockskill[MAX_SKILL]; // [orn]
+ char blockskill[MAX_SKILL_DB]; // [orn]
int64 masterteleport_timer;
};
@@ -133,7 +133,7 @@ struct homun_skill_tree_entry {
short id;
unsigned char max;
unsigned char joblv;
- short intimacylv;
+ int intimacylv;
struct {
short id;
unsigned char lv;
@@ -167,17 +167,18 @@ struct homunculus_interface {
enum homun_type (*class2type) (int class_);
void (*damaged) (struct homun_data *hd);
int (*dead) (struct homun_data *hd);
- int (*vaporize) (struct map_session_data *sd, enum homun_state flag);
+ int (*vaporize) (struct map_session_data *sd, enum homun_state state, bool force);
int (*delete) (struct homun_data *hd, int emote);
int (*checkskill) (struct homun_data *hd, uint16 skill_id);
int (*calc_skilltree) (struct homun_data *hd, int flag_evolve);
int (*skill_tree_get_max) (int id, int b_class);
void (*skillup) (struct homun_data *hd, uint16 skill_id);
bool (*levelup) (struct homun_data *hd);
- int (*change_class) (struct homun_data *hd, short class_);
+ int (*change_class) (struct homun_data *hd, int class_);
bool (*evolve) (struct homun_data *hd);
bool (*mutate) (struct homun_data *hd, int homun_id);
int (*gainexp) (struct homun_data *hd, unsigned int exp);
+ int (*gainexp_real) (struct homun_data *hd, unsigned int exp);
unsigned int (*add_intimacy) (struct homun_data * hd, unsigned int value);
unsigned int (*consume_intimacy) (struct homun_data *hd, unsigned int value);
void (*healed) (struct homun_data *hd);
@@ -189,7 +190,7 @@ struct homunculus_interface {
int (*change_name) (struct map_session_data *sd, const char *name);
bool (*change_name_ack) (struct map_session_data *sd, const char *name, int flag);
int (*db_search) (int key,int type);
- bool (*create) (struct map_session_data *sd, const struct s_homunculus *hom);
+ bool (*create) (struct map_session_data *sd, const struct s_homunculus *hom, bool is_new);
void (*init_timers) (struct homun_data * hd);
bool (*call) (struct map_session_data *sd);
bool (*recv_data) (int account_id, const struct s_homunculus *sh, int flag);
diff --git a/src/map/instance.c b/src/map/instance.c
index a6700d486..1104b7e88 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
#include "map/npc.h"
#include "map/party.h"
#include "map/pc.h"
+#include "map/quest.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/db.h"
@@ -47,11 +48,12 @@
#include <string.h>
#include <time.h>
-struct instance_interface instance_s;
+static struct instance_interface instance_s;
struct instance_interface *instance;
/// Checks whether given instance id is valid or not.
-bool instance_is_valid(int instance_id) {
+static bool instance_is_valid(int instance_id)
+{
if( instance_id < 0 || instance_id >= instance->instances ) {// out of range
return false;
}
@@ -69,7 +71,8 @@ bool instance_is_valid(int instance_id) {
* -4 = already exists | -3 = no free instances | -2 = owner not found | -1 = invalid type
* On success return instance_id
*--------------------------------------*/
-int instance_create(int owner_id, const char *name, enum instance_owner_type type) {
+static int instance_create(int owner_id, const char *name, enum instance_owner_type type)
+{
struct map_session_data *sd = NULL;
unsigned short *icptr = NULL;
struct party_data *p = NULL;
@@ -180,7 +183,8 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ
* @retval -3 No more map indices available.
* @retval -4 Source map is already an instance.
**/
-int instance_add_map(const char *name, int instance_id, bool usebasename, const char *map_name) {
+static int instance_add_map(const char *name, int instance_id, bool usebasename, const char *map_name)
+{
int16 m = map->mapname2mapid(name);
int i, im = -1;
size_t num_cell, size, j;
@@ -291,13 +295,6 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const
}
}
- //Mimic questinfo
- if( map->list[m].qi_count ) {
- map->list[im].qi_count = map->list[m].qi_count;
- CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count );
- memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) );
- }
-
map->list[im].m = im;
map->list[im].instance_id = instance_id;
map->list[im].instance_src_map = m;
@@ -317,7 +314,8 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const
* party_id : source party of this instance
* type : result (0 = map id | 1 = instance id)
*--------------------------------------*/
-int instance_map2imap(int16 m, int instance_id) {
+static int instance_map2imap(int16 m, int instance_id)
+{
int i;
if( !instance->valid(instance_id) ) {
@@ -331,7 +329,8 @@ int instance_map2imap(int16 m, int instance_id) {
return -1;
}
-int instance_mapname2imap(const char *map_name, int instance_id) {
+static int instance_mapname2imap(const char *map_name, int instance_id)
+{
int i;
nullpo_retr(-1, map_name);
@@ -351,7 +350,8 @@ int instance_mapname2imap(const char *map_name, int instance_id) {
* instance_id : where to search
* result : mapid of map "m" in this instance
*--------------------------------------*/
-int instance_mapid2imapid(int16 m, int instance_id) {
+static int instance_mapid2imapid(int16 m, int instance_id)
+{
Assert_retr(-1, m >= 0 && m < map->count);
if( map->list[m].flag.src4instance == 0 )
return m; // not instances found for this map
@@ -369,7 +369,7 @@ int instance_mapid2imapid(int16 m, int instance_id) {
/*--------------------------------------
* Used on Init instance. Duplicates each script on source map
*--------------------------------------*/
-int instance_map_npcsub(struct block_list* bl, va_list args)
+static int instance_map_npcsub(struct block_list *bl, va_list args)
{
struct npc_data *nd = NULL;
int16 m = va_arg(args, int); // Destination Map
@@ -384,7 +384,7 @@ int instance_map_npcsub(struct block_list* bl, va_list args)
return 1;
}
-int instance_init_npc(struct block_list* bl, va_list args)
+static int instance_init_npc(struct block_list *bl, va_list args)
{
struct npc_data *nd = NULL;
struct event_data *ev;
@@ -405,7 +405,8 @@ int instance_init_npc(struct block_list* bl, va_list args)
/*--------------------------------------
* Init all map on the instance. Npcs are created here
*--------------------------------------*/
-void instance_init(int instance_id) {
+static void instance_init(int instance_id)
+{
int i;
if( !instance->valid(instance_id) )
@@ -424,7 +425,8 @@ void instance_init(int instance_id) {
* Used on instance deleting process.
* Warps all players on each instance map to its save points.
*--------------------------------------*/
-int instance_del_load(struct map_session_data* sd, va_list args) {
+static int instance_del_load(struct map_session_data *sd, va_list args)
+{
int16 m = va_arg(args,int);
if( !sd || sd->bl.m != m )
@@ -435,7 +437,8 @@ int instance_del_load(struct map_session_data* sd, va_list args) {
}
/* for npcs behave differently when being unloaded within a instance */
-int instance_cleanup_sub(struct block_list *bl, va_list ap) {
+static int instance_cleanup_sub(struct block_list *bl, va_list ap)
+{
nullpo_ret(bl);
switch(bl->type) {
@@ -443,7 +446,7 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) {
map->quit(BL_UCAST(BL_PC, bl));
break;
case BL_NPC:
- npc->unload(BL_UCAST(BL_NPC, bl), true);
+ npc->unload(BL_UCAST(BL_NPC, bl), true, true);
break;
case BL_MOB:
unit->free(bl,CLR_OUTSIGHT);
@@ -465,7 +468,8 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) {
/*--------------------------------------
* Removes a simple instance map
*--------------------------------------*/
-void instance_del_map(int16 m) {
+static void instance_del_map(int16 m)
+{
int i;
if( m <= 0 || map->list[m].instance_id == -1 ) {
@@ -507,8 +511,7 @@ void instance_del_map(int16 m) {
aFree(map->list[m].zone_mf);
}
- if( map->list[m].qi_data )
- aFree(map->list[m].qi_data);
+ VECTOR_CLEAR(map->list[m].qi_list);
// Remove from instance
for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) {
@@ -537,7 +540,8 @@ void instance_del_map(int16 m) {
/*--------------------------------------
* Timer to destroy instance by process or idle
*--------------------------------------*/
-int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data) {
+static int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data)
+{
instance->destroy(id);
return 0;
}
@@ -545,13 +549,14 @@ int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data) {
/*--------------------------------------
* Removes a instance, all its maps and npcs.
*--------------------------------------*/
-void instance_destroy(int instance_id) {
+static void instance_destroy(int instance_id)
+{
struct map_session_data *sd = NULL;
unsigned short *icptr = NULL;
struct party_data *p = NULL;
struct guild *g = NULL;
short *iptr = NULL;
- int type, j;
+ int type;
unsigned int now = (unsigned int)time(NULL);
if( !instance->valid(instance_id) )
@@ -596,9 +601,10 @@ void instance_destroy(int instance_id) {
}
if( iptr != NULL ) {
- ARR_FIND(0, *icptr, j, iptr[j] == instance_id);
- if( j != *icptr )
- iptr[j] = -1;
+ int i;
+ ARR_FIND(0, *icptr, i, iptr[i] == instance_id);
+ if (i != *icptr)
+ iptr[i] = -1;
}
if (instance->list[instance_id].map) {
@@ -635,7 +641,8 @@ void instance_destroy(int instance_id) {
/*--------------------------------------
* Checks if there are users in the instance or not to start idle timer
*--------------------------------------*/
-void instance_check_idle(int instance_id) {
+static void instance_check_idle(int instance_id)
+{
bool idle = true;
unsigned int now = (unsigned int)time(NULL);
@@ -660,7 +667,7 @@ void instance_check_idle(int instance_id) {
/*--------------------------------------
* Set instance Timers
*--------------------------------------*/
-void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout)
+static void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout)
{
unsigned int now = (unsigned int)time(0);
@@ -699,7 +706,8 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign
/*--------------------------------------
* Checks if sd in on a instance and should be kicked from it
*--------------------------------------*/
-void instance_check_kick(struct map_session_data *sd) {
+static void instance_check_kick(struct map_session_data *sd)
+{
int16 m = sd->bl.m;
nullpo_retv(sd);
@@ -712,7 +720,68 @@ void instance_check_kick(struct map_session_data *sd) {
}
}
-void do_reload_instance(void) {
+/**
+ * Look up existing memorial dungeon of the player and destroy it
+ *
+ * @param sd session data.
+ *
+ */
+static void instance_force_destroy(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ for (int i = 0; i < instance->instances; ++i) {
+ switch (instance->list[i].owner_type) {
+ case IOT_CHAR:
+ {
+ if (instance->list[i].owner_id != sd->status.char_id)
+ continue;
+ break;
+ }
+ case IOT_PARTY:
+ {
+ int party_id = sd->status.party_id;
+ if (instance->list[i].owner_id != party_id)
+ continue;
+ int j = 0;
+ struct party_data *pt = party->search(party_id);
+ nullpo_retv(pt);
+
+ ARR_FIND(0, MAX_PARTY, j, pt->party.member[j].leader);
+ if (j == MAX_PARTY) {
+ ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a party instance, while the party has no leader.");
+ return;
+ }
+ if (pt->party.member[j].char_id != sd->status.char_id) {
+ ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a party instance, from a non party-leader player.");
+ return;
+ }
+ break;
+ }
+ case IOT_GUILD:
+ {
+ int guild_id = sd->status.guild_id;
+ if (instance->list[i].owner_id != guild_id)
+ continue;
+ struct guild *g = guild->search(guild_id);
+ nullpo_retv(g);
+
+ if (g->member[0].char_id != sd->status.char_id) {
+ ShowWarning("clif_parse_memorial_dungeon_command: trying to destroy a guild instance, from a non guild-master player.");
+ return;
+ }
+ break;
+ }
+ default:
+ continue;
+ }
+ instance->destroy(instance->list[i].id);
+ return;
+ }
+}
+
+static void do_reload_instance(void)
+{
struct s_mapiterator *iter;
struct map_session_data *sd;
int i, k;
@@ -742,7 +811,8 @@ void do_reload_instance(void) {
mapit->free(iter);
}
-void do_final_instance(void) {
+static void do_final_instance(void)
+{
int i;
for(i = 0; i < instance->instances; i++) {
@@ -756,14 +826,16 @@ void do_final_instance(void) {
instance->instances = 0;
}
-void do_init_instance(bool minimal) {
+static void do_init_instance(bool minimal)
+{
if (minimal)
return;
timer->add_func_list(instance->destroy_timer, "instance_destroy_timer");
}
-void instance_defaults(void) {
+void instance_defaults(void)
+{
instance = &instance_s;
instance->init = do_init_instance;
@@ -791,4 +863,5 @@ void instance_defaults(void) {
instance->set_timeout = instance_set_timeout;
instance->valid = instance_is_valid;
instance->destroy_timer = instance_destroy_timer;
+ instance->force_destroy = instance_force_destroy;
}
diff --git a/src/map/instance.h b/src/map/instance.h
index 2019b1a42..8206902c1 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -96,6 +96,7 @@ struct instance_interface {
void (*set_timeout) (int instance_id, unsigned int progress_timeout, unsigned int idle_timeout);
bool (*valid) (int instance_id);
int (*destroy_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*force_destroy) (struct map_session_data *sd);
};
#ifdef HERCULES_CORE
diff --git a/src/map/intif.c b/src/map/intif.c
index ec0251dad..a420b7204 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
#include "map/atcommand.h"
#include "map/battle.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/elemental.h"
#include "map/guild.h"
@@ -38,7 +39,10 @@
#include "map/pc.h"
#include "map/pet.h"
#include "map/quest.h"
+#include "map/rodex.h"
#include "map/storage.h"
+#include "map/achievement.h"
+
#include "common/memmgr.h"
#include "common/nullpo.h"
#include "common/showmsg.h"
@@ -53,7 +57,7 @@
#include <string.h>
#include <sys/types.h>
-struct intif_interface intif_s;
+static struct intif_interface intif_s;
struct intif_interface *intif;
#define inter_fd (chrif->fd) // alias
@@ -61,37 +65,37 @@ struct intif_interface *intif;
//-----------------------------------------------------------------
// Send to inter server
-int CheckForCharServer(void)
+static int CheckForCharServer(void)
{
return ((chrif->fd <= 0) || sockt->session[chrif->fd] == NULL || sockt->session[chrif->fd]->wdata == NULL);
}
// pet
-int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
- short pet_equip,short intimate,short hungry,char rename_flag,char incubate,char *pet_name)
+static int intif_create_pet(int account_id, int char_id, int pet_class, int pet_lv, int pet_egg_id,
+ int pet_equip, short intimate, short hungry, char rename_flag, char incubate, char *pet_name)
{
if (intif->CheckForCharServer())
return 0;
nullpo_ret(pet_name);
- WFIFOHEAD(inter_fd, 24 + NAME_LENGTH);
- WFIFOW(inter_fd,0) = 0x3080;
- WFIFOL(inter_fd,2) = account_id;
- WFIFOL(inter_fd,6) = char_id;
- WFIFOW(inter_fd,10) = pet_class;
- WFIFOW(inter_fd,12) = pet_lv;
- WFIFOW(inter_fd,14) = pet_egg_id;
- WFIFOW(inter_fd,16) = pet_equip;
- WFIFOW(inter_fd,18) = intimate;
- WFIFOW(inter_fd,20) = hungry;
- WFIFOB(inter_fd,22) = rename_flag;
- WFIFOB(inter_fd,23) = incubate;
- memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH);
- WFIFOSET(inter_fd,24+NAME_LENGTH);
+ WFIFOHEAD(inter_fd, 32 + NAME_LENGTH);
+ WFIFOW(inter_fd, 0) = 0x3080;
+ WFIFOL(inter_fd, 2) = account_id;
+ WFIFOL(inter_fd, 6) = char_id;
+ WFIFOL(inter_fd, 10) = pet_class;
+ WFIFOL(inter_fd, 14) = pet_lv;
+ WFIFOL(inter_fd, 18) = pet_egg_id;
+ WFIFOL(inter_fd, 22) = pet_equip;
+ WFIFOW(inter_fd, 26) = intimate;
+ WFIFOW(inter_fd, 28) = hungry;
+ WFIFOB(inter_fd, 30) = rename_flag;
+ WFIFOB(inter_fd, 31) = incubate;
+ memcpy(WFIFOP(inter_fd, 32), pet_name, NAME_LENGTH);
+ WFIFOSET(inter_fd, 32 + NAME_LENGTH);
return 0;
}
-int intif_request_petdata(int account_id,int char_id,int pet_id)
+static int intif_request_petdata(int account_id, int char_id, int pet_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -105,7 +109,7 @@ int intif_request_petdata(int account_id,int char_id,int pet_id)
return 0;
}
-int intif_save_petdata(int account_id,struct s_pet *p)
+static int intif_save_petdata(int account_id, struct s_pet *p)
{
if (intif->CheckForCharServer())
return 0;
@@ -120,7 +124,7 @@ int intif_save_petdata(int account_id,struct s_pet *p)
return 0;
}
-int intif_delete_petdata(int pet_id)
+static int intif_delete_petdata(int pet_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -132,7 +136,7 @@ int intif_delete_petdata(int pet_id)
return 1;
}
-int intif_rename(struct map_session_data *sd, int type, const char *name)
+static int intif_rename(struct map_session_data *sd, int type, const char *name)
{
if (intif->CheckForCharServer())
return 1;
@@ -149,158 +153,8 @@ int intif_rename(struct map_session_data *sd, int type, const char *name)
return 0;
}
-// GM Send a message
-int intif_broadcast(const char* mes, size_t len, int type)
-{
- int lp = (type&BC_COLOR_MASK) ? 4 : 0;
-
- nullpo_ret(mes);
- Assert_ret(len < 32000);
- // Send to the local players
- clif->broadcast(NULL, mes, len, type, ALL_CLIENT);
-
- if (intif->CheckForCharServer())
- return 0;
-
- if (chrif->other_mapserver_count < 1)
- return 0; //No need to send.
-
- WFIFOHEAD(inter_fd, 16 + lp + len);
- WFIFOW(inter_fd,0) = 0x3000;
- WFIFOW(inter_fd,2) = 16 + lp + len;
- WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast
- WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast
- WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast
- WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast
- WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast
- if (type&BC_BLUE)
- WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow.
- else if (type&BC_WOE)
- WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'.
- memcpy(WFIFOP(inter_fd,16 + lp), mes, len);
- WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
- return 0;
-}
-
-int intif_broadcast2(const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY)
-{
- nullpo_ret(mes);
- Assert_ret(len < 32000);
- // Send to the local players
- clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT);
-
- if (intif->CheckForCharServer())
- return 0;
-
- if (chrif->other_mapserver_count < 1)
- return 0; //No need to send.
-
- WFIFOHEAD(inter_fd, 16 + len);
- WFIFOW(inter_fd,0) = 0x3000;
- WFIFOW(inter_fd,2) = 16 + len;
- WFIFOL(inter_fd,4) = fontColor;
- WFIFOW(inter_fd,8) = fontType;
- WFIFOW(inter_fd,10) = fontSize;
- WFIFOW(inter_fd,12) = fontAlign;
- WFIFOW(inter_fd,14) = fontY;
- memcpy(WFIFOP(inter_fd,16), mes, len);
- WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
- return 0;
-}
-
-/// send a message using the main chat system
-/// <sd> the source of message
-/// <message> the message that was sent
-int intif_main_message(struct map_session_data* sd, const char* message)
-{
- char output[256];
-
- nullpo_ret(sd);
- nullpo_ret(message);
-
- // format the message for main broadcasting
- snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message );
-
- // send the message using the inter-server broadcast service
- intif->broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 );
-
- // log the chat message
- logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message );
-
- return 0;
-}
-
-// The transmission of Wisp/Page to inter-server (player not found on this server)
-int intif_wis_message(struct map_session_data *sd, const char *nick, const char *mes, size_t mes_len)
-{
- if (intif->CheckForCharServer())
- return 0;
- nullpo_ret(sd);
- nullpo_ret(nick);
- nullpo_ret(mes);
-
- if (chrif->other_mapserver_count < 1) {
- //Character not found.
- clif->wis_end(sd->fd, 1);
- return 0;
- }
-
- WFIFOHEAD(inter_fd,mes_len + 52);
- WFIFOW(inter_fd,0) = 0x3001;
- WFIFOW(inter_fd,2) = mes_len + 52;
- memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH);
- memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH);
- memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len);
- WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
-
- if (battle_config.etc_log)
- ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes);
-
- return 0;
-}
-
-// The reply of Wisp/page
-int intif_wis_replay(int id, int flag)
-{
- if (intif->CheckForCharServer())
- return 0;
- WFIFOHEAD(inter_fd,7);
- WFIFOW(inter_fd,0) = 0x3002;
- WFIFOL(inter_fd,2) = id;
- WFIFOB(inter_fd,6) = flag; // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
- WFIFOSET(inter_fd,7);
-
- if (battle_config.etc_log)
- ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag);
-
- return 0;
-}
-
-// The transmission of GM only Wisp/Page from server to inter-server
-int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
-{
- size_t mes_len;
- if (intif->CheckForCharServer())
- return 0;
- nullpo_ret(wisp_name);
- nullpo_ret(mes);
- mes_len = strlen(mes) + 1; // + null
- WFIFOHEAD(inter_fd, mes_len + 32);
- WFIFOW(inter_fd,0) = 0x3003;
- WFIFOW(inter_fd,2) = mes_len + 32;
- memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH);
- WFIFOL(inter_fd,4+NAME_LENGTH) = permission;
- memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len);
- WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
-
- if (battle_config.etc_log)
- ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes);
-
- return 0;
-}
-
//Request for saving registry values.
-int intif_saveregistry(struct map_session_data *sd)
+static int intif_saveregistry(struct map_session_data *sd)
{
struct DBIterator *iter;
union DBKey key;
@@ -417,7 +271,7 @@ int intif_saveregistry(struct map_session_data *sd)
}
//Request the registries for this player.
-int intif_request_registry(struct map_session_data *sd, int flag)
+static int intif_request_registry(struct map_session_data *sd, int flag)
{
nullpo_ret(sd);
@@ -437,7 +291,137 @@ int intif_request_registry(struct map_session_data *sd, int flag)
return 0;
}
-int intif_request_guild_storage(int account_id,int guild_id)
+//=================================================================
+// Account Storage
+//-----------------------------------------------------------------
+
+/**
+ * Request the inter-server for a character's storage data.
+ * @packet 0x3010 [out] <account_id>.L
+ * @param sd [in] pointer to session data.
+ */
+static void intif_request_account_storage(const struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ /* Check for character server availability */
+ if (intif->CheckForCharServer())
+ return;
+
+ WFIFOHEAD(inter_fd, 6);
+ WFIFOW(inter_fd, 0) = 0x3010;
+ WFIFOL(inter_fd, 2) = sd->status.account_id;
+ WFIFOSET(inter_fd, 6);
+}
+
+/**
+ * Parse the reception of account storage from the inter-server.
+ * @packet 0x3805 [in] <packet_len>.W <account_id>.L <struct item[]>.P
+ * @param fd [in] file/socket descriptor.
+ */
+static void intif_parse_account_storage(int fd)
+{
+ int account_id = 0, payload_size = 0, storage_count = 0;
+ int i = 0;
+ struct map_session_data *sd = NULL;
+
+ Assert_retv(fd > 0);
+
+ payload_size = RFIFOW(fd, 2) - 8;
+
+ if ((account_id = RFIFOL(fd, 4)) == 0 || (sd = map->id2sd(account_id)) == NULL) {
+ ShowError("intif_parse_account_storage: Session pointer was null for account id %d!\n", account_id);
+ return;
+ }
+
+ if (sd->storage.received == true) {
+ ShowError("intif_parse_account_storage: Multiple calls from the inter-server received.\n");
+ return;
+ }
+
+ storage_count = (payload_size/sizeof(struct item));
+
+ VECTOR_ENSURE(sd->storage.item, storage_count, 1);
+
+ sd->storage.aggregate = storage_count; // Total items in storage.
+
+ for (i = 0; i < storage_count; i++) {
+ const struct item *it = RFIFOP(fd, 8 + i * sizeof(struct item));
+ VECTOR_PUSH(sd->storage.item, *it);
+ }
+
+ sd->storage.received = true; // Mark the storage state as received.
+ sd->storage.save = false; // Initialize the save flag as false.
+
+ pc->checkitem(sd); // re-check remaining items.
+}
+
+/**
+ * Send account storage information for saving.
+ * @packet 0x3011 [out] <packet_len>.W <account_id>.L <struct item[]>.P
+ * @param sd [in] pointer to session data.
+ */
+static void intif_send_account_storage(struct map_session_data *sd)
+{
+ int len = 0, i = 0, c = 0;
+
+ nullpo_retv(sd);
+
+ // Assert that at this point in the code, both flags are true.
+ Assert_retv(sd->storage.save == true);
+ Assert_retv(sd->storage.received == true);
+
+ if (intif->CheckForCharServer())
+ return;
+
+ len = 8 + sd->storage.aggregate * sizeof(struct item);
+
+ WFIFOHEAD(inter_fd, len);
+
+ WFIFOW(inter_fd, 0) = 0x3011;
+ WFIFOW(inter_fd, 2) = (uint16) len;
+ WFIFOL(inter_fd, 4) = sd->status.account_id;
+ for (i = 0, c = 0; i < VECTOR_LENGTH(sd->storage.item); i++) {
+ if (VECTOR_INDEX(sd->storage.item, i).nameid == 0)
+ continue;
+ memcpy(WFIFOP(inter_fd, 8 + c * sizeof(struct item)), &VECTOR_INDEX(sd->storage.item, i), sizeof(struct item));
+ c++;
+ }
+
+ WFIFOSET(inter_fd, len);
+
+ sd->storage.save = false; // Save request has been sent
+}
+
+/**
+ * Parse acknowledgement packet for the saving of an account's storage.
+ * @packet 0x3808 [in] <account_id>.L <saved_flag>.B
+ * @param fd [in] file/socket descriptor.
+ */
+static void intif_parse_account_storage_save_ack(int fd)
+{
+ int account_id = RFIFOL(fd, 2);
+ uint8 saved = RFIFOB(fd, 6);
+ struct map_session_data *sd = NULL;
+
+ Assert_retv(account_id > 0);
+ Assert_retv(fd > 0);
+
+ if ((sd = map->id2sd(account_id)) == NULL)
+ return; // character is most probably offline.
+
+ if (saved == 0) {
+ ShowError("intif_parse_account_storage_save_ack: Storage has not been saved! (AID: %d)\n", account_id);
+ sd->storage.save = true; // Flag it as unsaved, to re-attempt later
+ return;
+ }
+}
+
+//=================================================================
+// Guild Storage
+//-----------------------------------------------------------------
+
+static int intif_request_guild_storage(int account_id, int guild_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -448,7 +432,7 @@ int intif_request_guild_storage(int account_id,int guild_id)
WFIFOSET(inter_fd,10);
return 0;
}
-int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
+static int intif_send_guild_storage(int account_id, struct guild_storage *gstor)
{
if (intif->CheckForCharServer())
return 0;
@@ -464,7 +448,7 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
}
// Party creation request
-int intif_create_party(struct party_member *member, const char *name, int item, int item2)
+static int intif_create_party(struct party_member *member, const char *name, int item, int item2)
{
if (intif->CheckForCharServer())
return 0;
@@ -483,7 +467,7 @@ int intif_create_party(struct party_member *member, const char *name, int item,
}
// Party information request
-int intif_request_partyinfo(int party_id, int char_id)
+static int intif_request_partyinfo(int party_id, int char_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -496,7 +480,7 @@ int intif_request_partyinfo(int party_id, int char_id)
}
// Request to add a member to party
-int intif_party_addmember(int party_id,struct party_member *member)
+static int intif_party_addmember(int party_id, struct party_member *member)
{
if (intif->CheckForCharServer())
return 0;
@@ -511,7 +495,7 @@ int intif_party_addmember(int party_id,struct party_member *member)
}
// Request to change party configuration (exp,item share)
-int intif_party_changeoption(int party_id,int account_id,int exp,int item)
+static int intif_party_changeoption(int party_id, int account_id, int exp, int item)
{
if (intif->CheckForCharServer())
return 0;
@@ -526,7 +510,7 @@ int intif_party_changeoption(int party_id,int account_id,int exp,int item)
}
// Request to leave party
-int intif_party_leave(int party_id,int account_id, int char_id)
+static int intif_party_leave(int party_id, int account_id, int char_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -540,7 +524,8 @@ int intif_party_leave(int party_id,int account_id, int char_id)
}
// Request keeping party for new map ??
-int intif_party_changemap(struct map_session_data *sd,int online) {
+static int intif_party_changemap(struct map_session_data *sd, int online)
+{
int16 m, map_index;
if (intif->CheckForCharServer())
@@ -566,7 +551,7 @@ int intif_party_changemap(struct map_session_data *sd,int online) {
}
// Request breaking party
-int intif_break_party(int party_id)
+static int intif_break_party(int party_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -577,29 +562,8 @@ int intif_break_party(int party_id)
return 0;
}
-// Sending party chat
-int intif_party_message(int party_id,int account_id,const char *mes,int len)
-{
- if (intif->CheckForCharServer())
- return 0;
-
- if (chrif->other_mapserver_count < 1)
- return 0; //No need to send.
-
- nullpo_ret(mes);
- Assert_ret(len > 0 && len < 32000);
- WFIFOHEAD(inter_fd,len + 12);
- WFIFOW(inter_fd,0)=0x3027;
- WFIFOW(inter_fd,2)=len+12;
- WFIFOL(inter_fd,4)=party_id;
- WFIFOL(inter_fd,8)=account_id;
- memcpy(WFIFOP(inter_fd,12),mes,len);
- WFIFOSET(inter_fd,len+12);
- return 0;
-}
-
// Request a new leader for party
-int intif_party_leaderchange(int party_id,int account_id,int char_id)
+static int intif_party_leaderchange(int party_id, int account_id, int char_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -612,8 +576,83 @@ int intif_party_leaderchange(int party_id,int account_id,int char_id)
return 0;
}
+//=========================
+// Clan System
+//-------------------------
+
+/**
+ * Request clan member count
+ *
+ * @param clan_id Id of the clan to have members counted
+ * @param kick_interval Interval of the inactivity kick
+ */
+static int intif_clan_membercount(int clan_id, int kick_interval)
+{
+ if (intif->CheckForCharServer() || clan_id == 0 || kick_interval <= 0)
+ return 0;
+
+ WFIFOHEAD(inter_fd, 10);
+ WFIFOW(inter_fd, 0) = 0x3044;
+ WFIFOL(inter_fd, 2) = clan_id;
+ WFIFOL(inter_fd, 6) = kick_interval;
+ WFIFOSET(inter_fd, 10);
+ return 1;
+}
+
+static int intif_clan_kickoffline(int clan_id, int kick_interval)
+{
+ if (intif->CheckForCharServer() || clan_id == 0 || kick_interval <= 0)
+ return 0;
+
+ WFIFOHEAD(inter_fd, 10);
+ WFIFOW(inter_fd, 0) = 0x3045;
+ WFIFOL(inter_fd, 2) = clan_id;
+ WFIFOL(inter_fd, 6) = kick_interval;
+ WFIFOSET(inter_fd, 10);
+ return 1;
+}
+
+static void intif_parse_RecvClanMemberAction(int fd)
+{
+ struct clan *c;
+ int clan_id = RFIFOL(fd, 2);
+ int count = RFIFOL(fd, 6);
+
+ if ((c = clan->search(clan_id)) == NULL) {
+ ShowError("intif_parse_RecvClanMemberAction: Received invalid clan_id '%d'\n", clan_id);
+ return;
+ }
+
+ if (count < 0) {
+ ShowError("intif_parse_RecvClanMemberAction: Received invalid member count value '%d'\n", count);
+ return;
+ }
+
+ c->received = true;
+ if (c->req_count_tid != INVALID_TIMER) {
+ timer->delete(c->req_count_tid, clan->request_membercount);
+ c->req_count_tid = INVALID_TIMER;
+ }
+
+ c->member_count = count;
+ switch (c->req_state) {
+ case CLAN_REQ_AFTER_KICK:
+ if (c->req_kick_tid != INVALID_TIMER) {
+ timer->delete(c->req_kick_tid, clan->request_kickoffline);
+ c->req_kick_tid = INVALID_TIMER;
+ }
+ break;
+ case CLAN_REQ_RELOAD:
+ map->foreachpc(clan->rejoin);
+ break;
+ default:
+ break;
+ }
+ c->req_state = CLAN_REQ_NONE;
+}
+
// Request a Guild creation
-int intif_guild_create(const char *name,const struct guild_member *master)
+static int intif_guild_create(const char *name, const struct guild_member *master)
{
if (intif->CheckForCharServer())
return 0;
@@ -631,7 +670,7 @@ int intif_guild_create(const char *name,const struct guild_member *master)
}
// Request Guild information
-int intif_guild_request_info(int guild_id)
+static int intif_guild_request_info(int guild_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -643,7 +682,7 @@ int intif_guild_request_info(int guild_id)
}
// Request to add member to the guild
-int intif_guild_addmember(int guild_id,struct guild_member *m)
+static int intif_guild_addmember(int guild_id, struct guild_member *m)
{
if (intif->CheckForCharServer())
return 0;
@@ -658,7 +697,7 @@ int intif_guild_addmember(int guild_id,struct guild_member *m)
}
// Request a new leader for guild
-int intif_guild_change_gm(int guild_id, const char* name, size_t len)
+static int intif_guild_change_gm(int guild_id, const char *name, int len)
{
if (intif->CheckForCharServer())
return 0;
@@ -674,7 +713,7 @@ int intif_guild_change_gm(int guild_id, const char* name, size_t len)
}
// Request to leave guild
-int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes)
+static int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes)
{
if (intif->CheckForCharServer())
return 0;
@@ -691,24 +730,24 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha
}
//Update request / Lv online status of the guild members
-int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
+static int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class)
{
if (intif->CheckForCharServer())
return 0;
- WFIFOHEAD(inter_fd, 19);
+ WFIFOHEAD(inter_fd, 23);
WFIFOW(inter_fd, 0) = 0x3035;
WFIFOL(inter_fd, 2) = guild_id;
WFIFOL(inter_fd, 6) = account_id;
WFIFOL(inter_fd,10) = char_id;
WFIFOB(inter_fd,14) = online;
- WFIFOW(inter_fd,15) = lv;
- WFIFOW(inter_fd,17) = class_;
- WFIFOSET(inter_fd,19);
+ WFIFOL(inter_fd,15) = lv;
+ WFIFOL(inter_fd,19) = class;
+ WFIFOSET(inter_fd,23);
return 0;
}
//Guild disbanded notification
-int intif_guild_break(int guild_id)
+static int intif_guild_break(int guild_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -719,33 +758,11 @@ int intif_guild_break(int guild_id)
return 0;
}
-// Send a guild message
-int intif_guild_message(int guild_id,int account_id,const char *mes,int len)
-{
- if (intif->CheckForCharServer())
- return 0;
-
- if (chrif->other_mapserver_count < 1)
- return 0; //No need to send.
-
- nullpo_ret(mes);
- Assert_ret(len > 0 && len < 32000);
- WFIFOHEAD(inter_fd, len + 12);
- WFIFOW(inter_fd,0)=0x3037;
- WFIFOW(inter_fd,2)=len+12;
- WFIFOL(inter_fd,4)=guild_id;
- WFIFOL(inter_fd,8)=account_id;
- memcpy(WFIFOP(inter_fd,12),mes,len);
- WFIFOSET(inter_fd,len+12);
-
- return 0;
-}
-
/**
* 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)
+static int intif_guild_change_basicinfo(int guild_id, int type, const void *data, int len)
{
if (intif->CheckForCharServer())
return 0;
@@ -762,8 +779,7 @@ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
}
// Request a change of Guild member information
-int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
- int type,const void *data,int len)
+static int intif_guild_change_memberinfo(int guild_id, int account_id, int char_id, int type, const void *data, int len)
{
if (intif->CheckForCharServer())
return 0;
@@ -782,7 +798,7 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
}
// Request a change of Guild title
-int intif_guild_position(int guild_id,int idx,struct guild_position *p)
+static int intif_guild_position(int guild_id, int idx, struct guild_position *p)
{
if (intif->CheckForCharServer())
return 0;
@@ -798,7 +814,7 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p)
}
// Request an update of Guildskill skill_id
-int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max)
+static int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max)
{
if( intif->CheckForCharServer() )
return 0;
@@ -813,7 +829,7 @@ int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max)
}
// Request a new guild relationship
-int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag)
+static int intif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag)
{
if (intif->CheckForCharServer())
return 0;
@@ -829,7 +845,7 @@ int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account
}
// Request to change guild notice
-int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
+static int intif_guild_notice(int guild_id, const char *mes1, const char *mes2)
{
if (intif->CheckForCharServer())
return 0;
@@ -845,7 +861,7 @@ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
}
// Request to change guild emblem
-int intif_guild_emblem(int guild_id,int len,const char *data)
+static int intif_guild_emblem(int guild_id, int len, const char *data)
{
if (intif->CheckForCharServer())
return 0;
@@ -868,7 +884,7 @@ int intif_guild_emblem(int guild_id,int len,const char *data)
* @param num Number of castles, size of castle_ids array.
* @param castle_ids Pointer to array of castle IDs.
*/
-int intif_guild_castle_dataload(int num, int *castle_ids)
+static int intif_guild_castle_dataload(int num, int *castle_ids)
{
if (intif->CheckForCharServer())
return 0;
@@ -882,7 +898,7 @@ int intif_guild_castle_dataload(int num, int *castle_ids)
}
// Request change castle guild owner and save data
-int intif_guild_castle_datasave(int castle_id,int index, int value)
+static int intif_guild_castle_datasave(int castle_id, int index, int value)
{
if (intif->CheckForCharServer())
return 0;
@@ -899,7 +915,7 @@ int intif_guild_castle_datasave(int castle_id,int index, int value)
// Homunculus Packets send to Inter server [albator]
//-----------------------------------------------------------------
-int intif_homunculus_create(int account_id, struct s_homunculus *sh)
+static int intif_homunculus_create(int account_id, struct s_homunculus *sh)
{
if (intif->CheckForCharServer())
return 0;
@@ -913,7 +929,8 @@ int intif_homunculus_create(int account_id, struct s_homunculus *sh)
return 0;
}
-bool intif_homunculus_requestload(int account_id, int homun_id) {
+static bool intif_homunculus_requestload(int account_id, int homun_id)
+{
if (intif->CheckForCharServer())
return false;
WFIFOHEAD(inter_fd, 10);
@@ -924,7 +941,7 @@ bool intif_homunculus_requestload(int account_id, int homun_id) {
return true;
}
-int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh)
+static int intif_homunculus_requestsave(int account_id, struct s_homunculus *sh)
{
if (intif->CheckForCharServer())
return 0;
@@ -939,7 +956,7 @@ int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh)
}
-int intif_homunculus_requestdelete(int homun_id)
+static int intif_homunculus_requestdelete(int homun_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -954,98 +971,8 @@ int intif_homunculus_requestdelete(int homun_id)
//-----------------------------------------------------------------
// Packets receive from inter server
-// Wisp/Page reception // rewritten by [Yor]
-void intif_parse_WisMessage(int fd) {
- struct map_session_data* sd;
- const char *wisp_source;
- char name[NAME_LENGTH];
- int id, i;
-
- id=RFIFOL(fd,4);
-
- safestrncpy(name, RFIFOP(fd,32), NAME_LENGTH);
- sd = map->nick2sd(name);
- if(sd == NULL || strcmp(sd->status.name, name) != 0) {
- //Not found
- intif_wis_replay(id,1);
- return;
- }
- if(sd->state.ignoreAll) {
- intif_wis_replay(id, 2);
- return;
- }
- wisp_source = RFIFOP(fd,8); // speed up [Yor]
- for(i=0; i < MAX_IGNORE_LIST &&
- sd->ignore[i].name[0] != '\0' &&
- strcmp(sd->ignore[i].name, wisp_source) != 0
- ; i++);
-
- if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') {
- //Ignored
- intif_wis_replay(id, 2);
- return;
- }
- //Success to send whisper.
- clif->wis_message(sd->fd, wisp_source, RFIFOP(fd,56),RFIFOW(fd,2)-56);
- intif_wis_replay(id,0); // success
-}
-
-// Wisp/page transmission result reception
-void intif_parse_WisEnd(int fd)
-{
- struct map_session_data* sd;
- const char *playername = RFIFOP(fd, 2);
-
- if (battle_config.etc_log)
- ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", playername, RFIFOB(fd,26)); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
- sd = map->nick2sd(playername);
- if (sd != NULL)
- clif->wis_end(sd->fd, RFIFOB(fd,26));
-
- return;
-}
-
-int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) {
- int permission = va_arg(va, int);
- char *wisp_name;
- char *message;
- int len;
-
- nullpo_ret(sd);
- if (!pc_has_permission(sd, permission))
- return 0;
- wisp_name = va_arg(va, char*);
- message = va_arg(va, char*);
- len = va_arg(va, int);
- clif->wis_message(sd->fd, wisp_name, message, len);
- return 1;
-}
-
-// Received wisp message from map-server via char-server for ALL gm
-// 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.l <message>.?B
-void mapif_parse_WisToGM(int fd)
-{
- int permission, mes_len;
- char Wisp_name[NAME_LENGTH];
- char mbuf[255] = { 0 };
- char *message;
-
- mes_len = RFIFOW(fd,2) - 32;
- Assert_retv(mes_len > 0 && mes_len < 32000);
- message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf);
-
- permission = RFIFOL(fd,28);
- safestrncpy(Wisp_name, RFIFOP(fd,4), NAME_LENGTH);
- safestrncpy(message, RFIFOP(fd,32), mes_len);
- // information is sent to all online GM
- map->foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len);
-
- if (message != mbuf)
- aFree(message);
-}
-
// Request player registre
-void intif_parse_Registers(int fd)
+static void intif_parse_Registers(int fd)
{
int flag;
struct map_session_data *sd;
@@ -1111,7 +1038,7 @@ void intif_parse_Registers(int fd)
safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
cursor += len + 1;
- script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, sval, NULL);
+ script->set_reg(NULL,sd,reference_uid(script->add_variable(key), index), key, sval, NULL);
}
/**
* Vessel!
@@ -1133,7 +1060,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, (const void *)h64BPTRSIZE(ival), NULL);
+ script->set_reg(NULL,sd,reference_uid(script->add_variable(key), index), key, (const void *)h64BPTRSIZE(ival), NULL);
}
}
script->parser_current_file = NULL;/* reset */
@@ -1146,7 +1073,7 @@ void intif_parse_Registers(int fd)
pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex]
}
-void intif_parse_LoadGuildStorage(int fd)
+static void intif_parse_LoadGuildStorage(int fd)
{
struct guild_storage *gstor;
struct map_session_data *sd;
@@ -1188,13 +1115,13 @@ void intif_parse_LoadGuildStorage(int fd)
}
// ACK guild_storage saved
-void intif_parse_SaveGuildStorage(int fd)
+static void intif_parse_SaveGuildStorage(int fd)
{
gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6));
}
// ACK party creation
-void intif_parse_PartyCreated(int fd)
+static void intif_parse_PartyCreated(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party created by account %u\n\n", RFIFOL(fd,2));
@@ -1202,7 +1129,8 @@ void intif_parse_PartyCreated(int fd)
}
// Receive party info
-void intif_parse_PartyInfo(int fd) {
+static void intif_parse_PartyInfo(int fd)
+{
if (RFIFOW(fd,2) == 12) {
ShowWarning("intif: party noinfo (char_id=%u party_id=%u)\n", RFIFOL(fd,4), RFIFOL(fd,8));
party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4));
@@ -1216,7 +1144,7 @@ void intif_parse_PartyInfo(int fd) {
}
// ACK adding party member
-void intif_parse_PartyMemberAdded(int fd)
+static void intif_parse_PartyMemberAdded(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party member added Party (%u), Account(%u), Char(%u)\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
@@ -1224,13 +1152,13 @@ void intif_parse_PartyMemberAdded(int fd)
}
// ACK changing party option
-void intif_parse_PartyOptionChanged(int fd)
+static void intif_parse_PartyOptionChanged(int fd)
{
party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14));
}
// ACK member leaving party
-void intif_parse_PartyMemberWithdraw(int fd)
+static void intif_parse_PartyMemberWithdraw(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party member withdraw: Party(%u), Account(%u), Char(%u)\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
@@ -1238,28 +1166,26 @@ void intif_parse_PartyMemberWithdraw(int fd)
}
// ACK party break
-void intif_parse_PartyBroken(int fd) {
+static void intif_parse_PartyBroken(int fd)
+{
party->broken(RFIFOL(fd,2));
}
// ACK party on new map
-void intif_parse_PartyMove(int fd)
+static void intif_parse_PartyMove(int fd)
{
party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17));
}
-// ACK party messages
-void intif_parse_PartyMessage(int fd) {
- party->recv_message(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12);
-}
-
// ACK guild creation
-void intif_parse_GuildCreated(int fd) {
+static void intif_parse_GuildCreated(int fd)
+{
guild->created(RFIFOL(fd,2),RFIFOL(fd,6));
}
// ACK guild infos
-void intif_parse_GuildInfo(int fd) {
+static void intif_parse_GuildInfo(int fd)
+{
if (RFIFOW(fd,2) == 8) {
ShowWarning("intif: guild noinfo %u\n", RFIFOL(fd,4));
guild->recv_noinfo(RFIFOL(fd,4));
@@ -1272,30 +1198,35 @@ void intif_parse_GuildInfo(int fd) {
}
// ACK adding guild member
-void intif_parse_GuildMemberAdded(int fd) {
+static void intif_parse_GuildMemberAdded(int fd)
+{
if(battle_config.etc_log)
ShowInfo("intif: guild member added %u %u %u %d\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14));
guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14));
}
// ACK member leaving guild
-void intif_parse_GuildMemberWithdraw(int fd) {
+static void intif_parse_GuildMemberWithdraw(int fd)
+{
guild->member_withdraw(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14), RFIFOP(fd,55), RFIFOP(fd,15));
}
// ACK guild member basic info
-void intif_parse_GuildMemberInfoShort(int fd) {
- guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17));
+static void intif_parse_GuildMemberInfoShort(int fd)
+{
+ guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOL(fd,17),RFIFOL(fd,21));
}
// ACK guild break
-void intif_parse_GuildBroken(int fd) {
+static void intif_parse_GuildBroken(int fd)
+{
guild->broken(RFIFOL(fd,2),RFIFOB(fd,6));
}
// basic guild info change notice
// 0x3839 <packet len>.w <guild id>.l <type>.w <data>.?b
-void intif_parse_GuildBasicInfoChanged(int fd) {
+static void intif_parse_GuildBasicInfoChanged(int fd)
+{
//int len = RFIFOW(fd,2) - 10;
int guild_id = RFIFOL(fd,4);
int type = RFIFOW(fd,8);
@@ -1331,7 +1262,8 @@ void intif_parse_GuildBasicInfoChanged(int fd) {
// guild member info change notice
// 0x383a <packet len>.w <guild id>.l <account id>.l <char id>.l <type>.w <data>.?b
-void intif_parse_GuildMemberInfoChanged(int fd) {
+static void intif_parse_GuildMemberInfoChanged(int fd)
+{
//int len = RFIFOW(fd,2) - 18;
int guild_id = RFIFOL(fd,4);
int account_id = RFIFOL(fd,8);
@@ -1356,13 +1288,14 @@ void intif_parse_GuildMemberInfoChanged(int fd) {
case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break;
case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break;
case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break;
- case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break;
+ case GMI_CLASS: g->member[idx].class = RFIFOW(fd,18); break;
case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break;
}
}
// ACK change of guild title
-void intif_parse_GuildPosition(int fd) {
+static void intif_parse_GuildPosition(int fd)
+{
if (RFIFOW(fd,2)!=sizeof(struct guild_position)+12)
ShowError("intif: guild info: data size mismatch (%u) %d != %"PRIuS"\n",
RFIFOL(fd,4), RFIFOW(fd,2), sizeof(struct guild_position) + 12);
@@ -1370,47 +1303,50 @@ void intif_parse_GuildPosition(int fd) {
}
// ACK change of guild skill update
-void intif_parse_GuildSkillUp(int fd) {
+static void intif_parse_GuildSkillUp(int fd)
+{
guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
}
// ACK change of guild relationship
-void intif_parse_GuildAlliance(int fd) {
+static void intif_parse_GuildAlliance(int fd)
+{
guild->allianceack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOB(fd,18), RFIFOP(fd,19), RFIFOP(fd,43));
}
// ACK change of guild notice
-void intif_parse_GuildNotice(int fd) {
+static void intif_parse_GuildNotice(int fd)
+{
guild->notice_changed(RFIFOL(fd,2), RFIFOP(fd,6), RFIFOP(fd,66));
}
// ACK change of guild emblem
-void intif_parse_GuildEmblem(int fd) {
+static void intif_parse_GuildEmblem(int fd)
+{
guild->emblem_changed(RFIFOW(fd,2)-12, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12));
}
-// ACK guild message
-void intif_parse_GuildMessage(int fd) {
- guild->recv_message(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12);
-}
-
// Reply guild castle data request
-void intif_parse_GuildCastleDataLoad(int fd) {
+static void intif_parse_GuildCastleDataLoad(int fd)
+{
guild->castledataloadack(RFIFOW(fd,2), RFIFOP(fd,4));
}
// ACK change of guildmaster
-void intif_parse_GuildMasterChanged(int fd) {
+static void intif_parse_GuildMasterChanged(int fd)
+{
guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
}
// Request pet creation
-void intif_parse_CreatePet(int fd) {
- pet->get_egg(RFIFOL(fd,2), RFIFOW(fd,6), RFIFOL(fd,8));
+static void intif_parse_CreatePet(int fd)
+{
+ pet->get_egg(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10));
}
// ACK pet data
-void intif_parse_RecvPetData(int fd) {
+static void intif_parse_RecvPetData(int fd)
+{
struct s_pet p;
int len;
len=RFIFOW(fd,2);
@@ -1424,19 +1360,21 @@ void intif_parse_RecvPetData(int fd) {
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
// ACK pet save data
-void intif_parse_SavePetOk(int fd) {
+static void intif_parse_SavePetOk(int fd)
+{
if(RFIFOB(fd,6) == 1)
ShowError("pet data save failure\n");
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
// ACK deleting pet
-void intif_parse_DeletePetOk(int fd) {
+static void intif_parse_DeletePetOk(int fd)
+{
if(RFIFOB(fd,2) == 1)
ShowError("pet data delete failure\n");
}
// ACK changing name request, players,pets,homun
-void intif_parse_ChangeNameOk(int fd)
+static void intif_parse_ChangeNameOk(int fd)
{
struct map_session_data *sd = NULL;
if((sd=map->id2sd(RFIFOL(fd,2)))==NULL ||
@@ -1459,7 +1397,8 @@ void intif_parse_ChangeNameOk(int fd)
//----------------------------------------------------------------
// Homunculus recv packets [albator]
-void intif_parse_CreateHomunculus(int fd) {
+static void intif_parse_CreateHomunculus(int fd)
+{
int len = RFIFOW(fd,2)-9;
if (sizeof(struct s_homunculus) != len) {
if (battle_config.etc_log)
@@ -1469,7 +1408,8 @@ void intif_parse_CreateHomunculus(int fd) {
homun->recv_data(RFIFOL(fd,4), RFIFOP(fd,9), RFIFOB(fd,8)) ;
}
-void intif_parse_RecvHomunculusData(int fd) {
+static void intif_parse_RecvHomunculusData(int fd)
+{
int len = RFIFOW(fd,2)-9;
if (sizeof(struct s_homunculus) != len) {
@@ -1481,29 +1421,122 @@ void intif_parse_RecvHomunculusData(int fd) {
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_SaveHomunculusOk(int fd) {
+static void intif_parse_SaveHomunculusOk(int fd)
+{
if(RFIFOB(fd,6) != 1)
ShowError("homunculus data save failure for account %u\n", RFIFOL(fd,2));
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_DeleteHomunculusOk(int fd) {
+static void intif_parse_DeleteHomunculusOk(int fd)
+{
if(RFIFOB(fd,2) != 1)
ShowError("Homunculus data delete failure\n");
}
-/**************************************
+/***************************************
+ * ACHIEVEMENT SYSTEM FUNCTIONS
+ ***************************************/
+/**
+ * Sends a request to the inter-server to load
+ * and send a character's achievement data.
+ * @packet [out] 0x3012 <char_id>.L
+ * @param sd pointer to map_session_data.
+ */
+static void intif_achievements_request(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
-QUESTLOG SYSTEM FUNCTIONS
+ if (intif->CheckForCharServer())
+ return;
-***************************************/
+ WFIFOHEAD(inter_fd, 6);
+ WFIFOW(inter_fd, 0) = 0x3012;
+ WFIFOL(inter_fd, 2) = sd->status.char_id;
+ WFIFOSET(inter_fd, 6);
+}
+
+/**
+ * Handles reception of achievement data for a character from the inter-server.
+ * @packet [in] 0x3810 <packet_len>.W <char_id>.L <char_achievements[]>.P
+ * @param fd socket descriptor.
+ */
+static void intif_parse_achievements_load(int fd)
+{
+ int size = RFIFOW(fd, 2);
+ int char_id = RFIFOL(fd, 4);
+ int payload_count = (size - 8) / sizeof(struct achievement);
+ struct map_session_data *sd = map->charid2sd(char_id);
+ int i = 0;
+
+ if (sd == NULL) {
+ ShowError("intif_parse_achievements_load: Parse request for achievements received but character is offline!\n");
+ return;
+ }
+
+ if (VECTOR_LENGTH(sd->achievement) > 0) {
+ ShowError("intif_parse_achievements_load: Achievements already loaded! Possible multiple calls from the inter-server received.\n");
+ return;
+ }
+
+ VECTOR_ENSURE(sd->achievement, payload_count, 1);
+
+ for (i = 0; i < payload_count; i++) {
+ struct achievement t_ach = { 0 };
+
+ memcpy(&t_ach, RFIFOP(fd, 8 + i * sizeof(struct achievement)), sizeof(struct achievement));
+
+ if (achievement->get(t_ach.id) == NULL) {
+ ShowError("intif_parse_achievements_load: Invalid Achievement %d received from character %d. Ignoring...\n", t_ach.id, char_id);
+ continue;
+ }
+
+ VECTOR_PUSH(sd->achievement, t_ach);
+ }
+
+ achievement->init_titles(sd);
+ clif->achievement_send_list(fd, sd);
+ sd->achievements_received = true;
+}
+
+/**
+ * Send character's achievement data to the inter-server.
+ * @packet 0x3013 <packet_len>.W <char_id>.L <achievements[]>.P
+ * @param sd pointer to map session data.
+ */
+static void intif_achievements_save(struct map_session_data *sd)
+{
+ int packet_len = 0, payload_size = 0, i = 0;
+
+ nullpo_retv(sd);
+ /* check for character server. */
+ if (intif->CheckForCharServer())
+ return;
+ /* Return if no data. */
+ if (!(payload_size = VECTOR_LENGTH(sd->achievement) * sizeof(struct achievement)))
+ return;
+
+ packet_len = payload_size + 8;
+
+ WFIFOHEAD(inter_fd, packet_len);
+ WFIFOW(inter_fd, 0) = 0x3013;
+ WFIFOW(inter_fd, 2) = packet_len;
+ WFIFOL(inter_fd, 4) = sd->status.char_id;
+ for (i = 0; i < VECTOR_LENGTH(sd->achievement); i++)
+ memcpy(WFIFOP(inter_fd, 8 + i * sizeof(struct achievement)), &VECTOR_INDEX(sd->achievement, i), sizeof(struct achievement));
+ WFIFOSET(inter_fd, packet_len);
+}
+
+/**************************************
+ * QUESTLOG SYSTEM FUNCTIONS *
+ **************************************/
/**
* Requests a character's quest log entries to the inter server.
*
* @param sd Character's data
*/
-void intif_request_questlog(struct map_session_data *sd)
+static void intif_request_questlog(struct map_session_data *sd)
{
nullpo_retv(sd);
WFIFOHEAD(inter_fd,6);
@@ -1519,7 +1552,8 @@ void intif_request_questlog(struct map_session_data *sd)
*
* @see intif_parse
*/
-void intif_parse_QuestLog(int fd) {
+static void intif_parse_QuestLog(int fd)
+{
int char_id = RFIFOL(fd, 4), num_received = (RFIFOW(fd, 2)-8)/sizeof(struct quest);
struct map_session_data *sd = map->charid2sd(char_id);
@@ -1574,7 +1608,8 @@ void intif_parse_QuestLog(int fd) {
*
* @see intif_parse
*/
-void intif_parse_QuestSave(int fd) {
+static void intif_parse_QuestSave(int fd)
+{
int cid = RFIFOL(fd, 2);
struct map_session_data *sd = map->id2sd(cid);
@@ -1590,7 +1625,7 @@ void intif_parse_QuestSave(int fd) {
* @param sd Character's data
* @return 0 in case of success, nonzero otherwise
*/
-int intif_quest_save(struct map_session_data *sd)
+static int intif_quest_save(struct map_session_data *sd)
{
int len = sizeof(struct quest)*sd->num_quests + 8;
@@ -1617,7 +1652,7 @@ int intif_quest_save(struct map_session_data *sd)
* Inbox Request
* flag: 0 Update Inbox | 1 OpenMail
*------------------------------------------*/
-int intif_Mail_requestinbox(int char_id, unsigned char flag)
+static int intif_Mail_requestinbox(int char_id, unsigned char flag)
{
if (intif->CheckForCharServer())
return 0;
@@ -1631,7 +1666,8 @@ int intif_Mail_requestinbox(int char_id, unsigned char flag)
return 0;
}
-void intif_parse_MailInboxReceived(int fd) {
+static void intif_parse_MailInboxReceived(int fd)
+{
struct map_session_data *sd;
unsigned char flag = RFIFOB(fd,8);
@@ -1654,13 +1690,13 @@ void intif_parse_MailInboxReceived(int fd) {
else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) {
char output[128];
sprintf(output, msg_sd(sd,510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
}
/*------------------------------------------
* Mail Read
*------------------------------------------*/
-int intif_Mail_read(int mail_id)
+static int intif_Mail_read(int mail_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -1675,7 +1711,7 @@ int intif_Mail_read(int mail_id)
/*------------------------------------------
* Get Attachment
*------------------------------------------*/
-int intif_Mail_getattach(int char_id, int mail_id)
+static int intif_Mail_getattach(int char_id, int mail_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -1689,7 +1725,8 @@ int intif_Mail_getattach(int char_id, int mail_id)
return 0;
}
-void intif_parse_MailGetAttach(int fd) {
+static void intif_parse_MailGetAttach(int fd)
+{
struct map_session_data *sd;
struct item item;
int zeny = RFIFOL(fd,8);
@@ -1714,7 +1751,7 @@ void intif_parse_MailGetAttach(int fd) {
/*------------------------------------------
* Delete Message
*------------------------------------------*/
-int intif_Mail_delete(int char_id, int mail_id)
+static int intif_Mail_delete(int char_id, int mail_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -1728,7 +1765,8 @@ int intif_Mail_delete(int char_id, int mail_id)
return 0;
}
-void intif_parse_MailDelete(int fd) {
+static void intif_parse_MailDelete(int fd)
+{
struct map_session_data *sd;
int char_id = RFIFOL(fd,2);
int mail_id = RFIFOL(fd,6);
@@ -1756,7 +1794,7 @@ void intif_parse_MailDelete(int fd) {
/*------------------------------------------
* Return Message
*------------------------------------------*/
-int intif_Mail_return(int char_id, int mail_id)
+static int intif_Mail_return(int char_id, int mail_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -1770,7 +1808,8 @@ int intif_Mail_return(int char_id, int mail_id)
return 0;
}
-void intif_parse_MailReturn(int fd) {
+static void intif_parse_MailReturn(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int mail_id = RFIFOL(fd,6);
short fail = RFIFOB(fd,10);
@@ -1797,7 +1836,7 @@ void intif_parse_MailReturn(int fd) {
/*------------------------------------------
* Send Mail
*------------------------------------------*/
-int intif_Mail_send(int account_id, struct mail_message *msg)
+static int intif_Mail_send(int account_id, struct mail_message *msg)
{
int len = sizeof(struct mail_message) + 8;
@@ -1815,7 +1854,8 @@ int intif_Mail_send(int account_id, struct mail_message *msg)
return 1;
}
-void intif_parse_MailSend(int fd) {
+static void intif_parse_MailSend(int fd)
+{
struct mail_message msg;
struct map_session_data *sd;
bool fail;
@@ -1841,7 +1881,8 @@ void intif_parse_MailSend(int fd) {
}
}
-void intif_parse_MailNew(int fd) {
+static void intif_parse_MailNew(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int mail_id = RFIFOL(fd,6);
const char *sender_name = RFIFOP(fd,10);
@@ -1858,7 +1899,7 @@ void intif_parse_MailNew(int fd) {
* AUCTION SYSTEM
* By Zephyrus
*==========================================*/
-int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page)
+static int intif_Auction_requestlist(int char_id, short type, int price, const char *searchtext, short page)
{
int len = NAME_LENGTH + 16;
@@ -1879,7 +1920,8 @@ int intif_Auction_requestlist(int char_id, short type, int price, const char* se
return 0;
}
-void intif_parse_AuctionResults(int fd) {
+static void intif_parse_AuctionResults(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,4));
short count = RFIFOW(fd,8);
short pages = RFIFOW(fd,10);
@@ -1891,7 +1933,7 @@ void intif_parse_AuctionResults(int fd) {
clif->auction_results(sd, count, pages, data);
}
-int intif_Auction_register(struct auction_data *auction)
+static int intif_Auction_register(struct auction_data *auction)
{
int len = sizeof(struct auction_data) + 4;
@@ -1908,7 +1950,8 @@ int intif_Auction_register(struct auction_data *auction)
return 1;
}
-void intif_parse_AuctionRegister(int fd) {
+static void intif_parse_AuctionRegister(int fd)
+{
struct map_session_data *sd;
struct auction_data auction;
@@ -1935,7 +1978,7 @@ void intif_parse_AuctionRegister(int fd) {
}
}
-int intif_Auction_cancel(int char_id, unsigned int auction_id)
+static int intif_Auction_cancel(int char_id, unsigned int auction_id)
{
if( intif->CheckForCharServer() )
return 0;
@@ -1949,7 +1992,8 @@ int intif_Auction_cancel(int char_id, unsigned int auction_id)
return 0;
}
-void intif_parse_AuctionCancel(int fd) {
+static void intif_parse_AuctionCancel(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int result = RFIFOB(fd,6);
@@ -1964,7 +2008,7 @@ void intif_parse_AuctionCancel(int fd) {
}
}
-int intif_Auction_close(int char_id, unsigned int auction_id)
+static int intif_Auction_close(int char_id, unsigned int auction_id)
{
if( intif->CheckForCharServer() )
return 0;
@@ -1978,7 +2022,8 @@ int intif_Auction_close(int char_id, unsigned int auction_id)
return 0;
}
-void intif_parse_AuctionClose(int fd) {
+static void intif_parse_AuctionClose(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
unsigned char result = RFIFOB(fd,6);
@@ -1993,7 +2038,7 @@ void intif_parse_AuctionClose(int fd) {
}
}
-int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid)
+static int intif_Auction_bid(int char_id, const char *name, unsigned int auction_id, int bid)
{
int len = 16 + NAME_LENGTH;
@@ -2013,7 +2058,8 @@ int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, in
return 0;
}
-void intif_parse_AuctionBid(int fd) {
+static void intif_parse_AuctionBid(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int bid = RFIFOL(fd,6);
unsigned char result = RFIFOB(fd,10);
@@ -2032,7 +2078,8 @@ void intif_parse_AuctionBid(int fd) {
}
// Used to send 'You have won the auction' and 'You failed to won the auction' messages
-void intif_parse_AuctionMessage(int fd) {
+static void intif_parse_AuctionMessage(int fd)
+{
struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
unsigned char result = RFIFOB(fd,6);
@@ -2045,7 +2092,7 @@ void intif_parse_AuctionMessage(int fd) {
/*==========================================
* Mercenary's System
*------------------------------------------*/
-int intif_mercenary_create(struct s_mercenary *merc)
+static int intif_mercenary_create(struct s_mercenary *merc)
{
int size = sizeof(struct s_mercenary) + 4;
@@ -2061,7 +2108,8 @@ int intif_mercenary_create(struct s_mercenary *merc)
return 0;
}
-void intif_parse_MercenaryReceived(int fd) {
+static void intif_parse_MercenaryReceived(int fd)
+{
int len = RFIFOW(fd,2) - 5;
if (sizeof(struct s_mercenary) != len) {
@@ -2073,7 +2121,7 @@ void intif_parse_MercenaryReceived(int fd) {
mercenary->data_received(RFIFOP(fd,5), RFIFOB(fd,4));
}
-int intif_mercenary_request(int merc_id, int char_id)
+static int intif_mercenary_request(int merc_id, int char_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -2086,7 +2134,7 @@ int intif_mercenary_request(int merc_id, int char_id)
return 0;
}
-int intif_mercenary_delete(int merc_id)
+static int intif_mercenary_delete(int merc_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -2098,12 +2146,13 @@ int intif_mercenary_delete(int merc_id)
return 0;
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_MercenaryDeleted(int fd) {
+static void intif_parse_MercenaryDeleted(int fd)
+{
if( RFIFOB(fd,2) != 1 )
ShowError("Mercenary data delete failure\n");
}
-int intif_mercenary_save(struct s_mercenary *merc)
+static int intif_mercenary_save(struct s_mercenary *merc)
{
int size = sizeof(struct s_mercenary) + 4;
@@ -2119,7 +2168,8 @@ int intif_mercenary_save(struct s_mercenary *merc)
return 0;
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_MercenarySaved(int fd) {
+static void intif_parse_MercenarySaved(int fd)
+{
if( RFIFOB(fd,2) != 1 )
ShowError("Mercenary data save failure\n");
}
@@ -2127,7 +2177,7 @@ void intif_parse_MercenarySaved(int fd) {
/*==========================================
* Elemental's System
*------------------------------------------*/
-int intif_elemental_create(struct s_elemental *ele)
+static int intif_elemental_create(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
@@ -2143,7 +2193,8 @@ int intif_elemental_create(struct s_elemental *ele)
return 0;
}
-void intif_parse_ElementalReceived(int fd) {
+static void intif_parse_ElementalReceived(int fd)
+{
int len = RFIFOW(fd,2) - 5;
if (sizeof(struct s_elemental) != len) {
@@ -2155,7 +2206,7 @@ void intif_parse_ElementalReceived(int fd) {
elemental->data_received(RFIFOP(fd,5), RFIFOB(fd,4));
}
-int intif_elemental_request(int ele_id, int char_id)
+static int intif_elemental_request(int ele_id, int char_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -2168,7 +2219,7 @@ int intif_elemental_request(int ele_id, int char_id)
return 0;
}
-int intif_elemental_delete(int ele_id)
+static int intif_elemental_delete(int ele_id)
{
if (intif->CheckForCharServer())
return 0;
@@ -2180,12 +2231,13 @@ int intif_elemental_delete(int ele_id)
return 0;
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_ElementalDeleted(int fd) {
+static void intif_parse_ElementalDeleted(int fd)
+{
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data delete failure\n");
}
-int intif_elemental_save(struct s_elemental *ele)
+static int intif_elemental_save(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
@@ -2201,12 +2253,14 @@ int intif_elemental_save(struct s_elemental *ele)
return 0;
}
/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
-void intif_parse_ElementalSaved(int fd) {
+static void intif_parse_ElementalSaved(int fd)
+{
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data save failure\n");
}
-void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) {
+static void intif_request_accinfo(int u_fd, int aid, int group_lv, char *query)
+{
nullpo_retv(query);
WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
@@ -2221,7 +2275,8 @@ void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) {
return;
}
-void intif_parse_MessageToFD(int fd) {
+static void intif_parse_MessageToFD(int fd)
+{
int u_fd = RFIFOL(fd,4);
Assert_retv(sockt->session_is_valid(u_fd));
@@ -2242,7 +2297,8 @@ void intif_parse_MessageToFD(int fd) {
/*==========================================
* Item Bound System [Xantara][Mhalicot]
*------------------------------------------*/
-void intif_itembound_req(int char_id,int aid,int guild_id) {
+static void intif_itembound_req(int char_id, int aid, int guild_id)
+{
#ifdef GP_BOUND_ITEMS
struct guild_storage *gstor = idb_get(gstorage->db,guild_id);
WFIFOHEAD(inter_fd,12);
@@ -2257,7 +2313,8 @@ void intif_itembound_req(int char_id,int aid,int guild_id) {
}
//3856
-void intif_parse_Itembound_ack(int fd) {
+static void intif_parse_Itembound_ack(int fd)
+{
#ifdef GP_BOUND_ITEMS
struct guild_storage *gstor;
int guild_id = RFIFOW(fd,6);
@@ -2267,11 +2324,277 @@ void intif_parse_Itembound_ack(int fd) {
gstor->lock = 0; //Unlock now that operation is completed
#endif
}
+
+/*==========================================
+ * RoDEX System
+ *==========================================*/
+
+/*------------------------------------------
+ * Mail List
+ *------------------------------------------*/
+
+// Rodex Inbox Request
+// char_id: char_id
+// account_id: account_id (used by account mail)
+// flag: 0 - Open/Refresh ; 1 = Next Page
+static int intif_rodex_requestinbox(int char_id, int account_id, int8 flag, int8 opentype, int64 mail_id)
+{
+ if (intif->CheckForCharServer())
+ return 0;
+
+ WFIFOHEAD(inter_fd, 20);
+ WFIFOW(inter_fd, 0) = 0x3095;
+ WFIFOL(inter_fd, 2) = char_id;
+ WFIFOL(inter_fd, 6) = account_id;
+ WFIFOL(inter_fd, 10) = flag;
+ WFIFOB(inter_fd, 11) = opentype;
+ WFIFOQ(inter_fd, 12) = mail_id;
+ WFIFOSET(inter_fd, 20);
+
+ return 0;
+}
+
+static void intif_parse_RequestRodexOpenInbox(int fd)
+{
+ struct map_session_data *sd;
+#if PACKETVER < 20170419
+ int8 opentype = RFIFOB(fd, 8);
+#endif
+ int8 flag = RFIFOB(fd, 9);
+ int8 is_end = RFIFOB(fd, 10);
+ int is_first = RFIFOB(fd, 11);
+ int count = RFIFOL(fd, 12);
+#if PACKETVER >= 20170419
+ int64 mail_id = RFIFOQ(fd, 16);
+#endif
+ int i, j;
+
+ sd = map->charid2sd(RFIFOL(fd, 4));
+
+ if (sd == NULL) // user is not online anymore
+ return;
+
+ if (is_first == false && sd->rodex.total == 0) {
+ ShowError("intif_parse_RodexInboxOpenReceived: mail list received in wrong order.\n");
+ return;
+ }
+
+ if (is_first)
+ sd->rodex.total = count;
+ else
+ sd->rodex.total += count;
+
+ if (RFIFOW(fd, 2) - 24 != count * sizeof(struct rodex_message)) {
+ ShowError("intif_parse_RodexInboxOpenReceived: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd, 2) - 24, count * sizeof(struct rodex_message));
+ return;
+ }
+
+ if (flag == 0 && is_first)
+ VECTOR_CLEAR(sd->rodex.messages);
+
+ for (i = 0, j = 24; i < count; ++i, j += sizeof(struct rodex_message)) {
+ struct rodex_message msg = { 0 };
+ VECTOR_ENSURE(sd->rodex.messages, 1, 1);
+ memcpy(&msg, RFIFOP(fd, j), sizeof(struct rodex_message));
+ VECTOR_PUSH(sd->rodex.messages, msg);
+ }
+
+ if (is_end == true) {
+#if PACKETVER >= 20170419
+ clif->rodex_send_mails_all(sd->fd, sd, mail_id);
+#else
+ if (flag == 0)
+ clif->rodex_send_maillist(sd->fd, sd, opentype, VECTOR_LENGTH(sd->rodex.messages) - 1);
+ else
+ clif->rodex_send_refresh(sd->fd, sd, opentype, count);
+#endif
+ }
+}
+
+/*------------------------------------------
+ * Notifications
+ *------------------------------------------*/
+static int intif_rodex_hasnew(struct map_session_data *sd)
+{
+ nullpo_retr(0, sd);
+
+ if (intif->CheckForCharServer())
+ return 0;
+
+ WFIFOHEAD(inter_fd, 10);
+ WFIFOW(inter_fd, 0) = 0x3096;
+ WFIFOL(inter_fd, 2) = sd->status.char_id;
+ WFIFOL(inter_fd, 6) = sd->status.account_id;
+ WFIFOSET(inter_fd, 10);
+
+ return 0;
+}
+
+static void intif_parse_RodexNotifications(int fd)
+{
+ struct map_session_data *sd;
+ bool has_messages;
+
+ sd = map->charid2sd(RFIFOL(fd, 2));
+ has_messages = RFIFOB(fd, 6);
+
+ if (sd == NULL) // user is not online anymore
+ return;
+
+ clif->rodex_icon(sd->fd, has_messages);
+}
+
+/*------------------------------------------
+ * Update Mail
+ *------------------------------------------*/
+
+/// Updates a mail
+/// flag:
+/// 0 - receiver Read
+/// 1 - user got Zeny
+/// 2 - user got Items
+/// 3 - delete
+/// 4 - sender Read (returned mail)
+static int intif_rodex_updatemail(struct map_session_data *sd, int64 mail_id, uint8 opentype, int8 flag)
+{
+ nullpo_ret(sd);
+
+ if (intif->CheckForCharServer())
+ return 0;
+
+ WFIFOHEAD(inter_fd, 20);
+ WFIFOW(inter_fd, 0) = 0x3097;
+ WFIFOL(inter_fd, 2) = sd->status.account_id;
+ WFIFOL(inter_fd, 6) = sd->status.char_id;
+ WFIFOQ(inter_fd, 10) = mail_id;
+ WFIFOB(inter_fd, 18) = opentype;
+ WFIFOB(inter_fd, 19) = flag;
+ WFIFOSET(inter_fd, 20);
+
+ return 0;
+}
+
+/*------------------------------------------
+ * Send Mail
+ *------------------------------------------*/
+static int intif_rodex_sendmail(struct rodex_message *msg)
+{
+ if (intif->CheckForCharServer())
+ return 0;
+
+ nullpo_retr(0, msg);
+
+ WFIFOHEAD(inter_fd, 4 + sizeof(struct rodex_message));
+ WFIFOW(inter_fd, 0) = 0x3098;
+ WFIFOW(inter_fd, 2) = 4 + sizeof(struct rodex_message);
+ memcpy(WFIFOP(inter_fd, 4), msg, sizeof(struct rodex_message));
+ WFIFOSET(inter_fd, 4 + sizeof(struct rodex_message));
+
+ return 0;
+}
+
+static void intif_parse_RodexSendMail(int fd)
+{
+ struct map_session_data *ssd = NULL, *rsd = NULL;
+ int sender_id = RFIFOL(fd, 2);
+ int receiver_id = RFIFOL(fd, 6);
+ int receiver_accountid = RFIFOL(fd, 10);
+
+ if (sender_id > 0)
+ ssd = map->charid2sd(sender_id);
+
+ if (receiver_id > 0)
+ rsd = map->charid2sd(receiver_id);
+ else if (receiver_accountid > 0)
+ rsd = map->id2sd(receiver_accountid);
+
+ rodex->send_mail_result(ssd, rsd, RFIFOL(fd, 14));
+}
+
+/*------------------------------------------
+ * Check Player
+ *------------------------------------------*/
+static int intif_rodex_checkname(struct map_session_data *sd, const char *name)
+{
+ if (intif->CheckForCharServer())
+ return 0;
+
+ nullpo_retr(0, sd);
+ nullpo_retr(0, name);
+
+ WFIFOHEAD(inter_fd, 6 + NAME_LENGTH);
+ WFIFOW(inter_fd, 0) = 0x3099;
+ WFIFOL(inter_fd, 2) = sd->status.char_id;
+ safestrncpy(WFIFOP(inter_fd, 6), name, NAME_LENGTH);
+ WFIFOSET(inter_fd, 6 + NAME_LENGTH);
+
+ return 0;
+}
+
+static void intif_parse_RodexCheckName(int fd)
+{
+ struct map_session_data *sd = NULL;
+ int reqchar_id = RFIFOL(fd, 2);
+ int target_char_id = RFIFOL(fd, 6);
+ int target_class = RFIFOL(fd, 10);
+ int target_level = RFIFOL(fd, 14);
+ char name[NAME_LENGTH];
+
+ safestrncpy(name, RFIFOP(inter_fd, 18), NAME_LENGTH);
+
+ if (reqchar_id <= 0)
+ return;
+
+ sd = map->charid2sd(reqchar_id);
+
+ if (sd == NULL) // User is not online anymore
+ return;
+
+ if (target_char_id == 0) {
+ clif->rodex_checkname_result(sd, 0, 0, 0, name);
+ return;
+ }
+
+ sd->rodex.tmp.receiver_id = target_char_id;
+ safestrncpy(sd->rodex.tmp.receiver_name, name, NAME_LENGTH);
+
+ clif->rodex_checkname_result(sd, target_char_id, target_class, target_level, name);
+}
+
+static void intif_parse_GetZenyAck(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+ int64 zeny = RFIFOL(fd, 6);
+ int64 mail_id = RFIFOQ(fd, 14);
+ uint8 opentype = RFIFOB(fd, 22);
+ struct map_session_data *sd = map->charid2sd(char_id);
+
+ if (sd == NULL) // User is not online anymore
+ return;
+ rodex->getZenyAck(sd, mail_id, opentype, zeny);
+}
+
+static void intif_parse_GetItemsAck(int fd)
+{
+ int char_id = RFIFOL(fd, 2);
+
+ struct map_session_data *sd = map->charid2sd(char_id);
+ if (sd == NULL) // User is not online anymore
+ return;
+
+ int64 mail_id = RFIFOQ(fd, 6);
+ uint8 opentype = RFIFOB(fd, 14);
+ int count = RFIFOB(fd, 15);
+ struct rodex_item items[RODEX_MAX_ITEM];
+ memcpy(&items[0], RFIFOP(fd, 16), sizeof(struct rodex_item) * RODEX_MAX_ITEM);
+ rodex->getItemsAck(sd, mail_id, opentype, count, &items[0]);
+}
+
//-----------------------------------------------------------------
// Communication from the inter server
// Return a 0 (false) if there were any errors.
// 1, 2 if there are not enough to return the length of the packet if the packet processing
-int intif_parse(int fd)
+static int intif_parse(int fd)
{
int packet_len, cmd;
cmd = RFIFOW(fd,0);
@@ -2293,18 +2616,12 @@ int intif_parse(int fd)
}
// Processing branch
switch(cmd){
- case 0x3800:
- if (RFIFOL(fd,4) == 0xFF000000) //Normal announce.
- clif->broadcast(NULL, RFIFOP(fd,16), packet_len-16, BC_DEFAULT, ALL_CLIENT);
- else //Color announce.
- clif->broadcast2(NULL, RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT);
- break;
- case 0x3801: intif->pWisMessage(fd); break;
- case 0x3802: intif->pWisEnd(fd); break;
- case 0x3803: intif->pWisToGM(fd); break;
case 0x3804: intif->pRegisters(fd); break;
+ case 0x3805: intif->pAccountStorage(fd); break;
case 0x3806: intif->pChangeNameOk(fd); break;
case 0x3807: intif->pMessageToFD(fd); break;
+ case 0x3808: intif->pAccountStorageSaveAck(fd); break;
+ case 0x3810: intif->pAchievementsLoad(fd); break;
case 0x3818: intif->pLoadGuildStorage(fd); break;
case 0x3819: intif->pSaveGuildStorage(fd); break;
case 0x3820: intif->pPartyCreated(fd); break;
@@ -2314,14 +2631,12 @@ int intif_parse(int fd)
case 0x3824: intif->pPartyMemberWithdraw(fd); break;
case 0x3825: intif->pPartyMove(fd); break;
case 0x3826: intif->pPartyBroken(fd); break;
- case 0x3827: intif->pPartyMessage(fd); break;
case 0x3830: intif->pGuildCreated(fd); break;
case 0x3831: intif->pGuildInfo(fd); break;
case 0x3832: intif->pGuildMemberAdded(fd); break;
case 0x3834: intif->pGuildMemberWithdraw(fd); break;
case 0x3835: intif->pGuildMemberInfoShort(fd); break;
case 0x3836: intif->pGuildBroken(fd); break;
- case 0x3837: intif->pGuildMessage(fd); break;
case 0x3839: intif->pGuildBasicInfoChanged(fd); break;
case 0x383a: intif->pGuildMemberInfoChanged(fd); break;
case 0x383b: intif->pGuildPosition(fd); break;
@@ -2375,6 +2690,17 @@ int intif_parse(int fd)
case 0x3891: intif->pRecvHomunculusData(fd); break;
case 0x3892: intif->pSaveHomunculusOk(fd); break;
case 0x3893: intif->pDeleteHomunculusOk(fd); break;
+
+ // RoDEX
+ case 0x3895: intif->pRequestRodexOpenInbox(fd); break;
+ case 0x3896: intif->pRodexHasNew(fd); break;
+ case 0x3897: intif->pRodexSendMail(fd); break;
+ case 0x3898: intif->pRodexCheckName(fd); break;
+ case 0x3899: intif->pGetZenyAck(fd); break;
+ case 0x389a: intif->pGetItemsAck(fd); break;
+
+ // Clan System
+ case 0x3858: intif->pRecvClanMemberAction(fd); break;
default:
ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0));
return 0;
@@ -2385,22 +2711,23 @@ int intif_parse(int fd)
}
/*=====================================
-* Default Functions : intif.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void intif_defaults(void) {
+ * Default Functions : intif.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void intif_defaults(void)
+{
const int packet_len_table [INTIF_PACKET_LEN_TABLE_SIZE] = {
- -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
- 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
- 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
- 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
+ 0, 0, 0, 0, -1,-1,37,-1, 7, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
+ -1, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 Achievements [Smokexyz/Hercules]
+ 39,-1,15,15, 14,19, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
+ 10,-1,15, 0, 79,25, 7, 0, 0,-1,-1,-1, 14,67,186,-1, //0x3830
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
- -1,-1, 7, 7, 7,11, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari]
+ -1,-1, 7, 7, 7,11, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] Clan System[Murilo BiO]
-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]
- 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]
+ 14,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
+ -1,-1, 7, 3, 0,-1, 7, 15,18 + NAME_LENGTH, 23, 16 + sizeof(struct rodex_item) * RODEX_MAX_ITEM, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] / RoDEX [KirieZ]
};
intif = &intif_s;
@@ -2411,13 +2738,10 @@ void intif_defaults(void) {
/* funcs */
intif->parse = intif_parse;
intif->create_pet = intif_create_pet;
- intif->broadcast = intif_broadcast;
- intif->broadcast2 = intif_broadcast2;
- intif->main_message = intif_main_message;
- intif->wis_message = intif_wis_message;
- intif->wis_message_to_gm = intif_wis_message_to_gm;
intif->saveregistry = intif_saveregistry;
intif->request_registry = intif_request_registry;
+ intif->request_account_storage = intif_request_account_storage;
+ intif->send_account_storage = intif_send_account_storage;
intif->request_guild_storage = intif_request_guild_storage;
intif->send_guild_storage = intif_send_guild_storage;
intif->create_party = intif_create_party;
@@ -2427,7 +2751,6 @@ void intif_defaults(void) {
intif->party_leave = intif_party_leave;
intif->party_changemap = intif_party_changemap;
intif->break_party = intif_break_party;
- intif->party_message = intif_party_message;
intif->party_leaderchange = intif_party_leaderchange;
intif->guild_create = intif_guild_create;
intif->guild_request_info = intif_guild_request_info;
@@ -2435,7 +2758,6 @@ void intif_defaults(void) {
intif->guild_leave = intif_guild_leave;
intif->guild_memberinfoshort = intif_guild_memberinfoshort;
intif->guild_break = intif_guild_break;
- intif->guild_message = intif_guild_message;
intif->guild_change_gm = intif_guild_change_gm;
intif->guild_change_basicinfo = intif_guild_change_basicinfo;
intif->guild_change_memberinfo = intif_guild_change_memberinfo;
@@ -2480,20 +2802,30 @@ void intif_defaults(void) {
intif->elemental_request = intif_elemental_request;
intif->elemental_delete = intif_elemental_delete;
intif->elemental_save = intif_elemental_save;
+ // RoDEX
+ intif->rodex_requestinbox = intif_rodex_requestinbox;
+ intif->rodex_checkhasnew = intif_rodex_hasnew;
+ intif->rodex_updatemail = intif_rodex_updatemail;
+ intif->rodex_sendmail = intif_rodex_sendmail;
+ intif->rodex_checkname = intif_rodex_checkname;
+ /* Clan System */
+ intif->clan_kickoffline = intif_clan_kickoffline;
+ intif->clan_membercount = intif_clan_membercount;
/* @accinfo */
intif->request_accinfo = intif_request_accinfo;
/* */
intif->CheckForCharServer = CheckForCharServer;
/* */
intif->itembound_req = intif_itembound_req;
+ /* Achievement System */
+ intif->achievements_request = intif_achievements_request;
+ intif->achievements_save = intif_achievements_save;
/* parse functions */
- intif->pWisMessage = intif_parse_WisMessage;
- intif->pWisEnd = intif_parse_WisEnd;
- intif->pWisToGM_sub = mapif_parse_WisToGM_sub;
- intif->pWisToGM = mapif_parse_WisToGM;
intif->pRegisters = intif_parse_Registers;
intif->pChangeNameOk = intif_parse_ChangeNameOk;
intif->pMessageToFD = intif_parse_MessageToFD;
+ intif->pAccountStorage = intif_parse_account_storage;
+ intif->pAccountStorageSaveAck = intif_parse_account_storage_save_ack;
intif->pLoadGuildStorage = intif_parse_LoadGuildStorage;
intif->pSaveGuildStorage = intif_parse_SaveGuildStorage;
intif->pPartyCreated = intif_parse_PartyCreated;
@@ -2503,14 +2835,12 @@ void intif_defaults(void) {
intif->pPartyMemberWithdraw = intif_parse_PartyMemberWithdraw;
intif->pPartyMove = intif_parse_PartyMove;
intif->pPartyBroken = intif_parse_PartyBroken;
- intif->pPartyMessage = intif_parse_PartyMessage;
intif->pGuildCreated = intif_parse_GuildCreated;
intif->pGuildInfo = intif_parse_GuildInfo;
intif->pGuildMemberAdded = intif_parse_GuildMemberAdded;
intif->pGuildMemberWithdraw = intif_parse_GuildMemberWithdraw;
intif->pGuildMemberInfoShort = intif_parse_GuildMemberInfoShort;
intif->pGuildBroken = intif_parse_GuildBroken;
- intif->pGuildMessage = intif_parse_GuildMessage;
intif->pGuildBasicInfoChanged = intif_parse_GuildBasicInfoChanged;
intif->pGuildMemberInfoChanged = intif_parse_GuildMemberInfoChanged;
intif->pGuildPosition = intif_parse_GuildPosition;
@@ -2549,4 +2879,15 @@ void intif_defaults(void) {
intif->pRecvHomunculusData = intif_parse_RecvHomunculusData;
intif->pSaveHomunculusOk = intif_parse_SaveHomunculusOk;
intif->pDeleteHomunculusOk = intif_parse_DeleteHomunculusOk;
+ /* RoDEX */
+ intif->pRequestRodexOpenInbox = intif_parse_RequestRodexOpenInbox;
+ intif->pRodexHasNew = intif_parse_RodexNotifications;
+ intif->pRodexSendMail = intif_parse_RodexSendMail;
+ intif->pRodexCheckName = intif_parse_RodexCheckName;
+ intif->pGetZenyAck = intif_parse_GetZenyAck;
+ intif->pGetItemsAck = intif_parse_GetItemsAck;
+ /* Clan System */
+ intif->pRecvClanMemberAction = intif_parse_RecvClanMemberAction;
+ /* Achievement System */
+ intif->pAchievementsLoad = intif_parse_achievements_load;
}
diff --git a/src/map/intif.h b/src/map/intif.h
index dccd31d80..c397eda7d 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ struct s_elemental;
struct s_homunculus;
struct s_mercenary;
struct s_pet;
+struct rodex_message;
/**
* Defines
@@ -57,15 +58,12 @@ struct intif_interface {
int packet_len_table[INTIF_PACKET_LEN_TABLE_SIZE];
/* 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 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);
- int (*wis_message) (struct map_session_data *sd, const char *nick, const char *mes, size_t mes_len);
- int (*wis_message_to_gm) (char *Wisp_name, int permission, char *mes);
+ int (*create_pet)(int account_id, int char_id, int pet_type, int pet_lv, int pet_egg_id,
+ int pet_equip, short intimate, short hungry, char rename_flag, char incubate, char *pet_name);
int (*saveregistry) (struct map_session_data *sd);
int (*request_registry) (struct map_session_data *sd, int flag);
+ void (*request_account_storage) (const struct map_session_data *sd);
+ void (*send_account_storage) (struct map_session_data *sd);
int (*request_guild_storage) (int account_id, int guild_id);
int (*send_guild_storage) (int account_id, struct guild_storage *gstor);
int (*create_party) (struct party_member *member, const char *name, int item, int item2);
@@ -75,16 +73,14 @@ struct intif_interface {
int (*party_leave) (int party_id,int account_id, int char_id);
int (*party_changemap) (struct map_session_data *sd, int online);
int (*break_party) (int party_id);
- int (*party_message) (int party_id, int account_id, const char *mes,int len);
int (*party_leaderchange) (int party_id,int account_id,int char_id);
int (*guild_create) (const char *name, const struct guild_member *master);
int (*guild_request_info) (int guild_id);
int (*guild_addmember) (int guild_id, struct guild_member *m);
int (*guild_leave) (int guild_id, int account_id, int char_id, int flag, const char *mes);
- int (*guild_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class_);
+ int (*guild_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class);
int (*guild_break) (int guild_id);
- int (*guild_message) (int guild_id, int account_id, const char *mes, int len);
- int (*guild_change_gm) (int guild_id, const char* name, size_t len);
+ int (*guild_change_gm) (int guild_id, const char *name, int len);
int (*guild_change_basicinfo) (int guild_id, int type, const void *data, int len);
int (*guild_change_memberinfo) (int guild_id, int account_id, int char_id, int type, const void *data, int len);
int (*guild_position) (int guild_id, int idx, struct guild_position *p);
@@ -129,18 +125,30 @@ struct intif_interface {
int (*elemental_request) (int ele_id, int char_id);
int (*elemental_delete) (int ele_id);
int (*elemental_save) (struct s_elemental *ele);
+ // RoDEX
+ int(*rodex_requestinbox) (int char_id, int account_id, int8 flag, int8 opentype, int64 mail_id);
+ int(*rodex_checkhasnew) (struct map_session_data *sd);
+ int(*rodex_updatemail) (struct map_session_data *sd, int64 mail_id, uint8 opentype, int8 flag);
+ int(*rodex_sendmail) (struct rodex_message *msg);
+ int(*rodex_checkname) (struct map_session_data *sd, const char *name);
+ void (*pGetZenyAck) (int fd);
+ void (*pGetItemsAck) (int fd);
+ /* Clan System */
+ int (*clan_kickoffline) (int clan_id, int kick_interval);
+ int (*clan_membercount) (int clan_id, int kick_interval);
/* @accinfo */
void (*request_accinfo) (int u_fd, int aid, int group_lv, char* query);
/* */
int (*CheckForCharServer) (void);
+ /* Achievement System [Smokexyz/Hercules] */
+ void(*achievements_request) (struct map_session_data *sd);
+ void(*achievements_save) (struct map_session_data *sd);
/* */
- void (*pWisMessage) (int fd);
- void (*pWisEnd) (int fd);
- int (*pWisToGM_sub) (struct map_session_data* sd,va_list va);
- void (*pWisToGM) (int fd);
void (*pRegisters) (int fd);
+ void (*pAccountStorage) (int fd);
void (*pChangeNameOk) (int fd);
void (*pMessageToFD) (int fd);
+ void (*pAccountStorageSaveAck) (int fd);
void (*pLoadGuildStorage) (int fd);
void (*pSaveGuildStorage) (int fd);
void (*pPartyCreated) (int fd);
@@ -150,14 +158,12 @@ struct intif_interface {
void (*pPartyMemberWithdraw) (int fd);
void (*pPartyMove) (int fd);
void (*pPartyBroken) (int fd);
- void (*pPartyMessage) (int fd);
void (*pGuildCreated) (int fd);
void (*pGuildInfo) (int fd);
void (*pGuildMemberAdded) (int fd);
void (*pGuildMemberWithdraw) (int fd);
void (*pGuildMemberInfoShort) (int fd);
void (*pGuildBroken) (int fd);
- void (*pGuildMessage) (int fd);
void (*pGuildBasicInfoChanged) (int fd);
void (*pGuildMemberInfoChanged) (int fd);
void (*pGuildPosition) (int fd);
@@ -196,6 +202,15 @@ struct intif_interface {
void (*pRecvHomunculusData) (int fd);
void (*pSaveHomunculusOk) (int fd);
void (*pDeleteHomunculusOk) (int fd);
+ /* RoDEX */
+ void(*pRequestRodexOpenInbox) (int fd);
+ void(*pRodexHasNew) (int fd);
+ void(*pRodexSendMail) (int fd);
+ void(*pRodexCheckName) (int fd);
+ /* Clan System */
+ void (*pRecvClanMemberAction) (int fd);
+ /* Achievements */
+ void (*pAchievementsLoad) (int fd);
};
#ifdef HERCULES_CORE
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index b520e9e91..bc9cb6ad1 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,16 +43,14 @@
//#define IRCBOT_DEBUG
-struct irc_bot_interface irc_bot_s;
+static struct irc_bot_interface irc_bot_s;
struct irc_bot_interface *ircbot;
-char send_string[IRC_MESSAGE_LENGTH];
+static char send_string[IRC_MESSAGE_LENGTH];
-/**
- * Timer callback to (re-)connect to an IRC server
- * @see timer->do_timer
- */
-int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
+/// @copydoc irc_bot_interface::connect_timer()
+static int irc_connect_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct hSockOpt opt;
if( ircbot->isOn || ++ircbot->fails >= 3 )
return 0;
@@ -65,60 +63,54 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
if ((ircbot->fd = sockt->make_connection(ircbot->ip, channel->config->irc_server_port, &opt)) > 0) {
sockt->session[ircbot->fd]->func_parse = ircbot->parse;
sockt->session[ircbot->fd]->flag.server = 1;
+ sockt->session[ircbot->fd]->flag.validate = 0;
timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0);
ircbot->isOn = true;
}
return 0;
}
-/**
- * Timer callback to send identification commands to an IRC server
- * @see timer->do_timer
- */
-int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) {
+/// @copydoc irc_bot_interface::identify_timer()
+static int irc_identify_timer(int tid, int64 tick, int id, intptr_t data)
+{
if( !ircbot->isOn )
return 0;
sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rnd()%777);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
sprintf(send_string, "NICK %s", channel->config->irc_nick);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0);
return 0;
}
-/**
- * Timer callback to join channels (and optionally send NickServ commands)
- * @see timer->do_timer
- */
-int irc_join_timer(int tid, int64 tick, int id, intptr_t data) {
+/// @copydoc irc_bot_interface::join_timer()
+static int irc_join_timer(int tid, int64 tick, int id, intptr_t data)
+{
if( !ircbot->isOn )
return 0;
if (channel->config->irc_nick_pw[0] != '\0') {
sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", channel->config->irc_nick_pw);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
if (channel->config->irc_use_ghost) {
sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", channel->config->irc_nick, channel->config->irc_nick_pw);
+ ircbot->send(send_string, true);
}
}
sprintf(send_string, "JOIN %s", channel->config->irc_channel);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
ircbot->isIn = true;
return 0;
}
-/**
- * Search the handler for a given IRC received command
- * @param function_name Name of the received IRC command
- * @return Function pointer to the command handler, NULL in case
- * of unhandled commands
- */
-struct irc_func* irc_func_search(char* function_name) {
+/// @copydoc irc_bot_interface::func_search()
+static struct irc_func *irc_func_search(char *function_name)
+{
int i;
nullpo_retr(NULL, function_name);
for(i = 0; i < ircbot->funcs.size; i++) {
@@ -129,11 +121,9 @@ struct irc_func* irc_func_search(char* function_name) {
return NULL;
}
-/**
- * Parser for the IRC server connection
- * @see do_sockets
- */
-int irc_parse(int fd) {
+/// @copydoc irc_bot_interface::parse()
+static int irc_parse(int fd)
+{
char *parse_string = NULL, *p = NULL, *str_safe = NULL;
if (sockt->session[fd]->flag.eof) {
@@ -166,17 +156,9 @@ int irc_parse(int fd) {
return 0;
}
-/**
- * Parse the source from a received irc message
- * @param source Source string, as reported by the server
- * @param nick Pointer to a string where to return the nick (may not be NULL,
- * needs to be able to fit an IRC_NICK_LENGTH long string)
- * @param ident Pointer to a string where to return the ident (may not be
- * NULL, needs to be able to fit an IRC_IDENT_LENGTH long string)
- * @param host Pointer to a string where to return the hostname (may not be
- * NULL, needs to be able to fit an IRC_HOST_LENGTH long string)
- */
-void irc_parse_source(char *source, char *nick, char *ident, char *host) {
+/// @copydoc irc_bot_interface::parse_source()
+static void irc_parse_source(char *source, char *nick, char *ident, char *host)
+{
int i, pos = 0;
size_t len;
unsigned char stage = 0;
@@ -199,13 +181,9 @@ void irc_parse_source(char *source, char *nick, char *ident, char *host) {
}
}
-/**
- * Parse a received message from the irc server, and do the appropriate action
- * for the detected command
- * @param fd IRC server connection file descriptor
- * @param str Raw received message
- */
-void irc_parse_sub(int fd, char *str) {
+/// @copydoc irc_bot_interface::parse_sub()
+static void irc_parse_sub(int fd, char *str)
+{
char source[180], command[60], buf1[IRC_MESSAGE_LENGTH], buf2[IRC_MESSAGE_LENGTH];
char *target = buf1, *message = buf2;
struct irc_func *func;
@@ -234,36 +212,95 @@ void irc_parse_sub(int fd, char *str) {
func->func(fd,command,source,target,message);
}
-/**
- * Send a raw command to the irc server
- * @param str Command to send
- */
-void irc_send(char *str) {
+/// @copydoc irc_bot_interface::queue()
+static void irc_queue(char *str)
+{
+ struct message_flood *queue_entry = NULL;
+
+ if (!ircbot->flood_protection_enabled) {
+ ircbot->send(str, true);
+ return;
+ }
+
+ if (ircbot->message_current == NULL) {
+ // No queue yet
+ if (ircbot->messages_burst_count < ircbot->flood_protection_burst) {
+ ircbot->send(str, true);
+ if (DIFF_TICK(timer->gettick(), ircbot->last_message_tick) <= ircbot->flood_protection_rate)
+ ircbot->messages_burst_count++;
+ else
+ ircbot->messages_burst_count = 0;
+ ircbot->last_message_tick = timer->gettick();
+ } else { //queue starts
+ CREATE(queue_entry, struct message_flood, 1);
+ safestrncpy(queue_entry->message, str, sizeof(queue_entry->message));
+ queue_entry->next = NULL;
+ ircbot->message_current = queue_entry;
+ ircbot->message_last = queue_entry;
+ ircbot->queue_tid = timer->add(timer->gettick() + ircbot->flood_protection_rate, ircbot->queue_timer, 0, 0); //start queue timer
+ ircbot->messages_burst_count = 0;
+ }
+ } else {
+ CREATE(queue_entry, struct message_flood, 1);
+ safestrncpy(queue_entry->message, str, sizeof(queue_entry->message));
+ queue_entry->next = NULL;
+ ircbot->message_last->next = queue_entry;
+ ircbot->message_last = queue_entry;
+ }
+}
+
+/// @copydoc irc_bot_interface::queue_timer()
+static int irc_queue_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct message_flood *queue_entry = ircbot->message_current;
+ nullpo_ret(queue_entry);
+
+ ircbot->send(queue_entry->message, true);
+ if (queue_entry->next != NULL) {
+ ircbot->message_current = queue_entry->next;
+ ircbot->queue_tid = timer->add(timer->gettick() + ircbot->flood_protection_rate, ircbot->queue_timer, 0, 0);
+ } else {
+ ircbot->message_current = NULL;
+ ircbot->message_last = NULL;
+ ircbot->queue_tid = INVALID_TIMER;
+ }
+
+ aFree(queue_entry);
+
+ return 0;
+}
+
+/// @copydoc irc_bot_interface::send()
+static void irc_send(char *str, bool force)
+{
size_t len;
nullpo_retv(str);
len = strlen(str) + 2;
if (len > IRC_MESSAGE_LENGTH-3)
len = IRC_MESSAGE_LENGTH-3;
+
+ if (!force && ircbot->flood_protection_enabled) {
+ // Add to queue
+ ircbot->queue(str);
+ return;
+ }
+
WFIFOHEAD(ircbot->fd, len);
snprintf(WFIFOP(ircbot->fd,0),IRC_MESSAGE_LENGTH, "%s\r\n", str);
WFIFOSET(ircbot->fd, len);
}
-/**
- * Handler for the PING IRC command (send back a PONG)
- * @see irc_parse_sub
- */
-void irc_pong(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_interface_bot::pong()
+static void irc_pong(int fd, char *cmd, char *source, char *target, char *msg)
+{
nullpo_retv(cmd);
snprintf(send_string, IRC_MESSAGE_LENGTH, "PONG %s", cmd);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
}
-/**
- * Handler for CTCP commands received via PRIVMSG
- * @see irc_privmsg
- */
-void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_interface_bot::privmsg_ctcp()
+static void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
+{
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
source_nick[0] = source_ident[0] = source_host[0] = '\0';
@@ -283,7 +320,7 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
// Ignore it
} else if( strcmpi(cmd,"PING") == 0 ) {
snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001PING %s\001",source_nick,msg);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
} else if( strcmpi(cmd,"TIME") == 0 ) {
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
@@ -297,10 +334,10 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X.
snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001TIME %s\001",source_nick,temp);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
} else if( strcmpi(cmd,"VERSION") == 0 ) {
- snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001VERSION Hercules.ws IRC Bridge\001",source_nick);
- ircbot->send(send_string);
+ snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001VERSION Herc.ws IRC Bridge\001",source_nick);
+ ircbot->send(send_string, false);
#ifdef IRCBOT_DEBUG
} else {
ShowWarning("Unknown CTCP command received %s (%s) from %s\n",cmd,msg,source);
@@ -308,11 +345,9 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
}
}
-/**
- * Handler for the PRIVMSG IRC command (action depends on the message contents)
- * @see irc_parse_sub
- */
-void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_bot_interface::privmsg()
+static void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg)
+{
size_t len = msg ? strlen(msg) : 0;
nullpo_retv(source);
nullpo_retv(target);
@@ -322,7 +357,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
command[0] = message[0] = '\0';
sscanf(msg, "\001%499[^\001\r\n ] %499[^\r\n\001]\001", command, message);
- irc_privmsg_ctcp(fd, command, source, target, message);
+ ircbot->privmsg_ctcp(fd, command, source, target, message);
#ifdef IRCBOT_DEBUG
} else if (strcmpi(target, channel->config->irc_nick) == 0) {
ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg);
@@ -349,12 +384,9 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
}
}
-/**
- * Handler for the JOIN IRC command (notify an in-game channel of users joining
- * the IRC channel)
- * @see irc_parse_sub
- */
-void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_bot_interface::userjoin()
+static void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg)
+{
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
nullpo_retv(source);
@@ -364,17 +396,14 @@ void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
ircbot->parse_source(source,source_nick,source_ident,source_host);
if( ircbot->channel ) {
- snprintf(send_string, 150, "[ #%s ] User IRC.%s joined the channel.",ircbot->channel->name,source_nick);
+ snprintf(send_string, 150, msg_txt(468), ircbot->channel->name, source_nick); // [ #%s ] User IRC.%s joined the channel.
clif->channel_msg2(ircbot->channel,send_string);
}
}
-/**
- * Handler for the PART and QUIT IRC commands (notify an in-game channel of
- * users leaving the IRC channel)
- * @see irc_parse_sub
- */
-void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_bot_interface::userleave()
+static void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg)
+{
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
nullpo_retv(source);
@@ -385,19 +414,16 @@ void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
if( ircbot->channel ) {
if (!strcmpi(cmd, "QUIT"))
- snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [Quit: %s]",ircbot->channel->name,source_nick,msg);
+ snprintf(send_string, 150, msg_txt(465), ircbot->channel->name, source_nick, msg); // [ #%s ] User IRC.%s left the channel. [Quit: %s]
else
- snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [%s]",ircbot->channel->name,source_nick,msg);
+ snprintf(send_string, 150, msg_txt(466), ircbot->channel->name, source_nick, msg); // [ #%s ] User IRC.%s left the channel. [%s]
clif->channel_msg2(ircbot->channel,send_string);
}
}
-/**
- * Handler for the NICK IRC commands (notify an in-game channel of users
- * changing their name while in the IRC channel)
- * @see irc_parse_sub
- */
-void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
+/// @copydoc irc_bot_interface::usernick()
+static void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg)
+{
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
nullpo_retv(source);
@@ -407,17 +433,13 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
ircbot->parse_source(source,source_nick,source_ident,source_host);
if( ircbot->channel ) {
- snprintf(send_string, 150, "[ #%s ] User IRC.%s is now known as IRC.%s",ircbot->channel->name,source_nick,msg);
+ snprintf(send_string, 150, msg_txt(467), ircbot->channel->name, source_nick, msg); // [ #%s ] User IRC.%s is now known as IRC.%s
clif->channel_msg2(ircbot->channel,send_string);
}
}
-/**
- * Relay a chat message to the irc channel the bot is connected to
- * @param name Sender's name
- * @param msg Message text
- */
-void irc_relay(const char *name, const char *msg)
+/// @copydoc irc_bot_interface::relay()
+static void irc_relay(const char *name, const char *msg)
{
if (!ircbot->isIn)
return;
@@ -428,13 +450,12 @@ void irc_relay(const char *name, const char *msg)
else
sprintf(send_string,"PRIVMSG %s :%s", channel->config->irc_channel, msg);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
}
-/**
- * IRC bot initializer
- */
-void irc_bot_init(bool minimal) {
+/// @copydoc irc_bot_interface::init()
+static void irc_bot_init(bool minimal)
+{
/// Command handlers
const struct irc_func irc_func_base[] = {
{ "PING" , ircbot->pong },
@@ -479,22 +500,32 @@ void irc_bot_init(bool minimal) {
ircbot->isOn = false;
timer->add_func_list(ircbot->connect_timer, "irc_connect_timer");
+ timer->add_func_list(ircbot->queue_timer, "irc_queue_timer");
+
timer->add(timer->gettick() + 7000, ircbot->connect_timer, 0, 0);
}
-/**
- * IRC bot finalizer
- */
-void irc_bot_final(void) {
+/// @copydoc irc_bot_interface::final()
+static void irc_bot_final(void)
+{
int i;
if (!channel->config->irc)
return;
if( ircbot->isOn ) {
- ircbot->send("QUIT :Hercules is shutting down");
+ ircbot->send("QUIT :Hercules is shutting down", true);
sockt->close(ircbot->fd);
}
+ if (ircbot->queue_tid != INVALID_TIMER)
+ timer->delete(ircbot->queue_tid, ircbot->queue_timer);
+
+ while (ircbot->message_current != NULL) {
+ struct message_flood *next = ircbot->message_current->next;
+ aFree(ircbot->message_current);
+ ircbot->message_current = next;
+ }
+
for( i = 0; i < ircbot->funcs.size; i++ ) {
aFree(ircbot->funcs.list[i]);
}
@@ -504,11 +535,21 @@ void irc_bot_final(void) {
/**
* IRC bot interface defaults initializer
*/
-void ircbot_defaults(void) {
+void ircbot_defaults(void)
+{
ircbot = &irc_bot_s;
ircbot->channel = NULL;
+ ircbot->flood_protection_enabled = true;
+ ircbot->flood_protection_rate = 1000;
+ ircbot->flood_protection_burst = 3;
+ ircbot->last_message_tick = INVALID_TIMER;
+ ircbot->queue_tid = INVALID_TIMER;
+ ircbot->messages_burst_count = 0;
+ ircbot->message_current = NULL;
+ ircbot->message_last = NULL;
+
ircbot->init = irc_bot_init;
ircbot->final = irc_bot_final;
@@ -522,11 +563,14 @@ void ircbot_defaults(void) {
ircbot->identify_timer = irc_identify_timer;
ircbot->join_timer = irc_join_timer;
+ ircbot->queue_timer = irc_queue_timer;
+ ircbot->queue = irc_queue;
ircbot->send = irc_send;
ircbot->relay = irc_relay;
ircbot->pong = irc_pong;
ircbot->privmsg = irc_privmsg;
+ ircbot->privmsg_ctcp = irc_privmsg_ctcp;
ircbot->userjoin = irc_userjoin;
ircbot->userleave = irc_userleave;
diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h
index dc67e2fe8..66880f427 100644
--- a/src/map/irc-bot.h
+++ b/src/map/irc-bot.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,6 +39,11 @@ struct irc_func {
void (*func)(int, char*, char*, char*, char*);
};
+struct message_flood {
+ char message[IRC_MESSAGE_LENGTH];
+ struct message_flood *next;
+};
+
struct irc_bot_interface {
int fd;
bool isIn, isOn;
@@ -46,6 +51,15 @@ struct irc_bot_interface {
unsigned char fails;
uint32 ip;
unsigned short port;
+ /* messages flood protection */
+ bool flood_protection_enabled;
+ int flood_protection_rate;
+ int flood_protection_burst;
+ int64 last_message_tick;
+ int messages_burst_count;
+ int queue_tid;
+ struct message_flood *message_current;
+ struct message_flood *message_last;
/* */
struct channel_data *channel;
/* */
@@ -53,27 +67,132 @@ struct irc_bot_interface {
struct irc_func **list;
unsigned int size;
} funcs;
- /* */
+
+ /**
+ * IRC bot initializer
+ */
void (*init) (bool minimal);
+
+ /**
+ * IRC bot finalizer
+ */
void (*final) (void);
- /* */
+
+ /**
+ * Parser for the IRC server connection
+ * @see do_sockets
+ */
int (*parse) (int fd);
+
+ /**
+ * Parse a received message from the irc server, and do the appropriate action
+ * for the detected command
+ * @param fd IRC server connection file descriptor
+ * @param str Raw received message
+ */
void (*parse_sub) (int fd, char *str);
+
+ /**
+ * Parse the source from a received irc message
+ * @param source Source string, as reported by the server
+ * @param nick Pointer to a string where to return the nick (may not be NULL,
+ * needs to be able to fit an IRC_NICK_LENGTH long string)
+ * @param ident Pointer to a string where to return the ident (may not be
+ * NULL, needs to be able to fit an IRC_IDENT_LENGTH long string)
+ * @param host Pointer to a string where to return the hostname (may not be
+ * NULL, needs to be able to fit an IRC_HOST_LENGTH long string)
+ */
void (*parse_source) (char *source, char *nick, char *ident, char *host);
- /* */
+
+ /**
+ * Search the handler for a given IRC received command
+ * @param function_name Name of the received IRC command
+ * @return Function pointer to the command handler, NULL in case
+ * of unhandled commands
+ */
struct irc_func* (*func_search) (char* function_name);
- /* */
+
+ /**
+ * Timer callback to (re-)connect to an IRC server
+ * @see timer_interface::do_timer
+ */
int (*connect_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Timer callback to send identification commands to an IRC server
+ * @see timer_interface::do_timer
+ */
int (*identify_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Timer callback to join channels (and optionally send NickServ commands)
+ * @see timer_interface::do_timer
+ */
int (*join_timer) (int tid, int64 tick, int id, intptr_t data);
- /* */
- void (*send)(char *str);
+
+ /**
+ * Timer callback to send queued IRC Commands
+ * @see timer_interface::do_timer
+ */
+ int (*queue_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Decides if an IRC Command should be queued or not, based on the flood protection settings.
+ *
+ * @param str Command to be checked
+ */
+ void (*queue) (char *str);
+
+ /**
+ * Send a raw command to the irc server
+ * @param str Command to send
+ */
+ void (*send)(char *str, bool force);
+
+ /**
+ * Relay a chat message to the irc channel the bot is connected to
+ * @param name Sender's name
+ * @param msg Message text
+ */
void (*relay) (const char *name, const char *msg);
- /* */
+
+ /**
+ * Handler for the PING IRC command (send back a PONG)
+ * @see irc_bot_interface::parse_sub
+ */
void (*pong) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the PRIVMSG IRC command (action depends on the message contents)
+ * @see irc_bot_interface::parse_sub
+ */
void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for CTCP commands received via PRIVMSG
+ * @see irc_bot_interface::privmsg
+ */
+ void (*privmsg_ctcp) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the JOIN IRC command (notify an in-game channel of users joining
+ * the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*userjoin) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the PART and QUIT IRC commands (notify an in-game channel of
+ * users leaving the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*userleave) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the NICK IRC commands (notify an in-game channel of users
+ * changing their name while in the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*usernick) (int fd, char *cmd, char *source, char *target, char *msg);
};
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index c59f627cc..2b8200c06 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include "map/map.h"
#include "map/mob.h" // MAX_MOB_DB
#include "map/pc.h" // W_MUSICAL, W_WHIP
+#include "map/refine.h"
#include "map/script.h" // item script processing
#include "common/HPM.h"
#include "common/conf.h"
@@ -41,7 +42,7 @@
#include <stdlib.h>
#include <string.h>
-struct itemdb_interface itemdb_s;
+static struct itemdb_interface itemdb_s;
struct itemdb_interface *itemdb;
/**
@@ -49,7 +50,7 @@ struct itemdb_interface *itemdb;
* name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
* @see DBApply
*/
-int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
+static int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *item = DB->data2ptr(data), **dst, **dst2;
char *str;
@@ -78,7 +79,8 @@ int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
/*==========================================
* Return item data from item name. (lookup)
*------------------------------------------*/
-struct item_data* itemdb_searchname(const char *str) {
+static struct item_data *itemdb_searchname(const char *str)
+{
struct item_data* item;
struct item_data* item2=NULL;
int i;
@@ -105,83 +107,118 @@ struct item_data* itemdb_searchname(const char *str) {
return item?item:item2;
}
/* name to item data */
-struct item_data* itemdb_name2id(const char *str) {
+static struct item_data *itemdb_name2id(const char *str)
+{
return strdb_get(itemdb->names,str);
}
/**
* @see DBMatcher
*/
-int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
+static int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
{
- struct item_data *item = DB->data2ptr(&data);
- char *str;
- str=va_arg(ap,char *);
+ struct item_data *itd = DB->data2ptr(&data);
+ const char *str = va_arg(ap, const char *);
+ enum item_name_search_flag flag = va_arg(ap, enum item_name_search_flag);
+
nullpo_ret(str);
- if (item == &itemdb->dummy)
+
+ if (itd == &itemdb->dummy)
return 1; //Invalid item.
- if(stristr(item->jname,str))
- return 0;
- if(battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- return 0;
- if(!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
+
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+
return 0;
- return strcmpi(item->jname,str);
+ } else {
+ return 1;
+ }
}
-/*==========================================
- * Founds up to N matches. Returns number of matches [Skotlex]
- * search flag :
- * 0 - approximate match
- * 1 - exact match
- *------------------------------------------*/
-int itemdb_searchname_array(struct item_data** data, int size, const char *str, int flag) {
- struct item_data* item;
- int i;
- int count=0;
-
+/**
+ * Finds up to passed size matches
+ * @param data array of struct item_data for returning the results in
+ * @param size size of the array
+ * @param str string used in this search
+ * @param flag search mode refer to enum item_name_search_flag for possible values
+ * @return returns all found matches in the database which could be bigger than size
+ **/
+static int itemdb_searchname_array(struct item_data **data, const int size, const char *str, enum item_name_search_flag flag)
+{
nullpo_ret(data);
nullpo_ret(str);
- // Search in the array
- for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i )
- {
- item = itemdb->array[i];
- if( item == NULL )
+ Assert_ret(flag >= IT_SEARCH_NAME_PARTIAL && flag < IT_SEARCH_NAME_MAX);
+ Assert_ret(size > 0);
+
+ int
+ results_count = 0,
+ length = 0;
+
+ // Search in array
+ for (int i = 0; i < ARRAYLENGTH(itemdb->array); ++i) {
+ struct item_data *itd = itemdb->array[i];
+
+ if (itd == NULL)
continue;
- if(
- (!flag
- && (stristr(item->jname,str)
- || (battle_config.case_sensitive_aegisnames && strstr(item->name,str))
- || (!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
- ))
- || (flag
- && (strcmp(item->jname,str) == 0
- || (battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0)
- || (!battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0)
- ))
- ) {
- if( count < size )
- data[count] = item;
- ++count;
+ if (
+ (flag == IT_SEARCH_NAME_PARTIAL
+ && (stristr(itd->jname, str) != NULL
+ || (battle_config.case_sensitive_aegisnames && strstr(itd->name, str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(itd->name, str))
+ ))
+ || (flag == IT_SEARCH_NAME_EXACT
+ && (strcmp(itd->jname, str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(itd->name, str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(itd->name, str) == 0)
+ ))
+ ) {
+ if (length < size) {
+ data[length] = itd;
+ ++length;
+ }
+
+ ++results_count;
}
}
- // search in the db
- if( count < size )
- {
- struct DBData *db_data[MAX_SEARCH];
- int db_count = 0;
- size -= count;
- db_count = itemdb->other->getall(itemdb->other, (struct DBData**)&db_data, size, itemdb->searchname_array_sub, str);
- for (i = 0; i < db_count; i++)
- data[count++] = DB->data2ptr(db_data[i]);
- count += db_count;
+ // Search in dbmap
+ int dbmap_size = size - length;
+ if (dbmap_size > 0) {
+ struct DBData **dbmap_data = NULL;
+ int dbmap_count = 0;
+ CREATE(dbmap_data, struct DBData *, dbmap_size);
+
+ dbmap_count = itemdb->other->getall(itemdb->other, dbmap_data, dbmap_size, itemdb->searchname_array_sub, str, flag);
+ dbmap_size = min(dbmap_count, dbmap_size);
+
+ for (int i = 0; i < dbmap_size; ++i) {
+ data[length] = DB->data2ptr(dbmap_data[i]);
+ ++length;
+ }
+
+ results_count += dbmap_count;
+ aFree(dbmap_data);
+ } else { // We got all matches we can return, so we only need to count now.
+ results_count += itemdb->other->getall(itemdb->other, NULL, 0, itemdb->searchname_array_sub, str, flag);
}
- return count;
+
+ return results_count;
}
+
/* [Ind/Hercules] */
-int itemdb_chain_item(unsigned short chain_id, int *rate) {
+static int itemdb_chain_item(unsigned short chain_id, int *rate)
+{
struct item_chain_entry *entry;
if( chain_id >= itemdb->chain_count ) {
@@ -199,7 +236,8 @@ int itemdb_chain_item(unsigned short chain_id, int *rate) {
return entry->id;
}
/* [Ind/Hercules] */
-void itemdb_package_item(struct map_session_data *sd, struct item_package *package) {
+static void itemdb_package_item(struct map_session_data *sd, struct item_package *package)
+{
int i = 0, get_count, j, flag;
nullpo_retv(sd);
@@ -287,7 +325,8 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa
/*==========================================
* Return a random item id from group. (takes into account % chance giving/tot group)
*------------------------------------------*/
-int itemdb_searchrandomid(struct item_group *group) {
+static int itemdb_searchrandomid(struct item_group *group)
+{
nullpo_retr(UNKNOWN_ITEM_ID, group);
if (group->qty)
@@ -296,7 +335,8 @@ int itemdb_searchrandomid(struct item_group *group) {
ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group->id);
return UNKNOWN_ITEM_ID;
}
-bool itemdb_in_group(struct item_group *group, int nameid) {
+static bool itemdb_in_group(struct item_group *group, int nameid)
+{
int i;
nullpo_retr(false, group);
@@ -309,7 +349,7 @@ bool itemdb_in_group(struct item_group *group, int nameid) {
/// Searches for the item_data.
/// Returns the item_data or NULL if it does not exist.
-struct item_data* itemdb_exists(int nameid)
+static struct item_data *itemdb_exists(int nameid)
{
struct item_data* item;
@@ -321,9 +361,19 @@ struct item_data* itemdb_exists(int nameid)
return item;
}
+/**
+ * Searches for the item_option data.
+ * @param option_index as the index of the item option (client side).
+ * @return pointer to struct itemdb_option data or NULL.
+ */
+static struct itemdb_option *itemdb_option_exists(int idx)
+{
+ return (struct itemdb_option *)idb_get(itemdb->options, idx);
+}
+
/// Returns human readable name for given item type.
/// @param type Type id to retrieve name for ( IT_* ).
-const char* itemdb_typename(int type)
+static const char *itemdb_typename(int type)
{
switch(type)
{
@@ -342,7 +392,7 @@ const char* itemdb_typename(int type)
return "Unknown Type";
}
- /**
+/**
* Converts the JobID to the format used by map-server to check item
* restriction as per job.
*
@@ -352,14 +402,14 @@ const char* itemdb_typename(int type)
*
* @author Dastgir
*/
-void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
+static void itemdb_jobid2mapid(uint64 *bclass, int job_class, bool enable)
{
uint64 mask[3] = { 0 };
int i;
nullpo_retv(bclass);
- switch(job_id) {
+ switch (job_class) {
// Base Classes
case JOB_NOVICE:
case JOB_SUPER_NOVICE:
@@ -367,12 +417,22 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
mask[1] = 1ULL << MAPID_NOVICE;
break;
case JOB_SWORDMAN:
+ mask[0] = 1ULL << MAPID_SWORDMAN;
+ break;
case JOB_MAGE:
+ mask[0] = 1ULL << MAPID_MAGE;
+ break;
case JOB_ARCHER:
+ mask[0] = 1ULL << MAPID_ARCHER;
+ break;
case JOB_ACOLYTE:
+ mask[0] = 1ULL << MAPID_ACOLYTE;
+ break;
case JOB_MERCHANT:
+ mask[0] = 1ULL << MAPID_MERCHANT;
+ break;
case JOB_THIEF:
- mask[0] = 1ULL << (MAPID_NOVICE+job_id);
+ mask[0] = 1ULL << MAPID_THIEF;
break;
// 2-1 Classes
case JOB_KNIGHT:
@@ -437,6 +497,9 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
case JOB_REBELLION:
mask[1] = 1ULL << MAPID_GUNSLINGER;
break;
+ case JOB_SUMMONER:
+ mask[0] = 1ULL << MAPID_SUMMONER;
+ break;
// Other Classes
case JOB_GANGSI: //Bongun/Munak
mask[0] = 1ULL << MAPID_GANGSI;
@@ -466,9 +529,8 @@ void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable)
* @param bclass Pointer to the variable containing the new format.
* @param jobmask Variable containing JobMask.
*/
-void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
+static void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
{
- int i;
nullpo_retv(bclass);
bclass[0] = bclass[1] = bclass[2] = 0;
//Base classes
@@ -477,10 +539,18 @@ void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
bclass[0] |= 1ULL<<MAPID_NOVICE;
bclass[1] |= 1ULL<<MAPID_NOVICE;
}
- for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) {
- if (jobmask & 1ULL<<i)
- bclass[0] |= 1ULL<<(MAPID_NOVICE+i);
- }
+ if (jobmask & 1ULL<<JOB_SWORDMAN)
+ bclass[0] |= 1ULL<<MAPID_SWORDMAN;
+ if (jobmask & 1ULL<<JOB_MAGE)
+ bclass[0] |= 1ULL<<MAPID_MAGE;
+ if (jobmask & 1ULL<<JOB_ARCHER)
+ bclass[0] |= 1ULL<<MAPID_ARCHER;
+ if (jobmask & 1ULL<<JOB_ACOLYTE)
+ bclass[0] |= 1ULL<<MAPID_ACOLYTE;
+ if (jobmask & 1ULL<<JOB_MERCHANT)
+ bclass[0] |= 1ULL<<MAPID_MERCHANT;
+ if (jobmask & 1ULL<<JOB_THIEF)
+ bclass[0] |= 1ULL<<MAPID_THIEF;
//2-1 classes
if (jobmask & 1ULL<<JOB_KNIGHT)
bclass[1] |= 1ULL<<MAPID_SWORDMAN;
@@ -538,9 +608,11 @@ void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask)
bclass[1] |= 1ULL<<MAPID_NINJA;
if (jobmask & 1ULL<<30) //Rebellion
bclass[1] |= 1ULL<<MAPID_GUNSLINGER;
+ if (jobmask & 1ULL<<31) //Summoner
+ bclass[0] |= 1ULL<<MAPID_SUMMONER;
}
-void create_dummy_data(void)
+static void create_dummy_data(void)
{
memset(&itemdb->dummy, 0, sizeof(struct item_data));
itemdb->dummy.nameid=500;
@@ -552,7 +624,7 @@ void create_dummy_data(void)
itemdb->dummy.view_id=UNKNOWN_ITEM_ID;
}
-struct item_data* create_item_data(int nameid)
+static struct item_data *create_item_data(int nameid)
{
struct item_data *id;
CREATE(id, struct item_data, 1);
@@ -565,7 +637,8 @@ struct item_data* create_item_data(int nameid)
/*==========================================
* Loads (and creates if not found) an item from the db.
*------------------------------------------*/
-struct item_data* itemdb_load(int nameid) {
+static struct item_data *itemdb_load(int nameid)
+{
struct item_data *id;
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
@@ -588,7 +661,7 @@ struct item_data* itemdb_load(int nameid) {
/*==========================================
* Loads an item from the db. If not found, it will return the dummy item.
*------------------------------------------*/
-struct item_data* itemdb_search(int nameid)
+static struct item_data *itemdb_search(int nameid)
{
struct item_data* id;
if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
@@ -608,7 +681,7 @@ struct item_data* itemdb_search(int nameid)
/*==========================================
* Returns if given item is a player-equippable piece.
*------------------------------------------*/
-int itemdb_isequip(int nameid)
+static int itemdb_isequip(int nameid)
{
int type=itemdb_type(nameid);
switch (type) {
@@ -624,7 +697,8 @@ int itemdb_isequip(int nameid)
/*==========================================
* Alternate version of itemdb_isequip
*------------------------------------------*/
-int itemdb_isequip2(struct item_data *data) {
+static int itemdb_isequip2(struct item_data *data)
+{
nullpo_ret(data);
switch(data->type) {
case IT_WEAPON:
@@ -639,7 +713,7 @@ int itemdb_isequip2(struct item_data *data) {
/*==========================================
* Returns if given item's type is stackable.
*------------------------------------------*/
-int itemdb_isstackable(int nameid)
+static int itemdb_isstackable(int nameid)
{
int type=itemdb_type(nameid);
switch(type) {
@@ -656,7 +730,7 @@ int itemdb_isstackable(int nameid)
/*==========================================
* Alternate version of itemdb_isstackable
*------------------------------------------*/
-int itemdb_isstackable2(struct item_data *data)
+static int itemdb_isstackable2(struct item_data *data)
{
nullpo_ret(data);
switch(data->type) {
@@ -673,43 +747,52 @@ int itemdb_isstackable2(struct item_data *data)
/*==========================================
* Trade Restriction functions [Skotlex]
*------------------------------------------*/
-int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) {
+static int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_cantrade_sub(struct item_data *item, int gmlv, int gmlv2)
+{
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) {
+static int itemdb_canpartnertrade_sub(struct item_data *item, int gmlv, int gmlv2)
+{
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) {
+static int itemdb_cansell_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_cancartstore_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_canstore_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_canguildstore_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_canmail_sub(struct item_data *item, int gmlv, int unused)
+{
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) {
+static int itemdb_canauction_sub(struct item_data *item, int gmlv, int unused)
+{
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))
+static int itemdb_isrestricted(struct item *item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int))
{
struct item_data* item_data;
int i;
@@ -733,7 +816,8 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru
/*==========================================
* Specifies if item-type should drop unidentified.
*------------------------------------------*/
-int itemdb_isidentified(int nameid) {
+static int itemdb_isidentified(int nameid)
+{
int type=itemdb_type(nameid);
switch (type) {
case IT_WEAPON:
@@ -745,7 +829,8 @@ int itemdb_isidentified(int nameid) {
}
}
/* same as itemdb_isidentified but without a lookup */
-int itemdb_isidentified2(struct item_data *data) {
+static int itemdb_isidentified2(struct item_data *data)
+{
nullpo_ret(data);
switch (data->type) {
case IT_WEAPON:
@@ -757,14 +842,12 @@ int itemdb_isidentified2(struct item_data *data) {
}
}
-void itemdb_read_groups(void) {
+static void itemdb_read_groups(void)
+{
struct config_t item_group_conf;
struct config_setting_t *itg = NULL, *it = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_group.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_group.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_group.conf", config_filename, sizeof(config_filename));
const char *itname;
int i = 0, count = 0, c;
unsigned int *gsize = NULL;
@@ -810,7 +893,7 @@ void itemdb_read_groups(void) {
itemdb->groups[count].id = data->nameid;
itemdb->groups[count].qty = gsize[ count ];
- CREATE(itemdb->groups[count].nameid, unsigned short, gsize[ count ] + 1);
+ CREATE(itemdb->groups[count].nameid, int, gsize[count] + 1);
c = 0;
while( (it = libconfig->setting_get_elem(itg,c++)) ) {
int repeat = 1;
@@ -820,7 +903,7 @@ void itemdb_read_groups(void) {
} else
itname = libconfig->setting_get_string_elem(itg,c - 1);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_groups: unknown item ID '%d' in group '%s'!\n",atoi(itname+2),config_setting_name(itg));
} else if( !( data = itemdb->name2id(itname) ) )
@@ -845,7 +928,8 @@ void itemdb_read_groups(void) {
}
/* [Ind/Hercules] - HCache for Packages */
-void itemdb_write_cached_packages(const char *config_filename) {
+static void itemdb_write_cached_packages(const char *config_filename)
+{
FILE *file;
unsigned short pcount = itemdb->package_count;
unsigned short i;
@@ -859,7 +943,8 @@ void itemdb_write_cached_packages(const char *config_filename) {
hwrite(&pcount,sizeof(pcount),1,file);
for(i = 0; i < pcount; i++) {
- unsigned short id = itemdb->packages[i].id, random_qty = itemdb->packages[i].random_qty, must_qty = itemdb->packages[i].must_qty;
+ int id = itemdb->packages[i].id;
+ unsigned short random_qty = itemdb->packages[i].random_qty, must_qty = itemdb->packages[i].must_qty;
unsigned short c;
//into a package, first 2 bytes = id.
hwrite(&id,sizeof(id),1,file);
@@ -916,7 +1001,9 @@ void itemdb_write_cached_packages(const char *config_filename) {
return;
}
-bool itemdb_read_cached_packages(const char *config_filename) {
+
+static bool itemdb_read_cached_packages(const char *config_filename)
+{
FILE *file;
unsigned short pcount = 0;
unsigned short i;
@@ -933,12 +1020,13 @@ bool itemdb_read_cached_packages(const char *config_filename) {
itemdb->package_count = pcount;
for( i = 0; i < pcount; i++ ) {
- unsigned short id = 0, random_qty = 0, must_qty = 0;
+ int id = 0;
+ unsigned short random_qty = 0, must_qty = 0;
struct item_data *pdata;
struct item_package *package = &itemdb->packages[i];
unsigned short c;
- //into a package, first 2 bytes = id.
+ //into a package, first 4 bytes = id.
hread(&id,sizeof(id),1,file);
//next 2 bytes = must count
hread(&must_qty,sizeof(must_qty),1,file);
@@ -961,10 +1049,11 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//now we loop into must
for(c = 0; c < package->must_qty; c++) {
struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
- unsigned short mid = 0, qty = 0, hours = 0;
+ int mid = 0;
+ unsigned short qty = 0, hours = 0;
unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
- //first 2 byte = item id
+ //first 4 byte = item id
hread(&mid,sizeof(mid),1,file);
//next 2 byte = qty
hread(&qty,sizeof(qty),1,file);
@@ -1004,7 +1093,8 @@ bool itemdb_read_cached_packages(const char *config_filename) {
//now we loop into the group's list
for(h = 0; h < group_qty; h++) {
struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
- unsigned short mid = 0, qty = 0, hours = 0, rate = 0;
+ int mid = 0;
+ unsigned short qty = 0, hours = 0, rate = 0;
unsigned char announce = 0, named = 0, force_serial = 0;
struct item_data *data;
@@ -1047,14 +1137,12 @@ bool itemdb_read_cached_packages(const char *config_filename) {
return true;
}
-void itemdb_read_packages(void) {
+static void itemdb_read_packages(void)
+{
struct config_t item_packages_conf;
struct config_setting_t *itg = NULL, *it = NULL, *t = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_packages.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_packages.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_packages.conf", config_filename, sizeof(config_filename));
const char *itname;
int i = 0, count = 0, c = 0, highest_gcount = 0;
unsigned int *must = NULL, *random = NULL, *rgroup = NULL, **rgroups = NULL;
@@ -1179,7 +1267,7 @@ void itemdb_read_packages(void) {
itname = config_setting_name(it);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_packages: unknown item ID '%d' in package '%s'!\n",atoi(itname+2),config_setting_name(itg));
} else if( !( data = itemdb->name2id(itname) ) )
@@ -1277,14 +1365,132 @@ void itemdb_read_packages(void) {
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-void itemdb_read_chains(void) {
+/**
+ * Processes any (plugin-defined) additional fields for a itemdb_options entry.
+ *
+ * @param[in,out] entry The destination ito entry, already initialized
+ * (item_opt.index, status.mode are expected to be already set).
+ * @param[in] t The libconfig entry.
+ * @param[in] source Source of the entry (file name), to be displayed in
+ * case of validation errors.
+ */
+static void itemdb_readdb_options_additional_fields(struct itemdb_option *ito, struct config_setting_t *t, const char *source)
+{
+ // do nothing. plugins can do their own work
+}
+
+/**
+ * Reads the Item Options configuration file.
+ */
+static void itemdb_read_options(void)
+{
+ struct config_t item_options_db;
+ struct config_setting_t *ito = NULL, *conf = NULL;
+ int index = 0, count = 0;
+ char filepath[256];
+ libconfig->format_db_path("item_options.conf", filepath, sizeof(filepath));
+ VECTOR_DECL(int) duplicate_id;
+
+ if (!libconfig->load_file(&item_options_db, filepath))
+ return;
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = filepath;
+#endif // ENABLE_CASE_CHECK
+
+ if ((ito=libconfig->setting_get_member(item_options_db.root, "item_options_db")) == NULL) {
+ ShowError("itemdb_read_options: '%s' could not be loaded.\n", filepath);
+ libconfig->destroy(&item_options_db);
+ return;
+ }
+
+ VECTOR_INIT(duplicate_id);
+
+ VECTOR_ENSURE(duplicate_id, libconfig->setting_length(ito), 1);
+
+ while ((conf = libconfig->setting_get_elem(ito, index++))) {
+ struct itemdb_option t_opt = { 0 }, *s_opt = NULL;
+ const char *str = NULL;
+ int i = 0;
+
+ /* Id Lookup */
+ if (!libconfig->setting_lookup_int16(conf, "Id", &t_opt.index) || t_opt.index <= 0) {
+ ShowError("itemdb_read_options: Invalid Option Id provided for entry %d in '%s', skipping...\n", t_opt.index, filepath);
+ continue;
+ }
+
+ /* Checking for duplicate entries. */
+ ARR_FIND(0, VECTOR_LENGTH(duplicate_id), i, VECTOR_INDEX(duplicate_id, i) == t_opt.index);
+
+ if (i != VECTOR_LENGTH(duplicate_id)) {
+ ShowError("itemdb_read_options: Duplicate entry for Option Id %d in '%s', skipping...\n", t_opt.index, filepath);
+ continue;
+ }
+
+ VECTOR_PUSH(duplicate_id, t_opt.index);
+
+ /* Name Lookup */
+ if (!libconfig->setting_lookup_string(conf, "Name", &str)) {
+ ShowError("itemdb_read_options: Invalid Option Name '%s' provided for Id %d in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+
+ /* check for illegal characters in the constant. */
+ {
+ const char *c = str;
+
+ while (ISALNUM(*c) || *c == '_')
+ ++c;
+
+ if (*c != '\0') {
+ ShowError("itemdb_read_options: Invalid characters in Option Name '%s' for Id %d in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+ }
+
+ /* Set name as a script constant with index as value. */
+ script->set_constant2(str, t_opt.index, false, false);
+
+ /* Script Code Lookup */
+ if (!libconfig->setting_lookup_string(conf, "Script", &str)) {
+ ShowError("itemdb_read_options: Script code not found for entry %s (Id: %d) in '%s', skipping...\n", str, t_opt.index, filepath);
+ continue;
+ }
+
+ /* Set Script */
+ t_opt.script = *str ? script->parse(str, filepath, t_opt.index, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ /* Additional fields through plugins */
+ itemdb->readdb_options_additional_fields(&t_opt, ito, filepath);
+
+ /* Allocate memory and copy contents */
+ CREATE(s_opt, struct itemdb_option, 1);
+
+ *s_opt = t_opt;
+
+ /* Store ptr in the database */
+ idb_put(itemdb->options, t_opt.index, s_opt);
+
+ count++;
+ }
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
+
+ libconfig->destroy(&item_options_db);
+
+ VECTOR_CLEAR(duplicate_id);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+}
+
+static void itemdb_read_chains(void)
+{
struct config_t item_chain_conf;
struct config_setting_t *itc = NULL;
-#ifdef RENEWAL
- const char *config_filename = "db/re/item_chain.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/item_chain.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"item_chain.conf", config_filename, sizeof(config_filename));
int i = 0, count = 0;
if (!libconfig->load_file(&item_chain_conf, config_filename))
@@ -1310,7 +1516,7 @@ void itemdb_read_chains(void) {
while( (entry = libconfig->setting_get_elem(itc,c++)) ) {
const char *itname = config_setting_name(entry);
- if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if (itname[0] == 'I' && itname[1] == 'D' && strlen(itname) <= 12) {
if( !( data = itemdb->exists(atoi(itname+2)) ) )
ShowWarning("itemdb_read_chains: unknown item ID '%d' in chain '%s'!\n",atoi(itname+2),name);
} else if( !( data = itemdb->name2id(itname) ) )
@@ -1341,155 +1547,127 @@ void itemdb_read_chains(void) {
else
itemdb->chain_cache[ECC_ORE] = i;
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
-}
-
-/**
- * @return: amount of retrieved entries.
- **/
-int itemdb_combo_split_atoi (char *str, int *val) {
- int i;
-
- nullpo_ret(val);
-
- for (i=0; i<MAX_ITEMS_PER_COMBO; i++) {
- if (!str) break;
-
- val[i] = atoi(str);
- str = strchr(str,':');
- if (str)
- *str++=0;
- }
+ if (!script->get_constant("ITMCHAIN_SIEGFRIED", &i))
+ ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_SIEGFRIED' chain to link to cache!\n");
+ else
+ itemdb->chain_cache[ECC_SIEGFRIED] = i;
- if( i == 0 ) //No data found.
- return 0;
+ if (!script->get_constant("ITMCHAIN_NEO_INSURANCE", &i))
+ ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_NEO_INSURANCE' chain to link to cache!\n");
+ else
+ itemdb->chain_cache[ECC_NEO_INSURANCE] = i;
- return i;
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-/**
- * <combo{:combo{:combo:{..}}}>,<{ script }>
- **/
-void itemdb_read_combos(void)
+
+static bool itemdb_read_combodb_libconfig(void)
{
- uint32 lines = 0, count = 0;
- char line[1024];
+ struct config_t combo_conf;
char filepath[256];
- FILE* fp;
-
- sprintf(filepath, "%s/%s", map->db_path, DBPATH"item_combo_db.txt");
+ safesnprintf(filepath, sizeof(filepath), "%s/%s/%s", map->db_path, DBPATH, "item_combo_db.conf");
- if ((fp = fopen(filepath, "r")) == NULL) {
- ShowError("itemdb_read_combos: File not found \"%s\".\n", filepath);
- return;
+ if (libconfig->load_file(&combo_conf, filepath) == CONFIG_FALSE) {
+ ShowError("itemdb_read_combodb_libconfig: can't read %s\n", filepath);
+ return false;
}
- // process rows one by one
- while(fgets(line, sizeof(line), fp)) {
- char *str[2], *p;
-
- lines++;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
+ struct config_setting_t *combo_db = NULL;
+ if ((combo_db = libconfig->setting_get_member(combo_conf.root, "combo_db")) == NULL) {
+ ShowError("itemdb_read_combodb_libconfig: can't read %s\n", filepath);
+ return false;
+ }
- memset(str, 0, sizeof(str));
+ int i = 0;
+ int count = 0;
+ struct config_setting_t *it = NULL;
- p = line;
- p = trim(p);
- if (*p == '\0')
- continue;// empty line
+ while ((it = libconfig->setting_get_elem(combo_db, i++)) != NULL) {
+ if (itemdb->read_combodb_libconfig_sub(it, i - 1, filepath))
+ ++count;
+ }
- if (!strchr(p,',')) {
- /* is there even a single column? */
- ShowError("itemdb_read_combos: Insufficient columns in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- }
+ libconfig->destroy(&combo_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+ return true;
+}
- str[0] = p;
- p = strchr(p,',');
- *p = '\0';
- p++;
+static bool itemdb_read_combodb_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
- str[1] = p;
- p = strchr(p,',');
- p++;
+ struct config_setting_t *t = NULL;
- if (str[1][0] != '{') {
- ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- }
+ if ((t = libconfig->setting_get_member(it, "Items")) == NULL) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: invalid item list for combo (%d), in (%s), skipping..\n", idx, source);
+ return false;
+ }
- /* no ending key anywhere (missing \}\) */
- if ( str[1][strlen(str[1])-1] != '}' ) {
- ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath);
- continue;
- } else {
- int items[MAX_ITEMS_PER_COMBO];
- int v = 0, retcount = 0;
- struct item_combo *combo = NULL;
+ if (!config_setting_is_array(t)) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: the combo (%d) item list must be an array, in (%s), skipping..\n", idx, source);
+ return false;
+ }
- if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) {
- ShowError("itemdb_read_combos: line %u of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath);
- continue;
- }
+ int len = libconfig->setting_length(t);
+ if (len > MAX_ITEMS_PER_COMBO) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: the size of combo (%d) item list is too big (%d, max = %d), in (%s), skipping..\n", idx, len, MAX_ITEMS_PER_COMBO, source);
+ return false;
+ }
- /* validate */
- for(v = 0; v < retcount; v++) {
- if( !itemdb->exists(items[v]) ) {
- ShowError("itemdb_read_combos: line %u of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath, items[v]);
- break;
- }
- }
- /* failed at some item */
- if( v < retcount )
- continue;
+ struct item_combo *combo = NULL;
+ RECREATE(itemdb->combos, struct item_combo *, ++itemdb->combo_count);
+ CREATE(combo, struct item_combo, 1);
- RECREATE(itemdb->combos, struct item_combo*, ++itemdb->combo_count);
+ combo->id = itemdb->combo_count - 1;
+ combo->count = len;
- CREATE(combo, struct item_combo, 1);
+ for (int i = 0; i < len; i++) {
+ struct item_data *item = NULL;
+ const char *name = libconfig->setting_get_string_elem(t, i);
- combo->count = retcount;
- 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++ ) {
- combo->nameid[v] = items[v];
- }
+ if ((item = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: unknown item '%s', in (%s), skipping..\n", name, source);
+ --itemdb->combo_count;
+ aFree(combo);
+ return false;
+ }
+ combo->nameid[i] = item->nameid;
+ }
- itemdb->combos[itemdb->combo_count - 1] = combo;
+ const char *str = NULL;
+ if (libconfig->setting_lookup_string(it, "Script", &str) == CONFIG_TRUE) {
+ combo->script = *str ? script->parse(str, source, -idx, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ } else {
+ ShowWarning("itemdb_read_combodb_libconfig_sub: invalid script for combo (%d) in (%s), skipping..\n", idx, source);
+ --itemdb->combo_count;
+ aFree(combo);
+ return false;
+ }
- /* populate the items to refer to this combo */
- for( v = 0; v < retcount; v++ ) {
- struct item_data * it;
- int index;
+ itemdb->combos[combo->id] = combo;
- it = itemdb->exists(items[v]);
- index = it->combos_count;
- RECREATE(it->combos, struct item_combo*, ++it->combos_count);
- it->combos[index] = combo;
- }
- }
- count++;
+ /* populate the items to refer to this combo */
+ for (int i = 0; i < len; i++) {
+ struct item_data *item = itemdb->exists(combo->nameid[i]);
+ RECREATE(item->combos, struct item_combo *, ++item->combos_count);
+ item->combos[item->combos_count - 1] = combo;
}
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
-
- return;
+ return true;
}
/*======================================
* Applies gender restrictions according to settings. [Skotlex]
*======================================*/
-int itemdb_gendercheck(struct item_data *id)
+static int itemdb_gendercheck(struct item_data *id)
{
nullpo_ret(id);
if (id->nameid == WEDDING_RING_M) //Grom Ring
return 1;
if (id->nameid == WEDDING_RING_F) //Bride Ring
return 0;
- if (id->look == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only
+ if (id->subtype == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only
return 1;
- if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only
+ if (id->subtype == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only
return 0;
return (battle_config.ignore_items_gender) ? 2 : id->sex;
@@ -1512,14 +1690,20 @@ int itemdb_gendercheck(struct item_data *id)
* (i.e. item_db2 inheritance), as it will make sure not to free any scripts
* still in use by the new entry.
*/
-int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
+static int itemdb_validate_entry(struct item_data *entry, int n, const char *source)
+{
struct item_data *item;
nullpo_ret(entry);
nullpo_ret(source);
- if( entry->nameid <= 0 || entry->nameid >= MAX_ITEMDB ) {
- ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEMDB), skipping.\n",
- entry->nameid, n, source, MAX_ITEMDB);
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ if (entry->nameid <= 0 || entry->nameid > MAX_ITEM_ID) {
+#else
+ if (entry->nameid <= 0) {
+#endif
+ // item id wrong for any packet versions
+ ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEM_ID), skipping.\n",
+ entry->nameid, n, source, MAX_ITEM_ID);
if (entry->script) {
script->free_code(entry->script);
entry->script = NULL;
@@ -1532,7 +1716,54 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
script->free_code(entry->unequip_script);
entry->unequip_script = NULL;
}
+ if (entry->rental_start_script != NULL) {
+ script->free_code(entry->rental_start_script);
+ entry->rental_start_script = NULL;
+ }
+ if (entry->rental_end_script != NULL) {
+ script->free_code(entry->rental_end_script);
+ entry->rental_end_script = NULL;
+ }
return 0;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ }
+#else
+ } else if (entry->nameid > MAX_ITEM_ID) {
+ // item id too big for packet version before item id in 4 bytes
+ entry->view_id = UNKNOWN_ITEM_ID;
+ }
+#endif
+
+ {
+ const char *c = entry->name;
+ while (ISALNUM(*c) || *c == '_')
+ ++c;
+
+ if (*c != '\0') {
+ ShowWarning("itemdb_validate_entry: Invalid characters in the AegisName '%s' for item %d in '%s'. Skipping.\n",
+ entry->name, entry->nameid, source);
+ if (entry->script) {
+ script->free_code(entry->script);
+ entry->script = NULL;
+ }
+ if (entry->equip_script) {
+ script->free_code(entry->equip_script);
+ entry->equip_script = NULL;
+ }
+ if (entry->unequip_script) {
+ script->free_code(entry->unequip_script);
+ entry->unequip_script = NULL;
+ }
+ if (entry->rental_start_script != NULL) {
+ script->free_code(entry->rental_start_script);
+ entry->rental_start_script = NULL;
+ }
+ if (entry->rental_end_script != NULL) {
+ script->free_code(entry->rental_end_script);
+ entry->rental_end_script = NULL;
+ }
+ return 0;
+ }
}
if( entry->type < 0 || entry->type == IT_UNKNOWN || entry->type == IT_UNKNOWN2
@@ -1613,10 +1844,14 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
memset(&entry->stack, '\0', sizeof(entry->stack));
}
- if (entry->type == IT_WEAPON && (entry->look < 0 || entry->look >= MAX_SINGLE_WEAPON_TYPE)) {
- ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to 1.\n",
- entry->look, entry->nameid, entry->jname, source);
- entry->look = 1;
+ if (entry->type == IT_WEAPON && (entry->subtype <= 0 || entry->subtype >= MAX_SINGLE_WEAPON_TYPE)) {
+ ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to W_DAGGER.\n",
+ entry->subtype, entry->nameid, entry->jname, source);
+ entry->subtype = W_DAGGER;
+ } else if (entry->type == IT_AMMO && (entry->subtype <= 0 || entry->subtype >= MAX_AMMO_TYPE)) {
+ ShowWarning("itemdb_validate_entry: Invalid View for ammunition items. View value %d for item %d (%s) in '%s', defaulting to A_ARROW.\n",
+ entry->subtype, entry->nameid, entry->jname, source);
+ entry->subtype = A_ARROW;
}
entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
@@ -1629,6 +1864,9 @@ 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;
+ if (entry->type != IT_ARMOR && entry->type != IT_WEAPON && !entry->flag.no_options)
+ entry->flag.no_options = 1;
+
if (entry->flag.available != 1) {
entry->flag.available = 1;
entry->view_id = 0;
@@ -1651,14 +1889,21 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
script->free_code(item->unequip_script);
item->unequip_script = NULL;
}
-
+ if (item->rental_start_script != NULL && item->rental_start_script != entry->rental_start_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->rental_start_script);
+ item->rental_start_script = NULL;
+ }
+ if (item->rental_end_script != NULL && item->rental_end_script != entry->rental_end_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->rental_end_script);
+ item->rental_end_script = NULL;
+ }
*item = *entry;
return item->nameid;
}
-void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source)
+static void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source)
{
- // do nothing. plugins can do own work
+ // do nothing. plugins can do own work
}
/**
@@ -1668,7 +1913,7 @@ void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, in
* @param t Libconfig setting entry. It is expected to be valid and it won't
* be freed (it is care of the caller to do so if necessary).
*/
-void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
+static void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
{
int idx = 0;
struct config_setting_t *it = NULL;
@@ -1707,7 +1952,8 @@ void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
* validation errors.
* @return Nameid of the validated entry, or 0 in case of failure.
*/
-int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source) {
+static int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source)
+{
struct item_data id = { 0 };
struct config_setting_t *t = NULL;
const char *str = NULL;
@@ -1766,13 +2012,15 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
* ">
* OnEquipScript: <" OnEquip Script ">
* OnUnequipScript: <" OnUnequip Script ">
+ * OnRentalStartScript: <" on renting script ">
+ * OnRentalEndScript: <" on renting end script ">
* Inherit: inherit or override
*/
if( !itemdb->lookup_const(it, "Id", &i32) ) {
ShowWarning("itemdb_readdb_libconfig_sub: Invalid or missing id in \"%s\", entry #%d, skipping.\n", source, n);
return 0;
}
- id.nameid = (uint16)i32;
+ id.nameid = i32;
if( (t = libconfig->setting_get_member(it, "Inherit")) && (inherit = libconfig->setting_get_bool(t)) ) {
if( !itemdb->exists(id.nameid) ) {
@@ -1808,6 +2056,14 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
else if( !inherit )
id.type = IT_ETC;
+ if (itemdb->lookup_const(it, "Subtype", &i32) && i32 >= 0) {
+ if (id.type == IT_WEAPON || id.type == IT_AMMO)
+ id.subtype = i32;
+ else
+ ShowWarning("itemdb_readdb_libconfig_sub: Field 'Subtype' is only allowed for IT_WEAPON or IT_AMMO (Item #%d: %s). Ignoring.\n",
+ id.nameid, id.name);
+ }
+
if( itemdb->lookup_const(it, "Buy", &i32) )
id.value_buy = i32;
else if( !inherit )
@@ -1847,7 +2103,7 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
itemdb->jobmask2mapid(id.class_base, UINT64_MAX);
}
- if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 )
+ if (itemdb->lookup_const_mask(it, "Upper", &i32) && i32 >= 0)
id.class_upper = (unsigned int)i32;
else if( !inherit )
id.class_upper = ITEMUPPER_ALL;
@@ -1857,7 +2113,7 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
else if( !inherit )
id.sex = 2;
- if( itemdb->lookup_const(it, "Loc", &i32) && i32 >= 0 )
+ if (itemdb->lookup_const_mask(it, "Loc", &i32) && i32 >= 0)
id.equip = i32;
if( itemdb->lookup_const(it, "WeaponLv", &i32) && i32 >= 0 )
@@ -1877,8 +2133,32 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if( (t = libconfig->setting_get_member(it, "Refine")) )
id.flag.no_refine = libconfig->setting_get_bool(t) ? 0 : 1;
- if( itemdb->lookup_const(it, "View", &i32) && i32 >= 0 )
- id.look = i32;
+ if ((t = libconfig->setting_get_member(it, "DisableOptions")))
+ id.flag.no_options = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if ((t = libconfig->setting_get_member(it, "ShowDropEffect")))
+ id.flag.showdropeffect = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if (itemdb->lookup_const(it, "DropEffectMode", &i32) && i32 >= 0)
+ id.dropeffectmode = i32;
+
+ if (itemdb->lookup_const(it, "ViewSprite", &i32) && i32 >= 0)
+ id.view_sprite = i32;
+
+ if (itemdb->lookup_const(it, "View", &i32) && i32 >= 0) { // TODO: Remove (Deprecated - 2016-09-04 [Haru])
+ if ((id.type == IT_WEAPON || id.type == IT_AMMO) && id.subtype == 0) {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'Subtype' (or 'ViewSprite'). (Item #%d: %s)\n",
+ id.nameid, id.name);
+ id.subtype = i32;
+ } else if ((id.type != IT_WEAPON && id.type != IT_AMMO) && id.view_sprite == 0) {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'ViewSprite' (or 'Subtype'). (Item #%d: %s)\n",
+ id.nameid, id.name);
+ id.view_sprite = i32;
+ } else {
+ ShowWarning("itemdb_readdb_libconfig_sub: The 'View' field is deprecated. Please rename it to 'Subtype' or 'ViewSprite'. (Item #%d: %s)\n",
+ id.nameid, id.name);
+ }
+ }
if( (t = libconfig->setting_get_member(it, "BindOnEquip")) )
id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0;
@@ -1892,6 +2172,9 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if ((t = libconfig->setting_get_member(it, "KeepAfterUse")))
id.flag.keepafteruse = libconfig->setting_get_bool(t) ? 1 : 0;
+ if ((t = libconfig->setting_get_member(it, "DropAnnounce")))
+ id.flag.drop_announce = libconfig->setting_get_bool(t) ? 1 : 0;
+
if (itemdb->lookup_const(it, "Delay", &i32) && i32 >= 0)
id.delay = i32;
@@ -2008,26 +2291,87 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if( libconfig->setting_lookup_string(it, "OnUnequipScript", &str) )
id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ if (libconfig->setting_lookup_string(it, "OnRentalStartScript", &str) != CONFIG_FALSE)
+ id.rental_start_script = (*str != '\0') ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ if (libconfig->setting_lookup_string(it, "OnRentalEndScript", &str) != CONFIG_FALSE)
+ id.rental_end_script = (*str != '\0') ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
return itemdb->validate_entry(&id, n, source);
}
-bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value)
+static bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value)
{
+ const char *str = NULL;
+
nullpo_retr(false, name);
nullpo_retr(false, value);
- if (libconfig->setting_lookup_int(it, name, value))
- {
+
+ if (libconfig->setting_lookup_int(it, name, value)) {
return true;
}
- else
- {
+
+ if (libconfig->setting_lookup_string(it, name, &str)) {
+ if (*str && script->get_constant(str, value))
+ return true;
+ }
+
+ return false;
+}
+
+static bool itemdb_lookup_const_mask(const struct config_setting_t *it, const char *name, int *value)
+{
+ const struct config_setting_t *t = NULL;
+
+ nullpo_retr(false, it);
+ nullpo_retr(false, name);
+ nullpo_retr(false, value);
+
+ if ((t = libconfig->setting_get_member(it, name)) == NULL) {
+ return false;
+ }
+
+ if (config_setting_is_scalar(t)) {
const char *str = NULL;
- if (libconfig->setting_lookup_string(it, name, &str))
- {
- if (*str && script->get_constant(str, value))
+
+ if (config_setting_is_number(t)) {
+ *value = libconfig->setting_get_int(t);
+ return true;
+ }
+
+ if ((str = libconfig->setting_get_string(t)) != NULL) {
+ int i32 = -1;
+ if (script->get_constant(str, &i32) && i32 >= 0) {
+ *value = i32;
return true;
+ }
+ }
+
+ return false;
+ }
+
+ if (config_setting_is_aggregate(t) && libconfig->setting_length(t) >= 1) {
+ const struct config_setting_t *elem = NULL;
+ int i = 0;
+
+ *value = 0;
+
+ while ((elem = libconfig->setting_get_elem(t, i++)) != NULL) {
+ const char *str = libconfig->setting_get_string(elem);
+ int i32 = -1;
+
+ if (str == NULL)
+ return false;
+
+ if (!script->get_constant(str, &i32) || i32 < 0)
+ return false;
+
+ *value |= i32;
}
+
+ return true;
}
+
return false;
}
@@ -2038,8 +2382,10 @@ bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, in
* @param filename File name, relative to the database path.
* @return The number of found entries.
*/
-int itemdb_readdb_libconfig(const char *filename) {
+static int itemdb_readdb_libconfig(const char *filename)
+{
bool duplicate[MAX_ITEMDB];
+ struct DBMap *duplicate_db;
struct config_t item_db_conf;
struct config_setting_t *itdb, *it;
char filepath[256];
@@ -2047,7 +2393,7 @@ int itemdb_readdb_libconfig(const char *filename) {
nullpo_ret(filename);
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&item_db_conf, filepath))
return 0;
@@ -2056,43 +2402,149 @@ int itemdb_readdb_libconfig(const char *filename) {
return 0;
}
+ // TODO add duplicates check for itemdb->other
memset(&duplicate,0,sizeof(duplicate));
+ duplicate_db = idb_alloc(DB_OPT_BASE);
while( (it = libconfig->setting_get_elem(itdb,i++)) ) {
int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename);
- if (nameid <= 0 || nameid >= MAX_ITEMDB)
+ if (nameid <= 0 || nameid > MAX_ITEM_ID)
continue;
itemdb->readdb_additional_fields(nameid, it, i - 1, filename);
count++;
- if( duplicate[nameid] ) {
- ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
- filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
- } else
- duplicate[nameid] = true;
+ if (nameid < MAX_ITEMDB) {
+ if (duplicate[nameid]) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
+ filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
+ } else {
+ duplicate[nameid] = true;
+ }
+ } else {
+ if (idb_exists(duplicate_db, nameid)) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
+ filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
+ } else {
+ idb_iput(duplicate_db, nameid, true);
+ }
+ }
}
+ db_destroy(duplicate_db);
libconfig->destroy(&item_db_conf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
-
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
return count;
}
/*==========================================
-* Unique item ID function
-* Only one operation by once
-*------------------------------------------*/
-uint64 itemdb_unique_id(struct map_session_data *sd) {
+ * Unique item ID function
+ * Only one operation by once
+ *------------------------------------------*/
+static uint64 itemdb_unique_id(struct map_session_data *sd)
+{
nullpo_ret(sd);
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
+static bool itemdb_read_libconfig_lapineddukddak(void)
+{
+ struct config_t item_lapineddukddak;
+ struct config_setting_t *it = NULL;
+ char filepath[256];
+
+ int i = 0;
+ int count = 0;
+
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, DBPATH"item_lapineddukddak.conf");
+ if (libconfig->load_file(&item_lapineddukddak, filepath) == CONFIG_FALSE)
+ return false;
+
+ while ((it = libconfig->setting_get_elem(item_lapineddukddak.root, i++)) != NULL) {
+ if (itemdb->read_libconfig_lapineddukddak_sub(it, filepath))
+ ++count;
+ }
+
+ libconfig->destroy(&item_lapineddukddak);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+ return true;
+}
+
+static bool itemdb_read_libconfig_lapineddukddak_sub(struct config_setting_t *it, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
+
+ struct item_data *data = NULL;
+ const char *name = config_setting_name(it);
+ const char *str = NULL;
+ int i32 = 0;
+
+ if ((data = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: unknown item '%s', skipping..\n", name);
+ return false;
+ }
+
+ data->lapineddukddak = aCalloc(1, sizeof(struct item_lapineddukddak));
+ if (libconfig->setting_lookup_int(it, "NeedCount", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedCount = (int16)i32;
+
+ if (libconfig->setting_lookup_int(it, "NeedRefineMin", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedRefineMin = (int8)i32;
+
+ if (libconfig->setting_lookup_int(it, "NeedRefineMax", &i32) == CONFIG_TRUE)
+ data->lapineddukddak->NeedRefineMax = (int8)i32;
+
+ struct config_setting_t *sources = libconfig->setting_get_member(it, "SourceItems");
+ itemdb->read_libconfig_lapineddukddak_sub_sources(sources, data);
+
+ if (libconfig->setting_lookup_string(it, "Script", &str) == CONFIG_TRUE)
+ data->lapineddukddak->script = *str ? script->parse(str, source, -data->nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ return true;
+}
+
+static bool itemdb_read_libconfig_lapineddukddak_sub_sources(struct config_setting_t *sources, struct item_data *data)
+{
+ nullpo_retr(false, data);
+ nullpo_retr(false, data->lapineddukddak);
+
+ int i = 0;
+ struct config_setting_t *entry = NULL;
+
+ if (sources == NULL || !config_setting_is_group(sources))
+ return false;
+
+ VECTOR_INIT(data->lapineddukddak->SourceItems);
+ while ((entry = libconfig->setting_get_elem(sources, i++)) != NULL) {
+ struct item_data *edata = NULL;
+ struct itemlist_entry item = { 0 };
+ const char *name = config_setting_name(entry);
+ int i32 = 0;
+
+ if ((edata = itemdb->name2id(name)) == NULL) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: unknown item '%s', skipping..\n", name);
+ continue;
+ }
+ item.id = edata->nameid;
+
+ if ((i32 = libconfig->setting_get_int(entry)) == CONFIG_TRUE && (i32 <= 0 || i32 > MAX_AMOUNT)) {
+ ShowWarning("itemdb_read_libconfig_lapineddukddak_sub: invalid amount (%d) for source item '%s', skipping..\n", i32, name);
+ continue;
+ }
+ item.amount = i32;
+
+ VECTOR_ENSURE(data->lapineddukddak->SourceItems, 1, 1);
+ VECTOR_PUSH(data->lapineddukddak->SourceItems, item);
+ }
+ return true;
+}
+
/**
* Reads all item-related databases.
*/
-void itemdb_read(bool minimal) {
+static void itemdb_read(bool minimal)
+{
int i;
struct DBData prev;
@@ -2103,6 +2555,7 @@ void itemdb_read(bool minimal) {
for (i = 0; i < ARRAYLENGTH(filename); i++)
itemdb->readdb_libconfig(filename[i]);
+ // TODO check duplicate names also in itemdb->other
for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
if( itemdb->array[i] ) {
if( itemdb->names->put(itemdb->names,DB->str2key(itemdb->array[i]->name),DB->ptr2data(itemdb->array[i]),&prev) ) {
@@ -2112,20 +2565,44 @@ void itemdb_read(bool minimal) {
}
}
+ itemdb->other->foreach(itemdb->other, itemdb->addname_sub);
+
+ itemdb->read_options();
+
if (minimal)
return;
- itemdb->read_combos();
+ itemdb->name_constants();
+
+ itemdb->read_combodb_libconfig();
itemdb->read_groups();
itemdb->read_chains();
itemdb->read_packages();
+ itemdb->read_libconfig_lapineddukddak();
+}
+
+/**
+ * Add item name with high id into map
+ * @see DBApply
+ */
+static int itemdb_addname_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct item_data *item = DB->data2ptr(data);
+ struct DBData prev;
+ if (itemdb->names->put(itemdb->names, DB->str2key(item->name), DB->ptr2data(item), &prev)) {
+ struct item_data *oldItem = DB->data2ptr(&prev);
+ ShowError("itemdb_read: duplicate AegisName '%s' in item ID %d and %d\n", item->name, item->nameid, oldItem->nameid);
+ }
+
+ return 0;
}
/**
* retrieves item_combo data by combo id
**/
-struct item_combo * itemdb_id2combo( unsigned short id ) {
+static struct item_combo *itemdb_id2combo(int id)
+{
if( id > itemdb->combo_count )
return NULL;
return itemdb->combos[id];
@@ -2134,7 +2611,7 @@ struct item_combo * itemdb_id2combo( unsigned short id ) {
/**
* check is item have usable type
**/
-bool itemdb_is_item_usable(struct item_data *item)
+static bool itemdb_is_item_usable(struct item_data *item)
{
nullpo_retr(false, item);
return item->type == IT_HEALING || item->type == IT_USABLE || item->type == IT_CASH;
@@ -2145,7 +2622,7 @@ bool itemdb_is_item_usable(struct item_data *item)
*------------------------------------------*/
/// Destroys the item_data.
-void destroy_item_data(struct item_data* self, int free_self)
+static void destroy_item_data(struct item_data *self, int free_self)
{
if( self == NULL )
return;
@@ -2156,8 +2633,18 @@ void destroy_item_data(struct item_data* self, int free_self)
script->free_code(self->equip_script);
if( self->unequip_script )
script->free_code(self->unequip_script);
+ if (self->rental_start_script != NULL)
+ script->free_code(self->rental_start_script);
+ if (self->rental_end_script != NULL)
+ script->free_code(self->rental_end_script);
if( self->combos )
aFree(self->combos);
+ if (self->lapineddukddak != NULL) {
+ if (self->lapineddukddak->script != NULL)
+ script->free_code(self->lapineddukddak->script);
+ VECTOR_CLEAR(self->lapineddukddak->SourceItems);
+ aFree(self->lapineddukddak);
+ }
HPM->data_store_destroy(&self->hdata);
#if defined(DEBUG)
// trash item
@@ -2171,7 +2658,7 @@ void destroy_item_data(struct item_data* self, int free_self)
/**
* @see DBApply
*/
-int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
+static int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *id = DB->data2ptr(data);
@@ -2180,7 +2667,19 @@ int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-void itemdb_clear(bool total) {
+
+static int itemdb_options_final_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct itemdb_option *ito = DB->data2ptr(data);
+
+ if (ito->script != NULL)
+ script->free_code(ito->script);
+
+ return 0;
+}
+
+static void itemdb_clear(bool total)
+{
int i;
// clear the previous itemdb data
for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
@@ -2243,13 +2742,15 @@ void itemdb_clear(bool total) {
return;
itemdb->other->clear(itemdb->other, itemdb->final_sub);
+ itemdb->options->clear(itemdb->options, itemdb->options_final_sub);
memset(itemdb->array, 0, sizeof(itemdb->array));
db_clear(itemdb->names);
}
-void itemdb_reload(void) {
+static void itemdb_reload(void)
+{
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -2293,21 +2794,25 @@ void itemdb_reload(void) {
for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays
pc->setinventorydata(sd);
- if( battle_config.item_check )
- sd->state.itemcheck = 1;
+
+ if (battle->bc->item_check != PCCHECKITEM_NONE) // Check and flag items for inspection.
+ sd->itemcheck = (enum pc_checkitem_types) battle->bc->item_check;
+
/* clear combo bonuses */
- if( sd->combo_count ) {
+ if (sd->combo_count) {
aFree(sd->combos);
sd->combos = NULL;
sd->combo_count = 0;
if( pc->load_combo(sd) > 0 )
status_calc_pc(sd,SCO_FORCE);
}
+
+ // Check for and delete unavailable/disabled items.
pc->checkitem(sd);
}
mapit->free(iter);
}
-void itemdb_name_constants(void)
+static void itemdb_name_constants(void)
{
struct DBIterator *iter = db_iterator(itemdb->names);
struct item_data *data;
@@ -2323,17 +2828,22 @@ void itemdb_name_constants(void)
dbi_destroy(iter);
}
-void do_final_itemdb(void) {
+static void do_final_itemdb(void)
+{
itemdb->clear(true);
itemdb->other->destroy(itemdb->other, itemdb->final_sub);
+ itemdb->options->destroy(itemdb->options, itemdb->options_final_sub);
itemdb->destroy_item_data(&itemdb->dummy, 0);
db_destroy(itemdb->names);
+ VECTOR_CLEAR(clif->attendance_data);
}
-void do_init_itemdb(bool minimal) {
+static void do_init_itemdb(bool minimal)
+{
memset(itemdb->array, 0, sizeof(itemdb->array));
itemdb->other = idb_alloc(DB_OPT_BASE);
+ itemdb->options = idb_alloc(DB_OPT_RELEASE_DATA);
itemdb->names = strdb_alloc(DB_OPT_BASE,ITEM_NAME_LENGTH);
itemdb->create_dummy_data(); //Dummy data item.
itemdb->read(minimal);
@@ -2346,8 +2856,11 @@ void do_init_itemdb(bool minimal) {
/** it failed? we disable it **/
if (battle_config.feature_roulette == 1 && !clif->parse_roulette_db())
battle_config.feature_roulette = 0;
+ VECTOR_INIT(clif->attendance_data);
+ clif->pAttendanceDB();
}
-void itemdb_defaults(void) {
+void itemdb_defaults(void)
+{
itemdb = &itemdb_s;
itemdb->init = do_init_itemdb;
@@ -2376,6 +2889,7 @@ void itemdb_defaults(void) {
itemdb->read_groups = itemdb_read_groups;
itemdb->read_chains = itemdb_read_chains;
itemdb->read_packages = itemdb_read_packages;
+ itemdb->read_options = itemdb_read_options;
/* */
itemdb->write_cached_packages = itemdb_write_cached_packages;
itemdb->read_cached_packages = itemdb_read_cached_packages;
@@ -2386,6 +2900,7 @@ void itemdb_defaults(void) {
itemdb->load = itemdb_load;
itemdb->search = itemdb_search;
itemdb->exists = itemdb_exists;
+ itemdb->option_exists = itemdb_option_exists;
itemdb->in_group = itemdb_in_group;
itemdb->group_item = itemdb_searchrandomid;
itemdb->chain_item = itemdb_chain_item;
@@ -2414,10 +2929,11 @@ void itemdb_defaults(void) {
itemdb->isrestricted = itemdb_isrestricted;
itemdb->isidentified = itemdb_isidentified;
itemdb->isidentified2 = itemdb_isidentified2;
- itemdb->combo_split_atoi = itemdb_combo_split_atoi;
- itemdb->read_combos = itemdb_read_combos;
+ itemdb->read_combodb_libconfig = itemdb_read_combodb_libconfig;
+ itemdb->read_combodb_libconfig_sub = itemdb_read_combodb_libconfig_sub;
itemdb->gendercheck = itemdb_gendercheck;
itemdb->validate_entry = itemdb_validate_entry;
+ itemdb->readdb_options_additional_fields = itemdb_readdb_options_additional_fields;
itemdb->readdb_additional_fields = itemdb_readdb_additional_fields;
itemdb->readdb_job_sub = itemdb_readdb_job_sub;
itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub;
@@ -2426,8 +2942,14 @@ void itemdb_defaults(void) {
itemdb->read = itemdb_read;
itemdb->destroy_item_data = destroy_item_data;
itemdb->final_sub = itemdb_final_sub;
+ itemdb->options_final_sub = itemdb_options_final_sub;
itemdb->clear = itemdb_clear;
itemdb->id2combo = itemdb_id2combo;
itemdb->is_item_usable = itemdb_is_item_usable;
itemdb->lookup_const = itemdb_lookup_const;
+ itemdb->lookup_const_mask = itemdb_lookup_const_mask;
+ itemdb->addname_sub = itemdb_addname_sub;
+ itemdb->read_libconfig_lapineddukddak = itemdb_read_libconfig_lapineddukddak;
+ itemdb->read_libconfig_lapineddukddak_sub = itemdb_read_libconfig_lapineddukddak_sub;
+ itemdb->read_libconfig_lapineddukddak_sub_sources = itemdb_read_libconfig_lapineddukddak_sub_sources;
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index d33805174..5f0790b10 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,10 +33,29 @@ struct hplugin_data_store;
/**
* Defines
**/
-#define MAX_ITEMDB 0x8000 // 32k array entries in array (the rest goes to the db)
+#ifndef MAX_ITEMDB
+#define MAX_ITEMDB 0xFFFF
+#endif
+
+#ifndef MAX_ITEM_ID
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+#define MAX_ITEM_ID INT32_MAX
+#else
+#define MAX_ITEM_ID 0xFFFF
+#endif
+#endif
+
+#ifndef MAX_ITEMDELAYS
#define MAX_ITEMDELAYS 10 // The maximum number of item delays
+#endif
+
+#ifndef MAX_SEARCH
#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display.
+#endif
+
+#ifndef MAX_ITEMS_PER_COMBO
#define MAX_ITEMS_PER_COMBO 6 /* maximum amount of items a combo may require */
+#endif
#define CARD0_FORGE 0x00FF
#define CARD0_CREATE 0x00FE
@@ -45,8 +64,17 @@ struct hplugin_data_store;
//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
#define itemdb_isspecial(i) ((i) == CARD0_FORGE || (i) == CARD0_CREATE || (i) == CARD0_PET)
+#ifndef UNKNOWN_ITEM_ID
//Use apple for unknown items.
#define UNKNOWN_ITEM_ID 512
+#endif
+
+#if MAX_ITEM_ID < MAX_ITEMDB
+#error "MAX_ITEM_ID must be bigger or same with MAX_ITEMDB"
+#endif
+#if MAX_ITEM_ID > 0xFFFF && PACKETVER_MAIN_NUM < 20181121 && PACKETVER_RE_NUM < 20180704 && PACKETVER_ZERO_NUM < 20181114
+#error "For clients before 20181121 Main and 20180704 RE and 20181114 zero, MAX_ITEM_ID must be smaller than 0x10000"
+#endif
enum item_itemid {
ITEMID_RED_POTION = 501,
@@ -54,6 +82,7 @@ enum item_itemid {
ITEMID_WHITE_POTION = 504,
ITEMID_BLUE_POTION = 505,
ITEMID_APPLE = 512,
+ ITEMID_CARROT = 515,
ITEMID_HOLY_WATER = 523,
ITEMID_PUMPKIN = 535,
ITEMID_RED_SLIM_POTION = 545,
@@ -64,8 +93,10 @@ enum item_itemid {
ITEMID_BRANCH_OF_DEAD_TREE = 604,
ITEMID_ANODYNE = 605,
ITEMID_ALOEBERA = 606,
- ITEMID_MAGNIFIER = 611,
+ ITEMID_SPECTACLES = 611,
ITEMID_POISON_BOTTLE = 678,
+ ITEMID_EARTH_SCROLL_1_3 = 686,
+ ITEMID_EARTH_SCROLL_1_5 = 687,
ITEMID_EMPTY_BOTTLE = 713,
ITEMID_EMPERIUM = 714,
ITEMID_YELLOW_GEMSTONE = 715,
@@ -92,15 +123,16 @@ enum item_itemid {
ITEMID_IRON_ORE = 1002,
ITEMID_PHRACON = 1010,
ITEMID_EMVERETARCON = 1011,
- ITEMID_TRAP = 1065,
+ ITEMID_BOOBY_TRAP = 1065,
ITEMID_PILEBUNCKER = 1549,
ITEMID_ANGRA_MANYU = 1599,
ITEMID_STRANGE_EMBRYO = 6415,
ITEMID_FACE_PAINT = 6120,
- ITEMID_SCARLET_POINT = 6360,
- ITEMID_INDIGO_POINT = 6361,
- ITEMID_YELLOW_WISH_POINT = 6362,
- ITEMID_LIME_GREEN_POINT = 6363,
+ ITEMID_SCARLET_PTS = 6360,
+ ITEMID_INDIGO_PTS = 6361,
+ ITEMID_YELLOW_WISH_PTS = 6362,
+ ITEMID_LIME_GREEN_PTS = 6363,
+ ITEMID_BLACKSMITH_BLESSING = 6635,
ITEMID_STONE = 7049,
ITEMID_FIRE_BOTTLE = 7135,
ITEMID_ACID_BOTTLE = 7136,
@@ -109,10 +141,8 @@ enum item_itemid {
ITEMID_COATING_BOTTLE = 7139,
ITEMID_FRAGMENT_OF_CRYSTAL = 7321,
ITEMID_SKULL_ = 7420,
- ITEMID_TOKEN_OF_SIEGFRIED = 7621,
- ITEMID_GOLD_KEY77 = 7782,
- ITEMID_SILVER_KEY77 = 7783,
- ITEMID_TRAP_ALLOY = 7940,
+ ITEMID_SPECIAL_ALLOY_TRAP = 7940,
+ ITEMID_CATNIP_FRUIT = 11602,
ITEMID_RED_POUCH_OF_SURPRISE = 12024,
ITEMID_BLOODY_DEAD_BRANCH = 12103,
ITEMID_PORING_BOX = 12109,
@@ -137,14 +167,34 @@ enum item_itemid {
ITEMID_MAGIC_CASTLE = 12308,
ITEMID_BULGING_HEAD = 12309,
ITEMID_THICK_MANUAL50 = 12312,
- ITEMID_NOVICE_MAGNIFIER = 12325,
- ITEMID_ANCILLA = 12333,
- ITEMID_REPAIR_A = 12392,
- ITEMID_REPAIR_B = 12393,
- ITEMID_REPAIR_C = 12394,
+ ITEMID_N_FLY_WING = 12323,
+ ITEMID_N_BUTTERFLY_WING = 12324,
+ ITEMID_N_MAGNIFIER = 12325,
+ ITEMID_ANSILA = 12333,
+ ITEMID_REPAIRA = 12392,
+ ITEMID_REPAIRB = 12393,
+ ITEMID_REPAIRC = 12394,
ITEMID_BLACK_THING = 12435,
- ITEMID_REINS_OF_MOUNT = 12622,
+ ITEMID_BOARDING_HALTER = 12622,
ITEMID_NOBLE_NAMEPLATE = 12705,
+ ITEMID_POISON_PARALYSIS = 12717,
+ ITEMID_POISON_LEECH = 12718,
+ ITEMID_POISON_OBLIVION = 12719,
+ ITEMID_POISON_CONTAMINATION = 12720,
+ ITEMID_POISON_NUMB = 12721,
+ ITEMID_POISON_FEVER = 12722,
+ ITEMID_POISON_LAUGHING = 12723,
+ ITEMID_POISON_FATIGUE = 12724,
+ ITEMID_NAUTHIZ = 12725,
+ ITEMID_RAIDO = 12726,
+ ITEMID_BERKANA = 12727,
+ ITEMID_ISA = 12728,
+ ITEMID_OTHILA = 12729,
+ ITEMID_URUZ = 12730,
+ ITEMID_THURISAZ = 12731,
+ ITEMID_WYRD = 12732,
+ ITEMID_HAGALAZ = 12733,
+ ITEMID_C_WING_OF_FLY = 12887,
ITEMID_DUN_TELE_SCROLL1 = 14527,
ITEMID_BATTLE_MANUAL25 = 14532,
ITEMID_BATTLE_MANUAL100 = 14533,
@@ -159,6 +209,7 @@ enum item_itemid {
ITEMID_PILEBUNCKER_S = 16030,
ITEMID_PILEBUNCKER_P = 16031,
ITEMID_PILEBUNCKER_T = 16032,
+ ITEMID_LUX_ANIMA = 22540,
};
enum cards_item_list {
@@ -248,49 +299,6 @@ enum mercenary_scroll_item_list {
};
/**
- * Cash Food
- */
-enum cash_food_item_list {
- ITEMID_STR_DISH10_ = 12202,
- ITEMID_AGI_DISH10_, // 12203
- ITEMID_INT_DISH10_, // 12204
- ITEMID_DEX_DISH10_, // 12205
- ITEMID_LUK_DISH10_, // 12206
- ITEMID_VIT_DISH10_, // 12207
-};
-
-/**
- * GC Poison
- */
-enum poison_item_list {
- ITEMID_POISON_PARALYSIS = 12717,
- ITEMID_POISON_LEECH, // 12718
- ITEMID_POISON_OBLIVION, // 12719
- ITEMID_POISON_CONTAMINATION, // 12720
- ITEMID_POISON_NUMB, // 12721
- ITEMID_POISON_FEVER, // 12722
- ITEMID_POISON_LAUGHING, // 12723
- ITEMID_POISON_FATIGUE, // 12724
-};
-
-
-/**
- * Rune Knight
- **/
-enum rune_item_list {
- ITEMID_NAUTHIZ = 12725,
- ITEMID_RAIDO, // 12726
- ITEMID_BERKANA, // 12727
- ITEMID_ISA, // 12728
- ITEMID_OTHILA, // 12729
- ITEMID_URUZ, // 12730
- ITEMID_THURISAZ, // 12731
- ITEMID_WYRD, // 12732
- ITEMID_HAGALAZ, // 12733
- ITEMID_LUX_ANIMA = 22540,
-};
-
-/**
* Geneticist
*/
enum geneticist_item_list {
@@ -352,6 +360,8 @@ enum geneticist_item_list {
//
enum e_chain_cache {
ECC_ORE,
+ ECC_SIEGFRIED,
+ ECC_NEO_INSURANCE,
/* */
ECC_MAX,
};
@@ -362,7 +372,7 @@ enum item_class_upper {
ITEMUPPER_UPPER = 0x02,
ITEMUPPER_BABY = 0x04,
ITEMUPPER_THIRD = 0x08,
- ITEMUPPER_THURDUPPER = 0x10,
+ ITEMUPPER_THIRDUPPER = 0x10,
ITEMUPPER_THIRDBABY = 0x20,
ITEMUPPER_ALL = 0x3f, // Sum of all the above
};
@@ -386,7 +396,7 @@ enum ItemTradeRestrictions {
};
/**
- * Iten No-use restrictions
+ * Item No-use restrictions
*/
enum ItemNouseRestrictions {
INR_NONE = 0x0, ///< No restrictions
@@ -395,6 +405,26 @@ enum ItemNouseRestrictions {
INR_ALL = 0x1 ///< Sum of all the above values
};
+/**
+ * Item Option Types
+ */
+enum ItemOptionTypes {
+ IT_OPT_INDEX = 0,
+ IT_OPT_VALUE,
+ IT_OPT_PARAM,
+ IT_OPT_MAX
+};
+
+/**
+ * Item name search flags
+ **/
+
+enum item_name_search_flag {
+ IT_SEARCH_NAME_PARTIAL,
+ IT_SEARCH_NAME_EXACT,
+ IT_SEARCH_NAME_MAX,
+};
+
/** Convenience item list (entry) used in various functions */
struct itemlist_entry {
int id; ///< Item ID or (inventory) index
@@ -405,19 +435,19 @@ VECTOR_STRUCT_DECL(itemlist, struct itemlist_entry);
struct item_combo {
struct script_code *script;
- unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */
+ int nameid[MAX_ITEMS_PER_COMBO];/* nameid array */
unsigned char count;
- unsigned short id;/* id of this combo */
+ int id; /* id of this combo */
};
struct item_group {
- unsigned short id;
- unsigned short *nameid;
+ int id;
+ int *nameid;
unsigned short qty;
};
struct item_chain_entry {
- unsigned short id;
+ int id;
unsigned short rate;
struct item_chain_entry *next;
};
@@ -428,7 +458,7 @@ struct item_chain {
};
struct item_package_rand_entry {
- unsigned short id;
+ int id;
unsigned short qty;
unsigned short rate;
unsigned short hours;
@@ -439,7 +469,7 @@ struct item_package_rand_entry {
};
struct item_package_must_entry {
- unsigned short id;
+ int id;
unsigned short qty;
unsigned short hours;
unsigned int announce : 1;
@@ -453,21 +483,34 @@ struct item_package_rand_group {
};
struct item_package {
- unsigned short id;
+ int id;
struct item_package_rand_group *random_groups;
struct item_package_must_entry *must_items;
unsigned short random_qty;
unsigned short must_qty;
};
+struct itemdb_option {
+ int16 index;
+ struct script_code *script;
+};
+
+struct item_lapineddukddak {
+ int16 NeedCount;
+ int8 NeedRefineMin;
+ int8 NeedRefineMax;
+ VECTOR_DECL(struct itemlist_entry) SourceItems;
+ struct script_code *script;
+};
+
struct item_data {
- uint16 nameid;
+ int nameid;
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
- //Do not add stuff between value_buy and view_id (see how getiteminfo works)
int value_buy;
int value_sell;
int type;
+ int subtype;
int maxchance; //For logs, for external game info, for scripts: Max drop chance of this item (e.g. 0.01% , etc.. if it = 0, then monsters don't drop it, -1 denotes items sold in shops only) [Lupus]
int sex;
int equip;
@@ -476,16 +519,15 @@ struct item_data {
int def;
int range;
int slot;
- int look;
+ int view_sprite;
int elv;
int wlv;
int view_id;
int matk;
int elvmax;/* maximum level for this item */
+ int dropeffectmode;
int delay;
-//Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command
-// some script commands should be revised as well...
uint64 class_base[3]; ///< Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2)
unsigned class_upper : 6; ///< Specifies if the upper-type can equip it (bitfield, 0x01: normal, 0x02: upper, 0x04: baby normal, 0x08: third normal, 0x10: third upper, 0x20: third baby)
struct {
@@ -495,16 +537,22 @@ struct item_data {
struct script_code *script; ///< Default script for everything.
struct script_code *equip_script; ///< Script executed once when equipping.
struct script_code *unequip_script; ///< Script executed once when unequipping.
+ struct script_code *rental_start_script; ///< Script executed once this item get rented
+ struct script_code *rental_end_script; ///< Script executed once this item rent ends
struct {
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 trade restrictions mask (@see enum ItemTradeRestrictions)
- unsigned autoequip: 1;
+ unsigned autoequip : 1;
+ unsigned auto_favorite : 1;
unsigned buyingstore : 1;
unsigned bindonequip : 1;
unsigned keepafteruse : 1;
unsigned force_serial : 1;
+ unsigned no_options: 1; // < disallows use of item options on the item. (non-equippable items are automatically flagged) [Smokexyz]
+ unsigned drop_announce : 1; // Official Drop Announce [Jedzkie]
+ unsigned showdropeffect: 1; // < Allow showing effect on item drop [Asheraf]
} flag;
struct {// item stacking limitation
unsigned short amount;
@@ -524,6 +572,7 @@ struct item_data {
/* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */
struct item_group *group;
struct item_package *package;
+ struct item_lapineddukddak *lapineddukddak;
struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
@@ -532,7 +581,8 @@ struct item_data {
#define itemdb_type(n) (itemdb->search(n)->type)
#define itemdb_atk(n) (itemdb->search(n)->atk)
#define itemdb_def(n) (itemdb->search(n)->def)
-#define itemdb_look(n) (itemdb->search(n)->look)
+#define itemdb_subtype(n) (itemdb->search(n)->subtype)
+#define itemdb_sprite(n) (itemdb->search(n)->view_sprite)
#define itemdb_weight(n) (itemdb->search(n)->weight)
#define itemdb_equip(n) (itemdb->search(n)->equip)
#define itemdb_usescript(n) (itemdb->search(n)->script)
@@ -546,13 +596,14 @@ struct item_data {
#define itemdb_value_buy(n) (itemdb->search(n)->value_buy)
#define itemdb_value_sell(n) (itemdb->search(n)->value_sell)
#define itemdb_canrefine(n) (!itemdb->search(n)->flag.no_refine)
+#define itemdb_allowoption(n) (!itemdb->search(n)->flag.no_options)
+#define itemdb_showdropeffect(n) (itemdb->search(n)->flag.showdropeffect)
+#define itemdb_dropeffectmode(n) (itemdb->search(n)->dropeffectmode)
-#define itemdb_is_rune(n) (((n) >= ITEMID_NAUTHIZ && (n) <= ITEMID_HAGALAZ) || (n) == ITEMID_LUX_ANIMA)
-#define itemdb_is_element(n) ((n) >= ITEMID_SCARLET_POINT && (n) <= ITEMID_LIME_GREEN_POINT)
+#define itemdb_is_element(n) ((n) >= ITEMID_SCARLET_PTS && (n) <= ITEMID_LIME_GREEN_PTS)
#define itemdb_is_spellbook(n) ((n) >= ITEMID_MAGIC_BOOK_FB && (n) <= ITEMID_MAGIC_BOOK_DL)
#define itemdb_is_poison(n) ((n) >= ITEMID_POISON_PARALYSIS && (n) <= ITEMID_POISON_FATIGUE)
#define itemid_isgemstone(n) ((n) >= ITEMID_YELLOW_GEMSTONE && (n) <= ITEMID_BLUE_GEMSTONE)
-#define itemdb_iscashfood(n) ((n) >= ITEMID_STR_DISH10_ && (n) <= ITEMID_VIT_DISH10_)
#define itemdb_is_GNbomb(n) ((n) >= ITEMID_APPLE_BOMB && (n) <= ITEMID_VERY_HARD_LUMP)
#define itemdb_is_GNthrowable(n) ((n) >= ITEMID_MYSTERIOUS_POWDER && (n) <= ITEMID_BLACK_THING_TO_THROW)
#define itemid_is_pilebunker(n) ((n) == ITEMID_PILEBUNCKER || (n) == ITEMID_PILEBUNCKER_P || (n) == ITEMID_PILEBUNCKER_S || (n) == ITEMID_PILEBUNCKER_T)
@@ -593,21 +644,24 @@ struct itemdb_interface {
/* */
struct item_data *array[MAX_ITEMDB];
struct DBMap *other;// int nameid -> struct item_data*
+ struct DBMap *options; // int opt_id -> struct itemdb_option*
struct item_data dummy; //This is the default dummy item used for non-existant items. [Skotlex]
/* */
void (*read_groups) (void);
void (*read_chains) (void);
void (*read_packages) (void);
+ void (*read_options) (void);
/* */
void (*write_cached_packages) (const char *config_filename);
bool (*read_cached_packages) (const char *config_filename);
/* */
struct item_data* (*name2id) (const char *str);
struct item_data* (*search_name) (const char *name);
- int (*search_name_array) (struct item_data** data, int size, const char *str, int flag);
+ int (*search_name_array) (struct item_data **data, const int size, const char *str, enum item_name_search_flag flag);
struct item_data* (*load)(int nameid);
struct item_data* (*search)(int nameid);
struct item_data* (*exists) (int nameid);
+ struct itemdb_option* (*option_exists) (int idx);
bool (*in_group) (struct item_group *group, int nameid);
int (*group_item) (struct item_group *group);
int (*chain_item) (unsigned short chain_id, int *rate);
@@ -617,7 +671,7 @@ struct itemdb_interface {
int (*searchrandomid) (struct item_group *group);
const char* (*typename) (int type);
void (*jobmask2mapid) (uint64 *bclass, uint64 jobmask);
- void (*jobid2mapid) (uint64 *bclass, int job_id, bool enable);
+ void (*jobid2mapid) (uint64 *bclass, int job_class, bool enable);
void (*create_dummy_data) (void);
struct item_data* (*create_item_data) (int nameid);
int (*isequip) (int nameid);
@@ -636,10 +690,11 @@ 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);
- int (*combo_split_atoi) (char *str, int *val);
- void (*read_combos) (void);
+ bool (*read_combodb_libconfig) (void);
+ bool (*read_combodb_libconfig_sub) (struct config_setting_t *it, int idx, const char *source);
int (*gendercheck) (struct item_data *id);
int (*validate_entry) (struct item_data *entry, int n, const char *source);
+ void (*readdb_options_additional_fields) (struct itemdb_option *ito, struct config_setting_t *t, const char *source);
void (*readdb_additional_fields) (int itemid, struct config_setting_t *it, int n, const char *source);
void (*readdb_job_sub) (struct item_data *id, struct config_setting_t *t);
int (*readdb_libconfig_sub) (struct config_setting_t *it, int n, const char *source);
@@ -648,10 +703,16 @@ struct itemdb_interface {
void (*read) (bool minimal);
void (*destroy_item_data) (struct item_data *self, int free_self);
int (*final_sub) (union DBKey key, struct DBData *data, va_list ap);
+ int (*options_final_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*clear) (bool total);
- struct item_combo * (*id2combo) (unsigned short id);
+ struct item_combo * (*id2combo) (int id);
bool (*is_item_usable) (struct item_data *item);
bool (*lookup_const) (const struct config_setting_t *it, const char *name, int *value);
+ bool (*lookup_const_mask) (const struct config_setting_t *it, const char *name, int *value);
+ int (*addname_sub) (union DBKey key, struct DBData *data, va_list ap);
+ bool (*read_libconfig_lapineddukddak) (void);
+ bool (*read_libconfig_lapineddukddak_sub) (struct config_setting_t *it, const char *source);
+ bool (*read_libconfig_lapineddukddak_sub_sources) (struct config_setting_t *sources, struct item_data *data);
};
#ifdef HERCULES_CORE
diff --git a/src/map/log.c b/src/map/log.c
index c19190d90..61679089b 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "map/mob.h"
#include "map/pc.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/sql.h" // SQL_INNODB
@@ -38,15 +39,16 @@
#include <stdlib.h>
#include <string.h>
-struct log_interface log_s;
+static struct log_interface log_s;
struct log_interface *logs;
/// obtain log type character for item/zeny logs
-char log_picktype2char(e_log_pick_type type) {
+static char log_picktype2char(e_log_pick_type type)
+{
switch( type ) {
case LOG_TYPE_TRADE: return 'T'; // (T)rade
case LOG_TYPE_VENDING: return 'V'; // (V)ending
- case LOG_TYPE_PICKDROP_PLAYER: return 'P'; // (P)player
+ case LOG_TYPE_PICKDROP_PLAYER: return 'P'; // (P)layer
case LOG_TYPE_PICKDROP_MONSTER: return 'M'; // (M)onster
case LOG_TYPE_NPC: return 'S'; // NPC (S)hop
case LOG_TYPE_SCRIPT: return 'N'; // (N)PC Script
@@ -73,6 +75,7 @@ char log_picktype2char(e_log_pick_type type) {
case LOG_TYPE_SKILL: return '1'; // Skill
case LOG_TYPE_REFINE: return '2'; // Refine
case LOG_TYPE_OTHER: return 'X'; // Other
+ case LOG_TYPE_ACHIEVEMENT: return '3'; // Achievement
}
// should not get here, fallback
@@ -81,13 +84,21 @@ char log_picktype2char(e_log_pick_type type) {
}
/// obtain log type character for chat logs
-char log_chattype2char(e_log_chat_type type) {
- switch( type ) {
- case LOG_CHAT_GLOBAL: return 'O'; // Gl(O)bal
- case LOG_CHAT_WHISPER: return 'W'; // (W)hisper
- case LOG_CHAT_PARTY: return 'P'; // (P)arty
- case LOG_CHAT_GUILD: return 'G'; // (G)uild
- case LOG_CHAT_MAINCHAT: return 'M'; // (M)ain chat
+static char log_chattype2char(e_log_chat_type type)
+{
+ switch (type) {
+ case LOG_CHAT_GLOBAL:
+ return 'O'; // Gl(O)bal
+ case LOG_CHAT_WHISPER:
+ return 'W'; // (W)hisper
+ case LOG_CHAT_PARTY:
+ return 'P'; // (P)arty
+ case LOG_CHAT_GUILD:
+ return 'G'; // (G)uild
+ case LOG_CHAT_MAINCHAT:
+ return 'M'; // (M)ain chat
+ case LOG_CHAT_CLAN:
+ return 'C'; // (C)lan
}
// should not get here, fallback
@@ -96,7 +107,8 @@ char log_chattype2char(e_log_chat_type type) {
}
/// check if this item should be logged according the settings
-bool should_log_item(int nameid, int amount, int refine, struct item_data *id) {
+static bool should_log_item(int nameid, int amount, int refine_level, struct item_data *id)
+{
int filter = logs->config.filter;
if( id == NULL )
@@ -112,14 +124,14 @@ bool should_log_item(int nameid, int amount, int refine, struct item_data *id) {
( filter&LOG_FILTER_PETITEM && ( id->type == IT_PETEGG || id->type == IT_PETARMOR ) ) ||
( filter&LOG_FILTER_PRICE && id->value_buy >= logs->config.price_items_log ) ||
( filter&LOG_FILTER_AMOUNT && abs(amount) >= logs->config.amount_items_log ) ||
- ( filter&LOG_FILTER_REFINE && refine >= logs->config.refine_items_log ) ||
+ ( filter&LOG_FILTER_REFINE && refine_level >= logs->config.refine_items_log ) ||
( filter&LOG_FILTER_CHANCE && ( ( id->maxchance != -1 && id->maxchance <= logs->config.rare_items_log ) || id->nameid == ITEMID_EMPERIUM ) )
)
return true;
return false;
}
-void log_branch_sub_sql(struct map_session_data* sd)
+static void log_branch_sub_sql(struct map_session_data *sd)
{
struct SqlStmt *stmt;
@@ -135,7 +147,8 @@ void log_branch_sub_sql(struct map_session_data* sd)
}
SQL->StmtFree(stmt);
}
-void log_branch_sub_txt(struct map_session_data* sd) {
+static void log_branch_sub_txt(struct map_session_data *sd)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -150,7 +163,8 @@ void log_branch_sub_txt(struct map_session_data* sd) {
}
/// logs items, that summon monsters
-void log_branch(struct map_session_data* sd) {
+static void log_branch(struct map_session_data *sd)
+{
nullpo_retv(sd);
if( !logs->config.branch )
@@ -158,19 +172,24 @@ void log_branch(struct map_session_data* sd) {
logs->branch_sub(sd);
}
-void log_pick_sub_sql(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
+static void log_pick_sub_sql(int id, int16 m, e_log_pick_type type, int amount, struct item *itm, struct item_data *data)
+{
nullpo_retv(itm);
- if( SQL_ERROR == SQL->Query(logs->mysql_handle,
- LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) "
- "VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')",
+ if (SQL_ERROR == SQL->Query(logs->mysql_handle,
+ LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, "
+ "`opt_idx0`, `opt_val0`, `opt_idx1`, `opt_val1`, `opt_idx2`, `opt_val2`, `opt_idx3`, `opt_val3`, `opt_idx4`, `opt_val4`, `map`, `unique_id`) "
+ "VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')",
logs->config.log_pick, id, logs->picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3],
- map->list[m].name, itm->unique_id)
- ) {
+ itm->option[0].index, itm->option[0].value, itm->option[1].index, itm->option[1].value, itm->option[2].index, itm->option[2].value,
+ itm->option[3].index, itm->option[3].value, itm->option[4].index, itm->option[4].value,
+ map->list[m].name, itm->unique_id))
+ {
Sql_ShowDebug(logs->mysql_handle);
return;
}
}
-void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
+static void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct item *itm, struct item_data *data)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -186,7 +205,8 @@ void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct
fclose(logfp);
}
/// logs item transactions (generic)
-void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
+static void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item *itm, struct item_data *data)
+{
nullpo_retv(itm);
if( ( logs->config.enable_logs&type ) == 0 ) {// disabled
return;
@@ -199,19 +219,22 @@ void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* it
}
/// logs item transactions (players)
-void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
+static void log_pick_pc(struct map_session_data *sd, e_log_pick_type type, int amount, struct item *itm, struct item_data *data)
+{
nullpo_retv(sd);
nullpo_retv(itm);
log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
/// logs item transactions (monsters)
-void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
+static void log_pick_mob(struct mob_data *md, e_log_pick_type type, int amount, struct item *itm, struct item_data *data)
+{
nullpo_retv(md);
nullpo_retv(itm);
log_pick(md->class_, md->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
-void log_zeny_sub_sql(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) {
+static void log_zeny_sub_sql(struct map_session_data *sd, e_log_pick_type type, struct map_session_data *src_sd, int amount)
+{
nullpo_retv(sd);
nullpo_retv(src_sd);
if( SQL_ERROR == SQL->Query(logs->mysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')",
@@ -221,7 +244,8 @@ void log_zeny_sub_sql(struct map_session_data* sd, e_log_pick_type type, struct
return;
}
}
-void log_zeny_sub_txt(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) {
+static void log_zeny_sub_txt(struct map_session_data *sd, e_log_pick_type type, struct map_session_data *src_sd, int amount)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -236,7 +260,7 @@ void log_zeny_sub_txt(struct map_session_data* sd, e_log_pick_type type, struct
fclose(logfp);
}
/// logs zeny transactions
-void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount)
+static void log_zeny(struct map_session_data *sd, e_log_pick_type type, struct map_session_data *src_sd, int amount)
{
nullpo_retv(sd);
@@ -245,7 +269,8 @@ void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_sess
logs->zeny_sub(sd,type,src_sd,amount);
}
-void log_mvpdrop_sub_sql(struct map_session_data* sd, int monster_id, int* log_mvp) {
+static void log_mvpdrop_sub_sql(struct map_session_data *sd, int monster_id, int *log_mvp)
+{
nullpo_retv(sd);
nullpo_retv(log_mvp);
if( SQL_ERROR == SQL->Query(logs->mysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ",
@@ -255,7 +280,8 @@ void log_mvpdrop_sub_sql(struct map_session_data* sd, int monster_id, int* log_m
return;
}
}
-void log_mvpdrop_sub_txt(struct map_session_data* sd, int monster_id, int* log_mvp) {
+static void log_mvpdrop_sub_txt(struct map_session_data *sd, int monster_id, int *log_mvp)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -270,7 +296,7 @@ void log_mvpdrop_sub_txt(struct map_session_data* sd, int monster_id, int* log_m
fclose(logfp);
}
/// logs MVP monster rewards
-void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp)
+static void log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp)
{
nullpo_retv(sd);
@@ -280,7 +306,7 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp)
logs->mvpdrop_sub(sd,monster_id,log_mvp);
}
-void log_atcommand_sub_sql(struct map_session_data* sd, const char* message)
+static void log_atcommand_sub_sql(struct map_session_data *sd, const char *message)
{
struct SqlStmt *stmt;
@@ -298,7 +324,8 @@ void log_atcommand_sub_sql(struct map_session_data* sd, const char* message)
}
SQL->StmtFree(stmt);
}
-void log_atcommand_sub_txt(struct map_session_data* sd, const char* message) {
+static void log_atcommand_sub_txt(struct map_session_data *sd, const char *message)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -313,7 +340,7 @@ void log_atcommand_sub_txt(struct map_session_data* sd, const char* message) {
fclose(logfp);
}
/// logs used atcommands
-void log_atcommand(struct map_session_data* sd, const char* message)
+static void log_atcommand(struct map_session_data *sd, const char *message)
{
nullpo_retv(sd);
@@ -324,7 +351,7 @@ void log_atcommand(struct map_session_data* sd, const char* message)
logs->atcommand_sub(sd,message);
}
-void log_npc_sub_sql(struct map_session_data *sd, const char *message)
+static void log_npc_sub_sql(struct map_session_data *sd, const char *message)
{
struct SqlStmt *stmt;
@@ -342,7 +369,8 @@ void log_npc_sub_sql(struct map_session_data *sd, const char *message)
}
SQL->StmtFree(stmt);
}
-void log_npc_sub_txt(struct map_session_data *sd, const char *message) {
+static void log_npc_sub_txt(struct map_session_data *sd, const char *message)
+{
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -357,7 +385,7 @@ void log_npc_sub_txt(struct map_session_data *sd, const char *message) {
fclose(logfp);
}
/// logs messages passed to script command 'logmes'
-void log_npc(struct map_session_data* sd, const char* message)
+static void log_npc(struct map_session_data *sd, const char *message)
{
nullpo_retv(sd);
@@ -380,7 +408,7 @@ void log_npc(struct map_session_data* sd, const char* message)
* @param dst_charname Destination character name. Must not be NULL.
* @param message Message to log.
*/
-void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
+static void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
{
struct SqlStmt* stmt;
@@ -412,7 +440,7 @@ void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src
* @param dst_charname Destination character name. Must not be NULL.
* @param message Message to log.
*/
-void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
+static void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
{
char timestring[255];
time_t curtime;
@@ -442,7 +470,7 @@ void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src
* @param dst_charname Destination character name. May be NULL when unused.
* @param message Message to log.
*/
-void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
+static void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
{
if ((logs->config.chat&type) == 0) {
// disabled
@@ -460,7 +488,8 @@ void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid,
logs->chat_sub(type,type_id,src_charid,src_accid,mapname,x,y,dst_charname,message);
}
-void log_sql_init(void) {
+static void log_sql_init(void)
+{
// log db connection
logs->mysql_handle = SQL->Malloc();
@@ -473,128 +502,262 @@ void log_sql_init(void) {
if ( SQL_ERROR == SQL->SetEncoding(logs->mysql_handle, map->default_codepage) )
Sql_ShowDebug(logs->mysql_handle);
}
-void log_sql_final(void) {
+static void log_sql_final(void)
+{
ShowStatus("Close Log DB Connection....\n");
SQL->Free(logs->mysql_handle);
logs->mysql_handle = NULL;
}
-void log_set_defaults(void) {
+/**
+ * Initializes logs->config variables
+ */
+static void log_set_defaults(void)
+{
memset(&logs->config, 0, sizeof(logs->config));
- //LOG FILTER Default values
+ //map_log default values
+ logs->config.enable_logs = 0xFFFFF;
+ logs->config.commands = true;
+
+ //map_log/database default values
+ logs->config.sql_logs = true;
+ // file/table names defaults are defined inside log_config_read_database
+
+ //map_log/filter/item default values
+ logs->config.filter = 1; // logs any item
logs->config.refine_items_log = 5; // log refined items, with refine >= +5
logs->config.rare_items_log = 100; // log rare items. drop chance <= 1%
logs->config.price_items_log = 1000; // 1000z
logs->config.amount_items_log = 100;
}
-int log_config_read(const char* cfgName) {
- static int count = 0;
- char line[1024], w1[1024], w2[1024];
- FILE *fp;
+/**
+ * Reads 'map_log/database' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool log_config_read_database(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "map_log/database")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("log_config_read: map_log/database was not found in %s!\n", filename);
+ return false;
+ }
+ libconfig->setting_lookup_bool_real(setting, "use_sql", &logs->config.sql_logs);
+
+ // map_log.database defaults are defined in order to not make unecessary calls to safestrncpy [Panikon]
+ if (libconfig->setting_lookup_mutable_string(setting, "log_branch_db",
+ logs->config.log_branch, sizeof(logs->config.log_branch)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_branch, "branchlog", sizeof(logs->config.log_branch));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_pick_db",
+ logs->config.log_pick, sizeof(logs->config.log_pick)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_pick, "picklog", sizeof(logs->config.log_pick));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_zeny_db",
+ logs->config.log_zeny, sizeof(logs->config.log_zeny)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_zeny, "zenylog", sizeof(logs->config.log_zeny));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_mvpdrop_db",
+ logs->config.log_mvpdrop, sizeof(logs->config.log_mvpdrop)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_mvpdrop, "mvplog", sizeof(logs->config.log_mvpdrop));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_gm_db",
+ logs->config.log_gm, sizeof(logs->config.log_gm)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_gm, "atcommandlog", sizeof(logs->config.log_gm));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_npc_db",
+ logs->config.log_npc, sizeof(logs->config.log_npc)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_npc, "npclog", sizeof(logs->config.log_npc));
+
+ if (libconfig->setting_lookup_mutable_string(setting, "log_chat_db",
+ logs->config.log_chat, sizeof(logs->config.log_chat)) == CONFIG_FALSE)
+ safestrncpy(logs->config.log_chat, "chatlog", sizeof(logs->config.log_chat));
+
+ return true;
+}
+
+/**
+ * Reads 'map_log/filter/item' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool log_config_read_filter_item(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "map_log/filter/item")) == NULL) {
+ if (!imported)
+ ShowError("log_config_read: map_log/filter/item was not found in %s!\n", filename);
+ return false;
+ }
+ libconfig->setting_lookup_int(setting, "log_filter", &logs->config.filter);
+ libconfig->setting_lookup_int(setting, "refine_items_log", &logs->config.refine_items_log);
+ libconfig->setting_lookup_int(setting, "rare_items_log", &logs->config.rare_items_log);
+ libconfig->setting_lookup_int(setting, "price_items_log", &logs->config.price_items_log);
+ libconfig->setting_lookup_int(setting, "amount_items_log", &logs->config.amount_items_log);
+ return true;
+}
+
+/**
+ * Reads 'map_log.filter.chat' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool log_config_read_filter_chat(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
- nullpo_retr(1, cfgName);
- if( count++ == 0 )
+ if ((setting = libconfig->lookup(config, "map_log/filter/chat")) == NULL) {
+ if (!imported)
+ ShowError("log_config_read: map_log/filter/chat was not found in %s!\n", filename);
+ return false;
+ }
+ libconfig->setting_lookup_int(setting, "log_chat", &logs->config.chat);
+ libconfig->setting_lookup_bool_real(setting, "log_chat_woe_disable", &logs->config.log_chat_woe_disable);
+ return true;
+}
+
+/**
+ * Reads 'map_log.filter' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool log_config_read_filter(const char *filename, struct config_t *config, bool imported)
+{
+ bool retval = true;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if (!log_config_read_filter_item(filename, config, imported))
+ retval = false;
+ if (!log_config_read_filter_chat(filename, config, imported))
+ retval = false;
+
+ return retval;
+}
+
+/**
+ * Reads 'map_log' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool log_config_read(const char *filename, bool imported)
+{
+ struct config_t config;
+ struct config_setting_t *setting = NULL;
+ const char *import;
+ const char *target; // Type of storage 'file'/'table'
+ int temp;
+ bool retval = true;
+
+ nullpo_retr(false, filename);
+
+ if (!imported)
log_set_defaults();
- if( ( fp = fopen(cfgName, "r") ) == NULL ) {
- ShowError("Log configuration file not found at: %s\n", cfgName);
- return 1;
+ if (!libconfig->load_file(&config, filename))
+ return false;
+
+ if ((setting = libconfig->lookup(&config, "map_log")) == NULL) {
+ libconfig->destroy(&config);
+ if (imported)
+ return true;
+ ShowError("log_config_read: map_log was not found in %s!\n", filename);
+ return false;
}
- while (fgets(line, sizeof(line), fp)) {
- if (line[0] == '/' && line[1] == '/')
- continue;
-
- if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) == 2) {
- if( strcmpi(w1, "enable_logs") == 0 )
- logs->config.enable_logs = (e_log_pick_type)config_switch(w2);
- else if( strcmpi(w1, "sql_logs") == 0 )
- logs->config.sql_logs = (bool)config_switch(w2);
-//start of common filter settings
- else if( strcmpi(w1, "rare_items_log") == 0 )
- logs->config.rare_items_log = atoi(w2);
- else if( strcmpi(w1, "refine_items_log") == 0 )
- logs->config.refine_items_log = atoi(w2);
- else if( strcmpi(w1, "price_items_log") == 0 )
- logs->config.price_items_log = atoi(w2);
- else if( strcmpi(w1, "amount_items_log") == 0 )
- logs->config.amount_items_log = atoi(w2);
-//end of common filter settings
- else if( strcmpi(w1, "log_branch") == 0 )
- logs->config.branch = config_switch(w2);
- else if( strcmpi(w1, "log_filter") == 0 )
- logs->config.filter = config_switch(w2);
- else if( strcmpi(w1, "log_zeny") == 0 )
- logs->config.zeny = config_switch(w2);
- else if( strcmpi(w1, "log_commands") == 0 )
- logs->config.commands = config_switch(w2);
- else if( strcmpi(w1, "log_npc") == 0 )
- logs->config.npc = config_switch(w2);
- else if( strcmpi(w1, "log_chat") == 0 )
- logs->config.chat = config_switch(w2);
- else if( strcmpi(w1, "log_mvpdrop") == 0 )
- logs->config.mvpdrop = config_switch(w2);
- else if( strcmpi(w1, "log_chat_woe_disable") == 0 )
- logs->config.log_chat_woe_disable = (bool)config_switch(w2);
- else if( strcmpi(w1, "log_branch_db") == 0 )
- safestrncpy(logs->config.log_branch, w2, sizeof(logs->config.log_branch));
- else if( strcmpi(w1, "log_pick_db") == 0 )
- safestrncpy(logs->config.log_pick, w2, sizeof(logs->config.log_pick));
- else if( strcmpi(w1, "log_zeny_db") == 0 )
- safestrncpy(logs->config.log_zeny, w2, sizeof(logs->config.log_zeny));
- else if( strcmpi(w1, "log_mvpdrop_db") == 0 )
- safestrncpy(logs->config.log_mvpdrop, w2, sizeof(logs->config.log_mvpdrop));
- else if( strcmpi(w1, "log_gm_db") == 0 )
- safestrncpy(logs->config.log_gm, w2, sizeof(logs->config.log_gm));
- else if( strcmpi(w1, "log_npc_db") == 0 )
- safestrncpy(logs->config.log_npc, w2, sizeof(logs->config.log_npc));
- else if( strcmpi(w1, "log_chat_db") == 0 )
- safestrncpy(logs->config.log_chat, w2, sizeof(logs->config.log_chat));
- //support the import command, just like any other config
- else if( strcmpi(w1,"import") == 0 )
- logs->config_read(w2);
- else if (HPM->parseConf(w1, w2, HPCT_LOG))
- ; // handled by plugins
- else
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
- }
+ if (libconfig->setting_lookup_int(setting, "enable", &temp) == CONFIG_TRUE) {
+ logs->config.enable_logs = temp&LOG_TYPE_ALL; // e_log_pick_type
}
+ libconfig->setting_lookup_int(setting, "log_zeny", &logs->config.zeny);
+ libconfig->setting_lookup_bool_real(setting, "log_branch", &logs->config.branch);
+ libconfig->setting_lookup_bool_real(setting, "log_mvpdrop", &logs->config.mvpdrop);
+ libconfig->setting_lookup_bool_real(setting, "log_commands", &logs->config.commands);
+ libconfig->setting_lookup_bool_real(setting, "log_npc", &logs->config.npc);
- fclose(fp);
+ if (!log_config_read_database(filename, &config, imported))
+ retval = false;
+ if (!log_config_read_filter(filename, &config, imported))
+ retval = false;
- if( --count == 0 ) {// report final logging state
- const char* target = logs->config.sql_logs ? "table" : "file";
+ if (!HPM->parse_conf(&config, filename, HPCT_LOG, imported))
+ retval = false;
- if( logs->config.enable_logs && logs->config.filter ) {
- ShowInfo("Logging item transactions to %s '%s'.\n", target, logs->config.log_pick);
- }
- if( logs->config.branch ) {
- ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, logs->config.log_pick);
- }
- if( logs->config.chat ) {
- ShowInfo("Logging chat to %s '%s'.\n", target, logs->config.log_chat);
- }
- if( logs->config.commands ) {
- ShowInfo("Logging commands to %s '%s'.\n", target, logs->config.log_gm);
- }
- if( logs->config.mvpdrop ) {
- ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, logs->config.log_mvpdrop);
- }
- if( logs->config.npc ) {
- ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, logs->config.log_npc);
- }
- if( logs->config.zeny ) {
- ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, logs->config.log_zeny);
+ target = logs->config.sql_logs ? "table" : "file";
+
+ if (logs->config.enable_logs && logs->config.filter)
+ ShowInfo("Logging item transactions to %s '%s'.\n", target, logs->config.log_pick);
+
+ if (logs->config.branch)
+ ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, logs->config.log_branch);
+
+ if (logs->config.chat)
+ ShowInfo("Logging chat to %s '%s'.\n", target, logs->config.log_chat);
+
+ if (logs->config.commands)
+ ShowInfo("Logging commands to %s '%s'.\n", target, logs->config.log_gm);
+
+ if (logs->config.mvpdrop)
+ ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, logs->config.log_mvpdrop);
+
+ if (logs->config.npc)
+ ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, logs->config.log_npc);
+
+ if (logs->config.zeny)
+ ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, logs->config.log_zeny);
+
+ logs->config_done();
+
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ if (strcmp(import, filename) == 0 || strcmp(import, map->LOG_CONF_NAME) == 0) {
+ ShowWarning("log_config_read: Loop detected! Skipping 'import'...\n");
+ } else {
+ if (!logs->config_read(import, true))
+ retval = false;
}
- logs->config_done();
}
- return 0;
+ libconfig->destroy(&config);
+ return retval;
}
-void log_config_complete(void) {
+static void log_config_complete(void)
+{
if( logs->config.sql_logs ) {
logs->pick_sub = log_pick_sub_sql;
logs->zeny_sub = log_zeny_sub_sql;
@@ -606,7 +769,11 @@ void log_config_complete(void) {
}
}
-void log_defaults(void) {
+/**
+ * Initializes the log interface to the default values.
+ */
+void log_defaults(void)
+{
logs = &log_s;
sprintf(logs->db_ip,"127.0.0.1");
diff --git a/src/map/log.h b/src/map/log.h
index 0a5e13208..3f9a80e36 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -52,6 +52,7 @@ typedef enum e_log_chat_type {
LOG_CHAT_PARTY = 0x04,
LOG_CHAT_GUILD = 0x08,
LOG_CHAT_MAINCHAT = 0x10,
+ LOG_CHAT_CLAN = 0x20,
// all
LOG_CHAT_ALL = 0xFF,
} e_log_chat_type;
@@ -86,9 +87,9 @@ typedef enum e_log_pick_type {
LOG_TYPE_QUEST = 0x02000000,
LOG_TYPE_SKILL = 0x04000000,
LOG_TYPE_REFINE = 0x08000000,
+ LOG_TYPE_LOOT = 0x10000000,
+ LOG_TYPE_ACHIEVEMENT = 0x20000000,
- // combinations
- LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME,
// all
LOG_TYPE_ALL = 0xFFFFFFFF,
} e_log_pick_type;
@@ -118,7 +119,8 @@ struct log_interface {
bool sql_logs;
bool log_chat_woe_disable;
int rare_items_log,refine_items_log,price_items_log,amount_items_log;
- int branch, mvpdrop, zeny, commands, npc, chat;
+ int zeny, chat;
+ bool branch, mvpdrop, commands, npc;
char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64];
} config;
/* */
@@ -146,14 +148,14 @@ struct log_interface {
void (*branch_sub) (struct map_session_data* sd);
void (*mvpdrop_sub) (struct map_session_data* sd, int monster_id, int* log_mvp);
- int (*config_read) (const char* cfgName);
+ bool (*config_read) (const char *filename, bool imported);
void (*config_done) (void);
void (*sql_init) (void);
void (*sql_final) (void);
char (*picktype2char) (e_log_pick_type type);
char (*chattype2char) (e_log_chat_type type);
- bool (*should_log_item) (int nameid, int amount, int refine, struct item_data *id);
+ bool (*should_log_item) (int nameid, int amount, int refine_level, struct item_data *id);
};
#ifdef HERCULES_CORE
diff --git a/src/map/mail.c b/src/map/mail.c
index e446a10d2..a1176e8fc 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,10 +34,10 @@
#include <time.h>
#include <string.h>
-struct mail_interface mail_s;
+static struct mail_interface mail_s;
struct mail_interface *mail;
-void mail_clear(struct map_session_data *sd)
+static void mail_clear(struct map_session_data *sd)
{
nullpo_retv(sd);
sd->mail.nameid = 0;
@@ -48,7 +48,7 @@ void mail_clear(struct map_session_data *sd)
return;
}
-int mail_removeitem(struct map_session_data *sd, short flag)
+static int mail_removeitem(struct map_session_data *sd, short flag)
{
nullpo_ret(sd);
@@ -66,7 +66,7 @@ int mail_removeitem(struct map_session_data *sd, short flag)
return 1;
}
-int mail_removezeny(struct map_session_data *sd, short flag)
+static int mail_removezeny(struct map_session_data *sd, short flag)
{
nullpo_ret(sd);
@@ -79,7 +79,8 @@ int mail_removezeny(struct map_session_data *sd, short flag)
return 1;
}
-unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
+static unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount)
+{
nullpo_retr(1, sd);
if( pc_istrading(sd) )
@@ -99,7 +100,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
idx -= 2;
mail->removeitem(sd, 0);
- if( idx < 0 || idx >= MAX_INVENTORY )
+ if (idx < 0 || idx >= sd->status.inventorySize)
return 1;
if( amount <= 0 || amount > sd->status.inventory[idx].amount )
return 1;
@@ -116,7 +117,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
}
}
-bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
+static bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
{
int n;
@@ -127,7 +128,7 @@ bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
return false;
n = sd->mail.index;
- Assert_retr(false, n >= 0 && n < MAX_INVENTORY);
+ Assert_retr(false, n >= 0 && n < sd->status.inventorySize);
if( sd->mail.amount )
{
if( sd->status.inventory[n].nameid != sd->mail.nameid )
@@ -156,7 +157,7 @@ bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
return true;
}
-void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item)
+static void mail_getattachment(struct map_session_data *sd, int zeny, struct item *item)
{
nullpo_retv(sd);
nullpo_retv(item);
@@ -172,11 +173,11 @@ void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item
}
}
-int mail_openmail(struct map_session_data *sd)
+static int mail_openmail(struct map_session_data *sd)
{
nullpo_ret(sd);
- if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading)
+ if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.trading)
return 0;
clif->mail_window(sd->fd, 0);
@@ -184,7 +185,7 @@ int mail_openmail(struct map_session_data *sd)
return 1;
}
-void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
+static void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
{
nullpo_retv(sd);
nullpo_retv(msg);
@@ -204,7 +205,8 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
}
// This function only check if the mail operations are valid
-bool mail_invalid_operation(struct map_session_data *sd) {
+static bool mail_invalid_operation(struct map_session_data *sd)
+{
nullpo_retr(false, sd);
if( !map->list[sd->bl.m].flag.town && !pc->can_use_command(sd, "@mail") ) {
ShowWarning("clif->parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name);
diff --git a/src/map/mail.h b/src/map/mail.h
index 94100e608..6281890c0 100644
--- a/src/map/mail.h
+++ b/src/map/mail.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/map.c b/src/map/map.c
index 3a7d752c3..40e66e4df 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/duel.h"
#include "map/elemental.h"
@@ -44,7 +45,6 @@
#include "map/mapreg.h"
#include "map/mercenary.h"
#include "map/mob.h"
-#include "map/npc.h"
#include "map/npc.h" // npc_setcells(), npc_unsetcells()
#include "map/party.h"
#include "map/path.h"
@@ -55,8 +55,12 @@
#include "map/skill.h"
#include "map/status.h"
#include "map/storage.h"
+#include "map/stylist.h"
+#include "map/rodex.h"
+#include "map/refine.h"
#include "map/trade.h"
#include "map/unit.h"
+#include "map/achievement.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
@@ -64,6 +68,7 @@
#include "common/core.h"
#include "common/ers.h"
#include "common/grfio.h"
+#include "common/md5calc.h"
#include "common/memmgr.h"
#include "common/nullpo.h"
#include "common/random.h"
@@ -79,12 +84,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#ifndef _WIN32
#include <unistd.h>
#endif
-struct map_interface map_s;
-struct mapit_interface mapit_s;
+static struct map_interface map_s;
+static struct mapit_interface mapit_s;
struct map_interface *map;
struct mapit_interface *mapit;
@@ -92,18 +98,21 @@ struct mapit_interface *mapit;
/*==========================================
* server player count (of all mapservers)
*------------------------------------------*/
-void map_setusers(int users) {
+static void map_setusers(int users)
+{
map->users = users;
}
-int map_getusers(void) {
+static int map_getusers(void)
+{
return map->users;
}
/**
* Expands map->bl_list on demand
**/
-static inline void map_bl_list_expand(void) {
+static inline void map_bl_list_expand(void)
+{
map->bl_list_size += 250;
RECREATE(map->bl_list, struct block_list *, map->bl_list_size);
}
@@ -111,7 +120,8 @@ static inline void map_bl_list_expand(void) {
/**
* Expands map->block_free on demand
**/
-static inline void map_block_free_expand(void) {
+static inline void map_block_free_expand(void)
+{
map->block_free_list_size += 100;
RECREATE(map->block_free, struct block_list *, map->block_free_list_size);
}
@@ -119,14 +129,16 @@ static inline void map_block_free_expand(void) {
/*==========================================
* server player count (this mapserver only)
*------------------------------------------*/
-int map_usercount(void) {
+static int map_usercount(void)
+{
return db_size(map->pc_db);
}
/*==========================================
* Attempt to free a map blocklist
*------------------------------------------*/
-int map_freeblock (struct block_list *bl) {
+static int map_freeblock(struct block_list *bl)
+{
nullpo_retr(map->block_free_lock, bl);
if (map->block_free_lock == 0) {
@@ -147,14 +159,16 @@ int map_freeblock (struct block_list *bl) {
/*==========================================
* Lock blocklist, (prevent map->freeblock usage)
*------------------------------------------*/
-int map_freeblock_lock (void) {
+static int map_freeblock_lock(void)
+{
return ++map->block_free_lock;
}
/*==========================================
* Remove the lock on map_bl
*------------------------------------------*/
-int map_freeblock_unlock (void) {
+static int map_freeblock_unlock(void)
+{
if ((--map->block_free_lock) == 0) {
int i;
for (i = 0; i < map->block_free_count; i++) {
@@ -175,7 +189,8 @@ int map_freeblock_unlock (void) {
// Timer function to check if there some remaining lock and remove them if so.
// Called each 1s
-int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data) {
+static int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data)
+{
if (map->block_free_lock > 0) {
ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", map->block_free_lock);
map->block_free_lock = 1;
@@ -189,7 +204,8 @@ int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data) {
* 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 ) {
+static void map_update_cell_bl(struct block_list *bl, bool increase)
+{
#ifdef CELL_NOSTACK
int pos;
@@ -218,7 +234,7 @@ void map_update_cell_bl( struct block_list *bl, bool increase ) {
* Adds a block to the map.
* Returns 0 on success, 1 on failure (illegal coordinates).
*------------------------------------------*/
-int map_addblock(struct block_list* bl)
+static int map_addblock(struct block_list *bl)
{
int16 m, x, y;
int pos;
@@ -266,7 +282,7 @@ int map_addblock(struct block_list* bl)
/*==========================================
* Removes a block from the map.
*------------------------------------------*/
-int map_delblock(struct block_list* bl)
+static int map_delblock(struct block_list *bl)
{
int pos;
nullpo_ret(bl);
@@ -309,7 +325,8 @@ int map_delblock(struct block_list* bl)
* Pass flag as 1 to prevent doing skill->unit_move checks
* (which are executed by default on BL_CHAR types)
*------------------------------------------*/
-int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
+static int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick)
+{
struct status_change *sc = NULL;
int x0, y0;
int moveblock;
@@ -336,6 +353,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
//status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
status_change_end(bl, SC_NJ_TATAMIGAESHI, INVALID_TIMER);
status_change_end(bl, SC_MAGICROD, INVALID_TIMER);
+ status_change_end(bl, SC_SU_STOOP, INVALID_TIMER);
if (sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 >= skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) )
status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER);
@@ -426,7 +444,8 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
* 0x2 - don't count invinsible units
* TODO: merge with bl_getall_area
*------------------------------------------*/
-int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
+static int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag)
+{
int bx,by;
struct block_list *bl;
int count = 0;
@@ -444,6 +463,11 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
struct status_change *sc = status->get_sc(bl);
if (sc && (sc->option&OPTION_INVISIBLE))
continue;
+ if (bl->type == BL_NPC) {
+ const struct npc_data *nd = BL_UCCAST(BL_NPC, bl);
+ if (nd->class_ == FAKE_NPC || nd->class_ == HIDDEN_WARP_CLASS)
+ continue;
+ }
}
if (flag&0x1) {
struct unit_data *ud = unit->bl2ud(bl);
@@ -479,7 +503,8 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
* Looks for a skill unit on a given cell
* flag&1: runs battle_check_target check based on unit->group->target_flag
*/
-struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag) {
+static struct skill_unit *map_find_skill_unit_oncell(struct block_list *target, int16 x, int16 y, uint16 skill_id, struct skill_unit *out_unit, int flag)
+{
int16 m,bx,by;
struct block_list *bl;
struct skill_unit *su;
@@ -506,10 +531,12 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,
return NULL;
}
-/** @name Functions for block_list search and manipulation
+/**
+ * @name Functions for block_list search and manipulation
+ *
+ * @{
*/
-/* @{ */
/**
* Applies func to every block_list in bl_list starting with bl_list[blockcount].
* Sets bl_list_count back to blockcount.
@@ -520,7 +547,8 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,
* @param args Extra arguments for func
* @return Sum of the values returned by func
*/
-static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount, int max, va_list args) {
+static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount, int max, va_list args)
+{
int i;
int returnCount = 0;
@@ -549,7 +577,8 @@ static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount,
* @param args Extra arguments for func
* @return Sum of the values returned by func
*/
-static int map_vforeachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, va_list args) {
+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;
@@ -597,7 +626,8 @@ static int map_vforeachinmap(int (*func)(struct block_list*, va_list), int16 m,
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, ...) {
+static int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, ...)
+{
int returnCount;
va_list ap;
@@ -608,6 +638,21 @@ int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, int type
return returnCount;
}
+static int map_forcountinmap(int (*func)(struct block_list*, va_list), int16 m, int count, int type, ...)
+{
+ int returnCount = 0;
+ va_list ap;
+
+ if (m < 0)
+ return returnCount;
+
+ va_start(ap, type);
+ returnCount = map->vforcountinarea(func, m, 0, 0, map->list[m].xs, map->list[m].ys, count, type, ap);
+ va_end(ap);
+
+ return returnCount;
+}
+
/**
* Applies func to every block_list object of bl_type type on all maps
* of instance instance_id.
@@ -619,7 +664,8 @@ int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, int type
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, va_list ap) {
+static int map_vforeachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, va_list ap)
+{
int i;
int returnCount = 0;
@@ -645,7 +691,8 @@ int map_vforeachininstance(int (*func)(struct block_list*, va_list), int16 insta
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, ...) {
+static int map_foreachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, ...)
+{
int returnCount;
va_list ap;
@@ -665,7 +712,8 @@ int map_foreachininstance(int (*func)(struct block_list*, va_list), int16 instan
* @param ... Extra arguments for func
* @return Number of found objects
*/
-static int bl_getall_area(int type, int m, int x0, int y0, int x1, int y1, int (*func)(struct block_list*, va_list), ...) {
+static int bl_getall_area(int type, int m, int x0, int y0, int x1, int y1, int (*func)(struct block_list*, va_list), ...)
+{
va_list args;
int bx, by;
struct block_list *bl;
@@ -683,49 +731,95 @@ static int bl_getall_area(int type, int m, int x0, int y0, int x1, int y1, int (
x1 = min(x1, map->list[m].xs - 1);
y1 = min(y1, map->list[m].ys - 1);
- for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
- for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) {
- if (type&~BL_MOB) {
- for (bl = map->list[m].block[bx + by * map->list[m].bxs]; bl != NULL; bl = bl->next) {
- if (bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1) {
- if( map->bl_list_count >= map->bl_list_size )
- map_bl_list_expand();
- if (func) {
- va_start(args, func);
- if (func(bl, args)) {
+ {
+ const int x0b = x0 / BLOCK_SIZE;
+ const int x1b = x1 / BLOCK_SIZE;
+ const int y0b = y0 / BLOCK_SIZE;
+ const int y1b = y1 / BLOCK_SIZE;
+ const struct map_data *const listm = &map->list[m];
+ const int bxs0 = listm->bxs;
+
+ // duplication for better performance
+ if (func != NULL) {
+ if (type & ~BL_MOB) {
+ for (by = y0b; by <= y1b; by++) {
+ const int bxs = by * bxs0;
+ for (bx = x0b; bx <= x1b; bx++) {
+ for (bl = listm->block[bx + bxs]; bl != NULL; bl = bl->next) {
+ const int x = bl->x;
+ const int y = bl->y;
+ if (bl->type & type && x >= x0 && x <= x1 && y >= y0 && y <= y1) {
+ va_start(args, func);
+ if (func(bl, args)) {
+ if (map->bl_list_count >= map->bl_list_size)
+ map_bl_list_expand();
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ va_end(args);
+ }
+ }
+ }
+ }
+ }
+ if (type & BL_MOB) {
+ for (by = y0b; by <= y1b; by++) {
+ const int bxs = by * bxs0;
+ for (bx = x0b; bx <= x1b; bx++) {
+ for (bl = listm->block_mob[bx + bxs]; bl != NULL; bl = bl->next) {
+ const int x = bl->x;
+ const int y = bl->y;
+ if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
+ va_start(args, func);
+ if (func(bl, args)) {
+ if (map->bl_list_count >= map->bl_list_size)
+ map_bl_list_expand();
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ va_end(args);
+ }
+ }
+ }
+ }
+ }
+ } else { // func != NULL
+ if (type & ~BL_MOB) {
+ for (by = y0b; by <= y1b; by++) {
+ const int bxs = by * bxs0;
+ for (bx = x0b; bx <= x1b; bx++) {
+ for (bl = listm->block[bx + bxs]; bl != NULL; bl = bl->next) {
+ const int x = bl->x;
+ const int y = bl->y;
+ if (bl->type & type && x >= x0 && x <= x1 && y >= y0 && y <= y1) {
+ if (map->bl_list_count >= map->bl_list_size)
+ map_bl_list_expand();
map->bl_list[map->bl_list_count++] = bl;
found++;
}
- va_end(args);
- } else {
- map->bl_list[map->bl_list_count++] = bl;
- found++;
}
}
}
}
- if (type&BL_MOB) { // TODO: fix this code duplication
- for (bl = map->list[m].block_mob[bx + by * map->list[m].bxs]; bl != NULL; bl = bl->next) {
- if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1) {
- if( map->bl_list_count >= map->bl_list_size )
- map_bl_list_expand();
- if (func) {
- va_start(args, func);
- if (func(bl, args)) {
+ if (type & BL_MOB) {
+ for (by = y0b; by <= y1b; by++) {
+ const int bxs = by * bxs0;
+ for (bx = x0b; bx <= x1b; bx++) {
+ for (bl = listm->block_mob[bx + bxs]; bl != NULL; bl = bl->next) {
+ const int x = bl->x;
+ const int y = bl->y;
+ if (x >= x0 && x <= x1 && y >= y0 && y <= y1) {
+ if (map->bl_list_count >= map->bl_list_size)
+ map_bl_list_expand();
map->bl_list[map->bl_list_count++] = bl;
found++;
}
- va_end(args);
- } else {
- map->bl_list[map->bl_list_count++] = bl;
- found++;
}
}
}
}
}
}
-
return found;
}
@@ -757,7 +851,8 @@ static int bl_vgetall_inrange(struct block_list *bl, va_list args)
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, va_list ap) {
+static int map_vforeachinrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -785,7 +880,8 @@ int map_vforeachinrange(int (*func)(struct block_list*, va_list), struct block_l
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, ...) {
+static int map_foreachinrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int type, ...)
+{
int returnCount;
va_list ap;
@@ -809,7 +905,8 @@ int map_foreachinrange(int (*func)(struct block_list*, va_list), struct block_li
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforcountinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int count, int type, va_list ap) {
+static int map_vforcountinrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int count, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -839,7 +936,8 @@ int map_vforcountinrange(int (*func)(struct block_list*, va_list), struct block_
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_forcountinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int count, int type, ...) {
+static int map_forcountinrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int count, int type, ...)
+{
int returnCount;
va_list ap;
@@ -885,7 +983,8 @@ static int bl_vgetall_inshootrange(struct block_list *bl, va_list args)
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachinshootrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, va_list ap) {
+static int map_vforeachinshootrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -913,7 +1012,8 @@ int map_vforeachinshootrange(int (*func)(struct block_list*, va_list), struct bl
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinshootrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, ...) {
+static int map_foreachinshootrange(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int type, ...)
+{
int returnCount;
va_list ap;
@@ -938,7 +1038,8 @@ int map_foreachinshootrange(int (*func)(struct block_list*, va_list), struct blo
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, va_list ap) {
+static int map_vforeachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -967,7 +1068,8 @@ int map_vforeachinarea(int (*func)(struct block_list*, va_list), int16 m, int16
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...) {
+static int map_foreachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...)
+{
int returnCount;
va_list ap;
@@ -994,7 +1096,8 @@ int map_foreachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, va_list ap) {
+static int map_vforcountinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -1025,7 +1128,8 @@ int map_vforcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...) {
+static int map_forcountinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...)
+{
int returnCount;
va_list ap;
@@ -1082,7 +1186,8 @@ static int bl_vgetall_inmovearea(struct block_list *bl, va_list args)
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachinmovearea(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, va_list ap) {
+static int map_vforeachinmovearea(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int16 dx, int16 dy, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
int m, x0, x1, y0, y1;
@@ -1140,7 +1245,8 @@ int map_vforeachinmovearea(int (*func)(struct block_list*, va_list), struct bloc
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinmovearea(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...) {
+static int map_foreachinmovearea(int (*func)(struct block_list*, va_list), struct block_list *center, int16 range, int16 dx, int16 dy, int type, ...)
+{
int returnCount;
va_list ap;
@@ -1163,7 +1269,8 @@ int map_foreachinmovearea(int (*func)(struct block_list*, va_list), struct block
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, va_list ap) {
+static int map_vforeachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, va_list ap)
+{
int returnCount = 0;
int blockcount = map->bl_list_count;
va_list apcopy;
@@ -1189,7 +1296,8 @@ int map_vforeachincell(int (*func)(struct block_list*, va_list), int16 m, int16
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, ...) {
+static int map_foreachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, ...)
+{
int returnCount;
va_list ap;
@@ -1268,7 +1376,8 @@ static int bl_vgetall_inpath(struct block_list *bl, va_list args)
* @param ap Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_vforeachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, va_list ap) {
+static int map_vforeachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, va_list ap)
+{
// [Skotlex]
// check for all targets in the square that
// contains the initial and final positions (area range increased to match the
@@ -1345,7 +1454,8 @@ int map_vforeachinpath(int (*func)(struct block_list*, va_list), int16 m, int16
* @param ... Extra arguments for func
* @return Sum of the values returned by func
*/
-int map_foreachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...) {
+static int map_foreachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...)
+{
int returnCount;
va_list ap;
@@ -1361,7 +1471,7 @@ int map_foreachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x
/// Generates a new flooritem object id from the interval [MIN_FLOORITEM, MAX_FLOORITEM).
/// Used for floor items, skill units and chatroom objects.
/// @return The new object id
-int map_get_new_object_id(void)
+static int map_get_new_object_id(void)
{
static int last_object_id = MIN_FLOORITEM - 1;
int i;
@@ -1393,7 +1503,7 @@ int map_get_new_object_id(void)
* Timered function to clear the floor (remove remaining item)
* Called each flooritem_lifetime ms
*------------------------------------------*/
-int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data)
+static int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data)
{
struct block_list *bl = idb_get(map->id_db, id);
struct flooritem_data *fitem = BL_CAST(BL_ITEM, bl);
@@ -1416,7 +1526,7 @@ int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data)
/*
* clears a single bl item out of the bazooonga.
*/
-void map_clearflooritem(struct block_list *bl)
+static void map_clearflooritem(struct block_list *bl)
{
struct flooritem_data *fitem = BL_CAST(BL_ITEM, bl);
@@ -1436,7 +1546,8 @@ void map_clearflooritem(struct block_list *bl)
* to place an BL_ITEM object. Scan area is 9x9, returns 1 on success.
* x and y are modified with the target cell when successful.
*------------------------------------------*/
-int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int stack) {
+static int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int stack)
+{
int free_cell,i,j;
int free_cells[9][2];
@@ -1466,7 +1577,8 @@ int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16
return 1;
}
-int map_count_sub(struct block_list *bl,va_list ap) {
+static int map_count_sub(struct block_list *bl, va_list ap)
+{
return 1;
}
@@ -1482,7 +1594,7 @@ int map_count_sub(struct block_list *bl,va_list ap) {
* &2 = the target should be able to walk to the target tile.
* &4 = there shouldn't be any players around the target tile (use the no_spawn_on_player setting)
*------------------------------------------*/
-int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int16 rx, int16 ry, int flag)
+static int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag)
{
int tries, spawn=0;
int bx, by;
@@ -1556,9 +1668,9 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
* flag:
* 0x1 - only count standing units
*------------------------------------------*/
-bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag)
+static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag)
{
- uint8 dir = 6;
+ enum unit_dir dir = UNIT_DIR_EAST;
int16 tx;
int16 ty;
int costrange = 10;
@@ -1577,7 +1689,7 @@ bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16
short dy = diry[dir];
//Linear search
- if(dir%2 == 0 && costrange%MOVE_COST == 0) {
+ if (!unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 0) {
tx = *x+dx*(costrange/MOVE_COST);
ty = *y+dy*(costrange/MOVE_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1587,7 +1699,7 @@ bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16
}
}
//Full diagonal search
- else if(dir%2 == 1 && costrange%MOVE_DIAGONAL_COST == 0) {
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_DIAGONAL_COST) == 0) {
tx = *x+dx*(costrange/MOVE_DIAGONAL_COST);
ty = *y+dy*(costrange/MOVE_DIAGONAL_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1597,16 +1709,24 @@ bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16
}
}
//One cell diagonal, rest linear (TODO: Find a better algorithm for this)
- else if(dir%2 == 1 && costrange%MOVE_COST == 4) {
- tx = *x+dx*((dir%4==3)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==1)?(costrange/MOVE_COST):1);
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 4) {
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ tx = tx * costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ ty = ty * costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
return true;
}
- tx = *x+dx*((dir%4==1)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==3)?(costrange/MOVE_COST):1);
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ tx = tx * costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ ty = ty * costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
@@ -1615,17 +1735,17 @@ bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16
}
//Get next direction
- if (dir == 5) {
+ if (dir == UNIT_DIR_SOUTHEAST) {
//Diagonal search complete, repeat with higher cost range
if(costrange == 14) costrange += 6;
else if(costrange == 28 || costrange >= 38) costrange += 2;
else costrange += 4;
- dir = 6;
- } else if (dir == 4) {
+ dir = UNIT_DIR_EAST;
+ } else if (dir == UNIT_DIR_SOUTH) {
//Linear search complete, switch to diagonal directions
- dir = 7;
+ dir = UNIT_DIR_NORTHEAST;
} else {
- dir = (dir+2)%8;
+ dir = unit_get_ccw90_dir(dir);
}
}
@@ -1640,8 +1760,9 @@ bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16
* @m, @x, @y mapid,x,y
* @first_charid, @second_charid, @third_charid, looting priority
* @flag: &1 MVP item. &2 do stacking check.
+ * @showdropeffect: show effect when the item is dropped.
*------------------------------------------*/
-int map_addflooritem(const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags)
+static int map_addflooritem(const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags, bool showdropeffect)
{
int r;
struct flooritem_data *fitem=NULL;
@@ -1660,6 +1781,7 @@ int map_addflooritem(const struct block_list *bl, struct item *item_data, int am
fitem->bl.x = x;
fitem->bl.y = y;
fitem->bl.id = map->get_new_object_id();
+ fitem->showdropeffect = showdropeffect;
if(fitem->bl.id==0){
ers_free(map->flooritem_ers, fitem);
return 0;
@@ -1688,7 +1810,7 @@ int map_addflooritem(const struct block_list *bl, struct item *item_data, int am
/**
* @see DBCreateData
*/
-struct DBData create_charid2nick(union DBKey key, va_list args)
+static struct DBData create_charid2nick(union DBKey key, va_list args)
{
struct charid2nick *p;
CREATE(p, struct charid2nick, 1);
@@ -1697,7 +1819,7 @@ struct DBData create_charid2nick(union DBKey key, va_list args)
/// Adds(or replaces) the nick of charid to nick_db and fullfils pending requests.
/// Does nothing if the character is online.
-void map_addnickdb(int charid, const char* nick)
+static void map_addnickdb(int charid, const char *nick)
{
struct charid2nick* p;
struct charid_request* req;
@@ -1721,7 +1843,7 @@ void map_addnickdb(int charid, const char* nick)
/// Removes the nick of charid from nick_db.
/// Sends name to all pending requests on charid.
-void map_delnickdb(int charid, const char* name)
+static void map_delnickdb(int charid, const char *name)
{
struct charid2nick* p;
struct charid_request* req;
@@ -1745,7 +1867,7 @@ void map_delnickdb(int charid, const char* name)
/// Notifies sd of the nick of charid.
/// Uses the name in the character if online.
/// Uses the name in nick_db if offline.
-void map_reqnickdb(struct map_session_data * sd, int charid)
+static void map_reqnickdb(struct map_session_data *sd, int charid)
{
struct charid2nick* p;
struct charid_request* req;
@@ -1774,7 +1896,7 @@ void map_reqnickdb(struct map_session_data * sd, int charid)
/*==========================================
* add bl to id_db
*------------------------------------------*/
-void map_addiddb(struct block_list *bl)
+static void map_addiddb(struct block_list *bl)
{
nullpo_retv(bl);
@@ -1786,7 +1908,7 @@ void map_addiddb(struct block_list *bl)
struct mob_data *md = BL_UCAST(BL_MOB, bl);
idb_put(map->mobid_db,bl->id,bl);
- if( md->state.boss )
+ if (md->state.boss == BTYPE_MVP)
idb_put(map->bossid_db, bl->id, bl);
}
@@ -1799,7 +1921,7 @@ void map_addiddb(struct block_list *bl)
/*==========================================
* remove bl from id_db
*------------------------------------------*/
-void map_deliddb(struct block_list *bl)
+static void map_deliddb(struct block_list *bl)
{
nullpo_retv(bl);
@@ -1821,7 +1943,8 @@ void map_deliddb(struct block_list *bl)
/*==========================================
* Standard call when a player connection is closed.
*------------------------------------------*/
-int map_quit(struct map_session_data *sd) {
+static int map_quit(struct map_session_data *sd)
+{
int i;
nullpo_ret(sd);
@@ -1848,6 +1971,9 @@ int map_quit(struct map_session_data *sd) {
if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */
bg->team_leave(sd,BGTL_QUIT);
+ if (sd->status.clan_id)
+ clan->member_offline(sd);
+
if (sd->state.autotrade && core->runflag != MAPSERVER_ST_SHUTDOWN && !channel->config->closing)
pc->autotrade_update(sd,PAUC_REMOVE);
@@ -1867,6 +1993,7 @@ int map_quit(struct map_session_data *sd) {
}
npc->script_event(sd, NPCE_LOGOUT);
+ rodex->clean(sd, 0);
//Unit_free handles clearing the player related data,
//map->quit handles extra specific data which is related to quitting normally
@@ -1882,6 +2009,7 @@ int map_quit(struct map_session_data *sd) {
case SC_GDSKILL_REGENERATION:
if( !sd->sc.data[i]->val4 )
break;
+ FALLTHROUGH
default:
status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER);
}
@@ -1946,7 +2074,7 @@ int map_quit(struct map_session_data *sd) {
* @return The searched map_session_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a player unit.
*/
-struct map_session_data *map_id2sd(int id)
+static struct map_session_data *map_id2sd(int id)
{
struct block_list *bl = NULL;
if (id <= 0)
@@ -1966,7 +2094,7 @@ struct map_session_data *map_id2sd(int id)
* @return The searched npc_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a NPC.
*/
-struct npc_data *map_id2nd(int id)
+static struct npc_data *map_id2nd(int id)
{
// just a id2bl lookup because there's no npc_db
struct block_list* bl = map->id2bl(id);
@@ -1983,7 +2111,7 @@ struct npc_data *map_id2nd(int id)
* @return The searched mob_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a mob unit.
*/
-struct mob_data *map_id2md(int id)
+static struct mob_data *map_id2md(int id)
{
struct block_list *bl = NULL;
if (id <= 0)
@@ -2003,7 +2131,7 @@ struct mob_data *map_id2md(int id)
* @return The searched flooritem_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a floor item.
*/
-struct flooritem_data *map_id2fi(int id)
+static struct flooritem_data *map_id2fi(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2017,7 +2145,7 @@ struct flooritem_data *map_id2fi(int id)
* @return The searched chat_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a chat.
*/
-struct chat_data *map_id2cd(int id)
+static struct chat_data *map_id2cd(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2031,7 +2159,7 @@ struct chat_data *map_id2cd(int id)
* @return The searched skill_unit data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a skill unit.
*/
-struct skill_unit *map_id2su(int id)
+static struct skill_unit *map_id2su(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2045,7 +2173,7 @@ struct skill_unit *map_id2su(int id)
* @return The searched pet_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a pet.
*/
-struct pet_data *map_id2pd(int id)
+static struct pet_data *map_id2pd(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2059,7 +2187,7 @@ struct pet_data *map_id2pd(int id)
* @return The searched homun_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a homunculus.
*/
-struct homun_data *map_id2hd(int id)
+static struct homun_data *map_id2hd(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2073,7 +2201,7 @@ struct homun_data *map_id2hd(int id)
* @return The searched mercenary_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to a mercenary.
*/
-struct mercenary_data *map_id2mc(int id)
+static struct mercenary_data *map_id2mc(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2087,7 +2215,7 @@ struct mercenary_data *map_id2mc(int id)
* @return The searched elemental_data, if it exists.
* @retval NULL if the ID is invalid or doesn't belong to an elemental.
*/
-struct elemental_data *map_id2ed(int id)
+static struct elemental_data *map_id2ed(int id)
{
struct block_list* bl = map->id2bl(id);
@@ -2103,7 +2231,7 @@ struct elemental_data *map_id2ed(int id)
* @return The searched block_list, if it exists.
* @retval NULL if the ID is invalid.
*/
-struct block_list *map_id2bl(int id)
+static struct block_list *map_id2bl(int id)
{
return idb_get(map->id_db, id);
}
@@ -2115,13 +2243,14 @@ struct block_list *map_id2bl(int id)
* @retval true if the ID exists and is valid.
* @retval false otherwise.
*/
-bool map_blid_exists(int id)
+static bool map_blid_exists(int id)
{
return (idb_exists(map->id_db,id));
}
/// Returns the nick of the target charid or NULL if unknown (requests the nick to the char server).
-const char *map_charid2nick(int charid) {
+static const char *map_charid2nick(int charid)
+{
struct charid2nick *p;
struct map_session_data* sd;
@@ -2138,7 +2267,7 @@ const char *map_charid2nick(int charid) {
}
/// Returns the struct map_session_data of the charid or NULL if the char is not online.
-struct map_session_data* map_charid2sd(int charid)
+static struct map_session_data *map_charid2sd(int charid)
{
struct block_list *bl = idb_get(map->charid_db, charid);
if (bl)
@@ -2151,30 +2280,25 @@ struct map_session_data* map_charid2sd(int charid)
* (without sensitive case if necessary)
* return map_session_data pointer or NULL
*------------------------------------------*/
-struct map_session_data * map_nick2sd(const char *nick)
+static struct map_session_data *map_nick2sd(const char *nick, bool allow_partial)
{
- struct map_session_data* sd;
- struct map_session_data* found_sd;
- struct s_mapiterator* iter;
- size_t nicklen;
- int qty = 0;
-
- if( nick == NULL )
+ if (nick == NULL)
return NULL;
- nicklen = strlen(nick);
- iter = mapit_getallusers();
+ struct s_mapiterator *iter = mapit_getallusers();
+ struct map_session_data *found_sd = NULL;
+
+ if (battle_config.partial_name_scan && allow_partial) {
+ int nicklen = (int)strlen(nick);
+ int qty = 0;
- found_sd = NULL;
- for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if( battle_config.partial_name_scan )
- {// partial name search
- if( strnicmp(sd->status.name, nick, nicklen) == 0 )
- {
+ // partial name search
+ for (struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (strnicmp(sd->status.name, nick, nicklen) == 0) {
found_sd = sd;
- if( strcmp(sd->status.name, nick) == 0 )
- {// Perfect Match
+ if (strcmp(sd->status.name, nick) == 0) {
+ // Perfect Match
qty = 1;
break;
}
@@ -2182,24 +2306,27 @@ struct map_session_data * map_nick2sd(const char *nick)
qty++;
}
}
- else if( strcasecmp(sd->status.name, nick) == 0 )
- {// exact search only
- found_sd = sd;
- break;
+
+ if (qty != 1)
+ found_sd = NULL;
+ } else {
+ // exact search only
+ for (struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (strcasecmp(sd->status.name, nick) == 0) {
+ found_sd = sd;
+ break;
+ }
}
}
mapit->free(iter);
- if( battle_config.partial_name_scan && qty != 1 )
- found_sd = NULL;
-
return found_sd;
}
/*==========================================
* Convext Mirror
*------------------------------------------*/
-struct mob_data *map_getmob_boss(int16 m)
+static struct mob_data *map_getmob_boss(int16 m)
{
struct DBIterator *iter;
struct mob_data *md = NULL;
@@ -2217,7 +2344,7 @@ struct mob_data *map_getmob_boss(int16 m)
return (found)? md : NULL;
}
-struct mob_data *map_id2boss(int id)
+static struct mob_data *map_id2boss(int id)
{
struct block_list *bl = NULL;
if (id <= 0)
@@ -2235,7 +2362,7 @@ struct mob_data *map_id2boss(int id)
*
* @return The equivalent race bitmask.
*/
-uint32 map_race_id2mask(int race)
+static uint32 map_race_id2mask(int race)
{
if (race >= RC_FORMLESS && race < RC_MAX)
return 1 << race;
@@ -2263,7 +2390,7 @@ uint32 map_race_id2mask(int race)
/// Applies func to all the players in the db.
/// Stops iterating if func returns -1.
-void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_list args)
+static void map_vforeachpc(int (*func)(struct map_session_data *sd, va_list args), va_list args)
{
struct DBIterator *iter = db_iterator(map->pc_db);
struct map_session_data *sd = NULL;
@@ -2285,7 +2412,8 @@ void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_l
/// Applies func to all the players in the db.
/// Stops iterating if func returns -1.
/// @see map_vforeachpc
-void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) {
+static void map_foreachpc(int (*func)(struct map_session_data *sd, va_list args), ...)
+{
va_list args;
va_start(args, func);
@@ -2295,7 +2423,7 @@ void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...)
/// Applies func to all the mobs in the db.
/// Stops iterating if func returns -1.
-void map_vforeachmob(int (*func)(struct mob_data* md, va_list args), va_list args)
+static void map_vforeachmob(int (*func)(struct mob_data *md, va_list args), va_list args)
{
struct DBIterator *iter = db_iterator(map->mobid_db);
struct mob_data *md = NULL;
@@ -2316,7 +2444,8 @@ void map_vforeachmob(int (*func)(struct mob_data* md, va_list args), va_list arg
/// Applies func to all the mobs in the db.
/// Stops iterating if func returns -1.
/// @see map_vforeachmob
-void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) {
+static void map_foreachmob(int (*func)(struct mob_data *md, va_list args), ...)
+{
va_list args;
va_start(args, func);
@@ -2326,7 +2455,7 @@ void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) {
/// Applies func to all the npcs in the db.
/// Stops iterating if func returns -1.
-void map_vforeachnpc(int (*func)(struct npc_data* nd, va_list args), va_list args)
+static void map_vforeachnpc(int (*func)(struct npc_data *nd, va_list args), va_list args)
{
struct DBIterator *iter = db_iterator(map->id_db);
struct block_list *bl = NULL;
@@ -2350,7 +2479,8 @@ void map_vforeachnpc(int (*func)(struct npc_data* nd, va_list args), va_list arg
/// Applies func to all the npcs in the db.
/// Stops iterating if func returns -1.
/// @see map_vforeachnpc
-void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) {
+static void map_foreachnpc(int (*func)(struct npc_data *nd, va_list args), ...)
+{
va_list args;
va_start(args, func);
@@ -2360,7 +2490,7 @@ void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) {
/// Applies func to everything in the db.
/// Stops iterating gif func returns -1.
-void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list args)
+static void map_vforeachregen(int (*func)(struct block_list *bl, va_list args), va_list args)
{
struct DBIterator *iter = db_iterator(map->regen_db);
struct block_list *bl = NULL;
@@ -2381,7 +2511,8 @@ void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list
/// Applies func to everything in the db.
/// Stops iterating gif func returns -1.
/// @see map_vforeachregen
-void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) {
+static void map_foreachregen(int (*func)(struct block_list *bl, va_list args), ...)
+{
va_list args;
va_start(args, func);
@@ -2391,7 +2522,7 @@ void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) {
/// Applies func to everything in the db.
/// Stops iterating if func returns -1.
-void map_vforeachiddb(int (*func)(struct block_list* bl, va_list args), va_list args)
+static void map_vforeachiddb(int (*func)(struct block_list *bl, va_list args), va_list args)
{
struct DBIterator *iter = db_iterator(map->id_db);
struct block_list *bl = NULL;
@@ -2412,7 +2543,8 @@ void map_vforeachiddb(int (*func)(struct block_list* bl, va_list args), va_list
/// Applies func to everything in the db.
/// Stops iterating if func returns -1.
/// @see map_vforeachiddb
-void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) {
+static void map_foreachiddb(int (*func)(struct block_list *bl, va_list args), ...)
+{
va_list args;
va_start(args, func);
@@ -2444,7 +2576,8 @@ struct s_mapiterator {
/// @param flags Flags of the iterator
/// @param type Target types
/// @return Iterator
-struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) {
+static struct s_mapiterator *mapit_alloc(enum e_mapitflags flags, enum bl_type types)
+{
struct s_mapiterator* iter;
iter = ers_alloc(map->iterator_ers, struct s_mapiterator);
@@ -2459,7 +2592,8 @@ struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) {
/// Frees the iterator.
///
/// @param iter Iterator
-void mapit_free(struct s_mapiterator* iter) {
+static void mapit_free(struct s_mapiterator *iter)
+{
nullpo_retv(iter);
dbi_destroy(iter->dbi);
@@ -2471,7 +2605,8 @@ void mapit_free(struct s_mapiterator* iter) {
///
/// @param iter Iterator
/// @return first block_list or NULL
-struct block_list* mapit_first(struct s_mapiterator* iter) {
+static struct block_list *mapit_first(struct s_mapiterator *iter)
+{
struct block_list* bl;
nullpo_retr(NULL,iter);
@@ -2488,7 +2623,8 @@ struct block_list* mapit_first(struct s_mapiterator* iter) {
///
/// @param iter Iterator
/// @return last block_list or NULL
-struct block_list* mapit_last(struct s_mapiterator* iter) {
+static struct block_list *mapit_last(struct s_mapiterator *iter)
+{
struct block_list* bl;
nullpo_retr(NULL,iter);
@@ -2505,7 +2641,8 @@ struct block_list* mapit_last(struct s_mapiterator* iter) {
///
/// @param iter Iterator
/// @return next block_list or NULL
-struct block_list* mapit_next(struct s_mapiterator* iter) {
+static struct block_list *mapit_next(struct s_mapiterator *iter)
+{
struct block_list* bl;
nullpo_retr(NULL,iter);
@@ -2526,7 +2663,8 @@ struct block_list* mapit_next(struct s_mapiterator* iter) {
///
/// @param iter Iterator
/// @return previous block_list or NULL
-struct block_list* mapit_prev(struct s_mapiterator* iter) {
+static struct block_list *mapit_prev(struct s_mapiterator *iter)
+{
struct block_list* bl;
nullpo_retr(NULL,iter);
@@ -2546,7 +2684,8 @@ struct block_list* mapit_prev(struct s_mapiterator* iter) {
///
/// @param iter Iterator
/// @return true if it exists
-bool mapit_exists(struct s_mapiterator* iter) {
+static bool mapit_exists(struct s_mapiterator *iter)
+{
nullpo_retr(false,iter);
return dbi_exists(iter->dbi);
@@ -2555,7 +2694,8 @@ bool mapit_exists(struct s_mapiterator* iter) {
/*==========================================
* Add npc-bl to id_db, basically register npc to map
*------------------------------------------*/
-bool map_addnpc(int16 m,struct npc_data *nd) {
+static bool map_addnpc(int16 m, struct npc_data *nd)
+{
nullpo_ret(nd);
if( m < 0 || m >= map->count )
@@ -2577,7 +2717,8 @@ bool map_addnpc(int16 m,struct npc_data *nd) {
*-----------------------------------------*/
// Stores the spawn data entry in the mob list.
// Returns the index of successful, or -1 if the list was full.
-int map_addmobtolist(unsigned short m, struct spawn_data *spawn) {
+static int map_addmobtolist(unsigned short m, struct spawn_data *spawn)
+{
int i;
nullpo_retr(-1, spawn);
ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map->list[m].moblist[i] == NULL );
@@ -2588,7 +2729,8 @@ int map_addmobtolist(unsigned short m, struct spawn_data *spawn) {
return -1;
}
-void map_spawnmobs(int16 m) {
+static void map_spawnmobs(int16 m)
+{
int i, k=0;
if (map->list[m].mob_delete_timer != INVALID_TIMER) {
//Mobs have not been removed yet [Skotlex]
@@ -2607,7 +2749,7 @@ void map_spawnmobs(int16 m) {
}
}
-int map_removemobs_sub(struct block_list *bl, va_list ap)
+static int map_removemobs_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
nullpo_ret(bl);
@@ -2636,7 +2778,8 @@ int map_removemobs_sub(struct block_list *bl, va_list ap)
return 1;
}
-int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) {
+static int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data)
+{
int count;
const int16 m = id;
@@ -2660,7 +2803,8 @@ int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) {
return 1;
}
-void map_removemobs(int16 m) {
+static void map_removemobs(int16 m)
+{
Assert_retv(m >= 0 && m < map->count);
if (map->list[m].mob_delete_timer != INVALID_TIMER) // should never happen
return; //Mobs are already scheduled for removal
@@ -2671,7 +2815,8 @@ void map_removemobs(int16 m) {
/*==========================================
* Hookup, get map_id from map_name
*------------------------------------------*/
-int16 map_mapname2mapid(const char* name) {
+static int16 map_mapname2mapid(const char *name)
+{
unsigned short map_index;
map_index = mapindex->name2id(name);
if (!map_index)
@@ -2682,7 +2827,8 @@ int16 map_mapname2mapid(const char* name) {
/*==========================================
* Returns the map of the given mapindex. [Skotlex]
*------------------------------------------*/
-int16 map_mapindex2mapid(unsigned short map_index) {
+static int16 map_mapindex2mapid(unsigned short map_index)
+{
if (!map_index || map_index >= MAX_MAPINDEX)
return -1;
@@ -2693,7 +2839,8 @@ int16 map_mapindex2mapid(unsigned short map_index) {
/*==========================================
* Switching Ip, port ? (like changing map_server) get ip/port from map_name
*------------------------------------------*/
-int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) {
+static int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port)
+{
struct map_data_other_server *mdos;
nullpo_retr(-1, ip);
@@ -2706,63 +2853,70 @@ int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) {
return 0;
}
-/*==========================================
-* Checks if both dirs point in the same direction.
-*------------------------------------------*/
-int map_check_dir(int s_dir,int t_dir)
+/**
+ * Checks if both dirs point in the same direction.
+ * @param s_dir: direction source is facing
+ * @param t_dir: direction target is facing
+ * @return 0: success(both face the same direction), 1: failure
+ **/
+static int map_check_dir(enum unit_dir s_dir, enum unit_dir t_dir)
{
- if(s_dir == t_dir)
+ if (s_dir == t_dir || ((t_dir + UNIT_DIR_MAX - 1) % UNIT_DIR_MAX) == s_dir
+ || ((t_dir + UNIT_DIR_MAX + 1) % UNIT_DIR_MAX) == s_dir)
return 0;
- switch(s_dir) {
- case 0: if(t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; break;
- case 1: if(t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; break;
- case 2: if(t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; break;
- case 3: if(t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; break;
- case 4: if(t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; break;
- case 5: if(t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; break;
- case 6: if(t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; break;
- case 7: if(t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; break;
- }
return 1;
}
-/*==========================================
+/**
* Returns the direction of the given cell, relative to 'src'
- *------------------------------------------*/
-uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
+ * @param src: object to put in relation between coordinates
+ * @param x: x-coordinate of cell
+ * @param y: y-coordinate of cell
+ * @return the direction of the given cell, relative to 'src'
+ **/
+static enum unit_dir map_calc_dir(const struct block_list *src, int16 x, int16 y)
{
- uint8 dir = 0;
- int dx, dy;
-
- nullpo_ret(src);
+ nullpo_retr(UNIT_DIR_NORTH, src);
+ enum unit_dir dir = UNIT_DIR_NORTH;
- dx = x-src->x;
- dy = y-src->y;
+ int dx = x - src->x;
+ int dy = y - src->y;
if (dx == 0 && dy == 0) {
// both are standing on the same spot.
// aegis-style, makes knockback default to the left.
// athena-style, makes knockback default to behind 'src'.
- dir = (battle_config.knockback_left ? 6 : unit->getdir(src));
- } else if (dx >= 0 && dy >=0) {
- // upper-right
- if( dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( dx > dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 7; // up-right
+ if (battle_config.knockback_left != 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = unit->getdir(src);
+ } else if (dx >= 0 && dy >= 0) {
+ if (dx * 2 < dy || dx == 0)
+ dir = UNIT_DIR_NORTH;
+ else if (dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_NORTHEAST;
} else if (dx >= 0 && dy <= 0) {
- // lower-right
- if( dx*2 < -dy || dx == 0 ) dir = 4; // down
- else if( dx > -dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 5; // down-right
+ if (dx * 2 < -dy || dx == 0)
+ dir = UNIT_DIR_SOUTH;
+ else if (dx > -dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_SOUTHEAST;
} else if (dx <= 0 && dy <= 0) {
- // lower-left
- if( dx*2 > dy || dx == 0 ) dir = 4; // down
- else if( dx < dy*2-1 || dy == 0 ) dir = 2; // left
- else dir = 3; // down-left
+ if (dx * 2 > dy || dx == 0 )
+ dir = UNIT_DIR_SOUTH;
+ else if (dx < dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_SOUTHWEST;
} else {
- // upper-left
- if( -dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( -dx > dy*2+1 || dy == 0) dir = 2; // left
- else dir = 1; // up-left
+ if (-dx * 2 < dy || dx == 0 )
+ dir = UNIT_DIR_NORTH;
+ else if (-dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_NORTHWEST;
}
return dir;
}
@@ -2771,7 +2925,7 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
* Randomizes target cell x,y to a random walkable cell that
* has the same distance from object as given coordinates do. [Skotlex]
*------------------------------------------*/
-int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
+static int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
{
short xi;
short yi;
@@ -2790,11 +2944,11 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
if (dist < 1) dist =1;
do {
- int j = 1 + 2*(rnd()%4); //Pick a random diagonal direction
+ enum unit_dir dir = unit_get_rnd_diagonal_dir();
short segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction
- xi = bl->x + segment*dirx[j];
+ xi = bl->x + segment * dirx[dir];
segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
- yi = bl->y + segment*diry[j];
+ yi = bl->y + segment * diry[dir];
} while ((map->getcell(bl->m, bl, xi, yi, CELL_CHKNOPASS) || !path->search(NULL, bl, bl->m, bl->x, bl->y, xi, yi, 1, CELL_CHKNOREACH))
&& (++i)<100);
@@ -2807,7 +2961,8 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
}
// gat system
-struct mapcell map_gat2cell(int gat) {
+static struct mapcell map_gat2cell(int gat)
+{
struct mapcell cell;
memset(&cell,0,sizeof(struct mapcell));
@@ -2828,7 +2983,8 @@ struct mapcell map_gat2cell(int gat) {
return cell;
}
-int map_cell2gat(struct mapcell cell) {
+static int map_cell2gat(struct mapcell cell)
+{
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 0 ) return 0;
if( cell.walkable == 0 && cell.shootable == 0 && cell.water == 0 ) return 1;
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 1 ) return 3;
@@ -2837,21 +2993,26 @@ int map_cell2gat(struct mapcell cell) {
ShowWarning("map_cell2gat: cell has no matching gat type\n");
return 1; // default to 'wall'
}
-void map_cellfromcache(struct map_data *m) {
- struct map_cache_map_info *info;
+/**
+ * Extracts a map's cell data from its compressed mapcache.
+ *
+ * @param[in, out] m The target map.
+ */
+static void map_cellfromcache(struct map_data *m)
+{
nullpo_retv(m);
- info = (struct map_cache_map_info *)m->cellPos;
- if (info) {
+ if (m->cell_buf.data != NULL) {
char decode_buffer[MAX_MAP_SIZE];
unsigned long size, xy;
int i;
- size = (unsigned long)info->xs*(unsigned long)info->ys;
+ size = (unsigned long)m->xs * (unsigned long)m->ys;
// TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo]
- decode_zip(decode_buffer, &size, m->cellPos+sizeof(struct map_cache_map_info), info->len);
+ grfio->decode_zip(decode_buffer, &size, m->cell_buf.data, m->cell_buf.len);
+
CREATE(m->cell, struct mapcell, size);
// Set cell properties
@@ -2871,11 +3032,13 @@ void map_cellfromcache(struct map_data *m) {
/*==========================================
* Confirm if celltype in (m,x,y) match the one given in cellchk
*------------------------------------------*/
-int map_getcell(int16 m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) {
+static int map_getcell(int16 m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk)
+{
return (m < 0 || m >= map->count) ? 0 : map->list[m].getcellp(&map->list[m], bl, x, y, cellchk);
}
-int map_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) {
+static int map_getcellp(struct map_data *m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk)
+{
struct mapcell cell;
nullpo_ret(m);
@@ -2943,7 +3106,8 @@ int map_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16
}
/* [Ind/Hercules] */
-int map_sub_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) {
+static int map_sub_getcellp(struct map_data *m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk)
+{
nullpo_ret(m);
map->cellfromcache(m);
m->getcellp = map->getcellp;
@@ -2956,7 +3120,8 @@ int map_sub_getcellp(struct map_data* m, const struct block_list *bl, int16 x, i
* 'cell' - which flag to modify
* 'flag' - true = on, false = off
*------------------------------------------*/
-void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
+static void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
+{
int j;
if( m < 0 || m >= map->count || x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys )
@@ -2982,7 +3147,8 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
break;
}
}
-void map_sub_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
+static void map_sub_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
+{
if( m < 0 || m >= map->count || x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys )
return;
@@ -2991,7 +3157,8 @@ void map_sub_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
map->list[m].getcellp = map->getcellp;
map->list[m].setcell(m,x,y,cell,flag);
}
-void map_setgatcell(int16 m, int16 x, int16 y, int gat) {
+static void map_setgatcell(int16 m, int16 x, int16 y, int gat)
+{
int j;
struct mapcell cell;
@@ -3007,9 +3174,9 @@ void map_setgatcell(int16 m, int16 x, int16 y, int gat) {
}
/*==========================================
-* Invisible Walls
-*------------------------------------------*/
-void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1)
+ * Invisible Walls
+ *------------------------------------------*/
+static void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1)
{
nullpo_retv(x1);
nullpo_retv(y1);
@@ -3029,7 +3196,7 @@ void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1)
*y1 = y + pos;
}
-bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable, const char* wall_name)
+static bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable, const char *wall_name)
{
struct iwall_data *iwall;
int i;
@@ -3073,7 +3240,7 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable
return true;
}
-void map_iwall_get(struct map_session_data *sd)
+static void map_iwall_get(struct map_session_data *sd)
{
struct iwall_data *iwall;
struct DBIterator *iter;
@@ -3098,13 +3265,13 @@ void map_iwall_get(struct map_session_data *sd)
dbi_destroy(iter);
}
-void map_iwall_remove(const char *wall_name)
+static bool map_iwall_remove(const char *wall_name)
{
struct iwall_data *iwall;
int16 i, x1, y1;
if( (iwall = (struct iwall_data *)strdb_get(map->iwall_db, wall_name)) == NULL )
- return; // Nothing to do
+ return false;
for( i = 0; i < iwall->size; i++ ) {
map->iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
@@ -3117,12 +3284,13 @@ void map_iwall_remove(const char *wall_name)
map->list[iwall->m].iwall_num--;
strdb_remove(map->iwall_db, iwall->wall_name);
+ return true;
}
/**
* @see DBCreateData
*/
-struct DBData create_map_data_other_server(union DBKey key, va_list args)
+static struct DBData create_map_data_other_server(union DBKey key, va_list args)
{
struct map_data_other_server *mdos;
unsigned short map_index = (unsigned short)key.ui;
@@ -3135,7 +3303,7 @@ struct DBData create_map_data_other_server(union DBKey key, va_list args)
/*==========================================
* Add mapindex to db of another map server
*------------------------------------------*/
-int map_setipport(unsigned short map_index, uint32 ip, uint16 port)
+static int map_setipport(unsigned short map_index, uint32 ip, uint16 port)
{
struct map_data_other_server *mdos;
@@ -3157,7 +3325,7 @@ int map_setipport(unsigned short map_index, uint32 ip, uint16 port)
* Delete all the other maps server management
* @see DBApply
*/
-int map_eraseallipport_sub(union DBKey key, struct DBData *data, va_list va)
+static int map_eraseallipport_sub(union DBKey key, struct DBData *data, va_list va)
{
struct map_data_other_server *mdos = DB->data2ptr(data);
nullpo_ret(mdos);
@@ -3168,7 +3336,8 @@ int map_eraseallipport_sub(union DBKey key, struct DBData *data, va_list va)
return 0;
}
-int map_eraseallipport(void) {
+static int map_eraseallipport(void)
+{
map->map_db->foreach(map->map_db,map->eraseallipport_sub);
return 1;
}
@@ -3176,7 +3345,8 @@ int map_eraseallipport(void) {
/*==========================================
* Delete mapindex from db of another map server
*------------------------------------------*/
-int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port) {
+static int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port)
+{
struct map_data_other_server *mdos;
mdos = (struct map_data_other_server*)uidb_get(map->map_db,(unsigned int)map_index);
@@ -3191,113 +3361,163 @@ int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port) {
return 0;
}
-/*==========================================
- * [Shinryo]: Init the mapcache
- *------------------------------------------*/
-char *map_init_mapcache(FILE *fp) {
- struct map_cache_main_header header;
- size_t size = 0;
- char *buffer;
-
- // No file open? Return..
- nullpo_ret(fp);
+/**
+ * Reads a map's compressed cell data from its mapcache file.
+ *
+ * @param[in,out] m The target map.
+ * @return The loading success state.
+ * @retval false in case of errors.
+ */
+static bool map_readfromcache(struct map_data *m)
+{
+ unsigned int file_size;
+ char file_path[256];
+ FILE *fp = NULL;
+ bool retval = false;
+ int16 version;
- // Get file size
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
+ nullpo_retr(false, m);
- // Allocate enough space
- CREATE(buffer, char, size);
+ snprintf(file_path, sizeof(file_path), "%s%s%s.%s", "maps/", DBPATH, m->name, "mcache");
+ fp = fopen(file_path, "rb");
- // No memory? Return..
- nullpo_ret(buffer);
+ if (fp == NULL) {
+ ShowWarning("map_readfromcache: Could not open the mapcache file for map '%s' at path '%s'.\n", m->name, file_path);
+ return false;
+ }
- // 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;
+ if (fread(&version, sizeof(version), 1, fp) < 1) {
+ ShowError("map_readfromcache: Could not read file version for map '%s'.\n", m->name);
+ fclose(fp);
+ return false;
}
- rewind(fp);
+ fseek(fp, 0, SEEK_END);
+ file_size = (unsigned int)ftell(fp);
+ fseek(fp, 0, SEEK_SET); // Rewind file pointer before passing it to the read function.
- // 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;
+ switch(version) {
+ case 1:
+ retval = map->readfromcache_v1(fp, m, file_size);
+ break;
+ default:
+ ShowError("map_readfromcache: Mapcache file has unknown version '%d' for map '%s'.\n", version, m->name);
+ break;
}
- return buffer;
+ fclose(fp);
+ return retval;
}
-/*==========================================
- * Map cache reading
- * [Shinryo]: Optimized some behaviour to speed this up
- *==========================================*/
-int map_readfromcache(struct map_data *m, char *buffer) {
- int i;
- struct map_cache_main_header *header = (struct map_cache_main_header *)buffer;
- struct map_cache_map_info *info = NULL;
- char *p = buffer + sizeof(struct map_cache_main_header);
-
- nullpo_ret(m);
- nullpo_ret(buffer);
-
- for(i = 0; i < header->map_count; i++) {
- info = (struct map_cache_map_info *)p;
+/**
+ * Reads a map's compressed cell data from its mapcache file (file format
+ * version 1).
+ *
+ * @param[in] fp The file pointer to read from (opened and closed by
+ * the caller).
+ * @param[in,out] m The target map.
+ * @param[in] file_size The size of the file to load from.
+ * @return The loading success state.
+ * @retval false in case of errors.
+ */
+static bool map_readfromcache_v1(FILE *fp, struct map_data *m, unsigned int file_size)
+{
+ struct map_cache_header mheader = { 0 };
+ uint8 md5buf[16] = { 0 };
+ int map_size;
+ nullpo_retr(false, fp);
+ nullpo_retr(false, m);
+
+ if (file_size <= sizeof(mheader) || fread(&mheader, sizeof(mheader), 1, fp) < 1) {
+ ShowError("map_readfromcache: Failed to read cache header for map '%s'.\n", m->name);
+ return false;
+ }
- if( strcmp(m->name, info->name) == 0 )
- break; // Map found
+ if (mheader.len <= 0) {
+ ShowError("map_readfromcache: A file with negative or zero compressed length passed '%d'.\n", mheader.len);
+ return false;
+ }
- // Jump to next entry..
- p += sizeof(struct map_cache_map_info) + info->len;
+ if (file_size < sizeof(mheader) + mheader.len) {
+ ShowError("map_readfromcache: An incomplete file passed for map '%s'.\n", m->name);
+ return false;
}
- if( info && i < header->map_count ) {
- unsigned long size;
+ if (mheader.ys <= 0 || mheader.xs <= 0) {
+ ShowError("map_readfromcache: A map with invalid size passed '%s' xs: '%d' ys: '%d'.\n", m->name, mheader.xs, mheader.ys);
+ return false;
+ }
- if( info->xs <= 0 || info->ys <= 0 )
- return 0;// Invalid
+ m->xs = mheader.xs;
+ m->ys = mheader.ys;
+ map_size = (int)mheader.xs * (int)mheader.ys;
- m->xs = info->xs;
- m->ys = info->ys;
- size = (unsigned long)info->xs*(unsigned long)info->ys;
+ if (map_size > MAX_MAP_SIZE) {
+ ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d.\n", m->name, MAX_MAP_SIZE);
+ return false;
+ }
- if(size > MAX_MAP_SIZE) {
- ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d\n", info->name, MAX_MAP_SIZE);
- return 0; // Say not found to remove it from list.. [Shinryo]
- }
+ CREATE(m->cell_buf.data, uint8, mheader.len);
+ m->cell_buf.len = mheader.len;
+ if (fread(m->cell_buf.data, mheader.len, 1, fp) < 1) {
+ ShowError("mapreadfromcache: Could not load the compressed cell data for map '%s'.\n", m->name);
+ aFree(m->cell_buf.data);
+ m->cell_buf.data = NULL;
+ m->cell_buf.len = 0;
+ return false;
+ }
- m->cellPos = p;
- m->cell = (struct mapcell *)0xdeadbeaf;
+ md5->binary(m->cell_buf.data, m->cell_buf.len, md5buf);
- return 1;
+ if (memcmp(md5buf, mheader.md5_checksum, sizeof(md5buf)) != 0) {
+ ShowError("mapreadfromcache: md5 checksum check failed for map '%s'\n", m->name);
+ aFree(m->cell_buf.data);
+ m->cell_buf.data = NULL;
+ m->cell_buf.len = 0;
+ return false;
}
- return 0; // Not found
+ m->cell = (struct mapcell *)0xdeadbeaf;
+
+ return true;
}
-int map_addmap(const char* mapname) {
+/**
+ * Adds a new empty map to the map list.
+ *
+ * Assumes that there's enough space in the map list.
+ *
+ * @param mapname The new map's name.
+ * @return success state.
+ */
+static int map_addmap(const char *mapname)
+{
map->list[map->count].instance_id = -1;
mapindex->getmapname(mapname, map->list[map->count++].name);
return 0;
}
-void map_delmapid(int id) {
+/**
+ * Removes a map from the map list.
+ *
+ * @param id The map ID.
+ */
+static void map_delmapid(int id)
+{
Assert_retv(id >= 0 && id < map->count);
ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map->list[id].name);
memmove(map->list+id, map->list+id+1, sizeof(map->list[0])*(map->count-id-1));
map->count--;
}
-int map_delmap(char* mapname) {
+/**
+ * Removes a map fromt he map list.
+ *
+ * @param mapname The name of the map to remove.
+ * @return the number of removed maps.
+ */
+static int map_delmap(const char *mapname)
+{
int i;
char map_name[MAP_NAME_LENGTH];
@@ -3320,7 +3540,8 @@ int map_delmap(char* mapname) {
/**
*
**/
-void map_zone_clear_single(struct map_zone_data *zone) {
+static void map_zone_clear_single(struct map_zone_data *zone)
+{
int i;
nullpo_retv(zone);
@@ -3362,7 +3583,7 @@ void map_zone_clear_single(struct map_zone_data *zone) {
/**
*
**/
-void map_zone_db_clear(void)
+static void map_zone_db_clear(void)
{
struct DBIterator *iter = db_iterator(map->zone_db);
struct map_zone_data *zone = NULL;
@@ -3380,24 +3601,29 @@ void map_zone_db_clear(void)
/* clear the main zone stuff */
map->zone_clear_single(&map->zone_all);
}
-void map_clean(int i) {
- int v;
+static void map_clean(int i)
+{
Assert_retv(i >= 0 && i < map->count);
- if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map->list[i].cell);
- if(map->list[i].block) aFree(map->list[i].block);
- if(map->list[i].block_mob) aFree(map->list[i].block_mob);
- if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
- int j;
- if(map->list[i].mob_delete_timer != INVALID_TIMER)
+ if (map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf)
+ aFree(map->list[i].cell);
+ if (map->list[i].block)
+ aFree(map->list[i].block);
+ if (map->list[i].block_mob)
+ aFree(map->list[i].block_mob);
+
+ if (battle_config.dynamic_mobs != 0) { //Dynamic mobs flag by [random]
+ if (map->list[i].mob_delete_timer != INVALID_TIMER)
timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
- for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
+ for (int j = 0; j < MAX_MOB_LIST_PER_MAP; j++) {
+ if (map->list[i].moblist[j] != NULL)
+ aFree(map->list[i].moblist[j]);
+ }
}
- if( map->list[i].unit_count ) {
- if( map->list[i].units ) {
- for(v = 0; v < map->list[i].unit_count; v++) {
+ if (map->list[i].unit_count != 0) {
+ if (map->list[i].units != NULL) {
+ for (int v = 0; v < map->list[i].unit_count; v++) {
aFree(map->list[i].units[v]);
}
aFree(map->list[i].units);
@@ -3406,101 +3632,75 @@ void map_clean(int i) {
map->list[i].unit_count = 0;
}
- if( map->list[i].skill_count ) {
- if( map->list[i].skills ) {
- for(v = 0; v < map->list[i].skill_count; v++) {
- aFree(map->list[i].skills[v]);
- }
+ if (map->list[i].skill_count != 0) {
+ if (map->list[i].skills != NULL) {
+ for (int v = 0; v < map->list[i].skill_count; v++) {
+ aFree(map->list[i].skills[v]);
+ }
aFree(map->list[i].skills);
map->list[i].skills = NULL;
}
map->list[i].skill_count = 0;
}
- if( map->list[i].zone_mf_count ) {
- if( map->list[i].zone_mf ) {
- for(v = 0; v < map->list[i].zone_mf_count; v++) {
- aFree(map->list[i].zone_mf[v]);
- }
+ if (map->list[i].zone_mf_count != 0) {
+ if (map->list[i].zone_mf != NULL) {
+ for (int v = 0; v < map->list[i].zone_mf_count; v++) {
+ aFree(map->list[i].zone_mf[v]);
+ }
aFree(map->list[i].zone_mf);
map->list[i].zone_mf = NULL;
}
map->list[i].zone_mf_count = 0;
}
- if( map->list[i].channel )
- channel->delete(map->list[i].channel);
-}
-void do_final_maps(void) {
- int i, v = 0;
-
- for( i = 0; i < map->count; i++ ) {
-
- if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf ) aFree(map->list[i].cell);
- if(map->list[i].block) aFree(map->list[i].block);
- if(map->list[i].block_mob) aFree(map->list[i].block_mob);
+ if (map->list[i].drop_list_count != 0)
+ map->list[i].drop_list_count = 0;
+ if (map->list[i].drop_list != NULL)
+ aFree(map->list[i].drop_list);
- if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
- int j;
- if(map->list[i].mob_delete_timer != INVALID_TIMER)
- timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
- for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
- }
+ if (map->list[i].channel != NULL)
+ channel->delete(map->list[i].channel);
- if( map->list[i].unit_count ) {
- if( map->list[i].units ) {
- for(v = 0; v < map->list[i].unit_count; v++) {
- aFree(map->list[i].units[v]);
- }
- aFree(map->list[i].units);
- map->list[i].units = NULL;
- }
- map->list[i].unit_count = 0;
- }
+ VECTOR_CLEAR(map->list[i].qi_list);
+ HPM->data_store_destroy(&map->list[i].hdata);
+}
+static void do_final_maps(void)
+{
+ for (int i = 0; i < map->count; i++)
+ map->clean(i);
+ map->zone_db_clear();
+}
- if( map->list[i].skill_count ) {
- if( map->list[i].skills ) {
- for(v = 0; v < map->list[i].skill_count; v++) {
- aFree(map->list[i].skills[v]);
- }
- aFree(map->list[i].skills);
- map->list[i].skills = NULL;
- }
- map->list[i].skill_count = 0;
- }
+static void map_zonedb_reload(void)
+{
+ // first, reset maps to their initial zones:
+ for (int i = 0; i < map->count; i++) {
+ map->zone_remove_all(i);
- if( map->list[i].zone_mf_count ) {
- if( map->list[i].zone_mf ) {
- for(v = 0; v < map->list[i].zone_mf_count; v++) {
- aFree(map->list[i].zone_mf[v]);
- }
- aFree(map->list[i].zone_mf);
- map->list[i].zone_mf = NULL;
- }
- map->list[i].zone_mf_count = 0;
+ if (battle_config.pk_mode) {
+ map->list[i].flag.pvp = 1;
+ map->list[i].zone = &map->zone_pk;
+ } else {
+ map->list[i].flag.pvp = 0;
+ map->list[i].zone = &map->zone_all;
}
- if( map->list[i].drop_list_count ) {
- map->list[i].drop_list_count = 0;
- }
- if( map->list[i].drop_list != NULL )
- aFree(map->list[i].drop_list);
-
- if( map->list[i].channel )
- channel->delete(map->list[i].channel);
-
- if( map->list[i].qi_data )
- aFree(map->list[i].qi_data);
-
- HPM->data_store_destroy(&map->list[i].hdata);
+ map->list[i].prev_zone = map->list[i].zone;
}
+ // now it's safe to remove the zones:
map->zone_db_clear();
+ // then reload everything from scratch:
+ map->zone_db = strdb_alloc(DB_OPT_DUP_KEY | DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH);
+ map->read_zone_db();
}
+
+
/// Initializes map flags and adjusts them depending on configuration.
-void map_flags_init(void) {
+static void map_flags_init(void)
+{
int i, v = 0;
for( i = 0; i < map->count; i++ ) {
@@ -3560,11 +3760,8 @@ void map_flags_init(void) {
map->list[i].short_damage_rate = 100;
map->list[i].long_damage_rate = 100;
- if( map->list[i].qi_data )
- aFree(map->list[i].qi_data);
-
- map->list[i].qi_data = NULL;
- map->list[i].qi_count = 0;
+ VECTOR_CLEAR(map->list[i].qi_list);
+ VECTOR_INIT(map->list[i].qi_list);
}
}
@@ -3576,23 +3773,45 @@ void map_flags_init(void) {
* Assumed path for file is data/mapname.rsw
* Credits to LittleWolf
*/
-int map_waterheight(char* mapname)
+static int map_waterheight(char *mapname)
{
char fn[256];
- char *rsw, *found;
+ char *rsw = NULL;
+ const char *found;
nullpo_retr(NO_WATER, mapname);
//Look up for the rsw
snprintf(fn, sizeof(fn), "data\\%s.rsw", mapname);
- if ( (found = grfio_find_file(fn)) )
+ if ((found = grfio->find_file(fn)))
safestrncpy(fn, found, sizeof(fn)); // replace with real name
// read & convert fn
- rsw = (char *) grfio_read (fn);
+ rsw = grfio_read(fn);
if (rsw) {
+ if (memcmp(rsw, "GRSW", 4) != 0) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ int major_version = rsw[4];
+ int minor_version = rsw[5];
+ if (major_version > 2 || (major_version == 2 && minor_version > 2)) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ if (major_version < 1 || (major_version == 1 && minor_version <= 4)) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ int offset = 166;
+ if (major_version == 2 && minor_version >= 2) {
+ offset = 167;
+ }
//Load water height from file
- int wh = (int) *(float*)(rsw+166);
+ int wh = (int)*(float*)(rsw + offset);
aFree(rsw);
return wh;
}
@@ -3603,7 +3822,7 @@ int map_waterheight(char* mapname)
/*==================================
* .GAT format
*----------------------------------*/
-int map_readgat (struct map_data* m)
+static int map_readgat(struct map_data *m)
{
char filename[256];
uint8* gat;
@@ -3613,7 +3832,7 @@ int map_readgat (struct map_data* m)
nullpo_ret(m);
sprintf(filename, "data\\%s.gat", m->name);
- gat = (uint8 *) grfio_read(filename);
+ gat = grfio_read(filename);
if (gat == NULL)
return 0;
@@ -3647,12 +3866,14 @@ int map_readgat (struct map_data* m)
/*======================================
* Add/Remove map to the map_db
*--------------------------------------*/
-void map_addmap2db(struct map_data *m) {
+static void map_addmap2db(struct map_data *m)
+{
nullpo_retv(m);
map->index2mapid[m->index] = m->m;
}
-void map_removemapdb(struct map_data *m) {
+static void map_removemapdb(struct map_data *m)
+{
nullpo_retv(m);
map->index2mapid[m->index] = -1;
}
@@ -3660,28 +3881,15 @@ void map_removemapdb(struct map_data *m) {
/*======================================
* Initiate maps loading stage
*--------------------------------------*/
-int map_readallmaps (void) {
+static int map_readallmaps(void)
+{
int i;
- FILE* fp=NULL;
int maps_removed = 0;
- if( map->enable_grf )
+ if (map->enable_grf) {
ShowStatus("Loading maps (using GRF files)...\n");
- else {
- char mapcachefilepath[254];
- sprintf(mapcachefilepath,"%s/%s%s",map->db_path,DBPATH,"map_cache.dat");
- ShowStatus("Loading maps (using %s as map cache)...\n", mapcachefilepath);
- if( (fp = fopen(mapcachefilepath, "rb")) == NULL ) {
- ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", mapcachefilepath);
- exit(EXIT_FAILURE); //No use launching server if maps can't be read.
- }
-
- // Init mapcache data.. [Shinryo]
- map->cache_buffer = map->init_mapcache(fp);
- if(!map->cache_buffer) {
- ShowFatalError("Failed to initialize mapcache data (%s)..\n", mapcachefilepath);
- exit(EXIT_FAILURE);
- }
+ } else {
+ ShowStatus("Loading maps using map cache files...\n");
}
for(i = 0; i < map->count; i++) {
@@ -3695,7 +3903,7 @@ int map_readallmaps (void) {
if( !
(map->enable_grf?
map->readgat(&map->list[i])
- :map->readfromcache(&map->list[i], map->cache_buffer))
+ :map->readfromcache(&map->list[i]))
) {
map->delmapid(i);
maps_removed++;
@@ -3737,10 +3945,6 @@ int map_readallmaps (void) {
// intialization and configuration-dependent adjustments of mapflags
map->flags_init();
- if( !map->enable_grf ) {
- fclose(fp);
- }
-
// finished map loading
ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map->count);
instance->start_id = map->count; // Next Map Index will be instances
@@ -3751,181 +3955,388 @@ int map_readallmaps (void) {
return 0;
}
-/*==========================================
- * Read map server configuration files (conf/map_server.conf...)
- *------------------------------------------*/
-int map_config_read(char *cfgName) {
- char line[1024], w1[1024], w2[1024];
- FILE *fp;
+/**
+ * Reads 'map_configuration/console' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read_console(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
- nullpo_retr(1, cfgName);
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
- fp = fopen(cfgName,"r");
- if( fp == NULL ) {
- ShowError("Map configuration file not found at: %s\n", cfgName);
- return 1;
+ if ((setting = libconfig->lookup(config, "map_configuration/console")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("map_config_read: map_configuration/console was not found in %s!\n", filename);
+ return false;
}
- while (fgets(line, sizeof(line), fp)) {
- char* ptr;
+ libconfig->setting_lookup_bool_real(setting, "stdout_with_ansisequence", &showmsg->stdout_with_ansisequence);
+ if (libconfig->setting_lookup_int(setting, "console_silent", &showmsg->silent) == CONFIG_TRUE) {
+ if (showmsg->silent) // only bother if its actually enabled
+ ShowInfo("Console Silent Setting: %d\n", showmsg->silent);
+ }
+ libconfig->setting_lookup_mutable_string(setting, "timestamp_format", showmsg->timestamp_format, sizeof(showmsg->timestamp_format));
+ libconfig->setting_lookup_int(setting, "console_msg_log", &showmsg->console_log);
- if (line[0] == '/' && line[1] == '/')
- continue;
- if ((ptr = strstr(line, "//")) != NULL)
- *ptr = '\n'; //Strip comments
- if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
- continue;
+ return true;
+}
- //Strip trailing spaces
- ptr = w2 + strlen(w2);
- while (--ptr >= w2 && *ptr == ' ');
- ptr++;
- *ptr = '\0';
-
- if(strcmpi(w1,"timestamp_format")==0)
- safestrncpy(showmsg->timestamp_format, w2, 20);
- else if(strcmpi(w1,"stdout_with_ansisequence")==0)
- showmsg->stdout_with_ansisequence = config_switch(w2) ? true : false;
- else if(strcmpi(w1,"console_silent")==0) {
- showmsg->silent = atoi(w2);
- if (showmsg->silent) // only bother if its actually enabled
- ShowInfo("Console Silent Setting: %d\n", atoi(w2));
- } else if (strcmpi(w1, "userid")==0)
- chrif->setuserid(w2);
- else if (strcmpi(w1, "passwd") == 0)
- chrif->setpasswd(w2);
- else if (strcmpi(w1, "char_ip") == 0)
- map->char_ip_set = chrif->setip(w2);
- else if (strcmpi(w1, "char_port") == 0)
- chrif->setport(atoi(w2));
- else if (strcmpi(w1, "map_ip") == 0)
- map->ip_set = clif->setip(w2);
- else if (strcmpi(w1, "bind_ip") == 0)
- clif->setbindip(w2);
- else if (strcmpi(w1, "map_port") == 0) {
- clif->setport(atoi(w2));
- map->port = (atoi(w2));
- } else if (strcmpi(w1, "map") == 0)
- map->count++;
- else if (strcmpi(w1, "delmap") == 0)
- map->count--;
- else if (strcmpi(w1, "npc") == 0)
- npc->addsrcfile(w2);
- else if (strcmpi(w1, "delnpc") == 0)
- npc->delsrcfile(w2);
- else if (strcmpi(w1, "autosave_time") == 0) {
- map->autosave_interval = atoi(w2);
- if (map->autosave_interval < 1) //Revert to default saving.
- map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
- else
- map->autosave_interval *= 1000; //Pass from sec to ms
- } else if (strcmpi(w1, "minsave_time") == 0) {
- map->minsave_interval= atoi(w2);
- if (map->minsave_interval < 1)
- map->minsave_interval = 1;
- } else if (strcmpi(w1, "save_settings") == 0)
- map->save_settings = atoi(w2);
- else if (strcmpi(w1, "help_txt") == 0)
- strcpy(map->help_txt, w2);
- else if (strcmpi(w1, "help2_txt") == 0)
- strcpy(map->help2_txt, w2);
- else if (strcmpi(w1, "charhelp_txt") == 0)
- strcpy(map->charhelp_txt, w2);
- else if(strcmpi(w1,"db_path") == 0)
- safestrncpy(map->db_path,w2,255);
- else if (strcmpi(w1, "enable_spy") == 0)
- map->enable_spy = config_switch(w2);
- else if (strcmpi(w1, "use_grf") == 0)
- map->enable_grf = config_switch(w2);
- else if (strcmpi(w1, "console_msg_log") == 0)
- showmsg->console_log = atoi(w2);//[Ind]
- else if (strcmpi(w1, "default_language") == 0)
- safestrncpy(map->default_lang_str, w2, sizeof(map->default_lang_str));
- else if (strcmpi(w1, "import") == 0)
- map->config_read(w2);
+/**
+ * Reads 'map_configuration/sql_connection' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read_connection(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "map_configuration/sql_connection")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("map_config_read: map_configuration/sql_connection was not found in %s!\n", filename);
+ ShowWarning("map_config_read_connection: Defaulting sql_connection...\n");
+ return false;
+ }
+
+ libconfig->setting_lookup_int(setting, "db_port", &map->server_port);
+ libconfig->setting_lookup_mutable_string(setting, "db_hostname", map->server_ip, sizeof(map->server_ip));
+ libconfig->setting_lookup_mutable_string(setting, "db_username", map->server_id, sizeof(map->server_id));
+ libconfig->setting_lookup_mutable_string(setting, "db_password", map->server_pw, sizeof(map->server_pw));
+ libconfig->setting_lookup_mutable_string(setting, "db_database", map->server_db, sizeof(map->server_db));
+ libconfig->setting_lookup_mutable_string(setting, "default_codepage", map->default_codepage, sizeof(map->default_codepage));
+ return true;
+}
+
+/**
+ * Reads 'map_configuration/inter' and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read_inter(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+ const char *str = NULL;
+ char temp[24];
+ uint16 port;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "map_configuration/inter")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("map_config_read: map_configuration/inter was not found in %s!\n", filename);
+ return false;
+ }
+
+ // Login information
+ if (libconfig->setting_lookup_mutable_string(setting, "userid", temp, sizeof(temp)) == CONFIG_TRUE)
+ chrif->setuserid(temp);
+ if (libconfig->setting_lookup_mutable_string(setting, "passwd", temp, sizeof(temp)) == CONFIG_TRUE)
+ chrif->setpasswd(temp);
+
+ // Char and map-server information
+ if (libconfig->setting_lookup_string(setting, "char_ip", &str) == CONFIG_TRUE)
+ map->char_ip_set = chrif->setip(str);
+ if (libconfig->setting_lookup_uint16(setting, "char_port", &port) == CONFIG_TRUE)
+ chrif->setport(port);
+
+ if (libconfig->setting_lookup_string(setting, "map_ip", &str) == CONFIG_TRUE)
+ map->ip_set = clif->setip(str);
+ if (libconfig->setting_lookup_uint16(setting, "map_port", &port) == CONFIG_TRUE) {
+ clif->setport(port);
+ map->port = port;
+ }
+ if (libconfig->setting_lookup_string(setting, "bind_ip", &str) == CONFIG_TRUE)
+ clif->setbindip(str);
+
+ return true;
+}
+
+/**
+ * Reads 'map_configuration/database' and initializes required variables
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read_database(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "map_configuration/database")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("map_config_read: map_configuration/database was not found in %s!\n", filename);
+ return false;
+ }
+ libconfig->setting_lookup_mutable_string(setting, "db_path", map->db_path, sizeof(map->db_path));
+ libconfig->set_db_path(map->db_path);
+ libconfig->setting_lookup_int(setting, "save_settings", &map->save_settings);
+
+ if (libconfig->setting_lookup_int(setting, "autosave_time", &map->autosave_interval) == CONFIG_TRUE) {
+ if (map->autosave_interval < 1) // Revert to default saving
+ map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
else
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
+ map->autosave_interval *= 1000; // Pass from s to ms
+ }
+ if (libconfig->setting_lookup_int(setting, "minsave_time", &map->minsave_interval) == CONFIG_TRUE) {
+ if (map->minsave_interval < 1)
+ map->minsave_interval = 1;
}
- fclose(fp);
- return 0;
+ return true;
}
-int map_config_read_sub(char *cfgName) {
- char line[1024], w1[1024], w2[1024];
- FILE *fp;
- nullpo_retr(1, cfgName);
- fp = fopen(cfgName,"r");
- if (fp == NULL) {
- ShowError("Map configuration file not found at: %s\n", cfgName);
- return 1;
+/**
+ * Reads 'map_configuration/map_list'/'map_configuration/map_removed' and adds
+ * or removes maps from map-server.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read_map_list(const char *filename, struct config_t *config, bool imported)
+{
+ struct config_setting_t *setting = NULL;
+ int i, count = 0;
+ struct DBMap *deleted_maps;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ deleted_maps = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, MAP_NAME_LENGTH);
+
+ // Remove maps
+ if ((setting = libconfig->lookup(config, "map_configuration/map_removed")) != NULL) {
+ count = libconfig->setting_length(setting);
+ for (i = 0; i < count; i++) {
+ const char *mapname;
+
+ if ((mapname = libconfig->setting_get_string_elem(setting, i)) == NULL || mapname[0] == '\0')
+ continue;
+
+ strdb_put(deleted_maps, mapname, NULL);
+
+ if (imported) // Map list is empty on the first run, only do this for imported files.
+ map->delmap(mapname);
+ }
+ }
+
+ if ((setting = libconfig->lookup(config, "map_configuration/map_list")) == NULL) {
+ db_destroy(deleted_maps);
+ if (imported)
+ return true;
+ ShowError("map_config_read_map_list: map_configuration/map_list was not found in %s!\n", filename);
+ return false;
}
- while (fgets(line, sizeof(line), fp)) {
- char* ptr;
+ // Add maps to map->list
+ count = libconfig->setting_length(setting);
- if (line[0] == '/' && line[1] == '/')
+ if (count <= 0) {
+ db_destroy(deleted_maps);
+ if (imported)
+ return true;
+ ShowWarning("map_config_read_map_list: no maps found in %s!\n", filename);
+ return false;
+ }
+
+ RECREATE(map->list, struct map_data, map->count + count); // TODO: VECTOR candidate
+
+ for (i = 0; i < count; i++) {
+ const char *mapname;
+
+ if ((mapname = libconfig->setting_get_string_elem(setting, i)) == NULL || mapname[0] == '\0')
continue;
- if ((ptr = strstr(line, "//")) != NULL)
- *ptr = '\n'; //Strip comments
- if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
+
+ if (strdb_exists(deleted_maps, mapname))
continue;
- //Strip trailing spaces
- ptr = w2 + strlen(w2);
- while (--ptr >= w2 && *ptr == ' ');
- ptr++;
- *ptr = '\0';
+ map->addmap(mapname);
+ }
+
+ RECREATE(map->list, struct map_data, map->count);
+
+ db_destroy(deleted_maps);
+ return true;
+}
+
+/**
+ * Reads map-server configuration files (map-server.conf) and initialises
+ * required variables.
+ *
+ * @param filename Path to configuration file.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_config_read(const char *filename, bool imported)
+{
+ struct config_t config;
+ struct config_setting_t *setting = NULL;
+ const char *import = NULL;
+ bool retval = true;
+
+ nullpo_retr(false, filename);
- if (strcmpi(w1, "map") == 0)
- map->addmap(w2);
- else if (strcmpi(w1, "delmap") == 0)
- map->delmap(w2);
- else if (strcmpi(w1, "import") == 0)
- map->config_read_sub(w2);
+ if (!libconfig->load_file(&config, filename))
+ return false;
+
+ if ((setting = libconfig->lookup(&config, "map_configuration")) == NULL) {
+ libconfig->destroy(&config);
+ if (imported)
+ return true;
+ ShowError("map_config_read: map_configuration was not found in %s!\n", filename);
+ return false;
}
- fclose(fp);
- return 0;
+ libconfig->setting_lookup_mutable_string(setting, "help_txt", map->help_txt, sizeof(map->help_txt));
+ libconfig->setting_lookup_mutable_string(setting, "charhelp_txt", map->charhelp_txt, sizeof(map->charhelp_txt));
+ libconfig->setting_lookup_bool(setting, "enable_spy", &map->enable_spy);
+ libconfig->setting_lookup_bool(setting, "use_grf", &map->enable_grf);
+ libconfig->setting_lookup_mutable_string(setting, "default_language", map->default_lang_str, sizeof(map->default_lang_str));
+
+ if (!map_config_read_console(filename, &config, imported))
+ retval = false;
+ if (!map_config_read_connection(filename, &config, imported))
+ retval = false;
+ if (!map_config_read_inter(filename, &config, imported))
+ retval = false;
+ if (!map_config_read_database(filename, &config, imported))
+ retval = false;
+ if (!map_config_read_map_list(filename, &config, imported))
+ retval = false;
+
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ if (strcmp(import, filename) == 0 || strcmp(import, map->MAP_CONF_NAME) == 0) {
+ ShowWarning("map_config_read: Loop detected! Skipping 'import'...\n");
+ } else {
+ if (!map->config_read(import, true))
+ retval = false;
+ }
+ }
+
+ libconfig->destroy(&config);
+ return retval;
}
-void map_reloadnpc_sub(char *cfgName) {
- char line[1024], w1[1024], w2[1024];
- FILE *fp;
- nullpo_retv(cfgName);
- fp = fopen(cfgName,"r");
- if (fp == NULL) {
- ShowError("Map configuration file not found at: %s\n", cfgName);
- return;
+/**
+ * Reads 'npc_global_list'/'npc_removed_list' and adds or removes NPC sources
+ * from map-server.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool map_read_npclist(const char *filename, bool imported)
+{
+ struct config_t config;
+ struct config_setting_t *setting = NULL;
+ const char *import = NULL;
+ bool retval = true;
+ bool remove_all = false;
+
+ struct DBMap *deleted_npcs;
+
+ nullpo_retr(false, filename);
+
+ if (!libconfig->load_file(&config, filename))
+ return false;
+
+ deleted_npcs = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0);
+
+ // Remove NPCs
+ if ((setting = libconfig->lookup(&config, "npc_removed_list")) != NULL) {
+ int i, del_count = libconfig->setting_length(setting);
+ for (i = 0; i < del_count; i++) {
+ const char *scriptname;
+
+ if ((scriptname = libconfig->setting_get_string_elem(setting, i)) == NULL || scriptname[0] == '\0')
+ continue;
+
+ if (strcmp(scriptname, "all") == 0) {
+ remove_all = true;
+ npc->clearsrcfile();
+ } else {
+ strdb_put(deleted_npcs, scriptname, NULL);
+ npc->delsrcfile(scriptname);
+ }
+ }
}
- while (fgets(line, sizeof(line), fp)) {
- char* ptr;
+ if ((setting = libconfig->lookup(&config, "npc_global_list")) != NULL) {
+ int i, count = libconfig->setting_length(setting);
+ if (count <= 0) {
+ if (!imported) {
+ ShowWarning("map_read_npclist: no NPCs found in %s!\n", filename);
+ retval = false;
+ }
+ }
+ for (i = 0; i < count; i++) {
+ const char *scriptname;
- if (line[0] == '/' && line[1] == '/')
- continue;
- if ((ptr = strstr(line, "//")) != NULL)
- *ptr = '\n'; //Strip comments
- if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
- continue;
+ if ((scriptname = libconfig->setting_get_string_elem(setting, i)) == NULL || scriptname[0] == '\0')
+ continue;
- //Strip trailing spaces
- ptr = w2 + strlen(w2);
- while (--ptr >= w2 && *ptr == ' ');
- ptr++;
- *ptr = '\0';
-
- if (strcmpi(w1, "npc") == 0)
- npc->addsrcfile(w2);
- else if (strcmpi(w1, "import") == 0)
- map->reloadnpc_sub(w2);
- else if (strcmpi(w1, "delnpc") == 0)
- npc->delsrcfile(w2);
- else
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
+ if (remove_all || strdb_exists(deleted_npcs, scriptname))
+ continue;
+
+ npc->addsrcfile(scriptname);
+ }
+ } else {
+ ShowError("map_read_npclist: npc_global_list was not found in %s!\n", filename);
+ retval = false;
}
- fclose(fp);
+ db_destroy(deleted_npcs);
+
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ const char *base_npclist = NULL;
+#ifdef RENEWAL
+ base_npclist = "npc/re/scripts_main.conf";
+#else
+ base_npclist = "npc/pre-re/scripts_main.conf";
+#endif
+ if (strcmp(import, filename) == 0 || strcmp(import, base_npclist) == 0) {
+ ShowWarning("map_read_npclist: Loop detected! Skipping 'import'...\n");
+ } else {
+ if (!map->read_npclist(import, true))
+ retval = false;
+ }
+ }
+
+ libconfig->destroy(&config);
+ return retval;
}
/**
@@ -3933,15 +4344,16 @@ void map_reloadnpc_sub(char *cfgName) {
*
* @param clear whether to clear the script list before reloading.
*/
-void map_reloadnpc(bool clear) {
+static void map_reloadnpc(bool clear)
+{
int i;
if (clear)
- npc->addsrcfile("clear"); // this will clear the current script list
+ npc->clearsrcfile();
#ifdef RENEWAL
- map->reloadnpc_sub("npc/re/scripts_main.conf");
+ map->read_npclist("npc/re/scripts_main.conf", false);
#else
- map->reloadnpc_sub("npc/pre-re/scripts_main.conf");
+ map->read_npclist("npc/pre-re/scripts_main.conf", false);
#endif
// Append extra scripts
@@ -3950,69 +4362,134 @@ void map_reloadnpc(bool clear) {
}
}
-int inter_config_read(char *cfgName) {
- char line[1024],w1[1024],w2[1024];
- FILE *fp;
+/**
+ * Reads inter-server.conf and initializes required variables.
+ *
+ * @param filename Path to configuration file
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool inter_config_read(const char *filename, bool imported)
+{
+ struct config_t config;
+ const struct config_setting_t *setting = NULL;
+ const char *import = NULL;
+ bool retval = true;
- nullpo_retr(1, cfgName);
- if (!(fp = fopen(cfgName,"r"))) {
- ShowError("File not found: %s\n",cfgName);
- return 1;
+ nullpo_retr(false, filename);
+
+ if (!libconfig->load_file(&config, filename))
+ return false;
+
+ if ((setting = libconfig->lookup(&config, "inter_configuration")) == NULL) {
+ libconfig->destroy(&config);
+ if (imported)
+ return true;
+ ShowError("inter_config_read: inter_configuration was not found in %s!\n", filename);
+ return false;
}
- while (fgets(line, sizeof(line), fp)) {
- if (line[0] == '/' && line[1] == '/')
- continue;
- if (sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2) < 2)
- continue;
- /* map sql stuff */
- if(strcmpi(w1,"map_server_ip")==0)
- safestrncpy(map->server_ip, w2, sizeof(map->server_ip));
- else if(strcmpi(w1,"map_server_port")==0)
- map->server_port=atoi(w2);
- else if(strcmpi(w1,"map_server_id")==0)
- safestrncpy(map->server_id, w2, sizeof(map->server_id));
- else if(strcmpi(w1,"map_server_pw")==0)
- safestrncpy(map->server_pw, w2, sizeof(map->server_pw));
- else if(strcmpi(w1,"map_server_db")==0)
- safestrncpy(map->server_db, w2, sizeof(map->server_db));
- else if(strcmpi(w1,"default_codepage")==0)
- safestrncpy(map->default_codepage, w2, sizeof(map->default_codepage));
- else if(strcmpi(w1,"autotrade_merchants_db")==0)
- safestrncpy(map->autotrade_merchants_db, w2, sizeof(map->autotrade_merchants_db));
- else if(strcmpi(w1,"autotrade_data_db")==0)
- safestrncpy(map->autotrade_data_db, w2, sizeof(map->autotrade_data_db));
- else if(strcmpi(w1,"npc_market_data_db")==0)
- safestrncpy(map->npc_market_data_db, w2, sizeof(map->npc_market_data_db));
- /* sql log db */
- else if(strcmpi(w1,"log_db_ip")==0)
- safestrncpy(logs->db_ip, w2, sizeof(logs->db_ip));
- else if(strcmpi(w1,"log_db_id")==0)
- safestrncpy(logs->db_id, w2, sizeof(logs->db_id));
- else if(strcmpi(w1,"log_db_pw")==0)
- safestrncpy(logs->db_pw, w2, sizeof(logs->db_pw));
- else if(strcmpi(w1,"log_db_port")==0)
- logs->db_port = atoi(w2);
- else if(strcmpi(w1,"log_db_db")==0)
- safestrncpy(logs->db_name, w2, sizeof(logs->db_name));
- /* mapreg */
- else if( mapreg->config_read(w1,w2) )
- continue;
- /* import */
- else if(strcmpi(w1,"import")==0)
- map->inter_config_read(w2);
- else
- HPM->parseConf(w1, w2, HPCT_MAP_INTER);
+ if (!map->inter_config_read_database_names(filename, &config, imported))
+ retval = false;
+ if (!map->inter_config_read_connection(filename, &config, imported))
+ retval = false;
+
+ if (!HPM->parse_conf(&config, filename, HPCT_MAP_INTER, imported))
+ retval = false;
+
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ if (strcmp(import, filename) == 0 || strcmp(import, map->INTER_CONF_NAME) == 0) {
+ ShowWarning("inter_config_read: Loop detected in %s! Skipping 'import'...\n", filename);
+ } else {
+ if (!map->inter_config_read(import, true))
+ retval = false;
+ }
}
- fclose(fp);
- return 0;
+ libconfig->destroy(&config);
+ return retval;
+}
+
+/**
+ * Reads the 'inter_configuration/log/sql_connection' config entry and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool inter_config_read_connection(const char *filename, const struct config_t *config, bool imported)
+{
+ const struct config_setting_t *setting = NULL;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "inter_configuration/log/sql_connection")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("inter_config_read: inter_configuration/log/sql_connection was not found in %s!\n", filename);
+ return false;
+ }
+
+ libconfig->setting_lookup_int(setting, "db_port", &logs->db_port);
+ libconfig->setting_lookup_mutable_string(setting, "db_hostname", logs->db_ip, sizeof(logs->db_ip));
+ libconfig->setting_lookup_mutable_string(setting, "db_username", logs->db_id, sizeof(logs->db_id));
+ libconfig->setting_lookup_mutable_string(setting, "db_password", logs->db_pw, sizeof(logs->db_pw));
+ libconfig->setting_lookup_mutable_string(setting, "db_database", logs->db_name, sizeof(logs->db_name));
+
+ return true;
+}
+
+/**
+ * Reads the 'inter_configuration/database_names' config entry and initializes required variables.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool inter_config_read_database_names(const char *filename, const struct config_t *config, bool imported)
+{
+ const struct config_setting_t *setting = NULL;
+ bool retval = true;
+
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if ((setting = libconfig->lookup(config, "inter_configuration/database_names")) == NULL) {
+ if (imported)
+ return true;
+ ShowError("inter_config_read: inter_configuration/database_names was not found in %s!\n", filename);
+ return false;
+ }
+
+ libconfig->setting_lookup_mutable_string(setting, "autotrade_merchants_db", map->autotrade_merchants_db, sizeof(map->autotrade_merchants_db));
+ libconfig->setting_lookup_mutable_string(setting, "autotrade_data_db", map->autotrade_data_db, sizeof(map->autotrade_data_db));
+ libconfig->setting_lookup_mutable_string(setting, "npc_market_data_db", map->npc_market_data_db, sizeof(map->npc_market_data_db));
+ libconfig->setting_lookup_mutable_string(setting, "npc_barter_data_db", map->npc_barter_data_db, sizeof(map->npc_barter_data_db));
+ libconfig->setting_lookup_mutable_string(setting, "npc_expanded_barter_data_db", map->npc_expanded_barter_data_db, sizeof(map->npc_expanded_barter_data_db));
+
+ if (!mapreg->config_read(filename, setting, imported))
+ retval = false;
+
+ if ((setting = libconfig->lookup(config, "inter_configuration/database_names/registry")) == NULL) {
+ if (imported)
+ return retval;
+ ShowError("inter_config_read: inter_configuration/database_names/registry was not found in %s!\n", filename);
+ return false;
+ }
+ return retval;
}
/*=======================================
* MySQL Init
*---------------------------------------*/
-int map_sql_init(void)
+static int map_sql_init(void)
{
// main db connection
map->mysql_handle = SQL->Malloc();
@@ -4029,7 +4506,7 @@ int map_sql_init(void)
return 0;
}
-int map_sql_close(void)
+static int map_sql_close(void)
{
ShowStatus("Close Map DB Connection....\n");
SQL->Free(map->mysql_handle);
@@ -4047,7 +4524,8 @@ int map_sql_close(void)
*
* @return the newly created zone from merging main and other
**/
-struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone_data *other) {
+static struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone_data *other)
+{
char newzone[MAP_ZONE_NAME_LENGTH];
struct map_zone_data *zone = NULL;
int cursor, i, j;
@@ -4055,7 +4533,7 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone
nullpo_retr(NULL, main);
nullpo_retr(NULL, other);
- sprintf(newzone, "%s+%s",main->name,other->name);
+ safesnprintf(newzone, MAP_ZONE_NAME_LENGTH, "%s+%s", main->name, other->name);
if( (zone = strdb_get(map->zone_db, newzone)) )
return zone;/* this zone has already been merged */
@@ -4144,10 +4622,12 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone
return zone;
}
-void map_zone_change2(int m, struct map_zone_data *zone)
+static void map_zone_change2(int m, struct map_zone_data *zone)
{
const char *empty = "";
+ if (zone == NULL)
+ return;
Assert_retv(m >= 0 && m < map->count);
if( map->list[m].zone == zone )
return;
@@ -4165,7 +4645,8 @@ void map_zone_change2(int m, struct map_zone_data *zone)
map->zone_apply(m,zone,empty,empty,empty);
}
/* when changing from a mapflag to another during runtime */
-void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) {
+static void map_zone_change(int m, struct map_zone_data *zone, const char *start, const char *buffer, const char *filepath)
+{
Assert_retv(m >= 0 && m < map->count);
map->list[m].prev_zone = map->list[m].zone;
@@ -4174,7 +4655,7 @@ void map_zone_change(int m, struct map_zone_data *zone, const char* start, const
map->zone_apply(m,zone,start,buffer,filepath);
}
/* removes previous mapflags from this map */
-void map_zone_remove(int m)
+static void map_zone_remove(int m)
{
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
unsigned short k;
@@ -4201,7 +4682,29 @@ void map_zone_remove(int m)
map->list[m].zone_mf = NULL;
map->list[m].zone_mf_count = 0;
}
-static inline void map_zone_mf_cache_add(int m, char *rflag) {
+// this one removes every flag, even if they were previously turned on before
+// the current zone was applied
+static void map_zone_remove_all(int m)
+{
+ Assert_retv(m >= 0 && m < map->count);
+
+ for (unsigned short k = 0; k < map->list[m].zone_mf_count; k++) {
+ char flag[MAP_ZONE_MAPFLAG_LENGTH];
+
+ memcpy(flag, map->list[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH);
+ strtok(flag, "\t");
+
+ npc->parse_mapflag(map->list[m].name, "", flag, "off", "", "", "", NULL);
+ aFree(map->list[m].zone_mf[k]);
+ map->list[m].zone_mf[k] = NULL;
+ }
+
+ aFree(map->list[m].zone_mf);
+ map->list[m].zone_mf = NULL;
+ map->list[m].zone_mf_count = 0;
+}
+static inline void map_zone_mf_cache_add(int m, char *rflag)
+{
Assert_retv(m >= 0 && m < map->count);
RECREATE(map->list[m].zone_mf, char *, ++map->list[m].zone_mf_count);
CREATE(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH);
@@ -4209,7 +4712,8 @@ static inline void map_zone_mf_cache_add(int m, char *rflag) {
}
/* TODO: introduce enumerations to each mapflag so instead of reading the string a number of times we read it only once and use its value wherever we need */
/* cache previous values to revert */
-bool map_zone_mf_cache(int m, char *flag, char *params) {
+static bool map_zone_mf_cache(int m, char *flag, char *params)
+{
char rflag[MAP_ZONE_MAPFLAG_LENGTH];
int state = 1;
@@ -4465,6 +4969,15 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
else if( map->list[m].flag.battleground )
map_zone_mf_cache_add(m,"battleground");
}
+ } else if (!strcmpi(flag,"cvc")) {
+ if (state && map->list[m].flag.cvc) {
+ ;/* nothing to do */
+ } else {
+ if (state)
+ map_zone_mf_cache_add(m,"cvc\toff");
+ else if (map->list[m].flag.cvc)
+ map_zone_mf_cache_add(m,"cvc");
+ }
} else if (!strcmpi(flag,"noexppenalty")) {
if( state && map->list[m].flag.noexppenalty )
;/* nothing to do */
@@ -4737,11 +5250,12 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
}
} else if (!strcmpi(flag,"adjust_unit_duration")) {
int skill_id, k;
- char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- size_t len = strlen(params);
+ char skill_name[MAX_SKILL_NAME_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
+ size_t len;
modifier[0] = '\0';
- memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH);
+ safestrncpy(skill_name, params, MAX_SKILL_NAME_LENGTH);
+ len = strlen(skill_name);
for(k = 0; k < len; k++) {
if( skill_name[k] == '\t' ) {
@@ -4770,11 +5284,12 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
}
} else if (!strcmpi(flag,"adjust_skill_damage")) {
int skill_id, k;
- char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- size_t len = strlen(params);
+ char skill_name[MAX_SKILL_NAME_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
+ size_t len;
modifier[0] = '\0';
- memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH);
+ safestrncpy(skill_name, params, MAX_SKILL_NAME_LENGTH);
+ len = strlen(skill_name);
for(k = 0; k < len; k++) {
if( skill_name[k] == '\t' ) {
@@ -4904,11 +5419,37 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
else if( map->list[m].flag.nocashshop )
map_zone_mf_cache_add(m,"nocashshop");
}
+ } else if (strcmpi(flag, "nostorage") == 0) {
+ if (!state) {
+ if (map->list[m].flag.nostorage != 0) {
+ sprintf(rflag, "nostorage\t%d", map->list[m].flag.nostorage);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ if (sscanf(params, "%d", &state) == 1) {
+ if (state != map->list[m].flag.nostorage) {
+ sprintf(rflag, "nostorage\t%d", state);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ } else if (strcmpi(flag, "nogstorage") == 0) {
+ if (!state) {
+ if (map->list[m].flag.nogstorage != 0) {
+ sprintf(rflag, "nogstorage\t%d", map->list[m].flag.nogstorage);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ if (sscanf(params, "%d", &state) == 1) {
+ if (state != map->list[m].flag.nogstorage) {
+ sprintf(rflag, "nogstorage\t%d", state);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
}
return false;
}
-void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath)
+static void map_zone_apply(int m, struct map_zone_data *zone, const char *start, const char *buffer, const char *filepath)
{
int i;
const char *empty = "";
@@ -4936,7 +5477,7 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const
}
}
/* used on npc load and reload to apply all "Normal" and "PK Mode" zones */
-void map_zone_init(void)
+static void map_zone_init(void)
{
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
struct map_zone_data *zone;
@@ -4990,12 +5531,13 @@ void map_zone_init(void)
}
}
-unsigned short map_zone_str2itemid(const char *name) {
+static int map_zone_str2itemid(const char *name)
+{
struct item_data *data;
if( !name )
return 0;
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) < 8 ) {
+ if (name[0] == 'I' && name[1] == 'D' && strlen(name) <= 12) {
if( !( data = itemdb->exists(atoi(name+2))) ) {
return 0;
}
@@ -5006,13 +5548,14 @@ unsigned short map_zone_str2itemid(const char *name) {
}
return data->nameid;
}
-unsigned short map_zone_str2skillid(const char *name) {
+static unsigned short map_zone_str2skillid(const char *name)
+{
unsigned short nameid = 0;
if( !name )
return 0;
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) < 8 ) {
+ if (name[0] == 'I' && name[1] == 'D' && strlen(name) <= 12) {
if( !skill->get_index((nameid = atoi(name+2))) )
return 0;
} else {
@@ -5022,7 +5565,8 @@ unsigned short map_zone_str2skillid(const char *name) {
}
return nameid;
}
-enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *subtype) {
+static enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *subtype)
+{
char temp[200], *parse;
enum bl_type bl = BL_NUL;
@@ -5068,15 +5612,12 @@ enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *su
return bl;
}
/* [Ind/Hercules] */
-void read_map_zone_db(void) {
+static void read_map_zone_db(void)
+{
struct config_t map_zone_db;
struct config_setting_t *zones = NULL;
- /* TODO: #ifndef required for re/pre-re */
-#ifdef RENEWAL
- const char *config_filename = "db/re/map_zone_db.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/map_zone_db.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"map_zone_db.conf", config_filename, sizeof(config_filename));
if (!libconfig->load_file(&map_zone_db, config_filename))
return;
@@ -5489,45 +6030,46 @@ void read_map_zone_db(void) {
zone->merge_type = MZMT_MERGEABLE;
if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) )
zone->merge_type = MZMT_MERGEABLE;
+ if ((zone = strdb_get(map->zone_db, MAP_ZONE_CVC_NAME)))
+ zone->merge_type = MZMT_MERGEABLE;
}
/* not supposed to go in here but in skill_final whatever */
libconfig->destroy(&map_zone_db);
}
-int map_get_new_bonus_id (void) {
+static int map_get_new_bonus_id(void)
+{
return map->bonus_id++;
}
-void map_add_questinfo(int m, struct questinfo *qi) {
- unsigned short i;
+static bool map_add_questinfo(int m, struct npc_data *nd)
+{
+ nullpo_retr(false, nd);
+ Assert_retr(false, m >= 0 && m < map->count);
- nullpo_retv(qi);
- Assert_retv(m >= 0 && m < map->count);
- /* duplicate, override */
- for(i = 0; i < map->list[m].qi_count; i++) {
- if( map->list[m].qi_data[i].nd == qi->nd )
- break;
- }
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, VECTOR_INDEX(map->list[m].qi_list, i) == nd);
- if( i == map->list[m].qi_count )
- RECREATE(map->list[m].qi_data, struct questinfo, ++map->list[m].qi_count);
+ if (i < VECTOR_LENGTH(map->list[m].qi_list)) {
+ return false;
+ }
- memcpy(&map->list[m].qi_data[i], qi, sizeof(struct questinfo));
+ VECTOR_ENSURE(map->list[m].qi_list, 1, 1);
+ VECTOR_PUSH(map->list[m].qi_list, nd);
+ return true;
}
-bool map_remove_questinfo(int m, struct npc_data *nd) {
- unsigned short i;
+static bool map_remove_questinfo(int m, struct npc_data *nd)
+{
+ nullpo_retr(false, nd);
Assert_retr(false, m >= 0 && m < map->count);
- for(i = 0; i < map->list[m].qi_count; i++) {
- struct questinfo *qi = &map->list[m].qi_data[i];
- if( qi->nd == nd ) {
- memset(&map->list[m].qi_data[i], 0, sizeof(struct questinfo));
- if( i != --map->list[m].qi_count ) {
- memmove(&map->list[m].qi_data[i],&map->list[m].qi_data[i+1],sizeof(struct questinfo)*(map->list[m].qi_count-i));
- }
- return true;
- }
+
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, VECTOR_INDEX(map->list[m].qi_list, i) == nd);
+ if (i != VECTOR_LENGTH(map->list[m].qi_list)) {
+ VECTOR_ERASE(map->list[m].qi_list, i);
+ return true;
}
return false;
}
@@ -5535,7 +6077,7 @@ bool map_remove_questinfo(int m, struct npc_data *nd) {
/**
* @see DBApply
*/
-int map_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int map_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct map_data_other_server *mdos = DB->data2ptr(data);
@@ -5548,7 +6090,7 @@ int map_db_final(union DBKey key, struct DBData *data, va_list ap)
/**
* @see DBApply
*/
-int nick_db_final(union DBKey key, struct DBData *data, va_list args)
+static int nick_db_final(union DBKey key, struct DBData *data, va_list args)
{
struct charid2nick* p = DB->data2ptr(data);
struct charid_request* req;
@@ -5565,7 +6107,8 @@ int nick_db_final(union DBKey key, struct DBData *data, va_list args)
return 0;
}
-int cleanup_sub(struct block_list *bl, va_list ap) {
+static int cleanup_sub(struct block_list *bl, va_list ap)
+{
nullpo_ret(bl);
switch(bl->type) {
@@ -5573,7 +6116,7 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
map->quit(BL_UCAST(BL_PC, bl));
break;
case BL_NPC:
- npc->unload(BL_UCAST(BL_NPC, bl), false);
+ npc->unload(BL_UCAST(BL_NPC, bl), false, true);
break;
case BL_MOB:
unit->free(bl,CLR_OUTSIGHT);
@@ -5595,7 +6138,7 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
/**
* @see DBApply
*/
-int cleanup_db_sub(union DBKey key, struct DBData *data, va_list va)
+static int cleanup_db_sub(union DBKey key, struct DBData *data, va_list va)
{
return map->cleanup_sub(DB->data2ptr(data), va);
}
@@ -5603,7 +6146,8 @@ int cleanup_db_sub(union DBKey key, struct DBData *data, va_list va)
/*==========================================
* map destructor
*------------------------------------------*/
-int do_final(void) {
+int do_final(void)
+{
int i;
struct map_session_data* sd;
struct s_mapiterator* iter;
@@ -5649,6 +6193,7 @@ int do_final(void) {
ircbot->final();/* before channel. */
channel->final();
chrif->final();
+ clan->final();
clif->final();
npc->final();
quest->final();
@@ -5665,20 +6210,24 @@ int do_final(void) {
atcommand->final_msg();
skill->final();
status->final();
+ refine->final();
unit->final();
bg->final();
duel->final();
elemental->final();
map->list_final();
vending->final();
+ rodex->final();
+ achievement->final();
+ stylist->final();
HPM_map_do_final();
map->map_db->destroy(map->map_db, map->db_final);
mapindex->final();
- if(map->enable_grf)
- grfio_final();
+ if (map->enable_grf)
+ grfio->final();
db_destroy(map->id_db);
db_destroy(map->pc_db);
@@ -5693,6 +6242,11 @@ int do_final(void) {
ers_destroy(map->iterator_ers);
ers_destroy(map->flooritem_ers);
+ for (i = 0; i < map->count; ++i) {
+ if (map->list[i].cell_buf.data != NULL)
+ aFree(map->list[i].cell_buf.data);
+ map->list[i].cell_buf.len = 0;
+ }
aFree(map->list);
if( map->block_free )
@@ -5700,9 +6254,6 @@ int do_final(void) {
if( map->bl_list )
aFree(map->bl_list);
- if( !map->enable_grf )
- aFree(map->cache_buffer);
-
aFree(map->MAP_CONF_NAME);
aFree(map->BATTLE_CONF_FILENAME);
aFree(map->ATCOMMAND_CONF_FILENAME);
@@ -5718,7 +6269,8 @@ int do_final(void) {
return map->retval;
}
-int map_abort_sub(struct map_session_data* sd, va_list ap) {
+static int map_abort_sub(struct map_session_data *sd, va_list ap)
+{
chrif->save(sd,1);
return 1;
}
@@ -5747,12 +6299,13 @@ void do_abort(void)
chrif->flush();
}
-void set_server_type(void) {
+void set_server_type(void)
+{
SERVER_TYPE = SERVER_TYPE_MAP;
}
/// Called when a terminate signal is received.
-void do_shutdown(void)
+static void do_shutdown(void)
{
if( core->runflag != MAPSERVER_ST_SHUTDOWN )
{
@@ -5770,7 +6323,8 @@ void do_shutdown(void)
}
}
-CPCMD(gm_position) {
+static CPCMD(gm_position)
+{
int x = 0, y = 0, m = 0;
char map_name[25];
@@ -5793,8 +6347,10 @@ CPCMD(gm_position) {
map->cpsd->bl.x = x;
map->cpsd->bl.y = y;
map->cpsd->bl.m = m;
+ map->cpsd->mapindex = map_id2index(m);
}
-CPCMD(gm_use) {
+static CPCMD(gm_use)
+{
if( line == NULL ) {
ShowError("gm:use invalid syntax. use '"CL_WHITE"gm:use @command <optional params>"CL_RESET"'\n");
@@ -5811,7 +6367,8 @@ CPCMD(gm_use) {
map->cpsd_active = false;
}
/* Hercules Console Parser */
-void map_cp_defaults(void) {
+static void map_cp_defaults(void)
+{
#ifdef CONSOLE_INPUT
/* default HCP data */
map->cpsd = pc->get_dummy_sd();
@@ -5819,13 +6376,16 @@ void map_cp_defaults(void) {
map->cpsd->bl.x = mapindex->default_x;
map->cpsd->bl.y = mapindex->default_y;
map->cpsd->bl.m = map->mapname2mapid(mapindex->default_map);
+ Assert_retv(map->cpsd->bl.m >= 0);
+ map->cpsd->mapindex = map_id2index(map->cpsd->bl.m);
console->input->addCommand("gm:info",CPCMD_A(gm_position));
console->input->addCommand("gm:use",CPCMD_A(gm_use));
#endif
}
-void map_load_defaults(void) {
+static void map_load_defaults(void)
+{
mapindex_defaults();
map_defaults();
/* */
@@ -5834,6 +6394,7 @@ void map_load_defaults(void) {
battleground_defaults();
buyingstore_defaults();
channel_defaults();
+ clan_defaults();
clif_defaults();
chrif_defaults();
guild_defaults();
@@ -5866,7 +6427,11 @@ void map_load_defaults(void) {
pet_defaults();
path_defaults();
quest_defaults();
+ achievement_defaults();
npc_chat_defaults();
+ rodex_defaults();
+ stylist_defaults();
+ refine_defaults();
}
/**
* --run-once handler
@@ -6002,22 +6567,6 @@ static CMDLINEARG(loadscript)
}
/**
- * --generate-translations
- *
- * Creates "./generated_translations.pot"
- * @see cmdline->exec
- **/
-static CMDLINEARG(generatetranslations) {
- script->lang_export_file = aStrdup("./generated_translations.pot");
-
- if( !(script->lang_export_fp = fopen(script->lang_export_file,"wb")) ) {
- ShowError("export-dialog: failed to open '%s' for writing\n",script->lang_export_file);
- }
- core->runflag = CORE_ST_STOP;
- return true;
-}
-
-/**
* Defines the local command line arguments
*/
void cmdline_args_init_local(void)
@@ -6033,7 +6582,6 @@ void cmdline_args_init_local(void)
CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT);
CMDLINEARG_DEF2(load-script, loadscript, "Loads an additional script (can be repeated).", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
- CMDLINEARG_DEF2(generate-translations, generatetranslations, "Creates './generated_translations.pot' file with all translateable strings from scripts, server terminates afterwards.", CMDLINE_OPT_NORMAL);
}
int do_init(int argc, char *argv[])
@@ -6047,12 +6595,12 @@ int do_init(int argc, char *argv[])
map_load_defaults();
- map->INTER_CONF_NAME = aStrdup("conf/inter-server.conf");
- map->LOG_CONF_NAME = aStrdup("conf/logs.conf");
- map->MAP_CONF_NAME = aStrdup("conf/map-server.conf");
- map->BATTLE_CONF_FILENAME = aStrdup("conf/battle.conf");
+ map->INTER_CONF_NAME = aStrdup("conf/common/inter-server.conf");
+ map->LOG_CONF_NAME = aStrdup("conf/map/logs.conf");
+ map->MAP_CONF_NAME = aStrdup("conf/map/map-server.conf");
+ map->BATTLE_CONF_FILENAME = aStrdup("conf/map/battle.conf");
map->ATCOMMAND_CONF_FILENAME = aStrdup("conf/atcommand.conf");
- map->SCRIPT_CONF_NAME = aStrdup("conf/script.conf");
+ map->SCRIPT_CONF_NAME = aStrdup("conf/map/script.conf");
map->MSG_CONF_NAME = aStrdup("conf/messages.conf");
map->GRF_PATH_FILENAME = aStrdup("conf/grf-files.txt");
@@ -6065,10 +6613,30 @@ int do_init(int argc, char *argv[])
cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */
if (!minimal) {
- map->config_read(map->MAP_CONF_NAME);
- CREATE(map->list,struct map_data,map->count);
- map->count = 0;
- map->config_read_sub(map->MAP_CONF_NAME);
+ map->config_read(map->MAP_CONF_NAME, false);
+
+ {
+ // TODO: Remove this when no longer needed.
+#define CHECK_OLD_LOCAL_CONF(oldname, newname) do { \
+ if (stat((oldname), &fileinfo) == 0 && fileinfo.st_size > 0) { \
+ ShowWarning("An old configuration file \"%s\" was found.\n", (oldname)); \
+ ShowWarning("If it contains settings you wish to keep, please merge them into \"%s\".\n", (newname)); \
+ ShowWarning("Otherwise, just delete it.\n"); \
+ ShowInfo("Resuming in 10 seconds...\n"); \
+ HSleep(10); \
+ } \
+} while (0)
+ struct stat fileinfo;
+
+ CHECK_OLD_LOCAL_CONF("conf/import/map_conf.txt", "conf/import/map-server.conf");
+ CHECK_OLD_LOCAL_CONF("conf/import/inter_conf.txt", "conf/import/inter-server.conf");
+ CHECK_OLD_LOCAL_CONF("conf/import/log_conf.txt", "conf/import/logs.conf");
+ CHECK_OLD_LOCAL_CONF("conf/import/script_conf.txt", "conf/import/script.conf");
+ CHECK_OLD_LOCAL_CONF("conf/import/packet_conf.txt", "conf/import/socket.conf");
+ CHECK_OLD_LOCAL_CONF("conf/import/battle_conf.txt", "conf/import/battle.conf");
+
+#undef CHECK_OLD_LOCAL_CONF
+ }
// loads npcs
map->reloadnpc(false);
@@ -6079,7 +6647,9 @@ int do_init(int argc, char *argv[])
char ip_str[16];
sockt->ip2str(sockt->addr_[0], ip_str);
- ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n");
+#ifndef BUILDBOT
+ ShowWarning("Not all IP addresses in /conf/map/map-server.conf configured, auto-detecting...\n");
+#endif
if (sockt->naddr_ == 0)
ShowError("Unable to determine your IP address...\n");
@@ -6094,12 +6664,12 @@ int do_init(int argc, char *argv[])
chrif->setip(ip_str);
}
- battle->config_read(map->BATTLE_CONF_FILENAME);
+ battle->config_read(map->BATTLE_CONF_FILENAME, false);
atcommand->msg_read(map->MSG_CONF_NAME, false);
- map->inter_config_read(map->INTER_CONF_NAME);
- logs->config_read(map->LOG_CONF_NAME);
+ map->inter_config_read(map->INTER_CONF_NAME, false);
+ logs->config_read(map->LOG_CONF_NAME, false);
}
- script->config_read(map->SCRIPT_CONF_NAME);
+ script->config_read(map->SCRIPT_CONF_NAME, false);
map->id_db = idb_alloc(DB_OPT_BASE);
map->pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map->id2sd() use. [Skotlex]
@@ -6137,8 +6707,8 @@ int do_init(int argc, char *argv[])
}
}
- if(map->enable_grf)
- grfio_init(map->GRF_PATH_FILENAME);
+ if (map->enable_grf)
+ grfio->init(map->GRF_PATH_FILENAME);
map->readallmaps();
@@ -6160,11 +6730,13 @@ int do_init(int argc, char *argv[])
ircbot->init(minimal);
script->init(minimal);
itemdb->init(minimal);
+ clan->init(minimal);
skill->init(minimal);
if (!minimal)
map->read_zone_db();/* read after item and skill initialization */
mob->init(minimal);
pc->init(minimal);
+ refine->init(minimal);
status->init(minimal);
party->init(minimal);
guild->init(minimal);
@@ -6174,11 +6746,14 @@ int do_init(int argc, char *argv[])
mercenary->init(minimal);
elemental->init(minimal);
quest->init(minimal);
+ achievement->init(minimal);
+ stylist->init(minimal);
npc->init(minimal);
unit->init(minimal);
bg->init(minimal);
duel->init(minimal);
vending->init(minimal);
+ rodex->init(minimal);
if (map->scriptcheck) {
bool failed = map->extra_scripts_count > 0 ? false : true;
@@ -6198,6 +6773,8 @@ int do_init(int argc, char *argv[])
npc->event_do_oninit( false ); // Init npcs (OnInit)
npc->market_fromsql(); /* after OnInit */
+ npc->barter_fromsql(); /* after OnInit */
+ npc->expanded_barter_fromsql(); /* after OnInit */
if (battle_config.pk_mode)
ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
@@ -6225,11 +6802,12 @@ int do_init(int argc, char *argv[])
}
/*=====================================
-* Default Functions : map.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void map_defaults(void) {
+ * Default Functions : map.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void map_defaults(void)
+{
map = &map_s;
/* */
@@ -6242,8 +6820,8 @@ void map_defaults(void) {
map->extra_scripts_count = 0;
sprintf(map->db_path ,"db");
+ libconfig->set_db_path(map->db_path);
sprintf(map->help_txt ,"conf/help.txt");
- sprintf(map->help2_txt ,"conf/help2.txt");
sprintf(map->charhelp_txt ,"conf/charhelp.txt");
sprintf(map->wisp_server_name ,"Server"); // can be modified in char-server configuration file
@@ -6256,12 +6834,12 @@ void map_defaults(void) {
map->night_flag = 0; // 0=day, 1=night [Yor]
map->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
- map->INTER_CONF_NAME="conf/inter-server.conf";
- map->LOG_CONF_NAME="conf/logs.conf";
- map->MAP_CONF_NAME = "conf/map-server.conf";
- map->BATTLE_CONF_FILENAME = "conf/battle.conf";
+ map->INTER_CONF_NAME="conf/common/inter-server.conf";
+ map->LOG_CONF_NAME="conf/map/logs.conf";
+ map->MAP_CONF_NAME = "conf/map/map-server.conf";
+ map->BATTLE_CONF_FILENAME = "conf/map/battle.conf";
map->ATCOMMAND_CONF_FILENAME = "conf/atcommand.conf";
- map->SCRIPT_CONF_NAME = "conf/script.conf";
+ map->SCRIPT_CONF_NAME = "conf/map/script.conf";
map->MSG_CONF_NAME = "conf/messages.conf";
map->GRF_PATH_FILENAME = "conf/grf-files.txt";
@@ -6304,13 +6882,15 @@ void map_defaults(void) {
map->bl_list_size = 0;
//all in a big chunk, respects order
+PRAGMA_GCC9(GCC diagnostic push)
+PRAGMA_GCC9(GCC diagnostic ignored "-Warray-bounds")
memset(ZEROED_BLOCK_POS(map), 0, ZEROED_BLOCK_SIZE(map));
+PRAGMA_GCC9(GCC diagnostic pop)
map->cpsd = NULL;
map->list = NULL;
map->iterator_ers = NULL;
- map->cache_buffer = NULL;
map->flooritem_ers = NULL;
/* */
@@ -6318,9 +6898,11 @@ void map_defaults(void) {
/* funcs */
map->zone_init = map_zone_init;
map->zone_remove = map_zone_remove;
+ map->zone_remove_all = map_zone_remove_all;
map->zone_apply = map_zone_apply;
map->zone_change = map_zone_change;
map->zone_change2 = map_zone_change2;
+ map->zone_reload = map_zonedb_reload;
map->getcell = map_getcell;
map->setgatcell = map_setgatcell;
@@ -6390,6 +6972,7 @@ void map_defaults(void) {
map->foreachinpath = map_foreachinpath;
map->vforeachinmap = map_vforeachinmap;
map->foreachinmap = map_foreachinmap;
+ map->forcountinmap = map_forcountinmap;
map->vforeachininstance = map_vforeachininstance;
map->foreachininstance = map_foreachininstance;
@@ -6457,8 +7040,8 @@ void map_defaults(void) {
map->iwall_nextxy = map_iwall_nextxy;
map->create_map_data_other_server = create_map_data_other_server;
map->eraseallipport_sub = map_eraseallipport_sub;
- map->init_mapcache = map_init_mapcache;
map->readfromcache = map_readfromcache;
+ map->readfromcache_v1 = map_readfromcache_v1;
map->addmap = map_addmap;
map->delmapid = map_delmapid;
map->zone_db_clear = map_zone_db_clear;
@@ -6467,9 +7050,10 @@ void map_defaults(void) {
map->readgat = map_readgat;
map->readallmaps = map_readallmaps;
map->config_read = map_config_read;
- map->config_read_sub = map_config_read_sub;
- map->reloadnpc_sub = map_reloadnpc_sub;
+ map->read_npclist = map_read_npclist;
map->inter_config_read = inter_config_read;
+ map->inter_config_read_database_names = inter_config_read_database_names;
+ map->inter_config_read_connection = inter_config_read_connection;
map->sql_init = map_sql_init;
map->sql_close = map_sql_close;
map->zone_mf_cache = map_zone_mf_cache;
diff --git a/src/map/map.h b/src/map/map.h
index dbd30febf..2de6df2f7 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,12 +27,14 @@
#include "common/db.h"
#include "common/mapindex.h"
#include "common/mmo.h"
+#include "map/unitdefines.h" // enum unit_dir
#include <stdio.h>
#include <stdarg.h>
/* Forward Declarations */
struct Sql; // common/sql.h
+struct config_t; // common/conf.h
struct mob_data;
struct npc_data;
struct channel_data;
@@ -44,36 +46,12 @@ enum E_MAPSERVER_ST {
MAPSERVER_ST_LAST
};
-#define MAX_NPC_PER_MAP 512
-#define AREA_SIZE (battle->bc->area_size)
-#define DAMAGELOG_SIZE 30
-#define LOOTITEM_SIZE 10
-#define MAX_MOBSKILL 50
-#define MAX_MOB_LIST_PER_MAP 100
-#define MAX_EVENTQUEUE 2
-#define MAX_EVENTTIMER 32
-#define NATURAL_HEAL_INTERVAL 500
-#define MIN_FLOORITEM 2
-#define MAX_FLOORITEM START_ACCOUNT_NUM
-#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]
-
-#define BLOCK_SIZE 8
-#define block_free_max 1048576
-#define BL_LIST_MAX 1048576
-
-// For filtering and quick checking.
-#define MAPID_BASEMASK 0x00ff
-#define MAPID_UPPERMASK 0x0fff
-#define MAPID_THIRDMASK (JOBL_THIRD|MAPID_UPPERMASK)
-
//First Jobs
//Note the oddity of the novice:
//Super Novices are considered the 2-1 version of the novice! Novices are considered a first class type.
enum {
//Novice And 1-1 Jobs
- MAPID_NOVICE = 0x0,
+ MAPID_NOVICE = 0,
MAPID_SWORDMAN,
MAPID_MAGE,
MAPID_ARCHER,
@@ -87,146 +65,249 @@ enum {
MAPID_XMAS,
MAPID_SUMMER,
MAPID_GANGSI,
+ MAPID_SUMMONER,
+ MAPID_1_1_MAX,
+
//2-1 Jobs
- MAPID_SUPER_NOVICE = JOBL_2_1|0x0,
- MAPID_KNIGHT,
- MAPID_WIZARD,
- MAPID_HUNTER,
- MAPID_PRIEST,
- MAPID_BLACKSMITH,
- MAPID_ASSASSIN,
- MAPID_STAR_GLADIATOR,
- MAPID_REBELLION = JOBL_2_1|0x09,
- MAPID_KAGEROUOBORO = JOBL_2_1|0x0A,
- MAPID_DEATH_KNIGHT = JOBL_2_1|0x0E,
+ MAPID_SUPER_NOVICE = JOBL_2_1 | MAPID_NOVICE,
+ MAPID_KNIGHT = JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_WIZARD = JOBL_2_1 | MAPID_MAGE,
+ MAPID_HUNTER = JOBL_2_1 | MAPID_ARCHER,
+ MAPID_PRIEST = JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_BLACKSMITH = JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_ASSASSIN = JOBL_2_1 | MAPID_THIEF,
+ MAPID_STAR_GLADIATOR = JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_2_1 | MAPID_WEDDING,
+ MAPID_REBELLION = JOBL_2_1 | MAPID_GUNSLINGER,
+ MAPID_KAGEROUOBORO = JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_2_1 | MAPID_SUMMER,
+ MAPID_DEATH_KNIGHT = JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_2_1 | MAPID_SUMMONER,
+
//2-2 Jobs
- MAPID_CRUSADER = JOBL_2_2|0x1,
- MAPID_SAGE,
- MAPID_BARDDANCER,
- MAPID_MONK,
- MAPID_ALCHEMIST,
- MAPID_ROGUE,
- MAPID_SOUL_LINKER,
- MAPID_DARK_COLLECTOR = JOBL_2_2|0x0E,
+ // = JOBL_2_1 | MAPID_NOVICE,
+ MAPID_CRUSADER = JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_SAGE = JOBL_2_2 | MAPID_MAGE,
+ MAPID_BARDDANCER = JOBL_2_2 | MAPID_ARCHER,
+ MAPID_MONK = JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_ALCHEMIST = JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_ROGUE = JOBL_2_2 | MAPID_THIEF,
+ MAPID_SOUL_LINKER = JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_2_2 | MAPID_SUMMER,
+ MAPID_DARK_COLLECTOR = JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_2_2 | MAPID_SUMMONER,
+
//Trans Novice And Trans 1-1 Jobs
- MAPID_NOVICE_HIGH = JOBL_UPPER|0x0,
- MAPID_SWORDMAN_HIGH,
- MAPID_MAGE_HIGH,
- MAPID_ARCHER_HIGH,
- MAPID_ACOLYTE_HIGH,
- MAPID_MERCHANT_HIGH,
- MAPID_THIEF_HIGH,
+ MAPID_NOVICE_HIGH = JOBL_UPPER | MAPID_NOVICE,
+ MAPID_SWORDMAN_HIGH = JOBL_UPPER | MAPID_SWORDMAN,
+ MAPID_MAGE_HIGH = JOBL_UPPER | MAPID_MAGE,
+ MAPID_ARCHER_HIGH = JOBL_UPPER | MAPID_ARCHER,
+ MAPID_ACOLYTE_HIGH = JOBL_UPPER | MAPID_ACOLYTE,
+ MAPID_MERCHANT_HIGH = JOBL_UPPER | MAPID_MERCHANT,
+ MAPID_THIEF_HIGH = JOBL_UPPER | MAPID_THIEF,
+ // = JOBL_UPPER | MAPID_TAEKWON,
+ // = JOBL_UPPER | MAPID_WEDDING,
+ // = JOBL_UPPER | MAPID_GUNSLINGER,
+ // = JOBL_UPPER | MAPID_NINJA,
+ // = JOBL_UPPER | MAPID_XMAS,
+ // = JOBL_UPPER | MAPID_SUMMER,
+ // = JOBL_UPPER | MAPID_GANGSI,
+ // = JOBL_UPPER | MAPID_SUMMONER,
+
//Trans 2-1 Jobs
- MAPID_LORD_KNIGHT = JOBL_UPPER|JOBL_2_1|0x1,
- MAPID_HIGH_WIZARD,
- MAPID_SNIPER,
- MAPID_HIGH_PRIEST,
- MAPID_WHITESMITH,
- MAPID_ASSASSIN_CROSS,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_NOVICE,
+ MAPID_LORD_KNIGHT = JOBL_UPPER | JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_HIGH_WIZARD = JOBL_UPPER | JOBL_2_1 | MAPID_MAGE,
+ MAPID_SNIPER = JOBL_UPPER | JOBL_2_1 | MAPID_ARCHER,
+ MAPID_HIGH_PRIEST = JOBL_UPPER | JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_WHITESMITH = JOBL_UPPER | JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_ASSASSIN_CROSS = JOBL_UPPER | JOBL_2_1 | MAPID_THIEF,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_WEDDING,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_GUNSLINGER,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_SUMMER,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_UPPER | JOBL_2_1 | MAPID_SUMMONER,
+
//Trans 2-2 Jobs
- MAPID_PALADIN = JOBL_UPPER|JOBL_2_2|0x1,
- MAPID_PROFESSOR,
- MAPID_CLOWNGYPSY,
- MAPID_CHAMPION,
- MAPID_CREATOR,
- MAPID_STALKER,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_NOVICE,
+ MAPID_PALADIN = JOBL_UPPER | JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_PROFESSOR = JOBL_UPPER | JOBL_2_2 | MAPID_MAGE,
+ MAPID_CLOWNGYPSY = JOBL_UPPER | JOBL_2_2 | MAPID_ARCHER,
+ MAPID_CHAMPION = JOBL_UPPER | JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_CREATOR = JOBL_UPPER | JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_STALKER = JOBL_UPPER | JOBL_2_2 | MAPID_THIEF,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_SUMMER,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_UPPER | JOBL_2_2 | MAPID_SUMMONER,
+
//Baby Novice And Baby 1-1 Jobs
- MAPID_BABY = JOBL_BABY|0x0,
- MAPID_BABY_SWORDMAN,
- MAPID_BABY_MAGE,
- MAPID_BABY_ARCHER,
- MAPID_BABY_ACOLYTE,
- MAPID_BABY_MERCHANT,
- MAPID_BABY_THIEF,
+ MAPID_BABY = JOBL_BABY | MAPID_NOVICE,
+ MAPID_BABY_SWORDMAN = JOBL_BABY | MAPID_SWORDMAN,
+ MAPID_BABY_MAGE = JOBL_BABY | MAPID_MAGE,
+ MAPID_BABY_ARCHER = JOBL_BABY | MAPID_ARCHER,
+ MAPID_BABY_ACOLYTE = JOBL_BABY | MAPID_ACOLYTE,
+ MAPID_BABY_MERCHANT = JOBL_BABY | MAPID_MERCHANT,
+ MAPID_BABY_THIEF = JOBL_BABY | MAPID_THIEF,
+ // = JOBL_BABY | MAPID_TAEKWON,
+ // = JOBL_BABY | MAPID_WEDDING,
+ // = JOBL_BABY | MAPID_GUNSLINGER,
+ // = JOBL_BABY | MAPID_NINJA,
+ // = JOBL_BABY | MAPID_XMAS,
+ // = JOBL_BABY | MAPID_SUMMER,
+ // = JOBL_BABY | MAPID_GANGSI,
+ // = JOBL_BABY | MAPID_SUMMONER,
+
//Baby 2-1 Jobs
- MAPID_SUPER_BABY = JOBL_BABY|JOBL_2_1|0x0,
- MAPID_BABY_KNIGHT,
- MAPID_BABY_WIZARD,
- MAPID_BABY_HUNTER,
- MAPID_BABY_PRIEST,
- MAPID_BABY_BLACKSMITH,
- MAPID_BABY_ASSASSIN,
+ MAPID_SUPER_BABY = JOBL_BABY | JOBL_2_1 | MAPID_NOVICE,
+ MAPID_BABY_KNIGHT = JOBL_BABY | JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_BABY_WIZARD = JOBL_BABY | JOBL_2_1 | MAPID_MAGE,
+ MAPID_BABY_HUNTER = JOBL_BABY | JOBL_2_1 | MAPID_ARCHER,
+ MAPID_BABY_PRIEST = JOBL_BABY | JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_BABY_BLACKSMITH = JOBL_BABY | JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_BABY_ASSASSIN = JOBL_BABY | JOBL_2_1 | MAPID_THIEF,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_WEDDING,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_GUNSLINGER,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_SUMMER,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_BABY | JOBL_2_1 | MAPID_SUMMONER,
+
//Baby 2-2 Jobs
- MAPID_BABY_CRUSADER = JOBL_BABY|JOBL_2_2|0x1,
- MAPID_BABY_SAGE,
- MAPID_BABY_BARDDANCER,
- MAPID_BABY_MONK,
- MAPID_BABY_ALCHEMIST,
- MAPID_BABY_ROGUE,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_NOVICE,
+ MAPID_BABY_CRUSADER = JOBL_BABY | JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_BABY_SAGE = JOBL_BABY | JOBL_2_2 | MAPID_MAGE,
+ MAPID_BABY_BARDDANCER = JOBL_BABY | JOBL_2_2 | MAPID_ARCHER,
+ MAPID_BABY_MONK = JOBL_BABY | JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_BABY_ALCHEMIST = JOBL_BABY | JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_BABY_ROGUE = JOBL_BABY | JOBL_2_2 | MAPID_THIEF,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_SUMMER,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_BABY | JOBL_2_2 | MAPID_SUMMONER,
+
//3-1 Jobs
- MAPID_SUPER_NOVICE_E = JOBL_THIRD|JOBL_2_1|0x0,
- MAPID_RUNE_KNIGHT,
- MAPID_WARLOCK,
- MAPID_RANGER,
- MAPID_ARCH_BISHOP,
- MAPID_MECHANIC,
- MAPID_GUILLOTINE_CROSS,
+ MAPID_SUPER_NOVICE_E = JOBL_THIRD | JOBL_2_1 | MAPID_NOVICE,
+ MAPID_RUNE_KNIGHT = JOBL_THIRD | JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_WARLOCK = JOBL_THIRD | JOBL_2_1 | MAPID_MAGE,
+ MAPID_RANGER = JOBL_THIRD | JOBL_2_1 | MAPID_ARCHER,
+ MAPID_ARCH_BISHOP = JOBL_THIRD | JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_MECHANIC = JOBL_THIRD | JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_GUILLOTINE_CROSS = JOBL_THIRD | JOBL_2_1 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_2_1 | MAPID_SUMMONER,
+
//3-2 Jobs
- MAPID_ROYAL_GUARD = JOBL_THIRD|JOBL_2_2|0x1,
- MAPID_SORCERER,
- MAPID_MINSTRELWANDERER,
- MAPID_SURA,
- MAPID_GENETIC,
- MAPID_SHADOW_CHASER,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_NOVICE,
+ MAPID_ROYAL_GUARD = JOBL_THIRD | JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_SORCERER = JOBL_THIRD | JOBL_2_2 | MAPID_MAGE,
+ MAPID_MINSTRELWANDERER = JOBL_THIRD | JOBL_2_2 | MAPID_ARCHER,
+ MAPID_SURA = JOBL_THIRD | JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_GENETIC = JOBL_THIRD | JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_SHADOW_CHASER = JOBL_THIRD | JOBL_2_2 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_2_2 | MAPID_SUMMONER,
+
//Trans 3-1 Jobs
- MAPID_RUNE_KNIGHT_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_1|0x1,
- MAPID_WARLOCK_T,
- MAPID_RANGER_T,
- MAPID_ARCH_BISHOP_T,
- MAPID_MECHANIC_T,
- MAPID_GUILLOTINE_CROSS_T,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_NOVICE,
+ MAPID_RUNE_KNIGHT_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_WARLOCK_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_MAGE,
+ MAPID_RANGER_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_ARCHER,
+ MAPID_ARCH_BISHOP_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_MECHANIC_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_GUILLOTINE_CROSS_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_1 | MAPID_SUMMONER,
+
//Trans 3-2 Jobs
- MAPID_ROYAL_GUARD_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_2|0x1,
- MAPID_SORCERER_T,
- MAPID_MINSTRELWANDERER_T,
- MAPID_SURA_T,
- MAPID_GENETIC_T,
- MAPID_SHADOW_CHASER_T,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_NOVICE,
+ MAPID_ROYAL_GUARD_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_SORCERER_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_MAGE,
+ MAPID_MINSTRELWANDERER_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_ARCHER,
+ MAPID_SURA_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_GENETIC_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_SHADOW_CHASER_T = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_UPPER | JOBL_2_2 | MAPID_SUMMONER,
+
//Baby 3-1 Jobs
- MAPID_SUPER_BABY_E = JOBL_THIRD|JOBL_BABY|JOBL_2_1|0x0,
- MAPID_BABY_RUNE,
- MAPID_BABY_WARLOCK,
- MAPID_BABY_RANGER,
- MAPID_BABY_BISHOP,
- MAPID_BABY_MECHANIC,
- MAPID_BABY_CROSS,
+ MAPID_SUPER_BABY_E = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_NOVICE,
+ MAPID_BABY_RUNE = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_SWORDMAN,
+ MAPID_BABY_WARLOCK = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_MAGE,
+ MAPID_BABY_RANGER = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_ARCHER,
+ MAPID_BABY_BISHOP = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_ACOLYTE,
+ MAPID_BABY_MECHANIC = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_MERCHANT,
+ MAPID_BABY_CROSS = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_1 | MAPID_SUMMONER,
+
//Baby 3-2 Jobs
- MAPID_BABY_GUARD = JOBL_THIRD|JOBL_BABY|JOBL_2_2|0x1,
- MAPID_BABY_SORCERER,
- MAPID_BABY_MINSTRELWANDERER,
- MAPID_BABY_SURA,
- MAPID_BABY_GENETIC,
- MAPID_BABY_CHASER,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_NOVICE,
+ MAPID_BABY_GUARD = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_SWORDMAN,
+ MAPID_BABY_SORCERER = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_MAGE,
+ MAPID_BABY_MINSTRELWANDERER = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_ARCHER,
+ MAPID_BABY_SURA = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_ACOLYTE,
+ MAPID_BABY_GENETIC = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_MERCHANT,
+ MAPID_BABY_CHASER = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_THIEF,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_TAEKWON,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_WEDDING,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_GUNSLINGER,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_NINJA,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_XMAS,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_SUMMER,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_GANGSI,
+ // = JOBL_THIRD | JOBL_BABY | JOBL_2_2 | MAPID_SUMMONER,
};
-// Max size for inputs to Graffiti, Talkie Box and Vending text prompts
-#define MESSAGE_SIZE (79 + 1)
-// String length you can write in the 'talking box'
-#define CHATBOX_SIZE (70 + 1)
-// Chatroom-related string sizes
-#define CHATROOM_TITLE_SIZE (36 + 1)
-#define CHATROOM_PASS_SIZE (8 + 1)
-// Max allowed chat text length
-#define CHAT_SIZE_MAX (255 + 1)
-// 24 for npc name + 24 for label + 2 for a "::" and 1 for EOS
-#define EVENT_NAME_LENGTH ( NAME_LENGTH * 2 + 3 )
-#define DEFAULT_AUTOSAVE_INTERVAL (5*60*1000)
-// Specifies maps where players may hit each other
-#define map_flag_vs(m) ( \
- map->list[m].flag.pvp \
- || map->list[m].flag.gvg_dungeon \
- || map->list[m].flag.gvg \
- || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) \
- || map->list[m].flag.battleground \
- )
-// Specifies maps that have special GvG/WoE restrictions
-#define map_flag_gvg(m) (map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle))
-// Specifies if the map is tagged as GvG/WoE (regardless of map->agit_flag status)
-#define map_flag_gvg2(m) (map->list[m].flag.gvg || map->list[m].flag.gvg_castle)
-// No Kill Steal Protection
-#define map_flag_ks(m) (map->list[m].flag.town || map->list[m].flag.pvp || map->list[m].flag.gvg || map->list[m].flag.battleground)
-// No ViewID
-#define map_no_view(m, view) (map->list[m].flag.noviewid & (view))
+STATIC_ASSERT(((MAPID_1_1_MAX - 1) | MAPID_BASEMASK) == MAPID_BASEMASK, "First class map IDs do not fit into MAPID_BASEMASK");
//This stackable implementation does not means a BL can be more than one type at a time, but it's
// meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex]
@@ -246,9 +327,6 @@ enum bl_type {
BL_ALL = 0xFFF,
};
-// For common mapforeach calls. Since pets cannot be affected, they aren't included here yet.
-#define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM)
-
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, TOMB };
/**
@@ -372,7 +450,7 @@ struct block_list {
// Mob List Held in memory for Dynamic Mobs [Wizputer]
// Expanded to specify all mob-related spawn data by [Skotlex]
struct spawn_data {
- short class_; ///< Class, used because a mob can change it's class
+ int class_; ///< Class, used because a mob can change it's class
unsigned short m, x, y; ///< Spawn information (map, point, spawn-area around point)
signed short xs, ys;
unsigned short num; ///< Number of mobs using this structure
@@ -385,7 +463,7 @@ struct spawn_data {
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
unsigned int dynamic : 1; ///< Whether this data is indexed by a map's dynamic mob list
- unsigned int boss : 1; ///< 0: Non-boss monster | 1: Boss monster
+ uint8 boss; ///< 0: Non-boss monster | 1: Boss monster | 2: MVP
} state;
char name[NAME_LENGTH], eventname[EVENT_NAME_LENGTH]; //Name/event
};
@@ -397,9 +475,11 @@ struct flooritem_data {
int first_get_charid,second_get_charid,third_get_charid;
int64 first_get_tick,second_get_tick,third_get_tick;
struct item item_data;
+ bool showdropeffect;
};
enum status_point_types { //we better clean up this enum and change it name [Hemagx]
+ SP_NONE = -1,
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
@@ -419,6 +499,7 @@ enum status_point_types { //we better clean up this enum and change it name [Hem
SP_MOD_EXP=125,
SP_MOD_DROP=126,
SP_MOD_DEATH=127,
+ SP_BANKVAULT=128,
// Mercenaries
SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,
@@ -488,6 +569,10 @@ enum look {
LOOK_FLOOR,
LOOK_ROBE,
LOOK_BODY2,
+
+#ifndef LOOK_MAX
+ LOOK_MAX
+#endif
};
// used by map_setcell()
@@ -573,7 +658,7 @@ enum map_zone_skill_subtype {
};
struct map_zone_disabled_skill_entry {
- unsigned short nameid;
+ int nameid;
enum bl_type type;
enum map_zone_skill_subtype subtype;
};
@@ -583,7 +668,7 @@ struct map_zone_disabled_command_entry {
};
struct map_zone_skill_damage_cap_entry {
- unsigned short nameid;
+ int nameid;
unsigned int cap;
enum bl_type type;
enum map_zone_skill_subtype subtype;
@@ -595,15 +680,6 @@ enum map_zone_merge_type {
MZMT_NEVERMERGE, ///< Cannot merge with any zones.
};
-#define MAP_ZONE_NAME_LENGTH 60
-#define MAP_ZONE_ALL_NAME "All"
-#define MAP_ZONE_NORMAL_NAME "Normal"
-#define MAP_ZONE_PVP_NAME "PvP"
-#define MAP_ZONE_GVG_NAME "GvG"
-#define MAP_ZONE_BG_NAME "Battlegrounds"
-#define MAP_ZONE_PK_NAME "PK Mode"
-#define MAP_ZONE_MAPFLAG_LENGTH 50
-
struct map_zone_data {
char name[MAP_ZONE_NAME_LENGTH];/* 20'd */
enum map_zone_merge_type merge_type;
@@ -630,17 +706,6 @@ struct map_drop_list {
int drop_per;
};
-
-struct questinfo {
- struct npc_data *nd;
- unsigned short icon;
- unsigned char color;
- int quest_id;
- bool hasJob;
- unsigned short job;/* perhaps a mapid mask would be most flexible? */
-};
-
-
struct map_data {
char name[MAP_NAME_LENGTH];
uint16 index; // The map index used by the mapindex* functions.
@@ -687,6 +752,7 @@ struct map_data {
unsigned gvg_dungeon : 1; // Celest
unsigned gvg_noparty : 1;
unsigned battleground : 2; // [BattleGround System]
+ unsigned cvc : 1;
unsigned nozenypenalty : 1;
unsigned notrade : 1;
unsigned noskill : 1;
@@ -717,6 +783,11 @@ struct map_data {
unsigned noknockback : 1;
unsigned notomb : 1;
unsigned nocashshop : 1;
+ unsigned noautoloot : 1;
+ unsigned pairship_startable : 1;
+ unsigned pairship_endable : 1;
+ unsigned nostorage : 2;
+ unsigned nogstorage : 2;
uint32 noviewid; ///< noviewid (bitmask - @see enum equip_pos)
} flag;
struct point save;
@@ -769,11 +840,13 @@ struct map_data {
/* */
int (*getcellp)(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk);
void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
- char *cellPos;
+ struct {
+ uint8 *data;
+ int len;
+ } cell_buf;
- /* ShowEvent Data Cache */
- struct questinfo *qi_data;
- unsigned short qi_count;
+ /* questinfo entries list */
+ VECTOR_DECL(struct npc_data *) qi_list;
/* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
unsigned short hpmeter_visible;
@@ -924,20 +997,20 @@ struct charid2nick {
struct charid_request* requests;// requests of notification on this nick
};
-// This is the main header found at the very beginning of the map cache
-struct map_cache_main_header {
- uint32 file_size;
- uint16 map_count;
-};
-
-// This is the header appended before every compressed map cells info in the map cache
-struct map_cache_map_info {
- char name[MAP_NAME_LENGTH];
+// New mcache file format header
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(push, 1)
+#endif // not NetBSD < 6 / Solaris
+struct map_cache_header {
+ int16 version;
+ uint8 md5_checksum[16];
int16 xs;
int16 ys;
int32 len;
-};
-
+} __attribute__((packed));
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(pop)
+#endif // not NetBSD < 6 / Solaris
/*=====================================
* Interface : map.h
@@ -967,7 +1040,6 @@ struct map_interface {
char db_path[256];
char help_txt[256];
- char help2_txt[256];
char charhelp_txt[256];
char wisp_server_name[NAME_LENGTH];
@@ -984,6 +1056,8 @@ struct map_interface {
char autotrade_merchants_db[32];
char autotrade_data_db[32];
char npc_market_data_db[32];
+ char npc_barter_data_db[32];
+ char npc_expanded_barter_data_db[32];
char default_codepage[32];
char default_lang_str[64];
@@ -996,7 +1070,7 @@ struct map_interface {
char server_db[32];
struct Sql *mysql_handle;
- int port;
+ uint16 port;
int users;
int enable_grf; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
bool ip_set;
@@ -1028,7 +1102,6 @@ END_ZEROED_BLOCK;
struct map_data *list;
/* [Ind/Hercules] */
struct eri *iterator_ers;
- char *cache_buffer; // Has the uncompressed gat data of all maps, so just one allocation has to be made
/* */
struct eri *flooritem_ers;
/* */
@@ -1038,9 +1111,11 @@ END_ZEROED_BLOCK;
/* funcs */
void (*zone_init) (void);
void (*zone_remove) (int m);
+ void (*zone_remove_all) (int m);
void (*zone_apply) (int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath);
void (*zone_change) (int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath);
void (*zone_change2) (int m, struct map_zone_data *zone);
+ void (*zone_reload) (void);
int (*getcell) (int16 m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk);
void (*setgatcell) (int16 m, int16 x, int16 y, int gat);
@@ -1073,7 +1148,7 @@ END_ZEROED_BLOCK;
int (*clearflooritem_timer) (int tid, int64 tick, int id, intptr_t data);
int (*removemobs_timer) (int tid, int64 tick, int id, intptr_t data);
void (*clearflooritem) (struct block_list* bl);
- int (*addflooritem) (const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags);
+ int (*addflooritem) (const struct block_list *bl, struct item *item_data, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags, bool showdropeffect);
// player to map session
void (*addnickdb) (int charid, const char* nick);
void (*delnickdb) (int charid, const char* nick);
@@ -1110,6 +1185,7 @@ END_ZEROED_BLOCK;
int (*foreachinpath) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...);
int (*vforeachinmap) (int (*func)(struct block_list*,va_list), int16 m, int type, va_list args);
int (*foreachinmap) (int (*func)(struct block_list*,va_list), int16 m, int type, ...);
+ int (*forcountinmap) (int (*func)(struct block_list*,va_list), int16 m, int count, int type, ...);
int (*vforeachininstance)(int (*func)(struct block_list*,va_list), int16 instance_id, int type, va_list ap);
int (*foreachininstance)(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...);
@@ -1134,25 +1210,25 @@ END_ZEROED_BLOCK;
void (*addiddb) (struct block_list *bl);
void (*deliddb) (struct block_list *bl);
/* */
- struct map_session_data * (*nick2sd) (const char *nick);
+ struct map_session_data * (*nick2sd) (const char *nick, bool allow_partial);
struct mob_data * (*getmob_boss) (int16 m);
struct mob_data * (*id2boss) (int id);
uint32 (*race_id2mask) (int race);
// reload config file looking only for npcs
void (*reloadnpc) (bool clear);
- int (*check_dir) (int s_dir,int t_dir);
- uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y);
+ int (*check_dir) (enum unit_dir s_dir, enum unit_dir t_dir);
+ enum unit_dir (*calc_dir) (const struct block_list *src, int16 x, int16 y);
int (*random_dir) (struct block_list *bl, short *x, short *y); // [Skotlex]
int (*cleanup_sub) (struct block_list *bl, va_list ap);
- int (*delmap) (char* mapname);
+ int (*delmap) (const char *mapname);
void (*flags_init) (void);
bool (*iwall_set) (int16 m, int16 x, int16 y, int size, int8 dir, bool shootable, const char* wall_name);
void (*iwall_get) (struct map_session_data *sd);
- void (*iwall_remove) (const char *wall_name);
+ bool (*iwall_remove) (const char *wall_name);
int (*addmobtolist) (unsigned short m, struct spawn_data *spawn); // [Wizputer]
void (*spawnmobs) (int16 m); // [Wizputer]
@@ -1178,8 +1254,8 @@ END_ZEROED_BLOCK;
void (*iwall_nextxy) (int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1);
struct DBData (*create_map_data_other_server) (union DBKey key, va_list args);
int (*eraseallipport_sub) (union DBKey key, struct DBData *data, va_list va);
- char* (*init_mapcache) (FILE *fp);
- int (*readfromcache) (struct map_data *m, char *buffer);
+ bool (*readfromcache) (struct map_data *m);
+ bool (*readfromcache_v1) (FILE *fp, struct map_data *m, unsigned int file_size);
int (*addmap) (const char *mapname);
void (*delmapid) (int id);
void (*zone_db_clear) (void);
@@ -1187,14 +1263,15 @@ END_ZEROED_BLOCK;
int (*waterheight) (char *mapname);
int (*readgat) (struct map_data *m);
int (*readallmaps) (void);
- int (*config_read) (char *cfgName);
- int (*config_read_sub) (char *cfgName);
- void (*reloadnpc_sub) (char *cfgName);
- int (*inter_config_read) (char *cfgName);
+ bool (*config_read) (const char *filename, bool imported);
+ bool (*read_npclist) (const char *filename, bool imported);
+ bool (*inter_config_read) (const char *filename, bool imported);
+ bool (*inter_config_read_database_names) (const char *filename, const struct config_t *config, bool imported);
+ bool (*inter_config_read_connection) (const char *filename, const struct config_t *config, bool imported);
int (*sql_init) (void);
int (*sql_close) (void);
bool (*zone_mf_cache) (int m, char *flag, char *params);
- unsigned short (*zone_str2itemid) (const char *name);
+ int (*zone_str2itemid) (const char *name);
unsigned short (*zone_str2skillid) (const char *name);
enum bl_type (*zone_bl_type) (const char *entry, enum map_zone_skill_subtype *subtype);
void (*read_zone_db) (void);
@@ -1204,7 +1281,7 @@ END_ZEROED_BLOCK;
int (*abort_sub) (struct map_session_data *sd, va_list ap);
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 (*add_questinfo) (int m, struct npc_data *nd);
bool (*remove_questinfo) (int m, struct npc_data *nd);
struct map_zone_data *(*merge_zone) (struct map_zone_data *main, struct map_zone_data *other);
void (*zone_clear_single) (struct map_zone_data *zone);
diff --git a/src/map/mapdefines.h b/src/map/mapdefines.h
new file mode 100644
index 000000000..8a363e2d4
--- /dev/null
+++ b/src/map/mapdefines.h
@@ -0,0 +1,119 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_MAPDEFINES_H
+#define MAP_MAPDEFINES_H
+
+#include "common/mmo.h" // packet versions
+
+#define MAX_NPC_PER_MAP 512
+#define AREA_SIZE (battle->bc->area_size)
+#define CHAT_AREA_SIZE (battle->bc->chat_area_size)
+#define DEAD_AREA_SIZE (battle->bc->dead_area_size)
+#define DAMAGELOG_SIZE 30
+#define LOOTITEM_SIZE 10
+#define MAX_MOBSKILL 50
+
+#ifndef MAX_MOB_LIST_PER_MAP
+#ifdef RENEWAL
+#define MAX_MOB_LIST_PER_MAP 100
+#else
+#define MAX_MOB_LIST_PER_MAP 115
+#endif
+#endif
+
+#define MAX_EVENTQUEUE 2
+#define MAX_EVENTTIMER 32
+#define NATURAL_HEAL_INTERVAL 500
+#define MIN_FLOORITEM 2
+#define MAX_FLOORITEM START_ACCOUNT_NUM
+#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]
+
+#define BLOCK_SIZE 8
+#define block_free_max 1048576
+#define BL_LIST_MAX 1048576
+
+// The following system marks a different job ID system used by the map server,
+// which makes a lot more sense than the normal one. [Skotlex]
+// These marks the "level" of the job.
+#define JOBL_2_1 0x0100
+#define JOBL_2_2 0x0200
+#define JOBL_2 0x0300 // JOBL_2_1 | JOBL_2_2
+#define JOBL_UPPER 0x1000
+#define JOBL_BABY 0x2000
+#define JOBL_THIRD 0x4000
+
+// For filtering and quick checking.
+#define MAPID_BASEMASK 0x00ff
+#define MAPID_UPPERMASK 0x0fff
+#define MAPID_THIRDMASK (JOBL_THIRD|MAPID_UPPERMASK)
+
+// Max size for inputs to Vending text prompts
+#define MESSAGE_SIZE (79 + 1)
+// Max size for inputs to Graffiti, Talkie Box text prompts
+#if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
+#define TALKBOX_MESSAGE_SIZE 21
+#else
+#define TALKBOX_MESSAGE_SIZE (79 + 1)
+#endif
+// String length you can write in the 'talking box'
+#define CHATBOX_SIZE (70 + 1)
+// Chatroom-related string sizes
+#define CHATROOM_TITLE_SIZE (36 + 1)
+#define CHATROOM_PASS_SIZE (8 + 1)
+// Max allowed chat text length
+#define CHAT_SIZE_MAX (255 + 1)
+// 24 for npc name + 24 for label + 2 for a "::" and 1 for EOS
+#define EVENT_NAME_LENGTH ( NAME_LENGTH * 2 + 3 )
+#define DEFAULT_AUTOSAVE_INTERVAL (5*60*1000)
+// Specifies maps where players may hit each other
+#define map_flag_vs(m) ( \
+ map->list[m].flag.pvp \
+ || map->list[m].flag.gvg_dungeon \
+ || map->list[m].flag.gvg \
+ || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) \
+ || map->list[m].flag.battleground \
+ || map->list[m].flag.cvc \
+ )
+// Specifies maps that have special GvG/WoE restrictions
+#define map_flag_gvg(m) (map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle))
+// Specifies if the map is tagged as GvG/WoE (regardless of map->agit_flag status)
+#define map_flag_gvg2(m) (map->list[m].flag.gvg || map->list[m].flag.gvg_castle)
+// No Kill Steal Protection
+#define map_flag_ks(m) (map->list[m].flag.town || map->list[m].flag.pvp || map->list[m].flag.gvg || map->list[m].flag.battleground)
+// No ViewID
+#define map_no_view(m, view) (map->list[m].flag.noviewid & (view))
+
+// For common mapforeach calls. Since pets cannot be affected, they aren't included here yet.
+#define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM)
+
+#define MAP_ZONE_NAME_LENGTH 60
+#define MAP_ZONE_ALL_NAME "All"
+#define MAP_ZONE_NORMAL_NAME "Normal"
+#define MAP_ZONE_PVP_NAME "PvP"
+#define MAP_ZONE_GVG_NAME "GvG"
+#define MAP_ZONE_BG_NAME "Battlegrounds"
+#define MAP_ZONE_CVC_NAME "CvC"
+#define MAP_ZONE_PK_NAME "PK Mode"
+#define MAP_ZONE_MAPFLAG_LENGTH 65
+
+#endif /* MAP_MAPDEFINES_H */
diff --git a/src/map/mapreg.h b/src/map/mapreg.h
index d19b2bb80..b3b89e1b2 100644
--- a/src/map/mapreg.h
+++ b/src/map/mapreg.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,8 @@
#include "common/hercules.h"
#include "common/db.h"
+/* Forward Declarations */
+struct config_setting_t; // common/conf.h
struct eri;
/** Container for a mapreg value */
@@ -61,7 +63,7 @@ struct mapreg_interface {
int (*save_timer) (int tid, int64 tick, int id, intptr_t data);
int (*destroyreg) (union DBKey key, struct DBData *data, va_list ap);
void (*reload) (void);
- bool (*config_read) (const char *w1, const char *w2);
+ bool (*config_read) (const char *filename, const struct config_setting_t *config, bool imported);
};
#ifdef HERCULES_CORE
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 82ce39d64..741505e17 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include "map/map.h" // map-"mysql_handle
#include "map/script.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/db.h"
#include "common/ers.h"
#include "common/memmgr.h"
@@ -37,7 +38,7 @@
#include <stdlib.h>
#include <string.h>
-struct mapreg_interface mapreg_s;
+static struct mapreg_interface mapreg_s;
struct mapreg_interface *mapreg;
#define MAPREG_AUTOSAVE_INTERVAL (300*1000)
@@ -48,7 +49,8 @@ struct mapreg_interface *mapreg;
* @param uid variable's unique identifier.
* @return variable's integer value
*/
-int mapreg_readreg(int64 uid) {
+static int mapreg_readreg(int64 uid)
+{
struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
return m?m->u.i:0;
}
@@ -59,7 +61,8 @@ int mapreg_readreg(int64 uid) {
* @param uid variable's unique identifier
* @return variable's string value
*/
-char* mapreg_readregstr(int64 uid) {
+static char *mapreg_readregstr(int64 uid)
+{
struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
return m?m->u.str:NULL;
}
@@ -71,7 +74,8 @@ char* mapreg_readregstr(int64 uid) {
* @param val new value
* @retval true value was successfully set
*/
-bool mapreg_setreg(int64 uid, int val) {
+static bool mapreg_setreg(int64 uid, int val)
+{
struct mapreg_save *m;
int num = script_getvarid(uid);
unsigned int i = script_getvaridx(uid);
@@ -128,7 +132,8 @@ bool mapreg_setreg(int64 uid, int val) {
* @param str new value
* @retval true value was successfully set
*/
-bool mapreg_setregstr(int64 uid, const char* str) {
+static bool mapreg_setregstr(int64 uid, const char *str)
+{
struct mapreg_save *m;
int num = script_getvarid(uid);
unsigned int i = script_getvaridx(uid);
@@ -187,7 +192,8 @@ bool mapreg_setregstr(int64 uid, const char* str) {
/**
* Loads permanent variables from database.
*/
-void script_load_mapreg(void) {
+static void script_load_mapreg(void)
+{
/*
0 1 2
+-------------------------+
@@ -210,12 +216,12 @@ void script_load_mapreg(void) {
mapreg->skip_insert = true;
- SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname[0], sizeof(varname), &length, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL);
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname, sizeof varname, &length, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, sizeof index, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value, sizeof value, NULL, NULL);
while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
- int s = script->add_str(varname);
+ int s = script->add_variable(varname);
int i = index;
@@ -240,7 +246,7 @@ void script_load_mapreg(void) {
/**
* Saves permanent variables to database.
*/
-void script_save_mapreg(void)
+static void script_save_mapreg(void)
{
if (mapreg->dirty) {
struct DBIterator *iter = db_iterator(mapreg->regs.vars);
@@ -273,7 +279,8 @@ void script_save_mapreg(void)
*
* @see timer->do_timer
*/
-int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data) {
+static int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data)
+{
mapreg->save();
return 0;
}
@@ -283,7 +290,7 @@ int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data) {
*
* @see DBApply
*/
-int mapreg_destroyreg(union DBKey key, struct DBData *data, va_list ap)
+static int mapreg_destroyreg(union DBKey key, struct DBData *data, va_list ap)
{
struct mapreg_save *m = NULL;
@@ -307,7 +314,8 @@ int mapreg_destroyreg(union DBKey key, struct DBData *data, va_list ap)
* This has the effect of clearing the temporary variables, and
* reloading the permanent ones.
*/
-void mapreg_reload(void) {
+static void mapreg_reload(void)
+{
mapreg->save();
mapreg->regs.vars->clear(mapreg->regs.vars, mapreg->destroyreg);
@@ -323,7 +331,8 @@ void mapreg_reload(void) {
/**
* Finalizer.
*/
-void mapreg_final(void) {
+static void mapreg_final(void)
+{
mapreg->save();
mapreg->regs.vars->destroy(mapreg->regs.vars, mapreg->destroyreg);
@@ -337,7 +346,8 @@ void mapreg_final(void) {
/**
* Initializer.
*/
-void mapreg_init(void) {
+static void mapreg_init(void)
+{
mapreg->regs.vars = i64db_alloc(DB_OPT_BASE);
mapreg->ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_CLEAN);
@@ -349,13 +359,19 @@ void mapreg_init(void) {
/**
* Loads the mapreg configuration file.
+ *
+ * @param filename Path to configuration file (used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
*/
-bool mapreg_config_read(const char* w1, const char* w2) {
- nullpo_retr(false, w1);
- nullpo_retr(false, w2);
- if(!strcmpi(w1, "mapreg_db"))
- safestrncpy(mapreg->table, w2, sizeof(mapreg->table));
- else
+static bool mapreg_config_read(const char *filename, const struct config_setting_t *config, bool imported)
+{
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ if (libconfig->setting_lookup_mutable_string(config, "mapreg_db", mapreg->table, sizeof(mapreg->table)) != CONFIG_TRUE)
return false;
return true;
@@ -364,7 +380,8 @@ bool mapreg_config_read(const char* w1, const char* w2) {
/**
* Interface defaults initializer.
*/
-void mapreg_defaults(void) {
+void mapreg_defaults(void)
+{
mapreg = &mapreg_s;
/* */
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 0b055bedf..00fdcae9f 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,12 +57,12 @@
#include <stdlib.h>
#include <string.h>
-struct mercenary_interface mercenary_s;
-struct s_mercenary_db mercdb[MAX_MERCENARY_CLASS];
+static struct mercenary_interface mercenary_s;
+static struct s_mercenary_db mercdb[MAX_MERCENARY_CLASS];
struct mercenary_interface *mercenary;
-int merc_search_index(int class_)
+static int merc_search_index(int class_)
{
int i;
ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary->db[i].class_ == class_);
@@ -71,14 +71,14 @@ int merc_search_index(int class_)
return i;
}
-bool merc_class(int class_)
+static bool merc_class(int class_)
{
if (mercenary->search_index(class_) != INDEX_NOT_FOUND)
return true;
return false;
}
-struct view_data * merc_get_viewdata(int class_)
+static struct view_data *merc_get_viewdata(int class_)
{
int i = mercenary->search_index(class_);
if (i == INDEX_NOT_FOUND)
@@ -87,7 +87,7 @@ struct view_data * merc_get_viewdata(int class_)
return &mercenary->db[i].vd;
}
-int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
+static int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
{
struct s_mercenary merc;
struct s_mercenary_db *db;
@@ -112,7 +112,7 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
return 1;
}
-int mercenary_get_lifetime(struct mercenary_data *md)
+static int mercenary_get_lifetime(struct mercenary_data *md)
{
const struct TimerData * td;
if( md == NULL || md->contract_timer == INVALID_TIMER )
@@ -122,7 +122,7 @@ int mercenary_get_lifetime(struct mercenary_data *md)
return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0;
}
-int mercenary_get_guild(struct mercenary_data *md)
+static int mercenary_get_guild(struct mercenary_data *md)
{
int class_;
@@ -141,7 +141,7 @@ int mercenary_get_guild(struct mercenary_data *md)
return -1;
}
-int mercenary_get_faith(struct mercenary_data *md)
+static int mercenary_get_faith(struct mercenary_data *md)
{
struct map_session_data *sd;
int class_;
@@ -161,7 +161,7 @@ int mercenary_get_faith(struct mercenary_data *md)
return 0;
}
-int mercenary_set_faith(struct mercenary_data *md, int value)
+static int mercenary_set_faith(struct mercenary_data *md, int value)
{
struct map_session_data *sd;
int class_, *faith;
@@ -187,7 +187,7 @@ int mercenary_set_faith(struct mercenary_data *md, int value)
return 0;
}
-int mercenary_get_calls(struct mercenary_data *md)
+static int mercenary_get_calls(struct mercenary_data *md)
{
struct map_session_data *sd;
int class_;
@@ -207,7 +207,7 @@ int mercenary_get_calls(struct mercenary_data *md)
return 0;
}
-int mercenary_set_calls(struct mercenary_data *md, int value)
+static int mercenary_set_calls(struct mercenary_data *md, int value)
{
struct map_session_data *sd;
int class_, *calls;
@@ -232,7 +232,7 @@ int mercenary_set_calls(struct mercenary_data *md, int value)
return 0;
}
-int mercenary_save(struct mercenary_data *md)
+static int mercenary_save(struct mercenary_data *md)
{
nullpo_retr(1, md);
md->mercenary.hp = md->battle_status.hp;
@@ -243,7 +243,8 @@ int mercenary_save(struct mercenary_data *md)
return 1;
}
-int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) {
+static int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
struct mercenary_data *md;
@@ -264,7 +265,7 @@ int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int merc_delete(struct mercenary_data *md, int reply)
+static int merc_delete(struct mercenary_data *md, int reply)
{
struct map_session_data *sd;
@@ -293,7 +294,7 @@ int merc_delete(struct mercenary_data *md, int reply)
return unit->remove_map(&md->bl, CLR_OUTSIGHT, ALC_MARK);
}
-void merc_contract_stop(struct mercenary_data *md)
+static void merc_contract_stop(struct mercenary_data *md)
{
nullpo_retv(md);
if( md->contract_timer != INVALID_TIMER )
@@ -301,7 +302,7 @@ void merc_contract_stop(struct mercenary_data *md)
md->contract_timer = INVALID_TIMER;
}
-void merc_contract_init(struct mercenary_data *md)
+static void merc_contract_init(struct mercenary_data *md)
{
nullpo_retv(md);
if( md->contract_timer == INVALID_TIMER )
@@ -310,7 +311,7 @@ void merc_contract_init(struct mercenary_data *md)
md->regen.state.block = 0;
}
-int merc_data_received(const struct s_mercenary *merc, bool flag)
+static int merc_data_received(const struct s_mercenary *merc, bool flag)
{
struct map_session_data *sd;
struct mercenary_data *md;
@@ -375,7 +376,7 @@ int merc_data_received(const struct s_mercenary *merc, bool flag)
return 1;
}
-void mercenary_heal(struct mercenary_data *md, int hp, int sp)
+static void mercenary_heal(struct mercenary_data *md, int hp, int sp)
{
nullpo_retv(md);
if( hp )
@@ -384,13 +385,13 @@ void mercenary_heal(struct mercenary_data *md, int hp, int sp)
clif->mercenary_updatestatus(md->master, SP_SP);
}
-int mercenary_dead(struct mercenary_data *md)
+static int mercenary_dead(struct mercenary_data *md)
{
mercenary->delete(md, 1);
return 0;
}
-int mercenary_killbonus(struct mercenary_data *md)
+static int mercenary_killbonus(struct mercenary_data *md)
{
const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT };
int index = rnd() % ARRAYLENGTH(scs);
@@ -400,7 +401,7 @@ int mercenary_killbonus(struct mercenary_data *md)
return 0;
}
-int mercenary_kills(struct mercenary_data *md)
+static int mercenary_kills(struct mercenary_data *md)
{
nullpo_ret(md);
md->mercenary.kill_count++;
@@ -418,7 +419,7 @@ int mercenary_kills(struct mercenary_data *md)
return 0;
}
-int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id)
+static int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id)
{
int i = skill_id - MC_SKILLBASE;
@@ -430,7 +431,8 @@ int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id)
return 0;
}
-bool read_mercenarydb_sub(char* str[], int columns, int current) {
+static bool read_mercenarydb_sub(char *str[], int columns, int current)
+{
int ele;
struct s_mercenary_db *db;
struct status_data *mstatus;
@@ -444,7 +446,7 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) {
db->lv = atoi(str[3]);
mstatus = &db->status;
- db->vd.class_ = db->class_;
+ db->vd.class = db->class_;
mstatus->max_hp = atoi(str[4]);
mstatus->max_sp = atoi(str[5]);
@@ -465,7 +467,7 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) {
mstatus->race = atoi(str[20]);
ele = atoi(str[21]);
- mstatus->def_ele = ele%10;
+ mstatus->def_ele = ele % ELE_MAX;
mstatus->ele_lv = ele/20;
if( mstatus->def_ele >= ELE_MAX ) {
ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, mstatus->def_ele, ELE_MAX - 1);
@@ -485,15 +487,17 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) {
return true;
}
-int read_mercenarydb(void) {
+static int read_mercenarydb(void)
+{
memset(mercenary->db, 0, sizeof(struct s_mercenary_db) * MAX_MERCENARY_CLASS);
sv->readdb(map->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, mercenary->read_db_sub);
return 0;
}
-bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
-{// <merc id>,<skill id>,<skill level>
+static bool read_mercenary_skilldb_sub(char *str[], int columns, int current)
+{
+ // <merc id>,<skill id>,<skill level>
struct s_mercenary_db *db;
int i, class_;
uint16 skill_id, skill_lv;
@@ -524,13 +528,15 @@ bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
return true;
}
-int read_mercenary_skilldb(void) {
+static int read_mercenary_skilldb(void)
+{
sv->readdb(map->db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, mercenary->read_skill_db_sub);
return 0;
}
-void do_init_mercenary(bool minimal) {
+static void do_init_mercenary(bool minimal)
+{
if (minimal)
return;
@@ -541,11 +547,12 @@ void do_init_mercenary(bool minimal) {
}
/*=====================================
-* Default Functions : mercenary.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void mercenary_defaults(void) {
+ * Default Functions : mercenary.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void mercenary_defaults(void)
+{
mercenary = &mercenary_s;
/* vars */
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index 142460e2a..bd28729c5 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -92,7 +92,7 @@ struct mercenary_data {
struct regen_data regen;
struct s_mercenary_db *db;
struct s_mercenary mercenary;
- char blockskill[MAX_SKILL];
+ char blockskill[MAX_SKILL_DB];
struct map_session_data *master;
int contract_timer;
diff --git a/src/map/messages.h b/src/map/messages.h
new file mode 100644
index 000000000..adf5bc7e0
--- /dev/null
+++ b/src/map/messages.h
@@ -0,0 +1,36 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_MESSAGES_H
+#define MAP_MESSAGES_H
+
+#if defined(PACKETVER_ZERO)
+#include "map/messages_zero.h"
+#elif defined(PACKETVER_RE)
+#include "map/messages_re.h"
+#elif defined(PACKETVER_SAK)
+#include "map/messages_sak.h"
+#elif defined(PACKETVER_AD)
+#include "map/messages_ad.h"
+#else
+#include "map/messages_main.h"
+#endif
+
+#endif /* MAP_MESSAGES_H */
diff --git a/src/map/messages_ad.h b/src/map/messages_ad.h
new file mode 100644
index 000000000..9a3ada406
--- /dev/null
+++ b/src/map/messages_ad.h
@@ -0,0 +1,7311 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_MESSAGES_AD_H
+#define MAP_MESSAGES_AD_H
+
+/* This file is autogenerated, please do not commit manual changes
+
+Latest version: 20080701
+*/
+
+enum clif_messages {
+/*20040804 to latest
+동의 하십니까?
+Do you agree?
+*/
+ MSG_DO_YOU_AGREE = 0x0,
+/*20040804 to latest
+서버 연결 실패
+Failed to Connect to Server.
+*/
+ MSG_SERVER_CONNECTION_FAILED = 0x1,
+/*20040804 to latest
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+*/
+ MSG_UNABLE_TO_CONNECT_SERVER = 0x2,
+/*20040804 to 20080617
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+20080624 to latest
+서버와 연결이 끊어졌습니다!
+Disconnected from Server!
+*/
+ MSG_BANNED = 0x3,
+/*20040804 to latest
+서버 종료됨
+Server Closed.
+*/
+ MSG_SERVER_OFF = 0x4,
+/*20040804 to latest
+같은 계정으로 다른 사용자가 로그인 하였습니다.
+Someone has Logged in with this ID.
+*/
+ MSG_DOUBLE_LOGIN_PROHIBITED = 0x5,
+/*20040804 to latest
+등록되지 않은 계정입니다. 다시 확인 바랍니다.
+Unregistered ID. Please make sure you have a registered account and you have correctly typed in the user ID.
+*/
+ MSG_INCORRECT_USERID = 0x6,
+/*20040804 to 20070704
+비밀번호가 틀립니다
+20070710 to latest
+입력하신 비밀번호가 올바르지 않습니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_PASSWORD = 0x7,
+/*20040804 to latest
+본 ID 는 사용기간이 만료 되었습니다
+This ID is expired.
+*/
+ MSG_ID_EXPIRED = 0x8,
+/*20040804 to latest
+서버 접근 거부
+Rejected from Server.
+*/
+ MSG_ACCESS_DENIED = 0x9,
+/*20040804 to latest
+같은 캐릭터 이름이 있습니다.
+Character Name already exists.
+*/
+ MSG_CHARACTER_NAME_ALREADY_EXISTS = 0xa,
+/*20040804 to latest
+캐릭터 생성 거부됨
+Character Creation is denied.
+*/
+ MSG_CHARACTER_CREATION_DENIED = 0xb,
+/*20040804 to latest
+캐릭터 삭제 거부
+Character Deletion is denied.
+*/
+ MSG_CANNOT_DELETE_CHARACTER = 0xc,
+/*20040804 to latest
+방제목를 입력하세요.
+Please Enter Room Title.
+*/
+ MSG_ENTER_ROOM_TITLE = 0xd,
+/*20040804 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_SENTANGE = 0xe,
+/*20040804 to latest
+암호를 입력하세요.
+Please enter Password.
+*/
+ MSG_ENTER_PASSWORD = 0xf,
+/*20040804 to latest
+암호를 영문 4자 이상 입력하세요.
+Please enter Password. Passwords must be at least 4 characters long.
+*/
+ MSG_Enter_Password_more_than_4_char = 0x10,
+/*20040804 to latest
+종료 하시겠습니까?
+Are you sure that you want to quit?
+*/
+ MSG_DO_YOU_REALLY_WANT_TO_QUIT = 0x11,
+/*20040804 to latest
+4자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Passwords are at least 4 characters long. Please try again.
+*/
+ MSG_NAME_MUST_EXCEED_4_CHAR = 0x12,
+/*20040804 to 20070704
+캐릭터를 삭제하겠습니까?
+20070618 to latest
+한 번 삭제된 캐릭터 및 관련 정보는 다시 복구되지 않습니다. 캐릭터를 삭제하시겠습니까?
+Are you sure that you want to delete this character?
+*/
+ MSG_DELETE_CHARACTER = 0x13,
+/*20040804 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_NAME = 0x14,
+/*20040804 to latest
+이름을 입력해 주세요.(한글 2자 영문 4자 이상)
+Character Name must be at least 4 characters long.
+*/
+ MSG_ENTER_NAME_MORE_THAN_4_CHAR = 0x15,
+/*20040804 to latest
+명령어 일람: /h
+Command List: /h | /help
+*/
+ MSG_LIST_COMMAND = 0x16,
+/*20040804 to latest
+이펙트 On
+Effects On
+*/
+ MSG_EFFECT_ON = 0x17,
+/*20040804 to latest
+이펙트 Off
+Effects Off
+*/
+ MSG_EFFECT_OFF = 0x18,
+/*20040804 to latest
+사운드 볼륨
+Sound Volume
+*/
+ MSG_VOLUME_OF_SOUND = 0x19,
+/*20040804 to latest
+배경음악 볼륨
+BGM Volume
+*/
+ MSG_VOLUME_OF_BGM = 0x1a,
+/*20040804 to latest
+효과음 On
+Sound Effects On
+*/
+ MSG_SOUND_ON = 0x1b,
+/*20040804 to latest
+효과음 Off
+Sound Effects Off
+*/
+ MSG_SOUND_OFF = 0x1c,
+/*20040804 to latest
+프레임스킵 On
+Frame Skip On
+*/
+ MSG_FRAME_SKIP_ON = 0x1d,
+/*20040804 to latest
+프레임스킵 Off
+Frame Skip Off
+*/
+ MSG_FRAME_SKIP_OFF = 0x1e,
+/*20040804 to latest
+배경음악 On
+BGM On
+*/
+ MSG_BGM_ON = 0x1f,
+/*20040804 to latest
+배경음악 Off
+BGM Off
+*/
+ MSG_BGM_OFF = 0x20,
+/*20040804 to latest
+/h or /help: 명령어 일람
+/h or /help: Shows this Command Help List
+*/
+ MSG_EXPLAIN_HELP = 0x21,
+/*20040804 to latest
+/w or /who or /접속자 or /누구: 현재 접속자수 보기
+/w or /who or /player or /who: wiew current the number of player
+*/
+ MSG_EXPLAIN_WHO = 0x22,
+/*20040804 to latest
+/음악 : 배경음악 On Off
+/music: Turns BGM On or Off
+*/
+ MSG_EXPLAIN_MUSIC = 0x23,
+/*20040804 to latest
+/효과음 : 효과음 On Off
+/sound: Turns Sound Effects On or Off
+*/
+ MSG_EXPLAIN_SOUND = 0x24,
+/*20040804 to latest
+/이펙트 : 이펙트 On Off
+/effect: Effects On or Off
+*/
+ MSG_EXPLAIN_EFFECT = 0x25,
+/*20040804 to latest
+/좌표 or /장소: 현재 위치 표시
+/where: Shows your present location
+*/
+ MSG_EXPLAIN_POS = 0x26,
+/*20040804 to latest
+/skip : 프래임스킵 On Off
+/skip: Turns Frame Skip On or Off
+*/
+ MSG_EXPLAIN_FRAMESKIP = 0x27,
+/*20040804 to latest
+/v (0~127): 효과음 볼륨조정
+/v (0~127): Controls the volume of the Sound Effects
+*/
+ MSG_EXPLAIN_SOUNDVOLUME = 0x28,
+/*20040804 to latest
+/bv (0~127): 배경음악 볼륨조정
+/bv (0~127): Controls the volume of the BGM
+*/
+ MSG_EXPLAIN_BGMVOLUME = 0x29,
+/*20040804 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당캐릭터에 대해 귓말차단
+/ex (Character Name): Blocks whispering from the Character
+*/
+ MSG_EXPLAIN_SAYISOLATION = 0x2a,
+/*20040804 to latest
+/ex or /차단 : 귓말차단 캐릭터 리스트
+/ex: View a list of Characters you have Blocked
+*/
+ MSG_EXPLAIN_LIST_SAYISOLATION_CHAR = 0x2b,
+/*20040804 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당캐릭터에 대해 귓말허용
+/in (Character Name): Allows whispering from the Character
+*/
+ MSG_EXPLAIN_SAY_PERMIT = 0x2c,
+/*20040804 to latest
+/inall or /해제전부 : 모두에게 귓말허용
+/inall: Allows whispers from anyone
+*/
+ MSG_EXPLAIN_SAY_PERMITALL = 0x2d,
+/*20040804 to latest
+/exall or /차단전부 : 모두에게 귓말차단
+/exall: Blocks whispers from everyone
+*/
+ MSG_EXPLAIN_SAY_ISOLATEALL = 0x2e,
+/*20040804 to latest
+다른유저 캐릭터를 마우스 오른버튼을 누르고 있는 상태에서 왼버튼으로 클릭하면 그캐릭터이름이 귓말콤보박스에 저장됩니다.
+Right click on a character and select [Register as a Friend] to add a person to your Friend List.
+*/
+ MSG_EXPLAIN_TIP1 = 0x2f,
+/*20040804 to latest
+단축아이탬창(F12) 소비장비 아이템을 드래그한후 사용하세요. 사용키(F1F2F3F4F5F6F7F8F9)
+F12 Brings up a Hotkey Window which allows you to drag and drop Recovery Items, Equipment and Skills into it for faster access.
+*/
+ MSG_EXPLAIN_TIP2 = 0x30,
+/*20040804 to latest
+같은말을 3번이상 연속해서 전송할 수 없습니다.
+You can't type the same word/phrase more than 3 times.
+*/
+ MSG_NO_SAME_SENTANCE = 0x31,
+/*20040804 to latest
+불량단어 검출로 전송이 중단 되었습니다.
+Chat Filter: Yeah, uh, I don't think so buddy...
+*/
+ MSG_NO_SEND_BECAUSE_INSULT = 0x32,
+/*20040804 to latest
+같은아이템은 한번만 올릴수 있습니다.
+You cannot overlap items on a window.
+*/
+ MSG_CAN_DRAG_ITEM_OLNY_ONETIME = 0x33,
+/*20040804 to latest
+무게가 초과하여 아이템을 가질 수 없습니다.
+You cannot carry more items because you are overweight.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_WEIGHT = 0x34,
+/*20040804 to latest
+아이템을 가질 수 없습니다.
+You cannot get the item.
+*/
+ MSG_CANT_GET_ITEM = 0x35,
+/*20040804 to latest
+거래가 잘 이루어졌습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SECCESS = 0x36,
+/*20040804 to latest
+돈이 부족합니다.
+You do not have enough zeny.
+*/
+ MSG_INSUFFICIENT_MONEY = 0x37,
+/*20040804 to latest
+무게가 초과 되었습니다.
+You are over your Weight Limit.
+*/
+ MSG_OVER_WEIGHT = 0x38,
+/*20040804 to latest
+거래가 실패 했습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAIL = 0x39,
+/*20040804 to latest
+모두에게 귓말거부상태로됨
+You've blocked whispers from everyone.
+*/
+ MSG_REFUSE_HEAR_ALL = 0x3a,
+/*20040804 to latest
+모두에게 귓말거부요청 실패함
+You've failed to block all whispers.
+*/
+ MSG_REQ_REFUSE_HEAR_ALL_FAIL = 0x3b,
+/*20040804 to latest
+모두에게 귓말가능상태가됨
+You've allowed whispers from everyone.
+*/
+ MSG_HEAR_ALL = 0x3c,
+/*20040804 to latest
+모두에게 귓말가능요청 실패함
+You've failed to allow all whispers.
+*/
+ MSG_REQ_HEAR_ALL_FAIL = 0x3d,
+/*20040804 to latest
+귓말 거부 리스트가 없습니다
+You have no Block List.
+*/
+ MSG_NO_REFUSE_HEAR_LIST = 0x3e,
+/*20040804 to latest
+-귓말 거부 리스트-
+[ Character Block List ]
+*/
+ MSG_REFUSE_HEAR_LIST = 0x3f,
+/*20040804 to latest
+방이 잘 만들어 졌습니다.
+Room has been successfully created.
+*/
+ MSG_ROOM_IS_MADE = 0x40,
+/*20040804 to latest
+방갯수가 허용갯수를 초과 하였습니다.
+Room Limit Exceeded.
+*/
+ MSG_TOO_MANY_ROOM = 0x41,
+/*20040804 to latest
+같은 방제목이 있습니다.
+Same Room exists.
+*/
+ MSG_SAME_ROOM_TITLE = 0x42,
+/*20040804 to latest
+인원초과로 방에 들어갈 수 없습니다.
+The Room is full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_ROOM = 0x43,
+/*20040804 to latest
+강제로 퇴장된 방입니다.
+You have been kicked out of this room.
+*/
+ MSG_YOU_HAVE_BANNED_FROM_THE_ROOM = 0x44,
+/*20040804 to latest
+교환요청을 거절 했습니다.
+The deal has been rejected.
+*/
+ MSG_REJECT_DEAL = 0x45,
+/*20040804 to latest
+교환가능거리를 벗어났습니다.
+You are too far away from the person to trade.
+*/
+ MSG_TOO_FAR_TO_DEAL = 0x46,
+/*20040804 to latest
+해당 캐릭터가 없습니다.
+The Character is not currently online or does not exist.
+*/
+ MSG_CHARACTER_IS_NOT_EXIST = 0x47,
+/*20040804 to latest
+다른캐릭터와 교환중입니다.
+The person is in another deal.
+*/
+ MSG_CHARACTER_IS_DEALING = 0x48,
+/*20040804 to latest
+상태캐릭터 중량초과로 올려놓을수가 없습니다.
+*/
+ MSG_CHARACTER_IS_OVER_WEIGHT = 0x49,
+/*20040804 to latest
+거래가 취소 되었습니다.
+The deal has been canceled.
+*/
+ MSG_DEAL_IS_CANCELED = 0x4a,
+/*20040804 to latest
+아이템 교환이 잘 되었습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SUCCESS = 0x4b,
+/*20040804 to latest
+아이템 교환이 실패 하였습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAILED = 0x4c,
+/*20040804 to latest
+파티가 만들어졌습니다.
+Party has successfully been organized.
+*/
+ MSG_PARTY_MAKE_SUCCEED = 0x4d,
+/*20040804 to latest
+같은 파티이름이 있습니다.
+That Party Name already exists.
+*/
+ MSG_SAME_PARTY_NAME = 0x4e,
+/*20040804 to latest
+이미 파티에 속해있습니다.
+The Character is already in a party.
+*/
+ MSG_YOU_ARE_ALREADY_IN_PARTY = 0x4f,
+/*20040804 to latest
+다른파티에 가입되어 있습니다.
+The Character already joined another party.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_PARTY = 0x50,
+/*20040804 to latest
+파티가입을 거부했습니다.
+Request for party rejected.
+*/
+ MSG_CHARACTER_REJECT_JOIN = 0x51,
+/*20040804 to latest
+파티가입을 수락했습니다.
+Request for party accepted.
+*/
+ MSG_CHARACTER_ACCEPT_JOIN = 0x52,
+/*20040804 to latest
+파티정원을 초과했습니다.
+Party Capacity exceeded.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_PARTY = 0x53,
+/*20040804 to latest
+파티에서 탈퇴하였습니다.
+You left the party.
+*/
+ MSG_YOU_LEAVE_FROM_PARTY = 0x54,
+/*20040804 to latest
+전체에게 보냄
+Send to All
+*/
+ MSG_SEND_TO_ALL = 0x55,
+/*20040804 to latest
+파티에게 보냄
+Send to Party
+*/
+ MSG_SEND_TO_PARTY = 0x56,
+/*20040804 to latest
+님과의 거래요청
+Request a deal with %s
+*/
+ MSG_REQ_DEAL_WITH = 0x57,
+/*20040804 to latest
+님 파티에 가입요청
+Ask %s to join your party
+*/
+ MSG_REQ_JOIN_PARTY = 0x58,
+/*20040804 to latest
+비공개 :
+Pri:
+*/
+ MSG_ROOM_PRIVATE = 0x59,
+/*20040804 to latest
+공개 :
+Pub:
+*/
+ MSG_ROOM_PUBLIC = 0x5a,
+/*20040804 to latest
+마지막 체크지점부터 시작하려면 '재시작'을 캐릭터 선택으로 돌아가려면 '종료'를 눌러주세요.
+Click ''Restart'' to go back to your save point or click ''Exit'' to select another character.
+*/
+ MSG_RESTART_MSG = 0x5b,
+/*20040804 to latest
+원하는 거래를 선택하세요.
+Please select a Deal Type.
+*/
+ MSG_SELECT_DEAL_TYPE = 0x5c,
+/*20040804 to latest
+님이 거래를 요청했습니다.
+ requests a deal.
+*/
+ MSG_SUGGEST_DEAL = 0x5d,
+/*20040804 to latest
+ 파티에서 초청 메시지가 왔습니다. 합류하겠습니까?
+ Party has sent you an invitation. Would you like to join?
+*/
+ MSG_SUGGEST_JOIN_PARTY = 0x5e,
+/*20040804 to latest
+명령이 틀렸습니다.
+Invalid Command
+*/
+ MSG_INVALID_COMMAND = 0x5f,
+/*20040804 to latest
+탈퇴하기
+Leave party
+*/
+ MSG_LEAVE_PARTY = 0x60,
+/*20040804 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL = 0x61,
+/*20040804 to latest
+쪽지보내기
+Send Message
+*/
+ MSG_MSG = 0x62,
+/*20040804 to latest
+1:1 대화
+1:1 Chat
+*/
+ MSG_1ON1 = 0x63,
+/*20040804 to latest
+정보
+Information
+*/
+ MSG_CHARACTER_INFO = 0x64,
+/*20040804 to latest
+파티설정
+Party Setup
+*/
+ MSG_PARTY_SETTING = 0x65,
+/*20040804 to latest
+친구
+Friend
+*/
+ MSG_FRIEND = 0x66,
+/*20040804 to latest
+파티
+Party
+*/
+ MSG_PARTY = 0x67,
+/*20040804 to latest
+장착아이템
+Equipment
+*/
+ MSG_EQUIPED_ITEM = 0x68,
+/*20040804 to latest
+스테이터스
+Status
+*/
+ MSG_STATUS_ = 0x69,
+/*20040804 to latest
+소지아이템
+Inventory
+*/
+ MSG_ITEM = 0x6a,
+/*20040804 to latest
+/결성 [파티이름] : 파티결성 /탈퇴 : 파티탈퇴
+/organize ''Party Name'' To organize a party. Type /leave To leave a Party.
+*/
+ MSG_EXPLAIN_PARTY = 0x6b,
+/*20040804 to latest
+자신이 파티리더일때 캐릭터를 오른버튼으로 클릭하면 파티에 가입요청하기 메뉴가 뜹니다.
+If you are the party master, you can invite someone into your party by right-clicking on a Character.
+*/
+ MSG_EXPLAIN_TIP3 = 0x6c,
+/*20040804 to latest
+회복
+Consumables
+*/
+ MSG_RESTORE = 0x6d,
+/*20040804 to latest
+공격
+Attack
+*/
+ MSG_ATTACK = 0x6e,
+/*20040804 to latest
+보조
+Support
+*/
+ MSG_SUPPORT = 0x6f,
+/*20040804 to latest
+전체
+All
+*/
+ MSG_ALL = 0x70,
+/*20040804 to latest
+무기
+Weapons
+*/
+ MSG_WEAPON = 0x71,
+/*20040804 to latest
+방어
+Defense
+*/
+ MSG_DEFENCE = 0x72,
+/*20040804 to latest
+수
+Water
+*/
+ MSG_WATER = 0x73,
+/*20040804 to latest
+지
+Earth
+*/
+ MSG_EARTH = 0x74,
+/*20040804 to latest
+화
+Fire
+*/
+ MSG_FIRE = 0x75,
+/*20040804 to latest
+풍
+Wind
+*/
+ MSG_WIND = 0x76,
+/*20040804 to latest
+같은종류의 장비아이템은 한번에 한개만 살 수 있습니다.
+Please avoid buying 2 of the same items at one time.
+*/
+ MSG_EQUIPITEM_OLNY_ONE = 0x77,
+/*20040804 to latest
+창모드에서 실행 할때는 16비트 컬러로 맞춰주세요.
+Please change your desktop Color Depth to 16-bit when running Ragnarok in windowed mode.
+*/
+ MSG_ONLY_16BIT_WHEN_WINDOWMODE = 0x78,
+/*20040804 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_PLEASE_BE_PATIENT = 0x79,
+/*20040804 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_WAITING_RESPONSE_FROM_SERVER = 0x7a,
+/*20040804 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_MAKING_CHARACTER = 0x7b,
+/*20040804 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_DELETING_CHARACTER = 0x7c,
+/*20040804 to latest
+방 만들기
+Make a Room
+*/
+ MSG_MAKING_ROOM = 0x7d,
+/*20040804 to latest
+방셋팅 바꾸기
+Room Setup
+*/
+ MSG_CHANGE_ROOM_SETTING = 0x7e,
+/*20040804 to latest
+강퇴시키기
+Kick Character Out
+*/
+ MSG_BAN = 0x7f,
+/*20040804 to latest
+방장권한 주기
+Give Master Authority
+*/
+ MSG_GIVE_GIVE_ROOM_POWER = 0x80,
+/*20040804 to latest
+정보보기
+View Information
+*/
+ MSG_SEE_INFORMATION_OF_CHARACTER = 0x81,
+/*20040804 to latest
+대화방
+Chat Room
+*/
+ MSG_CHAT_ROOM = 0x82,
+/*20040804 to latest
+명
+Ppl
+*/
+ MSG_COUNT_UNIT_OF_PEOPLE = 0x83,
+/*20040804 to latest
+/앉기 or /sit : 앉기. 앉아있을때 서기
+/sit: Sit command. If you are sitting, you will stand instead.
+*/
+ MSG_EXPLAIN_SIT = 0x84,
+/*20040804 to latest
+/서기 or /stand : 서기. 서있을때 앉기
+/stand: Stand command. If you are standing, you will sit instead.
+*/
+ MSG_EXPLAIN_STAND = 0x85,
+/*20040804 to latest
+/채팅방 or /chat : 채팅방 만들기창 띄우기
+/chat: Creates a Chat Room
+*/
+ MSG_EXPLAIN_MAKE_CHAT = 0x86,
+/*20040804 to latest
+/q : 채팅방 나가기.
+/q: Leaves a Chat Room
+*/
+ MSG_EXPLAIN_EXIT_CHAT_ROOM = 0x87,
+/*20040804 to latest
+/거래 [캐릭터이름] or /교환 [캐릭터이름] or /deal [캐릭터이름] : 해당 캐릭터와 거래요청
+/deal ''Character Name'' Requests a deal with a character
+*/
+ MSG_EXPLAIN_DEAL = 0x88,
+/*20040804 to latest
+/결성 [파티이름] or /organize [파티이름] : 파티결성
+/organize ''Party Name'' Organizes a party
+*/
+ MSG_EXPLAIN_ORGANIZE_PARTY = 0x89,
+/*20040804 to latest
+/탈퇴 or /leave : 파티 탈퇴
+/leave: Leaves a party
+*/
+ MSG_EXPLAIN_LEAVE_PARTY = 0x8a,
+/*20040804 to latest
+/제명 [캐릭터이름] or /expel [캐릭터이름] : 해당캐릭터를 파티에서 제명시킴
+/expel ''Character Name'' kicks a Character out of your party
+*/
+ MSG_EXPLAIN_EXPEL_PARTY_MEMBER = 0x8b,
+/*20040804 to latest
+[Alt] + [End] : 플레이어 hp/sp 게이지 On Off
+[Alt] + [End]: Turns HP/SP Bar On or Off
+*/
+ MSG_EXPLAIN_TIP4 = 0x8c,
+/*20040804 to latest
+[Alt] + [Home] : 지면 커서 표시 On Off
+[Alt] + [Home]: Turns Ground Cursor On or Off
+*/
+ MSG_EXPLAIN_TIP5 = 0x8d,
+/*20040804 to latest
+[Insert] : 앉기 서기
+[Insert]: Makes you sit or stand. (Hotkey to toggle between /sit and /stand)
+*/
+ MSG_EXPLAIN_TIP6 = 0x8e,
+/*20040804 to latest
+MVP가 되셨습니다!! MVP 아이템은
+Congratulations! You are the MVP! Your reward item is
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM = 0x8f,
+/*20040804 to latest
+ !!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM2 = 0x90,
+/*20040804 to latest
+MVP가 되셨습니다!! 특별경험치
+Congratulations! You are the MVP! Your reward EXP Points are
+*/
+ MSG_YOU_RECEIVE_MVP_EXP = 0x91,
+/*20040804 to latest
+ 획득!!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_EXP2 = 0x92,
+/*20040804 to latest
+MVP가 되셨습니다만 무게초과로 MVP 아이템을 가질 수 없었습니다!!
+You are the MVP, but you can't take the reward because you are over your weight limit.
+*/
+ MSG_YOU_THROW_MVPITEM = 0x93,
+/*20040804 to latest
+ 없는 캐릭터 이름 입니다.
+There is no such character name or the user is offline.
+*/
+ MSG_NOT_EXIST_CHARACTER = 0x94,
+/*20040804 to latest
+ 수신 거부 상태입니다.
+ doesn't want to receive your messages.
+*/
+ MSG_NO_RECEIVE_MODE = 0x95,
+/*20040804 to latest
+ 모든 캐릭터에 대해 수신 거부 상태 입니다.
+ is not in the mood to talk with anyone.
+*/
+ MSG_NO_RECEIVE_MODE_FOR_ALL = 0x96,
+/*20040804 to latest
+캐릭터 접속끊기 성공.
+Killed/Disconnected User.
+*/
+ MSG_SUCCESS_DISCONNECT_CHARACTER = 0x97,
+/*20040804 to latest
+캐릭터 접속끊기 실패.
+Kill has failed.
+*/
+ MSG_FAIL_DISCONNECT_CHARACTER = 0x98,
+/*20040804 to latest
+%s %d 개 획득
+You got %s (%d).
+*/
+ MSG_GET_ITEM = 0x99,
+/*20040804 to latest
+[Alt] + [=] : 알파벳 간격이 넓어졌을때 되돌리기.
+[Alt] + [=]: Fix the interval error between letters.
+*/
+ MSG_EXPLAIN_TIP7 = 0x9a,
+/*20040804 to latest
+[F10] : 채팅창 크기조정 [Alt] + [F10] : 채팅창 On Off
+[F10]: To toggle Chat Window size; [Alt] + [F10]: Toggle Chat Window On or Off
+*/
+ MSG_EXPLAIN_TIP8 = 0x9b,
+/*20040804 to latest
+귓속말 하는법 : 채팅창 왼쪽 입력란에 캐릭터이름을 입력하고 오른쪽 입력란에 말을 입력하면 됩니다. TAB키로 두입력란 사이로 커서를 이동할 수 있습니다.
+How to Whisper: Enter a Character's Name on the left side of chat window and type your message on the right side. The Tab key helps you move between these boxes.
+*/
+ MSG_EXPLAIN_TIP9 = 0x9c,
+/*20040804 to latest
+/! /? /기쁨 /하트 /땀 /아하 /짜증 /화 /돈 /... /가위 /바위 /보 : Alt + (1~9) Ctrl + (-=\) 에 대응되는 명령어 입니다.
+/!,/?,/ho,/lv,/lv2,/swt,/ic,/an,/ag,/$,/….,/thx,/wah,/sry,/heh,/swt2,/hmm,/no1,/??,/omg,/oh,/X,/hp,/go,/sob,/gg,/kis,/kis2,/pif,/ok: Emotion icons corresponding to Alt + (1~9) Ctrl + (-=\\)
+*/
+ MSG_EXPLAIN_TIP10 = 0x9d,
+/*20040804 to latest
+파티원에게 말하는법 : 말의 제일앞에 '%'를 붙이면 파티원에게 말이 갑니다. (예: "%안녕")
+How to Speak to Party: Add % in front of every message.(Example: \%Hello\)
+*/
+ MSG_EXPLAIN_TIP11 = 0x9e,
+/*20040804 to latest
+스킬레벨이 부족합니다. 교환 불능.
+You haven't learned enough Basic Skills to Trade.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE1 = 0x9f,
+/*20040804 to latest
+스킬레벨이 부족합니다. 이모션 불능.
+You haven't learned enough Basic Skills to use Emotion icons.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE2 = 0xa0,
+/*20040804 to latest
+스킬레벨이 부족합니다. 앉기 불능.
+You haven't learned enough Basic Skills to Sit.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE3 = 0xa1,
+/*20040804 to latest
+스킬레벨이 부족합니다. 채팅방만들기 불능.
+You haven't learned enough Basic Skills to create a chat room.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE4 = 0xa2,
+/*20040804 to latest
+스킬레벨이 부족합니다. 파티만들기 불능
+You haven't learned enough Basic Skills to Party.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5 = 0xa3,
+/*20040804 to latest
+스킬레벨이 부족합니다. 외치기 불능
+You haven't learned enough skills to Shout.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE6 = 0xa4,
+/*20040804 to latest
+스킬레벨이 부족합니다. pk 불능
+You haven't learned enough skills for Pking.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE7 = 0xa5,
+/*20040804 to latest
+사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY = 0xa6,
+/*20040804 to latest
+아이템 상점
+Item Shop
+*/
+ MSG_ITEM_STORE = 0xa7,
+/*20040804 to latest
+팔고자하는 품목
+Selling Items
+*/
+ MSG_ITEMS_FOR_SELL = 0xa8,
+/*20040804 to latest
+보관아이템
+Storage
+*/
+ MSG_ITEMS_THAT_IS_STORED = 0xa9,
+/*20040804 to latest
+ 장비가 장착 되었습니다.
+ is put on.
+*/
+ MSG_ITEM_IS_EQUIPED = 0xaa,
+/*20040804 to latest
+ 장비가 해제 되었습니다.
+ is taken off.
+*/
+ MSG_ITEM_IS_REMOVED = 0xab,
+/*20040804 to latest
+귓말리스트에 이름넣기
+To add names on the Whispering List
+*/
+ MSG_ADD_TO_WHISPER_CHAR_LIST = 0xac,
+/*20040804 to latest
+스크린샷 찍는법 : [Print Screen]키나 [Scroll Lock]키를 누르면 됩니다.
+How to Take Screen Shots: Press [Print Screen] or [Scroll Lock]
+*/
+ MSG_EXPLAIN_TIP12 = 0xad,
+/*20040804 to latest
+오늘의 팁
+Tip of the Day
+*/
+ MSG_TIPOFTHEDAY = 0xae,
+/*20040804 to latest
+^3850a0알고 계셨습니까... ^000000 //^709fed
+^3850a0Did you know...?^709fed
+*/
+ MSG_DIDYOUKNOW = 0xaf,
+/*20040804 to latest
+시작할때 열기
+Display at startup
+*/
+ MSG_SHOWTIPSATSTARTUP = 0xb0,
+/*20040804 to latest
+/tip : 오늘의팁 열기
+/tip: Opens ''Tip of the Day''
+*/
+ MSG_EXPLAIN_OPENTIP = 0xb1,
+/*20040804 to latest
+현재 접속자 %d명
+There are %d Players Currently Connected.
+*/
+ MSG_NUMPEOPLE = 0xb2,
+/*20040804 to latest
+(%s)님이 입장 하였습니다.
+(%s) has entered.
+*/
+ MSG_USERGETINTHEROOM = 0xb3,
+/*20040804 to latest
+(%s)님이 퇴장 하였습니다.
+(%s) has left.
+*/
+ MSG_USERGETOUTOFTHEROOM = 0xb4,
+/*20040804 to latest
+(%s)님이 강제 퇴장 되었습니다.
+(%s) was kicked out.
+*/
+ MSG_USERGETOUTOFTHEROOMBYFORCE = 0xb5,
+/*20040804 to latest
+ %d 개
+%d ea.
+*/
+ MSG_EA = 0xb6,
+/*20040804 to latest
+%s : %d 개
+%s: %d ea.
+*/
+ MSG_EA2 = 0xb7,
+/*20040804 to latest
+%s %s : %d 개
+%s %s: %d
+*/
+ MSG_EA3 = 0xb8,
+/*20040804 to latest
+팔 수 있는 품목
+Available Items to sell
+*/
+ MSG_ITEMSYOUCANSELL = 0xb9,
+/*20040804 to latest
+상점에서 파는 품목
+Shop Items
+*/
+ MSG_SHOPITEMS = 0xba,
+/*20040804 to latest
+알 수 없는곳
+Unknown Area
+*/
+ MSG_NOWHERE = 0xbb,
+/*20040804 to latest
+서버와 언어가 맞지 않습니다.
+Your Client language doesn't match the Server language.
+*/
+ MSG_CLIENTTYPEMISMATCH = 0xbc,
+/*20040804 to latest
+아이템을 버릴려면 장비창을 닫으세요.
+Please move your equipment to the inventory. And close the equipment window.
+*/
+ MSG_CLOSEEQUIPWND = 0xbd,
+/*20040804 to latest
+영어만 됩니다.
+This server provides English Text Characters Only.
+*/
+ MSG_ENGLISHONLY = 0xbe,
+/*20040804 to latest
+지금은 지원되지 않습니다.
+This is not implemented yet.
+*/
+ MSG_NOTSUPPORTEDYET = 0xbf,
+/*20040804 to latest
+귓말 리스트가 없습니다.
+No Whisper List.
+*/
+ MSG_NOWHISPERLIST = 0xc0,
+/*20040804 to latest
+ 에게 귓말거부상태로됨
+: Whispering Blocked.
+*/
+ MSG_WHISPERIGNORESUCCESS = 0xc1,
+/*20040804 to latest
+ 에게 귓말거부 요청실패함
+: Whispering Block has failed.
+*/
+ MSG_WHISPERIGNOREFAILED1 = 0xc2,
+/*20040804 to latest
+ 에게 귓말거부 요청실패함 (인원초과)
+: Whispering Block has failed. Block List is full.
+*/
+ MSG_WHISPERIGNOREFAILED2 = 0xc3,
+/*20040804 to latest
+ 에게 귓말가능상태로됨
+: Whispering accepted.
+*/
+ MSG_WHISPERNOIGNORESUCCESS = 0xc4,
+/*20040804 to latest
+ 에게 귓말가능 요청실패함
+: Command has failed.
+*/
+ MSG_WHISPERNOIGNOREFAILED1 = 0xc5,
+/*20040804 to latest
+ 에게 귓말가능 요청실패함 (인원초과)
+: Command has failed. Block List is full.
+*/
+ MSG_WHISPERNOIGNOREFAILED2 = 0xc6,
+/*20040804 to latest
+이름의 처음과 마지막에는 공백문자를 사용할 수 없습니다.
+You cannot put a space at the beginning or end of a name.
+*/
+ MSG_NO_SPACE_IN_NAME = 0xc7,
+/*20040804 to latest
+비공개
+Private
+*/
+ MSG_ROOM_PRIVATE2 = 0xc8,
+/*20040804 to latest
+공개
+Public
+*/
+ MSG_ROOM_PUBLIC2 = 0xc9,
+/*20040804 to latest
+SP가 부족합니다.
+Not Enough SP
+*/
+ MSG_USESKILL_FAIL_SP_INSUFFICIENT = 0xca,
+/*20040804 to latest
+HP가 부족합니다.
+Not Enough HP
+*/
+ MSG_USESKILL_FAIL_HP_INSUFFICIENT = 0xcb,
+/*20040804 to latest
+스킬사용 실패.
+Skill has failed.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE8 = 0xcc,
+/*20040804 to latest
+훔치기 실패.
+Steal has failed.
+*/
+ MSG_FAIL_STEAL = 0xcd,
+/*20040804 to latest
+교환창
+Trade
+*/
+ MSG_EXCHANGE = 0xce,
+/*20040804 to latest
+독걸기 실패.
+Envenom skill has failed.
+*/
+ MSG_FAIL_POISON = 0xcf,
+/*20040804 to latest
+이 아이디로는 이 서버에 접속할 수 없습니다.
+You cannot use this ID on this server.
+*/
+ MSG_ID_MISMATCH = 0xd0,
+/*20040804 to latest
+스피드가 향상되었습니다.
+Your Speed has increased.
+*/
+ MSG_SPEEDUP = 0xd1,
+/*20040804 to latest
+스피드가 감소되었습니다.
+Your Speed has decreased.
+*/
+ MSG_SPEEDDOWN = 0xd2,
+/*20040804 to latest
+/기억 : 워프할 장소 기억(워프 스킬이 있는경우)
+/memo: To memorize a place as Warp Point (If you are an Acolyte Class character)
+*/
+ MSG_EXPLAIN_TIP13 = 0xd3,
+/*20040804 to latest
+임의의 위치
+Random Area
+*/
+ MSG_RANDOM_POS = 0xd4,
+/*20040804 to latest
+워프 할 위치를 선택하세요.
+Select an Area to Warp
+*/
+ MSG_SELECTWHERETOWARP = 0xd5,
+/*20040804 to latest
+스킬레벨이 부족합니다.
+Skill Level is not high enough
+*/
+ MSG_NOTENOUGHSKILLLEVEL = 0xd6,
+/*20040804 to latest
+저장된 워프할 장소가 없습니다.
+There are no memorized locations (Memo Points).
+*/
+ MSG_NO_STORED_PLACE_TO_WARP = 0xd7,
+/*20040804 to latest
+워프 관련 스킬이 없습니다.
+You haven't learned Warp.
+*/
+ MSG_NOWARPSKILL = 0xd8,
+/*20040804 to latest
+워프 장소로 저장됨.
+Saved location as a Memo Point for Warp Skill.
+*/
+ MSG_WARPPOINTSTORED = 0xd9,
+/*20040804 to latest
+취소
+Cancel
+*/
+ MSG_CANCEL = 0xda,
+/*20040804 to latest
+스킬 사용후 시간이 충분히 지나지 않았습니다.
+There is a Delay after using a Skill.
+*/
+ MSG_SKILLINTERVAL = 0xdb,
+/*20040804 to latest
+한번에 가질 수 있는 아이템 종류수를 초과하여 아이템을 가질 수 없습니다.
+You can't have this item because you will exceed the weight limit.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_COUNT = 0xdc,
+/*20040804 to latest
+아이템 최대 종류수를 초과 하였습니다.
+Out of the maximum capacity
+*/
+ MSG_INSUFFICIENT_OVER_COUNT = 0xdd,
+/*20040804 to latest
+수레아이템
+Cart Items
+*/
+ MSG_MERCHANTITEM = 0xde,
+/*20040804 to latest
+수레 벗기
+Take off Cart
+*/
+ MSG_CARTOFF = 0xdf,
+/*20040804 to latest
+노점 개설
+Opening a stall
+*/
+ MSG_MERCHANTSHOPMAKER = 0xe0,
+/*20040804 to 20041207
+노점이름를 입력하세요.
+20041213 to latest
+노점이름을 입력하세요.
+Please Name your Shop.
+*/
+ MSG_ENTER_SHOP_TITLE = 0xe1,
+/*20040804 to latest
+나의 노점
+My Shop
+*/
+ MSG_ITEM_MY_STORE = 0xe2,
+/*20040804 to latest
+상인 아이템 상점
+Merchant Shop
+*/
+ MSG_ITEM_MERCHANT_STORE = 0xe3,
+/*20040804 to latest
+상인에게 사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY_FROM_MERCHANT = 0xe4,
+/*20040804 to latest
+%s 사기 실패 %s
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT = 0xe5,
+/*20040804 to latest
+재고 부족.
+Out of Stock
+*/
+ MSG_INSUFFICIENT_STOCK = 0xe6,
+/*20040804 to latest
+%s %d 개 팔림.
+%s %d sold.
+*/
+ MSG_ITEM_IS_SOLD = 0xe7,
+/*20040804 to latest
+노점에서 팔 수 있는 아이템
+Available Items for Vending
+*/
+ MSG_MERCHANTMIRRORITEM = 0xe8,
+/*20040804 to latest
+돈이 부족해서 스킬을 쓸 수 없습니다.
+*/
+ MSG_SKILL_FAIL_MONEY = 0xe9,
+/*20040804 to latest
+사용할 대상을 선택하세요
+Select a Target.
+*/
+ MSG_SELECTTARGET = 0xea,
+/*20040804 to latest
+/pk on : pk On /pk off : pk Off
+/pk on: Turns PK On. /pk off: Turns PK Off.
+*/
+ MSG_EXPLAIN_TIP14 = 0xeb,
+/*20040804 to latest
+노점
+Shop
+*/
+ MSG_STREETSHOP = 0xec,
+/*20040804 to latest
+수레 아이템 [Alt+W]
+Cart Items [Alt+W]
+*/
+ MSG_OPENCARTWINDOW = 0xed,
+/*20040804 to latest
+기본정보
+Basic Information
+*/
+ MSG_BASICINFOWND = 0xee,
+/*20040804 to latest
+이무기로는 이스킬을 사용할수 없습니다.
+The skill cannot be used with this weapon.
+*/
+ MSG_USESKILL_FAIL_NOT_SUITABLE_WEAPON = 0xef,
+/*20040804 to latest
+%s 사기 실패 재고 부족 현재 재고 %d 개.
+Buying %s has been failed. Out of Stock. Current Stock %d.
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT_NO_STOCK = 0xf0,
+/*20040804 to latest
+서버와 동기화가 틀려 연결이 끊어졌습니다.
+You've been disconnected due to a time gap between you and the server.
+*/
+ MSG_SPEEDHACK = 0xf1,
+/*20040804 to latest
+화살을 장착하세요
+Please equip the proper ammunition first.
+*/
+ MSG_ERR_ATTACK_ARROW = 0xf2,
+/*20040804 to latest
+중량과다로 공격이나 스킬을 사용할 수 없습니다.
+You can't attack or use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_ATTACK_WEIGHT = 0xf3,
+/*20040804 to latest
+중량과다로 스킬을 사용할 수 없습니다.
+You can't use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_SKILL_WEIGHT = 0xf4,
+/*20040804 to latest
+화살이 장착되었습니다.
+Ammunition has been equipped.
+*/
+ MSG_MSG_ARROW_EQUIPMENT_SUCCESS = 0xf5,
+/*20040804 to latest
+레드젬스톤이 필요합니다.
+Red Gemstone required.
+*/
+ MSG_NEED_REDJAMSTONE = 0xf6,
+/*20040804 to latest
+블루젬스톤이 필요합니다.
+Blue Gemstone required.
+*/
+ MSG_NEED_BLUEJAMSTONE = 0xf7,
+/*20040804 to latest
+힘 파라메터
+Strength
+*/
+ MSG_DESC_STR = 0xf8,
+/*20040804 to latest
+민첩성 파라메터
+Agility
+*/
+ MSG_DESC_AGI = 0xf9,
+/*20040804 to latest
+체력 파라메터
+Vitality
+*/
+ MSG_DESC_VIT = 0xfa,
+/*20040804 to latest
+지력 파라메터
+Intelligence
+*/
+ MSG_DESC_INT = 0xfb,
+/*20040804 to latest
+손재주 파라메터
+Dexterity
+*/
+ MSG_DESC_DEX = 0xfc,
+/*20040804 to latest
+운 파라메터
+Luck
+*/
+ MSG_DESC_LUK = 0xfd,
+/*20040804 to latest
+공격력
+Hit Point
+*/
+ MSG_DESC_ATK = 0xfe,
+/*20040804 to latest
+방어력
+Defence Rate
+*/
+ MSG_DESC_DEF = 0xff,
+/*20040804 to latest
+명중률
+Accuracy
+*/
+ MSG_DESC_HIT = 0x100,
+/*20040804 to latest
+필살공격률
+Critical Attack
+*/
+ MSG_DESC_CRI = 0x101,
+/*20040804 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_DESC_GUILD = 0x102,
+/*20040804 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_DESC_POINT = 0x103,
+/*20040804 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_DESC_MATK = 0x104,
+/*20040804 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_DESC_MDEF = 0x105,
+/*20040804 to latest
+회피율
+Dodge
+*/
+ MSG_DESC_FLEE = 0x106,
+/*20040804 to latest
+공격스피드
+Attack Speed
+*/
+ MSG_DESC_ASPD = 0x107,
+/*20040804 to latest
+지역당 수용인원 초과로 접속할 수 없습니다.
+Server is jammed due to over population. Please try again shortly.
+*/
+ MSG_PC_OVERFLOW = 0x108,
+/*20040804 to latest
+옵션
+Option
+*/
+ MSG_OPTIONWND = 0x109,
+/*20040804 to latest
+E-MAIL 인증이 되지않았거나 블럭된 계정입니다.
+Account ID blocked by the Game Master Team.
+*/
+ MSG_ID_EMAIL_CONFIRM_NEEDED = 0x10a,
+/*20040804 to latest
+비밀번호가 틀립니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_LOGIN_PASSWORD = 0x10b,
+/*20040804 to latest
+머리모양 선택
+Choose Hairstyle
+*/
+ MSG_SELECT_HAIR_STYLE = 0x10c,
+/*20040804 to latest
+공격력
+Hit Point
+*/
+ MSG_ATK = 0x10d,
+/*20040804 to latest
+방어력
+Defence Rate
+*/
+ MSG_DEF = 0x10e,
+/*20040804 to latest
+공격스냅 On
+Attack Snap On
+*/
+ MSG_ATTACK_SNAP_ON = 0x10f,
+/*20040804 to latest
+공격스냅 Off
+Attack Snap Off
+*/
+ MSG_ATTACK_SNAP_OFF = 0x110,
+/*20040804 to latest
+스킬스냅 On
+Skill Snap On
+*/
+ MSG_SKILL_SNAP_ON = 0x111,
+/*20040804 to latest
+스킬스냅 Off
+Skill Snap Off
+*/
+ MSG_SKILL_SNAP_OFF = 0x112,
+/*20040804 to latest
+/스냅 or /snap: 몬스터 공격시 스냅 On Off /스킬스냅 or /skillsnap: 스킬로 몬스터 공격시 스냅 On Off /아이템스냅 or /itemsnap: 아이템 주울때 스냅 On Off
+/snap: Turns snap On | Off for fights, /skillsnap: Turns snap On | Off for skills. /itemsnap: Turns snap On | Off for items on the grounds.
+*/
+ MSG_EXPLAIN_SNAP = 0x113,
+/*20040804 to latest
+아이템스냅 On
+Item Snap On
+*/
+ MSG_ITEM_SNAP_ON = 0x114,
+/*20040804 to latest
+아이템스냅 Off
+Item Snap Off
+*/
+ MSG_ITEM_SNAP_OFF = 0x115,
+/*20040804 to latest
+스냅
+Snap
+*/
+ MSG_SNAP = 0x116,
+/*20040804 to latest
+한가지 아이템을 3만개 이상 가질수 없습니다.
+You cannot carry more than 30,000 of one kind of item.
+*/
+ MSG_CANT_GET_ITEM_OVERCOUNT_ONEITEM = 0x117,
+/*20040804 to latest
+레벨 30이상의 캐릭터는 삭제할 수 없습니다. 삭제를 원하시면 관계자에게 문의 하세요.
+You cannot delete a Character with a level greater than 30. If you want to delete the character please contact a Game Master.
+*/
+ MSG_CANT_DELETE_CHARACTER_OVER_30_LEVEL = 0x118,
+/*20040804 to latest
+이이템 교환중에는 아이템을 사고 팔 수 없습니다.
+*/
+ MSG_FAIL_BUY_ITEM_ITEM_EXCHANGING = 0x119,
+/*20040804 to latest
+상점명
+Shop Name
+*/
+ MSG_STALL_NAME = 0x11a,
+/*20040804 to latest
+스킬목록
+Skill Tree
+*/
+ MSG_SKILLLIST = 0x11b,
+/*20040804 to latest
+스킬포인트 : %d
+Skill Point: %d
+*/
+ MSG_SKILLPOINT = 0x11c,
+/*20040804 to latest
+스킬사용 실패
+Skill has failed.
+*/
+ MSG_USESKILL_FAIL = 0x11d,
+/*20040804 to latest
+패시브
+Passive
+*/
+ MSG_PASSIVE = 0x11e,
+/*20040804 to latest
+각자 취득
+Individual
+*/
+ MSG_EXPDIV1 = 0x11f,
+/*20040804 to latest
+균등하게 분배
+Shared
+*/
+ MSG_EXPDIV2 = 0x120,
+/*20040804 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMCOLLECT1 = 0x121,
+/*20040804 to latest
+파티 전체 공유
+Party Share
+*/
+ MSG_ITEMCOLLECT2 = 0x122,
+/*20040804 to latest
+파티 설정
+Party Setup
+*/
+ MSG_PARTYSETTING = 0x123,
+/*20040804 to latest
+경험치 분배방식
+How to share EXP
+*/
+ MSG_HOWEXPDIV = 0x124,
+/*20040804 to latest
+아이템 수집방식
+How to share Items
+*/
+ MSG_HOWITEMCOLLECT = 0x125,
+/*20040804 to latest
+파티 리더만 설정할 수 있습니다.
+Only the Party Leader can change this setting.
+*/
+ MSG_ONLY_PARTYMASTER = 0x126,
+/*20040804 to latest
+아이템 갯수 안물어보기
+Toggle Item Amount.
+*/
+ MSG_NOQUESTION_ITEMCOUNT = 0x127,
+/*20040804 to latest
+^ff0000%d^000000 초 후에 캐릭터가 지워집니다. 취소 하려면 취소 버튼을 누르세요.
+Character will be deleted after ^ff0000%d^000000 seconds. Press Cancel to quit.
+*/
+ MSG_CHARARATER_DELETE_COUNT = 0x128,
+/*20040804 to latest
+교환할 수 있는 최대 아이템 갯수는 10가지 입니다.
+You cannot trade more than 10 types of items per trade.
+*/
+ MSG_MAXEXCHANGE_IS_10_KIND = 0x129,
+/*20040804 to latest
+이서버를 이용할 수 없는 나이입니다.
+You are underaged.
+*/
+ MSG_LIMIT_AGE = 0x12a,
+/*20040804 to latest
+이메일 주소를 입력하세요.
+Please enter the deletion password.
+*/
+ MSG_ENTER_EMAIL = 0x12b,
+/*20040804 to latest
+이메일 주소 입력하기
+E-mail Address (Case Sensitive).
+*/
+ MSG_ENTER_EMAIL_TOOLTIP = 0x12c,
+/*20040804 to latest
+이메일 주소가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect e-mail address.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_EMAIL = 0x12d,
+/*20040804 to 20070703
+주민등록번호 뒷자리를 입력하세요.
+20070618 to 20070622
+비밀번호를 한 번 더 입력해 주시기 바랍니다.
+20070704 to latest
+계정 비밀번호를 입력하세요.
+Enter Second Serial Cord of your Social Security number.
+*/
+ MSG_ENTER_PEOPLE_REG_NUMBER = 0x12e,
+/*20040804 to 20070703
+주민등록번호 뒷자리가 틀려서 캐릭터가 삭제 되지 않았습니다.
+20070618 to 20070622
+비밀번호가 맞지 않아 캐릭터가 삭제 되지 않았습니다.
+20070704 to latest
+비밀번호가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect SSN.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_PEOPLE_REG_NUMBER = 0x12f,
+/*20040804 to latest
+한번에 15가지 이상의 아이템을 팔 수 없습니다.
+You can't sell more than 15 types of Items at one time.
+*/
+ MSG_CANT_SELL_OVER_15 = 0x130,
+/*20040804 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_UNDER_AGE = 0x131,
+/*20040804 to latest
+무게가 50 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+HP/SP will not be restored when your carried weight is over 50% of the Weight Limit.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT = 0x132,
+/*20040804 to latest
+무게가 90 퍼센트 이상일때는 공격과 스킬을 사용할 수 없습니다.
+You can't use Skills or Attack while your carried weight is over 90% of your Weight Limit.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT = 0x133,
+/*20040804 to latest
+HP SP가 자연적으로 회복이 가능한 상태가 되었습니다.
+Your HP/SP are now being restored naturally.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT_RELEASED = 0x134,
+/*20040804 to latest
+공격과 스킬이 가능한 상태가 되었습니다.
+Attack and Skills are now available.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT_RELEASED = 0x135,
+/*20040804 to latest
+서버 점검중입니다.
+Your Game's Exe File is not the latest version.
+*/
+ MSG_INVALID_VERSION = 0x136,
+/*20040804 to latest
+아이템이 모두 팔렸습니다.
+Items are sold out.
+*/
+ MSG_ITEM_IS_SOLD_OUT = 0x137,
+/*20040804 to latest
+채팅내용 파일로 저장하기
+Save Chat as Text File
+*/
+ MSG_WRITE_CHAT_TO_FILE = 0x138,
+/*20040804 to latest
+/갈무리 or /savechat : 채팅 내용 파일로 저장하기.
+/savechat: Save a Chat Log
+*/
+ MSG_EXPLAIN_SAVE_CHAT = 0x139,
+/*20040804 to latest
+계정 만들기
+Register
+*/
+ MSG_MAKEACCOUNT = 0x13a,
+/*20040804 to latest
+수신거부하기
+Reject Whispering
+*/
+ MSG_REQ_EX_LIST = 0x13b,
+/*20040804 to latest
+수신거부해제하기
+Allow Whispering
+*/
+ MSG_REQ_IN = 0x13c,
+/*20040804 to latest
+미스표시 On
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_ON = 0x13d,
+/*20040804 to latest
+미스표시 Off
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_OFF = 0x13e,
+/*20040804 to latest
+카메라고정 On
+Camera Zooming On
+*/
+ MSG_FIXED_CAMERA_ON = 0x13f,
+/*20040804 to latest
+카메라고정 Off
+Camera Zooming Off
+*/
+ MSG_FIXED_CAMERA_OFF = 0x140,
+/*20040804 to latest
+/camera : 플레이어에게 카메라고정 On Off /miss : 미스이펙트 On Off
+/camera: Camera Zooming On or Off. /miss: Toggle ''Miss'' display
+*/
+ MSG_EXPLAIN_CAMERA_MISS = 0x141,
+/*20040804 to latest
+스킬정보보기
+View Skill Info
+*/
+ MSG_SEE_INFORMATION_OF_SKILL = 0x142,
+/*20040804 to latest
+스킬이름바꾸기
+Change Skill
+*/
+ MSG_CHANGE_SKILL_NAME = 0x143,
+/*20040804 to latest
+스프라이트 해상도
+Sprite Resolution
+*/
+ MSG_SPRITE_RESOLUTION = 0x144,
+/*20040804 to latest
+텍스쳐 해상도
+Texture Resolution
+*/
+ MSG_TEXTURE_RESOLUTION = 0x145,
+/*20040804 to latest
+디테일 조정
+Arrange Detail
+*/
+ MSG_DETAILLEVELWND = 0x146,
+/*20040804 to latest
+%s Zeny 획득
+You got %s Zeny
+*/
+ MSG_GET_ZENY = 0x147,
+/*20040804 to latest
+길드명
+Guild Name
+*/
+ MSG_GUILDNAME = 0x148,
+/*20040804 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILDLEVEL = 0x149,
+/*20040804 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_GUILD_MASTER_NAME = 0x14a,
+/*20040804 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_NUM_MEMBER = 0x14b,
+/*20040804 to latest
+조합원 평균레벨
+Avg.lvl of Guildsmen
+*/
+ MSG_GUILD_AVG_MEMBER_LEVEL = 0x14c,
+/*20040804 to latest
+관리영지
+Castles Owned
+*/
+ MSG_GUILD_MANAGE_LAND = 0x14d,
+/*20040804 to latest
+성향
+Tendency
+*/
+ MSG_GUILD_FAIR = 0x14e,
+/*20040804 to latest
+경험치
+EXP
+*/
+ MSG_GUILD_EXP = 0x14f,
+/*20040804 to latest
+길드엠블렘
+Emblem
+*/
+ MSG_GUILD_EMBLEM = 0x150,
+/*20040804 to latest
+길드상납포인트
+Tax Point
+*/
+ MSG_GUILD_POINT = 0x151,
+/*20040804 to latest
+동맹길드
+Alliances
+*/
+ MSG_ALLY_GUILD = 0x152,
+/*20040804 to latest
+적대길드
+Antagonists
+*/
+ MSG_HOSTILITY_GUILD = 0x153,
+/*20040804 to latest
+길드정보
+Guild Info
+*/
+ MSG_GUILDINFOMANAGE = 0x154,
+/*20040804 to latest
+조합원정보
+Guildsmen Info
+*/
+ MSG_GUILDMEMBERMANAGE = 0x155,
+/*20040804 to latest
+직위설정
+Position
+*/
+ MSG_GUILDPOSITIONMANAGE = 0x156,
+/*20040804 to latest
+길드스킬
+Guild Skill
+*/
+ MSG_GUILDSKILL = 0x157,
+/*20040804 to latest
+추방자 리스트
+Expel History
+*/
+ MSG_GUILDBANISHEDMEMBER = 0x158,
+/*20040804 to latest
+공지사항
+Guild Notice
+*/
+ MSG_GUILDNOTICE = 0x159,
+/*20040804 to latest
+전체길드 리스트
+Entire Guild List
+*/
+ MSG_GUILDTOTALINFO = 0x15a,
+/*20040804 to latest
+귓말 리스트
+Whispering List
+*/
+ MSG_WHISPERLISTWND = 0x15b,
+/*20040804 to latest
+귓말창 열기
+Open Whispering Window
+*/
+ MSG_OPENWHISPERLISTWND = 0x15c,
+/*20040804 to latest
+귓말 리스트 창 여는법 : [Alt] + [H] 를 누르면 귓말 리스트 창이 열립니다.
+How to Open Whispering List: Press [Alt] + [H]
+*/
+ MSG_EXPLAIN_WHISPER_LIST_WND = 0x15d,
+/*20040804 to latest
+자동으로 귓말창 열기
+Open Whispering List Automatically
+*/
+ MSG_AUTOOPENWHISPERLISTWND = 0x15e,
+/*20040804 to latest
+지우기
+Delete
+*/
+ MSG_DELETE = 0x15f,
+/*20040804 to latest
+다음부터 열리지 않음
+Close since next
+*/
+ MSG_DONTOPEN = 0x160,
+/*20040804 to latest
+마지막으로 접속한 시간
+Last Log-in Time
+*/
+ MSG_LAST_LOGIN_TIME = 0x161,
+/*20040804 to latest
+마지막으로 접속한 IP
+Last Log-in IP
+*/
+ MSG_LAST_LOGIN_IP = 0x162,
+/*20040804 to latest
+친구 설정
+Friend Setup
+*/
+ MSG_FRIEND_SETTING = 0x163,
+/*20040804 to latest
+정말 지우시겠습니까?
+Are you sure that you want to delete?
+*/
+ MSG_DO_YOU_REALLY_WANT_DELETE = 0x164,
+/*20040804 to latest
+정말 탈퇴하시겠습니까?
+Are you sure that you want to leave?
+*/
+ MSG_DO_YOU_REALLY_WANT_LEAVE = 0x165,
+/*20040804 to latest
+친구로 등록하기
+Register as a Friend
+*/
+ MSG_ADD_TO_FRIEND_CHAR_LIST = 0x166,
+/*20040804 to latest
+친구일때 자동으로 1:1창 열기
+Open 1:1 Chat between Friends
+*/
+ MSG_AUTOOPENWHISPERLISTWND_FRIEND = 0x167,
+/*20040804 to latest
+1:1창 열기
+Open 1:1 Chat
+*/
+ MSG_OPEN_1ON1_WINDOW = 0x168,
+/*20040804 to latest
+친구가 아닐때 자동으로 1:1창 열기
+Open 1:1 Chat between Strangers
+*/
+ MSG_AUTOOPEN_1ON1_WINDOW = 0x169,
+/*20040804 to latest
+1:1창 열릴때 소리로 알림
+Alarm when you recieve a 1:1 Chat
+*/
+ MSG_WHISPER_OPEN_SOUND = 0x16a,
+/*20040804 to latest
+정말 제명시키시겠습니까?
+Are you sure that you want to expel?
+*/
+ MSG_DO_YOU_REALLY_WANT_EXPEL = 0x16b,
+/*20040804 to latest
+%s 님이 길드를 탈퇴했습니다.
+%s has withdrawn from the guild.
+*/
+ MSG_USER_LEFT_GUILD = 0x16c,
+/*20040804 to latest
+탈퇴사유 : %s
+Secession Reason: %s
+*/
+ MSG_REASON_LEAVE_GUILD = 0x16d,
+/*20040804 to latest
+길드 해체 실패
+*/
+ MSG_DISORGANIZE_GUILD_FAILURE = 0x16e,
+/*20040804 to latest
+길드해체사유 : %s
+Disband Reason: %s
+*/
+ MSG_DISORGANIZATION_REASON = 0x16f,
+/*20040804 to latest
+해당 계정은 삭제된 아이디 입니다.
+This ID has been removed.
+*/
+ MSG_DELETED_ACCOUNT = 0x170,
+/*20040804 to latest
+판매가 :
+Price:
+*/
+ MSG_SELLPRICE = 0x171,
+/*20040804 to latest
+%s 님이 길드에서 추방되었습니다.
+%s has been expelled from our guild.
+*/
+ MSG_BAN_GUILD = 0x172,
+/*20040804 to latest
+추방사유 : %s
+Expulsion Reason: %s
+*/
+ MSG_REASON_BAN_GUILD = 0x173,
+/*20040804 to latest
+아이템을 착용할 수 없습니다.
+You can't put this item on.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM = 0x174,
+/*20040804 to latest
+파티설정을 변경할 수 없습니다.
+You can't modify Party Setup.
+*/
+ MSG_PARTYSETTING_CHANGE_IMPOSSIBLE = 0x175,
+/*20040804 to latest
+길드가 만들어 졌습니다.
+Guild has been Created.
+*/
+ MSG_GUILD_MAKE_SUCCESS = 0x176,
+/*20040804 to latest
+이미 길드에 속해있습니다.
+You are already in a Guild.
+*/
+ MSG_GUILD_MAKE_ALREADY_MEMBER = 0x177,
+/*20040804 to latest
+같은이름의 길드가 존재합니다.
+That Guild Name already exists.
+*/
+ MSG_GUILD_MAKE_GUILD_EXIST = 0x178,
+/*20040804 to latest
+ 길드에서 초청 메시지가 왔습니다. 가입하겠습니까?
+ Guild has sent you an invitation. Would you like to join this Guild?
+*/
+ MSG_SUGGEST_JOIN_GUILD = 0x179,
+/*20040804 to latest
+다른길드에 가입되어 있습니다.
+He/She is already in a Guild.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_GUILD = 0x17a,
+/*20040804 to latest
+길드가입을 거절 했습니다.
+Offer Rejected
+*/
+ MSG_CHARACTER_REJECT_JOIN_GUILD = 0x17b,
+/*20040804 to latest
+길드가입을 수락했습니다.
+Offer Accepted
+*/
+ MSG_CHARACTER_ACCEPT_JOIN_GUILD = 0x17c,
+/*20040804 to latest
+길드정원을 초과했습니다.
+Your Guild is Full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_GUILD = 0x17d,
+/*20040804 to latest
+(%s)님 길드에 가입요청
+Send (%s) a Guild invitation
+*/
+ MSG_REQ_JOIN_GUILD = 0x17e,
+/*20040804 to latest
+스킬 레벨이 모자라서 매너포인트를 줄 수 없습니다.
+You haven't learned enough skills for aligning.
+*/
+ MSG_NOT_ENOUGH_FOR_MANNER_POINT = 0x17f,
+/*20040804 to latest
+매너 포인트 주기 성공
+Aligning completed.
+*/
+ MSG_GIVING_MANNER_POINT_SUCCESS = 0x180,
+/*20040804 to latest
+오늘 이미 사용했습니다.
+You already spent your point for today.
+*/
+ MSG_YOU_USE_TODAY_ALREADY = 0x181,
+/*20040804 to latest
+이캐릭터에게 지급한지 한달이 지나지 않았습니다.
+Hasn't been a month yet since you aligned this person.
+*/
+ MSG_ONE_MONTH_NOT_PASSED = 0x182,
+/*20040804 to latest
+%s 님으로부터 플러스 매너 포인트를 받았습니다.
+Remember, Spamming isn't nice.
+*/
+ MSG_RECEIVE_PLUS_MANNER_POINT = 0x183,
+/*20040804 to latest
+%s 님으로부터 마이너스 매너 포인트를 받았습니다.
+Please refrain from ill-mannered conduct, thank you.
+*/
+ MSG_RECEIVE_MINUS_MANNER_POINT = 0x184,
+/*20040804 to latest
+채팅 금지 시간 줄이기(풀기)
+Align with a Good Point
+*/
+ MSG_GIVE_PLUS_MANNER_POINT = 0x185,
+/*20040804 to latest
+채팅 금지 시간 늘이기(걸기)
+Align with a Bad Point
+*/
+ MSG_GIVE_MINUS_MANNER_POINT = 0x186,
+/*20040804 to latest
+(%s)님과의 거래요청
+Request a deal with (%s)
+*/
+ MSG_REQ_DEAL_WITH2 = 0x187,
+/*20040804 to latest
+(%s)님 파티에 가입요청
+Ask (%s) to join your party
+*/
+ MSG_REQ_JOIN_PARTY2 = 0x188,
+/*20040804 to latest
+ 길드에서 동맹요청 메시지가 왔습니다. 동맹하겠습니까?
+ Guild is asking you to agree to an Alliance with them. Do you accept?
+*/
+ MSG_SUGGEST_ALLY_GUILD = 0x189,
+/*20040804 to latest
+이미 동맹되어 있습니다.
+This Guild is already your Ally.
+*/
+ MSG_REQALLYGUILD_ALREADY_ALLIED = 0x18a,
+/*20040804 to latest
+동맹을 거절 했습니다.
+You reject the offer
+*/
+ MSG_REQALLYGUILD_REJECT = 0x18b,
+/*20040804 to latest
+동맹을 수락 했습니다.
+You accept the offer
+*/
+ MSG_REQALLYGUILD_ACCEPT = 0x18c,
+/*20040804 to latest
+상대길드의 동맹길드의 수가 초과 되었습니다.
+They have too many Alliances.
+*/
+ MSG_REQALLYGUILD_OVERSIZE = 0x18d,
+/*20040804 to latest
+길드의 동맹길드의 수가 초과 되었습니다.
+You have too many Alliances.
+*/
+ MSG_REQALLYMYGUILD_OVERSIZE = 0x18e,
+/*20040804 to latest
+길드 동맹 요청
+Set this guild as an Alliance
+*/
+ MSG_REQ_ALLY_GUILD = 0x18f,
+/*20040804 to latest
+길드가 성공적으로 해체 되었습니다.
+Guild was successfully disbanded.
+*/
+ MSG_DISORGANIZE_GUILD_SUCCESS = 0x190,
+/*20040804 to latest
+주민등록번호가 틀려서 길드가 해체되지 않았습니다.
+You have failed to disband the guild due to your incorrect SSN.
+*/
+ MSG_DISORGANIZE_GUILD_INVALIDKEY = 0x191,
+/*20040804 to latest
+길드맴버가 존재해서 길드가 해체되지 않았습니다.
+You have failed to disband the guild because there are guildsmen still present.
+*/
+ MSG_DISORGANIZE_GUILD_MEMBEREXIST = 0x192,
+/*20040804 to latest
+길드 적대 요청
+Set this guild as an Antagonist
+*/
+ MSG_REQ_HOSTILE_GUILD = 0x193,
+/*20040804 to latest
+머리색깔 선택
+Choose Hair Color
+*/
+ MSG_SELECT_HAIR_COLOR = 0x194,
+/*20040804 to latest
+길드결성시 필요한 아이템이 없습니다.
+You don't have necessary item to create a Guild.
+*/
+ MSG_GUILD_MAKE_GUILD_NONE_ITEM = 0x195,
+/*20040804 to latest
+몬스터 정보
+Monster Info
+*/
+ MSG_MONSTER_INFO_WINDOW = 0x196,
+/*20040804 to latest
+이름
+Name
+*/
+ MSG_NAME = 0x197,
+/*20040804 to latest
+레벨
+Level
+*/
+ MSG_LEVEL = 0x198,
+/*20040804 to latest
+HP
+*/
+ MSG_HP = 0x199,
+/*20040804 to latest
+크기
+Size
+*/
+ MSG_SIZE = 0x19a,
+/*20040804 to latest
+종족
+Type
+*/
+ MSG_RACETYPE = 0x19b,
+/*20040804 to latest
+MDEF
+*/
+ MSG_MDEFPOWER = 0x19c,
+/*20040804 to latest
+속성
+Attribute
+*/
+ MSG_PROPERTY = 0x19d,
+/*20040804 to latest
+無
+Neutral
+*/
+ MSG_PROPERTY_NEUTURAL = 0x19e,
+/*20040804 to latest
+水
+Water
+*/
+ MSG_PROPERTY_WATER = 0x19f,
+/*20040804 to latest
+地
+Earth
+*/
+ MSG_PROPERTY_EARTH = 0x1a0,
+/*20040804 to latest
+火
+Fire
+*/
+ MSG_PROPERTY_FIRE = 0x1a1,
+/*20040804 to latest
+風
+Wind
+*/
+ MSG_PROPERTY_WIND = 0x1a2,
+/*20040804 to latest
+毒
+Poison
+*/
+ MSG_PROPERTY_POISON = 0x1a3,
+/*20040804 to latest
+聖
+Holy
+*/
+ MSG_PROPERTY_SAINT = 0x1a4,
+/*20040804 to latest
+暗
+Shadow
+*/
+ MSG_PROPERTY_DARK = 0x1a5,
+/*20040804 to latest
+念
+Ghost
+*/
+ MSG_PROPERTY_MENTAL = 0x1a6,
+/*20040804 to latest
+死
+Undead
+*/
+ MSG_PROPERTY_UNDEAD = 0x1a7,
+/*20040804 to latest
+현재는 아이템을 만들 수 없습니다.
+You can't create items yet.
+*/
+ MSG_CANT_MAKE_ITEM = 0x1a8,
+/*20040804 to latest
+제조 목록
+Item List you can craft
+*/
+ MSG_MAKE_LIST = 0x1a9,
+/*20040804 to latest
+ 만들기
+ Create
+*/
+ MSG_MAKE_TARGET = 0x1aa,
+/*20040804 to latest
+ 에 필요한 재료:
+'s materials
+*/
+ MSG_REQUIRE_FOR_MAKE_TARGET = 0x1ab,
+/*20040804 to latest
+ 만들기 실패
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL = 0x1ac,
+/*20040804 to latest
+ 만들기 성공
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS = 0x1ad,
+/*20040804 to latest
+%s 만들기를 실패하였습니다.
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL_MSG = 0x1ae,
+/*20040804 to latest
+%s 만들기를 성공했습니다.
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS_MSG = 0x1af,
+/*20040804 to latest
+레벨이 부족합니다.
+You are not the required lvl.
+*/
+ MSG_NOT_ENOUGH_LEVEL = 0x1b0,
+/*20040804 to latest
+레벨이 너무 높습니다.
+Too high lvl for this job.
+*/
+ MSG_TOO_HIGH_LEVEL = 0x1b1,
+/*20040804 to latest
+직업이 적합하지 않습니다.
+Not the suitable job for this type of work.
+*/
+ MSG_NOT_ACCEPTABLE_JOB = 0x1b2,
+/*20040804 to latest
+토키 박스 트랩 메세지
+Record a message in the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW = 0x1b3,
+/*20040804 to latest
+기록할 메세지를 입력하시기 바랍니다.
+Please type a message for the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW_MSG = 0x1b4,
+/*20040804 to latest
+길드에게 보냄
+Send to Guild
+*/
+ MSG_SEND_TO_GUILD = 0x1b5,
+/*20040804 to latest
+결제된 계정이 아닙니다. 결제 페이지로 이동하시겠습니까?
+You didn't pay for this ID. Would you like to pay for it now?
+*/
+ MSG_NOT_SETTLED = 0x1b6,
+/*20040804 to latest
+서버가 혼잡한 관계로 잠시후 다시 시도해 주시기 바랍니다.
+Server is jammed due to overpopulation. Please try again after few minutes.
+*/
+ MSG_ACCOUNT_BUSY = 0x1b7,
+/*20040804 to latest
+지난 접속 정보가 남아 있습니다. 30초정도 지난뒤에 다시 시도해 주시기 바랍니다.
+Server still recognizes your last log-in. Please try again after a few minutes.
+*/
+ MSG_INFORMATION_REMAINED = 0x1b8,
+/*20040804 to latest
+매 풀어주기
+Release Falcon
+*/
+ MSG_BIRDOFF = 0x1b9,
+/*20040804 to latest
+페코페코 내리기
+Dismount
+*/
+ MSG_CHIKENOFF = 0x1ba,
+/*20040804 to latest
+小
+Small
+*/
+ MSG_SIZE_SMALL = 0x1bb,
+/*20040804 to latest
+中
+Med
+*/
+ MSG_SIZE_MIDDLE = 0x1bc,
+/*20040804 to latest
+大
+Big
+*/
+ MSG_SIZE_BIG = 0x1bd,
+/*20040804 to latest
+더블
+Double
+*/
+ MSG_DOUBLE = 0x1be,
+/*20040804 to latest
+트리플
+Triple
+*/
+ MSG_TRIPLE = 0x1bf,
+/*20040804 to latest
+쿼드로플
+Quadruple
+*/
+ MSG_QUADROPLE = 0x1c0,
+/*20040804 to latest
+%s 까지 로그인을 금지하고 있습니다.
+You are prohibited to log in until %s.
+*/
+ MSG_LOGIN_REFUSE_BLOCKED_UNTIL = 0x1c1,
+/*20040804 to latest
+의
+'s
+*/
+ MSG_MANUFACTURED_NORMAL_ITEM = 0x1c2,
+/*20040804 to latest
+의 파이어
+'s Fire
+*/
+ MSG_MANUFACTURED_FIRE_ITEM = 0x1c3,
+/*20040804 to latest
+의 아이스
+'s Ice
+*/
+ MSG_MANUFACTURED_ICE_ITEM = 0x1c4,
+/*20040804 to latest
+의 윈드
+'s Wind
+*/
+ MSG_MANUFACTURED_WIND_ITEM = 0x1c5,
+/*20040804 to latest
+의 어스
+'s Earth
+*/
+ MSG_MANUFACTURED_EARTH_ITEM = 0x1c6,
+/*20040804 to latest
+211.239.161.246
+38.144.194.2
+*/
+ MSG_ACCOUNT_ADDRESS = 0x1c7,
+/*20040804 to latest
+6900
+*/
+ MSG_ACCOUNT_PORT = 0x1c8,
+/*20040804 to latest
+http://www.ragnarok.co.kr
+*/
+ MSG_REGISTRATION_WEB_URL = 0x1c9,
+/*20040804 to latest
+%s 사용자 강제 종료
+Kill %s
+*/
+ MSG_BAN_USER = 0x1ca,
+/*20040804 to latest
+무지쎈
+Very Strong
+*/
+ MSG_ONE_STARPIECE = 0x1cb,
+/*20040804 to latest
+무지무지쎈
+Very Very Strong
+*/
+ MSG_TWO_STARPIECE = 0x1cc,
+/*20040804 to latest
+무무무쎈
+Very Very Very Strong
+*/
+ MSG_THREE_STARPIECE = 0x1cd,
+/*20040804 to latest
+길드 추방 사유
+The Reason of Expulsion
+*/
+ MSG_GUILD_KICK_REASON = 0x1ce,
+/*20040804 to latest
+ 공격 속도가 증가했습니다.
+Attack Speed is up.
+*/
+ MSG_INCATTACKSPEED = 0x1cf,
+/*20040804 to latest
+ 공격 속도가 감소했습니다.
+Attack Speed is down.
+*/
+ MSG_DECATTACKSPEED = 0x1d0,
+/*20040804 to latest
+ 무기의 공격력이 향상되었습니다.
+Weapon Damage is improved.
+*/
+ MSG_INCWEAPONATTACK = 0x1d1,
+/*20040804 to latest
+ 무기의 공격력이 감소되었습니다.
+Weapon Damage is reduced.
+*/
+ MSG_DECWEAPONATTACK = 0x1d2,
+/*20040804 to latest
+ 시전 딜레이가 줄었습니다.
+Cast Delay is reduced.
+*/
+ MSG_FASTPREDELAY = 0x1d3,
+/*20040804 to latest
+ 시전 딜레이가 정상으로 되었습니다.
+Cast Delay has returned to normal.
+*/
+ MSG_NORMALPREDELAY = 0x1d4,
+/*20040804 to latest
+ 무기에 독속성이 부여되었습니다.
+Weapon is temporarily enchanted with Poison.
+*/
+ MSG_WEAPONPROPERTYPOISON = 0x1d5,
+/*20040804 to latest
+ 무기에 성속성이 부여되었습니다.
+Weapon is temporarily enchanted with an elemental property.
+*/
+ MSG_WEAPONPROPERTYSAINT = 0x1d6,
+/*20040804 to latest
+ 무기의 원래속성이 적용되었습니다.
+Weapon has changed back to normal.
+*/
+ MSG_WEAPONPROPERTYORIGINAL = 0x1d7,
+/*20040804 to latest
+ 방어구에 성속성이 부여되었습니다.
+Armor has been enchanted with the Holy Ghost.
+*/
+ MSG_ARMORPROPERTYSAINT = 0x1d8,
+/*20040804 to latest
+ 방어구의 원래속성이 적용되었습니다.
+Armor has changed back to normal.
+*/
+ MSG_ARMORPROPERTYORIGINAL = 0x1d9,
+/*20040804 to latest
+ 배리어 상태가 되었습니다.
+Barrier Formed.
+*/
+ MSG_BARRIOR = 0x1da,
+/*20040804 to latest
+ 배리어 상태가 해제 되었습니다.
+Barrier Canceled.
+*/
+ MSG_DISAPPEARBARRIOR = 0x1db,
+/*20040804 to latest
+ 소형, 중형, 대형 몬스터에게 100% 공격력을 줍니다.
+Weapon Perfection Initiated.
+*/
+ MSG_PERFECTDAMAGE = 0x1dc,
+/*20040804 to latest
+ 웨폰퍼펙션 모드가 해제 되었습니다.
+Weapon perfection Canceled.
+*/
+ MSG_DISAPPEARPERFECTDAMAGE = 0x1dd,
+/*20040804 to latest
+ 무기가 파괴될 가능성이 높아진 대신 무기의 공격력이 증가하였습니다.
+Power-Thrust Initiated.
+*/
+ MSG_OVERTHRUSTING = 0x1de,
+/*20040804 to 20050118
+ 오버트러스팅 상태가 해제 되었습니다.
+20050124 to latest
+ 오버트러스트 상태가 해제 되었습니다.
+Power-Thrust Canceled.
+*/
+ MSG_DISAPPEAROVERTHRUSTING = 0x1df,
+/*20040804 to latest
+ 무기의 최대 성능을 끌어냅니다.
+Maximize-Power Initiated.
+*/
+ MSG_MAXIMIZE = 0x1e0,
+/*20040804 to latest
+ 맥시마이즈 상태가 해제 되었습니다.
+Maximize-Power Canceled.
+*/
+ MSG_DISAPPEARMAXIMIZE = 0x1e1,
+/*20040804 to latest
+[신서버]
+[New Server]
+*/
+ MSG_SERVER_PROPERTY_NEW = 0x1e2,
+/*20040804 to latest
+(%d 명)
+(%d players)
+*/
+ MSG_SERVER_USER_COUNT = 0x1e3,
+/*20040804 to latest
+(점검중)
+(On the maintenance)
+*/
+ MSG_SERVER_INSPECTING = 0x1e4,
+/*20040804 to latest
+길드멤버 %s님이 접속하셨습니다.
+Guild member %s has connected.
+*/
+ MSG_GUILD_MEMBER_STATUS_ONLINE = 0x1e5,
+/*20040804 to latest
+길드멤버 %s님이 종료하셨습니다.
+Guild member %s has disconnected.
+*/
+ MSG_GUILD_MEMBER_STATUS_OFFLINE = 0x1e6,
+/*20040804 to latest
+경험치 %d 얻음
+You got %d Base EXP.
+*/
+ MSG_GOT_EXPERIENCE_POINT = 0x1e7,
+/*20040804 to latest
+잡경험치 %d 얻음
+You got %d Job EXP.
+*/
+ MSG_GOT_JOB_EXPERIENCE_POINT = 0x1e8,
+/*20040804 to latest
+길드에서 탈퇴 했습니다.
+You left the guild.
+*/
+ MSG_LEFT_GUILD = 0x1e9,
+/*20040804 to latest
+길드에서 추방 당했습니다.
+You have been expelled from the Guild.
+*/
+ MSG_BAN_FROM_GUILD = 0x1ea,
+/*20040804 to latest
+아이템 감정 성공
+Item Appraisal has completed successfully.
+*/
+ MSG_ITEM_IDENTIFY_SUCCEESS = 0x1eb,
+/*20040804 to latest
+아이템 감정 실패
+Item appraisal has failed.
+*/
+ MSG_ITEM_IDENTIFY_FAIL = 0x1ec,
+/*20040804 to latest
+아이템 조합 성공
+Compounding has completed successfully.
+*/
+ MSG_ITEM_COMPOUNDING_SUCCEESS = 0x1ed,
+/*20040804 to latest
+아이템 조합 실패
+Compounding has failed.
+*/
+ MSG_ITEM_COMPOUNDING_FAIL = 0x1ee,
+/*20040804 to latest
+길드 적대 성공
+Antagonist has been set.
+*/
+ MSG_HOSTILE_GUILD_SUCCEESS = 0x1ef,
+/*20040804 to latest
+적대 길드수 초과로 길드 적대 실패
+Guild has too many Antagonists.
+*/
+ MSG_TOO_MANY_HOSTILE_GUILD = 0x1f0,
+/*20040804 to latest
+이미 적대 길드 입니다
+Already set as an Antagonist
+*/
+ MSG_ALREADY_REGISTERED_HOSTILE_GUILD = 0x1f1,
+/*20040804 to latest
+제련이 성공적으로 되었습니다.
+Upgrade has been completed successfully.
+*/
+ MSG_ITEM_REFINING_SUCCEESS = 0x1f2,
+/*20040804 to latest
+제련이 실패하였습니다.
+Upgrade has failed.
+*/
+ MSG_ITEM_REFINING_FAIL = 0x1f3,
+/*20040804 to latest
+이곳에서는 순간이동이 불가능합니다.
+Unavailable Area to Teleport
+*/
+ MSG_IMPOSSIBLE_TELEPORT_AREA = 0x1f4,
+/*20040804 to latest
+이 장소는 기억할 수 없습니다.
+Unable to memorize this place as Warp Point
+*/
+ MSG_POSSIBLE_TELEPORT_AREA = 0x1f5,
+/*20040804 to latest
+지금은 종료할 수 없습니다.
+Please wait 10 seconds before trying to log out.
+*/
+ MSG_CANT_EXIT_NOW = 0x1f6,
+/*20040804 to latest
+직위
+Position
+*/
+ MSG_POSITION = 0x1f7,
+/*20040804 to latest
+직업
+Job
+*/
+ MSG_JOB = 0x1f8,
+/*20040804 to latest
+메모
+Note
+*/
+ MSG_MEMO = 0x1f9,
+/*20040804 to latest
+기여
+Devotion
+*/
+ MSG_CONTRIBUTION = 0x1fa,
+/*20040804 to latest
+상납경험치
+Tax Point
+*/
+ MSG_EXP_CONTIRIBUTION = 0x1fb,
+/*20040804 to latest
+길드탈퇴
+Leave Guild
+*/
+ MSG_LEAVE_GUILD = 0x1fc,
+/*20040804 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL_GUILD = 0x1fd,
+/*20040804 to latest
+서열
+Rank
+*/
+ MSG_GRADE = 0x1fe,
+/*20040804 to latest
+직위명
+Position Title
+*/
+ MSG_POSITION_NAME = 0x1ff,
+/*20040804 to latest
+가입권한
+Invitation
+*/
+ MSG_JOIN_AUTHORITY = 0x200,
+/*20040804 to latest
+처벌권한
+Punish
+*/
+ MSG_PENALTY_AUTORITY = 0x201,
+/*20040804 to latest
+상납%
+Tax %
+*/
+ MSG_CONTRIBUTION_PERCENT = 0x202,
+/*20040804 to latest
+제목
+Title
+*/
+ MSG_TITLE = 0x203,
+/*20040804 to latest
+내용
+For
+*/
+ MSG_CONTENTS = 0x204,
+/*20040804 to latest
+길드이름
+Guild Name
+*/
+ MSG_GUILD_NAME = 0x205,
+/*20040804 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILD_LEVEL = 0x206,
+/*20040804 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_PEOPLE_COUNT = 0x207,
+/*20040804 to latest
+랭킹
+Ranking
+*/
+ MSG_RANKING = 0x208,
+/*20040804 to latest
+아이템 감정
+Item Appraisal
+*/
+ MSG_ITEM_IDENTIFY = 0x209,
+/*20040804 to latest
+아이템 조합
+Insert Card
+*/
+ MSG_ITEM_COMPOUNDING = 0x20a,
+/*20040804 to latest
+탈퇴 사유를 입력해주세요.
+Please enter the reason of Secession.
+*/
+ MSG_PLEASE_INPUT_WHY_LEAVING = 0x20b,
+/*20040804 to latest
+추방 사유를 입력해주세요.
+Please enter the reason of Expulsion.
+*/
+ MSG_PELASE_INPUT_WHY_EXPEL = 0x20c,
+/*20040804 to latest
+상점을 닫으세요.
+Please close Shop.
+*/
+ MSG_PLEASE_CLOSE_STORE = 0x20d,
+/*20040804 to latest
+스킬 이름
+Skill
+*/
+ MSG_SKILL_NAME = 0x20e,
+/*20040804 to latest
+아이템 이름
+Item Name
+*/
+ MSG_ITEM_NAME = 0x20f,
+/*20040804 to latest
+https://payment.ragnarok.co.kr
+https://pay.ragnarok.co.kr (Billing Web)
+*/
+ MSG_SETTLE_WEB_URL = 0x210,
+/*20040804 to latest
+게임방에서 사용가능한 IP개수가 모두 사용중입니다. 개인 계정으로 결제 하시겠습니까?
+IP capacity of this Internet Cafe is full. Would you like to pay the personal base?
+*/
+ MSG_BAN_IP_OVERFLOW = 0x211,
+/*20040804 to latest
+결제시간이 다되어 게임을 종료합니다.
+You are out of available paid playing time. Game will be shut down automatically.
+*/
+ MSG_BAN_PAY_OUT = 0x212,
+/*20040804 to latest
+이름이 너무 깁니다. 한글 11자 영문 23자 이내로 써주십시오.
+Name is too long. Please enter a name no greater than 23 english characters.
+*/
+ MSG_NAMELENGTH_TOO_LONG = 0x213,
+/*20040804 to latest
+deleted
+Character will be deleted in %d seconds.
+*/
+ MSG_DELETE_AFTER_10_SECOND = 0x214,
+/*20040804 to latest
+귀하는 개인 정액제 사용자입니다.
+You paid with the personal regular base.
+*/
+ MSG_BILLING_100 = 0x215,
+/*20040804 to latest
+귀하는 개인정량제 사용자입니다.
+You paid with the personal regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_200 = 0x216,
+/*20040804 to latest
+귀하는 개인 무료 사용자입니다.
+You are free!
+*/
+ MSG_BILLING_300 = 0x217,
+/*20040804 to latest
+귀하는 개인 무료 허용기간 사용자입니다.
+You are free for the test, your available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_400 = 0x218,
+/*20040804 to latest
+귀하는 게임방 정액제 사용자입니다.
+You paid with the Internet Cafe regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_500 = 0x219,
+/*20040804 to latest
+귀하는 게임방 정량제 사용자입니다.
+You paid with the Time Limit for Internet Cafe. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_501 = 0x21a,
+/*20040804 to latest
+귀하는 게임방 무료 허용기간 사용자입니다.
+You are free for the test of Internet Cafe version .
+*/
+ MSG_BILLING_600 = 0x21b,
+/*20040804 to latest
+귀하는 게임방 무료 사용자입니다.
+You are free for the Internet Cafe version.
+*/
+ MSG_BILLING_700 = 0x21c,
+/*20040804 to latest
+귀하는 종량제 사이트 이용자입니다.
+You paid on the Time Limit Website.
+*/
+ MSG_BILLING_800 = 0x21d,
+/*20040804 to latest
+이모션 목록
+Emotion icon List
+*/
+ MSG_EMOTION_LIST = 0x21e,
+/*20040804 to latest
+/이모션
+/emo
+*/
+ MSG_VIEW_EMOTION = 0x21f,
+/*20040804 to latest
+/!
+*/
+ MSG_EMOTION_SURPRISE = 0x220,
+/*20040804 to latest
+/?
+*/
+ MSG_EMOTION_QUESTION = 0x221,
+/*20040804 to latest
+/기쁨
+/ho
+*/
+ MSG_EMOTION_DELIGHT = 0x222,
+/*20040804 to latest
+/하트
+/lv
+*/
+ MSG_EMOTION_THROB = 0x223,
+/*20040804 to latest
+/왕하트
+/lv2
+*/
+ MSG_EMOTION_BIGTHROB = 0x224,
+/*20040804 to latest
+/땀
+/swt
+*/
+ MSG_EMOTION_SWEAT = 0x225,
+/*20040804 to latest
+/아하
+/ic
+*/
+ MSG_EMOTION_AHA = 0x226,
+/*20040804 to latest
+/짜증
+/an
+*/
+ MSG_EMOTION_FRET = 0x227,
+/*20040804 to latest
+/화
+/ag
+*/
+ MSG_EMOTION_ANGER = 0x228,
+/*20040804 to latest
+/돈
+/$
+*/
+ MSG_EMOTION_MONEY = 0x229,
+/*20040804 to latest
+/...
+*/
+ MSG_EMOTION_THINK = 0x22a,
+/*20040804 to latest
+/감사
+/thx
+*/
+ MSG_EMOTION_THANKS = 0x22b,
+/*20040804 to latest
+/꽥
+/wah
+*/
+ MSG_EMOTION_KEK = 0x22c,
+/*20040804 to latest
+/죄송
+/sry
+*/
+ MSG_EMOTION_SORRY = 0x22d,
+/*20040804 to latest
+/웃음
+/heh
+*/
+ MSG_EMOTION_SMILE = 0x22e,
+/*20040804 to latest
+/뻘뻘
+/swt2
+*/
+ MSG_EMOTION_PROFUSELY_SWEAT = 0x22f,
+/*20040804 to latest
+/긁적
+/hmm
+*/
+ MSG_EMOTION_SCRATCH = 0x230,
+/*20040804 to latest
+/최고
+/no1
+*/
+ MSG_EMOTION_BEST = 0x231,
+/*20040804 to latest
+/두리번
+/??
+*/
+ MSG_EMOTION_STARE_ABOUT = 0x232,
+/*20040804 to latest
+/헉
+/omg
+*/
+ MSG_EMOTION_HUK = 0x233,
+/*20040804 to latest
+/오
+/oh
+*/
+ MSG_EMOTION_O = 0x234,
+/*20040804 to latest
+/엑스
+/X
+*/
+ MSG_EMOTION_X = 0x235,
+/*20040804 to latest
+/헬프
+/hlp
+*/
+ MSG_EMOTION_HELP = 0x236,
+/*20040804 to latest
+/가
+/go
+*/
+ MSG_EMOTION_GO = 0x237,
+/*20040804 to latest
+/엉엉
+/sob
+*/
+ MSG_EMOTION_CRY = 0x238,
+/*20040804 to latest
+/킥킥
+/gg
+*/
+ MSG_EMOTION_KIK = 0x239,
+/*20040804 to latest
+/쪽
+/kis
+*/
+ MSG_EMOTION_CHUP = 0x23a,
+/*20040804 to latest
+/쪽쪽
+/kis2
+*/
+ MSG_EMOTION_CHUPCHUP = 0x23b,
+/*20040804 to latest
+/흥
+/pif
+*/
+ MSG_EMOTION_HNG = 0x23c,
+/*20040804 to latest
+/응
+/ok
+*/
+ MSG_EMOTION_OK = 0x23d,
+/*20040804 to latest
+단축키 목록
+Shortcut List
+*/
+ MSG_SHORTCUT_LIST = 0x23e,
+/*20040804 to latest
+귀하의 계정은 보류되었습니다.
+Your account is suspended.
+*/
+ MSG_BAN_PAY_SUSPEND = 0x23f,
+/*20040804 to latest
+과금 정책 변경으로 인해 일시 종료됩니다. 다시 접속하여 주시기 바랍니다.
+Your connection is terminated due to change in the billing policy. Please connect again.
+*/
+ MSG_BAN_PAY_CHANGE = 0x240,
+/*20040804 to latest
+어카운트 서버에 인증된 IP와 귀하의 IP가 달라 연결을 종료합니다.
+Your connection is terminated because your IP doesn't match the authorized IP from the account server.
+*/
+ MSG_BAN_PAY_WRONGIP = 0x241,
+/*20040804 to latest
+게임방 IP에서 개인 종량제 과금을 막기 위해 연결을 종료합니다. 개인 종량제 과금을 사용하기 위해서는 게임방IP로 등록이 되지 않은 IP를 사용해 주세요.
+Your connection is terminated to prevent charging from your account's play time.
+*/
+ MSG_BAN_PAY_PNGAMEROOM = 0x242,
+/*20040804 to latest
+귀하는 운영자에 의해 강제 종료 되었습니다.
+You have been forced to disconnect by the Game Master Team.
+*/
+ MSG_BAN_OP_FORCE = 0x243,
+/*20040804 to latest
+무게가 90%를 초과하여 스킬을 사용할 수 없습니다.
+You can't use this Skill because you are over your Weight Limit.
+*/
+ MSG_USESKILL_FAIL_WEIGHTOVER = 0x244,
+/*20040804 to latest
+무명
+Nameless
+*/
+ MSG_NAMELESS_USER = 0x245,
+/*20040804 to latest
+축하합니다. %s님의 현재 랭킹이 %d위로 상승하였습니다.
+Congratulations! %s ranking has gone up to %d.
+*/
+ MSG_RANK_IN_TEN = 0x246,
+/*20040804 to latest
+안타깝게도 %s님의 현재 랭킹이 %d위로 하락하였습니다.
+What a pity! %s ranking has gone down to %d.
+*/
+ MSG_RANK_OUT_TEN = 0x247,
+/*20040804 to latest
+Pet Info
+*/
+ MSG_PET_INFO = 0x248,
+/*20040804 to latest
+만복도
+Hunger
+*/
+ MSG_PET_HUNGRY = 0x249,
+/*20040804 to latest
+친밀도
+Intimacy
+*/
+ MSG_PET_FRIENDLY = 0x24a,
+/*20040804 to latest
+상점과 채팅방을 동시에 열수 없습니다.
+Please avoid opening a chatroom while vending.
+*/
+ MSG_CANT_OPEN_STORE_WHILE_CHAT = 0x24b,
+/*20040804 to latest
+개
+Total
+*/
+ MSG_EA4 = 0x24c,
+/*20040804 to latest
+%s 를 전투불능으로 만들었습니다.
+You have knocked down %s.
+*/
+ MSG_SLAIN = 0x24d,
+/*20040804 to latest
+%s 님에 의해 전투불능 상태가 되었습니다.
+You have been knocked down by %s.
+*/
+ MSG_SLAINBY = 0x24e,
+/*20040804 to latest
+먹이 - '%s' 아이템이 존재하지 않습니다..
+Feed - "%s" is not available.
+*/
+ MSG_NOT_EXIST_PET_FOOD = 0x24f,
+/*20040804 to latest
+먹이 주기
+Feed Pet
+*/
+ MSG_PET_FEEDING = 0x250,
+/*20040804 to latest
+퍼포먼스
+Performance
+*/
+ MSG_PET_PERFORMANCE = 0x251,
+/*20040804 to latest
+알로 되돌리기
+Return to Egg Shell
+*/
+ MSG_PET_RETURN_EGG = 0x252,
+/*20040804 to latest
+악세사리 해제
+Unequip Accessory
+*/
+ MSG_PET_ACC_OFF = 0x253,
+/*20040804 to latest
+Pet 상태 보기
+Check Pet Status
+*/
+ MSG_PET_SHOWINFO = 0x254,
+/*20040804 to latest
+악세사리
+Accessory
+*/
+ MSG_PET_ACCESSARY = 0x255,
+/*20040804 to latest
+장착됨
+Equipped
+*/
+ MSG_ITEM_EQUIPED = 0x256,
+/*20040804 to latest
+펫 리스트
+Pet List
+*/
+ MSG_PET_EGG_LIST = 0x257,
+/*20040804 to latest
+장착 안됨
+Unequipped
+*/
+ MSG_ITEM_UNEQUIPED = 0x258,
+/*20040804 to latest
+정말로 먹이를 주시겠습니까?
+Are you sure that you want to feed your pet?
+*/
+ MSG_SURE_TO_FEED_PET = 0x259,
+/*20040804 to latest
+가격을 쓰실땐 숫자(0~9)만 써주십시오.
+Only the numbers (0~9) are available.
+*/
+ MSG_CAN_INPUT_NUMBER_ONLY = 0x25a,
+/*20040804 to latest
+감정되지 않은 아이템은 판매할 수 없습니다.
+You cannot sell unidentified items.
+*/
+ MSG_CANT_SELL_UNIDENTIFIED_ITEM = 0x25b,
+/*20040804 to latest
+가격이 0 Zeny인 아이템이 존재합니다. 계속 하시겠습니까?
+Item at 0 Zeny exists. Do you wish to continue?
+*/
+ MSG_YOU_HAVE_FREE_ITEM_ON_SHOP = 0x25c,
+/*20040804 to latest
+[새로 추가된 이모션 리스트]
+[New Emotion List]
+*/
+ MSG_NEW_EMOTION_LIST = 0x25d,
+/*20040804 to latest
+일본쪽 베타 사용자들에게 전하는 메세지. -> 겅호에서 재가입 하세요.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE1 = 0x25e,
+/*20040804 to latest
+일본쪽 과금이 종료된 사용자들에게 전하는 메세지. -> 돈내라. 두 번내라.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE2 = 0x25f,
+/*20040804 to latest
+같은 계정의 캐릭터가 이미 가입되어있습니다.
+Character in the same account already joined.
+*/
+ MSG_ALREADY_SAME_AID_JOINED = 0x260,
+/*20040804 to latest
+(%d 명) - 만18세이상
+(%d ppl) - over the age 18
+*/
+ MSG_SERVER_PROPERTY_ADULT = 0x261,
+/*20040804 to latest
+ 프로보크 상태가 되었습니다.
+Provoke initiated.
+*/
+ MSG_ENST_PROVOKE = 0x262,
+/*20040804 to latest
+ 프로보크 상태가 해제되었습니다.
+Provoke canceled.
+*/
+ MSG_DSST_PROVOKE = 0x263,
+/*20040804 to latest
+ 인듀어 상태가 되었습니다.
+Endure initiated.
+*/
+ MSG_ENST_ENDURE = 0x264,
+/*20040804 to latest
+ 인듀어 상태가 해제되었습니다.
+Endure canceled.
+*/
+ MSG_DSST_ENDURE = 0x265,
+/*20040804 to latest
+ 집중력 향상 상태가 되었습니다.
+Improve Concentration initiated.
+*/
+ MSG_ENST_CONCENTRATION = 0x266,
+/*20040804 to latest
+ 집중력 향상 상태가 해제되었습니다.
+Improve Concentration canceled.
+*/
+ MSG_DSST_CONCENTRATION = 0x267,
+/*20040804 to latest
+ 하이딩 상태가 되었습니다.
+Hiding Initiated.
+*/
+ MSG_ENST_HIDING = 0x268,
+/*20040804 to latest
+ 하이딩 상태가 해제되었습니다.
+Hiding Canceled.
+*/
+ MSG_DSST_HIDING = 0x269,
+/*20040804 to latest
+ 클로킹 상태가 되었습니다.
+Cloaking initiated.
+*/
+ MSG_ENST_CLOAKING = 0x26a,
+/*20040804 to latest
+ 클로킹 상태가 해제되었습니다.
+Cloaking canceled.
+*/
+ MSG_DSST_CLOAKING = 0x26b,
+/*20040804 to latest
+ 독을 반사 할 수 있는 상태가 되었습니다.
+Poison React initiated.
+*/
+ MSG_ENST_POISONREACT = 0x26c,
+/*20040804 to latest
+ 포이즌 리액트 상태가 해제되었습니다.
+Poison React canceled.
+*/
+ MSG_DSST_POISONREACT = 0x26d,
+/*20040804 to latest
+ 이동속도가 감소하였습니다.
+Speed reduced.
+*/
+ MSG_ENST_QUAGMIRE = 0x26e,
+/*20040804 to latest
+ 콰그마이어 상태가 해제되었습니다.
+Quagmire canceled.
+*/
+ MSG_DSST_QUAGMIRE = 0x26f,
+/*20040804 to latest
+ 방어력이 증가되었습니다.
+Defense increased.
+*/
+ MSG_ENST_ANGELUS = 0x270,
+/*20040804 to latest
+ 안젤루스 상태가 해제되었습니다.
+Angelus canceled.
+*/
+ MSG_DSST_ANGELUS = 0x271,
+/*20040804 to latest
+ 힘과 지능, 덱스가 증가하였습니다.
+Blessing aligned.
+*/
+ MSG_ENST_BLESSING = 0x272,
+/*20040804 to latest
+ 블레싱 상태가 해제되었습니다.
+Blessing canceled.
+*/
+ MSG_DSST_BLESSING = 0x273,
+/*20040804 to latest
+ 시그넘 크루시스를 사용하였습니다.
+Signum Crusis initiated.
+*/
+ MSG_ENST_CRUCIS = 0x274,
+/*20040804 to latest
+ 시그넘 크루시스 상태가 해제되었습니다.
+Signum Crusis canceled.
+*/
+ MSG_DSST_CRUCIS = 0x275,
+/*20040804 to latest
+ 독이 퍼지는 속도가 느려졌습니다.
+Slow Poison initiated.
+*/
+ MSG_ENST_SLOWPOISON = 0x276,
+/*20040804 to latest
+ 슬로우 포이즌 상태가 해제되었습니다.
+Slow Poison Canceled.
+*/
+ MSG_DSST_SLOWPOISON = 0x277,
+/*20040804 to latest
+ SP의 회복 속도가 향상 되었습니다.
+HP/SP recovery increased.
+*/
+ MSG_ENST_MAGNIFICAT = 0x278,
+/*20040804 to latest
+ 마니피캇 상태가 해제되었습니다.
+Magnificat canceled.
+*/
+ MSG_DSST_MAGNIFICAT = 0x279,
+/*20040804 to latest
+ 행운이 향상되었습니다.
+Luck increased.
+*/
+ MSG_ENST_GLORIA = 0x27a,
+/*20040804 to latest
+ 글로리아 상태가 해제되었습니다.
+Gloria canceled.
+*/
+ MSG_DSST_GLORIA = 0x27b,
+/*20040804 to latest
+ 1회 공격에 두 배 데미지를 받는 상태가 되었습니다.
+You will received double damage from all attacking opponents.
+*/
+ MSG_ENST_LEXAETERNA = 0x27c,
+/*20040804 to latest
+ 렉스에테르나 상태가 해제되었습니다.
+Lex Eterna canceled.
+*/
+ MSG_DSST_LEXAETERNA = 0x27d,
+/*20040804 to latest
+ 공격속도가 증가하였습니다.
+Attack Speed increased.
+*/
+ MSG_ENST_ADRENALINE = 0x27e,
+/*20040804 to latest
+ 공격속도가 감소하였습니다.
+Attack Speed reduced.
+*/
+ MSG_DSST_ADRENALINE = 0x27f,
+/*20040804 to latest
+ 페코에 올라 탔습니다.
+You've just been on a Peco Peco.
+*/
+ MSG_ENST_RIDING = 0x280,
+/*20040804 to latest
+ 페코에서 내렸습니다.
+You've just got off of a Peco Peco.
+*/
+ MSG_DSST_RIDING = 0x281,
+/*20040804 to latest
+ 팔콘을 장착하였습니다.
+You've just carried a Falcon with.
+*/
+ MSG_ENST_FALCON = 0x282,
+/*20040804 to latest
+ 팔콘을 풀어주었습니다.
+You've just released a Falcon.
+*/
+ MSG_DSST_FALCON = 0x283,
+/*20040804 to latest
+ 죽은척하기 상태가 되었습니다.
+Play Dead initiated.
+*/
+ MSG_ENST_TRICKDEAD = 0x284,
+/*20040804 to latest
+ 죽은척하기 상태가 해제되었습니다.
+Play Dead canceled.
+*/
+ MSG_DSST_TRICKDEAD = 0x285,
+/*20040804 to latest
+ 힘이 강해졌습니다.
+STR improved.
+*/
+ MSG_ENST_SHOUT = 0x286,
+/*20040804 to latest
+ 힘이 원래대로 돌아왔습니다.
+STR turned back to normal.
+*/
+ MSG_DSST_SHOUT = 0x287,
+/*20040804 to latest
+ 에너지코트 상태가 되었습니다.
+Energy Coat initiated.
+*/
+ MSG_ENST_ENERGYCOAT = 0x288,
+/*20040804 to latest
+ 에너지코트 상태가 해제되었습니다.
+Energy Coat canceled.
+*/
+ MSG_DSST_ENERGYCOAT = 0x289,
+/*20040804 to latest
+ 방어구가 파괴되었습니다.
+Armor destroyed.
+*/
+ MSG_ENST_BROKENAMOR = 0x28a,
+/*20040804 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENAMOR = 0x28b,
+/*20040804 to latest
+ 무기가 파괴되었니다.
+Weapon destroyed.
+*/
+ MSG_ENST_BROKENWEAPON = 0x28c,
+/*20040804 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENWEAPON = 0x28d,
+/*20040804 to latest
+ 환영상태가 되었습니다.
+Invisibility initiated.
+*/
+ MSG_ENST_ILLUSION = 0x28e,
+/*20040804 to latest
+ 환영상태가 해제되었습니다.
+Invisibility canceled.
+*/
+ MSG_DSST_ILLUSION = 0x28f,
+/*20040804 to latest
+과금 정보 처리가 늦어지고 있어 접속이 지연되고 있습니다. 잠시 후에 다시 시도해 주시기 바랍니다.
+Sorry. It is delayed due to the process of payment. Please re-connect in a minute.
+*/
+ MSG_REFUSE_BLOCK_TEMPORARY = 0x290,
+/*20040804 to 20060403
+장착된 화살을 해제 하여야 합니다.
+20060410 to 20061009
+장착된 화살 또는 탄환을 해제 하여야 합니다.
+20061016 to latest
+장착된 화살/탄환/수리검 을 해제해야합니다.
+You must unequip ammunition first.
+*/
+ MSG_UNEQUIP_ARROW = 0x291,
+/*20040804 to latest
+화살 목록
+Arrow List
+*/
+ MSG_ARROW_LIST = 0x292,
+/*20040804 to latest
+카트 목록
+Cart List
+*/
+ MSG_CART_LIST = 0x293,
+/*20040804 to latest
+카트를 장착한 상태여야 합니다.
+You must have a Pushcart.
+*/
+ MSG_MUST_EQUIP_CART = 0x294,
+/*20040804 to latest
+채팅방을 개설 할 수 없습니다.
+You cannot open a Chat Window.
+*/
+ MSG_CANT_MAKE_CHAT_ROOM = 0x295,
+/*20040804 to latest
+라그나로크 홈페이지로 접속하여 계정을 만듭니다. 처음 계정을 만드시면 3일 동안은 무료로 이용하실 수 있습니다.
+Registering an account is the first step to accessing the game. Do you want to visit the registration page now?
+*/
+ MSG_3DAY_FREE = 0x296,
+/*20040804 to latest
+앉은 상태에서는 이 아이템을 사용할 수 없습니다.
+You cannot use this item while sitting.
+*/
+ MSG_CANT_USE_WHEN_SITDOWN = 0x297,
+/*20040804 to latest
+채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+Your use of skills and chat will be blocked for the next %d minutes.
+*/
+ MSG_BAD_MANNER_REMAIN = 0x298,
+/*20040804 to latest
+채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+Your use of skills and chat have been reinstated.
+*/
+ MSG_BAD_MANNER_END = 0x299,
+/*20040804 to latest
+-[장착안됨]
+- [Not equipped]
+*/
+ MSG_REF_UNEQUIP = 0x29a,
+/*20040804 to latest
+배고픔
+Very Hungry
+*/
+ MSG_VERY_HUNGRY = 0x29b,
+/*20040804 to latest
+출출함
+Hungry
+*/
+ MSG_HUNGRY = 0x29c,
+/*20040804 to latest
+보통
+Normal
+*/
+ MSG_NORMAL = 0x29d,
+/*20040804 to latest
+배부름
+Satisfied
+*/
+ MSG_REPLETE = 0x29e,
+/*20040804 to latest
+아주 배부름
+Stuffed
+*/
+ MSG_VERY_REPLETE = 0x29f,
+/*20040804 to latest
+서먹서먹함
+Awkward
+*/
+ MSG_VERY_AWKWARD = 0x2a0,
+/*20040804 to latest
+어색함
+Shy
+*/
+ MSG_AWKWARD = 0x2a1,
+/*20040804 to latest
+친함
+Cordial
+*/
+ MSG_FRIENDLY = 0x2a2,
+/*20040804 to latest
+절친함
+Loyal
+*/
+ MSG_VERY_FRIENDLY = 0x2a3,
+/*20040804 to latest
+알수 없음
+Unknown
+*/
+ MSG_UNKNOWN = 0x2a4,
+/*20040804 to 20080513
+(태국)귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+20080520 to latest
+귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d day %d hour %d minute.
+*/
+ MSG_BILLING_DAY_HOUR_MINUTES = 0x2a5,
+/*20040804 to 20080513
+(태국)이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+20080520 to latest
+이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+Your account is already connected to account server.
+*/
+ MSG_BAN_INFORMATION_REMAINED_ANOTHER_ACCOUNT = 0x2a6,
+/*20040804 to 20080513
+(태국)귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+20080520 to latest
+귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d hour %d minute.
+*/
+ MSG_BILLING_HOUR_MINUTES = 0x2a7,
+/*20040804 to 20080513
+(태국)귀하는 무료 사용자 입니다.
+20080520 to latest
+귀하는 무료 사용자 입니다.
+Your account is a free account.
+*/
+ MSG_BILLING_FREE_USER = 0x2a8,
+/*20040804 to 20080513
+(태국)이 계정으로 사크라이에 접속할수 없습니다.
+20080520 to latest
+이 계정으로 사크라이에 접속할수 없습니다.
+This account can't connect the Sakray server.
+*/
+ MSG_REFUSE_NONSAKRAY_ID_BLOCKED = 0x2a9,
+/*20040804 to latest
+펫의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Your pet name must be 23 characters or less.
+*/
+ MSG_PETNAME_IN23 = 0x2aa,
+/*20040804 to latest
+이름은 단 한번만 바꿀수 있습니다. 펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You may change your pet's name only once. Your pet's name will be changed to ^0000ff^0000ff %s^000000^000000. Do you wish to continue?
+*/
+ MSG_PETNAME_CHANGE_ONLYONCE = 0x2ab,
+/*20040804 to latest
+/폰트
+/font
+*/
+ MSG_NAMEBALLOON_TYPE = 0x2ac,
+/*20040804 to latest
+길드에 남은 제니가 부족하여 작업이 실패하였습니다.
+Your guild lacks the funds to pay for this venture.
+*/
+ MSG_GUILDZENY_NOT_ENOUGH = 0x2ad,
+/*20040804 to latest
+길드가 소유할 수 있는 최대 금액을 초과하여 작업이 실패하였습니다.
+Your guild zeny limit prevents you from performing this action.
+*/
+ MSG_GUILDZENY_OVER = 0x2ae,
+/*20040804 to latest
+이펙트 간략화 On
+Simplified effects have been activated.
+*/
+ MSG_MINEFFECT_ON = 0x2af,
+/*20040804 to latest
+이펙트 간략화 Off
+Simplified effects have been deactivated.
+*/
+ MSG_MINEFFECT_OFF = 0x2b0,
+/*20040804 to latest
+자본금
+Required Fee
+*/
+ MSG_CAPITAL = 0x2b1,
+/*20040804 to latest
+아이템을 바닥에 버리려면, 아이템 창을 열어 주십시오.
+If you wish to drop an item, you must first open your Item Window (alt+e).
+*/
+ MSG_OPEN_ITEMWND_TO_THROW = 0x2b2,
+/*20040804 to latest
+PC방 요금이 종료하여 개인 요금제로 전환합니다. 개인 요금으로 게임을 계속 하시겠습니까?
+Internet Cafe Time Plan has been ended. Would you like to continue the game with your personal play time?
+*/
+ MSG_ASK_PNGAMEROOM = 0x2b3,
+/*20040804 to latest
+
+*/
+ MSG_REPLY_REMAINTIME = 0x2b4,
+/*20040804 to latest
+
+*/
+ MSG_INFO_REMAINTIME = 0x2b5,
+/*20040804 to latest
+돈이 모자라거나, 가질 수 있는 최대 금액을 초과하였습니다.
+Your lack of zeny or your zeny limit have prevented you from performing this action.
+*/
+ MSG_OVER_OR_LOW_MONEY = 0x2b6,
+/*20040804 to latest
+전투불능 상태가 되었습니다. esc키를 누르시면 선택창이 뜹니다.
+Your character has fainted. Push the ESC key to restart.
+*/
+ MSG_PRESS_ESC_TO_RESTART = 0x2b7,
+/*20040804 to latest
+ %d 개 획득
+- %d obtained.
+*/
+ MSG_EA_OBTAIN = 0x2b8,
+/*20040804 to latest
+스펠 리스트
+Spell List
+*/
+ MSG_SPELL_LIST = 0x2b9,
+/*20040804 to latest
+/최소화
+/minimize
+*/
+ MSG_MINEFFECT = 0x2ba,
+/*20040804 to latest
+이 아이템은 손상되어 있습니다..
+This item has been damaged.
+*/
+ MSG_DAMAGED_ITEM = 0x2bb,
+/*20040804 to latest
+/noshift : 쉬프트를 누르지않고 힐로 적을 공격할수있게됩니다 On Off
+/noshift: You may use your ''force heal'' ability without the Shift key. On | Off
+*/
+ MSG_EXPLAIN_NOSHIFT = 0x2bc,
+/*20040804 to latest
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns ON]
+[no shift] option activated. [ON]
+*/
+ MSG_NOSHIFT_ON = 0x2bd,
+/*20040804 to latest
+시프트를 눌러야 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+[no shift] option deactivated. [OFF]
+*/
+ MSG_NOSHIFT_OFF = 0x2be,
+/*20040804 to latest
+MSI_REFUSE_BAN_BY_DBA
+*/
+ MSG_REFUSE_BAN_BY_DBA = 0x2bf,
+/*20040804 to latest
+MSI_REFUSE_EMAIL_NOT_CONFIRMED
+*/
+ MSG_REFUSE_EMAIL_NOT_CONFIRMED = 0x2c0,
+/*20040804 to latest
+MSI_REFUSE_BAN_BY_GM
+*/
+ MSG_REFUSE_BAN_BY_GM = 0x2c1,
+/*20040804 to latest
+MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+*/
+ MSG_REFUSE_TEMP_BAN_FOR_DBWORK = 0x2c2,
+/*20040804 to latest
+MSI_REFUSE_SELF_LOCK
+*/
+ MSG_REFUSE_SELF_LOCK = 0x2c3,
+/*20040804 to latest
+MSI_REFUSE_NOT_PERMITTED_GROUP
+*/
+ MSG_REFUSE_NOT_PERMITTED_GROUP = 0x2c4,
+/*20040804 to latest
+MSI_REFUSE_WAIT_FOR_SAKRAY_ACTIVE
+*/
+ MSG_REFUSE_WAIT_FOR_SAKRAY_ACTIVE = 0x2c5,
+/*20040804 to latest
+/aura : 오오라를 간략화 시킬수있습니다 On Off
+/aura: Simplify Aura effect On | Off
+*/
+ MSG_EXPLAIN_AURA = 0x2c6,
+/*20040804 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_AURA_ON = 0x2c7,
+/*20040804 to latest
+오오라가 간략화되서 표시됩니다 [오오라 OFF]
+Simplify Aura enabled. [ON]
+*/
+ MSG_AURA_OFF = 0x2c8,
+/*20040804 to latest
+채팅금지 기록 %d 회
+Chat block record %d times
+*/
+ MSG_PROHIBIT_LOG = 0x2c9,
+/*20040804 to latest
+채팅 금지 리스트
+Chat block list
+*/
+ MSG_PROHIBIT_LIST = 0x2ca,
+/*20040804 to latest
+/이름표시 or /showname : 캐릭터의 이름 표시 방식을 변경합니다.
+/showname: Change the name font type.
+*/
+ MSG_EXPLAIN_SHOWNAMETYPE = 0x2cb,
+/*20040804 to latest
+/noctrl : 콘트롤을 누르지않아도 자동공격이 됩니다. On Off
+/noctrl | /nc: Auto attack without pressing ctrl key. On | Off
+*/
+ MSG_EXPLAIN_NOCTRL = 0x2cc,
+/*20040804 to latest
+콘트롤을 누르지 않아도 자동공격을 합니다 [/nc ON]
+Use auto attack without Ctrl. [Auto attack ON]
+*/
+ MSG_NOCTRL_ON = 0x2cd,
+/*20040804 to latest
+콘트롤을 눌러야 자동공격을 합니다 [/nc OFF]
+Use auto attack with Ctrl. [Auto attack OFF]
+*/
+ MSG_NOCTRL_OFF = 0x2ce,
+/*20040804 to latest
+채팅 금지 주기
+Mute this player.
+*/
+ MSG_APPEND_PROHIBIT = 0x2cf,
+/*20040804 to latest
+채팅 금지 완전 풀기 & 로그 삭제
+Unmute player & Erase mute time.
+*/
+ MSG_ERASE_PROHIBIT = 0x2d0,
+/*20040804 to latest
+채팅 금지 시간 줄이기(로그 삭제 안됨)
+Decrease Player Mute time.
+*/
+ MSG_REDUCE_PROHIBIT = 0x2d1,
+/*20040804 to latest
+폰트가 정상적으로 바뀌었습니다 [이름표시방식 1]
+Normal Font Displayed. [showname type 1]
+*/
+ MSG_SHOWNAME_ON = 0x2d2,
+/*20040804 to latest
+폰트가 가늘게 바뀌면서 파티명도 표시됩니다 [이름표시방식 2]
+Font will be thin and party name will be shown [showname type 2]
+*/
+ MSG_SHOWNAME_OFF = 0x2d3,
+/*20040804 to latest
+/doridori : 연속해서 이 명령어를 쳐주면 캐릭터가 도리도리 ^^;;
+/doridori: Shake head
+*/
+ MSG_EXPLAIN_DORIDORI = 0x2d4,
+/*20040804 to latest
+인터넷 카페에서 과금을 하고 있습니다.
+Internet room is paying now.
+*/
+ MSG_BILLING_INTERNET_CAFE = 0x2d5,
+/*20040804 to latest
+정액제 과금은 %d일 %d시간 %d분이 남았습니다.
+종량제 과금은 %d시간 %d분이 남았습니다.
+Prepaid voucher validate until %d days %d hours %d minutes later.
+Time limit voucher validate untill %d hours %d minutes later.
+*/
+ MSG_BILLING_BOTH = 0x2d6,
+/*20040804 to latest
+/bingbing : 연속해서 이 명령어를 쳐주면 캐릭터가 빙글빙글 ^^;;
+/bingbing: Rotates player counter clockwise.
+*/
+ MSG_EXPLAIN_BINGBING = 0x2d7,
+/*20040804 to latest
+/bangbang : 연속해서 이 명령어를 쳐주면 캐릭터가 뱅글뱅글 ^^;;
+/bangbang: Rotates player clockwise.
+*/
+ MSG_EXPLAIN_BANGBANG = 0x2d8,
+/*20040804 to latest
+/skillfail : 빨간색의 스킬사용 실패 메세지를 표시하지 않습니다 On Off
+/skillfail: Display red font message when skill fails. On | Off
+*/
+ MSG_EXPLAIN_SKILLFAIL = 0x2d9,
+/*20040804 to latest
+스킬사용 실패 메세지를 표시합니다 [/sf ON]
+Skill fail messages will be displayed. [Display On]
+*/
+ MSG_SKILLFAIL_ON = 0x2da,
+/*20040804 to latest
+스킬사용 실패 메세지를 표시하지 않습니다 [/sf OFF]
+Skill fail messages will not be displayed. [Display OFF]
+*/
+ MSG_SKILLFAIL_OFF = 0x2db,
+/*20040804 to latest
+/notalkmsg : 채팅내용을 채팅창에 표시하지 않습니다 On Off
+/notalkmsg: Chat will not be displayed in chat window. On | Off
+*/
+ MSG_EXPLAIN_NOTALKMSG = 0x2dc,
+/*20040804 to latest
+채팅내용을 채팅창에 표시합니다 [/nm ON]
+Chat content will be displayed in the chat window. [Display ON]
+*/
+ MSG_NOTALKMSG_ON = 0x2dd,
+/*20040804 to latest
+채팅내용을 채팅창에 표시하지않습니다 [/nm OFF]
+Chat content will not be displayed in the chat window. [Display OFF]
+*/
+ MSG_NOTALKMSG_OFF = 0x2de,
+/*20040804 to latest
+/set1 : /nc + /showname + /sf + /wi, /set2 : + /q3
+/set1: /noctrl + /showname + /skillfail
+*/
+ MSG_EXPLAIN_SET1 = 0x2df,
+/*20040804 to latest
+/fog : FOG이펙트를 키거나 끌수있습니다 On Off
+/fog: Fog effect. On | Off
+*/
+ MSG_EXPLAIN_FOG = 0x2e0,
+/*20040804 to latest
+ 청혼을 해왔습니다. 승낙하시겠습니까?
+You have received a marriage proposal. Do you accept?
+*/
+ MSG_SUGGEST_COUPLE = 0x2e1,
+/*20040804 to latest
+아이템 분배 방식
+Item sharing type
+*/
+ MSG_HOWITEMDIV = 0x2e2,
+/*20040804 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMDIV1 = 0x2e3,
+/*20040804 to latest
+균등하게 분배
+Shared
+*/
+ MSG_ITEMDIV2 = 0x2e4,
+/*20040804 to latest
+nProtect KeyCrypt
+*/
+ MSG_KEYCRYPT = 0x2e5,
+/*20040804 to latest
+Keyboard Driver가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+Keyboard Driver has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_INSTALL_KEYDRIVER = 0x2e6,
+/*20040804 to latest
+설치가 완료 되었습니다.
+
+시스템을 Reboot 합니다.
+Installation has been completed.
+
+System will be rebooted.
+*/
+ MSG_KEYCRYPT_REBOOT = 0x2e7,
+/*20040804 to latest
+설치 실패.
+Installation has been failed.
+*/
+ MSG_KEYCRYPT_INSTALLFAIL = 0x2e8,
+/*20040804 to latest
+키보드 보안을 적용하지 않고 계속합니다.
+Keyboard Security will be skipped.
+*/
+ MSG_KEYCRYPT_SKIPKEYCRYPT = 0x2e9,
+/*20040804 to latest
+키보드 보안에 필요한 파일이 존재하지 않습니다.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+Required file for Keyboard Security is not existing.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+*/
+ MSG_KEYCRYPT_NOKEYCRYPTFILE = 0x2ea,
+/*20040804 to latest
+USB Keyboard가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+USB Keyboard has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_USBKEYBOARD = 0x2eb,
+/*20040804 to latest
+ftp://ragnarok.nefficient.co.kr/pub/ragnarok/ragnarok0526.exe
+*/
+ MSG_FINDHACK_PATH = 0x2ec,
+/*20040804 to latest
+FindHack이 정상적으로 설치가 되어있지 않습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.(%d).
+FindHack is not installed correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.(%d).
+*/
+ MSG_FINDHACK_NOTINSTALLED = 0x2ed,
+/*20040804 to latest
+해킹툴이 존재하지만 치료가 정상적으로 되지 않았습니다. 라그나로크가 실행되지 않습니다.
+Hacking tool is existing but it hasn't been cleaned. Rangarok Online will not be executed.
+*/
+ MSG_FINDHACK_HACKTOOLEXIST = 0x2ee,
+/*20040804 to latest
+해킹툴 진단 프로그램이 정상적으로 다운로드 되지 않았습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+Hacking tool scan program has not been downloaded correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_CANTDOWNLOAD = 0x2ef,
+/*20040804 to latest
+NPX.DLL 등록에러 이거나 FindHack 구동에 필요한 파일이 없습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+NPX.DLL register error or there is no necessary file to run FindHack. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_NOFILE = 0x2f0,
+/*20040804 to latest
+예외사항이 발생했습니다. (02-3281-0361)로 문의해주세요. 리턴값(%d)
+Exceptional Error. Please contact the customer support. Return Value: (%d)
+*/
+ MSG_FINDHACK_EXCEPTION = 0x2f1,
+/*20040804 to latest
+종료버튼을 클릭 하셨습니다.
+Exit button has been clicked.
+*/
+ MSG_FINDHACK_EXITPRESSED = 0x2f2,
+/*20040804 to latest
+Findhack 업데이트 서버접근 실패하였습니다. 잠시 후에 다시 시도해 주시거나 그라비티 운영팀으로 연락해주시기 바랍니다.
+Unable to connect Findhack Update Server. Please try again or contact the customer support.
+*/
+ MSG_FINDHACK_UPDATEFAILED = 0x2f3,
+/*20040804 to latest
+사랑받고있는
+Beloved
+*/
+ MSG_NAMED_PET = 0x2f4,
+/*20040804 to latest
+/report or /신고 : 신고용 갈무리 파일을 저장합니다.
+/report: Save a chat log file.
+*/
+ MSG_REPORTCOMMAND_EXPLANATION = 0x2f5,
+/*20040804 to latest
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로 사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+Chat logs are not accepted as evidence for any ill-mannered violation on account of possible file modifications. However this feature is provided for players' personal reference.
+*/
+ MSG_REPORTTEXT_HEADER = 0x2f6,
+/*20040804 to latest
+당신을 사랑해요 ♡
+I love you.
+*/
+ MSG_LOVE_SKILL = 0x2f7,
+/*20040804 to latest
+화면 또는 이펙트가 밝아서 눈에 부담이 되시는분들은 모니터의 밝기를 조정해주시기바랍니다.
+Please adjust your monitor/video brightness if effects appear too bright.
+*/
+ MSG_EXPLAIN_BRIGHT = 0x2f8,
+/*20040804 to latest
+전체화면모드가 잘안되는 경우에 게임실행후 ALT+TAB으로 화면을 전환하면 잘되는 기종도 있습니다
+If full screen mode fails to work, it is suggested you alt+tab [or ctrl+esc] to inactivate and reactivate the Ragnarok Client.
+*/
+ MSG_EXPLAIN_ALTTAB = 0x2f9,
+/*20040804 to latest
+(%d 명) - 유료서버
+(%d players) - Pay to Play Server
+*/
+ MSG_SERVER_PROPERTY_PAY = 0x2fa,
+/*20040804 to latest
+(%d 명) - 무료서버
+(%d players) - Free Server
+*/
+ MSG_SERVER_PROPERTY_FREE = 0x2fb,
+/*20040804 to latest
+무료 회원은 유료 서버로 접속할 수 없습니다.
+Trial players can't connect Pay to Play Server.
+*/
+ MSG_CANT_CONNECT_TO_PAY_SERVER = 0x2fc,
+/*20040804 to latest
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [/q1 ON]
+Right click menu skills for F9 are Enabled.[/q1 ON]
+*/
+ MSG_QUICKSPELL_ON = 0x2fd,
+/*20040804 to latest
+마우스 우클릭으로 스킬을 사용하지 못합니다 [/q1 OFF]
+Right click menu skills for F9 are Disabled.[/q1 OFF]
+*/
+ MSG_QUICKSPELL_OFF = 0x2fe,
+/*20040804 to latest
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+/quickspell: Right-click menu enables you to use skills assigned to the F9 hotkey. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL = 0x2ff,
+/*20040804 to latest
+마우스의 WHEEL을 사용해서 F7 과 F8에 저장한 스킬을 사용합니다 [/q2 ON]
+Mouse wheel skills for F7 and F8 are Enabled.[/q2 ON]
+*/
+ MSG_QUICKSPELL2_ON = 0x300,
+/*20040804 to latest
+마우스 WHEEL로 스킬을 사용하지 못합니다 [/q2 OFF]
+Mouse wheel skills for F7 and F8 are Disabled.[/q2 OFF]
+*/
+ MSG_QUICKSPELL2_OFF = 0x301,
+/*20040804 to latest
+/quickspell2 : 마우스 WHEEL을 위,아래로 굴려서 F7과F8에 저장한 스킬을 사용합니다 On Off
+/quickspell2: By rolling the mouse wheel up and down, you are able to use skills registered on F7 and F8 hotkeys. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL2 = 0x302,
+/*20040804 to latest
+/q3 : /quickspell (/q1) + /quickspell2 (/q2)
+/q3: /quickspell (/q1) + /quickspell2 (/q2)
+*/
+ MSG_EXPLAIN_QUICKSPELL3 = 0x303,
+/*20040804 to latest
+/찌릿
+/bzz
+*/
+ MSG_EMOTION_STARE = 0x304,
+/*20040804 to latest
+/밥
+/rice
+*/
+ MSG_EMOTION_HUNGRY = 0x305,
+/*20040804 to latest
+/멋져
+/awsm
+*/
+ MSG_EMOTION_COOL = 0x306,
+/*20040804 to latest
+/메롱
+/meh
+*/
+ MSG_EMOTION_MERONG = 0x307,
+/*20040804 to latest
+/부끄
+/shy
+*/
+ MSG_EMOTION_SHY = 0x308,
+/*20040804 to latest
+/쓱쓱
+/pat
+*/
+ MSG_EMOTION_GOODBOY = 0x309,
+/*20040804 to latest
+/엠탐
+/mp
+*/
+ MSG_EMOTION_SPTIME = 0x30a,
+/*20040804 to latest
+/질질
+/slur
+*/
+ MSG_EMOTION_SEXY = 0x30b,
+/*20040804 to latest
+/컴온
+/com
+*/
+ MSG_EMOTION_COMEON = 0x30c,
+/*20040804 to latest
+/하품
+/yawn
+*/
+ MSG_EMOTION_SLEEPY = 0x30d,
+/*20040804 to latest
+/축하
+/grat
+*/
+ MSG_EMOTION_CONGRATULATION = 0x30e,
+/*20040804 to latest
+/피탐
+/hp
+*/
+ MSG_EMOTION_HPTIME = 0x30f,
+/*20040804 to latest
+/이모션 : 현재 사용가능한 이모션의 리스트를 보여줍니다.
+/emotion: views the emoticon list.
+*/
+ MSG_EXPLAIN_EMOTION = 0x310,
+/*20040804 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용합니다. [/bm ON]
+Skills assigned to shortcut windows 1, 2, 3 are Enabled. [/bm ON]
+*/
+ MSG_BATTLE_ON = 0x311,
+/*20040804 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용하지못합니다. [/bm OFF]
+Skills assigned to shortcut windows 1, 2, 3 are Disabled. [/bm OFF]
+*/
+ MSG_BATTLE_OFF = 0x312,
+/*20040804 to latest
+/battlemode : Q ~ O 를 누르면 스킬단축창2의 스킬들이 사용됩니다.
+/battlemode: allows you to use skills assigned to Shortcut Window 2 by pressing Q ~ O keys.
+*/
+ MSG_EXPLAIN_BATTLE = 0x313,
+/*20040804 to latest
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다.
+A ~ L keys allow you to use skills assigned to Shortcut Window 3.
+*/
+ MSG_EXPLAIN_BATTLE2 = 0x314,
+/*20040804 to latest
+라그나로크를 실행하실때 다른 프로그램을 띄우시면 게임이 느려질수도있습니다.
+Please remember, programs running in the background while playing may affect the game's performance.
+*/
+ MSG_EXPLAIN_LAG = 0x315,
+/*20040804 to 20041130
+천사님 제 목소리 들리세여? ^^;
+20041206 to latest
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+*/
+ MSG_SUPERNOVICE1 = 0x316,
+/*20040804 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_SUPERNOVICE2 = 0x317,
+/*20040804 to 20041130
+예여~
+20041206 to latest
+예요~
+Super Novice~
+*/
+ MSG_SUPERNOVICE3 = 0x318,
+/*20040804 to 20041130
+저 좀 도와주세여~ ㅠ_ㅠ
+20041206 to latest
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE4 = 0x319,
+/*20040804 to 20041011
+ 입양을 요청해왔습니다. 승낙하시겠습니까?
+20041018 to latest
+님께서 당신을 입양시키고 싶어하십니다. 승낙하시겠습니까?
+ wishes to adopt you. Do you accept?
+*/
+ MSG_SUGGEST_BABY = 0x31a,
+/*20040804 to latest
+ Z ~ > 을 누르면 스킬단축창1의 스킬들이 사용됩니다. On Off
+Z ~ > keys allow you to use skills assigned on shortcut window 1. On | Off
+*/
+ MSG_EXPLAIN_BATTLE3 = 0x31b,
+/*20040804 to latest
+ Space를 한번 누른뒤에 글자를 입력하면 채팅을 할수있습니다.
+Press the space bar to Chat when in Battle mode [/battlemode | /bm].
+*/
+ MSG_EXPLAIN_BATTLE4 = 0x31c,
+/*20040804 to latest
+게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다.
+"Either there's no Game Guard installed on the program or Game Guard is cracked. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_AUTH_GAMEGUARD = 0x31d,
+/*20040804 to latest
+윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다.
+Some of Windows system files have been damaged. Please re-install your Internet Explorer.
+*/
+ MSG_NPGAMEMON_ERROR_CRYPTOAPI = 0x31e,
+/*20040804 to latest
+게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다.
+"Failed to run Game Guard. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_EXECUTE = 0x31f,
+/*20040804 to latest
+불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다.
+"At least one hazardous program has been detected. Please, terminate all the unnecessary programs before executing Game Guard."
+*/
+ MSG_NPGAMEMON_ERROR_ILLEGAL_PRG = 0x320,
+/*20040804 to latest
+게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 방화벽 상태를 점검해보시기 바랍니다.
+"Game Guard update is canceled. If the disconnection continues, please, check your internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_ABORT = 0x321,
+/*20040804 to latest
+게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 인터넷 및 방화벽 상태를 점검해 보시기 바랍니다.
+"Failed to connect to Game Guard update server. Try to connect again later, or try to check the internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_CONNECT = 0x322,
+/*20040804 to latest
+게임가드 업데이트를 완료하지 못 했습니다. 바이러스 검사를 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정한 후 게임을 실행해 보시기 바랍니다.
+"Can't complete Game Guard update process. Please, try to execute a vaccine program to remove viruses. Or, please try to modify the settings of your PC managing tool if you are using any."
+*/
+ MSG_NPGMUP_ERROR_AUTH = 0x323,
+/*20040804 to latest
+/notrade : 거래신청을 자동으로 거절합니다 On Off
+/notrade: Declines trade offers automatically. On | Off
+*/
+ MSG_EXPLAIN_NOTRADE = 0x324,
+/*20040804 to 20040805
+거래신청을 자동으로 거절합니다 [/nt ON]
+20040809 to latest
+거래신청과 친구등록요청을 자동으로 거절합니다 [/nt ON]
+Auto decline trade offers has been Enabled. [/nt ON]
+*/
+ MSG_NOTRADE_ON = 0x325,
+/*20040804 to 20040805
+거래신청을 정상적으로 받습니다 [/nt OFF]
+20040809 to latest
+거래신청과 친구등록요청을 정상적으로 받습니다 [/nt OFF]
+Auto decline trade offers has been Disabled. [/nt OFF]
+*/
+ MSG_NOTRADE_OFF = 0x326,
+/*20040804 to latest
+같은 아이템은 한번에 30000개 이상은 살수 없습니다.
+You cannot buy more than 30,000ea items at once.
+*/
+ MSG_LIMIT_BUY_ITEM = 0x327,
+/*20040804 to latest
+재료가 충분하지 않습니다.
+You do not have enough ingredients.
+*/
+ MSG_NOT_ENOUGH_SOURCE = 0x328,
+/*20040804 to latest
+%s에 계정정보가 남아있습니다.
+Login information remains at %s.
+*/
+ MSG_ALREADY_CONNECT = 0x329,
+/*20040804 to 20040906
+해킹 관련 조사를 위해 로그인이 금지되 었습니다. 자세한 문의는 해킹관련 메일로 하여주시기 바랍니다.
+20040913 to latest
+계정도용 조사를 위해 로그인이 금지되었습니다. 자세한 문의는 계정도용 관련 문의 메일로 해주시기 바랍니다.
+Account has been locked for a hacking investigation. Please contact the GM Team for more information.
+*/
+ MSG_HACKING_INVESTIGATION = 0x32a,
+/*20040804 to latest
+귀하는 버그관련 조사중이므로 일시적으로 접속을 금합니다
+This account has been temporarily prohibited from login due to a bug-related investigation.
+*/
+ MSG_BUG_INVESTIGATION = 0x32b,
+/*20040804 to latest
+수리가능한 아이템
+Repairable items
+*/
+ MSG_REPAIRITEMLIST = 0x32c,
+/*20040804 to latest
+아이템 수리 성공
+Item has been successfully repaired.
+*/
+ MSG_ITEM_REPAIR_SUCCEESS = 0x32d,
+/*20040804 to latest
+아이템 수리 실패 (재료 또는 상대와의 거리등을 확인해주십시요)
+You have failed to repair this item. Please check the distance between you and opponent.
+*/
+ MSG_ITEM_REPAIR_FAIL = 0x32e,
+/*20040804 to latest
+시스템 상황을 지속적으로 체크 합니다.[운영자모드] [/sc ON]
+System process enabled [GM mode] [/sc ON]
+*/
+ MSG_SYSTEM_CHECK_ON = 0x32f,
+/*20040804 to latest
+시스템 상황을 지속적으로 체크 하지 않습니다.[운영자모드] [/sc OFF]
+System process disabled [GM mode] [/sc OFF]
+*/
+ MSG_SYSTEM_CHECK_OFF = 0x330,
+/*20040804 to latest
+/systemcheck : 시스템 상황을 지속적으로 체크 합니다.[운영자모드]
+/systemcheck: Check the system process [GM mode] On | Off
+*/
+ MSG_EXPLAIN_SYSTEM_CHECK = 0x331,
+/*20040804 to latest
+(%s)님이 친구 신청을 하셨습니다. 친구가 되시겠습니까?
+(%s) wishes to be friends with you. Would you like to accept?
+*/
+ MSG_SUGGEST_JOIN_FRIEND = 0x332,
+/*20040804 to latest
+더 이상 친구 등록을 하실수 없습니다.
+Your Friend List is full.
+*/
+ MSG_FRIEND_ADD_ME_OVERSIZE = 0x333,
+/*20040804 to latest
+(%s)님이 더 이상 친구 등록을 하실수 없습니다.
+(%s)'s Friend List is full.
+*/
+ MSG_FRIEND_ADD_OTHER_OVERSIZE = 0x334,
+/*20040804 to latest
+(%s)님과 친구가 되셨습니다.
+You have become friends with (%s).
+*/
+ MSG_FRIEND_ADD_SUCCEED = 0x335,
+/*20040804 to latest
+(%s)님이 친구 되기를 원하지 않습니다.
+(%s) does not want to be friends with you.
+*/
+ MSG_FRIEND_ADD_FALSE = 0x336,
+/*20040804 to latest
+이 캐릭터는 %s 까지 블럭되어있습니다.
+This character will be blocked to use until %s.
+*/
+ MSG_BLOCKED = 0x337,
+/*20040804 to latest
+천만제니 이상 입력하셔도 가격은 천만제니로 판매됩니다.
+Price will be fixed at 10,000,000 zeny, even if you enter higher price.
+*/
+ MSG_OVERPRICE = 0x338,
+/*20040804 to latest
+(적음)
+(Very low)
+*/
+ MSG_LITTLEUSER = 0x339,
+/*20040804 to latest
+(약간 적음)
+(Low)
+*/
+ MSG_ALITTLEUSER = 0x33a,
+/*20040804 to latest
+(보통)
+(Normal)
+*/
+ MSG_NORMLEUSER = 0x33b,
+/*20040804 to latest
+(많음)
+(High)
+*/
+ MSG_MANYUSER = 0x33c,
+/*20040804 to latest
+(매우 많음)
+(Very high)
+*/
+ MSG_VERYMANYUSER = 0x33d,
+/*20040804 to latest
+비매너에 의해 운영자로부터 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d minutes by the GM Team.
+*/
+ MSG_GM_BAD_MANNER_START = 0x33e,
+/*20040804 to latest
+GM에 의한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_REMAIN = 0x33f,
+/*20040804 to latest
+GM에 의한 채팅금지가 해지 되었습니다.
+You have been released from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_END = 0x340,
+/*20040804 to latest
+도배 방지 시스템으로 인한 자동 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d as an automatic penalty.
+*/
+ MSG_AUTO_BAD_MANNER_START = 0x341,
+/*20040804 to latest
+도배 방지 시스템으로 인한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from auto penalty.
+*/
+ MSG_AUTO_BAD_MANNER_REMAIN = 0x342,
+/*20040804 to latest
+도배 방지 시스템으로 인한 채팅금지가 해지되었습니다. 게임진행 시에는 도배에 대해서 주의하여 주시기 바랍니다.
+You have been released from the auto penalty. Please refrain from spamming in-game.
+*/
+ MSG_AUTO_BAD_MANNER_END = 0x343,
+/*20040804 to latest
+%s님과 %s님이 이혼하셨습니다.
+%s and %s have divorced from each other.
+*/
+ MSG_DIVORCE = 0x344,
+/*20040804 to 20041108
+星鬪士 %s의 태양의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE1 = 0x345,
+/*20040804 to 20041108
+星鬪士 %s의 달의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE2 = 0x346,
+/*20040804 to 20041108
+星鬪士 %s의 별의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE3 = 0x347,
+/*20040804 to 20041108
+星鬪士 %s의 태양의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 장소는 %s 입니다
+Gravity %s's Solar Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 장소는 %s 입니다
+*/
+ MSG_STARPLACE4 = 0x348,
+/*20040804 to 20041108
+星鬪士 %s의 달의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 장소는 %s 입니다
+Gravity %s's Luna Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 장소는 %s 입니다
+*/
+ MSG_STARPLACE5 = 0x349,
+/*20040804 to 20041108
+星鬪士 %s의 별의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 장소는 %s 입니다
+Gravity %s's Stellar Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 장소는 %s 입니다
+*/
+ MSG_STARPLACE6 = 0x34a,
+/*20040804 to 20041108
+星鬪士 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER1 = 0x34b,
+/*20040804 to 20041108
+星鬪士 %s의 달의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER2 = 0x34c,
+/*20040804 to 20041108
+星鬪士 %s의 별의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER3 = 0x34d,
+/*20040804 to 20041108
+星鬪士 %s의 태양의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 몬스터는 %s 입니다
+Gravity %s's Solar Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER4 = 0x34e,
+/*20040804 to 20041108
+星鬪士 %s의 달의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 몬스터는 %s 입니다
+Gravity %s's Luna Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER5 = 0x34f,
+/*20040804 to 20041108
+星鬪士 %s의 별의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 몬스터는 %s 입니다
+Gravity %s's Stellar Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER6 = 0x350,
+/*20040804 to latest
+/window : 창 위치 이동시 다른 창과 달라붙는 속성이 들어갑니다 On Off
+/window: Display windows will snap/dock together. On | Off
+*/
+ MSG_EXPLAIN_WINDOW = 0x351,
+/*20040804 to latest
+창 위치 이동시 다른 창과 잘 붙습니다 [/wi ON]
+Display window docking enabled. [/wi ON]
+*/
+ MSG_WINDOW_ON = 0x352,
+/*20040804 to latest
+창 위치 이동시 다른 창과 붙으려는 속성을 가지지 않습니다 [/wi OFF]
+Display window docking disabled. [/wi OFF]
+*/
+ MSG_WINDOW_OFF = 0x353,
+/*20040804 to latest
+/pvpinfo : 자신의 PVP 승패와 PVP 포인트를 알 수 있습니다.
+/pvpinfo: shows your PVP result and PVP points.
+*/
+ MSG_EXPLAIN_PVP_INFO = 0x354,
+/*20040804 to latest
+현재 %d승, %d패, PVP포인트는 %d입니다.
+You have won %d times and have lost %d times in PVP. Current points %d.
+*/
+ MSG_PVP_INFO = 0x355,
+/*20040804 to latest
+매너 포인트를 성공적으로 보냈습니다.
+A manner point has been successfully aligned.
+*/
+ MSG_SEND_MANNER_POINT = 0x356,
+#if PACKETVER >= 20040809
+/*20040809 to latest
+현재 이곳은 PK 가능 지역입니다. 불의의 공격에 유의 하시기 바랍니다.
+You are in a PK area. Please beware of sudden attack.
+*/
+ MSG_PKZONE = 0x357,
+#endif
+#if PACKETVER >= 20040817
+/*20040817 to latest
+게임가드 업데이트가 바이러스나 스파이웨어와의 충돌로 실패했습니다. 백신 프로그램/스파이웨어 제거 프로그램을 사용한 후 접속해 주십시기 바랍니다
+Game Guard update has been failed when either Virus or Spyware conflicted with. Please, Uninstall Spyware and Virus protection program before you log in.
+*/
+ MSG_NPGAMEMON_ERROR_100ERROR = 0x358,
+#endif
+#if PACKETVER >= 20040823
+/*20040823 to latest
+윈도우 호환성 문제로 프로그램을 종료합니다. 게임을 다시 실행해 주시기 바랍니다
+Program has encountered an error related to Windows compatibility. Please start the game again.
+*/
+ MSG_NPGAMEMON_XP_COMPATIBILITY = 0x359,
+#endif
+#if PACKETVER >= 20040906
+/*20040906 to latest
+채팅, 스킬, 아이템을 사용할수없게 되었습니다.
+You have been blocked from chatting, using skills and items.
+*/
+ MSG_PK_HONOR = 0x35a,
+/*20040906 to latest
+캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while this character is being deleted.
+*/
+ MSG_DELETING_CHAR = 0x35b,
+/*20040906 to latest
+결혼 상대자의 캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while your spouse character is being deleted.
+*/
+ MSG_DELETING_SPOUSE_CHAR = 0x35c,
+#endif
+#if PACKETVER >= 20040913
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE = 0x35d,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN = 0x35e,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN = 0x35f,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER = 0x360,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE = 0x361,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT = 0x362,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF = 0x363,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT = 0x364,
+/*20040913 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST = 0x365,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD = 0x366,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH = 0x367,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER = 0x368,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN = 0x369,
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE_W = 0x36a,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN_W = 0x36b,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN_W = 0x36c,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER_W = 0x36d,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE_W = 0x36e,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT_W = 0x36f,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF_W = 0x370,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT_W = 0x371,
+/*20040913 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST_W = 0x372,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD_W = 0x373,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH_W = 0x374,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER_W = 0x375,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN_W = 0x376,
+#endif
+#if PACKETVER >= 20041018
+/*20041018 to latest
+(%s)님을 아이로 입양신청
+Send an adoption request to %s
+*/
+ MSG_REQ_JOIN_BABY = 0x377,
+/*20041018 to 20041025
+아이가 되시면 전승을 하실수 없게 됩니다. 그래도 괜찮습니까?
+20041101 to latest
+아이가 되면 전승을 할수없고 스텟은 80이상 올릴수없게되며 HP와 SP가 줄어듭니다. 그래도 괜찮습니까?
+When you become a child, you will be unable to become a Transcendent Class character, all stats will be limited to a maximum of 80, and Max HP/SP will be reduced. Are you sure that you want to be adopted?
+*/
+ MSG_SUGGEST_BABY2 = 0x378,
+#endif
+#if PACKETVER >= 20041101
+/*20041101 to latest
+모든 나쁜 상태이상이 제거 되었습니다.
+All abnormal status effects have been removed.
+*/
+ MSG_GOSPEL1 = 0x379,
+/*20041101 to latest
+1분간 모든 상태이상에 대해 면역이 됩니다.
+You will be immune to abnormal status effects for the next minute.
+*/
+ MSG_GOSPEL2 = 0x37a,
+/*20041101 to latest
+1분간 최대 생명력이 크게 늘어납니다.
+Your Max HP will stay increased for the next minute.
+*/
+ MSG_GOSPEL3 = 0x37b,
+/*20041101 to latest
+1분간 최대 마법력이 크게 늘어납니다.
+Your Max SP will stay increased for the next minute.
+*/
+ MSG_GOSPEL4 = 0x37c,
+/*20041101 to latest
+1분간 모든 능력이 크게 상승합니다.
+All of your Stats will stay increased for the next minute.
+*/
+ MSG_GOSPEL5 = 0x37d,
+/*20041101 to latest
+1분간 사용하는 무기에 성스러운 속성이 부여됩니다.
+Your weapon will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL6 = 0x37e,
+/*20041101 to latest
+1분간 사용하는 갑옷에 성스러운 속성이 부여됩니다.
+Your armor will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL7 = 0x37f,
+/*20041101 to latest
+10초간 방어력이 크게 상승합니다.
+Your Defense will stay increased for the next 10 seconds.
+*/
+ MSG_GOSPEL8 = 0x380,
+/*20041101 to latest
+1분간 공격력이 크게 증가합니다.
+Your Attack strength will be increased for the next minute.
+*/
+ MSG_GOSPEL9 = 0x381,
+/*20041101 to latest
+1분간 명중률과 회피율이 크게 상승합니다.
+Your Accuracy and Flee Rate will be increased for the next minute.
+*/
+ MSG_GOSPEL10 = 0x382,
+#endif
+#if PACKETVER >= 20041108
+/*20041108 to latest
+아이를 한번 입양했던 부부는 추가 입양이 불가능합니다.
+You cannot adopt more than 1 child.
+*/
+ MSG_BABY1 = 0x383,
+/*20041108 to latest
+부부가 둘다 레벨70이 넘어야 아이를 입양할수있습니다.
+You must be at least character level 70 in order to adopt someone.
+*/
+ MSG_BABY2 = 0x384,
+/*20041108 to 20041108
+블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Blacksmith rank points. Your point total is %d.
+*/
+ MSG_BLACKSMITH_POINT = 0x385,
+/*20041108 to 20041108
+알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Alchemist rank points. Your point total is %d.
+*/
+ MSG_ALCHEMIST_POINT = 0x386,
+#endif
+#if PACKETVER >= 20041115
+/*20041115 to 20041130
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE11 = 0x387,
+/*20041115 to 20041130
+슈퍼노비스
+Super Novice
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE12 = 0x388,
+/*20041115 to 20041130
+예요~
+Super Novice~
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE13 = 0x389,
+/*20041115 to 20041130
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE14 = 0x38a,
+/*20041115 to latest
+/notalkmsg2 : 채팅내용을 채팅창에 표시하지 않습니다 (길드말 포함) On Off
+/notalkmsg2: Hides chat messages(including guild chat). On Off
+*/
+ MSG_EXPLAIN_NOTALKMSG2 = 0x38b,
+/*20041115 to latest
+채팅내용을 채팅창에 표시합니다 [/nm2 ON]
+Show chat messages. [/nm2 ON]
+*/
+ MSG_NOTALKMSG2_ON = 0x38c,
+/*20041115 to latest
+채팅내용을 채팅창에 표시하지않습니다 (길드말 포함) [/nm2 OFF]
+Hide chat messages(including guild chat) [/nm2 OFF]
+*/
+ MSG_NOTALKMSG2_OFF = 0x38d,
+#endif
+#if PACKETVER >= 20041129
+/*20041129 to latest
+제련가능한 아이템
+Upgradable Weapons
+*/
+ MSG_REFINEITEMLIST = 0x38e,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_SUCCEESS = 0x38f,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_FAIL = 0x390,
+/*20041129 to latest
+무기제련스킬의 레벨이 부족해서 %s 제련을 할수없습니다.
+You cannot upgrade %s until you level up your Upgrade Weapon skill.
+*/
+ MSG_ITEM_REFINE_FAIL_LEVEL = 0x391,
+/*20041129 to latest
+제련에 필요한 아이템 (%s) 이 없으므로 제련할수없습니다.
+You lack a necessary item %s to upgrade this weapon.
+*/
+ MSG_ITEM_REFINE_FAIL_MATERIAL = 0x392,
+#endif
+#if PACKETVER >= 20041206
+/*20041206 to latest
+완벽하게 코팅되어있어서 풀스트립이 통하지 않습니다.
+Full Divestment cannot pierce the target. The target is fully shielded.
+*/
+ MSG_FULLSTRIP = 0x393,
+#endif
+#if PACKETVER >= 20041213
+/*20041213 to latest
+결혼한 캐릭터는 입양시킬수 없습니다.
+You cannot adopt a married person.
+*/
+ MSG_BABY3 = 0x394,
+#endif
+#if PACKETVER >= 20041220
+/*20041220 to latest
+친구로 등록된 이름과 비슷하지만 등록된 이름이 아닙니다. 아는사람인지 확인하십시요.
+This name is not registered in your Friend List. Please check the name again.
+*/
+ MSG_ID_WARNING = 0x395,
+/*20041220 to latest
+/hi 또는 /hi 문장 : 친구로 등록된 캐릭터들에게 인사를 합니다.
+/hi or /hi message: Send greetings to people who are online and registered on your Friend List.
+*/
+ MSG_EXPLAIN_HI = 0x396,
+#endif
+#if PACKETVER >= 20041227
+/*20041227 to latest
+길드원의 이름과 비슷하지만 길드원이 아닙니다. 길드원인지 확인하십시요.
+This character is not your guildsman. Please check the name again.
+*/
+ MSG_ID_WARNING_GUILD = 0x397,
+#endif
+#if PACKETVER >= 20050117
+/*20050117 to latest
+9999만제니 이상 입력하셔도 가격은 9999만제니로 판매됩니다.
+Please be aware that the maximum selling price is fixed as 2 Billion. You cannot sell an item higher than that.
+*/
+ MSG_OVERPRICE9999 = 0x398,
+#endif
+#if PACKETVER >= 20050131
+/*20050131 to latest
+친구의 귓속말은 [ Friend ] , 길드원은 [ Member ] 로 표시됩니다.
+Whispers from friends are displayed as [ Friend ], and ones from guildsmen are displayed as [ Member ].
+*/
+ MSG_EXPLAIN_SACHING1 = 0x399,
+/*20050131 to latest
+( From 캐릭터이름 : ) 이라고 표시 되는 귓속말은 친구나 길드원이 아닙니다.
+( From character name: ) is from an anonymous character who is neither your friend nor guildsman.
+*/
+ MSG_EXPLAIN_SACHING2 = 0x39a,
+#endif
+#if PACKETVER >= 20050214
+/*20050214 to 20050310
+블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/blacksmith : 블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+/blacksmith: Shows top 10 Blacksmiths in the server.
+*/
+ MSG_EXPLAIN_BLACKSMITH = 0x39b,
+/*20050214 to 20050310
+알케미스트의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/alchemist : 알케미스트의 상위 10위권 랭킹을 보여줍니다.
+/alchemist: Shows top 10 Alchemists in the server.
+*/
+ MSG_EXPLAIN_ALCHEMIST = 0x39c,
+/*20050214 to latest
+ALT+Y : 여러가지 명령어를 쉽게 쓸수있는 윈도우가 열립니다.
+ALT+Y: Opens a window which allows you to use various commands with ease.
+*/
+ MSG_EXPLAIN_ALTY = 0x39d,
+#endif
+#if PACKETVER >= 20050328
+/*20050328 to latest
+[POINT] 태권미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Tae-Kwon Mission rank points. Your point total is %d.
+*/
+ MSG_TAEKWON_POINT = 0x39e,
+#endif
+#if PACKETVER >= 20050404
+/*20050404 to latest
+[태권미션] Target Monster : %s (%d%%)
+[Taekwon Mission] Target Monster: %s (%d%%)
+*/
+ MSG_TAEKWON_MISSION = 0x39f,
+#endif
+#if PACKETVER >= 20050502
+/*20050502 to latest
+게임가드 초기화 에러 : %lu
+Error - Failed to initialize GameGuard: %lu
+*/
+ MSG_INIT_ERROR = 0x3a0,
+/*20050502 to latest
+스피드핵이 감지되었습니다.
+Speed Hack has been detected.
+*/
+ MSG_SPEEDHACK_DETECT = 0x3a1,
+/*20050502 to latest
+불법 프로그램 (%s) 가 발견되었습니다
+The illegal program, (%s) has been detected.
+*/
+ MSG_GAMEHACK_DETECT = 0x3a2,
+/*20050502 to latest
+게임이나 게임가드가 변조되었습니다.
+The Game or Gameguard has been cracked.
+*/
+ MSG_GAMEHACK_DOUBT = 0x3a3,
+/*20050502 to latest
+게임가드가 실행 중 입니다. 잠시 후에 다시 실행해보시기 바랍니다.
+GameGuard is currently running. Please wait for sometime and restart the game.
+*/
+ MSG_ERROR_EXIST = 0x3a4,
+/*20050502 to latest
+게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다.
+The Game or GameGuard is already running. Please close the game and restart the game.
+*/
+ MSG_GAME_EXIST = 0x3a5,
+/*20050502 to latest
+게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다.
+Failed to intialize GameGuard. Please try again after rebooting the system or closing other programs.
+*/
+ MSG_ERROR_INIT = 0x3a6,
+/*20050502 to latest
+바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다.
+Failed to load the scan module of virus and hacking tool. It's caused by lack of memory or PC virus infection.
+*/
+ MSG_ERROR_NPSCAN = 0x3a7,
+#endif
+#if PACKETVER >= 20050509
+/*20050509 to latest
+호문클루스 정보
+Homunculus Info
+*/
+ MSG_HOMUN_INFO = 0x3a8,
+#endif
+#if PACKETVER >= 20050523
+/*20050523 to latest
+호문클루스 스킬목록
+Homunculus Skill List
+*/
+ MSG_HOMUN_SKILLLIST = 0x3a9,
+/*20050523 to latest
+호문클루스의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Please give your Homunculus a name no longer than 23 letters.
+*/
+ MSG_HOMUN_NAME_IN23 = 0x3aa,
+/*20050523 to latest
+이름은 단 한번만 바꿀수 있습니다. 호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You can name a Homunculus only once. You have entered the name, ^0000ff%s^000000. Would you like to continue?
+*/
+ MSG_HOMUN_NAME_CHANGE_ONLYONCE = 0x3ab,
+/*20050523 to latest
+지금은 부재중~
+(Away)
+*/
+ MSG_AUTO_MSG = 0x3ac,
+/*20050523 to latest
+[자동응답]
+[Automated Message]
+*/
+ MSG_AUTO_MSG2 = 0x3ad,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답합니다.
+Send an automated message while you are away.
+*/
+ MSG_AUTO_MSG_ON = 0x3ae,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답하지 않습니다.
+Cancel automated away message.
+*/
+ MSG_AUTO_MSG_OFF = 0x3af,
+/*20050523 to latest
+자동 응답 메시지를 입력하세요.
+Please enter Away Message.
+*/
+ MSG_ENTER_AUTO_MSG = 0x3b0,
+#endif
+#if PACKETVER >= 20050530
+/*20050530 to latest
+/번쩍
+/fsh
+*/
+ MSG_EMOTION_SPARK = 0x3b1,
+/*20050530 to latest
+/빙빙
+/spin
+*/
+ MSG_EMOTION_CONFUSE = 0x3b2,
+/*20050530 to latest
+/하아
+/sigh
+*/
+ MSG_EMOTION_OHNO = 0x3b3,
+/*20050530 to latest
+/덤덤
+/dum
+*/
+ MSG_EMOTION_HUM = 0x3b4,
+/*20050530 to latest
+/시끌
+/crwd
+*/
+ MSG_EMOTION_BLABLA = 0x3b5,
+/*20050530 to latest
+/좌절
+/desp
+*/
+ MSG_EMOTION_OTL = 0x3b6,
+/*20050530 to latest
+/주사위
+/dice
+*/
+ MSG_EMOTION_DICE = 0x3b7,
+/*20050530 to latest
+/pk : 학살자의 상위 10위권 랭킹을 보여줍니다.
+/pk: Shows top 10 Slayers in the server.
+*/
+ MSG_EXPLAIN_KILLER_RANK = 0x3b8,
+/*20050530 to latest
+[POINT] 학살자 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Slayer rank points. Your point total is %d.
+*/
+ MSG_KILLER_POINT = 0x3b9,
+#endif
+#if PACKETVER >= 20050608
+/*20050608 to latest
+진화 가능
+Evolution Available
+*/
+ MSG_HOMUN_EVOLVE = 0x3ba,
+/*20050608 to latest
+^ff0000^ff0000호문클루스를 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+You have decided to delete this Homunculus ^ff0000^ff0000. When deleted, the homunculus and its history will be deleted and they cannot be restored in the future. Would you like to continue?
+*/
+ MSG_DELETE_HOMUN = 0x3bb,
+#endif
+#if PACKETVER >= 20050613
+/*20050613 to latest
+호문의 상태를 파일에 저장합니다.
+Save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_ON = 0x3bc,
+/*20050613 to latest
+호문의 상태를 파일에 저장하지 않습니다.
+Do not save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_OFF = 0x3bd,
+/*20050613 to latest
+Crusader
+*/
+ MSG_CRUSADER = 0x3be,
+/*20050613 to latest
+Monk
+*/
+ MSG_MONK = 0x3bf,
+/*20050613 to latest
+Sage
+*/
+ MSG_SAGE = 0x3c0,
+/*20050613 to latest
+Rouge
+Rogue
+*/
+ MSG_ROGUE = 0x3c1,
+/*20050613 to latest
+Alchemist
+*/
+ MSG_ALCHEMIST = 0x3c2,
+/*20050613 to latest
+Bard
+*/
+ MSG_BARD = 0x3c3,
+/*20050613 to latest
+Crusader_W
+Crusader
+*/
+ MSG_CRUSADER_W = 0x3c4,
+/*20050613 to latest
+Monk_W
+Monk
+*/
+ MSG_MONK_W = 0x3c5,
+/*20050613 to latest
+Sage_W
+Sage
+*/
+ MSG_SAGE_W = 0x3c6,
+/*20050613 to latest
+Rouge_W
+Rogue
+*/
+ MSG_ROGUE_W = 0x3c7,
+/*20050613 to latest
+Alchemist_W
+Alchemist
+*/
+ MSG_ALCHEMIST_W = 0x3c8,
+/*20050613 to latest
+Dancer
+*/
+ MSG_DANCER = 0x3c9,
+/*20050613 to latest
+Novice High
+High Novice
+*/
+ MSG_NOVICE_H = 0x3ca,
+/*20050613 to latest
+Swordman High
+High Swordman
+*/
+ MSG_SWORDMAN_H = 0x3cb,
+/*20050613 to latest
+Magician High
+High Mage
+*/
+ MSG_MAGICIAN_H = 0x3cc,
+/*20050613 to latest
+Archer High
+High Archer
+*/
+ MSG_ARCHER_H = 0x3cd,
+/*20050613 to latest
+Acolyte High
+High Acolyte
+*/
+ MSG_ACOLYTE_H = 0x3ce,
+/*20050613 to latest
+Merchant High
+High Merchant
+*/
+ MSG_MERCHANT_H = 0x3cf,
+/*20050613 to latest
+Thief High
+High Thief
+*/
+ MSG_THIEF_H = 0x3d0,
+/*20050613 to latest
+Novice High_W
+High Novice
+*/
+ MSG_NOVICE_H_W = 0x3d1,
+/*20050613 to latest
+Swordman High_W
+High Swordman
+*/
+ MSG_SWORDMAN_H_W = 0x3d2,
+/*20050613 to latest
+Magician High_W
+High Mage
+*/
+ MSG_MAGICIAN_H_W = 0x3d3,
+/*20050613 to latest
+Archer High_W
+High Archer
+*/
+ MSG_ARCHER_H_W = 0x3d4,
+/*20050613 to latest
+Acolyte High_W
+High Acolyte
+*/
+ MSG_ACOLYTE_H_W = 0x3d5,
+/*20050613 to latest
+Merchant High_W
+High Merchant
+*/
+ MSG_MERCHANT_H_W = 0x3d6,
+/*20050613 to latest
+Thief High_W
+High Thief
+*/
+ MSG_THIEF_H_W = 0x3d7,
+/*20050613 to latest
+Lord Knight
+*/
+ MSG_KNIGHT_H = 0x3d8,
+/*20050613 to latest
+High Priest
+*/
+ MSG_PRIEST_H = 0x3d9,
+/*20050613 to latest
+High Wizard
+*/
+ MSG_WIZARD_H = 0x3da,
+/*20050613 to latest
+White Smith
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H = 0x3db,
+/*20050613 to latest
+Sniper
+*/
+ MSG_HUNTER_H = 0x3dc,
+/*20050613 to latest
+Saaassin Cross
+Assassin Cross
+*/
+ MSG_ASSASSIN_H = 0x3dd,
+/*20050613 to latest
+Lord Knight_W
+Lord Knight
+*/
+ MSG_KNIGHT_H_W = 0x3de,
+/*20050613 to latest
+High Priest_W
+High Priest
+*/
+ MSG_PRIEST_H_W = 0x3df,
+/*20050613 to latest
+High Wizard_W
+High Wizard
+*/
+ MSG_WIZARD_H_W = 0x3e0,
+/*20050613 to latest
+White Smith_W
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H_W = 0x3e1,
+/*20050613 to latest
+Sniper_W
+Sniper
+*/
+ MSG_HUNTER_H_W = 0x3e2,
+/*20050613 to latest
+Saaassin Cross_W
+Assassin Cross
+*/
+ MSG_ASSASSIN_H_W = 0x3e3,
+/*20050613 to latest
+Paladin
+*/
+ MSG_CRUSADER_H = 0x3e4,
+/*20050613 to latest
+Champion
+*/
+ MSG_MONK_H = 0x3e5,
+/*20050613 to latest
+Professor
+Scholar
+*/
+ MSG_SAGE_H = 0x3e6,
+/*20050613 to latest
+Stalker
+*/
+ MSG_ROGUE_H = 0x3e7,
+/*20050613 to latest
+Creator
+Biochemist
+*/
+ MSG_ALCHEMIST_H = 0x3e8,
+/*20050613 to latest
+Clown
+Minstrel
+*/
+ MSG_BARD_H = 0x3e9,
+/*20050613 to latest
+Paladin_W
+Paladin
+*/
+ MSG_CRUSADER_H_W = 0x3ea,
+/*20050613 to latest
+Champion_W
+Champion
+*/
+ MSG_MONK_H_W = 0x3eb,
+/*20050613 to latest
+Professor_W
+Professor
+*/
+ MSG_SAGE_H_W = 0x3ec,
+/*20050613 to latest
+Stalker_W
+Stalker
+*/
+ MSG_ROGUE_H_W = 0x3ed,
+/*20050613 to latest
+Creator_W
+Creator
+*/
+ MSG_ALCHEMIST_H_W = 0x3ee,
+/*20050613 to latest
+Gypsy
+*/
+ MSG_DANCER_H = 0x3ef,
+/*20050613 to latest
+비밀번호가 지정되어 있지 않습니다. 새로운 비밀번호를 지정하시겠습니까?
+You have not set a password yet. Would you like to create one now?
+*/
+ MSG_STORE_PASSWORD_REQ = 0x3f0,
+/*20050613 to latest
+비밀번호를 3회 틀려셨습니다. 나중에 다시 시도해 주세요.
+You have incorrectly entered the password 3 times. Please try again later.
+*/
+ MSG_STORE_PASSWORD_PENALTY = 0x3f1,
+/*20050613 to latest
+비밀번호 변경이 실패하였습니다.
+Password creation has failed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_NG = 0x3f2,
+/*20050613 to latest
+비밀번호는 4자리 이상 8자리이하여야만 합니다.
+Password must be 4~8 letters long.
+*/
+ MSG_STORE_PASSWORD_4_8 = 0x3f3,
+/*20050613 to latest
+비밀번호
+Password
+*/
+ MSG_STORE_PASSWORD = 0x3f4,
+/*20050613 to latest
+신규 비밀번호
+New Password
+*/
+ MSG_STORE_NEW_PASSWORD = 0x3f5,
+/*20050613 to latest
+확인 비밀번호
+Confirm Password
+*/
+ MSG_STORE_RENEW_PASSWORD = 0x3f6,
+/*20050613 to latest
+비밀번호 변경이 완료되었습니다.
+Password has been changed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_OK = 0x3f7,
+/*20050613 to latest
+비밀번호가 서로 다릅니다.
+Password does not match.
+*/
+ MSG_STORE_PASSWORD_MISMATCH = 0x3f8,
+/*20050613 to latest
+비밀번호 입력
+Enter Password
+*/
+ MSG_STORE_PASSWORD_INPUT = 0x3f9,
+#endif
+#if PACKETVER >= 20050624
+/*20050624 to 20050624
+호문이 아사 직전입니다!!! 밥좀 주셈~!!
+20050628 to latest
+호문이 아사 직전입니다! 먹이를 주지 않으면 가출하게됩니다.
+Your Homunculus is starving. Please feed it, otherwise it will leave you.
+*/
+ MSG_HOMUN_HUNGRY = 0x3fa,
+/*20050624 to latest
+경험치
+EXP
+*/
+ MSG_HOMUN_EXP = 0x3fb,
+#endif
+#if PACKETVER >= 20050628
+/*20050628 to latest
+[EVENT] 이벤트에 당첨되셨습니다. 게임내에서 아이템을 지급받으십시요.
+*/
+ MSG_EVENT_RESULT = 0x3fc,
+#endif
+#if PACKETVER >= 20050704
+/*20050704 to latest
+싫어함
+Hate
+*/
+ MSG_HATE = 0x3fd,
+/*20050704 to 20050704
+매우 싫어함
+20050711 to latest
+매우싫어함
+Hate with a Passion
+*/
+ MSG_VERYHATE = 0x3fe,
+#endif
+#if PACKETVER >= 20050718
+/*20050718 to latest
+호문클루스가 사용자 인공지능으로 동작합니다.
+Homunculus has been customized.
+*/
+ MSG_HOMUN_USERAI_ON = 0x3ff,
+/*20050718 to latest
+호문클루스가 기본 인공지능으로 동작합니다.
+Homunculus has been activated with the basic AI.
+*/
+ MSG_HOMUN_USERAI_OFF = 0x400,
+#endif
+#if PACKETVER >= 20050808
+/*20050808 to latest
+편지목록
+Mail List
+*/
+ MSG_MAIL_LIST = 0x401,
+/*20050808 to latest
+편지쓰기
+Write Mail
+*/
+ MSG_MAIL_WRITE = 0x402,
+/*20050808 to latest
+편지읽기
+Read Mail
+*/
+ MSG_MAIL_READ = 0x403,
+#endif
+#if PACKETVER >= 20050822
+/*20050822 to latest
+한번 지정하시면 변경이 불가능합니다! 이 맵으로 지정하시겠습니까?
+You cannot change a map's designation once it is designated. Are you sure that you want to designate this map?
+*/
+ MSG_STARPLACE_ACCEPT = 0x404,
+/*20050822 to 20050822
+보내실 아이템이 추가 되었습니다.
+20050829 to 20051017
+아이템창에 아이템이 추가 되었습니다.
+20051024 to latest
+메일 아이템을 수령했습니다.
+Item has been added in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_SUCCESS = 0x405,
+/*20050822 to 20050822
+보내실 아이템이 추가 되지 않았습니다.
+20050829 to 20051017
+아이템창에 아이템이 추가 되지 않았습니다.
+20051024 to latest
+메일 아이템을 수령하지 못했습니다.
+You have failed to add the item in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_FAILURE = 0x406,
+/*20050822 to latest
+메일 보내기가 성공하였습니다.
+You have successfully mailed a message.
+*/
+ MSG_MAIL_SEND_SUCCESS = 0x407,
+/*20050822 to latest
+메일 보내기가 실패하였습니다. 받는 사람이 존재하지 않습니다.
+You have failed to mail a message. Recipient does not exist.
+*/
+ MSG_MAIL_USER_NOT_FOUND = 0x408,
+#endif
+#if PACKETVER >= 20050829
+/*20050829 to latest
+[태양과 달과 별의 천사] 지정했던 장소들과 몬스터들이 초기화됐습니다!
+[Solar, Lunar and Stellar Angel] Designated places and monsters have been reset.
+*/
+ MSG_STAR_ANGEL = 0x409,
+/*20050829 to latest
+경매 등록이 실패했습니다.
+The minimum starting bid for auctions is 10,000,000 zeny.
+*/
+ MSG_AUCTION_ADD_FALSE = 0x40a,
+/*20050829 to latest
+경매 등록이 성공했습니다.
+You have successfully started a new auction.
+*/
+ MSG_AUCTION_ADD_TRUE = 0x40b,
+/*20050829 to latest
+해당 경매가 취소되었습니다.
+The auction has been canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL = 0x40c,
+/*20050829 to latest
+입찰자가 있는 경매는 취소할 수 없습니다.
+An auction with at least one bidder cannot be canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL_FALSE = 0x40d,
+#endif
+#if PACKETVER >= 20050905
+/*20050905 to latest
+메일 삭제가 성공하였습니다.
+Mail has been successfully deleted.
+*/
+ MSG_MAIL_DELETE_SUCCESS = 0x40e,
+/*20050905 to latest
+메일 삭제가 실패하였습니다.
+You have failed to delete the mail.
+*/
+ MSG_MAIL_DELETE_FAILURE = 0x40f,
+#endif
+#if PACKETVER >= 20050912
+/*20050912 to latest
+던지는 단검이 장착되었습니다.
+You have equipped throwing daggers.
+*/
+ MSG_MSG_KNIFE_EQUIPMENT_SUCCESS = 0x410,
+#endif
+#if PACKETVER >= 20050926
+/*20050926 to latest
+%s 님이 로그인했습니다.
+%s has logged in.
+*/
+ MSG_LOGIN_FRIEND = 0x411,
+/*20050926 to latest
+%s 님이 로그아웃했습니다.
+%s has logged out.
+*/
+ MSG_LOGOUT_FRIEND = 0x412,
+#endif
+#if PACKETVER >= 20051004
+/*20051004 to latest
+/loginout : 길드원과 친구들의 접속관련 메세지를 보여줍니다. On Off
+/loginout: Shows guildsmen and friends online status. On Off
+*/
+ MSG_EXPLAIN_LOGINOUT = 0x413,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시합니다. [/li ON]
+Display online status of friends in Chat Window. [/li ON]
+*/
+ MSG_LOGINOUT_ON = 0x414,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시하지않습니다. [/li OFF]
+Do not display online status of friends in Chat Window. [/li OFF]
+*/
+ MSG_LOGINOUT_OFF = 0x415,
+/*20051004 to latest
+이미 실행중입니다.
+It is already running.
+*/
+ MSG_SGP_CODE_ALREADY_RUNNING = 0x416,
+/*20051004 to latest
+매크로 사용이 감지되었습니다.
+Use of Macro program has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MACRO = 0x417,
+/*20051004 to latest
+스피드해킹이 감지되었습니다.
+Use of Speed hack has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_SPEEDHACK = 0x418,
+/*20051004 to latest
+API 후킹이 감지되었습니다.
+API Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_APIHOOK = 0x419,
+/*20051004 to latest
+메시지 후킹이 감지되었습니다.
+Message Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MSGHOOK = 0x41a,
+/*20051004 to latest
+모듈이 변조 또는 손상되었거나 버전이 일치하지 않습니다.
+Module has been modified or damaged or its version does not match.
+*/
+ MSG_SGP_CODE_NOT_EQUALENCRYPTEDDATA = 0x41b,
+#endif
+#if PACKETVER >= 20051010
+/*20051010 to latest
+(태국)귀하는 게임방 과금으로 로그인 하셨습니다.
+(Thailand) You have logged in game with PC cafe payment.
+*/
+ MSG_BILLING_PCB = 0x41c,
+#endif
+#if PACKETVER >= 20051017
+/*20051017 to latest
+이전
+Prev
+*/
+ MSG_PREV_PAGE = 0x41d,
+/*20051017 to latest
+다음
+Next
+*/
+ MSG_NEXT_PAGE = 0x41e,
+/*20051017 to latest
+경매
+Auction
+*/
+ MSG_AUCTION = 0x41f,
+/*20051017 to latest
+물품보기
+Product List
+*/
+ MSG_AUCTION_VIEW = 0x420,
+/*20051017 to latest
+등록하기
+Register
+*/
+ MSG_AUCTION_ADD = 0x421,
+/*20051017 to latest
+판매 진행상태
+Sale Status
+*/
+ MSG_AUCTION_SELL = 0x422,
+/*20051017 to latest
+구매 진행상태
+Purchase Status
+*/
+ MSG_AUCTION_BUY = 0x423,
+/*20051017 to latest
+아이템
+Item
+*/
+ MSG_ITEM2 = 0x424,
+/*20051017 to latest
+아이템명
+Name
+*/
+ MSG_ITEM_NAME2 = 0x425,
+/*20051017 to latest
+가격 / 즉시구입가격
+Current Bid / Max Bid
+*/
+ MSG_ITEM_PRICE = 0x426,
+/*20051017 to latest
+판매자
+Seller
+*/
+ MSG_SELLER = 0x427,
+/*20051017 to latest
+구매자
+Buyer
+*/
+ MSG_BUYER = 0x428,
+/*20051017 to latest
+종료시간
+End Time
+*/
+ MSG_FINISH_TIME = 0x429,
+/*20051017 to latest
+%m월 %d일 %H시
+%m %d %H
+*/
+ MSG_TIME_TYPE = 0x42a,
+/*20051017 to latest
+시간설정
+Time (Hr)
+*/
+ MSG_SET_TIME = 0x42b,
+/*20051017 to latest
+수수료
+Fee
+*/
+ MSG_CHARGE = 0x42c,
+/*20051017 to latest
+검색 된 아이템이 없습니다.
+*/
+ MSG_NOTHING_SEARCH_ITEM = 0x42d,
+/*20051017 to latest
+현재 판매중인 아이템이 없습니다.
+Your Sale List is empty.
+*/
+ MSG_NOTHING_SEARCH_SELL_ITEM = 0x42e,
+/*20051017 to latest
+현재 구매중인 아이템이 없습니다.
+Your Purchase List is empty.
+*/
+ MSG_NOTHING_SEARCH_BUY_ITEM = 0x42f,
+/*20051017 to latest
+경매정보가 정확하지 않습니다.
+Auction Information is incorrect or incomplete.
+*/
+ MSG_ERROR_AUCTION_ITEM_INFO = 0x430,
+/*20051017 to latest
+경매에 등록할 아이템 정보가 없습니다.
+You must drag and drop an item from your Inventory into the Register Window to begin a new auction.
+*/
+ MSG_NOTHING_AUCTION_ITEM_INFO = 0x431,
+/*20051017 to latest
+이미 등록된 경매입니다.
+The auction has already been registered.
+*/
+ MSG_ERROR_ADD_AUCTION = 0x432,
+/*20051017 to latest
+제시가격
+Starting Bid
+*/
+ MSG_PRICE = 0x433,
+/*20051017 to latest
+구입희망가격
+Current Bid
+*/
+ MSG_PRICE2 = 0x434,
+/*20051017 to latest
+즉시구입가격
+Buy Now Price
+*/
+ MSG_PRICE3 = 0x435,
+/*20051017 to latest
+현재소지제니
+Your Current Zeny
+*/
+ MSG_PRICE4 = 0x436,
+/*20051017 to latest
+현재최고가격
+Highest Bid
+*/
+ MSG_PRICE5 = 0x437,
+/*20051017 to latest
+이전입찰가격
+Previous Bid
+*/
+ MSG_PRICE6 = 0x438,
+/*20051017 to latest
+추가입찰가격
+Next Bid
+*/
+ MSG_PRICE7 = 0x439,
+/*20051017 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BUY_ACTION_ITEM = 0x43a,
+/*20051017 to latest
+이 가격에 판매하시겠습니까?
+Would you like to sell this item?
+*/
+ MSG_SELL_ACTION_ITEM = 0x43b,
+/*20051017 to latest
+입찰하기
+Place Bid
+*/
+ MSG_BUY_AUCTION = 0x43c,
+/*20051017 to latest
+즉시구매하기
+Buy Now
+*/
+ MSG_BUY_AUCTION2 = 0x43d,
+/*20051017 to latest
+경매종료하기
+End the Auction
+*/
+ MSG_BUY_AUCTION3 = 0x43e,
+/*20051017 to latest
+재입찰하기
+Place another Bid
+*/
+ MSG_FINISH_AUCTION = 0x43f,
+/*20051017 to latest
+해당 경매에 대한 입찰이 성공했습니다.
+You have placed a bid.
+*/
+ MSG_RESULT_BUY_TRUE = 0x440,
+/*20051017 to latest
+해당 경매에 대한 입찰이 실패했습니다.
+You have failed to place a bid.
+*/
+ MSG_RESULT_BUY_FALSE = 0x441,
+/*20051017 to latest
+제니가 충분하지 않습니다.
+You do not have enough zeny.
+*/
+ MSG_RESULT_BUY_FALSE_MONEY = 0x442,
+#endif
+#if PACKETVER >= 20051024
+/*20051024 to latest
+방어구
+Armors
+*/
+ MSG_EQUIP = 0x443,
+/*20051024 to latest
+카드
+Card
+*/
+ MSG_CARD = 0x444,
+/*20051024 to latest
+기타
+Other
+*/
+ MSG_ETC = 0x445,
+/*20051024 to latest
+경매번호
+Bid
+*/
+ MSG_AUCTION_NUM = 0x446,
+/*20051024 to latest
+검색
+Search
+*/
+ MSG_AUCTION_SEARCH = 0x447,
+/*20051024 to latest
+해당 경매를 종료했습니다.
+You have ended the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_TRUE = 0x448,
+/*20051024 to latest
+해당 경매를 종료 할 수 없습니다.
+You cannot end the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_FALSE = 0x449,
+/*20051024 to latest
+경매 번호가 정확하지 않습니다.
+Bid Number is incorrect.
+*/
+ MSG_RESULT_AUCTION_ID_FALSE = 0x44a,
+/*20051024 to latest
+받는이
+To
+*/
+ MSG_SENDER = 0x44b,
+#endif
+#if PACKETVER >= 20051205
+/*20051205 to latest
+제 목
+Title
+*/
+ MSG_TITLE2 = 0x44c,
+/*20051205 to latest
+새 메일이 도착하였습니다.
+You have received a message in the mail.
+*/
+ MSG_NEW_MAIL = 0x44d,
+/*20051205 to latest
+검색중입니다.
+Searching...
+*/
+ MSG_SEARCHING_ITEM = 0x44e,
+/*20051205 to latest
+더 이상 경매 등록할 수 없습니다. 경매 등록은 최대 5개까지 가능합니다.
+You cannot register more than 5 items in an auction at a time.
+*/
+ MSG_AUCTION_ADD_OVER = 0x44f,
+/*20051205 to latest
+더 이상 경매 물품에 입찰할 수 없습니다. 경매 물품 입찰은 최대 5개까지 가능합니다.
+You cannot place more than 5 bids at a time.
+*/
+ MSG_RESULT_BUY_OVER = 0x450,
+/*20051205 to latest
+삭제하려는 메일에 수령하지 않은 아이템이 있습니다.
+Please accept all items from your mail before deleting.
+*/
+ MSG_MAIL_DELETE_ERROR = 0x451,
+/*20051205 to latest
+메일 제목을 입력하여 주십시오.
+Please enter a title.
+*/
+ MSG_MAIL_SEND_ERROR = 0x452,
+/*20051205 to latest
+/shopping : 클릭 한번으로 상점을 열고 상점이름 오른쪽 클릭으로 상점을 닫습니다 On Off
+/shopping: Enables you to open a shop with a single left-click and close your shop with a single right-click. On Off
+*/
+ MSG_EXPLAIN_SHOPPING = 0x453,
+/*20051205 to latest
+클릭 한번으로 상점을 열고 상점이름을 오른쪽 클릭해서 상점을 닫을수있습니다. [/sh ON]
+You can now open a shop with a single left-click and close your shop with a single right-click. [sh ON].
+*/
+ MSG_SHOPPING_ON = 0x454,
+/*20051205 to latest
+더블클릭 으로 상점을 열게됩니다. [/sh OFF]
+You can open a shop by double-clicking. [/sh OFF]
+*/
+ MSG_SHOPPING_OFF = 0x455,
+/*20051205 to latest
+메일을 보내려면, 제니 입력을 완료해야 합니다.
+Please enter zeny amount before sending mail.
+*/
+ MSG_MAIL_SEND_ERROR2 = 0x456,
+/*20051205 to latest
+경매 수수료가 부족합니다.
+You do not have enough zeny to pay the Auction Fee.
+*/
+ MSG_ADD_MONEY_FALSE = 0x457,
+/*20051205 to latest
+상태보기
+View Status
+*/
+ MSG_HOMUN_SHOWINFO = 0x458,
+/*20051205 to latest
+먹이주기
+Feed
+*/
+ MSG_HOMUN_FEEDING = 0x459,
+/*20051205 to latest
+대기
+Stand By
+*/
+ MSG_HOMUN_WAITING = 0x45a,
+/*20051205 to latest
+슈퍼노비스(남)
+Super Novice (Male)
+*/
+ MSG_JOB_SUPERNOVICE_M = 0x45b,
+/*20051205 to latest
+슈퍼노비스(여)
+Super Novice (Female)
+*/
+ MSG_JOB_SUPERNOVICE_F = 0x45c,
+/*20051205 to latest
+태권소년
+Taekwon Boy
+*/
+ MSG_JOB_TAEKWON_M = 0x45d,
+/*20051205 to latest
+태권소녀
+Taekwon Girl
+*/
+ MSG_JOB_TAEKWON_F = 0x45e,
+/*20051205 to latest
+권성(남)
+Taekwon Master (Male)
+*/
+ MSG_KWONSUNG_M = 0x45f,
+/*20051205 to latest
+권성(여)
+Taekwon Master (Female)
+*/
+ MSG_KWONSUNG_F = 0x460,
+/*20051205 to latest
+소울링커(남)
+Soul Linker (Male)
+*/
+ MSG_SOULLINGKER_M = 0x461,
+/*20051205 to latest
+소울링커(여)
+Soul Linker (Female)
+*/
+ MSG_SOULLINGKER_F = 0x462,
+/*20051205 to latest
+PC방요금제로 2개이상의 계정이 접속되고있습니다. 확인후 다시 사용하시기 바랍니다.
+Please check the connection, more than 2 accounts are connected with Internet Cafe Time Plan.
+*/
+ MSG_BAN_PC_IP_UNFAIR = 0x463,
+/*20051205 to latest
+귀하는 월정액 요금제 사용자 입니다. (남은기간 : %d일)
+Your account is using monthly payment. (Remaining day: %d day)
+*/
+ MSG_BILLING_1 = 0x464,
+/*20051205 to latest
+귀하는 정량 요금제 사용자 입니다. (남은시간 : %d시간 %분 %초)
+Your account is using time limited. (Remaining time: %d hour %d minute %d second)
+*/
+ MSG_BILLING_2 = 0x465,
+#endif
+#if PACKETVER >= 20051212
+/*20051212 to latest
+해당 아이템은 메일에 첨부 할수 없는 아이템입니다.
+This item cannot be mailed.
+*/
+ MSG_MAIL_ITEM_ADD_FAILED = 0x466,
+/*20051212 to latest
+더이상 아이템을 가질수 없습니다. 아이템은 메일로 보관하겠습니다.
+You cannot accept any more items. Please try again later.
+*/
+ MSG_MAIL_ADD_ITEM_OVER_FAILURE = 0x467,
+#endif
+#if PACKETVER >= 20060109
+/*20060109 to latest
+남성
+Male
+*/
+ MSG_PTSEX1 = 0x468,
+/*20060109 to latest
+여성
+Female
+*/
+ MSG_PTSEX2 = 0x469,
+/*20060109 to latest
+새로운 유저입니다
+New User.
+*/
+ MSG_PT_NEWUSER = 0x46a,
+/*20060109 to latest
+E-mail은 캐릭터를 지울때 필요합니다.
+E-mail address is required to delete a character.
+*/
+ MSG_PT_ACINFO = 0x46b,
+/*20060109 to latest
+정확한 형식으로 입력해 주세요.
+Please enter the correct information.
+*/
+ MSG_PT_ACINFO2 = 0x46c,
+/*20060109 to latest
+이 키를 사용하세요
+Please use this key.
+*/
+ MSG_PT_NEWKEYINFO = 0x46d,
+/*20060109 to latest
+정확한 카드 패스워드를 다시 입력해주세요
+Please enter the correct card password.
+*/
+ MSG_PT_FAIL_CARDPASS = 0x46e,
+/*20060109 to latest
+PT정보
+PT Info
+*/
+ MSG_PTID1 = 0x46f,
+/*20060109 to latest
+PT_ID는 %s
+PT_ID is %s
+*/
+ MSG_PTID2 = 0x470,
+/*20060109 to latest
+NUM_ID는 %s
+NUM_ID is %s
+*/
+ MSG_PTID3 = 0x471,
+/*20060109 to latest
+잊지않게 주의하세요
+Please don't forget this information.
+*/
+ MSG_PTID4 = 0x472,
+/*20060109 to latest
+1001
+*/
+ MSG_PT_ERROR_1001 = 0x473,
+/*20060109 to latest
+1002
+*/
+ MSG_PT_ERROR_1002 = 0x474,
+/*20060109 to latest
+1003
+*/
+ MSG_PT_ERROR_1003 = 0x475,
+/*20060109 to latest
+1004
+*/
+ MSG_PT_ERROR_1004 = 0x476,
+/*20060109 to latest
+1006
+*/
+ MSG_PT_ERROR_1006 = 0x477,
+/*20060109 to latest
+1007
+*/
+ MSG_PT_ERROR_1007 = 0x478,
+/*20060109 to latest
+1008
+*/
+ MSG_PT_ERROR_1008 = 0x479,
+/*20060109 to latest
+1009
+*/
+ MSG_PT_ERROR_1009 = 0x47a,
+/*20060109 to latest
+1012
+*/
+ MSG_PT_ERROR_1012 = 0x47b,
+/*20060109 to latest
+1013
+*/
+ MSG_PT_ERROR_1013 = 0x47c,
+/*20060109 to latest
+1014
+*/
+ MSG_PT_ERROR_1014 = 0x47d,
+/*20060109 to latest
+1015
+*/
+ MSG_PT_ERROR_1015 = 0x47e,
+/*20060109 to latest
+1019
+*/
+ MSG_PT_ERROR_1019 = 0x47f,
+/*20060109 to latest
+1020
+Navigation
+*/
+ MSG_PT_ERROR_1020 = 0x480,
+/*20060109 to latest
+1021
+*/
+ MSG_PT_ERROR_1021 = 0x481,
+/*20060109 to latest
+1023
+*/
+ MSG_PT_ERROR_1023 = 0x482,
+/*20060109 to latest
+1024
+*/
+ MSG_PT_ERROR_1024 = 0x483,
+/*20060109 to latest
+1025
+*/
+ MSG_PT_ERROR_1025 = 0x484,
+/*20060109 to latest
+1027
+*/
+ MSG_PT_ERROR_1027 = 0x485,
+/*20060109 to latest
+1028
+*/
+ MSG_PT_ERROR_1028 = 0x486,
+/*20060109 to latest
+10
+*/
+ MSG_PT_ERROR_10 = 0x487,
+/*20060109 to latest
+20
+*/
+ MSG_PT_ERROR_20 = 0x488,
+/*20060109 to latest
+40
+*/
+ MSG_PT_ERROR_40 = 0x489,
+/*20060109 to latest
+50
+*/
+ MSG_PT_ERROR_50 = 0x48a,
+/*20060109 to latest
+60
+*/
+ MSG_PT_ERROR_60 = 0x48b,
+/*20060109 to latest
+70
+*/
+ MSG_PT_ERROR_70 = 0x48c,
+/*20060109 to latest
+80
+*/
+ MSG_PT_ERROR_80 = 0x48d,
+/*20060109 to latest
+90
+*/
+ MSG_PT_ERROR_90 = 0x48e,
+/*20060109 to latest
+100
+*/
+ MSG_PT_ERROR_100 = 0x48f,
+/*20060109 to latest
+110
+*/
+ MSG_PT_ERROR_110 = 0x490,
+#endif
+#if PACKETVER >= 20060126
+/*20060126 to latest
+30포인트를 받으시겠습니까?
+Do you want to receive 30 points?
+*/
+ MSG_PT_POINT1 = 0x491,
+/*20060126 to latest
+30포인트(5시간)이 충전되었습니다
+30 points (5 hours) have been added.
+*/
+ MSG_PT_POINT2 = 0x492,
+#endif
+#if PACKETVER >= 20060213
+/*20060213 to latest
+감정되지 않은 아이템은 경매에 등록할 수 없습니다.
+You cannot register Unidentified Items in auctions.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE = 0x493,
+/*20060213 to latest
+소비 아이템은 경매에 등록할 수 없습니다.
+You cannot register this Consumable Item in an auction.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE2 = 0x494,
+#endif
+#if PACKETVER >= 20060306
+/*20060306 to latest
+메일창을 열려면 카트창을 닫아 주십시요.
+Please close the Cart Window to open the Mail Window.
+*/
+ MSG_CLOSE_MERCHANTITEMWND = 0x495,
+/*20060306 to latest
+카트창을 열려면 메일창을 닫아 주십시요.
+Please close the Mail Window to open the Cart Window.
+*/
+ MSG_CLOSE_MAILWND = 0x496,
+#endif
+#if PACKETVER >= 20060313
+/*20060313 to latest
+탄환이 장착되었습니다.
+Bullets have been equipped.
+*/
+ MSG_MSG_BULLET_EQUIPMENT_SUCCESS = 0x497,
+/*20060313 to latest
+메일이 반송되었습니다.
+The mail has been returned to sender.
+*/
+ MSG_MAIL_RETURN_SUCCESS = 0x498,
+/*20060313 to latest
+메일이 존재하지 않습니다.
+The mail no longer exists.
+*/
+ MSG_MAIL_RETURN_FAILURE = 0x499,
+#endif
+#if PACKETVER >= 20060522
+/*20060522 to 20060522
+한시간 동안, 동일한 IP로 접속한 유저가 60건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+20060523 to latest
+한시간 동안, 동일한 IP로 접속한 유저가 30건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+More than 30 players sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT_ALL = 0x49a,
+/*20060522 to latest
+한시간 동안, 동일한 IP로 10번 이상 접속되었습니다. 확인후 다시 사용하시기 바랍니다.
+More than 10 connections sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT = 0x49b,
+/*20060522 to latest
+게임을 재시작 하십시오
+Please restart the game.
+*/
+ MSG_GAMEGUARD_RESTART = 0x49c,
+#endif
+#if PACKETVER >= 20060703
+/*20060703 to latest
+용병정보 - 아쳐타입
+Mercenary: Archer
+*/
+ MSG_MER_INFO_TYPE_ARCHER = 0x49d,
+/*20060703 to latest
+용병정보 - 검사타입
+Mercenary: Swordman
+*/
+ MSG_MER_INFO_TYPE_SWORDMAN = 0x49e,
+/*20060703 to latest
+용병정보 - 창병타입
+Mercenary: Spearman
+*/
+ MSG_MER_INFO_TYPE_LANCER = 0x49f,
+/*20060703 to 20070109
+남은시간
+20070115 to latest
+삭제시간
+Expiration
+*/
+ MSG_LEFT_TIME = 0x4a0,
+/*20060703 to latest
+신뢰도
+Loyalty
+*/
+ MSG_MER_FRIENDLY = 0x4a1,
+/*20060703 to latest
+소환횟수
+Summons
+*/
+ MSG_MER_CALLCOUNT = 0x4a2,
+/*20060703 to latest
+Kill
+*/
+ MSG_MER_KILL = 0x4a3,
+#endif
+#if PACKETVER >= 20060904
+/*20060904 to latest
+펫이 배가 고파서 당신을 원망하고 있다는 느낌이 든다.
+You can feel hatred from your pet for neglecting to feed it.
+*/
+ MSG_PET_STARVING = 0x4a4,
+/*20060904 to latest
+[POINT] 테이밍미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You earned %d Taming Mission Ranking Points, giving you a total of %d points.
+*/
+ MSG_GANGSI_POINT = 0x4a5,
+/*20060904 to latest
+[테이밍미션] Target Monster : %s
+[Taming Mission] Target Monster: %s
+*/
+ MSG_GANGSI_MISSION = 0x4a6,
+#endif
+#if PACKETVER >= 20060918
+/*20060918 to latest
+/hunting : 사냥 목록을 보여줍니다.
+/hunting: You can check the your hunting list.
+*/
+ MSG_EXPLAIN_HUNTING = 0x4a7,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s는 몇 스킬 찍으셨나요?
+[Angel's Question] Please tell me, how many %s skills do you have?
+*/
+ MSG_DEATH_Q01 = 0x4a8,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 소지하시고있는 제니를 십만으로 나누면 얼마가 되시나요?
+[Angel's Question] Please tell me, how much zeny you'll have if you divide it by 100,000?
+*/
+ MSG_DEATH_Q02 = 0x4a9,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 오늘이 몇일이신지 아시나요?
+[Angel's Question] Please tell me, what is today's date?
+*/
+ MSG_DEATH_Q03 = 0x4aa,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s은 지금 몇이신가요?
+[Angel's Question] Please tell me, how many %s do you have?
+*/
+ MSG_DEATH_Q04 = 0x4ab,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 슈노, 태권계열, 무낙계열을 담당하고있는 SiYeon씨의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in SiYeon's name?
+*/
+ MSG_DEATH_Q05 = 0x4ac,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 귀엽고 어여쁜 라그나로크의 히로인 Munak의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Munak's name?
+*/
+ MSG_DEATH_Q06 = 0x4ad,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 제가 어여뻐하는 Bongun의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Bongun's name?
+*/
+ MSG_DEATH_Q07 = 0x4ae,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 저희가 존재하는 온라인세계 Ragnarok의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, Ragnarok?
+*/
+ MSG_DEATH_Q08 = 0x4af,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 언제나 Online상태인 천사동료들은 큰힘이 되어주죠. Online의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, online?
+*/
+ MSG_DEATH_Q09 = 0x4b0,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 죽음도 두려워하지않는 기사들을 상징하는 단어인 Death의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, death?
+*/
+ MSG_DEATH_Q10 = 0x4b1,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 기사들은 너무 멋진다고 생각해요. Knight의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, knight?
+*/
+ MSG_DEATH_Q11 = 0x4b2,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 중력을 뜻하는 단어인 Gravity의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, gravity?
+*/
+ MSG_DEATH_Q12 = 0x4b3,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 어둠속에서도 밝게 사는게 중요하지요. Dark의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, dark?
+*/
+ MSG_DEATH_Q13 = 0x4b4,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 뭐든지 수집하는 Collector의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, collecter?
+*/
+ MSG_DEATH_Q14 = 0x4b5,
+/*20060918 to latest
+[천사의대답] 소녀에게 정확한 사실을 가르쳐주셔서 감사하옵니다.
+[Angel's Answer] Thank you for letting me know~
+*/
+ MSG_DEATH_R01 = 0x4b6,
+/*20060918 to latest
+[천사의대답] 사랑스러우신 분이시군요. 소녀 감탄했사옵니다.
+[Angel's Answer] I'm very pleased with your answer. You are a splendid adventurer.
+*/
+ MSG_DEATH_R02 = 0x4b7,
+/*20060918 to latest
+[천사의대답] 소녀 실망했사옵니다.
+[Angel's Answer] You've disappointed me...
+*/
+ MSG_DEATH_R05 = 0x4b8,
+#endif
+#if PACKETVER >= 20060925
+/*20060925 to latest
+[POINT] 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You earned %d Ranking Points, giving you a total of %d Ranking Points.
+*/
+ MSG_DEATH_POINT = 0x4b9,
+#endif
+#if PACKETVER >= 20060927
+/*20060927 to 20070417
+[%s]의 소지 Point : %d Point
+20070423 to latest
+[%s]의 소지 캐시 : %d 캐시
+[%s]'s Points: %d Points
+*/
+ MSG_POINT_SHOP = 0x4ba,
+#endif
+#if PACKETVER >= 20061009
+/*20061009 to latest
+선택하지 않은 캐릭터는 삭제 됩니다. 완료하시겠습니까?
+Unselected Characters will be deleted. Continue?
+*/
+ MSG_CONFIRM_SELECT_CHARACTERS = 0x4bb,
+/*20061009 to latest
+9개 이상 선택하실 수 없습니다.
+You cannot select more than 8.
+*/
+ MSG_ERROR_SELECT_CHARACTERS = 0x4bc,
+#endif
+#if PACKETVER >= 20061016
+/*20061016 to latest
+캐릭터명을 '%s' (으)로 변경하시겠습니까?
+Do you want to change your name to '%s'?
+*/
+ MSG_CONFIRM_TO_CHANGE_NAME = 0x4bd,
+/*20061016 to latest
+캐릭터명이 성공적으로 변경되었습니다.
+Character Name has been changed successfully.
+*/
+ MSG_CHANGE_NAME_SUCCESS = 0x4be,
+/*20061016 to latest
+캐릭터명 변경이 실패하였습니다.
+You have failed to change this character's name.
+*/
+ MSG_CHANGE_NAME_FAILURE = 0x4bf,
+/*20061016 to latest
+한 번에 한 종류의 아이템만 구매할 수 있습니다.
+You can purchase only one kind of item at a time.
+*/
+ MSG_CAN_BUY_ONLY_ONEITEM = 0x4c0,
+#endif
+#if PACKETVER >= 20061023
+/*20061023 to latest
+캐릭터가 한개도 선택되지 않았습니다. 반드시 한개 이상의 캐릭터를 선택하여야 합니다.
+No characters were selected. You must select at least one character.
+*/
+ MSG_NO_SELECT_CHARACTERS = 0x4c1,
+/*20061023 to latest
+이미 캐릭터명을 변경한 적이 있습니다. 더 이상 변경 할 수 없습니다.
+This character's name has already been changed. You cannot change a character's name more than once.
+*/
+ MSG_ALREADY_CHANGED_NAME = 0x4c2,
+/*20061023 to latest
+사용자 정보가 정확하지 않습니다.
+User Information is not correct.
+*/
+ MSG_NOTREGISTED_USER = 0x4c3,
+/*20061023 to latest
+다른 사용자가 같은 캐릭터 명을 먼저 사용하였습니다. 다른 캐릭터명을 사용하여 주십시요.
+Another user is using this character name, so please select another one.
+*/
+ MSG_DUPLICATED_CHAR_NAME = 0x4c4,
+#endif
+#if PACKETVER >= 20061030
+/*20061030 to latest
+파티장 권한이 없어 파티원을 소환하지 못했습니다.
+The party member was not summoned because you are not the party leader.
+*/
+ MSG_CANNOT_PARTYCALL = 0x4c5,
+/*20061030 to latest
+현재 맵에는 소환될 파티원이 존재하지 않습니다.
+There is no party member to summon in the current map.
+*/
+ MSG_NO_PARTYMEM_ON_THISMAP = 0x4c6,
+/*20061030 to latest
+이 지역에선 보스몬스터의 흔적을 찾을 수가 없습니다.
+You cannot find any trace of a Boss Monster in this area.
+*/
+ MSG_NOTFIND_BOSSMON = 0x4c7,
+/*20061030 to 20070122
+보스 몬스터 '%s'의 등장 예정시간 %02d시:%02d분
+20070129 to 20071204
+보스 몬스터 '%s'(이)가 %d시 %d분 후에 등장합니다.
+20071211 to latest
+보스 몬스터 '%s'(이)가 %d시간 %d분 후에 등장합니다.
+Boss Monster, '%s' will appear in %02d hour(s) and %02d minute(s).
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON = 0x4c8,
+/*20061030 to latest
+보스 몬스터 '%s'의 위치가 미니맵에 표시됩니다.
+The location of Boss Monster, '%s', will be displayed on your Mini-Map.
+*/
+ MSG_SHOW_POSITION_OF_BOSSMON = 0x4c9,
+#endif
+#if PACKETVER >= 20061106
+/*20061106 to 20061211
+%s를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20061218 to 20070618
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20070619 to 20071218
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20080102 to latest
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+*/
+ MSG_CONFIRM_TO_OPEN_CASH_ITEM = 0x4ca,
+/*20061106 to latest
+NPC가 존재하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the NPC does not exist.
+*/
+ MSG_BUY_CASH_FAIL_NPC = 0x4cb,
+/*20061106 to latest
+부분 유료화 시스템이 정상 작동하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Kafra Shop System is not working correctly.
+*/
+ MSG_BUY_CASH_FAIL_SYSTEM = 0x4cc,
+/*20061106 to latest
+교환중에는 아이템을 구매 할 수 없습니다.
+You cannot purchase items while you are in a trade.
+*/
+ MSG_BUY_CASH_FAIL_EXCHANGE = 0x4cd,
+/*20061106 to latest
+아이템 정보가 정확하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Item Information was incorrect.
+*/
+ MSG_BUY_CASH_FAIL_ITEM_ID = 0x4ce,
+#endif
+#if PACKETVER >= 20061204
+/*20061204 to latest
+ STR이 향상되었습니다.
+STR has increased.
+*/
+ MSG_ENST_STR = 0x4cf,
+/*20061204 to latest
+ STR이 원래대로 돌아왔습니다.
+STR has returned to normal.
+*/
+ MSG_DSST_STR = 0x4d0,
+/*20061204 to latest
+ AGI이 향상되었습니다.
+AGI has increased.
+*/
+ MSG_ENST_AGI = 0x4d1,
+/*20061204 to latest
+ AGI이 원래대로 돌아왔습니다.
+AGI has returned to normal.
+*/
+ MSG_DSST_AGI = 0x4d2,
+/*20061204 to latest
+ VIT이 향상되었습니다.
+VIT has increased.
+*/
+ MSG_ENST_VIT = 0x4d3,
+/*20061204 to latest
+ VIT이 원래대로 돌아왔습니다.
+VIT has returned to normal.
+*/
+ MSG_DSST_VIT = 0x4d4,
+/*20061204 to latest
+ INT이 향상되었습니다.
+INT has increased.
+*/
+ MSG_ENST_INT = 0x4d5,
+/*20061204 to latest
+ INT이 원래대로 돌아왔습니다.
+INT has returned to normal.
+*/
+ MSG_DSST_INT = 0x4d6,
+/*20061204 to latest
+ DEX이 향상되었습니다.
+DEX has increased.
+*/
+ MSG_ENST_DEX = 0x4d7,
+/*20061204 to latest
+ DEX이 원래대로 돌아왔습니다.
+DEX has returned to normal.
+*/
+ MSG_DSST_DEX = 0x4d8,
+/*20061204 to latest
+ LUK이 향상되었습니다.
+LUK has increased.
+*/
+ MSG_ENST_LUK = 0x4d9,
+/*20061204 to latest
+ LUK이 원래대로 돌아왔습니다.
+LUK has returned to normal.
+*/
+ MSG_DSST_LUK = 0x4da,
+/*20061204 to latest
+ 회피율이 향상되었습니다.
+Flee Rate (Flee) has increased.
+*/
+ MSG_ENST_AVOIDANCE = 0x4db,
+/*20061204 to latest
+ 회피율이 원래대로 돌아왔습니다.
+Flee Rate has returned to normal.
+*/
+ MSG_DSST_AVOIDANCE = 0x4dc,
+/*20061204 to latest
+ 명중률이 향상되었습니다.
+Accuracy Rate (Hit) has increased.
+*/
+ MSG_ENST_HIT = 0x4dd,
+/*20061204 to latest
+ 명중률이 원래대로 돌아왔습니다.
+Accuracy Rate has returned to normal.
+*/
+ MSG_DSST_HIT = 0x4de,
+/*20061204 to latest
+ 크리티컬 확률이 향상되었습니다.
+Critical Attack (Critical) has increased.
+*/
+ MSG_ENST_CRITICALSUCCESSVALUE = 0x4df,
+/*20061204 to latest
+ 크리티컬 확률이 원래대로 돌아왔습니다.
+Critical Attack has returned to normal.
+*/
+ MSG_DSST_CRITICALSUCCESSVALUE = 0x4e0,
+/*20061204 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.5배로 증가합니다.
+*/
+ MSG_PLUSEXP = 0x4e1,
+/*20061204 to latest
+ 30분내 사망시 1회에 한해 경험치 감소가 일어나지 않습니다.
+This character will not receive any EXP penalty if killed within the next 30 minutes.
+*/
+ MSG_DDEATHPENALTY = 0x4e2,
+/*20061204 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 30분간 2배로 증가합니다.
+Regular item drops from monsters will be doubled for the next 30 minutes.
+*/
+ MSG_RECEIVEITEM = 0x4e3,
+/*20061204 to latest
+ 10분간 맵 내에 출현 가능한 보스 몬스터에 대한 정보를 안내해 드립니다.
+Boss Monster Map Information for the next 10 minutes.
+*/
+ MSG_BOSS_ALARM = 0x4e4,
+/*20061204 to 20061211
+ 정말로 %s아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20061218 to 20070423
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20070423 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20080610 to latest
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+*/
+ MSG_BUY_RECONFIRM = 0x4e5,
+#endif
+#if PACKETVER >= 20061211
+/*20061211 to 20061211
+'%s'아이템의 사용시간이 %d분 남았습니다.
+20061218 to 20070423
+ 포인트가 부족합니다.
+20070423 to latest
+ 캐시가 부족합니다.
+ You do not have enough Kafra Credit Points.
+*/
+ MSG_BUY_CASH_FAIL_MONEY = 0x4e6,
+/*20061211 to 20061211
+1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+20061218 to latest
+ ^ff0000파기일시: %s^000000
+ ^ff0000Expiration Date: %s^000000
+*/
+ MSG_NOTICE_TO_DELETE_TIME = 0x4e7,
+/*20061211 to 20061211
+'%s'아이템이 인벤토리에서 삭제되었습니다.
+20061218 to latest
+ '%s'아이템의 사용시간이 %d분 남았습니다.
+ The '%s' item will disappear in %d minutes.
+20070102 to 20070312
+ '%s'아이템의 사용시간이 %s 남았습니다.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e8,
+#endif
+#if PACKETVER >= 20061218
+/*20061218 to latest
+ 1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+ '%s' item will be deleted from the Inventory in 1 minute.
+*/
+ MSG_LAST_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e9,
+/*20061218 to latest
+ '%s'아이템이 인벤토리에서 삭제되었습니다.
+ '%s' item has been deleted from the Inventory.
+*/
+ MSG_NOTICE_TO_DELETE_ITEM = 0x4ea,
+#endif
+#if PACKETVER >= 20070102
+/*20070102 to latest
+Input Number
+*/
+ MSG_INPUT_NUMBER = 0x4eb,
+/*20070102 to latest
+%m월 %d일 %H시 %M분
+%m/%d %H:%M
+*/
+ MSG_TIME_TYPE2 = 0x4ec,
+#endif
+#if PACKETVER >= 20070129
+/*20070129 to 20071120
+보스 몬스터 '%s'(이)가 1분 이내에 등장합니다.
+20071127 to latest
+보스 몬스터 '%s'(이)가 잠시 후에 등장합니다.
+Boss Monster '%s' will appear within 1 minute.
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON2 = 0x4ed,
+/*20070129 to latest
+용병 스킬목록
+Mercenary Soldier Skill List
+*/
+ MSG_MER_SKILLLIST = 0x4ee,
+/*20070129 to latest
+블랙젬스톤 1개와 백만제니를 소모하는 마법의 실행에 동의합니까?
+Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+*/
+ MSG_DA_EXP_ACCEPT = 0x4ef,
+#endif
+#if PACKETVER >= 20070220
+/*20070220 to latest
+[POINT] 콜렉터랭킹 포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have gained %d Collector Rank Points; you now have a total of %d Collector Rank Points.
+*/
+ MSG_COLLECTOR_POINT = 0x4f0,
+/*20070220 to latest
+[콜렉터랭킹] Target Item : %s
+[Collector Rank] Target Item: %s
+*/
+ MSG_COLLECTOR_MISSION = 0x4f1,
+#endif
+#if PACKETVER >= 20070227
+/*20070227 to latest
+용병 사용시간이 만료되었습니다.
+The mercenary contract has expired.
+*/
+ MSG_MER_FINISH = 0x4f2,
+/*20070227 to latest
+용병이 사망하였습니다.
+The mercenary has died.
+*/
+ MSG_MER_DIE = 0x4f3,
+/*20070227 to latest
+용병이 해고되었습니다.
+You have released the mercenary.
+*/
+ MSG_MER_RETIRE = 0x4f4,
+/*20070227 to latest
+용병이 도망갔습니다.
+The mercenary has run away.
+*/
+ MSG_MER_RUNAWAY = 0x4f5,
+#endif
+#if PACKETVER >= 20070319
+/*20070319 to latest
+ '%s'아이템의 사용시간이 %d초 남았습니다.
+ The '%s' item will disappear in %d seconds.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME2 = 0x4f6,
+#endif
+#if PACKETVER >= 20070326
+/*20070326 to 20070821
+PC방 이벤트 : 경험치 증가 %d%%, 죽을때 경험치 %d%%, 드롭율 증가 %d%%
+20070828 to latest
+PC방 프리미엄 서비스 : 경험치 %d%% 증가, 사망 페널티 %d%% 감소, 드롭율 %d%% 증가
+IP Bonus: EXP/JEXP %d%%, Death Penalty %d%%, Item Drop %d%%
+*/
+ MSG_PCBANG_EVENT = 0x4f7,
+#endif
+#if PACKETVER >= 20070402
+/*20070402 to latest
+24시간 이후에 시도하세요
+Symbols in Character Names are forbidden.
+*/
+ MSG_LIMIT_CHAR_DELETE = 0x4f8,
+#endif
+#if PACKETVER >= 20070416
+/*20070416 to latest
+용병이 사용자 인공지능으로 동작합니다.
+Mercenary will follow custom AI.
+*/
+ MSG_MER_USERAI_ON = 0x4f9,
+/*20070416 to latest
+용병이 기본 인공지능으로 동작합니다.
+Mercenary will follow basic AI.
+*/
+ MSG_MER_USERAI_OFF = 0x4fa,
+#endif
+#if PACKETVER >= 20070611
+/*20070611 to latest
+ %s님의
+ %s's
+*/
+ MSG_CHARACTER_NAME = 0x4fb,
+/*20070611 to 20070801
+%s님이 %s를 획득하셨습니다.
+20070807 to latest
+%s님이 %s 아이템을 획득하셨습니다.
+%s has acquired %s.
+*/
+ MSG_ITEM_PICKUP_PARTY = 0x4fc,
+/*20070611 to latest
+공개 채팅 메시지 표시
+Public Chat Display
+*/
+ MSG_VIEW_CHAT_MSG = 0x4fd,
+/*20070611 to latest
+귓속말 채팅 메시지 표시
+Whisper Display
+*/
+ MSG_VIEW_WHISPER_MSG = 0x4fe,
+/*20070611 to latest
+파티 채팅 메시지 표시
+Party Chat Display
+*/
+ MSG_VIEW_PARTY_MSG = 0x4ff,
+/*20070611 to latest
+길드 채팅 메시지 표시
+Guild Chat Display
+*/
+ MSG_VIEW_GUILD_MSG = 0x500,
+/*20070611 to latest
+아이템 획득/드롭 메시지 표시
+Item Get/Drop Message Display
+*/
+ MSG_VIEW_GET_ITEM_MSG = 0x501,
+/*20070611 to latest
+장비 장착/해제 메시지 표시
+Equipment On/Off Message Display
+*/
+ MSG_VIEW_EQUIP_MSG = 0x502,
+/*20070611 to latest
+상태이상 메시지 표시
+Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_MSG = 0x503,
+/*20070611 to latest
+파티원의 주요 아이템 획득 메시지 표시
+Party Member's Obtained Item Message Display
+*/
+ MSG_VIEW_GET_ITEM_PARTY_MSG = 0x504,
+/*20070611 to latest
+파티원의 상태이상 메시지 표시
+Party Member's Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_PARTY_MSG = 0x505,
+/*20070611 to latest
+스킬 사용 실패 메시지 표시
+Skill Failure Message Display
+*/
+ MSG_VIEW_FAIL_SKILL_MSG = 0x506,
+/*20070611 to latest
+파티 설정 메시지 표시
+Party Configuration Message Display
+*/
+ MSG_VIEW_PARTY_SETUP_MSG = 0x507,
+/*20070611 to latest
+장비 손상 메시지 표시
+Damaged Equipment Message Display
+*/
+ MSG_VIEW_DAMAGED_EQUIP_MSG = 0x508,
+/*20070611 to latest
+배틀 메시지 창 표시 정보
+Battle Message Window Display
+*/
+ MSG_BATTLE_CHAT_WND_OPTION = 0x509,
+/*20070611 to latest
+[%s]의 소지 한코인 : %d 한코인
+[%s]'s Han Coin: %d Han Coin
+*/
+ MSG_POINT_SHOP_NHN = 0x50a,
+#endif
+#if PACKETVER >= 20070618
+/*20070618 to latest
+일반 메시지
+Public Log
+*/
+ MSG_ST_CHAT = 0x50b,
+/*20070618 to latest
+배틀 메시지
+Battle Log
+*/
+ MSG_BT_CHAT = 0x50c,
+/*20070618 to latest
+휴대폰 인증.
+Mobile Authentication
+*/
+ MSG_PHONE_CONFIRM = 0x50d,
+/*20070618 to latest
+읽기
+Read
+*/
+ MSG_BOOK_READ = 0x50e,
+/*20070618 to latest
+자동낭독
+Auto Read
+*/
+ MSG_BOOK_AUTOREAD = 0x50f,
+/*20070618 to latest
+책갈피
+Bookmark
+*/
+ MSG_BOOK_KEEP = 0x510,
+/*20070618 to latest
+이전페이지
+Previous
+*/
+ MSG_BOOK_PREV = 0x511,
+/*20070618 to latest
+다음페이지
+Next
+*/
+ MSG_BOOK_NEXT = 0x512,
+/*20070618 to latest
+닫기
+Close
+*/
+ MSG_BOOK_CLOSE = 0x513,
+#endif
+#if PACKETVER >= 20070622
+/*20070622 to latest
+%s 장비가 손상되었습니다.
+%s's Equipment has been damaged.
+*/
+ MSG_DAMAGED_EQUIP = 0x514,
+/*20070622 to latest
+%s님의 %s 손상되었습니다.
+%s's %s was damaged.
+*/
+ MSG_DAMAGED_EQUIP_PARTY = 0x515,
+/*20070622 to latest
+무기가
+Weapon
+*/
+ MSG_DAMAGED_WEAPON = 0x516,
+/*20070622 to latest
+갑옷이
+Armor
+*/
+ MSG_DAMAGED_BODY = 0x517,
+/*20070622 to latest
+스킬레벨이 부족합니다. 파티가입 불능
+Insufficient Skill Level for joining a Party
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5_2 = 0x518,
+#endif
+#if PACKETVER >= 20070703
+/*20070703 to latest
+[%s]의 무료 캐시 : %d 캐시
+[%s]'s Free Cash: %d Cash
+*/
+ MSG_POINT_SHOP2 = 0x519,
+/*20070703 to latest
+무료 캐시 사용 :
+Use Free Cash:
+*/
+ MSG_USE_FREE_POINT = 0x51a,
+/*20070703 to latest
+캐시
+Cash
+*/
+ MSG_CASH = 0x51b,
+#endif
+#if PACKETVER >= 20070710
+/*20070710 to latest
+http://payment.ro.hangame.com/index.asp
+*/
+ MSG_SETTLE_WEB_URL_HANGAME = 0x51c,
+/*20070710 to latest
+그라비티 회원 정보동의를 하셔야 사용할수있습니다.
+*/
+ MSG_BAN_GRAVITY_MEM_AGREE = 0x51d,
+/*20070710 to latest
+이용약관에 동의를 하셔야 본 서비스를 이용하실 수 있습니다.
+You need to accept the User Agreement in order to use the service.
+*/
+ MSG_BAN_GAME_MEM_AGREE = 0x51e,
+/*20070710 to 20080513
+존재하지 않는 한게임 ID이거나 잘못된 ID입니다.
+20080520 to latest
+입력하신 아이디와 비밀번호가 등록된 정보와 일치하지 않습니다.
+Incorrect or nonexistent ID.
+*/
+ MSG_BAN_HAN_VALID = 0x51f,
+#endif
+#if PACKETVER >= 20070711
+/*20070711 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20080610 to latest
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+*/
+ MSG_BUY_RECONFIRM2 = 0x520,
+#endif
+#if PACKETVER >= 20070718
+/*20070718 to latest
+%d시간이 경과하였습니다.
+%d hour(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME1 = 0x521,
+/*20070718 to latest
+%d시간 %d분이 경과하였습니다.
+%d hour(s) %d minute(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME2 = 0x522,
+/*20070718 to latest
+게임을 종료하세요, 경험치 및 모든게 50%로 조정됩니다
+Please stop playing the game, and take a break. Exp and other features will be reduced to 50%.
+*/
+ MSG_WARNING_MSG1 = 0x523,
+/*20070718 to latest
+불건전 시간대에 접어들었습니다. 게임을 종료하세요, 경험치 및 모든게 0%로 조정됩니다
+Please stop playing the game since you'll need to rest. Exp and other features will be fixed to 0%.
+*/
+ MSG_WARNING_MSG2 = 0x524,
+#endif
+#if PACKETVER >= 20070724
+/*20070724 to latest
+퀘스트 목록
+Quest List
+*/
+ MSG_QUESTWIN = 0x525,
+#endif
+#if PACKETVER >= 20070807
+/*20070807 to latest
+RO SHOP
+RO Shop
+*/
+ MSG_RO_SHOP = 0x526,
+#endif
+#if PACKETVER >= 20070821
+/*20070821 to 20070904
+메모리얼던젼 '%s'이 예약되었습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 알수없는 이유로 실패 하였습니다.
+Memorial Dungeon, '%s' is booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN = 0x527,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 예약이 실패했습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 예약중복으로 실패 하였습니다.
+Failed to book Memorial Dungeon, '%s'.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE = 0x528,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 이미 예약중입니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 권한문제로 실패 하였습니다.
+Memorial Dungeon, '%s' is already booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT = 0x529,
+/*20070821 to 20070904
+메모리얼던젼 '%s'가 생성 되었습니다
+ 5분내에 입장하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 중복생성요청으로 실패하였습니다.
+Memorial Dungeon, '%s' is created.
+ Please enter in 5 minutes.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST = 0x52a,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 생성에 실패했습니다.
+ 나중에 다시 시도하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약취소가 실패 하였습니다.
+Failed to create Memorial Dungeon, '%s'.
+ Please try again.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_FAIL = 0x52b,
+/*20070821 to latest
+상대방이 파티 초대 거부 상태입니다.
+The character blocked the party invitation.
+*/
+ MSG_JOINMSG_REFUSE = 0x52c,
+#endif
+#if PACKETVER >= 20070828
+/*20070828 to latest
+모든 파티 초대를 거부합니다.
+Block all party invitations.
+*/
+ MSG_INVITE_PARTY_REFUSE = 0x52d,
+/*20070828 to latest
+모든 파티 초대를 수락합니다.
+Allow all party invitations.
+*/
+ MSG_INVITE_PARTY_ACCEPT = 0x52e,
+#endif
+#if PACKETVER >= 20070904
+/*20070904 to latest
+착용하시면 이 아이템은 영구 귀속됩니다. 착용하시겠습니까?
+This item will be permanently bound to this character once it is equipped. Do you really want to equip this item?
+*/
+ MSG_YOURITEM_EQUIP = 0x52f,
+/*20070904 to latest
+%s 아이템이 귀속되었습니다.
+%s is now permanently bound to this character.
+*/
+ MSG_YOURITEM_EQUIPED = 0x530,
+/*20070904 to latest
+캐시가 부족합니다. 무료 캐시 포인트를 입력해 주시기 바랍니다.
+You do not have enough Kafra Credit Points. Please enter whether you have free credit points.
+*/
+ MSG_BUY_TO_FREE_POINT = 0x531,
+/*20070904 to latest
+파티 가입요청
+Request to Join Party
+*/
+ MSG_REQ_JOIN_PARTY3 = 0x532,
+#endif
+#if PACKETVER >= 20070912
+/*20070912 to latest
+공성 정보 메시지 표시
+Display WOE Info
+*/
+ MSG_VIEW_SIEGE_INFO_MSG = 0x533,
+/*20070912 to latest
+메모리얼던젼 '%s'의 예약이 취소 되었습니다.
+Memorial Dungeon %s's reservation has been canceled.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_SUCCESS = 0x534,
+/*20070912 to latest
+메모리얼던젼 '%s' 생성에 실패하였습니다. 다시 시도 하세요.
+Failed to create Memorial Dungeon %s. Please try again.
+*/
+ MSG_MDUNGEON_CREATE_FAIL = 0x535,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 스킬입니다.
+This skill cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_SKILL_AREA = 0x536,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 아이템입니다.
+This item cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_USEITEM_AREA = 0x537,
+#endif
+#if PACKETVER >= 20070918
+/*20070918 to latest
+메모리얼 던전
+Memorial Dungeon
+*/
+ MSG_MEMORIAL_DUN = 0x538,
+/*20070918 to latest
+%s 대기중
+%s in Standby
+*/
+ MSG_MEMORIAL_DUN_WAITING = 0x539,
+/*20070918 to latest
+%s 입장 가능
+%s Available
+*/
+ MSG_MEMORIAL_DUN_READY = 0x53a,
+/*20070918 to 20071120
+%s 내부
+20071127 to latest
+%s 진행중
+%s in Progress
+*/
+ MSG_MEMORIAL_DUN_IN = 0x53b,
+/*20070918 to latest
+시간 안에 입장하지 않아 메모리얼 던전이 사라졌습니다.
+No one entered the Memorial Dungeon within its duration; the dungeon has disappeared.
+*/
+ MSG_MEMORIAL_DUN_OUT1 = 0x53c,
+/*20070918 to latest
+이용하시려면 이용 신청을 처음부터 다시 해주시기 바랍니다.
+Please apply for dungeon entry again to play in this dungeon.
+*/
+ MSG_MEMORIAL_DUN_OUT2 = 0x53d,
+/*20070918 to latest
+대기 순위 : ^ff0000%d^000000
+Your Standby Priority: ^ff0000%d^000000
+*/
+ MSG_MEMORIAL_DUN_PRIORITY = 0x53e,
+/*20070918 to latest
+^ff0000%s^000000 내에 입장하지 않을 경우 신청하신 던전이 삭제 됩니다.
+The requested dungeon will be removed if you do not enter within ^ff0000%s^000000.
+*/
+ MSG_MEMORIAL_DUN_NOTIFY = 0x53f,
+/*20070918 to latest
+던전 미션 제한 시간 :
+Dungeon Mission Time Limit:
+*/
+ MSG_MEMORIAL_DUN_NOTIFY2 = 0x540,
+/*20070918 to latest
+메모리얼 던전 예약이 취소되었습니다.
+The Memorial Dungeon reservation has been canceled.
+*/
+ MSG_MEMORIAL_DUN_CANCEL = 0x541,
+/*20070918 to latest
+메모리얼 던전이 유지 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon duration expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_LIVE_TIME_OUT = 0x542,
+/*20070918 to latest
+메모리얼 던전이 입장 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon's entry time limit expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_ENTER_TIME_OUT = 0x543,
+/*20070918 to latest
+메모리얼 던전이 삭제 되었습니다.
+The Memorial Dungeon has been removed.
+*/
+ MSG_MEMORIAL_DUN_DESTROY_REQUEST = 0x544,
+/*20070918 to latest
+메모리얼 던전에 시스템 오류가 발생하였습니다. 정상적인 게임 진행을 위해 재접속을 해주십시오.
+A system error has occurred in the Memorial Dungeon. Please relog in to the game to continue playing.
+*/
+ MSG_MEMORIAL_DUN_ERROR = 0x545,
+/*20070918 to latest
+사용할 수 없는 슬롯입니다.
+This slot is not usable.
+*/
+ MSG_FR_INVALID_SLOT = 0x546,
+/*20070918 to latest
+Base Level이 15를 넘었습니다.
+Your Base Level is over 15.
+*/
+ MSG_FR_BASELVL = 0x547,
+/*20070918 to latest
+Job Level이 15를 넘었습니다.
+Your Job Level is over 15.
+*/
+ MSG_FR_INVALID_JOBLV = 0x548,
+/*20070918 to latest
+해당슬롯 캐릭터에 직업군의 상인이므로 게임을 할 수 없습니다.
+You cannot play the Merchant class character in this slot.
+*/
+ MSG_FR_JOB = 0x549,
+/*20070918 to latest
+추후 사용예정
+Not Yet Implemented
+*/
+ MSG_FR_MAP = 0x54a,
+/*20070918 to latest
+만들수 있는 케릭터 슬롯이 아닙니다.
+You are not eligible to open the Character Slot.
+*/
+ MSG_FR_ERR_MKCHAR_INVALID_SLOT = 0x54b,
+/*20070918 to latest
+삭제할 수 없는 케릭터 입니다.
+This character cannot be deleted.
+*/
+ MSG_FR_ERR_DELCHAR_INVALID_SLOT = 0x54c,
+/*20070918 to latest
+상대방의 장비창이 공개되어 있지 않습니다.
+This character's equipment information is not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSED = 0x54d,
+/*20070918 to latest
+장비창을 공개하지 않습니다.
+Equipment information not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSE = 0x54e,
+/*20070918 to latest
+장비창을 공개합니다.
+Equipment information open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_ACCEPT = 0x54f,
+/*20070918 to latest
+(%s)님 장비창 보기
+Check %s's Equipment Info
+*/
+ MSG_REQ_VIEW_OTHERUSER = 0x550,
+/*20070918 to latest
+%s의 장착아이템
+'%s's Equipment
+*/
+ MSG_OTHERUSER_EQUIPED_ITEM = 0x551,
+/*20070918 to latest
+장비창 공개
+Show Equip
+*/
+ MSG_OPEN_EQUIPED_ITEM = 0x552,
+#endif
+#if PACKETVER >= 20071002
+/*20071002 to latest
+프리미엄 서비스를 이용해 주시기 바랍니다.
+This service is only available for premium users.
+*/
+ MSG_NEED_PREMIUM_SERVICE = 0x553,
+/*20071002 to latest
+무료 사용자는 최대 50000제니까지 소유할 수 있습니다.
+Free Trial users can only hold up to 50,000 zeny.
+*/
+ MSG_FR_INVALID_MONEY = 0x554,
+#endif
+#if PACKETVER >= 20071009
+/*20071009 to latest
+전장채팅 상태가 되었습니다.
+Battlefield Chat has been activated.
+*/
+ MSG_BATTLECHAT_ON = 0x555,
+/*20071009 to latest
+전장채팅 상태가 해제되었습니다.
+Battlefield Chat has been deactivated.
+*/
+ MSG_BATTLECHAT_OFF = 0x556,
+#endif
+#if PACKETVER >= 20071017
+/*20071017 to latest
+용병정보 - 몬스터타입
+Mercenary Info - Monster Type
+*/
+ MSG_MER_INFO_TYPE_MONSTER = 0x557,
+#endif
+#if PACKETVER >= 20071106
+/*20071106 to latest
+전체 맵 보기
+World Map
+*/
+ MSG_RO_MAP = 0x558,
+#endif
+#if PACKETVER >= 20071127
+/*20071127 to latest
+메모리얼던젼이 CLOSE 상태입니다.
+The Memorial Dungeon is now closed.
+*/
+ MSG_MEMORIAL_DUN_CLOSE = 0x559,
+#endif
+#if PACKETVER >= 20071204
+/*20071204 to latest
+^ff0000^ff0000용병을 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+^ff0000Deleting a Mercenary Soldier^000000 will also delete his growth history. Do you really want to proceed with the deletion?
+*/
+ MSG_DELETE_MER = 0x55a,
+#endif
+#if PACKETVER >= 20071211
+/*20071211 to latest
+메모리얼던젼이 OPEN 상태입니다.
+The Memorial Dungeon is now open.
+*/
+ MSG_MEMORIAL_DUN_OPEN = 0x55b,
+#endif
+#if PACKETVER >= 20080108
+/*20080108 to latest
+위의 계정은 아직 통신 안전 키에 연결되지 않았습니다. 먼저 안전 키를 해제하신 뒤 게임에 접속해 주십시오.
+This account has not been confirmed by connecting to the safe communication key. Please connect to the key first, and then log into the game.
+*/
+ MSG_PHONE_BLOCK = 0x55c,
+/*20080108 to latest
+한 아이피로 접속 가능한 유저수를 초과하였습니다.
+The number of accounts connected to this IP has exceeded the limit.
+*/
+ MSG_BAN_PC_IP_LIMIT_ACCESS = 0x55d,
+#endif
+#if PACKETVER >= 20080219
+/*20080219 to latest
+새로운 퀘스트를 받았습니다
+You have received a new quest.
+*/
+ MSG_QUESTGET = 0x55e,
+#endif
+#if PACKETVER >= 20080401
+/*20080401 to latest
+^777777습득조건 :
+^CC3399Requirement:
+*/
+ MSG_FINDTEXT_TO_SKILLDES = 0x55f,
+/*20080401 to latest
+스킬 설명 보기
+View Skill Info
+*/
+ MSG_VIEW_SKILL_DESCRIPT = 0x560,
+#endif
+#if PACKETVER >= 20080408
+/*20080408 to latest
+사용된 스킬 포인트는 다시 되돌릴 수 없습니다. 적용하시겠습니까?
+Once used, skill points cannot be re-allocated. Would you like to use the skill points?
+*/
+ MSG_APPLY_SKILL_UP = 0x561,
+/*20080408 to latest
+노비스·1차직업
+1st
+*/
+ MSG_1TABNAME_SKILLWND = 0x562,
+/*20080408 to latest
+2차·전승직업
+2nd
+*/
+ MSG_2TABNAME_SKILLWND = 0x563,
+/*20080408 to 20080513
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭시간 : %s
+20080520 to latest
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭종료시간 : %s
+This account has been used for illegal program or hacking program. Block Time: %s
+*/
+ MSG_RE17 = 0x564,
+/*20080408 to latest
+불법프로그램이 실행, 바이러스 감염, 또는 해킹툴이 설치되어 있을 가능성이 있습니다. 정상 클라이언트를 실행하여 주시기 바랍니다. 함께 만드는 밝은 라그나로크가 될 수 있도록 노력하고 있습니다.
+The possibility of exposure to illegal program, PC virus infection or Hacking Tool has been detected. Please execute licensed client. Our team is trying to make a best environment for Ro players.
+*/
+ MSG_RE18 = 0x565,
+#endif
+#if PACKETVER >= 20080415
+/*20080415 to latest
+당신은 지금 건강한 게임 시간 대에 있습니다, 즐거운 게임이 되시길 바랍니다
+You are currently playing in the best game environment. Please enjoy the Ragnarok.
+*/
+ MSG_WARNING_MSG3 = 0x566,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.5배로 증가합니다.
+*/
+ MSG_PLUSONLYJOBEXP = 0x567,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.25배로 증가합니다.
+*/
+ MSG_PLUSEXP14532 = 0x568,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 2배로 증가합니다.
+EXP points from hunting monsters are increased by 100%% for 30 minutes.
+*/
+ MSG_PLUSEXP14533 = 0x569,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 60분간 1.5배로 증가합니다.
+EXP points from hunting monsters are increased by 50% for 60 minutes.
+*/
+ MSG_PLUSEXP12312 = 0x56a,
+#endif
+#if PACKETVER >= 20080520
+/*20080520 to latest
+이 맵에서는 파티를 결성할 수 없습니다.
+Unable to organize a party in this map.
+*/
+ MSG_NOPARTY = 0x56b,
+/*20080520 to latest
+(%s)님은 파티에 참여할 수 없는 맵에 있습니다.
+(%s) are currently in restricted map to join a party.
+*/
+ MSG_NOPARTY2 = 0x56c,
+#endif
+#if PACKETVER >= 20080528
+/*20080528 to 20080603
+간편아이템샵.
+20080610 to latest
+간편아이템샵
+Simple Item Shop
+*/
+ MSG_SIMPLE_CASH_SHOP = 0x56d,
+/*20080528 to latest
+소지 한코인 : %d 한코인
+Han Coin: %d Han Coin
+*/
+ MSG_SIMPLE_POINT_SHOP_NHN = 0x56e,
+/*20080528 to latest
+소지 캐시 : %d 캐시
+RoK Point: %d RoK Point
+*/
+ MSG_SIMPLE_POINT_SHOP = 0x56f,
+/*20080528 to latest
+무료 캐시 : %d 캐시
+Free Cash: %d Cash
+*/
+ MSG_SIMPLE_POINT_SHOP2 = 0x570,
+#endif
+
+};
+#endif /* MAP_MESSAGES_AD_H */
diff --git a/src/map/messages_main.h b/src/map/messages_main.h
new file mode 100644
index 000000000..9f5a17662
--- /dev/null
+++ b/src/map/messages_main.h
@@ -0,0 +1,22617 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_MESSAGES_MAIN_H
+#define MAP_MESSAGES_MAIN_H
+
+/* This file is autogenerated, please do not commit manual changes
+
+Latest version: 20200304
+*/
+
+enum clif_messages {
+/*20031028 to latest
+동의 하십니까?
+Do you agree?
+*/
+ MSG_DO_YOU_AGREE = 0x0,
+/*20031028 to latest
+서버 연결 실패
+Failed to Connect to Server.
+*/
+ MSG_SERVER_CONNECTION_FAILED = 0x1,
+/*20031028 to latest
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+*/
+ MSG_UNABLE_TO_CONNECT_SERVER = 0x2,
+/*20031028 to 20080617
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+20080624 to latest
+서버와 연결이 끊어졌습니다!
+Disconnected from Server!
+*/
+ MSG_BANNED = 0x3,
+/*20031028 to latest
+서버 종료됨
+Server Closed.
+*/
+ MSG_SERVER_OFF = 0x4,
+/*20031028 to latest
+같은 계정으로 다른 사용자가 로그인 하였습니다.
+Someone has Logged in with this ID.
+*/
+ MSG_DOUBLE_LOGIN_PROHIBITED = 0x5,
+/*20031028 to latest
+등록되지 않은 계정입니다. 다시 확인 바랍니다.
+Unregistered ID. Please make sure you have a registered account and you have correctly typed in the user ID.
+*/
+ MSG_INCORRECT_USERID = 0x6,
+/*20031028 to 20070704
+비밀번호가 틀립니다
+20070710 to latest
+입력하신 비밀번호가 올바르지 않습니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_PASSWORD = 0x7,
+/*20031028 to latest
+본 ID 는 사용기간이 만료 되었습니다
+This ID is expired.
+*/
+ MSG_ID_EXPIRED = 0x8,
+/*20031028 to latest
+서버 접근 거부
+Rejected from Server.
+*/
+ MSG_ACCESS_DENIED = 0x9,
+/*20031028 to latest
+같은 캐릭터 이름이 있습니다.
+Character Name already exists.
+*/
+ MSG_CHARACTER_NAME_ALREADY_EXISTS = 0xa,
+/*20031028 to latest
+캐릭터 생성 거부됨
+Character Creation is denied.
+*/
+ MSG_CHARACTER_CREATION_DENIED = 0xb,
+/*20031028 to latest
+캐릭터 삭제 거부
+Character Deletion is denied.
+*/
+ MSG_CANNOT_DELETE_CHARACTER = 0xc,
+/*20031028 to latest
+방제목를 입력하세요.
+Please Enter Room Title.
+*/
+ MSG_ENTER_ROOM_TITLE = 0xd,
+/*20031028 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_SENTANGE = 0xe,
+/*20031028 to latest
+암호를 입력하세요.
+Please enter Password.
+*/
+ MSG_ENTER_PASSWORD = 0xf,
+/*20031028 to latest
+암호를 영문 4자 이상 입력하세요.
+Please enter Password. Passwords must be at least 4 characters long.
+*/
+ MSG_Enter_Password_more_than_4_char = 0x10,
+/*20031028 to latest
+종료 하시겠습니까?
+Are you sure that you want to quit?
+*/
+ MSG_DO_YOU_REALLY_WANT_TO_QUIT = 0x11,
+/*20031028 to latest
+4자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Passwords are at least 4 characters long. Please try again.
+*/
+ MSG_NAME_MUST_EXCEED_4_CHAR = 0x12,
+/*20031028 to 20070704
+캐릭터를 삭제하겠습니까?
+20070618 to latest
+한 번 삭제된 캐릭터 및 관련 정보는 다시 복구되지 않습니다. 캐릭터를 삭제하시겠습니까?
+Are you sure that you want to delete this character?
+*/
+ MSG_DELETE_CHARACTER = 0x13,
+/*20031028 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_NAME = 0x14,
+/*20031028 to latest
+이름을 입력해 주세요.(한글 2자 영문 4자 이상)
+Character Name must be at least 4 characters long.
+*/
+ MSG_ENTER_NAME_MORE_THAN_4_CHAR = 0x15,
+/*20031028 to latest
+명령어 일람: /h
+Command List: /h | /help
+*/
+ MSG_LIST_COMMAND = 0x16,
+/*20031028 to latest
+이펙트 On
+Effects On
+*/
+ MSG_EFFECT_ON = 0x17,
+/*20031028 to latest
+이펙트 Off
+Effects Off
+*/
+ MSG_EFFECT_OFF = 0x18,
+/*20031028 to latest
+사운드 볼륨
+Sound Volume
+*/
+ MSG_VOLUME_OF_SOUND = 0x19,
+/*20031028 to latest
+배경음악 볼륨
+BGM Volume
+*/
+ MSG_VOLUME_OF_BGM = 0x1a,
+/*20031028 to latest
+효과음 On
+Sound Effects On
+*/
+ MSG_SOUND_ON = 0x1b,
+/*20031028 to latest
+효과음 Off
+Sound Effects Off
+*/
+ MSG_SOUND_OFF = 0x1c,
+/*20031028 to latest
+프레임스킵 On
+Frame Skip On
+*/
+ MSG_FRAME_SKIP_ON = 0x1d,
+/*20031028 to latest
+프레임스킵 Off
+Frame Skip Off
+*/
+ MSG_FRAME_SKIP_OFF = 0x1e,
+/*20031028 to latest
+배경음악 On
+BGM On
+*/
+ MSG_BGM_ON = 0x1f,
+/*20031028 to latest
+배경음악 Off
+BGM Off
+*/
+ MSG_BGM_OFF = 0x20,
+/*20031028 to latest
+/h or /help: 명령어 일람
+/h or /help: Shows this Command Help List
+*/
+ MSG_EXPLAIN_HELP = 0x21,
+/*20031028 to latest
+/w or /who or /접속자 or /누구: 현재 접속자수 보기
+/w or /who or /player or /who: wiew current the number of player
+*/
+ MSG_EXPLAIN_WHO = 0x22,
+/*20031028 to latest
+/음악 : 배경음악 On Off
+/music: Turns BGM On or Off
+*/
+ MSG_EXPLAIN_MUSIC = 0x23,
+/*20031028 to latest
+/효과음 : 효과음 On Off
+/sound: Turns Sound Effects On or Off
+*/
+ MSG_EXPLAIN_SOUND = 0x24,
+/*20031028 to latest
+/이펙트 : 이펙트 On Off
+/effect: Effects On or Off
+*/
+ MSG_EXPLAIN_EFFECT = 0x25,
+/*20031028 to latest
+/좌표 or /장소: 현재 위치 표시
+/where: Shows your present location
+*/
+ MSG_EXPLAIN_POS = 0x26,
+/*20031028 to latest
+/skip : 프래임스킵 On Off
+/skip: Turns Frame Skip On or Off
+*/
+ MSG_EXPLAIN_FRAMESKIP = 0x27,
+/*20031028 to latest
+/v (0~127): 효과음 볼륨조정
+/v (0~127): Controls the volume of the Sound Effects
+*/
+ MSG_EXPLAIN_SOUNDVOLUME = 0x28,
+/*20031028 to latest
+/bv (0~127): 배경음악 볼륨조정
+/bv (0~127): Controls the volume of the BGM
+*/
+ MSG_EXPLAIN_BGMVOLUME = 0x29,
+/*20031028 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당캐릭터에 대해 귓말차단
+/ex (Character Name): Blocks whispering from the Character
+*/
+ MSG_EXPLAIN_SAYISOLATION = 0x2a,
+/*20031028 to latest
+/ex or /차단 : 귓말차단 캐릭터 리스트
+/ex: View a list of Characters you have Blocked
+*/
+ MSG_EXPLAIN_LIST_SAYISOLATION_CHAR = 0x2b,
+/*20031028 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당캐릭터에 대해 귓말허용
+/in (Character Name): Allows whispering from the Character
+*/
+ MSG_EXPLAIN_SAY_PERMIT = 0x2c,
+/*20031028 to latest
+/inall or /해제전부 : 모두에게 귓말허용
+/inall: Allows whispers from anyone
+*/
+ MSG_EXPLAIN_SAY_PERMITALL = 0x2d,
+/*20031028 to latest
+/exall or /차단전부 : 모두에게 귓말차단
+/exall: Blocks whispers from everyone
+*/
+ MSG_EXPLAIN_SAY_ISOLATEALL = 0x2e,
+/*20031028 to latest
+다른유저 캐릭터를 마우스 오른버튼을 누르고 있는 상태에서 왼버튼으로 클릭하면 그캐릭터이름이 귓말콤보박스에 저장됩니다.
+Right click on a character and select [Register as a Friend] to add a person to your Friend List.
+*/
+ MSG_EXPLAIN_TIP1 = 0x2f,
+/*20031028 to latest
+단축아이탬창(F12) 소비장비 아이템을 드래그한후 사용하세요. 사용키(F1F2F3F4F5F6F7F8F9)
+F12 Brings up a Hotkey Window which allows you to drag and drop Recovery Items, Equipment and Skills into it for faster access.
+*/
+ MSG_EXPLAIN_TIP2 = 0x30,
+/*20031028 to latest
+같은말을 3번이상 연속해서 전송할 수 없습니다.
+You can't type the same word/phrase more than 3 times.
+*/
+ MSG_NO_SAME_SENTANCE = 0x31,
+/*20031028 to latest
+불량단어 검출로 전송이 중단 되었습니다.
+Chat Filter: Yeah, uh, I don't think so buddy...
+*/
+ MSG_NO_SEND_BECAUSE_INSULT = 0x32,
+/*20031028 to latest
+같은아이템은 한번만 올릴수 있습니다.
+You cannot overlap items on a window.
+*/
+ MSG_CAN_DRAG_ITEM_OLNY_ONETIME = 0x33,
+/*20031028 to latest
+무게가 초과하여 아이템을 가질 수 없습니다.
+You cannot carry more items because you are overweight.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_WEIGHT = 0x34,
+/*20031028 to latest
+아이템을 가질 수 없습니다.
+You cannot get the item.
+*/
+ MSG_CANT_GET_ITEM = 0x35,
+/*20031028 to latest
+거래가 잘 이루어졌습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SECCESS = 0x36,
+/*20031028 to latest
+돈이 부족합니다.
+You do not have enough zeny.
+*/
+ MSG_INSUFFICIENT_MONEY = 0x37,
+/*20031028 to latest
+무게가 초과 되었습니다.
+You are over your Weight Limit.
+*/
+ MSG_OVER_WEIGHT = 0x38,
+/*20031028 to latest
+거래가 실패 했습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAIL = 0x39,
+/*20031028 to latest
+모두에게 귓말거부상태로됨
+You've blocked whispers from everyone.
+*/
+ MSG_REFUSE_HEAR_ALL = 0x3a,
+/*20031028 to latest
+모두에게 귓말거부요청 실패함
+You've failed to block all whispers.
+*/
+ MSG_REQ_REFUSE_HEAR_ALL_FAIL = 0x3b,
+/*20031028 to latest
+모두에게 귓말가능상태가됨
+You've allowed whispers from everyone.
+*/
+ MSG_HEAR_ALL = 0x3c,
+/*20031028 to latest
+모두에게 귓말가능요청 실패함
+You've failed to allow all whispers.
+*/
+ MSG_REQ_HEAR_ALL_FAIL = 0x3d,
+/*20031028 to latest
+귓말 거부 리스트가 없습니다
+You have no Block List.
+*/
+ MSG_NO_REFUSE_HEAR_LIST = 0x3e,
+/*20031028 to latest
+-귓말 거부 리스트-
+[ Character Block List ]
+*/
+ MSG_REFUSE_HEAR_LIST = 0x3f,
+/*20031028 to latest
+방이 잘 만들어 졌습니다.
+Room has been successfully created.
+*/
+ MSG_ROOM_IS_MADE = 0x40,
+/*20031028 to latest
+방갯수가 허용갯수를 초과 하였습니다.
+Room Limit Exceeded.
+*/
+ MSG_TOO_MANY_ROOM = 0x41,
+/*20031028 to latest
+같은 방제목이 있습니다.
+Same Room exists.
+*/
+ MSG_SAME_ROOM_TITLE = 0x42,
+/*20031028 to latest
+인원초과로 방에 들어갈 수 없습니다.
+The Room is full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_ROOM = 0x43,
+/*20031028 to latest
+강제로 퇴장된 방입니다.
+You have been kicked out of this room.
+*/
+ MSG_YOU_HAVE_BANNED_FROM_THE_ROOM = 0x44,
+/*20031028 to latest
+교환요청을 거절 했습니다.
+The deal has been rejected.
+*/
+ MSG_REJECT_DEAL = 0x45,
+/*20031028 to latest
+교환가능거리를 벗어났습니다.
+You are too far away from the person to trade.
+*/
+ MSG_TOO_FAR_TO_DEAL = 0x46,
+/*20031028 to latest
+해당 캐릭터가 없습니다.
+The Character is not currently online or does not exist.
+*/
+ MSG_CHARACTER_IS_NOT_EXIST = 0x47,
+/*20031028 to latest
+다른캐릭터와 교환중입니다.
+The person is in another deal.
+*/
+ MSG_CHARACTER_IS_DEALING = 0x48,
+/*20031028 to 20110627
+상태캐릭터 중량초과로 올려놓을수가 없습니다.
+20110705 to latest
+상대 캐릭터 중량초과로 올려놓을 수 없습니다.
+You cannot trade because this character will exceed his weight limit.
+*/
+ MSG_CHARACTER_IS_OVER_WEIGHT = 0x49,
+/*20031028 to latest
+거래가 취소 되었습니다.
+The deal has been canceled.
+*/
+ MSG_DEAL_IS_CANCELED = 0x4a,
+/*20031028 to latest
+아이템 교환이 잘 되었습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SUCCESS = 0x4b,
+/*20031028 to latest
+아이템 교환이 실패 하였습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAILED = 0x4c,
+/*20031028 to latest
+파티가 만들어졌습니다.
+Party has successfully been organized.
+*/
+ MSG_PARTY_MAKE_SUCCEED = 0x4d,
+/*20031028 to latest
+같은 파티이름이 있습니다.
+That Party Name already exists.
+*/
+ MSG_SAME_PARTY_NAME = 0x4e,
+/*20031028 to latest
+이미 파티에 속해있습니다.
+The Character is already in a party.
+*/
+ MSG_YOU_ARE_ALREADY_IN_PARTY = 0x4f,
+/*20031028 to latest
+다른파티에 가입되어 있습니다.
+The Character already joined another party.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_PARTY = 0x50,
+/*20031028 to latest
+파티가입을 거부했습니다.
+Request for party rejected.
+*/
+ MSG_CHARACTER_REJECT_JOIN = 0x51,
+/*20031028 to latest
+파티가입을 수락했습니다.
+Request for party accepted.
+*/
+ MSG_CHARACTER_ACCEPT_JOIN = 0x52,
+/*20031028 to latest
+파티정원을 초과했습니다.
+Party Capacity exceeded.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_PARTY = 0x53,
+/*20031028 to latest
+파티에서 탈퇴하였습니다.
+You left the party.
+*/
+ MSG_YOU_LEAVE_FROM_PARTY = 0x54,
+/*20031028 to latest
+전체에게 보냄
+Send to All
+*/
+ MSG_SEND_TO_ALL = 0x55,
+/*20031028 to latest
+파티에게 보냄
+Send to Party
+*/
+ MSG_SEND_TO_PARTY = 0x56,
+/*20031028 to latest
+님과의 거래요청
+Request a deal with %s
+*/
+ MSG_REQ_DEAL_WITH = 0x57,
+/*20031028 to latest
+님 파티에 가입요청
+Ask %s to join your party
+*/
+ MSG_REQ_JOIN_PARTY = 0x58,
+/*20031028 to latest
+비공개 :
+Pri:
+*/
+ MSG_ROOM_PRIVATE = 0x59,
+/*20031028 to latest
+공개 :
+Pub:
+*/
+ MSG_ROOM_PUBLIC = 0x5a,
+/*20031028 to latest
+마지막 체크지점부터 시작하려면 '재시작'을 캐릭터 선택으로 돌아가려면 '종료'를 눌러주세요.
+Click ''Restart'' to go back to your save point or click ''Exit'' to select another character.
+*/
+ MSG_RESTART_MSG = 0x5b,
+/*20031028 to latest
+원하는 거래를 선택하세요.
+Please select a Deal Type.
+*/
+ MSG_SELECT_DEAL_TYPE = 0x5c,
+/*20031028 to latest
+님이 거래를 요청했습니다.
+ requests a deal.
+*/
+ MSG_SUGGEST_DEAL = 0x5d,
+/*20031028 to latest
+ 파티에서 초청 메시지가 왔습니다. 합류하겠습니까?
+ Party has sent you an invitation. Would you like to join?
+*/
+ MSG_SUGGEST_JOIN_PARTY = 0x5e,
+/*20031028 to latest
+명령이 틀렸습니다.
+Invalid Command
+*/
+ MSG_INVALID_COMMAND = 0x5f,
+/*20031028 to latest
+탈퇴하기
+Leave party
+*/
+ MSG_LEAVE_PARTY = 0x60,
+/*20031028 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL = 0x61,
+/*20031028 to latest
+쪽지보내기
+Send Message
+*/
+ MSG_MSG = 0x62,
+/*20031028 to latest
+1:1 대화
+1:1 Chat
+*/
+ MSG_1ON1 = 0x63,
+/*20031028 to latest
+정보
+Information
+*/
+ MSG_CHARACTER_INFO = 0x64,
+/*20031028 to latest
+파티설정
+Party Setup
+*/
+ MSG_PARTY_SETTING = 0x65,
+/*20031028 to latest
+친구
+Friend
+*/
+ MSG_FRIEND = 0x66,
+/*20031028 to latest
+파티
+Party
+*/
+ MSG_PARTY = 0x67,
+/*20031028 to latest
+장착아이템
+Equipment
+*/
+ MSG_EQUIPED_ITEM = 0x68,
+/*20031028 to latest
+스테이터스
+Status
+*/
+ MSG_STATUS_ = 0x69,
+/*20031028 to latest
+소지아이템
+Inventory
+*/
+ MSG_ITEM = 0x6a,
+/*20031028 to latest
+/결성 [파티이름] : 파티결성 /탈퇴 : 파티탈퇴
+/organize ''Party Name'' To organize a party. Type /leave To leave a Party.
+*/
+ MSG_EXPLAIN_PARTY = 0x6b,
+/*20031028 to latest
+자신이 파티리더일때 캐릭터를 오른버튼으로 클릭하면 파티에 가입요청하기 메뉴가 뜹니다.
+If you are the party master, you can invite someone into your party by right-clicking on a Character.
+*/
+ MSG_EXPLAIN_TIP3 = 0x6c,
+/*20031028 to latest
+회복
+Consumables
+*/
+ MSG_RESTORE = 0x6d,
+/*20031028 to latest
+공격
+Attack
+*/
+ MSG_ATTACK = 0x6e,
+/*20031028 to latest
+보조
+Support
+*/
+ MSG_SUPPORT = 0x6f,
+/*20031028 to latest
+전체
+All
+*/
+ MSG_ALL = 0x70,
+/*20031028 to latest
+무기
+Weapons
+*/
+ MSG_WEAPON = 0x71,
+/*20031028 to latest
+방어
+Defense
+*/
+ MSG_DEFENCE = 0x72,
+/*20031028 to latest
+수
+Water
+*/
+ MSG_WATER = 0x73,
+/*20031028 to latest
+지
+Earth
+*/
+ MSG_EARTH = 0x74,
+/*20031028 to latest
+화
+Fire
+*/
+ MSG_FIRE = 0x75,
+/*20031028 to latest
+풍
+Wind
+*/
+ MSG_WIND = 0x76,
+/*20031028 to 20191023
+같은종류의 장비아이템은 한번에 한개만 살 수 있습니다.
+Please avoid buying 2 of the same items at one time.
+20191030 to latest
+같은 종류의 장비 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_EQUIPITEM_OLNY_ONE = 0x77,
+/*20031028 to latest
+창모드에서 실행 할때는 16비트 컬러로 맞춰주세요.
+Please change your desktop Color Depth to 16-bit when running Ragnarok in windowed mode.
+*/
+ MSG_ONLY_16BIT_WHEN_WINDOWMODE = 0x78,
+/*20031028 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_PLEASE_BE_PATIENT = 0x79,
+/*20031028 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_WAITING_RESPONSE_FROM_SERVER = 0x7a,
+/*20031028 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_MAKING_CHARACTER = 0x7b,
+/*20031028 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_DELETING_CHARACTER = 0x7c,
+/*20031028 to latest
+방 만들기
+Make a Room
+*/
+ MSG_MAKING_ROOM = 0x7d,
+/*20031028 to latest
+방셋팅 바꾸기
+Room Setup
+*/
+ MSG_CHANGE_ROOM_SETTING = 0x7e,
+/*20031028 to latest
+강퇴시키기
+Kick Character Out
+*/
+ MSG_BAN = 0x7f,
+/*20031028 to latest
+방장권한 주기
+Give Master Authority
+*/
+ MSG_GIVE_GIVE_ROOM_POWER = 0x80,
+/*20031028 to latest
+정보보기
+View Information
+*/
+ MSG_SEE_INFORMATION_OF_CHARACTER = 0x81,
+/*20031028 to latest
+대화방
+Chat Room
+*/
+ MSG_CHAT_ROOM = 0x82,
+/*20031028 to latest
+명
+Ppl
+*/
+ MSG_COUNT_UNIT_OF_PEOPLE = 0x83,
+/*20031028 to latest
+/앉기 or /sit : 앉기. 앉아있을때 서기
+/sit: Sit command. If you are sitting, you will stand instead.
+*/
+ MSG_EXPLAIN_SIT = 0x84,
+/*20031028 to latest
+/서기 or /stand : 서기. 서있을때 앉기
+/stand: Stand command. If you are standing, you will sit instead.
+*/
+ MSG_EXPLAIN_STAND = 0x85,
+/*20031028 to latest
+/채팅방 or /chat : 채팅방 만들기창 띄우기
+/chat: Creates a Chat Room
+*/
+ MSG_EXPLAIN_MAKE_CHAT = 0x86,
+/*20031028 to latest
+/q : 채팅방 나가기.
+/q: Leaves a Chat Room
+*/
+ MSG_EXPLAIN_EXIT_CHAT_ROOM = 0x87,
+/*20031028 to latest
+/거래 [캐릭터이름] or /교환 [캐릭터이름] or /deal [캐릭터이름] : 해당 캐릭터와 거래요청
+/deal ''Character Name'' Requests a deal with a character
+*/
+ MSG_EXPLAIN_DEAL = 0x88,
+/*20031028 to latest
+/결성 [파티이름] or /organize [파티이름] : 파티결성
+/organize ''Party Name'' Organizes a party
+*/
+ MSG_EXPLAIN_ORGANIZE_PARTY = 0x89,
+/*20031028 to latest
+/탈퇴 or /leave : 파티 탈퇴
+/leave: Leaves a party
+*/
+ MSG_EXPLAIN_LEAVE_PARTY = 0x8a,
+/*20031028 to latest
+/제명 [캐릭터이름] or /expel [캐릭터이름] : 해당캐릭터를 파티에서 제명시킴
+/expel ''Character Name'' kicks a Character out of your party
+*/
+ MSG_EXPLAIN_EXPEL_PARTY_MEMBER = 0x8b,
+/*20031028 to latest
+[Alt] + [End] : 플레이어 hp/sp 게이지 On Off
+[Alt] + [End]: Turns HP/SP Bar On or Off
+*/
+ MSG_EXPLAIN_TIP4 = 0x8c,
+/*20031028 to latest
+[Alt] + [Home] : 지면 커서 표시 On Off
+[Alt] + [Home]: Turns Ground Cursor On or Off
+*/
+ MSG_EXPLAIN_TIP5 = 0x8d,
+/*20031028 to latest
+[Insert] : 앉기 서기
+[Insert]: Makes you sit or stand. (Hotkey to toggle between /sit and /stand)
+*/
+ MSG_EXPLAIN_TIP6 = 0x8e,
+/*20031028 to latest
+MVP가 되셨습니다!! MVP 아이템은
+Congratulations! You are the MVP! Your reward item is
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM = 0x8f,
+/*20031028 to latest
+ !!
+!
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM2 = 0x90,
+/*20031028 to latest
+MVP가 되셨습니다!! 특별경험치
+Congratulations! You are the MVP! Your reward EXP Points are
+*/
+ MSG_YOU_RECEIVE_MVP_EXP = 0x91,
+/*20031028 to latest
+ 획득!!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_EXP2 = 0x92,
+/*20031028 to latest
+MVP가 되셨습니다만 무게초과로 MVP 아이템을 가질 수 없었습니다!!
+You are the MVP, but you can't take the reward because you are over your weight limit.
+*/
+ MSG_YOU_THROW_MVPITEM = 0x93,
+/*20031028 to latest
+ 없는 캐릭터 이름 입니다.
+There is no such character name or the user is offline.
+*/
+ MSG_NOT_EXIST_CHARACTER = 0x94,
+/*20031028 to latest
+ 수신 거부 상태입니다.
+ doesn't want to receive your messages.
+*/
+ MSG_NO_RECEIVE_MODE = 0x95,
+/*20031028 to latest
+ 모든 캐릭터에 대해 수신 거부 상태 입니다.
+ is not in the mood to talk with anyone.
+*/
+ MSG_NO_RECEIVE_MODE_FOR_ALL = 0x96,
+/*20031028 to latest
+캐릭터 접속끊기 성공.
+Killed/Disconnected User.
+*/
+ MSG_SUCCESS_DISCONNECT_CHARACTER = 0x97,
+/*20031028 to latest
+캐릭터 접속끊기 실패.
+Kill has failed.
+*/
+ MSG_FAIL_DISCONNECT_CHARACTER = 0x98,
+/*20031028 to latest
+%s %d 개 획득
+You got %s (%d).
+*/
+ MSG_GET_ITEM = 0x99,
+/*20031028 to latest
+[Alt] + [=] : 알파벳 간격이 넓어졌을때 되돌리기.
+[Alt] + [=]: Fix the interval error between letters.
+*/
+ MSG_EXPLAIN_TIP7 = 0x9a,
+/*20031028 to latest
+[F10] : 채팅창 크기조정 [Alt] + [F10] : 채팅창 On Off
+[F10]: To toggle Chat Window size; [Alt] + [F10]: Toggle Chat Window On or Off
+*/
+ MSG_EXPLAIN_TIP8 = 0x9b,
+/*20031028 to latest
+귓속말 하는법 : 채팅창 왼쪽 입력란에 캐릭터이름을 입력하고 오른쪽 입력란에 말을 입력하면 됩니다. TAB키로 두입력란 사이로 커서를 이동할 수 있습니다.
+How to Whisper: Enter a Character's Name on the left side of chat window and type your message on the right side. The Tab key helps you move between these boxes.
+*/
+ MSG_EXPLAIN_TIP9 = 0x9c,
+/*20031028 to latest
+/! /? /기쁨 /하트 /땀 /아하 /짜증 /화 /돈 /... /가위 /바위 /보 : Alt + (1~9) Ctrl + (-=\) 에 대응되는 명령어 입니다.
+/!,/?,/ho,/lv,/lv2,/swt,/ic,/an,/ag,/$,/….,/thx,/wah,/sry,/heh,/swt2,/hmm,/no1,/??,/omg,/oh,/X,/hp,/go,/sob,/gg,/kis,/kis2,/pif,/ok: Emotion icons corresponding to Alt + (1~9) Ctrl + (-=\\)
+*/
+ MSG_EXPLAIN_TIP10 = 0x9d,
+/*20031028 to latest
+파티원에게 말하는법 : 말의 제일앞에 '%'를 붙이면 파티원에게 말이 갑니다. (예: "%안녕")
+How to Speak to Party: Add % in front of every message.(Example: \%Hello\)
+*/
+ MSG_EXPLAIN_TIP11 = 0x9e,
+/*20031028 to latest
+스킬레벨이 부족합니다. 교환 불능.
+You haven't learned enough Basic Skills to Trade.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE1 = 0x9f,
+/*20031028 to latest
+스킬레벨이 부족합니다. 이모션 불능.
+You haven't learned enough Basic Skills to use Emotion icons.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE2 = 0xa0,
+/*20031028 to latest
+스킬레벨이 부족합니다. 앉기 불능.
+You haven't learned enough Basic Skills to Sit.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE3 = 0xa1,
+/*20031028 to latest
+스킬레벨이 부족합니다. 채팅방만들기 불능.
+You haven't learned enough Basic Skills to create a chat room.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE4 = 0xa2,
+/*20031028 to latest
+스킬레벨이 부족합니다. 파티만들기 불능
+You haven't learned enough Basic Skills to Party.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5 = 0xa3,
+/*20031028 to latest
+스킬레벨이 부족합니다. 외치기 불능
+You haven't learned enough skills to Shout.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE6 = 0xa4,
+/*20031028 to latest
+스킬레벨이 부족합니다. pk 불능
+You haven't learned enough skills for Pking.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE7 = 0xa5,
+/*20031028 to latest
+사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY = 0xa6,
+/*20031028 to latest
+아이템 상점
+Item Shop
+*/
+ MSG_ITEM_STORE = 0xa7,
+/*20031028 to latest
+팔고자하는 품목
+Selling Items
+*/
+ MSG_ITEMS_FOR_SELL = 0xa8,
+/*20031028 to latest
+보관아이템
+Storage
+*/
+ MSG_ITEMS_THAT_IS_STORED = 0xa9,
+/*20031028 to latest
+ 장비가 장착 되었습니다.
+ is put on.
+*/
+ MSG_ITEM_IS_EQUIPED = 0xaa,
+/*20031028 to latest
+ 장비가 해제 되었습니다.
+ is taken off.
+*/
+ MSG_ITEM_IS_REMOVED = 0xab,
+/*20031028 to latest
+귓말리스트에 이름넣기
+To add names on the Whispering List
+*/
+ MSG_ADD_TO_WHISPER_CHAR_LIST = 0xac,
+/*20031028 to latest
+스크린샷 찍는법 : [Print Screen]키나 [Scroll Lock]키를 누르면 됩니다.
+How to Take Screen Shots: Press [Print Screen] or [Scroll Lock]
+*/
+ MSG_EXPLAIN_TIP12 = 0xad,
+/*20031028 to latest
+오늘의 팁
+Tip of the Day
+*/
+ MSG_TIPOFTHEDAY = 0xae,
+/*20031028 to latest
+^3850a0알고 계셨습니까... ^000000 //^709fed
+^3850a0Did you know...?^709fed
+*/
+ MSG_DIDYOUKNOW = 0xaf,
+/*20031028 to latest
+시작할때 열기
+Display at startup
+*/
+ MSG_SHOWTIPSATSTARTUP = 0xb0,
+/*20031028 to latest
+/tip : 오늘의팁 열기
+/tip: Opens ''Tip of the Day''
+*/
+ MSG_EXPLAIN_OPENTIP = 0xb1,
+/*20031028 to latest
+현재 접속자 %d명
+There are %d Players Currently Connected.
+*/
+ MSG_NUMPEOPLE = 0xb2,
+/*20031028 to latest
+(%s)님이 입장 하였습니다.
+(%s) has entered.
+*/
+ MSG_USERGETINTHEROOM = 0xb3,
+/*20031028 to latest
+(%s)님이 퇴장 하였습니다.
+(%s) has left.
+*/
+ MSG_USERGETOUTOFTHEROOM = 0xb4,
+/*20031028 to latest
+(%s)님이 강제 퇴장 되었습니다.
+(%s) was kicked out.
+*/
+ MSG_USERGETOUTOFTHEROOMBYFORCE = 0xb5,
+/*20031028 to latest
+ %d 개
+%d ea.
+*/
+ MSG_EA = 0xb6,
+/*20031028 to latest
+%s : %d 개
+%s: %d ea.
+*/
+ MSG_EA2 = 0xb7,
+/*20031028 to latest
+%s %s : %d 개
+%s %s: %d
+*/
+ MSG_EA3 = 0xb8,
+/*20031028 to latest
+팔 수 있는 품목
+Available Items to sell
+*/
+ MSG_ITEMSYOUCANSELL = 0xb9,
+/*20031028 to latest
+상점에서 파는 품목
+Shop Items
+*/
+ MSG_SHOPITEMS = 0xba,
+/*20031028 to latest
+알 수 없는곳
+Unknown Area
+*/
+ MSG_NOWHERE = 0xbb,
+/*20031028 to latest
+서버와 언어가 맞지 않습니다.
+Your Client language doesn't match the Server language.
+*/
+ MSG_CLIENTTYPEMISMATCH = 0xbc,
+/*20031028 to latest
+아이템을 버릴려면 장비창을 닫으세요.
+Please move your equipment to the inventory. And close the equipment window.
+*/
+ MSG_CLOSEEQUIPWND = 0xbd,
+/*20031028 to latest
+영어만 됩니다.
+This server provides English Text Characters Only.
+*/
+ MSG_ENGLISHONLY = 0xbe,
+/*20031028 to latest
+지금은 지원되지 않습니다.
+This is not implemented yet.
+*/
+ MSG_NOTSUPPORTEDYET = 0xbf,
+/*20031028 to latest
+귓말 리스트가 없습니다.
+No Whisper List.
+*/
+ MSG_NOWHISPERLIST = 0xc0,
+/*20031028 to latest
+ 에게 귓말거부상태로됨
+: Whispering Blocked.
+*/
+ MSG_WHISPERIGNORESUCCESS = 0xc1,
+/*20031028 to latest
+ 에게 귓말거부 요청실패함
+: Whispering Block has failed.
+*/
+ MSG_WHISPERIGNOREFAILED1 = 0xc2,
+/*20031028 to latest
+ 에게 귓말거부 요청실패함 (인원초과)
+: Whispering Block has failed. Block List is full.
+*/
+ MSG_WHISPERIGNOREFAILED2 = 0xc3,
+/*20031028 to latest
+ 에게 귓말가능상태로됨
+: Whispering accepted.
+*/
+ MSG_WHISPERNOIGNORESUCCESS = 0xc4,
+/*20031028 to latest
+ 에게 귓말가능 요청실패함
+: Command has failed.
+*/
+ MSG_WHISPERNOIGNOREFAILED1 = 0xc5,
+/*20031028 to latest
+ 에게 귓말가능 요청실패함 (인원초과)
+: Command has failed. Block List is full.
+*/
+ MSG_WHISPERNOIGNOREFAILED2 = 0xc6,
+/*20031028 to latest
+이름의 처음과 마지막에는 공백문자를 사용할 수 없습니다.
+You cannot put a space at the beginning or end of a name.
+*/
+ MSG_NO_SPACE_IN_NAME = 0xc7,
+/*20031028 to latest
+비공개
+Private
+*/
+ MSG_ROOM_PRIVATE2 = 0xc8,
+/*20031028 to latest
+공개
+Public
+*/
+ MSG_ROOM_PUBLIC2 = 0xc9,
+/*20031028 to latest
+SP가 부족합니다.
+Not Enough SP
+*/
+ MSG_USESKILL_FAIL_SP_INSUFFICIENT = 0xca,
+/*20031028 to latest
+HP가 부족합니다.
+Not Enough HP
+*/
+ MSG_USESKILL_FAIL_HP_INSUFFICIENT = 0xcb,
+/*20031028 to latest
+스킬사용 실패.
+Skill has failed.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE8 = 0xcc,
+/*20031028 to latest
+훔치기 실패.
+Steal has failed.
+*/
+ MSG_FAIL_STEAL = 0xcd,
+/*20031028 to latest
+교환창
+Trade
+*/
+ MSG_EXCHANGE = 0xce,
+/*20031028 to latest
+독걸기 실패.
+Envenom skill has failed.
+*/
+ MSG_FAIL_POISON = 0xcf,
+/*20031028 to latest
+이 아이디로는 이 서버에 접속할 수 없습니다.
+You cannot use this ID on this server.
+*/
+ MSG_ID_MISMATCH = 0xd0,
+/*20031028 to latest
+스피드가 향상되었습니다.
+Your Speed has increased.
+*/
+ MSG_SPEEDUP = 0xd1,
+/*20031028 to latest
+스피드가 감소되었습니다.
+Your Speed has decreased.
+*/
+ MSG_SPEEDDOWN = 0xd2,
+/*20031028 to latest
+/기억 : 워프할 장소 기억(워프 스킬이 있는경우)
+/memo: To memorize a place as Warp Point (If you are an Acolyte Class character)
+*/
+ MSG_EXPLAIN_TIP13 = 0xd3,
+/*20031028 to latest
+임의의 위치
+Random Area
+*/
+ MSG_RANDOM_POS = 0xd4,
+/*20031028 to latest
+워프 할 위치를 선택하세요.
+Select an Area to Warp
+*/
+ MSG_SELECTWHERETOWARP = 0xd5,
+/*20031028 to latest
+스킬레벨이 부족합니다.
+Skill Level is not high enough
+*/
+ MSG_NOTENOUGHSKILLLEVEL = 0xd6,
+/*20031028 to latest
+저장된 워프할 장소가 없습니다.
+There are no memorized locations (Memo Points).
+*/
+ MSG_NO_STORED_PLACE_TO_WARP = 0xd7,
+/*20031028 to latest
+워프 관련 스킬이 없습니다.
+You haven't learned Warp.
+*/
+ MSG_NOWARPSKILL = 0xd8,
+/*20031028 to latest
+워프 장소로 저장됨.
+Saved location as a Memo Point for Warp Skill.
+*/
+ MSG_WARPPOINTSTORED = 0xd9,
+/*20031028 to latest
+취소
+Cancel
+*/
+ MSG_CANCEL = 0xda,
+/*20031028 to latest
+스킬 사용후 시간이 충분히 지나지 않았습니다.
+There is a Delay after using a Skill.
+*/
+ MSG_SKILLINTERVAL = 0xdb,
+/*20031028 to latest
+한번에 가질 수 있는 아이템 종류수를 초과하여 아이템을 가질 수 없습니다.
+You can't have this item because you will exceed the weight limit.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_COUNT = 0xdc,
+/*20031028 to latest
+아이템 최대 종류수를 초과 하였습니다.
+Out of the maximum capacity
+*/
+ MSG_INSUFFICIENT_OVER_COUNT = 0xdd,
+/*20031028 to latest
+수레아이템
+Cart Items
+*/
+ MSG_MERCHANTITEM = 0xde,
+/*20031028 to latest
+수레 벗기
+Take off Cart
+*/
+ MSG_CARTOFF = 0xdf,
+/*20031028 to latest
+노점 개설
+Opening a stall
+*/
+ MSG_MERCHANTSHOPMAKER = 0xe0,
+/*20031028 to 20041207
+노점이름를 입력하세요.
+20041213 to latest
+노점이름을 입력하세요.
+Please Name your Shop.
+*/
+ MSG_ENTER_SHOP_TITLE = 0xe1,
+/*20031028 to latest
+나의 노점
+My Shop
+*/
+ MSG_ITEM_MY_STORE = 0xe2,
+/*20031028 to latest
+상인 아이템 상점
+Merchant Shop
+*/
+ MSG_ITEM_MERCHANT_STORE = 0xe3,
+/*20031028 to latest
+상인에게 사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY_FROM_MERCHANT = 0xe4,
+/*20031028 to 20130508
+%s 사기 실패 %s
+20130515 to latest
+%s 구입 실패 %s
+%s Purchase Failed %s
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT = 0xe5,
+/*20031028 to latest
+재고 부족.
+Out of Stock
+*/
+ MSG_INSUFFICIENT_STOCK = 0xe6,
+/*20031028 to latest
+%s %d 개 팔림.
+%s %d sold.
+*/
+ MSG_ITEM_IS_SOLD = 0xe7,
+/*20031028 to latest
+노점에서 팔 수 있는 아이템
+Available Items for Vending
+*/
+ MSG_MERCHANTMIRRORITEM = 0xe8,
+/*20031028 to 20111012
+돈이 부족해서 스킬을 쓸 수 없습니다.
+20111017 to latest
+제니가 부족해서 스킬을 사용 할 수 없습니다.
+Skill has failed because you do not have enough zeny.
+*/
+ MSG_SKILL_FAIL_MONEY = 0xe9,
+/*20031028 to latest
+사용할 대상을 선택하세요
+Select a Target.
+*/
+ MSG_SELECTTARGET = 0xea,
+/*20031028 to latest
+/pk on : pk On /pk off : pk Off
+/pk on: Turns PK On. /pk off: Turns PK Off.
+*/
+ MSG_EXPLAIN_TIP14 = 0xeb,
+/*20031028 to latest
+노점
+Shop
+*/
+ MSG_STREETSHOP = 0xec,
+/*20031028 to latest
+수레 아이템 [Alt+W]
+Cart Items [Alt+W]
+*/
+ MSG_OPENCARTWINDOW = 0xed,
+/*20031028 to latest
+기본정보
+Basic Information
+*/
+ MSG_BASICINFOWND = 0xee,
+/*20031028 to 20191204
+이무기로는 이스킬을 사용할수 없습니다.
+The skill cannot be used with this weapon.
+20191211 to latest
+현재 무기로는 스킬을 사용할 수 없습니다.
+*/
+ MSG_USESKILL_FAIL_NOT_SUITABLE_WEAPON = 0xef,
+/*20031028 to latest
+%s 사기 실패 재고 부족 현재 재고 %d 개.
+Buying %s has been failed. Out of Stock. Current Stock %d.
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT_NO_STOCK = 0xf0,
+/*20031028 to latest
+서버와 동기화가 틀려 연결이 끊어졌습니다.
+You've been disconnected due to a time gap between you and the server.
+*/
+ MSG_SPEEDHACK = 0xf1,
+/*20031028 to latest
+화살을 장착하세요
+Please equip the proper ammunition first.
+*/
+ MSG_ERR_ATTACK_ARROW = 0xf2,
+/*20031028 to latest
+중량과다로 공격이나 스킬을 사용할 수 없습니다.
+You can't attack or use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_ATTACK_WEIGHT = 0xf3,
+/*20031028 to latest
+중량과다로 스킬을 사용할 수 없습니다.
+You can't use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_SKILL_WEIGHT = 0xf4,
+/*20031028 to latest
+화살이 장착되었습니다.
+Ammunition has been equipped.
+*/
+ MSG_MSG_ARROW_EQUIPMENT_SUCCESS = 0xf5,
+/*20031028 to latest
+레드젬스톤이 필요합니다.
+Red Gemstone required.
+*/
+ MSG_NEED_REDJAMSTONE = 0xf6,
+/*20031028 to latest
+블루젬스톤이 필요합니다.
+Blue Gemstone required.
+*/
+ MSG_NEED_BLUEJAMSTONE = 0xf7,
+/*20031028 to latest
+힘 파라메터
+Strength
+*/
+ MSG_DESC_STR = 0xf8,
+/*20031028 to latest
+민첩성 파라메터
+Agility
+*/
+ MSG_DESC_AGI = 0xf9,
+/*20031028 to latest
+체력 파라메터
+Vitality
+*/
+ MSG_DESC_VIT = 0xfa,
+/*20031028 to latest
+지력 파라메터
+Intelligence
+*/
+ MSG_DESC_INT = 0xfb,
+/*20031028 to latest
+손재주 파라메터
+Dexterity
+*/
+ MSG_DESC_DEX = 0xfc,
+/*20031028 to latest
+운 파라메터
+Luck
+*/
+ MSG_DESC_LUK = 0xfd,
+/*20031028 to latest
+공격력
+Hit Point
+*/
+ MSG_DESC_ATK = 0xfe,
+/*20031028 to latest
+방어력
+Defence Rate
+*/
+ MSG_DESC_DEF = 0xff,
+/*20031028 to latest
+명중률
+Accuracy
+*/
+ MSG_DESC_HIT = 0x100,
+/*20031028 to latest
+필살공격률
+Critical Attack
+*/
+ MSG_DESC_CRI = 0x101,
+/*20031028 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_DESC_GUILD = 0x102,
+/*20031028 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_DESC_POINT = 0x103,
+/*20031028 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_DESC_MATK = 0x104,
+/*20031028 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_DESC_MDEF = 0x105,
+/*20031028 to latest
+회피율
+Dodge
+*/
+ MSG_DESC_FLEE = 0x106,
+/*20031028 to latest
+공격스피드
+Attack Speed
+*/
+ MSG_DESC_ASPD = 0x107,
+/*20031028 to latest
+지역당 수용인원 초과로 접속할 수 없습니다.
+Server is jammed due to over population. Please try again shortly.
+*/
+ MSG_PC_OVERFLOW = 0x108,
+/*20031028 to latest
+옵션
+Option
+*/
+ MSG_OPTIONWND = 0x109,
+/*20031028 to latest
+E-MAIL 인증이 되지않았거나 블럭된 계정입니다.
+Account ID blocked by the Game Master Team.
+*/
+ MSG_ID_EMAIL_CONFIRM_NEEDED = 0x10a,
+/*20031028 to latest
+비밀번호가 틀립니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_LOGIN_PASSWORD = 0x10b,
+/*20031028 to latest
+머리모양 선택
+Choose Hairstyle
+*/
+ MSG_SELECT_HAIR_STYLE = 0x10c,
+/*20031028 to latest
+공격력
+Hit Point
+*/
+ MSG_ATK = 0x10d,
+/*20031028 to latest
+방어력
+Defence Rate
+*/
+ MSG_DEF = 0x10e,
+/*20031028 to latest
+공격스냅 On
+Attack Snap On
+*/
+ MSG_ATTACK_SNAP_ON = 0x10f,
+/*20031028 to latest
+공격스냅 Off
+Attack Snap Off
+*/
+ MSG_ATTACK_SNAP_OFF = 0x110,
+/*20031028 to latest
+스킬스냅 On
+Skill Snap On
+*/
+ MSG_SKILL_SNAP_ON = 0x111,
+/*20031028 to latest
+스킬스냅 Off
+Skill Snap Off
+*/
+ MSG_SKILL_SNAP_OFF = 0x112,
+/*20031028 to latest
+/스냅 or /snap: 몬스터 공격시 스냅 On Off /스킬스냅 or /skillsnap: 스킬로 몬스터 공격시 스냅 On Off /아이템스냅 or /itemsnap: 아이템 주울때 스냅 On Off
+/snap: Turns snap On | Off for fights, /skillsnap: Turns snap On | Off for skills. /itemsnap: Turns snap On | Off for items on the grounds.
+*/
+ MSG_EXPLAIN_SNAP = 0x113,
+/*20031028 to latest
+아이템스냅 On
+Item Snap On
+*/
+ MSG_ITEM_SNAP_ON = 0x114,
+/*20031028 to latest
+아이템스냅 Off
+Item Snap Off
+*/
+ MSG_ITEM_SNAP_OFF = 0x115,
+/*20031028 to latest
+스냅
+Snap
+*/
+ MSG_SNAP = 0x116,
+/*20031028 to latest
+한가지 아이템을 3만개 이상 가질수 없습니다.
+You cannot carry more than 30,000 of one kind of item.
+*/
+ MSG_CANT_GET_ITEM_OVERCOUNT_ONEITEM = 0x117,
+/*20031028 to latest
+레벨 30이상의 캐릭터는 삭제할 수 없습니다. 삭제를 원하시면 관계자에게 문의 하세요.
+You cannot delete a Character with a level greater than 30. If you want to delete the character please contact a Game Master.
+*/
+ MSG_CANT_DELETE_CHARACTER_OVER_30_LEVEL = 0x118,
+/*20031028 to 20091208
+이이템 교환중에는 아이템을 사고 팔 수 없습니다.
+20091215 to latest
+아이템 교환중에는 아이템을 사고 팔 수 없습니다.
+You cannot use an NPC shop while in a trade.
+*/
+ MSG_FAIL_BUY_ITEM_ITEM_EXCHANGING = 0x119,
+/*20031028 to latest
+상점명
+Shop Name
+*/
+ MSG_STALL_NAME = 0x11a,
+/*20031028 to latest
+스킬목록
+Skill Tree
+*/
+ MSG_SKILLLIST = 0x11b,
+/*20031028 to latest
+스킬포인트 : %d
+Skill Point: %d
+*/
+ MSG_SKILLPOINT = 0x11c,
+/*20031028 to latest
+스킬사용 실패
+Skill has failed.
+*/
+ MSG_USESKILL_FAIL = 0x11d,
+/*20031028 to latest
+패시브
+Passive
+*/
+ MSG_PASSIVE = 0x11e,
+/*20031028 to latest
+각자 취득
+Individual
+*/
+ MSG_EXPDIV1 = 0x11f,
+/*20031028 to latest
+균등하게 분배
+Shared
+*/
+ MSG_EXPDIV2 = 0x120,
+/*20031028 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMCOLLECT1 = 0x121,
+/*20031028 to latest
+파티 전체 공유
+Party Share
+*/
+ MSG_ITEMCOLLECT2 = 0x122,
+/*20031028 to latest
+파티 설정
+Party Setup
+*/
+ MSG_PARTYSETTING = 0x123,
+/*20031028 to latest
+경험치 분배방식
+How to share EXP
+*/
+ MSG_HOWEXPDIV = 0x124,
+/*20031028 to latest
+아이템 수집방식
+How to share Items
+*/
+ MSG_HOWITEMCOLLECT = 0x125,
+/*20031028 to latest
+파티 리더만 설정할 수 있습니다.
+Only the Party Leader can change this setting.
+*/
+ MSG_ONLY_PARTYMASTER = 0x126,
+/*20031028 to latest
+아이템 갯수 안물어보기
+Toggle Item Amount.
+*/
+ MSG_NOQUESTION_ITEMCOUNT = 0x127,
+/*20031028 to latest
+^ff0000%d^000000 초 후에 캐릭터가 지워집니다. 취소 하려면 취소 버튼을 누르세요.
+Character will be deleted after ^ff0000%d^000000 seconds. Press Cancel to quit.
+*/
+ MSG_CHARARATER_DELETE_COUNT = 0x128,
+/*20031028 to latest
+교환할 수 있는 최대 아이템 갯수는 10가지 입니다.
+You cannot trade more than 10 types of items per trade.
+*/
+ MSG_MAXEXCHANGE_IS_10_KIND = 0x129,
+/*20031028 to latest
+이서버를 이용할 수 없는 나이입니다.
+You are underaged.
+*/
+ MSG_LIMIT_AGE = 0x12a,
+/*20031028 to latest
+이메일 주소를 입력하세요.
+Please enter the deletion password.
+*/
+ MSG_ENTER_EMAIL = 0x12b,
+/*20031028 to latest
+이메일 주소 입력하기
+E-mail Address (Case Sensitive).
+*/
+ MSG_ENTER_EMAIL_TOOLTIP = 0x12c,
+/*20031028 to latest
+이메일 주소가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect e-mail address.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_EMAIL = 0x12d,
+/*20031028 to 20070703
+주민등록번호 뒷자리를 입력하세요.
+20070618 to 20070622
+비밀번호를 한 번 더 입력해 주시기 바랍니다.
+20070704 to latest
+계정 비밀번호를 입력하세요.
+Enter Second Serial Cord of your Social Security number.
+*/
+ MSG_ENTER_PEOPLE_REG_NUMBER = 0x12e,
+/*20031028 to 20070703
+주민등록번호 뒷자리가 틀려서 캐릭터가 삭제 되지 않았습니다.
+20070618 to 20070622
+비밀번호가 맞지 않아 캐릭터가 삭제 되지 않았습니다.
+20070704 to latest
+비밀번호가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect SSN.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_PEOPLE_REG_NUMBER = 0x12f,
+/*20031028 to latest
+한번에 15가지 이상의 아이템을 팔 수 없습니다.
+You can't sell more than 15 types of Items at one time.
+*/
+ MSG_CANT_SELL_OVER_15 = 0x130,
+/*20031028 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_UNDER_AGE = 0x131,
+/*20031028 to latest
+무게가 50 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+HP/SP will not be restored when your carried weight is over 50% of the Weight Limit.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT = 0x132,
+/*20031028 to latest
+무게가 90 퍼센트 이상일때는 공격과 스킬을 사용할 수 없습니다.
+You can't use Skills or Attack while your carried weight is over 90% of your Weight Limit.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT = 0x133,
+/*20031028 to latest
+HP SP가 자연적으로 회복이 가능한 상태가 되었습니다.
+Your HP/SP are now being restored naturally.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT_RELEASED = 0x134,
+/*20031028 to latest
+공격과 스킬이 가능한 상태가 되었습니다.
+Attack and Skills are now available.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT_RELEASED = 0x135,
+/*20031028 to latest
+서버 점검중입니다.
+Your Game's Exe File is not the latest version.
+*/
+ MSG_INVALID_VERSION = 0x136,
+/*20031028 to latest
+아이템이 모두 팔렸습니다.
+Items are sold out.
+*/
+ MSG_ITEM_IS_SOLD_OUT = 0x137,
+/*20031028 to latest
+채팅내용 파일로 저장하기
+Save Chat as Text File
+*/
+ MSG_WRITE_CHAT_TO_FILE = 0x138,
+/*20031028 to latest
+/갈무리 or /savechat : 채팅 내용 파일로 저장하기.
+/savechat: Save a Chat Log
+*/
+ MSG_EXPLAIN_SAVE_CHAT = 0x139,
+/*20031028 to latest
+계정 만들기
+Register
+*/
+ MSG_MAKEACCOUNT = 0x13a,
+/*20031028 to latest
+수신거부하기
+Reject Whispering
+*/
+ MSG_REQ_EX_LIST = 0x13b,
+/*20031028 to latest
+수신거부해제하기
+Allow Whispering
+*/
+ MSG_REQ_IN = 0x13c,
+/*20031028 to latest
+미스표시 On
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_ON = 0x13d,
+/*20031028 to latest
+미스표시 Off
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_OFF = 0x13e,
+/*20031028 to latest
+카메라고정 On
+Camera Zooming On
+*/
+ MSG_FIXED_CAMERA_ON = 0x13f,
+/*20031028 to latest
+카메라고정 Off
+Camera Zooming Off
+*/
+ MSG_FIXED_CAMERA_OFF = 0x140,
+/*20031028 to latest
+/camera : 플레이어에게 카메라고정 On Off /miss : 미스이펙트 On Off
+/camera: Camera Zooming On or Off. /miss: Toggle ''Miss'' display
+*/
+ MSG_EXPLAIN_CAMERA_MISS = 0x141,
+/*20031028 to latest
+스킬정보보기
+View Skill Info
+*/
+ MSG_SEE_INFORMATION_OF_SKILL = 0x142,
+/*20031028 to latest
+스킬이름바꾸기
+Change Skill
+*/
+ MSG_CHANGE_SKILL_NAME = 0x143,
+/*20031028 to latest
+스프라이트 해상도
+Sprite Resolution
+*/
+ MSG_SPRITE_RESOLUTION = 0x144,
+/*20031028 to latest
+텍스쳐 해상도
+Texture Resolution
+*/
+ MSG_TEXTURE_RESOLUTION = 0x145,
+/*20031028 to latest
+디테일 조정
+Arrange Detail
+*/
+ MSG_DETAILLEVELWND = 0x146,
+/*20031028 to latest
+%s Zeny 획득
+You got %s Zeny
+*/
+ MSG_GET_ZENY = 0x147,
+/*20031028 to latest
+길드명
+Guild Name
+*/
+ MSG_GUILDNAME = 0x148,
+/*20031028 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILDLEVEL = 0x149,
+/*20031028 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_GUILD_MASTER_NAME = 0x14a,
+/*20031028 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_NUM_MEMBER = 0x14b,
+/*20031028 to latest
+조합원 평균레벨
+Avg.lvl of Guildsmen
+*/
+ MSG_GUILD_AVG_MEMBER_LEVEL = 0x14c,
+/*20031028 to latest
+관리영지
+Castles Owned
+*/
+ MSG_GUILD_MANAGE_LAND = 0x14d,
+/*20031028 to latest
+성향
+Tendency
+*/
+ MSG_GUILD_FAIR = 0x14e,
+/*20031028 to latest
+경험치
+EXP
+*/
+ MSG_GUILD_EXP = 0x14f,
+/*20031028 to latest
+길드엠블렘
+Emblem
+*/
+ MSG_GUILD_EMBLEM = 0x150,
+/*20031028 to latest
+길드상납포인트
+Tax Point
+*/
+ MSG_GUILD_POINT = 0x151,
+/*20031028 to latest
+동맹길드
+Alliances
+*/
+ MSG_ALLY_GUILD = 0x152,
+/*20031028 to latest
+적대길드
+Antagonists
+*/
+ MSG_HOSTILITY_GUILD = 0x153,
+/*20031028 to latest
+길드정보
+Guild Info
+*/
+ MSG_GUILDINFOMANAGE = 0x154,
+/*20031028 to latest
+조합원정보
+Guildsmen Info
+*/
+ MSG_GUILDMEMBERMANAGE = 0x155,
+/*20031028 to latest
+직위설정
+Position
+*/
+ MSG_GUILDPOSITIONMANAGE = 0x156,
+/*20031028 to latest
+길드스킬
+Guild Skill
+*/
+ MSG_GUILDSKILL = 0x157,
+/*20031028 to latest
+추방자 리스트
+Expel History
+*/
+ MSG_GUILDBANISHEDMEMBER = 0x158,
+/*20031028 to latest
+공지사항
+Guild Notice
+*/
+ MSG_GUILDNOTICE = 0x159,
+/*20031028 to latest
+전체길드 리스트
+Entire Guild List
+*/
+ MSG_GUILDTOTALINFO = 0x15a,
+/*20031028 to latest
+귓말 리스트
+Whispering List
+*/
+ MSG_WHISPERLISTWND = 0x15b,
+/*20031028 to latest
+귓말창 열기
+Open Whispering Window
+*/
+ MSG_OPENWHISPERLISTWND = 0x15c,
+/*20031028 to latest
+귓말 리스트 창 여는법 : [Alt] + [H] 를 누르면 귓말 리스트 창이 열립니다.
+How to Open Whispering List: Press [Alt] + [H]
+*/
+ MSG_EXPLAIN_WHISPER_LIST_WND = 0x15d,
+/*20031028 to latest
+자동으로 귓말창 열기
+Open Whispering List Automatically
+*/
+ MSG_AUTOOPENWHISPERLISTWND = 0x15e,
+/*20031028 to latest
+지우기
+Delete
+*/
+ MSG_DELETE = 0x15f,
+/*20031028 to latest
+다음부터 열리지 않음
+Close since next
+*/
+ MSG_DONTOPEN = 0x160,
+/*20031028 to latest
+마지막으로 접속한 시간
+Last Log-in Time
+*/
+ MSG_LAST_LOGIN_TIME = 0x161,
+/*20031028 to latest
+마지막으로 접속한 IP
+Last Log-in IP
+*/
+ MSG_LAST_LOGIN_IP = 0x162,
+/*20031028 to latest
+친구 설정
+Friend Setup
+*/
+ MSG_FRIEND_SETTING = 0x163,
+/*20031028 to latest
+정말 지우시겠습니까?
+Are you sure that you want to delete?
+*/
+ MSG_DO_YOU_REALLY_WANT_DELETE = 0x164,
+/*20031028 to latest
+정말 탈퇴하시겠습니까?
+Are you sure that you want to leave?
+*/
+ MSG_DO_YOU_REALLY_WANT_LEAVE = 0x165,
+/*20031028 to latest
+친구로 등록하기
+Register as a Friend
+*/
+ MSG_ADD_TO_FRIEND_CHAR_LIST = 0x166,
+/*20031028 to latest
+친구일때 자동으로 1:1창 열기
+Open 1:1 Chat between Friends
+*/
+ MSG_AUTOOPENWHISPERLISTWND_FRIEND = 0x167,
+/*20031028 to latest
+1:1창 열기
+Open 1:1 Chat
+*/
+ MSG_OPEN_1ON1_WINDOW = 0x168,
+/*20031028 to latest
+친구가 아닐때 자동으로 1:1창 열기
+Open 1:1 Chat between Strangers
+*/
+ MSG_AUTOOPEN_1ON1_WINDOW = 0x169,
+/*20031028 to latest
+1:1창 열릴때 소리로 알림
+Alarm when you recieve a 1:1 Chat
+*/
+ MSG_WHISPER_OPEN_SOUND = 0x16a,
+/*20031028 to latest
+정말 제명시키시겠습니까?
+Are you sure that you want to expel?
+*/
+ MSG_DO_YOU_REALLY_WANT_EXPEL = 0x16b,
+/*20031028 to latest
+%s 님이 길드를 탈퇴했습니다.
+%s has withdrawn from the guild.
+*/
+ MSG_USER_LEFT_GUILD = 0x16c,
+/*20031028 to latest
+탈퇴사유 : %s
+Secession Reason: %s
+*/
+ MSG_REASON_LEAVE_GUILD = 0x16d,
+/*20031028 to 20120202
+길드 해체 실패
+20120207 to latest
+길드명이 일치하지 않습니다
+You have failed to disband the guild.
+*/
+ MSG_DISORGANIZE_GUILD_FAILURE = 0x16e,
+/*20031028 to latest
+길드해체사유 : %s
+Disband Reason: %s
+*/
+ MSG_DISORGANIZATION_REASON = 0x16f,
+/*20031028 to latest
+해당 계정은 삭제된 아이디 입니다.
+This ID has been removed.
+*/
+ MSG_DELETED_ACCOUNT = 0x170,
+/*20031028 to latest
+판매가 :
+Price:
+*/
+ MSG_SELLPRICE = 0x171,
+/*20031028 to latest
+%s 님이 길드에서 추방되었습니다.
+%s has been expelled from our guild.
+*/
+ MSG_BAN_GUILD = 0x172,
+/*20031028 to latest
+추방사유 : %s
+Expulsion Reason: %s
+*/
+ MSG_REASON_BAN_GUILD = 0x173,
+/*20031028 to latest
+아이템을 착용할 수 없습니다.
+You can't put this item on.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM = 0x174,
+/*20031028 to latest
+파티설정을 변경할 수 없습니다.
+You can't modify Party Setup.
+*/
+ MSG_PARTYSETTING_CHANGE_IMPOSSIBLE = 0x175,
+/*20031028 to latest
+길드가 만들어 졌습니다.
+Guild has been Created.
+*/
+ MSG_GUILD_MAKE_SUCCESS = 0x176,
+/*20031028 to latest
+이미 길드에 속해있습니다.
+You are already in a Guild.
+*/
+ MSG_GUILD_MAKE_ALREADY_MEMBER = 0x177,
+/*20031028 to latest
+같은이름의 길드가 존재합니다.
+That Guild Name already exists.
+*/
+ MSG_GUILD_MAKE_GUILD_EXIST = 0x178,
+/*20031028 to latest
+ 길드에서 초청 메시지가 왔습니다. 가입하겠습니까?
+ Guild has sent you an invitation. Would you like to join this Guild?
+*/
+ MSG_SUGGEST_JOIN_GUILD = 0x179,
+/*20031028 to latest
+다른길드에 가입되어 있습니다.
+He/She is already in a Guild.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_GUILD = 0x17a,
+/*20031028 to latest
+길드가입을 거절 했습니다.
+Offer Rejected
+*/
+ MSG_CHARACTER_REJECT_JOIN_GUILD = 0x17b,
+/*20031028 to latest
+길드가입을 수락했습니다.
+Offer Accepted
+*/
+ MSG_CHARACTER_ACCEPT_JOIN_GUILD = 0x17c,
+/*20031028 to latest
+길드정원을 초과했습니다.
+Your Guild is Full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_GUILD = 0x17d,
+/*20031028 to latest
+(%s)님 길드에 가입요청
+Send (%s) a Guild invitation
+*/
+ MSG_REQ_JOIN_GUILD = 0x17e,
+/*20031028 to latest
+스킬 레벨이 모자라서 매너포인트를 줄 수 없습니다.
+You haven't learned enough skills for aligning.
+*/
+ MSG_NOT_ENOUGH_FOR_MANNER_POINT = 0x17f,
+/*20031028 to latest
+매너 포인트 주기 성공
+Aligning completed.
+*/
+ MSG_GIVING_MANNER_POINT_SUCCESS = 0x180,
+/*20031028 to latest
+오늘 이미 사용했습니다.
+You already spent your point for today.
+*/
+ MSG_YOU_USE_TODAY_ALREADY = 0x181,
+/*20031028 to latest
+이캐릭터에게 지급한지 한달이 지나지 않았습니다.
+Hasn't been a month yet since you aligned this person.
+*/
+ MSG_ONE_MONTH_NOT_PASSED = 0x182,
+/*20031028 to latest
+%s 님으로부터 플러스 매너 포인트를 받았습니다.
+Remember, Spamming isn't nice.
+*/
+ MSG_RECEIVE_PLUS_MANNER_POINT = 0x183,
+/*20031028 to latest
+%s 님으로부터 마이너스 매너 포인트를 받았습니다.
+Please refrain from ill-mannered conduct, thank you.
+*/
+ MSG_RECEIVE_MINUS_MANNER_POINT = 0x184,
+/*20031028 to latest
+채팅 금지 시간 줄이기(풀기)
+Align with a Good Point
+*/
+ MSG_GIVE_PLUS_MANNER_POINT = 0x185,
+/*20031028 to latest
+채팅 금지 시간 늘이기(걸기)
+Align with a Bad Point
+*/
+ MSG_GIVE_MINUS_MANNER_POINT = 0x186,
+/*20031028 to latest
+(%s)님과의 거래요청
+Request a deal with (%s)
+*/
+ MSG_REQ_DEAL_WITH2 = 0x187,
+/*20031028 to latest
+(%s)님 파티에 가입요청
+Ask (%s) to join your party
+*/
+ MSG_REQ_JOIN_PARTY2 = 0x188,
+/*20031028 to latest
+ 길드에서 동맹요청 메시지가 왔습니다. 동맹하겠습니까?
+ Guild is asking you to agree to an Alliance with them. Do you accept?
+*/
+ MSG_SUGGEST_ALLY_GUILD = 0x189,
+/*20031028 to latest
+이미 동맹되어 있습니다.
+This Guild is already your Ally.
+*/
+ MSG_REQALLYGUILD_ALREADY_ALLIED = 0x18a,
+/*20031028 to latest
+동맹을 거절 했습니다.
+You reject the offer
+*/
+ MSG_REQALLYGUILD_REJECT = 0x18b,
+/*20031028 to latest
+동맹을 수락 했습니다.
+You accept the offer
+*/
+ MSG_REQALLYGUILD_ACCEPT = 0x18c,
+/*20031028 to latest
+상대길드의 동맹길드의 수가 초과 되었습니다.
+They have too many Alliances.
+*/
+ MSG_REQALLYGUILD_OVERSIZE = 0x18d,
+/*20031028 to latest
+길드의 동맹길드의 수가 초과 되었습니다.
+You have too many Alliances.
+*/
+ MSG_REQALLYMYGUILD_OVERSIZE = 0x18e,
+/*20031028 to latest
+길드 동맹 요청
+Set this guild as an Alliance
+*/
+ MSG_REQ_ALLY_GUILD = 0x18f,
+/*20031028 to latest
+길드가 성공적으로 해체 되었습니다.
+Guild was successfully disbanded.
+*/
+ MSG_DISORGANIZE_GUILD_SUCCESS = 0x190,
+/*20031028 to latest
+주민등록번호가 틀려서 길드가 해체되지 않았습니다.
+You have failed to disband the guild due to your incorrect SSN.
+*/
+ MSG_DISORGANIZE_GUILD_INVALIDKEY = 0x191,
+/*20031028 to latest
+길드맴버가 존재해서 길드가 해체되지 않았습니다.
+You have failed to disband the guild because there are guildsmen still present.
+*/
+ MSG_DISORGANIZE_GUILD_MEMBEREXIST = 0x192,
+/*20031028 to latest
+길드 적대 요청
+Set this guild as an Antagonist
+*/
+ MSG_REQ_HOSTILE_GUILD = 0x193,
+/*20031028 to latest
+머리색깔 선택
+Choose Hair Color
+*/
+ MSG_SELECT_HAIR_COLOR = 0x194,
+/*20031028 to latest
+길드결성시 필요한 아이템이 없습니다.
+You don't have necessary item to create a Guild.
+*/
+ MSG_GUILD_MAKE_GUILD_NONE_ITEM = 0x195,
+/*20031028 to latest
+몬스터 정보
+Monster Info
+*/
+ MSG_MONSTER_INFO_WINDOW = 0x196,
+/*20031028 to latest
+이름
+Name
+*/
+ MSG_NAME = 0x197,
+/*20031028 to latest
+레벨
+Level
+*/
+ MSG_LEVEL = 0x198,
+/*20031028 to latest
+HP
+*/
+ MSG_HP = 0x199,
+/*20031028 to latest
+크기
+Size
+*/
+ MSG_SIZE = 0x19a,
+/*20031028 to latest
+종족
+Type
+*/
+ MSG_RACETYPE = 0x19b,
+/*20031028 to latest
+MDEF
+*/
+ MSG_MDEFPOWER = 0x19c,
+/*20031028 to latest
+속성
+Attribute
+*/
+ MSG_PROPERTY = 0x19d,
+/*20031028 to latest
+無
+Neutral
+*/
+ MSG_PROPERTY_NEUTURAL = 0x19e,
+/*20031028 to latest
+水
+Water
+*/
+ MSG_PROPERTY_WATER = 0x19f,
+/*20031028 to latest
+地
+Earth
+*/
+ MSG_PROPERTY_EARTH = 0x1a0,
+/*20031028 to latest
+火
+Fire
+*/
+ MSG_PROPERTY_FIRE = 0x1a1,
+/*20031028 to latest
+風
+Wind
+*/
+ MSG_PROPERTY_WIND = 0x1a2,
+/*20031028 to latest
+毒
+Poison
+*/
+ MSG_PROPERTY_POISON = 0x1a3,
+/*20031028 to latest
+聖
+Holy
+*/
+ MSG_PROPERTY_SAINT = 0x1a4,
+/*20031028 to latest
+暗
+Shadow
+*/
+ MSG_PROPERTY_DARK = 0x1a5,
+/*20031028 to latest
+念
+Ghost
+*/
+ MSG_PROPERTY_MENTAL = 0x1a6,
+/*20031028 to latest
+死
+Undead
+*/
+ MSG_PROPERTY_UNDEAD = 0x1a7,
+/*20031028 to latest
+현재는 아이템을 만들 수 없습니다.
+You can't create items yet.
+*/
+ MSG_CANT_MAKE_ITEM = 0x1a8,
+/*20031028 to latest
+제조 목록
+Item List you can craft
+*/
+ MSG_MAKE_LIST = 0x1a9,
+/*20031028 to latest
+ 만들기
+ Create
+*/
+ MSG_MAKE_TARGET = 0x1aa,
+/*20031028 to latest
+ 에 필요한 재료:
+'s materials
+*/
+ MSG_REQUIRE_FOR_MAKE_TARGET = 0x1ab,
+/*20031028 to latest
+ 만들기 실패
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL = 0x1ac,
+/*20031028 to latest
+ 만들기 성공
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS = 0x1ad,
+/*20031028 to latest
+%s 만들기를 실패하였습니다.
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL_MSG = 0x1ae,
+/*20031028 to latest
+%s 만들기를 성공했습니다.
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS_MSG = 0x1af,
+/*20031028 to latest
+레벨이 부족합니다.
+You are not the required lvl.
+*/
+ MSG_NOT_ENOUGH_LEVEL = 0x1b0,
+/*20031028 to latest
+레벨이 너무 높습니다.
+Too high lvl for this job.
+*/
+ MSG_TOO_HIGH_LEVEL = 0x1b1,
+/*20031028 to latest
+직업이 적합하지 않습니다.
+Not the suitable job for this type of work.
+*/
+ MSG_NOT_ACCEPTABLE_JOB = 0x1b2,
+/*20031028 to latest
+토키 박스 트랩 메세지
+Record a message in the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW = 0x1b3,
+/*20031028 to latest
+기록할 메세지를 입력하시기 바랍니다.
+Please type a message for the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW_MSG = 0x1b4,
+/*20031028 to latest
+길드에게 보냄
+Send to Guild
+*/
+ MSG_SEND_TO_GUILD = 0x1b5,
+/*20031028 to latest
+결제된 계정이 아닙니다. 결제 페이지로 이동하시겠습니까?
+You didn't pay for this ID. Would you like to pay for it now?
+*/
+ MSG_NOT_SETTLED = 0x1b6,
+/*20031028 to latest
+서버가 혼잡한 관계로 잠시후 다시 시도해 주시기 바랍니다.
+Server is jammed due to overpopulation. Please try again after few minutes.
+*/
+ MSG_ACCOUNT_BUSY = 0x1b7,
+/*20031028 to latest
+지난 접속 정보가 남아 있습니다. 30초정도 지난뒤에 다시 시도해 주시기 바랍니다.
+Server still recognizes your last log-in. Please try again after a few minutes.
+*/
+ MSG_INFORMATION_REMAINED = 0x1b8,
+/*20031028 to latest
+매 풀어주기
+Release Falcon
+*/
+ MSG_BIRDOFF = 0x1b9,
+/*20031028 to latest
+페코페코 내리기
+Dismount
+*/
+ MSG_CHIKENOFF = 0x1ba,
+/*20031028 to latest
+小
+Small
+*/
+ MSG_SIZE_SMALL = 0x1bb,
+/*20031028 to latest
+中
+Med
+*/
+ MSG_SIZE_MIDDLE = 0x1bc,
+/*20031028 to latest
+大
+Big
+*/
+ MSG_SIZE_BIG = 0x1bd,
+/*20031028 to latest
+더블
+Double
+*/
+ MSG_DOUBLE = 0x1be,
+/*20031028 to latest
+트리플
+Triple
+*/
+ MSG_TRIPLE = 0x1bf,
+/*20031028 to latest
+쿼드로플
+Quadruple
+*/
+ MSG_QUADROPLE = 0x1c0,
+/*20031028 to latest
+%s 까지 로그인을 금지하고 있습니다.
+You are prohibited to log in until %s.
+*/
+ MSG_LOGIN_REFUSE_BLOCKED_UNTIL = 0x1c1,
+/*20031028 to latest
+의
+'s
+*/
+ MSG_MANUFACTURED_NORMAL_ITEM = 0x1c2,
+/*20031028 to latest
+의 파이어
+'s Fire
+*/
+ MSG_MANUFACTURED_FIRE_ITEM = 0x1c3,
+/*20031028 to latest
+의 아이스
+'s Ice
+*/
+ MSG_MANUFACTURED_ICE_ITEM = 0x1c4,
+/*20031028 to latest
+의 윈드
+'s Wind
+*/
+ MSG_MANUFACTURED_WIND_ITEM = 0x1c5,
+/*20031028 to latest
+의 어스
+'s Earth
+*/
+ MSG_MANUFACTURED_EARTH_ITEM = 0x1c6,
+/*20031028 to latest
+211.239.161.246
+38.144.194.2
+*/
+ MSG_ACCOUNT_ADDRESS = 0x1c7,
+/*20031028 to latest
+6900
+*/
+ MSG_ACCOUNT_PORT = 0x1c8,
+/*20031028 to 20171206
+http://www.ragnarok.co.kr
+20171213 to latest
+http://roz.gnjoy.com/
+http://www.ragnarok.co.kr
+*/
+ MSG_REGISTRATION_WEB_URL = 0x1c9,
+/*20031028 to latest
+%s 사용자 강제 종료
+Kill %s
+*/
+ MSG_BAN_USER = 0x1ca,
+/*20031028 to latest
+무지쎈
+Very Strong
+*/
+ MSG_ONE_STARPIECE = 0x1cb,
+/*20031028 to latest
+무지무지쎈
+Very Very Strong
+*/
+ MSG_TWO_STARPIECE = 0x1cc,
+/*20031028 to 20031028
+무지무지무지쎈
+20031103 to latest
+무무무쎈
+Very Very Very Strong
+*/
+ MSG_THREE_STARPIECE = 0x1cd,
+/*20031028 to latest
+길드 추방 사유
+The Reason of Expulsion
+*/
+ MSG_GUILD_KICK_REASON = 0x1ce,
+/*20031028 to latest
+ 공격 속도가 증가했습니다.
+Attack Speed is up.
+*/
+ MSG_INCATTACKSPEED = 0x1cf,
+/*20031028 to latest
+ 공격 속도가 감소했습니다.
+Attack Speed is down.
+*/
+ MSG_DECATTACKSPEED = 0x1d0,
+/*20031028 to latest
+ 무기의 공격력이 향상되었습니다.
+Weapon Damage is improved.
+*/
+ MSG_INCWEAPONATTACK = 0x1d1,
+/*20031028 to latest
+ 무기의 공격력이 감소되었습니다.
+Weapon Damage is reduced.
+*/
+ MSG_DECWEAPONATTACK = 0x1d2,
+/*20031028 to latest
+ 시전 딜레이가 줄었습니다.
+Cast Delay is reduced.
+*/
+ MSG_FASTPREDELAY = 0x1d3,
+/*20031028 to latest
+ 시전 딜레이가 정상으로 되었습니다.
+Cast Delay has returned to normal.
+*/
+ MSG_NORMALPREDELAY = 0x1d4,
+/*20031028 to latest
+ 무기에 독속성이 부여되었습니다.
+Weapon is temporarily enchanted with Poison.
+*/
+ MSG_WEAPONPROPERTYPOISON = 0x1d5,
+/*20031028 to latest
+ 무기에 성속성이 부여되었습니다.
+Weapon is temporarily enchanted with an elemental property.
+*/
+ MSG_WEAPONPROPERTYSAINT = 0x1d6,
+/*20031028 to latest
+ 무기의 원래속성이 적용되었습니다.
+Weapon has changed back to normal.
+*/
+ MSG_WEAPONPROPERTYORIGINAL = 0x1d7,
+/*20031028 to latest
+ 방어구에 성속성이 부여되었습니다.
+Armor has been enchanted with the Holy Ghost.
+*/
+ MSG_ARMORPROPERTYSAINT = 0x1d8,
+/*20031028 to latest
+ 방어구의 원래속성이 적용되었습니다.
+Armor has changed back to normal.
+*/
+ MSG_ARMORPROPERTYORIGINAL = 0x1d9,
+/*20031028 to latest
+ 배리어 상태가 되었습니다.
+Barrier Formed.
+*/
+ MSG_BARRIOR = 0x1da,
+/*20031028 to latest
+ 배리어 상태가 해제 되었습니다.
+Barrier Canceled.
+*/
+ MSG_DISAPPEARBARRIOR = 0x1db,
+/*20031028 to latest
+ 소형, 중형, 대형 몬스터에게 100% 공격력을 줍니다.
+Weapon Perfection Initiated.
+*/
+ MSG_PERFECTDAMAGE = 0x1dc,
+/*20031028 to latest
+ 웨폰퍼펙션 모드가 해제 되었습니다.
+Weapon perfection Canceled.
+*/
+ MSG_DISAPPEARPERFECTDAMAGE = 0x1dd,
+/*20031028 to latest
+ 무기가 파괴될 가능성이 높아진 대신 무기의 공격력이 증가하였습니다.
+Power-Thrust Initiated.
+*/
+ MSG_OVERTHRUSTING = 0x1de,
+/*20031028 to 20050118
+ 오버트러스팅 상태가 해제 되었습니다.
+20050124 to latest
+ 오버트러스트 상태가 해제 되었습니다.
+Power-Thrust Canceled.
+*/
+ MSG_DISAPPEAROVERTHRUSTING = 0x1df,
+/*20031028 to latest
+ 무기의 최대 성능을 끌어냅니다.
+Maximize-Power Initiated.
+*/
+ MSG_MAXIMIZE = 0x1e0,
+/*20031028 to latest
+ 맥시마이즈 상태가 해제 되었습니다.
+Maximize-Power Canceled.
+*/
+ MSG_DISAPPEARMAXIMIZE = 0x1e1,
+/*20031028 to latest
+[신서버]
+[New Server]
+*/
+ MSG_SERVER_PROPERTY_NEW = 0x1e2,
+/*20031028 to latest
+(%d 명)
+(%d players)
+*/
+ MSG_SERVER_USER_COUNT = 0x1e3,
+/*20031028 to latest
+(점검중)
+(On the maintenance)
+*/
+ MSG_SERVER_INSPECTING = 0x1e4,
+/*20031028 to latest
+길드멤버 %s님이 접속하셨습니다.
+Guild member %s has connected.
+*/
+ MSG_GUILD_MEMBER_STATUS_ONLINE = 0x1e5,
+/*20031028 to latest
+길드멤버 %s님이 종료하셨습니다.
+Guild member %s has disconnected.
+*/
+ MSG_GUILD_MEMBER_STATUS_OFFLINE = 0x1e6,
+/*20031028 to latest
+경험치 %d 얻음
+You got %d Base EXP.
+*/
+ MSG_GOT_EXPERIENCE_POINT = 0x1e7,
+/*20031028 to latest
+잡경험치 %d 얻음
+You got %d Job EXP.
+*/
+ MSG_GOT_JOB_EXPERIENCE_POINT = 0x1e8,
+/*20031028 to latest
+길드에서 탈퇴 했습니다.
+You left the guild.
+*/
+ MSG_LEFT_GUILD = 0x1e9,
+/*20031028 to latest
+길드에서 추방 당했습니다.
+You have been expelled from the Guild.
+*/
+ MSG_BAN_FROM_GUILD = 0x1ea,
+/*20031028 to latest
+아이템 감정 성공
+Item Appraisal has completed successfully.
+*/
+ MSG_ITEM_IDENTIFY_SUCCEESS = 0x1eb,
+/*20031028 to latest
+아이템 감정 실패
+Item appraisal has failed.
+*/
+ MSG_ITEM_IDENTIFY_FAIL = 0x1ec,
+/*20031028 to latest
+아이템 조합 성공
+Compounding has completed successfully.
+*/
+ MSG_ITEM_COMPOUNDING_SUCCEESS = 0x1ed,
+/*20031028 to latest
+아이템 조합 실패
+Compounding has failed.
+*/
+ MSG_ITEM_COMPOUNDING_FAIL = 0x1ee,
+/*20031028 to latest
+길드 적대 성공
+Antagonist has been set.
+*/
+ MSG_HOSTILE_GUILD_SUCCEESS = 0x1ef,
+/*20031028 to latest
+적대 길드수 초과로 길드 적대 실패
+Guild has too many Antagonists.
+*/
+ MSG_TOO_MANY_HOSTILE_GUILD = 0x1f0,
+/*20031028 to latest
+이미 적대 길드 입니다
+Already set as an Antagonist
+*/
+ MSG_ALREADY_REGISTERED_HOSTILE_GUILD = 0x1f1,
+/*20031028 to latest
+제련이 성공적으로 되었습니다.
+Upgrade has been completed successfully.
+*/
+ MSG_ITEM_REFINING_SUCCEESS = 0x1f2,
+/*20031028 to latest
+제련이 실패하였습니다.
+Upgrade has failed.
+*/
+ MSG_ITEM_REFINING_FAIL = 0x1f3,
+/*20031028 to 20040311
+텔레포트 불가능 지역입니다.
+20040315 to latest
+이곳에서는 순간이동이 불가능합니다.
+Unavailable Area to Teleport
+*/
+ MSG_IMPOSSIBLE_TELEPORT_AREA = 0x1f4,
+/*20031028 to 20040311
+텔레포트 가능 지역입니다.
+20040315 to latest
+이 장소는 기억할 수 없습니다.
+Unable to memorize this place as Warp Point
+*/
+ MSG_POSSIBLE_TELEPORT_AREA = 0x1f5,
+/*20031028 to latest
+지금은 종료할 수 없습니다.
+Please wait 10 seconds before trying to log out.
+*/
+ MSG_CANT_EXIT_NOW = 0x1f6,
+/*20031028 to latest
+직위
+Position
+*/
+ MSG_POSITION = 0x1f7,
+/*20031028 to latest
+직업
+Job
+*/
+ MSG_JOB = 0x1f8,
+/*20031028 to latest
+메모
+Note
+*/
+ MSG_MEMO = 0x1f9,
+/*20031028 to latest
+기여
+Devotion
+*/
+ MSG_CONTRIBUTION = 0x1fa,
+/*20031028 to latest
+상납경험치
+Tax Point
+*/
+ MSG_EXP_CONTIRIBUTION = 0x1fb,
+/*20031028 to latest
+길드탈퇴
+Leave Guild
+*/
+ MSG_LEAVE_GUILD = 0x1fc,
+/*20031028 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL_GUILD = 0x1fd,
+/*20031028 to latest
+서열
+Rank
+*/
+ MSG_GRADE = 0x1fe,
+/*20031028 to latest
+직위명
+Position Title
+*/
+ MSG_POSITION_NAME = 0x1ff,
+/*20031028 to latest
+가입권한
+Invitation
+*/
+ MSG_JOIN_AUTHORITY = 0x200,
+/*20031028 to latest
+처벌권한
+Punish
+*/
+ MSG_PENALTY_AUTORITY = 0x201,
+/*20031028 to latest
+상납%
+Tax %
+*/
+ MSG_CONTRIBUTION_PERCENT = 0x202,
+/*20031028 to latest
+제목
+Title
+*/
+ MSG_TITLE = 0x203,
+/*20031028 to latest
+내용
+For
+*/
+ MSG_CONTENTS = 0x204,
+/*20031028 to latest
+길드이름
+Guild Name
+*/
+ MSG_GUILD_NAME = 0x205,
+/*20031028 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILD_LEVEL = 0x206,
+/*20031028 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_PEOPLE_COUNT = 0x207,
+/*20031028 to latest
+랭킹
+Ranking
+*/
+ MSG_RANKING = 0x208,
+/*20031028 to latest
+아이템 감정
+Item Appraisal
+*/
+ MSG_ITEM_IDENTIFY = 0x209,
+/*20031028 to latest
+아이템 조합
+Insert Card
+*/
+ MSG_ITEM_COMPOUNDING = 0x20a,
+/*20031028 to latest
+탈퇴 사유를 입력해주세요.
+Please enter the reason of Secession.
+*/
+ MSG_PLEASE_INPUT_WHY_LEAVING = 0x20b,
+/*20031028 to latest
+추방 사유를 입력해주세요.
+Please enter the reason of Expulsion.
+*/
+ MSG_PELASE_INPUT_WHY_EXPEL = 0x20c,
+/*20031028 to latest
+상점을 닫으세요.
+Please close Shop.
+*/
+ MSG_PLEASE_CLOSE_STORE = 0x20d,
+/*20031028 to latest
+스킬 이름
+Skill
+*/
+ MSG_SKILL_NAME = 0x20e,
+/*20031028 to latest
+아이템 이름
+Item Name
+*/
+ MSG_ITEM_NAME = 0x20f,
+/*20031028 to 20031118
+https://pay.ragnarok.co.kr
+20031119 to latest
+https://payment.ragnarok.co.kr
+https://pay.ragnarok.co.kr (Billing Web)
+*/
+ MSG_SETTLE_WEB_URL = 0x210,
+/*20031028 to latest
+게임방에서 사용가능한 IP개수가 모두 사용중입니다. 개인 계정으로 결제 하시겠습니까?
+IP capacity of this Internet Cafe is full. Would you like to pay the personal base?
+*/
+ MSG_BAN_IP_OVERFLOW = 0x211,
+/*20031028 to latest
+결제시간이 다되어 게임을 종료합니다.
+You are out of available paid playing time. Game will be shut down automatically.
+*/
+ MSG_BAN_PAY_OUT = 0x212,
+/*20031028 to latest
+이름이 너무 깁니다. 한글 11자 영문 23자 이내로 써주십시오.
+Name is too long. Please enter a name no greater than 23 english characters.
+*/
+ MSG_NAMELENGTH_TOO_LONG = 0x213,
+/*20031028 to latest
+deleted
+Character will be deleted in %d seconds.
+*/
+ MSG_DELETE_AFTER_10_SECOND = 0x214,
+/*20031028 to latest
+귀하는 개인 정액제 사용자입니다.
+You paid with the personal regular base.
+*/
+ MSG_BILLING_100 = 0x215,
+/*20031028 to latest
+귀하는 개인정량제 사용자입니다.
+You paid with the personal regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_200 = 0x216,
+/*20031028 to latest
+귀하는 개인 무료 사용자입니다.
+You are free!
+*/
+ MSG_BILLING_300 = 0x217,
+/*20031028 to latest
+귀하는 개인 무료 허용기간 사용자입니다.
+You are free for the test, your available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_400 = 0x218,
+/*20031028 to latest
+귀하는 게임방 정액제 사용자입니다.
+You paid with the Internet Cafe regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_500 = 0x219,
+/*20031028 to latest
+귀하는 게임방 정량제 사용자입니다.
+You paid with the Time Limit for Internet Cafe. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_501 = 0x21a,
+/*20031028 to latest
+귀하는 게임방 무료 허용기간 사용자입니다.
+You are free for the test of Internet Cafe version .
+*/
+ MSG_BILLING_600 = 0x21b,
+/*20031028 to latest
+귀하는 게임방 무료 사용자입니다.
+You are free for the Internet Cafe version.
+*/
+ MSG_BILLING_700 = 0x21c,
+/*20031028 to latest
+귀하는 종량제 사이트 이용자입니다.
+You paid on the Time Limit Website.
+*/
+ MSG_BILLING_800 = 0x21d,
+/*20031028 to latest
+이모션 목록
+Emotion icon List
+*/
+ MSG_EMOTION_LIST = 0x21e,
+/*20031028 to latest
+/이모션
+/emo
+*/
+ MSG_VIEW_EMOTION = 0x21f,
+/*20031028 to latest
+/!
+*/
+ MSG_EMOTION_SURPRISE = 0x220,
+/*20031028 to latest
+/?
+*/
+ MSG_EMOTION_QUESTION = 0x221,
+/*20031028 to latest
+/기쁨
+/ho
+*/
+ MSG_EMOTION_DELIGHT = 0x222,
+/*20031028 to latest
+/하트
+/lv
+*/
+ MSG_EMOTION_THROB = 0x223,
+/*20031028 to latest
+/왕하트
+/lv2
+*/
+ MSG_EMOTION_BIGTHROB = 0x224,
+/*20031028 to latest
+/땀
+/swt
+*/
+ MSG_EMOTION_SWEAT = 0x225,
+/*20031028 to latest
+/아하
+/ic
+*/
+ MSG_EMOTION_AHA = 0x226,
+/*20031028 to latest
+/짜증
+/an
+*/
+ MSG_EMOTION_FRET = 0x227,
+/*20031028 to latest
+/화
+/ag
+*/
+ MSG_EMOTION_ANGER = 0x228,
+/*20031028 to latest
+/돈
+/$
+*/
+ MSG_EMOTION_MONEY = 0x229,
+/*20031028 to latest
+/...
+*/
+ MSG_EMOTION_THINK = 0x22a,
+/*20031028 to latest
+/감사
+/thx
+*/
+ MSG_EMOTION_THANKS = 0x22b,
+/*20031028 to latest
+/꽥
+/wah
+*/
+ MSG_EMOTION_KEK = 0x22c,
+/*20031028 to latest
+/죄송
+/sry
+*/
+ MSG_EMOTION_SORRY = 0x22d,
+/*20031028 to latest
+/웃음
+/heh
+*/
+ MSG_EMOTION_SMILE = 0x22e,
+/*20031028 to latest
+/뻘뻘
+/swt2
+*/
+ MSG_EMOTION_PROFUSELY_SWEAT = 0x22f,
+/*20031028 to latest
+/긁적
+/hmm
+*/
+ MSG_EMOTION_SCRATCH = 0x230,
+/*20031028 to latest
+/최고
+/no1
+*/
+ MSG_EMOTION_BEST = 0x231,
+/*20031028 to latest
+/두리번
+/??
+*/
+ MSG_EMOTION_STARE_ABOUT = 0x232,
+/*20031028 to latest
+/헉
+/omg
+*/
+ MSG_EMOTION_HUK = 0x233,
+/*20031028 to latest
+/오
+/oh
+*/
+ MSG_EMOTION_O = 0x234,
+/*20031028 to latest
+/엑스
+/X
+*/
+ MSG_EMOTION_X = 0x235,
+/*20031028 to latest
+/헬프
+/hlp
+*/
+ MSG_EMOTION_HELP = 0x236,
+/*20031028 to latest
+/가
+/go
+*/
+ MSG_EMOTION_GO = 0x237,
+/*20031028 to latest
+/엉엉
+/sob
+*/
+ MSG_EMOTION_CRY = 0x238,
+/*20031028 to latest
+/킥킥
+/gg
+*/
+ MSG_EMOTION_KIK = 0x239,
+/*20031028 to latest
+/쪽
+/kis
+*/
+ MSG_EMOTION_CHUP = 0x23a,
+/*20031028 to latest
+/쪽쪽
+/kis2
+*/
+ MSG_EMOTION_CHUPCHUP = 0x23b,
+/*20031028 to latest
+/흥
+/pif
+*/
+ MSG_EMOTION_HNG = 0x23c,
+/*20031028 to latest
+/응
+/ok
+*/
+ MSG_EMOTION_OK = 0x23d,
+/*20031028 to latest
+단축키 목록
+Shortcut List
+*/
+ MSG_SHORTCUT_LIST = 0x23e,
+/*20031028 to latest
+귀하의 계정은 보류되었습니다.
+Your account is suspended.
+*/
+ MSG_BAN_PAY_SUSPEND = 0x23f,
+/*20031028 to latest
+과금 정책 변경으로 인해 일시 종료됩니다. 다시 접속하여 주시기 바랍니다.
+Your connection is terminated due to change in the billing policy. Please connect again.
+*/
+ MSG_BAN_PAY_CHANGE = 0x240,
+/*20031028 to latest
+어카운트 서버에 인증된 IP와 귀하의 IP가 달라 연결을 종료합니다.
+Your connection is terminated because your IP doesn't match the authorized IP from the account server.
+*/
+ MSG_BAN_PAY_WRONGIP = 0x241,
+/*20031028 to latest
+게임방 IP에서 개인 종량제 과금을 막기 위해 연결을 종료합니다. 개인 종량제 과금을 사용하기 위해서는 게임방IP로 등록이 되지 않은 IP를 사용해 주세요.
+Your connection is terminated to prevent charging from your account's play time.
+*/
+ MSG_BAN_PAY_PNGAMEROOM = 0x242,
+/*20031028 to latest
+귀하는 운영자에 의해 강제 종료 되었습니다.
+You have been forced to disconnect by the Game Master Team.
+*/
+ MSG_BAN_OP_FORCE = 0x243,
+/*20031028 to latest
+무게가 90%를 초과하여 스킬을 사용할 수 없습니다.
+You can't use this Skill because you are over your Weight Limit.
+*/
+ MSG_USESKILL_FAIL_WEIGHTOVER = 0x244,
+/*20031028 to latest
+무명
+Nameless
+*/
+ MSG_NAMELESS_USER = 0x245,
+/*20031028 to latest
+축하합니다. %s님의 현재 랭킹이 %d위로 상승하였습니다.
+Congratulations! %s ranking has gone up to %d.
+*/
+ MSG_RANK_IN_TEN = 0x246,
+/*20031028 to latest
+안타깝게도 %s님의 현재 랭킹이 %d위로 하락하였습니다.
+What a pity! %s ranking has gone down to %d.
+*/
+ MSG_RANK_OUT_TEN = 0x247,
+/*20031028 to latest
+Pet Info
+*/
+ MSG_PET_INFO = 0x248,
+/*20031028 to latest
+만복도
+Hunger
+*/
+ MSG_PET_HUNGRY = 0x249,
+/*20031028 to latest
+친밀도
+Intimacy
+*/
+ MSG_PET_FRIENDLY = 0x24a,
+/*20031028 to latest
+상점과 채팅방을 동시에 열수 없습니다.
+Please avoid opening a chatroom while vending.
+*/
+ MSG_CANT_OPEN_STORE_WHILE_CHAT = 0x24b,
+/*20031028 to latest
+개
+Total
+*/
+ MSG_EA4 = 0x24c,
+/*20031028 to latest
+%s 를 전투불능으로 만들었습니다.
+You have knocked down %s.
+*/
+ MSG_SLAIN = 0x24d,
+/*20031028 to latest
+%s 님에 의해 전투불능 상태가 되었습니다.
+You have been knocked down by %s.
+*/
+ MSG_SLAINBY = 0x24e,
+/*20031028 to latest
+먹이 - '%s' 아이템이 존재하지 않습니다..
+Feed - "%s" is not available.
+*/
+ MSG_NOT_EXIST_PET_FOOD = 0x24f,
+/*20031028 to latest
+먹이 주기
+Feed Pet
+*/
+ MSG_PET_FEEDING = 0x250,
+/*20031028 to latest
+퍼포먼스
+Performance
+*/
+ MSG_PET_PERFORMANCE = 0x251,
+/*20031028 to latest
+알로 되돌리기
+Return to Egg Shell
+*/
+ MSG_PET_RETURN_EGG = 0x252,
+/*20031028 to latest
+악세사리 해제
+Unequip Accessory
+*/
+ MSG_PET_ACC_OFF = 0x253,
+/*20031028 to latest
+Pet 상태 보기
+Check Pet Status
+*/
+ MSG_PET_SHOWINFO = 0x254,
+/*20031028 to latest
+악세사리
+Accessory
+*/
+ MSG_PET_ACCESSARY = 0x255,
+/*20031028 to latest
+장착됨
+Equipped
+*/
+ MSG_ITEM_EQUIPED = 0x256,
+/*20031028 to latest
+펫 리스트
+Pet List
+*/
+ MSG_PET_EGG_LIST = 0x257,
+/*20031028 to latest
+장착 안됨
+Unequipped
+*/
+ MSG_ITEM_UNEQUIPED = 0x258,
+/*20031028 to latest
+정말로 먹이를 주시겠습니까?
+Are you sure that you want to feed your pet?
+*/
+ MSG_SURE_TO_FEED_PET = 0x259,
+/*20031028 to latest
+가격을 쓰실땐 숫자(0~9)만 써주십시오.
+Only the numbers (0~9) are available.
+*/
+ MSG_CAN_INPUT_NUMBER_ONLY = 0x25a,
+/*20031028 to latest
+감정되지 않은 아이템은 판매할 수 없습니다.
+You cannot sell unidentified items.
+*/
+ MSG_CANT_SELL_UNIDENTIFIED_ITEM = 0x25b,
+/*20031028 to latest
+가격이 0 Zeny인 아이템이 존재합니다. 계속 하시겠습니까?
+Item at 0 Zeny exists. Do you wish to continue?
+*/
+ MSG_YOU_HAVE_FREE_ITEM_ON_SHOP = 0x25c,
+/*20031028 to latest
+[새로 추가된 이모션 리스트]
+[New Emotion List]
+*/
+ MSG_NEW_EMOTION_LIST = 0x25d,
+/*20031028 to latest
+일본쪽 베타 사용자들에게 전하는 메세지. -> 겅호에서 재가입 하세요.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE1 = 0x25e,
+/*20031028 to latest
+일본쪽 과금이 종료된 사용자들에게 전하는 메세지. -> 돈내라. 두 번내라.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE2 = 0x25f,
+/*20031028 to latest
+같은 계정의 캐릭터가 이미 가입되어있습니다.
+Character in the same account already joined.
+*/
+ MSG_ALREADY_SAME_AID_JOINED = 0x260,
+/*20031028 to latest
+(%d 명) - 만18세이상
+(%d ppl) - over the age 18
+*/
+ MSG_SERVER_PROPERTY_ADULT = 0x261,
+/*20031028 to latest
+ 프로보크 상태가 되었습니다.
+Provoke initiated.
+*/
+ MSG_ENST_PROVOKE = 0x262,
+/*20031028 to latest
+ 프로보크 상태가 해제되었습니다.
+Provoke canceled.
+*/
+ MSG_DSST_PROVOKE = 0x263,
+/*20031028 to latest
+ 인듀어 상태가 되었습니다.
+Endure initiated.
+*/
+ MSG_ENST_ENDURE = 0x264,
+/*20031028 to latest
+ 인듀어 상태가 해제되었습니다.
+Endure canceled.
+*/
+ MSG_DSST_ENDURE = 0x265,
+/*20031028 to latest
+ 집중력 향상 상태가 되었습니다.
+Improve Concentration initiated.
+*/
+ MSG_ENST_CONCENTRATION = 0x266,
+/*20031028 to latest
+ 집중력 향상 상태가 해제되었습니다.
+Improve Concentration canceled.
+*/
+ MSG_DSST_CONCENTRATION = 0x267,
+/*20031028 to latest
+ 하이딩 상태가 되었습니다.
+Hiding Initiated.
+*/
+ MSG_ENST_HIDING = 0x268,
+/*20031028 to latest
+ 하이딩 상태가 해제되었습니다.
+Hiding Canceled.
+*/
+ MSG_DSST_HIDING = 0x269,
+/*20031028 to latest
+ 클로킹 상태가 되었습니다.
+Cloaking initiated.
+*/
+ MSG_ENST_CLOAKING = 0x26a,
+/*20031028 to latest
+ 클로킹 상태가 해제되었습니다.
+Cloaking canceled.
+*/
+ MSG_DSST_CLOAKING = 0x26b,
+/*20031028 to latest
+ 독을 반사 할 수 있는 상태가 되었습니다.
+Poison React initiated.
+*/
+ MSG_ENST_POISONREACT = 0x26c,
+/*20031028 to latest
+ 포이즌 리액트 상태가 해제되었습니다.
+Poison React canceled.
+*/
+ MSG_DSST_POISONREACT = 0x26d,
+/*20031028 to latest
+ 이동속도가 감소하였습니다.
+Speed reduced.
+*/
+ MSG_ENST_QUAGMIRE = 0x26e,
+/*20031028 to latest
+ 콰그마이어 상태가 해제되었습니다.
+Quagmire canceled.
+*/
+ MSG_DSST_QUAGMIRE = 0x26f,
+/*20031028 to latest
+ 방어력이 증가되었습니다.
+Defense increased.
+*/
+ MSG_ENST_ANGELUS = 0x270,
+/*20031028 to 20031223
+ 안젤루스 상태가 해제돼었습니다.
+20031229 to latest
+ 안젤루스 상태가 해제되었습니다.
+Angelus canceled.
+*/
+ MSG_DSST_ANGELUS = 0x271,
+/*20031028 to latest
+ 힘과 지능, 덱스가 증가하였습니다.
+Blessing aligned.
+*/
+ MSG_ENST_BLESSING = 0x272,
+/*20031028 to latest
+ 블레싱 상태가 해제되었습니다.
+Blessing canceled.
+*/
+ MSG_DSST_BLESSING = 0x273,
+/*20031028 to latest
+ 시그넘 크루시스를 사용하였습니다.
+Signum Crusis initiated.
+*/
+ MSG_ENST_CRUCIS = 0x274,
+/*20031028 to latest
+ 시그넘 크루시스 상태가 해제되었습니다.
+Signum Crusis canceled.
+*/
+ MSG_DSST_CRUCIS = 0x275,
+/*20031028 to latest
+ 독이 퍼지는 속도가 느려졌습니다.
+Slow Poison initiated.
+*/
+ MSG_ENST_SLOWPOISON = 0x276,
+/*20031028 to latest
+ 슬로우 포이즌 상태가 해제되었습니다.
+Slow Poison Canceled.
+*/
+ MSG_DSST_SLOWPOISON = 0x277,
+/*20031028 to latest
+ SP의 회복 속도가 향상 되었습니다.
+HP/SP recovery increased.
+*/
+ MSG_ENST_MAGNIFICAT = 0x278,
+/*20031028 to latest
+ 마니피캇 상태가 해제되었습니다.
+Magnificat canceled.
+*/
+ MSG_DSST_MAGNIFICAT = 0x279,
+/*20031028 to latest
+ 행운이 향상되었습니다.
+Luck increased.
+*/
+ MSG_ENST_GLORIA = 0x27a,
+/*20031028 to latest
+ 글로리아 상태가 해제되었습니다.
+Gloria canceled.
+*/
+ MSG_DSST_GLORIA = 0x27b,
+/*20031028 to latest
+ 1회 공격에 두 배 데미지를 받는 상태가 되었습니다.
+You will received double damage from all attacking opponents.
+*/
+ MSG_ENST_LEXAETERNA = 0x27c,
+/*20031028 to latest
+ 렉스에테르나 상태가 해제되었습니다.
+Lex Eterna canceled.
+*/
+ MSG_DSST_LEXAETERNA = 0x27d,
+/*20031028 to latest
+ 공격속도가 증가하였습니다.
+Attack Speed increased.
+*/
+ MSG_ENST_ADRENALINE = 0x27e,
+/*20031028 to latest
+ 공격속도가 감소하였습니다.
+Attack Speed reduced.
+*/
+ MSG_DSST_ADRENALINE = 0x27f,
+/*20031028 to latest
+ 페코에 올라 탔습니다.
+You've just been on a Peco Peco.
+*/
+ MSG_ENST_RIDING = 0x280,
+/*20031028 to latest
+ 페코에서 내렸습니다.
+You've just got off of a Peco Peco.
+*/
+ MSG_DSST_RIDING = 0x281,
+/*20031028 to latest
+ 팔콘을 장착하였습니다.
+You've just carried a Falcon with.
+*/
+ MSG_ENST_FALCON = 0x282,
+/*20031028 to latest
+ 팔콘을 풀어주었습니다.
+You've just released a Falcon.
+*/
+ MSG_DSST_FALCON = 0x283,
+/*20031028 to latest
+ 죽은척하기 상태가 되었습니다.
+Play Dead initiated.
+*/
+ MSG_ENST_TRICKDEAD = 0x284,
+/*20031028 to latest
+ 죽은척하기 상태가 해제되었습니다.
+Play Dead canceled.
+*/
+ MSG_DSST_TRICKDEAD = 0x285,
+/*20031028 to latest
+ 힘이 강해졌습니다.
+STR improved.
+*/
+ MSG_ENST_SHOUT = 0x286,
+/*20031028 to latest
+ 힘이 원래대로 돌아왔습니다.
+STR turned back to normal.
+*/
+ MSG_DSST_SHOUT = 0x287,
+/*20031028 to latest
+ 에너지코트 상태가 되었습니다.
+Energy Coat initiated.
+*/
+ MSG_ENST_ENERGYCOAT = 0x288,
+/*20031028 to latest
+ 에너지코트 상태가 해제되었습니다.
+Energy Coat canceled.
+*/
+ MSG_DSST_ENERGYCOAT = 0x289,
+/*20031028 to latest
+ 방어구가 파괴되었습니다.
+Armor destroyed.
+*/
+ MSG_ENST_BROKENAMOR = 0x28a,
+/*20031028 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENAMOR = 0x28b,
+/*20031028 to latest
+ 무기가 파괴되었니다.
+Weapon destroyed.
+*/
+ MSG_ENST_BROKENWEAPON = 0x28c,
+/*20031028 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENWEAPON = 0x28d,
+/*20031028 to latest
+ 환영상태가 되었습니다.
+Invisibility initiated.
+*/
+ MSG_ENST_ILLUSION = 0x28e,
+/*20031028 to latest
+ 환영상태가 해제되었습니다.
+Invisibility canceled.
+*/
+ MSG_DSST_ILLUSION = 0x28f,
+/*20031028 to latest
+과금 정보 처리가 늦어지고 있어 접속이 지연되고 있습니다. 잠시 후에 다시 시도해 주시기 바랍니다.
+Sorry. It is delayed due to the process of payment. Please re-connect in a minute.
+*/
+ MSG_REFUSE_BLOCK_TEMPORARY = 0x290,
+/*20031028 to 20060403
+장착된 화살을 해제 하여야 합니다.
+20060410 to 20061009
+장착된 화살 또는 탄환을 해제 하여야 합니다.
+20061016 to latest
+장착된 화살/탄환/수리검 을 해제해야합니다.
+You must unequip ammunition first.
+*/
+ MSG_UNEQUIP_ARROW = 0x291,
+/*20031028 to latest
+화살 목록
+Arrow List
+*/
+ MSG_ARROW_LIST = 0x292,
+/*20031028 to latest
+카트 목록
+Cart List
+*/
+ MSG_CART_LIST = 0x293,
+/*20031028 to latest
+카트를 장착한 상태여야 합니다.
+You must have a Pushcart.
+*/
+ MSG_MUST_EQUIP_CART = 0x294,
+/*20031028 to latest
+채팅방을 개설 할 수 없습니다.
+You cannot open a Chat Window.
+*/
+ MSG_CANT_MAKE_CHAT_ROOM = 0x295,
+/*20031028 to latest
+라그나로크 홈페이지로 접속하여 계정을 만듭니다. 처음 계정을 만드시면 3일 동안은 무료로 이용하실 수 있습니다.
+Registering an account is the first step to accessing the game. Do you want to visit the registration page now?
+*/
+ MSG_3DAY_FREE = 0x296,
+/*20031028 to latest
+앉은 상태에서는 이 아이템을 사용할 수 없습니다.
+You cannot use this item while sitting.
+*/
+ MSG_CANT_USE_WHEN_SITDOWN = 0x297,
+/*20031028 to 20040413
+운영자에 의한 채팅 및 스킬 금지가 %d 분간 남아 있습니다.
+20040419 to 20040714
+운영자에 의한 채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+20040726 to latest
+채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+Your use of skills and chat will be blocked for the next %d minutes.
+*/
+ MSG_BAD_MANNER_REMAIN = 0x298,
+/*20031028 to 20040413
+운영자에 의한 채팅 및 스킬 금지가 해지 되었습니다.
+20040419 to 20040714
+운영자에 의한 채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+20040726 to latest
+채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+Your use of skills and chat have been reinstated.
+*/
+ MSG_BAD_MANNER_END = 0x299,
+/*20031028 to latest
+-[장착안됨]
+- [Not equipped]
+*/
+ MSG_REF_UNEQUIP = 0x29a,
+/*20031028 to latest
+배고픔
+Very Hungry
+*/
+ MSG_VERY_HUNGRY = 0x29b,
+/*20031028 to latest
+출출함
+Hungry
+*/
+ MSG_HUNGRY = 0x29c,
+/*20031028 to latest
+보통
+Normal
+*/
+ MSG_NORMAL = 0x29d,
+/*20031028 to latest
+배부름
+Satisfied
+*/
+ MSG_REPLETE = 0x29e,
+/*20031028 to latest
+아주 배부름
+Stuffed
+*/
+ MSG_VERY_REPLETE = 0x29f,
+/*20031028 to latest
+서먹서먹함
+Awkward
+*/
+ MSG_VERY_AWKWARD = 0x2a0,
+/*20031028 to latest
+어색함
+Shy
+*/
+ MSG_AWKWARD = 0x2a1,
+/*20031028 to latest
+친함
+Cordial
+*/
+ MSG_FRIENDLY = 0x2a2,
+/*20031028 to latest
+절친함
+Loyal
+*/
+ MSG_VERY_FRIENDLY = 0x2a3,
+/*20031028 to latest
+알수 없음
+Unknown
+*/
+ MSG_UNKNOWN = 0x2a4,
+/*20031028 to 20080513
+(태국)귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+20080514 to latest
+귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d day %d hour %d minute.
+*/
+ MSG_BILLING_DAY_HOUR_MINUTES = 0x2a5,
+/*20031028 to 20080513
+(태국)이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+20080514 to latest
+이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+Your account is already connected to account server.
+*/
+ MSG_BAN_INFORMATION_REMAINED_ANOTHER_ACCOUNT = 0x2a6,
+/*20031028 to 20080513
+(태국)귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+20080514 to latest
+귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d hour %d minute.
+*/
+ MSG_BILLING_HOUR_MINUTES = 0x2a7,
+/*20031028 to 20080513
+(태국)귀하는 무료 사용자 입니다.
+20080514 to latest
+귀하는 무료 사용자 입니다.
+Your account is a free account.
+*/
+ MSG_BILLING_FREE_USER = 0x2a8,
+/*20031028 to 20080513
+(태국)이 계정으로 사크라이에 접속할수 없습니다.
+20080514 to latest
+이 계정으로 사크라이에 접속할수 없습니다.
+This account can't connect the Sakray server.
+*/
+ MSG_REFUSE_NONSAKRAY_ID_BLOCKED = 0x2a9,
+/*20031028 to latest
+펫의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Your pet name must be 23 characters or less.
+*/
+ MSG_PETNAME_IN23 = 0x2aa,
+/*20031028 to latest
+이름은 단 한번만 바꿀수 있습니다. 펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You may change your pet's name only once. Your pet's name will be changed to ^0000ff^0000ff %s^000000^000000. Do you wish to continue?
+*/
+ MSG_PETNAME_CHANGE_ONLYONCE = 0x2ab,
+/*20031028 to latest
+/폰트
+/font
+*/
+ MSG_NAMEBALLOON_TYPE = 0x2ac,
+/*20031028 to latest
+길드에 남은 제니가 부족하여 작업이 실패하였습니다.
+Your guild lacks the funds to pay for this venture.
+*/
+ MSG_GUILDZENY_NOT_ENOUGH = 0x2ad,
+/*20031028 to latest
+길드가 소유할 수 있는 최대 금액을 초과하여 작업이 실패하였습니다.
+Your guild zeny limit prevents you from performing this action.
+*/
+ MSG_GUILDZENY_OVER = 0x2ae,
+/*20031028 to latest
+이펙트 간략화 On
+Simplified effects have been activated.
+*/
+ MSG_MINEFFECT_ON = 0x2af,
+/*20031028 to latest
+이펙트 간략화 Off
+Simplified effects have been deactivated.
+*/
+ MSG_MINEFFECT_OFF = 0x2b0,
+/*20031028 to latest
+자본금
+Required Fee
+*/
+ MSG_CAPITAL = 0x2b1,
+/*20031028 to latest
+아이템을 바닥에 버리려면, 아이템 창을 열어 주십시오.
+If you wish to drop an item, you must first open your Item Window (alt+e).
+*/
+ MSG_OPEN_ITEMWND_TO_THROW = 0x2b2,
+/*20031028 to latest
+PC방 요금이 종료하여 개인 요금제로 전환합니다. 개인 요금으로 게임을 계속 하시겠습니까?
+Internet Cafe Time Plan has been ended. Would you like to continue the game with your personal play time?
+*/
+ MSG_ASK_PNGAMEROOM = 0x2b3,
+/*20031028 to 20100928
+
+20081008 to latest
+
+Current admission application state.
+*/
+ MSG_REPLY_REMAINTIME = 0x2b4,
+/*20031028 to 20100928
+
+20081008 to latest
+
+Current admission application state.
+*/
+ MSG_INFO_REMAINTIME = 0x2b5,
+/*20031028 to latest
+돈이 모자라거나, 가질 수 있는 최대 금액을 초과하였습니다.
+Your lack of zeny or your zeny limit have prevented you from performing this action.
+*/
+ MSG_OVER_OR_LOW_MONEY = 0x2b6,
+/*20031028 to latest
+전투불능 상태가 되었습니다. esc키를 누르시면 선택창이 뜹니다.
+Your character has fainted. Push the ESC key to restart.
+*/
+ MSG_PRESS_ESC_TO_RESTART = 0x2b7,
+/*20031028 to latest
+ %d 개 획득
+- %d obtained.
+*/
+ MSG_EA_OBTAIN = 0x2b8,
+/*20031028 to latest
+스펠 리스트
+Spell List
+*/
+ MSG_SPELL_LIST = 0x2b9,
+/*20031028 to latest
+/최소화
+/minimize
+*/
+ MSG_MINEFFECT = 0x2ba,
+/*20031028 to latest
+이 아이템은 손상되어 있습니다..
+This item has been damaged.
+*/
+ MSG_DAMAGED_ITEM = 0x2bb,
+/*20031028 to latest
+/noshift : 쉬프트를 누르지않고 힐로 적을 공격할수있게됩니다 On Off
+/noshift: You may use your ''force heal'' ability without the Shift key. On | Off
+*/
+ MSG_EXPLAIN_NOSHIFT = 0x2bc,
+/*20031028 to 20040223
+시프트를 누르지 않고도 힐로 몬스터를 공격할수 있습니다 [ON]
+20040225 to latest
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns ON]
+[no shift] option activated. [ON]
+*/
+ MSG_NOSHIFT_ON = 0x2bd,
+/*20031028 to 20040223
+시프트를 누르지 않고도 힐로 몬스터를 공격할수 있습니다 [OFF]
+20040225 to 20040315
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+20040322 to latest
+시프트를 눌러야 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+[no shift] option deactivated. [OFF]
+*/
+ MSG_NOSHIFT_OFF = 0x2be,
+/*20031028 to latest
+MSI_REFUSE_BAN_BY_DBA
+*/
+ MSG_REFUSE_BAN_BY_DBA = 0x2bf,
+/*20031028 to latest
+MSI_REFUSE_EMAIL_NOT_CONFIRMED
+*/
+ MSG_REFUSE_EMAIL_NOT_CONFIRMED = 0x2c0,
+/*20031028 to latest
+MSI_REFUSE_BAN_BY_GM
+*/
+ MSG_REFUSE_BAN_BY_GM = 0x2c1,
+/*20031028 to latest
+MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+*/
+ MSG_REFUSE_TEMP_BAN_FOR_DBWORK = 0x2c2,
+/*20031028 to latest
+MSI_REFUSE_SELF_LOCK
+*/
+ MSG_REFUSE_SELF_LOCK = 0x2c3,
+/*20031028 to latest
+MSI_REFUSE_NOT_PERMITTED_GROUP
+*/
+ MSG_REFUSE_NOT_PERMITTED_GROUP = 0x2c4,
+/*20031028 to latest
+MSI_REFUSE_WAIT_FOR_SAKRAY_ACTIVE
+*/
+ MSG_REFUSE_WAIT_FOR_SAKRAY_ACTIVE = 0x2c5,
+/*20031028 to latest
+/aura : 오오라를 간략화 시킬수있습니다 On Off
+/aura: Simplify Aura effect On | Off
+*/
+ MSG_EXPLAIN_AURA = 0x2c6,
+/*20031028 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_AURA_ON = 0x2c7,
+/*20031028 to latest
+오오라가 간략화되서 표시됩니다 [오오라 OFF]
+Simplify Aura enabled. [ON]
+*/
+ MSG_AURA_OFF = 0x2c8,
+/*20031028 to latest
+채팅금지 기록 %d 회
+Chat block record %d times
+*/
+ MSG_PROHIBIT_LOG = 0x2c9,
+/*20031028 to latest
+채팅 금지 리스트
+Chat block list
+*/
+ MSG_PROHIBIT_LIST = 0x2ca,
+/*20031028 to latest
+/이름표시 or /showname : 캐릭터의 이름 표시 방식을 변경합니다.
+/showname: Change the name font type.
+*/
+ MSG_EXPLAIN_SHOWNAMETYPE = 0x2cb,
+/*20031028 to latest
+/noctrl : 콘트롤을 누르지않아도 자동공격이 됩니다. On Off
+/noctrl | /nc: Auto attack without pressing ctrl key. On | Off
+*/
+ MSG_EXPLAIN_NOCTRL = 0x2cc,
+/*20031028 to 20040223
+콘트롤을 누르지 않아도 자동공격을 합니다 [자동공격 ON]
+20040225 to latest
+콘트롤을 누르지 않아도 자동공격을 합니다 [/nc ON]
+Use auto attack without Ctrl. [Auto attack ON]
+*/
+ MSG_NOCTRL_ON = 0x2cd,
+/*20031028 to 20040223
+콘트롤을 눌러야 자동공격을 합니다 [자동공격 OFF]
+20040225 to latest
+콘트롤을 눌러야 자동공격을 합니다 [/nc OFF]
+Use auto attack with Ctrl. [Auto attack OFF]
+*/
+ MSG_NOCTRL_OFF = 0x2ce,
+/*20031028 to latest
+채팅 금지 주기
+Mute this player.
+*/
+ MSG_APPEND_PROHIBIT = 0x2cf,
+/*20031028 to latest
+채팅 금지 완전 풀기 & 로그 삭제
+Unmute player & Erase mute time.
+*/
+ MSG_ERASE_PROHIBIT = 0x2d0,
+/*20031028 to latest
+채팅 금지 시간 줄이기(로그 삭제 안됨)
+Decrease Player Mute time.
+*/
+ MSG_REDUCE_PROHIBIT = 0x2d1,
+/*20031028 to latest
+폰트가 정상적으로 바뀌었습니다 [이름표시방식 1]
+Normal Font Displayed. [showname type 1]
+*/
+ MSG_SHOWNAME_ON = 0x2d2,
+/*20031028 to latest
+폰트가 가늘게 바뀌면서 파티명도 표시됩니다 [이름표시방식 2]
+Font will be thin and party name will be shown [showname type 2]
+*/
+ MSG_SHOWNAME_OFF = 0x2d3,
+/*20031028 to latest
+/doridori : 연속해서 이 명령어를 쳐주면 캐릭터가 도리도리 ^^;;
+/doridori: Shake head
+*/
+ MSG_EXPLAIN_DORIDORI = 0x2d4,
+/*20031028 to latest
+인터넷 카페에서 과금을 하고 있습니다.
+Internet room is paying now.
+*/
+ MSG_BILLING_INTERNET_CAFE = 0x2d5,
+/*20031028 to latest
+정액제 과금은 %d일 %d시간 %d분이 남았습니다.
+종량제 과금은 %d시간 %d분이 남았습니다.
+Prepaid voucher validate until %d days %d hours %d minutes later.
+Time limit voucher validate untill %d hours %d minutes later.
+*/
+ MSG_BILLING_BOTH = 0x2d6,
+/*20031028 to latest
+/bingbing : 연속해서 이 명령어를 쳐주면 캐릭터가 빙글빙글 ^^;;
+/bingbing: Rotates player counter clockwise.
+*/
+ MSG_EXPLAIN_BINGBING = 0x2d7,
+/*20031028 to latest
+/bangbang : 연속해서 이 명령어를 쳐주면 캐릭터가 뱅글뱅글 ^^;;
+/bangbang: Rotates player clockwise.
+*/
+ MSG_EXPLAIN_BANGBANG = 0x2d8,
+/*20031028 to latest
+/skillfail : 빨간색의 스킬사용 실패 메세지를 표시하지 않습니다 On Off
+/skillfail: Display red font message when skill fails. On | Off
+*/
+ MSG_EXPLAIN_SKILLFAIL = 0x2d9,
+/*20031028 to 20040223
+스킬사용 실패 메세지를 표시합니다 [표시 ON]
+20040225 to latest
+스킬사용 실패 메세지를 표시합니다 [/sf ON]
+Skill fail messages will be displayed. [Display On]
+*/
+ MSG_SKILLFAIL_ON = 0x2da,
+/*20031028 to 20040223
+스킬사용 실패 메세지를 표시하지 않습니다 [표시 OFF]
+20040225 to latest
+스킬사용 실패 메세지를 표시하지 않습니다 [/sf OFF]
+Skill fail messages will not be displayed. [Display OFF]
+*/
+ MSG_SKILLFAIL_OFF = 0x2db,
+/*20031028 to latest
+/notalkmsg : 채팅내용을 채팅창에 표시하지 않습니다 On Off
+/notalkmsg: Chat will not be displayed in chat window. On | Off
+*/
+ MSG_EXPLAIN_NOTALKMSG = 0x2dc,
+/*20031028 to 20040223
+채팅내용을 채팅창에 표시합니다 [표시 ON]
+20040225 to latest
+채팅내용을 채팅창에 표시합니다 [/nm ON]
+Chat content will be displayed in the chat window. [Display ON]
+*/
+ MSG_NOTALKMSG_ON = 0x2dd,
+/*20031028 to 20040223
+채팅내용을 채팅창에 표시하지않습니다 [표시 OFF]
+20040225 to latest
+채팅내용을 채팅창에 표시하지않습니다 [/nm OFF]
+Chat content will not be displayed in the chat window. [Display OFF]
+*/
+ MSG_NOTALKMSG_OFF = 0x2de,
+/*20031028 to 20040423
+/set1 : /noctrl + /showname + /skillfail
+20040426 to 20040707
+/set1 : /noctrl + /showname + /skillfail , /set2 : + /q3
+20040707 to latest
+/set1 : /nc + /showname + /sf + /wi, /set2 : + /q3
+/set1: /noctrl + /showname + /skillfail
+*/
+ MSG_EXPLAIN_SET1 = 0x2df,
+/*20031028 to latest
+/fog : FOG이펙트를 키거나 끌수있습니다 On Off
+/fog: Fog effect. On | Off
+*/
+ MSG_EXPLAIN_FOG = 0x2e0,
+/*20031028 to latest
+ 청혼을 해왔습니다. 승낙하시겠습니까?
+You have received a marriage proposal. Do you accept?
+*/
+ MSG_SUGGEST_COUPLE = 0x2e1,
+/*20031028 to latest
+아이템 분배 방식
+Item sharing type
+*/
+ MSG_HOWITEMDIV = 0x2e2,
+/*20031028 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMDIV1 = 0x2e3,
+/*20031028 to latest
+균등하게 분배
+Shared
+*/
+ MSG_ITEMDIV2 = 0x2e4,
+#if PACKETVER >= 20031103
+/*20031103 to latest
+nProtect KeyCrypt
+*/
+ MSG_KEYCRYPT = 0x2e5,
+/*20031103 to latest
+Keyboard Driver가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+Keyboard Driver has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_INSTALL_KEYDRIVER = 0x2e6,
+/*20031103 to latest
+설치가 완료 되었습니다.
+
+시스템을 Reboot 합니다.
+Installation has been completed.
+
+System will be rebooted.
+*/
+ MSG_KEYCRYPT_REBOOT = 0x2e7,
+/*20031103 to latest
+설치 실패.
+Installation has been failed.
+*/
+ MSG_KEYCRYPT_INSTALLFAIL = 0x2e8,
+/*20031103 to latest
+키보드 보안을 적용하지 않고 계속합니다.
+Keyboard Security will be skipped.
+*/
+ MSG_KEYCRYPT_SKIPKEYCRYPT = 0x2e9,
+/*20031103 to latest
+키보드 보안에 필요한 파일이 존재하지 않습니다.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+Required file for Keyboard Security is not existing.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+*/
+ MSG_KEYCRYPT_NOKEYCRYPTFILE = 0x2ea,
+/*20031103 to latest
+USB Keyboard가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+USB Keyboard has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_USBKEYBOARD = 0x2eb,
+/*20031103 to latest
+ftp://ragnarok.nefficient.co.kr/pub/ragnarok/ragnarok0526.exe
+*/
+ MSG_FINDHACK_PATH = 0x2ec,
+/*20031103 to latest
+FindHack이 정상적으로 설치가 되어있지 않습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.(%d).
+FindHack is not installed correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.(%d).
+*/
+ MSG_FINDHACK_NOTINSTALLED = 0x2ed,
+/*20031103 to latest
+해킹툴이 존재하지만 치료가 정상적으로 되지 않았습니다. 라그나로크가 실행되지 않습니다.
+Hacking tool is existing but it hasn't been cleaned. Rangarok Online will not be executed.
+*/
+ MSG_FINDHACK_HACKTOOLEXIST = 0x2ee,
+/*20031103 to latest
+해킹툴 진단 프로그램이 정상적으로 다운로드 되지 않았습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+Hacking tool scan program has not been downloaded correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_CANTDOWNLOAD = 0x2ef,
+/*20031103 to latest
+NPX.DLL 등록에러 이거나 FindHack 구동에 필요한 파일이 없습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+NPX.DLL register error or there is no necessary file to run FindHack. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_NOFILE = 0x2f0,
+/*20031103 to latest
+예외사항이 발생했습니다. (02-3281-0361)로 문의해주세요. 리턴값(%d)
+Exceptional Error. Please contact the customer support. Return Value: (%d)
+*/
+ MSG_FINDHACK_EXCEPTION = 0x2f1,
+/*20031103 to latest
+종료버튼을 클릭 하셨습니다.
+Exit button has been clicked.
+*/
+ MSG_FINDHACK_EXITPRESSED = 0x2f2,
+/*20031103 to latest
+Findhack 업데이트 서버접근 실패하였습니다. 잠시 후에 다시 시도해 주시거나 그라비티 운영팀으로 연락해주시기 바랍니다.
+Unable to connect Findhack Update Server. Please try again or contact the customer support.
+*/
+ MSG_FINDHACK_UPDATEFAILED = 0x2f3,
+/*20031103 to latest
+사랑받고있는
+Beloved
+*/
+ MSG_NAMED_PET = 0x2f4,
+#endif
+#if PACKETVER >= 20031110
+/*20031110 to latest
+/report or /신고 : 신고용 갈무리 파일을 저장합니다.
+/report: Save a chat log file.
+*/
+ MSG_REPORTCOMMAND_EXPLANATION = 0x2f5,
+/*20031110 to 20031112
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+20031117 to latest
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로 사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+Chat logs are not accepted as evidence for any ill-mannered violation on account of possible file modifications. However this feature is provided for players' personal reference.
+*/
+ MSG_REPORTTEXT_HEADER = 0x2f6,
+/*20031110 to latest
+당신을 사랑해요 ♡
+I love you.
+*/
+ MSG_LOVE_SKILL = 0x2f7,
+#endif
+#if PACKETVER >= 20031124
+/*20031124 to latest
+화면 또는 이펙트가 밝아서 눈에 부담이 되시는분들은 모니터의 밝기를 조정해주시기바랍니다.
+Please adjust your monitor/video brightness if effects appear too bright.
+*/
+ MSG_EXPLAIN_BRIGHT = 0x2f8,
+#endif
+#if PACKETVER >= 20031218
+/*20031218 to latest
+전체화면모드가 잘안되는 경우에 게임실행후 ALT+TAB으로 화면을 전환하면 잘되는 기종도 있습니다
+If full screen mode fails to work, it is suggested you alt+tab [or ctrl+esc] to inactivate and reactivate the Ragnarok Client.
+*/
+ MSG_EXPLAIN_ALTTAB = 0x2f9,
+#endif
+#if PACKETVER >= 20031223
+/*20031223 to latest
+(%d 명) - 유료서버
+(%d players) - Pay to Play Server
+*/
+ MSG_SERVER_PROPERTY_PAY = 0x2fa,
+/*20031223 to latest
+(%d 명) - 무료서버
+(%d players) - Free Server
+*/
+ MSG_SERVER_PROPERTY_FREE = 0x2fb,
+/*20031223 to latest
+무료 회원은 유료 서버로 접속할 수 없습니다.
+Trial players can't connect Pay to Play Server.
+*/
+ MSG_CANT_CONNECT_TO_PAY_SERVER = 0x2fc,
+#endif
+#if PACKETVER >= 20031230
+/*20031230 to 20040108
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [QUICK ON]
+20040112 to latest
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [/q1 ON]
+Right click menu skills for F9 are Enabled.[/q1 ON]
+*/
+ MSG_QUICKSPELL_ON = 0x2fd,
+/*20031230 to 20040108
+마우스 우클릭으로 스킬을 사용하지 못합니다 [QUICK OFF]
+20040112 to latest
+마우스 우클릭으로 스킬을 사용하지 못합니다 [/q1 OFF]
+Right click menu skills for F9 are Disabled.[/q1 OFF]
+*/
+ MSG_QUICKSPELL_OFF = 0x2fe,
+/*20031230 to 20040119
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+20040126 to latest
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+/quickspell: Right-click menu enables you to use skills assigned to the F9 hotkey. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL = 0x2ff,
+#endif
+#if PACKETVER >= 20040112
+/*20040112 to latest
+마우스의 WHEEL을 사용해서 F7 과 F8에 저장한 스킬을 사용합니다 [/q2 ON]
+Mouse wheel skills for F7 and F8 are Enabled.[/q2 ON]
+*/
+ MSG_QUICKSPELL2_ON = 0x300,
+/*20040112 to latest
+마우스 WHEEL로 스킬을 사용하지 못합니다 [/q2 OFF]
+Mouse wheel skills for F7 and F8 are Disabled.[/q2 OFF]
+*/
+ MSG_QUICKSPELL2_OFF = 0x301,
+/*20040112 to 20040119
+/quickspell2 : 마우스 WHEEL로 F7 과 F8에 저장한 스킬을 사용합니다 On Off
+20040126 to latest
+/quickspell2 : 마우스 WHEEL을 위,아래로 굴려서 F7과F8에 저장한 스킬을 사용합니다 On Off
+/quickspell2: By rolling the mouse wheel up and down, you are able to use skills registered on F7 and F8 hotkeys. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL2 = 0x302,
+/*20040112 to latest
+/q3 : /quickspell (/q1) + /quickspell2 (/q2)
+*/
+ MSG_EXPLAIN_QUICKSPELL3 = 0x303,
+#endif
+#if PACKETVER >= 20040202
+/*20040202 to latest
+/찌릿
+/bzz
+*/
+ MSG_EMOTION_STARE = 0x304,
+/*20040202 to latest
+/밥
+/rice
+*/
+ MSG_EMOTION_HUNGRY = 0x305,
+/*20040202 to latest
+/멋져
+/awsm
+*/
+ MSG_EMOTION_COOL = 0x306,
+/*20040202 to latest
+/메롱
+/meh
+*/
+ MSG_EMOTION_MERONG = 0x307,
+/*20040202 to latest
+/부끄
+/shy
+*/
+ MSG_EMOTION_SHY = 0x308,
+/*20040202 to latest
+/쓱쓱
+/pat
+*/
+ MSG_EMOTION_GOODBOY = 0x309,
+/*20040202 to latest
+/엠탐
+/mp
+*/
+ MSG_EMOTION_SPTIME = 0x30a,
+/*20040202 to latest
+/질질
+/slur
+*/
+ MSG_EMOTION_SEXY = 0x30b,
+/*20040202 to latest
+/컴온
+/com
+*/
+ MSG_EMOTION_COMEON = 0x30c,
+/*20040202 to latest
+/하품
+/yawn
+*/
+ MSG_EMOTION_SLEEPY = 0x30d,
+/*20040202 to latest
+/축하
+/grat
+*/
+ MSG_EMOTION_CONGRATULATION = 0x30e,
+/*20040202 to latest
+/피탐
+/hp
+*/
+ MSG_EMOTION_HPTIME = 0x30f,
+/*20040202 to latest
+/이모션 : 현재 사용가능한 이모션의 리스트를 보여줍니다.
+/emotion: views the emoticon list.
+*/
+ MSG_EXPLAIN_EMOTION = 0x310,
+#endif
+#if PACKETVER >= 20040223
+/*20040223 to 20040302
+키보드를 이용해서 스킬단축창2 와 3의 스킬들을 사용합니다. [/bm ON]
+20040308 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용합니다. [/bm ON]
+Skills assigned to shortcut windows 1, 2, 3 are Enabled. [/bm ON]
+*/
+ MSG_BATTLE_ON = 0x311,
+/*20040223 to 20040302
+키보드를 이용해서 스킬단축창2 와 3의 스킬들을 사용하지못합니다. [/bm OFF]
+20040308 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용하지못합니다. [/bm OFF]
+Skills assigned to shortcut windows 1, 2, 3 are Disabled. [/bm OFF]
+*/
+ MSG_BATTLE_OFF = 0x312,
+/*20040223 to latest
+/battlemode : Q ~ O 를 누르면 스킬단축창2의 스킬들이 사용됩니다.
+/battlemode: allows you to use skills assigned to Shortcut Window 2 by pressing Q ~ O keys.
+*/
+ MSG_EXPLAIN_BATTLE = 0x313,
+/*20040223 to 20040302
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다. On Off
+20040308 to latest
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다.
+A ~ L keys allow you to use skills assigned to Shortcut Window 3.
+*/
+ MSG_EXPLAIN_BATTLE2 = 0x314,
+/*20040223 to latest
+라그나로크를 실행하실때 다른 프로그램을 띄우시면 게임이 느려질수도있습니다.
+Please remember, programs running in the background while playing may affect the game's performance.
+*/
+ MSG_EXPLAIN_LAG = 0x315,
+#endif
+#if PACKETVER >= 20040302
+/*20040302 to 20041130
+천사님 제 목소리 들리세여? ^^;
+20041206 to latest
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+*/
+ MSG_SUPERNOVICE1 = 0x316,
+/*20040302 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_SUPERNOVICE2 = 0x317,
+/*20040302 to 20041130
+예여~
+20041206 to latest
+예요~
+Super Novice~
+*/
+ MSG_SUPERNOVICE3 = 0x318,
+/*20040302 to 20041130
+저 좀 도와주세여~ ㅠ_ㅠ
+20041206 to latest
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE4 = 0x319,
+#endif
+#if PACKETVER >= 20040308
+/*20040308 to 20041011
+ 입양을 요청해왔습니다. 승낙하시겠습니까?
+20041018 to latest
+님께서 당신을 입양시키고 싶어하십니다. 승낙하시겠습니까?
+ wishes to adopt you. Do you accept?
+*/
+ MSG_SUGGEST_BABY = 0x31a,
+/*20040308 to latest
+ Z ~ > 을 누르면 스킬단축창1의 스킬들이 사용됩니다. On Off
+Z ~ > keys allow you to use skills assigned on shortcut window 1. On | Off
+*/
+ MSG_EXPLAIN_BATTLE3 = 0x31b,
+/*20040308 to latest
+ Space를 한번 누른뒤에 글자를 입력하면 채팅을 할수있습니다.
+Press the space bar to Chat when in Battle mode [/battlemode | /bm].
+*/
+ MSG_EXPLAIN_BATTLE4 = 0x31c,
+/*20040308 to latest
+게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다.
+"Either there's no Game Guard installed on the program or Game Guard is cracked. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_AUTH_GAMEGUARD = 0x31d,
+/*20040308 to latest
+윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다.
+Some of Windows system files have been damaged. Please re-install your Internet Explorer.
+*/
+ MSG_NPGAMEMON_ERROR_CRYPTOAPI = 0x31e,
+/*20040308 to latest
+게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다.
+"Failed to run Game Guard. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_EXECUTE = 0x31f,
+/*20040308 to latest
+불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다.
+"At least one hazardous program has been detected. Please, terminate all the unnecessary programs before executing Game Guard."
+*/
+ MSG_NPGAMEMON_ERROR_ILLEGAL_PRG = 0x320,
+/*20040308 to latest
+게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 방화벽 상태를 점검해보시기 바랍니다.
+"Game Guard update is canceled. If the disconnection continues, please, check your internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_ABORT = 0x321,
+/*20040308 to latest
+게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 인터넷 및 방화벽 상태를 점검해 보시기 바랍니다.
+"Failed to connect to Game Guard update server. Try to connect again later, or try to check the internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_CONNECT = 0x322,
+/*20040308 to latest
+게임가드 업데이트를 완료하지 못 했습니다. 바이러스 검사를 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정한 후 게임을 실행해 보시기 바랍니다.
+"Can't complete Game Guard update process. Please, try to execute a vaccine program to remove viruses. Or, please try to modify the settings of your PC managing tool if you are using any."
+*/
+ MSG_NPGMUP_ERROR_AUTH = 0x323,
+#endif
+#if PACKETVER >= 20040311
+/*20040311 to latest
+/notrade : 거래신청을 자동으로 거절합니다 On Off
+/notrade: Declines trade offers automatically. On | Off
+*/
+ MSG_EXPLAIN_NOTRADE = 0x324,
+/*20040311 to 20040804
+거래신청을 자동으로 거절합니다 [/nt ON]
+20040809 to latest
+거래신청과 친구등록요청을 자동으로 거절합니다 [/nt ON]
+Auto decline trade offers has been Enabled. [/nt ON]
+*/
+ MSG_NOTRADE_ON = 0x325,
+/*20040311 to 20040804
+거래신청을 정상적으로 받습니다 [/nt OFF]
+20040809 to latest
+거래신청과 친구등록요청을 정상적으로 받습니다 [/nt OFF]
+Auto decline trade offers has been Disabled. [/nt OFF]
+*/
+ MSG_NOTRADE_OFF = 0x326,
+#endif
+#if PACKETVER >= 20040329
+/*20040329 to latest
+같은 아이템은 한번에 30000개 이상은 살수 없습니다.
+You cannot buy more than 30,000ea items at once.
+*/
+ MSG_LIMIT_BUY_ITEM = 0x327,
+/*20040329 to latest
+재료가 충분하지 않습니다.
+You do not have enough ingredients.
+*/
+ MSG_NOT_ENOUGH_SOURCE = 0x328,
+#endif
+#if PACKETVER >= 20040419
+/*20040419 to latest
+%s에 계정정보가 남아있습니다.
+Login information remains at %s.
+*/
+ MSG_ALREADY_CONNECT = 0x329,
+#endif
+#if PACKETVER >= 20040423
+/*20040423 to 20040429
+해킹조사에 관련되어 %s 까지 로그인을 금지하고 있습니다.
+20040503 to 20040906
+해킹 관련 조사를 위해 로그인이 금지되 었습니다. 자세한 문의는 해킹관련 메일로 하여주시기 바랍니다.
+20040913 to latest
+계정도용 조사를 위해 로그인이 금지되었습니다. 자세한 문의는 계정도용 관련 문의 메일로 해주시기 바랍니다.
+Account has been locked for a hacking investigation. Please contact the GM Team for more information.
+*/
+ MSG_HACKING_INVESTIGATION = 0x32a,
+/*20040423 to 20040429
+버그조사에 관련되어 %s 까지 로그인을 금지하고 있습니다.
+20040503 to latest
+귀하는 버그관련 조사중이므로 일시적으로 접속을 금합니다
+This account has been temporarily prohibited from login due to a bug-related investigation.
+*/
+ MSG_BUG_INVESTIGATION = 0x32b,
+/*20040423 to latest
+수리가능한 아이템
+Repairable items
+*/
+ MSG_REPAIRITEMLIST = 0x32c,
+#endif
+#if PACKETVER >= 20040426
+/*20040426 to latest
+아이템 수리 성공
+Item has been successfully repaired.
+*/
+ MSG_ITEM_REPAIR_SUCCEESS = 0x32d,
+/*20040426 to latest
+아이템 수리 실패 (재료 또는 상대와의 거리등을 확인해주십시요)
+You have failed to repair this item. Please check the distance between you and opponent.
+*/
+ MSG_ITEM_REPAIR_FAIL = 0x32e,
+#endif
+#if PACKETVER >= 20040531
+/*20040531 to latest
+시스템 상황을 지속적으로 체크 합니다.[운영자모드] [/sc ON]
+System process enabled [GM mode] [/sc ON]
+*/
+ MSG_SYSTEM_CHECK_ON = 0x32f,
+/*20040531 to latest
+시스템 상황을 지속적으로 체크 하지 않습니다.[운영자모드] [/sc OFF]
+System process disabled [GM mode] [/sc OFF]
+*/
+ MSG_SYSTEM_CHECK_OFF = 0x330,
+/*20040531 to latest
+/systemcheck : 시스템 상황을 지속적으로 체크 합니다.[운영자모드]
+/systemcheck: Check the system process [GM mode] On | Off
+*/
+ MSG_EXPLAIN_SYSTEM_CHECK = 0x331,
+#endif
+#if PACKETVER >= 20040614
+/*20040614 to latest
+(%s)님이 친구 신청을 하셨습니다. 친구가 되시겠습니까?
+(%s) wishes to be friends with you. Would you like to accept?
+*/
+ MSG_SUGGEST_JOIN_FRIEND = 0x332,
+#endif
+#if PACKETVER >= 20040621
+/*20040621 to latest
+더 이상 친구 등록을 하실수 없습니다.
+Your Friend List is full.
+*/
+ MSG_FRIEND_ADD_ME_OVERSIZE = 0x333,
+/*20040621 to latest
+(%s)님이 더 이상 친구 등록을 하실수 없습니다.
+(%s)'s Friend List is full.
+*/
+ MSG_FRIEND_ADD_OTHER_OVERSIZE = 0x334,
+/*20040621 to latest
+(%s)님과 친구가 되셨습니다.
+You have become friends with (%s).
+*/
+ MSG_FRIEND_ADD_SUCCEED = 0x335,
+/*20040621 to latest
+(%s)님이 친구 되기를 원하지 않습니다.
+(%s) does not want to be friends with you.
+*/
+ MSG_FRIEND_ADD_FALSE = 0x336,
+/*20040621 to latest
+이 캐릭터는 %s 까지 블럭되어있습니다.
+This character will be blocked to use until %s.
+*/
+ MSG_BLOCKED = 0x337,
+/*20040621 to 20040621
+천만제니이상을 입력하신 아이템은 천만제니로 판매됩니다.
+20040628 to latest
+천만제니 이상 입력하셔도 가격은 천만제니로 판매됩니다.
+Price will be fixed at 10,000,000 zeny, even if you enter higher price.
+*/
+ MSG_OVERPRICE = 0x338,
+#endif
+#if PACKETVER >= 20040628
+/*20040628 to latest
+(적음)
+(Very low)
+*/
+ MSG_LITTLEUSER = 0x339,
+/*20040628 to latest
+(약간 적음)
+(Low)
+*/
+ MSG_ALITTLEUSER = 0x33a,
+/*20040628 to latest
+(보통)
+(Normal)
+*/
+ MSG_NORMLEUSER = 0x33b,
+/*20040628 to latest
+(많음)
+(High)
+*/
+ MSG_MANYUSER = 0x33c,
+/*20040628 to latest
+(매우 많음)
+(Very high)
+*/
+ MSG_VERYMANYUSER = 0x33d,
+/*20040628 to 20040714
+비매너에 의해 GM으로부터 채팅금지가 %d 분간 적용됩니다.
+20040726 to latest
+비매너에 의해 운영자로부터 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d minutes by the GM Team.
+*/
+ MSG_GM_BAD_MANNER_START = 0x33e,
+/*20040628 to latest
+GM에 의한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_REMAIN = 0x33f,
+/*20040628 to latest
+GM에 의한 채팅금지가 해지 되었습니다.
+You have been released from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_END = 0x340,
+/*20040628 to 20040714
+도배 방지 시스템으로 인한 채팅금지가 %d 분간 적용됩니다.
+20040726 to latest
+도배 방지 시스템으로 인한 자동 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d as an automatic penalty.
+*/
+ MSG_AUTO_BAD_MANNER_START = 0x341,
+/*20040628 to latest
+도배 방지 시스템으로 인한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from auto penalty.
+*/
+ MSG_AUTO_BAD_MANNER_REMAIN = 0x342,
+/*20040628 to latest
+도배 방지 시스템으로 인한 채팅금지가 해지되었습니다. 게임진행 시에는 도배에 대해서 주의하여 주시기 바랍니다.
+You have been released from the auto penalty. Please refrain from spamming in-game.
+*/
+ MSG_AUTO_BAD_MANNER_END = 0x343,
+/*20040628 to latest
+%s님과 %s님이 이혼하셨습니다.
+%s and %s have divorced from each other.
+*/
+ MSG_DIVORCE = 0x344,
+#endif
+#if PACKETVER >= 20040705
+/*20040705 to 20041108
+星鬪士 %s의 태양의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE1 = 0x345,
+/*20040705 to 20041108
+星鬪士 %s의 달의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE2 = 0x346,
+/*20040705 to 20041108
+星鬪士 %s의 별의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Space.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE3 = 0x347,
+/*20040705 to 20040726
+星鬪士 %s의 태양의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 태양의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 장소는 %s 입니다
+Gravity %s's Solar Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 장소는 %s 입니다
+*/
+ MSG_STARPLACE4 = 0x348,
+/*20040705 to 20040726
+星鬪士 %s의 달의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 달의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 장소는 %s 입니다
+Gravity %s's Luna Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 장소는 %s 입니다
+*/
+ MSG_STARPLACE5 = 0x349,
+/*20040705 to 20040726
+星鬪士 %s의 별의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 별의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 장소는 %s 입니다
+Gravity %s's Stellar Space: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 장소는 %s 입니다
+*/
+ MSG_STARPLACE6 = 0x34a,
+#endif
+#if PACKETVER >= 20040706
+/*20040706 to 20041108
+星鬪士 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER1 = 0x34b,
+/*20040706 to 20041108
+星鬪士 %s의 달의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER2 = 0x34c,
+/*20040706 to 20041108
+星鬪士 %s의 별의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Monster.
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER3 = 0x34d,
+/*20040706 to 20040726
+星鬪士 %s의 태양의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 태양의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 몬스터는 %s 입니다
+Gravity %s's Solar Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 태양의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER4 = 0x34e,
+/*20040706 to 20040726
+星鬪士 %s의 달의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 달의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 몬스터는 %s 입니다
+Gravity %s's Luna Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 달의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER5 = 0x34f,
+/*20040706 to 20040726
+星鬪士 %s의 별의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 별의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 몬스터는 %s 입니다
+Gravity %s's Stellar Monster: %s
+20041220 to 20050816
+태양과 달과 별의 전사 %s의 별의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER6 = 0x350,
+#endif
+#if PACKETVER >= 20040707
+/*20040707 to latest
+/window : 창 위치 이동시 다른 창과 달라붙는 속성이 들어갑니다 On Off
+/window: Display windows will snap/dock together. On | Off
+*/
+ MSG_EXPLAIN_WINDOW = 0x351,
+/*20040707 to latest
+창 위치 이동시 다른 창과 잘 붙습니다 [/wi ON]
+Display window docking enabled. [/wi ON]
+*/
+ MSG_WINDOW_ON = 0x352,
+/*20040707 to latest
+창 위치 이동시 다른 창과 붙으려는 속성을 가지지 않습니다 [/wi OFF]
+Display window docking disabled. [/wi OFF]
+*/
+ MSG_WINDOW_OFF = 0x353,
+#endif
+#if PACKETVER >= 20040712
+/*20040712 to latest
+/pvpinfo : 자신의 PVP 승패와 PVP 포인트를 알 수 있습니다.
+/pvpinfo: shows your PVP result and PVP points.
+*/
+ MSG_EXPLAIN_PVP_INFO = 0x354,
+/*20040712 to latest
+현재 %d승, %d패, PVP포인트는 %d입니다.
+You have won %d times and have lost %d times in PVP. Current points %d.
+*/
+ MSG_PVP_INFO = 0x355,
+#endif
+#if PACKETVER >= 20040726
+/*20040726 to latest
+매너 포인트를 성공적으로 보냈습니다.
+A manner point has been successfully aligned.
+*/
+ MSG_SEND_MANNER_POINT = 0x356,
+#endif
+#if PACKETVER >= 20040809
+/*20040809 to latest
+현재 이곳은 PK 가능 지역입니다. 불의의 공격에 유의 하시기 바랍니다.
+You are in a PK area. Please beware of sudden attack.
+*/
+ MSG_PKZONE = 0x357,
+#endif
+#if PACKETVER >= 20040817
+/*20040817 to latest
+게임가드 업데이트가 바이러스나 스파이웨어와의 충돌로 실패했습니다. 백신 프로그램/스파이웨어 제거 프로그램을 사용한 후 접속해 주십시기 바랍니다
+Game Guard update has been failed when either Virus or Spyware conflicted with. Please, Uninstall Spyware and Virus protection program before you log in.
+*/
+ MSG_NPGAMEMON_ERROR_100ERROR = 0x358,
+#endif
+#if PACKETVER >= 20040823
+/*20040823 to latest
+윈도우 호환성 문제로 프로그램을 종료합니다. 게임을 다시 실행해 주시기 바랍니다
+Program has encountered an error related to Windows compatibility. Please start the game again.
+*/
+ MSG_NPGAMEMON_XP_COMPATIBILITY = 0x359,
+#endif
+#if PACKETVER >= 20040906
+/*20040906 to latest
+채팅, 스킬, 아이템을 사용할수없게 되었습니다.
+You have been blocked from chatting, using skills and items.
+*/
+ MSG_PK_HONOR = 0x35a,
+/*20040906 to latest
+캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while this character is being deleted.
+*/
+ MSG_DELETING_CHAR = 0x35b,
+/*20040906 to latest
+결혼 상대자의 캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while your spouse character is being deleted.
+*/
+ MSG_DELETING_SPOUSE_CHAR = 0x35c,
+#endif
+#if PACKETVER >= 20040913
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE = 0x35d,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN = 0x35e,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN = 0x35f,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER = 0x360,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE = 0x361,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT = 0x362,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF = 0x363,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT = 0x364,
+/*20040913 to 20181128
+Prieset
+Priest
+20181205 to latest
+Priest
+*/
+ MSG_PRIEST = 0x365,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD = 0x366,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH = 0x367,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER = 0x368,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN = 0x369,
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE_W = 0x36a,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN_W = 0x36b,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN_W = 0x36c,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER_W = 0x36d,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE_W = 0x36e,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT_W = 0x36f,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF_W = 0x370,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT_W = 0x371,
+/*20040913 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST_W = 0x372,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD_W = 0x373,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH_W = 0x374,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER_W = 0x375,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN_W = 0x376,
+#endif
+#if PACKETVER >= 20041018
+/*20041018 to latest
+(%s)님을 아이로 입양신청
+Send an adoption request to %s
+*/
+ MSG_REQ_JOIN_BABY = 0x377,
+/*20041018 to 20041025
+아이가 되시면 전승을 하실수 없게 됩니다. 그래도 괜찮습니까?
+20041101 to latest
+아이가 되면 전승을 할수없고 스텟은 80이상 올릴수없게되며 HP와 SP가 줄어듭니다. 그래도 괜찮습니까?
+When you become a child, you will be unable to become a Transcendent Class character, all stats will be limited to a maximum of 80, and Max HP/SP will be reduced. Are you sure that you want to be adopted?
+*/
+ MSG_SUGGEST_BABY2 = 0x378,
+#endif
+#if PACKETVER >= 20041101
+/*20041101 to latest
+모든 나쁜 상태이상이 제거 되었습니다.
+All abnormal status effects have been removed.
+*/
+ MSG_GOSPEL1 = 0x379,
+/*20041101 to latest
+1분간 모든 상태이상에 대해 면역이 됩니다.
+You will be immune to abnormal status effects for the next minute.
+*/
+ MSG_GOSPEL2 = 0x37a,
+/*20041101 to latest
+1분간 최대 생명력이 크게 늘어납니다.
+Your Max HP will stay increased for the next minute.
+*/
+ MSG_GOSPEL3 = 0x37b,
+/*20041101 to latest
+1분간 최대 마법력이 크게 늘어납니다.
+Your Max SP will stay increased for the next minute.
+*/
+ MSG_GOSPEL4 = 0x37c,
+/*20041101 to latest
+1분간 모든 능력이 크게 상승합니다.
+All of your Stats will stay increased for the next minute.
+*/
+ MSG_GOSPEL5 = 0x37d,
+/*20041101 to latest
+1분간 사용하는 무기에 성스러운 속성이 부여됩니다.
+Your weapon will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL6 = 0x37e,
+/*20041101 to latest
+1분간 사용하는 갑옷에 성스러운 속성이 부여됩니다.
+Your armor will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL7 = 0x37f,
+/*20041101 to latest
+10초간 방어력이 크게 상승합니다.
+Your Defense will stay increased for the next 10 seconds.
+*/
+ MSG_GOSPEL8 = 0x380,
+/*20041101 to latest
+1분간 공격력이 크게 증가합니다.
+Your Attack strength will be increased for the next minute.
+*/
+ MSG_GOSPEL9 = 0x381,
+/*20041101 to latest
+1분간 명중률과 회피율이 크게 상승합니다.
+Your Accuracy and Flee Rate will be increased for the next minute.
+*/
+ MSG_GOSPEL10 = 0x382,
+#endif
+#if PACKETVER >= 20041108
+/*20041108 to latest
+아이를 한번 입양했던 부부는 추가 입양이 불가능합니다.
+You cannot adopt more than 1 child.
+*/
+ MSG_BABY1 = 0x383,
+/*20041108 to latest
+부부가 둘다 레벨70이 넘어야 아이를 입양할수있습니다.
+You must be at least character level 70 in order to adopt someone.
+*/
+ MSG_BABY2 = 0x384,
+/*20041108 to 20041108
+블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Blacksmith rank points. Your point total is %d.
+*/
+ MSG_BLACKSMITH_POINT = 0x385,
+/*20041108 to 20041108
+알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Alchemist rank points. Your point total is %d.
+*/
+ MSG_ALCHEMIST_POINT = 0x386,
+#endif
+#if PACKETVER >= 20041115
+/*20041115 to 20041130
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE11 = 0x387,
+/*20041115 to 20041130
+슈퍼노비스
+Super Novice
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE12 = 0x388,
+/*20041115 to 20041130
+예요~
+Super Novice~
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE13 = 0x389,
+/*20041115 to 20041130
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE14 = 0x38a,
+/*20041115 to latest
+/notalkmsg2 : 채팅내용을 채팅창에 표시하지 않습니다 (길드말 포함) On Off
+/notalkmsg2: Hides chat messages(including guild chat). On Off
+*/
+ MSG_EXPLAIN_NOTALKMSG2 = 0x38b,
+/*20041115 to latest
+채팅내용을 채팅창에 표시합니다 [/nm2 ON]
+Show chat messages. [/nm2 ON]
+*/
+ MSG_NOTALKMSG2_ON = 0x38c,
+/*20041115 to latest
+채팅내용을 채팅창에 표시하지않습니다 (길드말 포함) [/nm2 OFF]
+Hide chat messages(including guild chat) [/nm2 OFF]
+*/
+ MSG_NOTALKMSG2_OFF = 0x38d,
+#endif
+#if PACKETVER >= 20041129
+/*20041129 to latest
+제련가능한 아이템
+Upgradable Weapons
+*/
+ MSG_REFINEITEMLIST = 0x38e,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_SUCCEESS = 0x38f,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_FAIL = 0x390,
+/*20041129 to latest
+무기제련스킬의 레벨이 부족해서 %s 제련을 할수없습니다.
+You cannot upgrade %s until you level up your Upgrade Weapon skill.
+*/
+ MSG_ITEM_REFINE_FAIL_LEVEL = 0x391,
+/*20041129 to latest
+제련에 필요한 아이템 (%s) 이 없으므로 제련할수없습니다.
+You lack a necessary item %s to upgrade this weapon.
+*/
+ MSG_ITEM_REFINE_FAIL_MATERIAL = 0x392,
+#endif
+#if PACKETVER >= 20041206
+/*20041206 to latest
+완벽하게 코팅되어있어서 풀스트립이 통하지 않습니다.
+Full Divestment cannot pierce the target. The target is fully shielded.
+*/
+ MSG_FULLSTRIP = 0x393,
+#endif
+#if PACKETVER >= 20041213
+/*20041213 to latest
+결혼한 캐릭터는 입양시킬수 없습니다.
+You cannot adopt a married person.
+*/
+ MSG_BABY3 = 0x394,
+#endif
+#if PACKETVER >= 20041220
+/*20041220 to latest
+친구로 등록된 이름과 비슷하지만 등록된 이름이 아닙니다. 아는사람인지 확인하십시요.
+This name is not registered in your Friend List. Please check the name again.
+*/
+ MSG_ID_WARNING = 0x395,
+/*20041220 to latest
+/hi 또는 /hi 문장 : 친구로 등록된 캐릭터들에게 인사를 합니다.
+/hi or /hi message: Send greetings to people who are online and registered on your Friend List.
+*/
+ MSG_EXPLAIN_HI = 0x396,
+#endif
+#if PACKETVER >= 20041227
+/*20041227 to latest
+길드원의 이름과 비슷하지만 길드원이 아닙니다. 길드원인지 확인하십시요.
+This character is not your guildsman. Please check the name again.
+*/
+ MSG_ID_WARNING_GUILD = 0x397,
+#endif
+#if PACKETVER >= 20050117
+/*20050117 to latest
+9999만제니 이상 입력하셔도 가격은 9999만제니로 판매됩니다.
+Please be aware that the maximum selling price is fixed as 2 Billion. You cannot sell an item higher than that.
+*/
+ MSG_OVERPRICE9999 = 0x398,
+#endif
+#if PACKETVER >= 20050131
+/*20050131 to latest
+친구의 귓속말은 [ Friend ] , 길드원은 [ Member ] 로 표시됩니다.
+Whispers from friends are displayed as [ Friend ], and ones from guildsmen are displayed as [ Member ].
+*/
+ MSG_EXPLAIN_SACHING1 = 0x399,
+/*20050131 to latest
+( From 캐릭터이름 : ) 이라고 표시 되는 귓속말은 친구나 길드원이 아닙니다.
+( From character name: ) is from an anonymous character who is neither your friend nor guildsman.
+*/
+ MSG_EXPLAIN_SACHING2 = 0x39a,
+#endif
+#if PACKETVER >= 20050214
+/*20050214 to 20050310
+블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/blacksmith : 블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+/blacksmith: Shows top 10 Blacksmiths in the server.
+*/
+ MSG_EXPLAIN_BLACKSMITH = 0x39b,
+/*20050214 to 20050310
+알케미스트의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/alchemist : 알케미스트의 상위 10위권 랭킹을 보여줍니다.
+/alchemist: Shows top 10 Alchemists in the server.
+*/
+ MSG_EXPLAIN_ALCHEMIST = 0x39c,
+/*20050214 to latest
+ALT+Y : 여러가지 명령어를 쉽게 쓸수있는 윈도우가 열립니다.
+ALT+Y: Opens a window which allows you to use various commands with ease.
+*/
+ MSG_EXPLAIN_ALTY = 0x39d,
+#endif
+#if PACKETVER >= 20050328
+/*20050328 to latest
+[POINT] 태권미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Tae-Kwon Mission rank points. Your point total is %d.
+*/
+ MSG_TAEKWON_POINT = 0x39e,
+#endif
+#if PACKETVER >= 20050404
+/*20050404 to latest
+[태권미션] Target Monster : %s (%d%%)
+[Taekwon Mission] Target Monster: %s (%d%%)
+*/
+ MSG_TAEKWON_MISSION = 0x39f,
+#endif
+#if PACKETVER >= 20050502
+/*20050502 to latest
+게임가드 초기화 에러 : %lu
+Error - Failed to initialize GameGuard: %lu
+*/
+ MSG_INIT_ERROR = 0x3a0,
+/*20050502 to latest
+스피드핵이 감지되었습니다.
+Speed Hack has been detected.
+*/
+ MSG_SPEEDHACK_DETECT = 0x3a1,
+/*20050502 to latest
+불법 프로그램 (%s) 가 발견되었습니다
+The illegal program, (%s) has been detected.
+*/
+ MSG_GAMEHACK_DETECT = 0x3a2,
+/*20050502 to latest
+게임이나 게임가드가 변조되었습니다.
+The Game or Gameguard has been cracked.
+*/
+ MSG_GAMEHACK_DOUBT = 0x3a3,
+/*20050502 to latest
+게임가드가 실행 중 입니다. 잠시 후에 다시 실행해보시기 바랍니다.
+GameGuard is currently running. Please wait for sometime and restart the game.
+*/
+ MSG_ERROR_EXIST = 0x3a4,
+/*20050502 to latest
+게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다.
+The Game or GameGuard is already running. Please close the game and restart the game.
+*/
+ MSG_GAME_EXIST = 0x3a5,
+/*20050502 to latest
+게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다.
+Failed to intialize GameGuard. Please try again after rebooting the system or closing other programs.
+*/
+ MSG_ERROR_INIT = 0x3a6,
+/*20050502 to latest
+바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다.
+Failed to load the scan module of virus and hacking tool. It's caused by lack of memory or PC virus infection.
+*/
+ MSG_ERROR_NPSCAN = 0x3a7,
+#endif
+#if PACKETVER >= 20050509
+/*20050509 to latest
+호문클루스 정보
+Homunculus Info
+*/
+ MSG_HOMUN_INFO = 0x3a8,
+#endif
+#if PACKETVER >= 20050523
+/*20050523 to latest
+호문클루스 스킬목록
+Homunculus Skill List
+*/
+ MSG_HOMUN_SKILLLIST = 0x3a9,
+/*20050523 to latest
+호문클루스의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Please give your Homunculus a name no longer than 23 letters.
+*/
+ MSG_HOMUN_NAME_IN23 = 0x3aa,
+/*20050523 to latest
+이름은 단 한번만 바꿀수 있습니다. 호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You can name a Homunculus only once. You have entered the name, ^0000ff%s^000000. Would you like to continue?
+*/
+ MSG_HOMUN_NAME_CHANGE_ONLYONCE = 0x3ab,
+/*20050523 to latest
+지금은 부재중~
+(Away)
+*/
+ MSG_AUTO_MSG = 0x3ac,
+/*20050523 to latest
+[자동응답]
+[Automated Message]
+*/
+ MSG_AUTO_MSG2 = 0x3ad,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답합니다.
+Send an automated message while you are away.
+*/
+ MSG_AUTO_MSG_ON = 0x3ae,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답하지 않습니다.
+Cancel automated away message.
+*/
+ MSG_AUTO_MSG_OFF = 0x3af,
+/*20050523 to latest
+자동 응답 메시지를 입력하세요.
+Please enter Away Message.
+*/
+ MSG_ENTER_AUTO_MSG = 0x3b0,
+#endif
+#if PACKETVER >= 20050530
+/*20050530 to latest
+/번쩍
+/fsh
+*/
+ MSG_EMOTION_SPARK = 0x3b1,
+/*20050530 to latest
+/빙빙
+/spin
+*/
+ MSG_EMOTION_CONFUSE = 0x3b2,
+/*20050530 to latest
+/하아
+/sigh
+*/
+ MSG_EMOTION_OHNO = 0x3b3,
+/*20050530 to latest
+/덤덤
+/dum
+*/
+ MSG_EMOTION_HUM = 0x3b4,
+/*20050530 to latest
+/시끌
+/crwd
+*/
+ MSG_EMOTION_BLABLA = 0x3b5,
+/*20050530 to latest
+/좌절
+/desp
+*/
+ MSG_EMOTION_OTL = 0x3b6,
+/*20050530 to latest
+/주사위
+/dice
+*/
+ MSG_EMOTION_DICE = 0x3b7,
+/*20050530 to latest
+/pk : 학살자의 상위 10위권 랭킹을 보여줍니다.
+/pk: Shows top 10 Slayers in the server.
+*/
+ MSG_EXPLAIN_KILLER_RANK = 0x3b8,
+/*20050530 to latest
+[POINT] 학살자 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Slayer rank points. Your point total is %d.
+*/
+ MSG_KILLER_POINT = 0x3b9,
+#endif
+#if PACKETVER >= 20050608
+/*20050608 to latest
+진화 가능
+Evolution Available
+*/
+ MSG_HOMUN_EVOLVE = 0x3ba,
+/*20050608 to latest
+^ff0000^ff0000호문클루스를 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+You have decided to delete this Homunculus ^ff0000^ff0000. When deleted, the homunculus and its history will be deleted and they cannot be restored in the future. Would you like to continue?
+*/
+ MSG_DELETE_HOMUN = 0x3bb,
+#endif
+#if PACKETVER >= 20050613
+/*20050613 to latest
+호문의 상태를 파일에 저장합니다.
+Save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_ON = 0x3bc,
+/*20050613 to latest
+호문의 상태를 파일에 저장하지 않습니다.
+Do not save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_OFF = 0x3bd,
+/*20050613 to latest
+Crusader
+*/
+ MSG_CRUSADER = 0x3be,
+/*20050613 to latest
+Monk
+*/
+ MSG_MONK = 0x3bf,
+/*20050613 to latest
+Sage
+*/
+ MSG_SAGE = 0x3c0,
+/*20050613 to latest
+Rouge
+Rogue
+*/
+ MSG_ROGUE = 0x3c1,
+/*20050613 to latest
+Alchemist
+*/
+ MSG_ALCHEMIST = 0x3c2,
+/*20050613 to latest
+Bard
+*/
+ MSG_BARD = 0x3c3,
+/*20050613 to latest
+Crusader_W
+Crusader
+*/
+ MSG_CRUSADER_W = 0x3c4,
+/*20050613 to latest
+Monk_W
+Monk
+*/
+ MSG_MONK_W = 0x3c5,
+/*20050613 to latest
+Sage_W
+Sage
+*/
+ MSG_SAGE_W = 0x3c6,
+/*20050613 to latest
+Rouge_W
+Rogue
+*/
+ MSG_ROGUE_W = 0x3c7,
+/*20050613 to latest
+Alchemist_W
+Alchemist
+*/
+ MSG_ALCHEMIST_W = 0x3c8,
+/*20050613 to latest
+Dancer
+*/
+ MSG_DANCER = 0x3c9,
+/*20050613 to latest
+Novice High
+High Novice
+*/
+ MSG_NOVICE_H = 0x3ca,
+/*20050613 to latest
+Swordman High
+High Swordman
+*/
+ MSG_SWORDMAN_H = 0x3cb,
+/*20050613 to latest
+Magician High
+High Mage
+*/
+ MSG_MAGICIAN_H = 0x3cc,
+/*20050613 to latest
+Archer High
+High Archer
+*/
+ MSG_ARCHER_H = 0x3cd,
+/*20050613 to latest
+Acolyte High
+High Acolyte
+*/
+ MSG_ACOLYTE_H = 0x3ce,
+/*20050613 to latest
+Merchant High
+High Merchant
+*/
+ MSG_MERCHANT_H = 0x3cf,
+/*20050613 to latest
+Thief High
+High Thief
+*/
+ MSG_THIEF_H = 0x3d0,
+/*20050613 to latest
+Novice High_W
+High Novice
+*/
+ MSG_NOVICE_H_W = 0x3d1,
+/*20050613 to latest
+Swordman High_W
+High Swordman
+*/
+ MSG_SWORDMAN_H_W = 0x3d2,
+/*20050613 to latest
+Magician High_W
+High Mage
+*/
+ MSG_MAGICIAN_H_W = 0x3d3,
+/*20050613 to latest
+Archer High_W
+High Archer
+*/
+ MSG_ARCHER_H_W = 0x3d4,
+/*20050613 to latest
+Acolyte High_W
+High Acolyte
+*/
+ MSG_ACOLYTE_H_W = 0x3d5,
+/*20050613 to latest
+Merchant High_W
+High Merchant
+*/
+ MSG_MERCHANT_H_W = 0x3d6,
+/*20050613 to latest
+Thief High_W
+High Thief
+*/
+ MSG_THIEF_H_W = 0x3d7,
+/*20050613 to latest
+Lord Knight
+*/
+ MSG_KNIGHT_H = 0x3d8,
+/*20050613 to latest
+High Priest
+*/
+ MSG_PRIEST_H = 0x3d9,
+/*20050613 to latest
+High Wizard
+*/
+ MSG_WIZARD_H = 0x3da,
+/*20050613 to latest
+White Smith
+MasterSmith
+*/
+ MSG_BLACKSMITH_H = 0x3db,
+/*20050613 to latest
+Sniper
+*/
+ MSG_HUNTER_H = 0x3dc,
+/*20050613 to 20181128
+Saaassin Cross
+Assassin Cross
+20181205 to latest
+Assassin Cross
+*/
+ MSG_ASSASSIN_H = 0x3dd,
+/*20050613 to latest
+Lord Knight_W
+Lord Knight
+*/
+ MSG_KNIGHT_H_W = 0x3de,
+/*20050613 to latest
+High Priest_W
+High Priest
+*/
+ MSG_PRIEST_H_W = 0x3df,
+/*20050613 to latest
+High Wizard_W
+High Wizard
+*/
+ MSG_WIZARD_H_W = 0x3e0,
+/*20050613 to latest
+White Smith_W
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H_W = 0x3e1,
+/*20050613 to latest
+Sniper_W
+Sniper
+*/
+ MSG_HUNTER_H_W = 0x3e2,
+/*20050613 to 20181128
+Saaassin Cross_W
+Assassin Cross
+20181205 to latest
+Assassin Cross_W
+*/
+ MSG_ASSASSIN_H_W = 0x3e3,
+/*20050613 to latest
+Paladin
+*/
+ MSG_CRUSADER_H = 0x3e4,
+/*20050613 to latest
+Champion
+*/
+ MSG_MONK_H = 0x3e5,
+/*20050613 to latest
+Professor
+Scholar
+*/
+ MSG_SAGE_H = 0x3e6,
+/*20050613 to latest
+Stalker
+*/
+ MSG_ROGUE_H = 0x3e7,
+/*20050613 to latest
+Creator
+Biochemist
+*/
+ MSG_ALCHEMIST_H = 0x3e8,
+/*20050613 to latest
+Clown
+Minstrel
+*/
+ MSG_BARD_H = 0x3e9,
+/*20050613 to latest
+Paladin_W
+Paladin
+*/
+ MSG_CRUSADER_H_W = 0x3ea,
+/*20050613 to latest
+Champion_W
+Champion
+*/
+ MSG_MONK_H_W = 0x3eb,
+/*20050613 to latest
+Professor_W
+Professor
+*/
+ MSG_SAGE_H_W = 0x3ec,
+/*20050613 to latest
+Stalker_W
+Stalker
+*/
+ MSG_ROGUE_H_W = 0x3ed,
+/*20050613 to latest
+Creator_W
+Creator
+*/
+ MSG_ALCHEMIST_H_W = 0x3ee,
+/*20050613 to latest
+Gypsy
+*/
+ MSG_DANCER_H = 0x3ef,
+/*20050613 to latest
+비밀번호가 지정되어 있지 않습니다. 새로운 비밀번호를 지정하시겠습니까?
+You have not set a password yet. Would you like to create one now?
+*/
+ MSG_STORE_PASSWORD_REQ = 0x3f0,
+/*20050613 to latest
+비밀번호를 3회 틀려셨습니다. 나중에 다시 시도해 주세요.
+You have incorrectly entered the password 3 times. Please try again later.
+*/
+ MSG_STORE_PASSWORD_PENALTY = 0x3f1,
+/*20050613 to latest
+비밀번호 변경이 실패하였습니다.
+Password creation has failed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_NG = 0x3f2,
+/*20050613 to latest
+비밀번호는 4자리 이상 8자리이하여야만 합니다.
+Password must be 4~8 letters long.
+*/
+ MSG_STORE_PASSWORD_4_8 = 0x3f3,
+/*20050613 to latest
+비밀번호
+Password
+*/
+ MSG_STORE_PASSWORD = 0x3f4,
+/*20050613 to latest
+신규 비밀번호
+New Password
+*/
+ MSG_STORE_NEW_PASSWORD = 0x3f5,
+/*20050613 to latest
+확인 비밀번호
+Confirm Password
+*/
+ MSG_STORE_RENEW_PASSWORD = 0x3f6,
+/*20050613 to latest
+비밀번호 변경이 완료되었습니다.
+Password has been changed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_OK = 0x3f7,
+/*20050613 to latest
+비밀번호가 서로 다릅니다.
+Password does not match.
+*/
+ MSG_STORE_PASSWORD_MISMATCH = 0x3f8,
+/*20050613 to latest
+비밀번호 입력
+Enter Password
+*/
+ MSG_STORE_PASSWORD_INPUT = 0x3f9,
+#endif
+#if PACKETVER >= 20050624
+/*20050624 to 20050624
+호문이 아사 직전입니다!!! 밥좀 주셈~!!
+20050628 to latest
+호문이 아사 직전입니다! 먹이를 주지 않으면 가출하게됩니다.
+Your Homunculus is starving. Please feed it, otherwise it will leave you.
+*/
+ MSG_HOMUN_HUNGRY = 0x3fa,
+/*20050624 to latest
+경험치
+EXP
+*/
+ MSG_HOMUN_EXP = 0x3fb,
+#endif
+#if PACKETVER >= 20050628
+/*20050628 to 20110526
+[EVENT] 이벤트에 당첨되셨습니다. 게임내에서 아이템을 지급받으십시요.
+20110531 to latest
+수령하지 않은 아이템이 존재합니다. 알베르타의 존다 기획사 직원을 찾아주세요. ^ff0000※ 아이템 수령 기간이 지나면 아이템이 소실 됩니다!^000000
+[EVENT] You have won an event prize. Please claim your prize in game.
+*/
+ MSG_EVENT_RESULT = 0x3fc,
+#endif
+#if PACKETVER >= 20050704
+/*20050704 to latest
+싫어함
+Hate
+*/
+ MSG_HATE = 0x3fd,
+/*20050704 to 20050704
+매우 싫어함
+20050711 to latest
+매우싫어함
+Hate with a Passion
+*/
+ MSG_VERYHATE = 0x3fe,
+#endif
+#if PACKETVER >= 20050718
+/*20050718 to latest
+호문클루스가 사용자 인공지능으로 동작합니다.
+Homunculus has been customized.
+*/
+ MSG_HOMUN_USERAI_ON = 0x3ff,
+/*20050718 to latest
+호문클루스가 기본 인공지능으로 동작합니다.
+Homunculus has been activated with the basic AI.
+*/
+ MSG_HOMUN_USERAI_OFF = 0x400,
+#endif
+#if PACKETVER >= 20050808
+/*20050808 to latest
+편지목록
+Mail List
+*/
+ MSG_MAIL_LIST = 0x401,
+/*20050808 to latest
+편지쓰기
+Write Mail
+*/
+ MSG_MAIL_WRITE = 0x402,
+/*20050808 to latest
+편지읽기
+Read Mail
+*/
+ MSG_MAIL_READ = 0x403,
+#endif
+#if PACKETVER >= 20050822
+/*20050822 to latest
+한번 지정하시면 변경이 불가능합니다! 이 맵으로 지정하시겠습니까?
+You cannot change a map's designation once it is designated. Are you sure that you want to designate this map?
+*/
+ MSG_STARPLACE_ACCEPT = 0x404,
+/*20050822 to 20050822
+보내실 아이템이 추가 되었습니다.
+20050829 to 20051018
+아이템창에 아이템이 추가 되었습니다.
+20051024 to latest
+메일 아이템을 수령했습니다.
+Item has been added in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_SUCCESS = 0x405,
+/*20050822 to 20050822
+보내실 아이템이 추가 되지 않았습니다.
+20050829 to 20051018
+아이템창에 아이템이 추가 되지 않았습니다.
+20051024 to latest
+메일 아이템을 수령하지 못했습니다.
+You have failed to add the item in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_FAILURE = 0x406,
+/*20050822 to latest
+메일 보내기가 성공하였습니다.
+You have successfully mailed a message.
+*/
+ MSG_MAIL_SEND_SUCCESS = 0x407,
+/*20050822 to latest
+메일 보내기가 실패하였습니다. 받는 사람이 존재하지 않습니다.
+You have failed to mail a message. Recipient does not exist.
+*/
+ MSG_MAIL_USER_NOT_FOUND = 0x408,
+#endif
+#if PACKETVER >= 20050829
+/*20050829 to latest
+[태양과 달과 별의 천사] 지정했던 장소들과 몬스터들이 초기화됐습니다!
+[Solar, Lunar and Stellar Angel] Designated places and monsters have been reset.
+*/
+ MSG_STAR_ANGEL = 0x409,
+/*20050829 to latest
+경매 등록이 실패했습니다.
+The minimum starting bid for auctions is 10,000,000 zeny.
+*/
+ MSG_AUCTION_ADD_FALSE = 0x40a,
+/*20050829 to latest
+경매 등록이 성공했습니다.
+You have successfully started a new auction.
+*/
+ MSG_AUCTION_ADD_TRUE = 0x40b,
+/*20050829 to latest
+해당 경매가 취소되었습니다.
+The auction has been canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL = 0x40c,
+/*20050829 to latest
+입찰자가 있는 경매는 취소할 수 없습니다.
+An auction with at least one bidder cannot be canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL_FALSE = 0x40d,
+#endif
+#if PACKETVER >= 20050905
+/*20050905 to latest
+메일 삭제가 성공하였습니다.
+Mail has been successfully deleted.
+*/
+ MSG_MAIL_DELETE_SUCCESS = 0x40e,
+/*20050905 to latest
+메일 삭제가 실패하였습니다.
+You have failed to delete the mail.
+*/
+ MSG_MAIL_DELETE_FAILURE = 0x40f,
+#endif
+#if PACKETVER >= 20050912
+/*20050912 to latest
+던지는 단검이 장착되었습니다.
+You have equipped throwing daggers.
+*/
+ MSG_MSG_KNIFE_EQUIPMENT_SUCCESS = 0x410,
+#endif
+#if PACKETVER >= 20050926
+/*20050926 to latest
+%s 님이 로그인했습니다.
+%s has logged in.
+*/
+ MSG_LOGIN_FRIEND = 0x411,
+/*20050926 to latest
+%s 님이 로그아웃했습니다.
+%s has logged out.
+*/
+ MSG_LOGOUT_FRIEND = 0x412,
+#endif
+#if PACKETVER >= 20051004
+/*20051004 to latest
+/loginout : 길드원과 친구들의 접속관련 메세지를 보여줍니다. On Off
+/loginout: Shows guildsmen and friends online status. On Off
+*/
+ MSG_EXPLAIN_LOGINOUT = 0x413,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시합니다. [/li ON]
+Display online status of friends in Chat Window. [/li ON]
+*/
+ MSG_LOGINOUT_ON = 0x414,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시하지않습니다. [/li OFF]
+Do not display online status of friends in Chat Window. [/li OFF]
+*/
+ MSG_LOGINOUT_OFF = 0x415,
+/*20051004 to latest
+이미 실행중입니다.
+It is already running.
+*/
+ MSG_SGP_CODE_ALREADY_RUNNING = 0x416,
+/*20051004 to latest
+매크로 사용이 감지되었습니다.
+Use of Macro program has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MACRO = 0x417,
+/*20051004 to latest
+스피드해킹이 감지되었습니다.
+Use of Speed hack has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_SPEEDHACK = 0x418,
+/*20051004 to latest
+API 후킹이 감지되었습니다.
+API Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_APIHOOK = 0x419,
+/*20051004 to latest
+메시지 후킹이 감지되었습니다.
+Message Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MSGHOOK = 0x41a,
+/*20051004 to latest
+모듈이 변조 또는 손상되었거나 버전이 일치하지 않습니다.
+Module has been modified or damaged or its version does not match.
+*/
+ MSG_SGP_CODE_NOT_EQUALENCRYPTEDDATA = 0x41b,
+#endif
+#if PACKETVER >= 20051010
+/*20051010 to latest
+(태국)귀하는 게임방 과금으로 로그인 하셨습니다.
+(Thailand) You have logged in game with PC cafe payment.
+*/
+ MSG_BILLING_PCB = 0x41c,
+#endif
+#if PACKETVER >= 20051017
+/*20051017 to latest
+이전
+Prev
+*/
+ MSG_PREV_PAGE = 0x41d,
+/*20051017 to latest
+다음
+Next
+*/
+ MSG_NEXT_PAGE = 0x41e,
+/*20051017 to latest
+경매
+Auction
+*/
+ MSG_AUCTION = 0x41f,
+/*20051017 to latest
+물품보기
+Product List
+*/
+ MSG_AUCTION_VIEW = 0x420,
+/*20051017 to latest
+등록하기
+Register
+*/
+ MSG_AUCTION_ADD = 0x421,
+/*20051017 to latest
+판매 진행상태
+Sale Status
+*/
+ MSG_AUCTION_SELL = 0x422,
+/*20051017 to latest
+구매 진행상태
+Purchase Status
+*/
+ MSG_AUCTION_BUY = 0x423,
+/*20051017 to latest
+아이템
+Item
+*/
+ MSG_ITEM2 = 0x424,
+/*20051017 to latest
+아이템명
+Name
+*/
+ MSG_ITEM_NAME2 = 0x425,
+/*20051017 to latest
+가격 / 즉시구입가격
+Current Bid / Max Bid
+*/
+ MSG_ITEM_PRICE = 0x426,
+/*20051017 to latest
+판매자
+Seller
+*/
+ MSG_SELLER = 0x427,
+/*20051017 to latest
+구매자
+Buyer
+*/
+ MSG_BUYER = 0x428,
+/*20051017 to latest
+종료시간
+End Time
+*/
+ MSG_FINISH_TIME = 0x429,
+/*20051017 to latest
+%m월 %d일 %H시
+%m %d %H
+*/
+ MSG_TIME_TYPE = 0x42a,
+/*20051017 to latest
+시간설정
+Time (Hr)
+*/
+ MSG_SET_TIME = 0x42b,
+/*20051017 to latest
+수수료
+Fee
+*/
+ MSG_CHARGE = 0x42c,
+/*20051017 to 20170906
+검색 된 아이템이 없습니다.
+20170913 to latest
+검색된 아이템이 없습니다.
+No items found in search.
+*/
+ MSG_NOTHING_SEARCH_ITEM = 0x42d,
+/*20051017 to latest
+현재 판매중인 아이템이 없습니다.
+Your Sale List is empty.
+*/
+ MSG_NOTHING_SEARCH_SELL_ITEM = 0x42e,
+/*20051017 to latest
+현재 구매중인 아이템이 없습니다.
+Your Purchase List is empty.
+*/
+ MSG_NOTHING_SEARCH_BUY_ITEM = 0x42f,
+/*20051017 to latest
+경매정보가 정확하지 않습니다.
+Auction Information is incorrect or incomplete.
+*/
+ MSG_ERROR_AUCTION_ITEM_INFO = 0x430,
+/*20051017 to latest
+경매에 등록할 아이템 정보가 없습니다.
+You must drag and drop an item from your Inventory into the Register Window to begin a new auction.
+*/
+ MSG_NOTHING_AUCTION_ITEM_INFO = 0x431,
+/*20051017 to latest
+이미 등록된 경매입니다.
+The auction has already been registered.
+*/
+ MSG_ERROR_ADD_AUCTION = 0x432,
+/*20051017 to latest
+제시가격
+Starting Bid
+*/
+ MSG_PRICE = 0x433,
+/*20051017 to latest
+구입희망가격
+Current Bid
+*/
+ MSG_PRICE2 = 0x434,
+/*20051017 to latest
+즉시구입가격
+Buy Now Price
+*/
+ MSG_PRICE3 = 0x435,
+/*20051017 to latest
+현재소지제니
+Your Current Zeny
+*/
+ MSG_PRICE4 = 0x436,
+/*20051017 to latest
+현재최고가격
+Highest Bid
+*/
+ MSG_PRICE5 = 0x437,
+/*20051017 to latest
+이전입찰가격
+Previous Bid
+*/
+ MSG_PRICE6 = 0x438,
+/*20051017 to latest
+추가입찰가격
+Next Bid
+*/
+ MSG_PRICE7 = 0x439,
+/*20051017 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BUY_ACTION_ITEM = 0x43a,
+/*20051017 to latest
+이 가격에 판매하시겠습니까?
+Would you like to sell this item?
+*/
+ MSG_SELL_ACTION_ITEM = 0x43b,
+/*20051017 to latest
+입찰하기
+Place Bid
+*/
+ MSG_BUY_AUCTION = 0x43c,
+/*20051017 to latest
+즉시구매하기
+Buy Now
+*/
+ MSG_BUY_AUCTION2 = 0x43d,
+/*20051017 to latest
+경매종료하기
+End the Auction
+*/
+ MSG_BUY_AUCTION3 = 0x43e,
+/*20051017 to latest
+재입찰하기
+Place another Bid
+*/
+ MSG_FINISH_AUCTION = 0x43f,
+/*20051017 to latest
+해당 경매에 대한 입찰이 성공했습니다.
+You have placed a bid.
+*/
+ MSG_RESULT_BUY_TRUE = 0x440,
+/*20051017 to latest
+해당 경매에 대한 입찰이 실패했습니다.
+You have failed to place a bid.
+*/
+ MSG_RESULT_BUY_FALSE = 0x441,
+/*20051017 to latest
+제니가 충분하지 않습니다.
+You do not have enough zeny.
+*/
+ MSG_RESULT_BUY_FALSE_MONEY = 0x442,
+#endif
+#if PACKETVER >= 20051024
+/*20051024 to latest
+방어구
+Armors
+*/
+ MSG_EQUIP = 0x443,
+/*20051024 to latest
+카드
+Card
+*/
+ MSG_CARD = 0x444,
+/*20051024 to latest
+기타
+Other
+*/
+ MSG_ETC = 0x445,
+/*20051024 to latest
+경매번호
+Bid
+*/
+ MSG_AUCTION_NUM = 0x446,
+/*20051024 to latest
+검색
+Search
+*/
+ MSG_AUCTION_SEARCH = 0x447,
+/*20051024 to latest
+해당 경매를 종료했습니다.
+You have ended the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_TRUE = 0x448,
+/*20051024 to latest
+해당 경매를 종료 할 수 없습니다.
+You cannot end the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_FALSE = 0x449,
+/*20051024 to latest
+경매 번호가 정확하지 않습니다.
+Bid Number is incorrect.
+*/
+ MSG_RESULT_AUCTION_ID_FALSE = 0x44a,
+/*20051024 to latest
+받는이
+To
+*/
+ MSG_SENDER = 0x44b,
+#endif
+#if PACKETVER >= 20051205
+/*20051205 to latest
+제 목
+Title
+*/
+ MSG_TITLE2 = 0x44c,
+/*20051205 to latest
+새 메일이 도착하였습니다.
+You have received a message in the mail.
+*/
+ MSG_NEW_MAIL = 0x44d,
+/*20051205 to latest
+검색중입니다.
+Searching...
+*/
+ MSG_SEARCHING_ITEM = 0x44e,
+/*20051205 to latest
+더 이상 경매 등록할 수 없습니다. 경매 등록은 최대 5개까지 가능합니다.
+You cannot register more than 5 items in an auction at a time.
+*/
+ MSG_AUCTION_ADD_OVER = 0x44f,
+/*20051205 to latest
+더 이상 경매 물품에 입찰할 수 없습니다. 경매 물품 입찰은 최대 5개까지 가능합니다.
+You cannot place more than 5 bids at a time.
+*/
+ MSG_RESULT_BUY_OVER = 0x450,
+/*20051205 to latest
+삭제하려는 메일에 수령하지 않은 아이템이 있습니다.
+Please accept all items from your mail before deleting.
+*/
+ MSG_MAIL_DELETE_ERROR = 0x451,
+/*20051205 to latest
+메일 제목을 입력하여 주십시오.
+Please enter a title.
+*/
+ MSG_MAIL_SEND_ERROR = 0x452,
+/*20051205 to latest
+/shopping : 클릭 한번으로 상점을 열고 상점이름 오른쪽 클릭으로 상점을 닫습니다 On Off
+/shopping: Enables you to open a shop with a single left-click and close your shop with a single right-click. On Off
+*/
+ MSG_EXPLAIN_SHOPPING = 0x453,
+/*20051205 to latest
+클릭 한번으로 상점을 열고 상점이름을 오른쪽 클릭해서 상점을 닫을수있습니다. [/sh ON]
+You can now open a shop with a single left-click and close your shop with a single right-click. [sh ON].
+*/
+ MSG_SHOPPING_ON = 0x454,
+/*20051205 to latest
+더블클릭 으로 상점을 열게됩니다. [/sh OFF]
+You can open a shop by double-clicking. [/sh OFF]
+*/
+ MSG_SHOPPING_OFF = 0x455,
+/*20051205 to latest
+메일을 보내려면, 제니 입력을 완료해야 합니다.
+Please enter zeny amount before sending mail.
+*/
+ MSG_MAIL_SEND_ERROR2 = 0x456,
+/*20051205 to latest
+경매 수수료가 부족합니다.
+You do not have enough zeny to pay the Auction Fee.
+*/
+ MSG_ADD_MONEY_FALSE = 0x457,
+/*20051205 to latest
+상태보기
+View Status
+*/
+ MSG_HOMUN_SHOWINFO = 0x458,
+/*20051205 to latest
+먹이주기
+Feed
+*/
+ MSG_HOMUN_FEEDING = 0x459,
+/*20051205 to latest
+대기
+Stand By
+*/
+ MSG_HOMUN_WAITING = 0x45a,
+/*20051205 to latest
+슈퍼노비스(남)
+Super Novice (Male)
+*/
+ MSG_JOB_SUPERNOVICE_M = 0x45b,
+/*20051205 to latest
+슈퍼노비스(여)
+Super Novice (Female)
+*/
+ MSG_JOB_SUPERNOVICE_F = 0x45c,
+/*20051205 to latest
+태권소년
+Taekwon Boy
+*/
+ MSG_JOB_TAEKWON_M = 0x45d,
+/*20051205 to latest
+태권소녀
+Taekwon Girl
+*/
+ MSG_JOB_TAEKWON_F = 0x45e,
+/*20051205 to latest
+권성(남)
+Taekwon Master (Male)
+*/
+ MSG_KWONSUNG_M = 0x45f,
+/*20051205 to latest
+권성(여)
+Taekwon Master (Female)
+*/
+ MSG_KWONSUNG_F = 0x460,
+/*20051205 to latest
+소울링커(남)
+Soul Linker (Male)
+*/
+ MSG_SOULLINGKER_M = 0x461,
+/*20051205 to latest
+소울링커(여)
+Soul Linker (Female)
+*/
+ MSG_SOULLINGKER_F = 0x462,
+/*20051205 to latest
+PC방요금제로 2개이상의 계정이 접속되고있습니다. 확인후 다시 사용하시기 바랍니다.
+Please check the connection, more than 2 accounts are connected with Internet Cafe Time Plan.
+*/
+ MSG_BAN_PC_IP_UNFAIR = 0x463,
+/*20051205 to latest
+귀하는 월정액 요금제 사용자 입니다. (남은기간 : %d일)
+Your account is using monthly payment. (Remaining day: %d day)
+*/
+ MSG_BILLING_1 = 0x464,
+/*20051205 to latest
+귀하는 정량 요금제 사용자 입니다. (남은시간 : %d시간 %분 %초)
+Your account is using time limited. (Remaining time: %d hour %d minute %d second)
+*/
+ MSG_BILLING_2 = 0x465,
+#endif
+#if PACKETVER >= 20051212
+/*20051212 to latest
+해당 아이템은 메일에 첨부 할수 없는 아이템입니다.
+This item cannot be mailed.
+*/
+ MSG_MAIL_ITEM_ADD_FAILED = 0x466,
+/*20051212 to latest
+더이상 아이템을 가질수 없습니다. 아이템은 메일로 보관하겠습니다.
+You cannot accept any more items. Please try again later.
+*/
+ MSG_MAIL_ADD_ITEM_OVER_FAILURE = 0x467,
+#endif
+#if PACKETVER >= 20060109
+/*20060109 to latest
+남성
+Male
+*/
+ MSG_PTSEX1 = 0x468,
+/*20060109 to latest
+여성
+Female
+*/
+ MSG_PTSEX2 = 0x469,
+/*20060109 to latest
+새로운 유저입니다
+New User.
+*/
+ MSG_PT_NEWUSER = 0x46a,
+/*20060109 to latest
+E-mail은 캐릭터를 지울때 필요합니다.
+E-mail address is required to delete a character.
+*/
+ MSG_PT_ACINFO = 0x46b,
+/*20060109 to latest
+정확한 형식으로 입력해 주세요.
+Please enter the correct information.
+*/
+ MSG_PT_ACINFO2 = 0x46c,
+/*20060109 to latest
+이 키를 사용하세요
+Please use this key.
+*/
+ MSG_PT_NEWKEYINFO = 0x46d,
+/*20060109 to latest
+정확한 카드 패스워드를 다시 입력해주세요
+Please enter the correct card password.
+*/
+ MSG_PT_FAIL_CARDPASS = 0x46e,
+/*20060109 to latest
+PT정보
+PT Info
+*/
+ MSG_PTID1 = 0x46f,
+/*20060109 to latest
+PT_ID는 %s
+PT_ID is %s
+*/
+ MSG_PTID2 = 0x470,
+/*20060109 to latest
+NUM_ID는 %s
+NUM_ID is %s
+*/
+ MSG_PTID3 = 0x471,
+/*20060109 to latest
+잊지않게 주의하세요
+Please don't forget this information.
+*/
+ MSG_PTID4 = 0x472,
+/*20060109 to latest
+1001
+*/
+ MSG_PT_ERROR_1001 = 0x473,
+/*20060109 to latest
+1002
+*/
+ MSG_PT_ERROR_1002 = 0x474,
+/*20060109 to latest
+1003
+*/
+ MSG_PT_ERROR_1003 = 0x475,
+/*20060109 to latest
+1004
+*/
+ MSG_PT_ERROR_1004 = 0x476,
+/*20060109 to latest
+1006
+*/
+ MSG_PT_ERROR_1006 = 0x477,
+/*20060109 to latest
+1007
+*/
+ MSG_PT_ERROR_1007 = 0x478,
+/*20060109 to latest
+1008
+*/
+ MSG_PT_ERROR_1008 = 0x479,
+/*20060109 to latest
+1009
+*/
+ MSG_PT_ERROR_1009 = 0x47a,
+/*20060109 to latest
+1012
+*/
+ MSG_PT_ERROR_1012 = 0x47b,
+/*20060109 to latest
+1013
+*/
+ MSG_PT_ERROR_1013 = 0x47c,
+/*20060109 to latest
+1014
+*/
+ MSG_PT_ERROR_1014 = 0x47d,
+/*20060109 to latest
+1015
+*/
+ MSG_PT_ERROR_1015 = 0x47e,
+/*20060109 to latest
+1019
+*/
+ MSG_PT_ERROR_1019 = 0x47f,
+/*20060109 to latest
+1020
+Navigation
+*/
+ MSG_PT_ERROR_1020 = 0x480,
+/*20060109 to latest
+1021
+*/
+ MSG_PT_ERROR_1021 = 0x481,
+/*20060109 to latest
+1023
+*/
+ MSG_PT_ERROR_1023 = 0x482,
+/*20060109 to latest
+1024
+*/
+ MSG_PT_ERROR_1024 = 0x483,
+/*20060109 to latest
+1025
+*/
+ MSG_PT_ERROR_1025 = 0x484,
+/*20060109 to latest
+1027
+*/
+ MSG_PT_ERROR_1027 = 0x485,
+/*20060109 to latest
+1028
+*/
+ MSG_PT_ERROR_1028 = 0x486,
+/*20060109 to latest
+10
+*/
+ MSG_PT_ERROR_10 = 0x487,
+/*20060109 to latest
+20
+*/
+ MSG_PT_ERROR_20 = 0x488,
+/*20060109 to latest
+40
+*/
+ MSG_PT_ERROR_40 = 0x489,
+/*20060109 to latest
+50
+*/
+ MSG_PT_ERROR_50 = 0x48a,
+/*20060109 to latest
+60
+*/
+ MSG_PT_ERROR_60 = 0x48b,
+/*20060109 to latest
+70
+*/
+ MSG_PT_ERROR_70 = 0x48c,
+/*20060109 to latest
+80
+*/
+ MSG_PT_ERROR_80 = 0x48d,
+/*20060109 to latest
+90
+*/
+ MSG_PT_ERROR_90 = 0x48e,
+/*20060109 to latest
+100
+*/
+ MSG_PT_ERROR_100 = 0x48f,
+/*20060109 to latest
+110
+*/
+ MSG_PT_ERROR_110 = 0x490,
+#endif
+#if PACKETVER >= 20060126
+/*20060126 to latest
+30포인트를 받으시겠습니까?
+Do you want to receive 30 points?
+*/
+ MSG_PT_POINT1 = 0x491,
+/*20060126 to latest
+30포인트(5시간)이 충전되었습니다
+30 points (5 hours) have been added.
+*/
+ MSG_PT_POINT2 = 0x492,
+#endif
+#if PACKETVER >= 20060213
+/*20060213 to latest
+감정되지 않은 아이템은 경매에 등록할 수 없습니다.
+You cannot register Unidentified Items in auctions.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE = 0x493,
+/*20060213 to latest
+소비 아이템은 경매에 등록할 수 없습니다.
+You cannot register this Consumable Item in an auction.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE2 = 0x494,
+#endif
+#if PACKETVER >= 20060306
+/*20060306 to latest
+메일창을 열려면 카트창을 닫아 주십시요.
+Please close the Cart Window to open the Mail Window.
+*/
+ MSG_CLOSE_MERCHANTITEMWND = 0x495,
+/*20060306 to latest
+카트창을 열려면 메일창을 닫아 주십시요.
+Please close the Mail Window to open the Cart Window.
+*/
+ MSG_CLOSE_MAILWND = 0x496,
+#endif
+#if PACKETVER >= 20060313
+/*20060313 to latest
+탄환이 장착되었습니다.
+Bullets have been equipped.
+*/
+ MSG_MSG_BULLET_EQUIPMENT_SUCCESS = 0x497,
+/*20060313 to latest
+메일이 반송되었습니다.
+The mail has been returned to sender.
+*/
+ MSG_MAIL_RETURN_SUCCESS = 0x498,
+/*20060313 to latest
+메일이 존재하지 않습니다.
+The mail no longer exists.
+*/
+ MSG_MAIL_RETURN_FAILURE = 0x499,
+#endif
+#if PACKETVER >= 20060522
+/*20060522 to 20060522
+한시간 동안, 동일한 IP로 접속한 유저가 60건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+20060523 to latest
+한시간 동안, 동일한 IP로 접속한 유저가 30건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+More than 30 players sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT_ALL = 0x49a,
+/*20060522 to latest
+한시간 동안, 동일한 IP로 10번 이상 접속되었습니다. 확인후 다시 사용하시기 바랍니다.
+More than 10 connections sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT = 0x49b,
+/*20060522 to latest
+게임을 재시작 하십시오
+Please restart the game.
+*/
+ MSG_GAMEGUARD_RESTART = 0x49c,
+#endif
+#if PACKETVER >= 20060703
+/*20060703 to latest
+용병정보 - 아쳐타입
+Mercenary: Archer
+*/
+ MSG_MER_INFO_TYPE_ARCHER = 0x49d,
+/*20060703 to latest
+용병정보 - 검사타입
+Mercenary: Swordman
+*/
+ MSG_MER_INFO_TYPE_SWORDMAN = 0x49e,
+/*20060703 to latest
+용병정보 - 창병타입
+Mercenary: Spearman
+*/
+ MSG_MER_INFO_TYPE_LANCER = 0x49f,
+/*20060703 to 20070109
+남은시간
+20070115 to latest
+삭제시간
+Expiration
+*/
+ MSG_LEFT_TIME = 0x4a0,
+/*20060703 to latest
+신뢰도
+Loyalty
+*/
+ MSG_MER_FRIENDLY = 0x4a1,
+/*20060703 to latest
+소환횟수
+Summons
+*/
+ MSG_MER_CALLCOUNT = 0x4a2,
+/*20060703 to latest
+Kill
+*/
+ MSG_MER_KILL = 0x4a3,
+#endif
+#if PACKETVER >= 20060904
+/*20060904 to latest
+펫이 배가 고파서 당신을 원망하고 있다는 느낌이 든다.
+You can feel hatred from your pet for neglecting to feed it.
+*/
+ MSG_PET_STARVING = 0x4a4,
+/*20060904 to latest
+[POINT] 테이밍미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You earned %d Taming Mission Ranking Points, giving you a total of %d points.
+*/
+ MSG_GANGSI_POINT = 0x4a5,
+/*20060904 to latest
+[테이밍미션] Target Monster : %s
+[Taming Mission] Target Monster: %s
+*/
+ MSG_GANGSI_MISSION = 0x4a6,
+#endif
+#if PACKETVER >= 20060918
+/*20060918 to latest
+/hunting : 사냥 목록을 보여줍니다.
+/hunting: You can check the your hunting list.
+*/
+ MSG_EXPLAIN_HUNTING = 0x4a7,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s는 몇 스킬 찍으셨나요?
+[Angel's Question] Please tell me, how many %s skills do you have?
+*/
+ MSG_DEATH_Q01 = 0x4a8,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 소지하시고있는 제니를 십만으로 나누면 얼마가 되시나요?
+[Angel's Question] Please tell me, how much zeny you'll have if you divide it by 100,000?
+*/
+ MSG_DEATH_Q02 = 0x4a9,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 오늘이 몇일이신지 아시나요?
+[Angel's Question] Please tell me, what is today's date?
+*/
+ MSG_DEATH_Q03 = 0x4aa,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s은 지금 몇이신가요?
+[Angel's Question] Please tell me, how many %s do you have?
+*/
+ MSG_DEATH_Q04 = 0x4ab,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 슈노, 태권계열, 무낙계열을 담당하고있는 SiYeon씨의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in SiYeon's name?
+*/
+ MSG_DEATH_Q05 = 0x4ac,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 귀엽고 어여쁜 라그나로크의 히로인 Munak의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Munak's name?
+*/
+ MSG_DEATH_Q06 = 0x4ad,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 제가 어여뻐하는 Bongun의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Bongun's name?
+*/
+ MSG_DEATH_Q07 = 0x4ae,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 저희가 존재하는 온라인세계 Ragnarok의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, Ragnarok?
+*/
+ MSG_DEATH_Q08 = 0x4af,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 언제나 Online상태인 천사동료들은 큰힘이 되어주죠. Online의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, online?
+*/
+ MSG_DEATH_Q09 = 0x4b0,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 죽음도 두려워하지않는 기사들을 상징하는 단어인 Death의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, death?
+*/
+ MSG_DEATH_Q10 = 0x4b1,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 기사들은 너무 멋진다고 생각해요. Knight의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, knight?
+*/
+ MSG_DEATH_Q11 = 0x4b2,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 중력을 뜻하는 단어인 Gravity의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, gravity?
+*/
+ MSG_DEATH_Q12 = 0x4b3,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 어둠속에서도 밝게 사는게 중요하지요. Dark의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, dark?
+*/
+ MSG_DEATH_Q13 = 0x4b4,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 뭐든지 수집하는 Collector의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, collecter?
+*/
+ MSG_DEATH_Q14 = 0x4b5,
+/*20060918 to latest
+[천사의대답] 소녀에게 정확한 사실을 가르쳐주셔서 감사하옵니다.
+[Angel's Answer] Thank you for letting me know~
+*/
+ MSG_DEATH_R01 = 0x4b6,
+/*20060918 to latest
+[천사의대답] 사랑스러우신 분이시군요. 소녀 감탄했사옵니다.
+[Angel's Answer] I'm very pleased with your answer. You are a splendid adventurer.
+*/
+ MSG_DEATH_R02 = 0x4b7,
+/*20060918 to latest
+[천사의대답] 소녀 실망했사옵니다.
+[Angel's Answer] You've disappointed me...
+*/
+ MSG_DEATH_R05 = 0x4b8,
+#endif
+#if PACKETVER >= 20060925
+/*20060925 to latest
+[POINT] 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You earned %d Ranking Points, giving you a total of %d Ranking Points.
+*/
+ MSG_DEATH_POINT = 0x4b9,
+#endif
+#if PACKETVER >= 20060927
+/*20060927 to 20070417
+[%s]의 소지 Point : %d Point
+20070423 to latest
+[%s]의 소지 캐시 : %d 캐시
+[%s]'s Points: %d Points
+*/
+ MSG_POINT_SHOP = 0x4ba,
+#endif
+#if PACKETVER >= 20061009
+/*20061009 to latest
+선택하지 않은 캐릭터는 삭제 됩니다. 완료하시겠습니까?
+Unselected Characters will be deleted. Continue?
+*/
+ MSG_CONFIRM_SELECT_CHARACTERS = 0x4bb,
+/*20061009 to latest
+9개 이상 선택하실 수 없습니다.
+You cannot select more than 8.
+*/
+ MSG_ERROR_SELECT_CHARACTERS = 0x4bc,
+#endif
+#if PACKETVER >= 20061016
+/*20061016 to latest
+캐릭터명을 '%s' (으)로 변경하시겠습니까?
+Do you want to change your name to '%s'?
+*/
+ MSG_CONFIRM_TO_CHANGE_NAME = 0x4bd,
+/*20061016 to latest
+캐릭터명이 성공적으로 변경되었습니다.
+Character Name has been changed successfully.
+*/
+ MSG_CHANGE_NAME_SUCCESS = 0x4be,
+/*20061016 to latest
+캐릭터명 변경이 실패하였습니다.
+You have failed to change this character's name.
+*/
+ MSG_CHANGE_NAME_FAILURE = 0x4bf,
+/*20061016 to latest
+한 번에 한 종류의 아이템만 구매할 수 있습니다.
+You can purchase only one kind of item at a time.
+*/
+ MSG_CAN_BUY_ONLY_ONEITEM = 0x4c0,
+#endif
+#if PACKETVER >= 20061017
+/*20061017 to 20061017
+캐릭터가 하나도 선택되지 않았습니다. 반드시 하나 이상의 캐릭터를 선택하여야 합니다.
+20061023 to latest
+캐릭터가 한개도 선택되지 않았습니다. 반드시 한개 이상의 캐릭터를 선택하여야 합니다.
+No characters were selected. You must select at least one character.
+*/
+ MSG_NO_SELECT_CHARACTERS = 0x4c1,
+#endif
+#if PACKETVER >= 20061023
+/*20061023 to latest
+이미 캐릭터명을 변경한 적이 있습니다. 더 이상 변경 할 수 없습니다.
+This character's name has already been changed. You cannot change a character's name more than once.
+*/
+ MSG_ALREADY_CHANGED_NAME = 0x4c2,
+/*20061023 to latest
+사용자 정보가 정확하지 않습니다.
+User Information is not correct.
+*/
+ MSG_NOTREGISTED_USER = 0x4c3,
+/*20061023 to latest
+다른 사용자가 같은 캐릭터 명을 먼저 사용하였습니다. 다른 캐릭터명을 사용하여 주십시요.
+Another user is using this character name, so please select another one.
+*/
+ MSG_DUPLICATED_CHAR_NAME = 0x4c4,
+#endif
+#if PACKETVER >= 20061030
+/*20061030 to latest
+파티장 권한이 없어 파티원을 소환하지 못했습니다.
+The party member was not summoned because you are not the party leader.
+*/
+ MSG_CANNOT_PARTYCALL = 0x4c5,
+/*20061030 to latest
+현재 맵에는 소환될 파티원이 존재하지 않습니다.
+There is no party member to summon in the current map.
+*/
+ MSG_NO_PARTYMEM_ON_THISMAP = 0x4c6,
+/*20061030 to latest
+이 지역에선 보스몬스터의 흔적을 찾을 수가 없습니다.
+You cannot find any trace of a Boss Monster in this area.
+*/
+ MSG_NOTFIND_BOSSMON = 0x4c7,
+/*20061030 to 20070122
+보스 몬스터 '%s'의 등장 예정시간 %02d시:%02d분
+20070129 to 20071205
+보스 몬스터 '%s'(이)가 %d시 %d분 후에 등장합니다.
+20071211 to latest
+보스 몬스터 '%s'(이)가 %d시간 %d분 후에 등장합니다.
+Boss Monster, '%s' will appear in %02d hour(s) and %02d minute(s).
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON = 0x4c8,
+/*20061030 to latest
+보스 몬스터 '%s'의 위치가 미니맵에 표시됩니다.
+The location of Boss Monster, '%s', will be displayed on your Mini-Map.
+*/
+ MSG_SHOW_POSITION_OF_BOSSMON = 0x4c9,
+#endif
+#if PACKETVER >= 20061106
+/*20061106 to 20061211
+%s를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20061218 to 20070618
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20070619 to 20071218
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20080102 to 20101026
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20101102 to 20110330
+'%s'를 개봉 하시겠습니까? ^ff0000상자를 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 한번 개봉 된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20110405 to latest
+'%s'를 개봉 하시겠습니까? ^ff0000상자를 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 한번 개봉 된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+Do you want to open '%s'? Once opened, the contents cannot be moved to other locations aside from the Kafra Storage. The item effect isn't doubled, even if the same items are used more than once.
+*/
+ MSG_CONFIRM_TO_OPEN_CASH_ITEM = 0x4ca,
+/*20061106 to latest
+NPC가 존재하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the NPC does not exist.
+*/
+ MSG_BUY_CASH_FAIL_NPC = 0x4cb,
+/*20061106 to latest
+부분 유료화 시스템이 정상 작동하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Kafra Shop System is not working correctly.
+*/
+ MSG_BUY_CASH_FAIL_SYSTEM = 0x4cc,
+/*20061106 to latest
+교환중에는 아이템을 구매 할 수 없습니다.
+You cannot purchase items while you are in a trade.
+*/
+ MSG_BUY_CASH_FAIL_EXCHANGE = 0x4cd,
+/*20061106 to latest
+아이템 정보가 정확하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Item Information was incorrect.
+*/
+ MSG_BUY_CASH_FAIL_ITEM_ID = 0x4ce,
+#endif
+#if PACKETVER >= 20061204
+/*20061204 to latest
+ STR이 향상되었습니다.
+STR has increased.
+*/
+ MSG_ENST_STR = 0x4cf,
+/*20061204 to latest
+ STR이 원래대로 돌아왔습니다.
+STR has returned to normal.
+*/
+ MSG_DSST_STR = 0x4d0,
+/*20061204 to latest
+ AGI이 향상되었습니다.
+AGI has increased.
+*/
+ MSG_ENST_AGI = 0x4d1,
+/*20061204 to latest
+ AGI이 원래대로 돌아왔습니다.
+AGI has returned to normal.
+*/
+ MSG_DSST_AGI = 0x4d2,
+/*20061204 to latest
+ VIT이 향상되었습니다.
+VIT has increased.
+*/
+ MSG_ENST_VIT = 0x4d3,
+/*20061204 to latest
+ VIT이 원래대로 돌아왔습니다.
+VIT has returned to normal.
+*/
+ MSG_DSST_VIT = 0x4d4,
+/*20061204 to latest
+ INT이 향상되었습니다.
+INT has increased.
+*/
+ MSG_ENST_INT = 0x4d5,
+/*20061204 to latest
+ INT이 원래대로 돌아왔습니다.
+INT has returned to normal.
+*/
+ MSG_DSST_INT = 0x4d6,
+/*20061204 to latest
+ DEX이 향상되었습니다.
+DEX has increased.
+*/
+ MSG_ENST_DEX = 0x4d7,
+/*20061204 to latest
+ DEX이 원래대로 돌아왔습니다.
+DEX has returned to normal.
+*/
+ MSG_DSST_DEX = 0x4d8,
+/*20061204 to latest
+ LUK이 향상되었습니다.
+LUK has increased.
+*/
+ MSG_ENST_LUK = 0x4d9,
+/*20061204 to latest
+ LUK이 원래대로 돌아왔습니다.
+LUK has returned to normal.
+*/
+ MSG_DSST_LUK = 0x4da,
+/*20061204 to latest
+ 회피율이 향상되었습니다.
+Flee Rate (Flee) has increased.
+*/
+ MSG_ENST_AVOIDANCE = 0x4db,
+/*20061204 to latest
+ 회피율이 원래대로 돌아왔습니다.
+Flee Rate has returned to normal.
+*/
+ MSG_DSST_AVOIDANCE = 0x4dc,
+/*20061204 to latest
+ 명중률이 향상되었습니다.
+Accuracy Rate (Hit) has increased.
+*/
+ MSG_ENST_HIT = 0x4dd,
+/*20061204 to latest
+ 명중률이 원래대로 돌아왔습니다.
+Accuracy Rate has returned to normal.
+*/
+ MSG_DSST_HIT = 0x4de,
+/*20061204 to latest
+ 크리티컬 확률이 향상되었습니다.
+Critical Attack (Critical) has increased.
+*/
+ MSG_ENST_CRITICALSUCCESSVALUE = 0x4df,
+/*20061204 to latest
+ 크리티컬 확률이 원래대로 돌아왔습니다.
+Critical Attack has returned to normal.
+*/
+ MSG_DSST_CRITICALSUCCESSVALUE = 0x4e0,
+/*20061204 to 20111021
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.5배로 증가합니다.
+20111025 to 20111101
+ 30분간 얻을 수 있는 경험치가 75%% 증가합니다.
+20111102 to latest
+ 30분간 얻을 수 있는 경험치가 50%% 증가합니다.
+You will receive 1.5 times more EXP from hunting monsters for the next 30 minutes.
+*/
+ MSG_PLUSEXP = 0x4e1,
+/*20061204 to latest
+ 30분내 사망시 1회에 한해 경험치 감소가 일어나지 않습니다.
+This character will not receive any EXP penalty if killed within the next 30 minutes.
+*/
+ MSG_DDEATHPENALTY = 0x4e2,
+/*20061204 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 30분간 2배로 증가합니다.
+Regular item drops from monsters will be doubled for the next 30 minutes.
+*/
+ MSG_RECEIVEITEM = 0x4e3,
+/*20061204 to latest
+ 10분간 맵 내에 출현 가능한 보스 몬스터에 대한 정보를 안내해 드립니다.
+Boss Monster Map Information for the next 10 minutes.
+*/
+ MSG_BOSS_ALARM = 0x4e4,
+/*20061204 to 20061211
+ 정말로 %s아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20061218 to 20070423
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20070423 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20080610 to 20100629
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20100701 to 20101026
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 %s아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20101102 to 20101130
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 정말로 %s아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20101207 to 20110330
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20110405 to 20120618
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20120626 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+Do you really want to purchase this item? %d points will be deducted from your total Kafra Credit Points.
+*/
+ MSG_BUY_RECONFIRM = 0x4e5,
+#endif
+#if PACKETVER >= 20061211
+/*20061211 to 20061211
+'%s'아이템의 사용시간이 %d분 남았습니다.
+20061218 to 20070423
+ 포인트가 부족합니다.
+20070423 to latest
+ 캐시가 부족합니다.
+ You do not have enough Kafra Credit Points.
+*/
+ MSG_BUY_CASH_FAIL_MONEY = 0x4e6,
+/*20061211 to 20061211
+1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+20061218 to latest
+ ^ff0000파기일시: %s^000000
+ ^ff0000Expiration Date: %s^000000
+*/
+ MSG_NOTICE_TO_DELETE_TIME = 0x4e7,
+/*20061211 to 20061211
+'%s'아이템이 인벤토리에서 삭제되었습니다.
+20061218 to latest
+ '%s'아이템의 사용시간이 %d분 남았습니다.
+ The '%s' item will disappear in %d minutes.
+20070102 to 20070312
+ '%s'아이템의 사용시간이 %s 남았습니다.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e8,
+#endif
+#if PACKETVER >= 20061218
+/*20061218 to latest
+ 1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+ '%s' item will be deleted from the Inventory in 1 minute.
+*/
+ MSG_LAST_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e9,
+/*20061218 to latest
+ '%s'아이템이 인벤토리에서 삭제되었습니다.
+ '%s' item has been deleted from the Inventory.
+*/
+ MSG_NOTICE_TO_DELETE_ITEM = 0x4ea,
+#endif
+#if PACKETVER >= 20070102
+/*20070102 to latest
+Input Number
+*/
+ MSG_INPUT_NUMBER = 0x4eb,
+/*20070102 to latest
+%m월 %d일 %H시 %M분
+%m/%d %H:%M
+*/
+ MSG_TIME_TYPE2 = 0x4ec,
+#endif
+#if PACKETVER >= 20070129
+/*20070129 to 20071120
+보스 몬스터 '%s'(이)가 1분 이내에 등장합니다.
+20071127 to latest
+보스 몬스터 '%s'(이)가 잠시 후에 등장합니다.
+Boss Monster '%s' will appear within 1 minute.
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON2 = 0x4ed,
+/*20070129 to latest
+용병 스킬목록
+Mercenary Soldier Skill List
+*/
+ MSG_MER_SKILLLIST = 0x4ee,
+/*20070129 to latest
+블랙젬스톤 1개와 백만제니를 소모하는 마법의 실행에 동의합니까?
+Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+*/
+ MSG_DA_EXP_ACCEPT = 0x4ef,
+#endif
+#if PACKETVER >= 20070220
+/*20070220 to latest
+[POINT] 콜렉터랭킹 포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have gained %d Collector Rank Points; you now have a total of %d Collector Rank Points.
+*/
+ MSG_COLLECTOR_POINT = 0x4f0,
+/*20070220 to latest
+[콜렉터랭킹] Target Item : %s
+[Collector Rank] Target Item: %s
+*/
+ MSG_COLLECTOR_MISSION = 0x4f1,
+#endif
+#if PACKETVER >= 20070227
+/*20070227 to latest
+용병 사용시간이 만료되었습니다.
+The mercenary contract has expired.
+*/
+ MSG_MER_FINISH = 0x4f2,
+/*20070227 to latest
+용병이 사망하였습니다.
+The mercenary has died.
+*/
+ MSG_MER_DIE = 0x4f3,
+/*20070227 to latest
+용병이 해고되었습니다.
+You have released the mercenary.
+*/
+ MSG_MER_RETIRE = 0x4f4,
+/*20070227 to latest
+용병이 도망갔습니다.
+The mercenary has run away.
+*/
+ MSG_MER_RUNAWAY = 0x4f5,
+#endif
+#if PACKETVER >= 20070319
+/*20070319 to latest
+ '%s'아이템의 사용시간이 %d초 남았습니다.
+ The '%s' item will disappear in %d seconds.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME2 = 0x4f6,
+#endif
+#if PACKETVER >= 20070326
+/*20070326 to 20070821
+PC방 이벤트 : 경험치 증가 %d%%, 죽을때 경험치 %d%%, 드롭율 증가 %d%%
+20070828 to latest
+PC방 프리미엄 서비스 : 경험치 %d%% 증가, 사망 페널티 %d%% 감소, 드롭율 %d%% 증가
+IP Bonus: EXP/JEXP %d%%, Death Penalty %d%%, Item Drop %d%%
+*/
+ MSG_PCBANG_EVENT = 0x4f7,
+#endif
+#if PACKETVER >= 20070402
+/*20070402 to latest
+24시간 이후에 시도하세요
+Symbols in Character Names are forbidden.
+*/
+ MSG_LIMIT_CHAR_DELETE = 0x4f8,
+#endif
+#if PACKETVER >= 20070416
+/*20070416 to latest
+용병이 사용자 인공지능으로 동작합니다.
+Mercenary will follow custom AI.
+*/
+ MSG_MER_USERAI_ON = 0x4f9,
+/*20070416 to latest
+용병이 기본 인공지능으로 동작합니다.
+Mercenary will follow basic AI.
+*/
+ MSG_MER_USERAI_OFF = 0x4fa,
+#endif
+#if PACKETVER >= 20070611
+/*20070611 to latest
+ %s님의
+ %s's
+*/
+ MSG_CHARACTER_NAME = 0x4fb,
+/*20070611 to 20070801
+%s님이 %s를 획득하셨습니다.
+20070807 to latest
+%s님이 %s 아이템을 획득하셨습니다.
+%s has acquired %s.
+*/
+ MSG_ITEM_PICKUP_PARTY = 0x4fc,
+/*20070611 to latest
+공개 채팅 메시지 표시
+Public Chat Display
+*/
+ MSG_VIEW_CHAT_MSG = 0x4fd,
+/*20070611 to latest
+귓속말 채팅 메시지 표시
+Whisper Display
+*/
+ MSG_VIEW_WHISPER_MSG = 0x4fe,
+/*20070611 to latest
+파티 채팅 메시지 표시
+Party Chat Display
+*/
+ MSG_VIEW_PARTY_MSG = 0x4ff,
+/*20070611 to latest
+길드 채팅 메시지 표시
+Guild Chat Display
+*/
+ MSG_VIEW_GUILD_MSG = 0x500,
+/*20070611 to latest
+아이템 획득/드롭 메시지 표시
+Item Get/Drop Message Display
+*/
+ MSG_VIEW_GET_ITEM_MSG = 0x501,
+/*20070611 to latest
+장비 장착/해제 메시지 표시
+Equipment On/Off Message Display
+*/
+ MSG_VIEW_EQUIP_MSG = 0x502,
+/*20070611 to latest
+상태이상 메시지 표시
+Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_MSG = 0x503,
+/*20070611 to latest
+파티원의 주요 아이템 획득 메시지 표시
+Party Member's Obtained Item Message Display
+*/
+ MSG_VIEW_GET_ITEM_PARTY_MSG = 0x504,
+/*20070611 to latest
+파티원의 상태이상 메시지 표시
+Party Member's Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_PARTY_MSG = 0x505,
+/*20070611 to latest
+스킬 사용 실패 메시지 표시
+Skill Failure Message Display
+*/
+ MSG_VIEW_FAIL_SKILL_MSG = 0x506,
+/*20070611 to latest
+파티 설정 메시지 표시
+Party Configuration Message Display
+*/
+ MSG_VIEW_PARTY_SETUP_MSG = 0x507,
+/*20070611 to latest
+장비 손상 메시지 표시
+Damaged Equipment Message Display
+*/
+ MSG_VIEW_DAMAGED_EQUIP_MSG = 0x508,
+/*20070611 to latest
+배틀 메시지 창 표시 정보
+Battle Message Window Display
+*/
+ MSG_BATTLE_CHAT_WND_OPTION = 0x509,
+/*20070611 to latest
+[%s]의 소지 한코인 : %d 한코인
+[%s]'s Han Coin: %d Han Coin
+*/
+ MSG_POINT_SHOP_NHN = 0x50a,
+#endif
+#if PACKETVER >= 20070618
+/*20070618 to latest
+일반 메시지
+Public Log
+*/
+ MSG_ST_CHAT = 0x50b,
+/*20070618 to latest
+배틀 메시지
+Battle Log
+*/
+ MSG_BT_CHAT = 0x50c,
+/*20070618 to latest
+휴대폰 인증.
+Mobile Authentication
+*/
+ MSG_PHONE_CONFIRM = 0x50d,
+/*20070618 to latest
+읽기
+Read
+*/
+ MSG_BOOK_READ = 0x50e,
+/*20070618 to latest
+자동낭독
+Auto Read
+*/
+ MSG_BOOK_AUTOREAD = 0x50f,
+/*20070618 to latest
+책갈피
+Bookmark
+*/
+ MSG_BOOK_KEEP = 0x510,
+/*20070618 to latest
+이전페이지
+Previous
+*/
+ MSG_BOOK_PREV = 0x511,
+/*20070618 to latest
+다음페이지
+Next
+*/
+ MSG_BOOK_NEXT = 0x512,
+/*20070618 to latest
+닫기
+Close
+*/
+ MSG_BOOK_CLOSE = 0x513,
+#endif
+#if PACKETVER >= 20070622
+/*20070622 to latest
+%s 장비가 손상되었습니다.
+%s's Equipment has been damaged.
+*/
+ MSG_DAMAGED_EQUIP = 0x514,
+/*20070622 to latest
+%s님의 %s 손상되었습니다.
+%s's %s was damaged.
+*/
+ MSG_DAMAGED_EQUIP_PARTY = 0x515,
+/*20070622 to latest
+무기가
+Weapon
+*/
+ MSG_DAMAGED_WEAPON = 0x516,
+/*20070622 to latest
+갑옷이
+Armor
+*/
+ MSG_DAMAGED_BODY = 0x517,
+/*20070622 to latest
+스킬레벨이 부족합니다. 파티가입 불능
+Insufficient Skill Level for joining a Party
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5_2 = 0x518,
+#endif
+#if PACKETVER >= 20070703
+/*20070703 to latest
+[%s]의 무료 캐시 : %d 캐시
+[%s]'s Free Cash: %d Cash
+*/
+ MSG_POINT_SHOP2 = 0x519,
+/*20070703 to latest
+무료 캐시 사용 :
+Use Free Cash:
+*/
+ MSG_USE_FREE_POINT = 0x51a,
+/*20070703 to latest
+캐시
+Cash
+*/
+ MSG_CASH = 0x51b,
+#endif
+#if PACKETVER >= 20070710
+/*20070710 to latest
+http://payment.ro.hangame.com/index.asp
+*/
+ MSG_SETTLE_WEB_URL_HANGAME = 0x51c,
+/*20070710 to 20090603
+그라비티 회원 정보동의를 하셔야 사용할수있습니다.
+20090610 to latest
+그라비티 회원 정보동의를 하셔야 사용할 수 있습니다.
+You need to accept the Privacy Policy from Gravity in order to use the service.
+*/
+ MSG_BAN_GRAVITY_MEM_AGREE = 0x51d,
+/*20070710 to latest
+이용약관에 동의를 하셔야 본 서비스를 이용하실 수 있습니다.
+You need to accept the User Agreement in order to use the service.
+*/
+ MSG_BAN_GAME_MEM_AGREE = 0x51e,
+/*20070710 to 20080514
+존재하지 않는 한게임 ID이거나 잘못된 ID입니다.
+20080520 to latest
+입력하신 아이디와 비밀번호가 등록된 정보와 일치하지 않습니다.
+Incorrect or nonexistent ID.
+*/
+ MSG_BAN_HAN_VALID = 0x51f,
+#endif
+#if PACKETVER >= 20070711
+/*20070711 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20080610 to 20100629
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20100701 to 20101026
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 %s아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20101102 to 20101130
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외됩니다.^000000 정말로 %s아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20101207 to 20110330
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20110405 to 20120618
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20120626 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+Do you really want to purchase these items? You will spend %d Regular Cash Points and %d Free Cash Points.
+*/
+ MSG_BUY_RECONFIRM2 = 0x520,
+#endif
+#if PACKETVER >= 20070718
+/*20070718 to latest
+%d시간이 경과하였습니다.
+%d hour(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME1 = 0x521,
+/*20070718 to latest
+%d시간 %d분이 경과하였습니다.
+%d hour(s) %d minute(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME2 = 0x522,
+/*20070718 to latest
+게임을 종료하세요, 경험치 및 모든게 50%로 조정됩니다
+Please stop playing the game, and take a break. Exp and other features will be reduced to 50%.
+*/
+ MSG_WARNING_MSG1 = 0x523,
+/*20070718 to latest
+불건전 시간대에 접어들었습니다. 게임을 종료하세요, 경험치 및 모든게 0%로 조정됩니다
+Please stop playing the game since you'll need to rest. Exp and other features will be fixed to 0%.
+*/
+ MSG_WARNING_MSG2 = 0x524,
+#endif
+#if PACKETVER >= 20070724
+/*20070724 to latest
+퀘스트 목록
+Quest List
+*/
+ MSG_QUESTWIN = 0x525,
+#endif
+#if PACKETVER >= 20070807
+/*20070807 to latest
+RO SHOP
+*/
+ MSG_RO_SHOP = 0x526,
+#endif
+#if PACKETVER >= 20070821
+/*20070821 to 20070904
+메모리얼던젼 '%s'이 예약되었습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 알수없는 이유로 실패 하였습니다.
+Memorial Dungeon, '%s' is booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN = 0x527,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 예약이 실패했습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 예약중복으로 실패 하였습니다.
+Failed to book Memorial Dungeon, '%s'.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE = 0x528,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 이미 예약중입니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 권한문제로 실패 하였습니다.
+Memorial Dungeon, '%s' is already booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT = 0x529,
+/*20070821 to 20070904
+메모리얼던젼 '%s'가 생성 되었습니다
+ 5분내에 입장하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 중복생성요청으로 실패하였습니다.
+Memorial Dungeon, '%s' is created.
+ Please enter in 5 minutes.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST = 0x52a,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 생성에 실패했습니다.
+ 나중에 다시 시도하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약취소가 실패 하였습니다.
+Failed to create Memorial Dungeon, '%s'.
+ Please try again.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_FAIL = 0x52b,
+/*20070821 to latest
+상대방이 파티 초대 거부 상태입니다.
+The character blocked the party invitation.
+*/
+ MSG_JOINMSG_REFUSE = 0x52c,
+#endif
+#if PACKETVER >= 20070828
+/*20070828 to latest
+모든 파티 초대를 거부합니다.
+Block all party invitations.
+*/
+ MSG_INVITE_PARTY_REFUSE = 0x52d,
+/*20070828 to latest
+모든 파티 초대를 수락합니다.
+Allow all party invitations.
+*/
+ MSG_INVITE_PARTY_ACCEPT = 0x52e,
+#endif
+#if PACKETVER >= 20070904
+/*20070904 to latest
+착용하시면 이 아이템은 영구 귀속됩니다. 착용하시겠습니까?
+This item will be permanently bound to this character once it is equipped. Do you really want to equip this item?
+*/
+ MSG_YOURITEM_EQUIP = 0x52f,
+/*20070904 to latest
+%s 아이템이 귀속되었습니다.
+%s is now permanently bound to this character.
+*/
+ MSG_YOURITEM_EQUIPED = 0x530,
+/*20070904 to latest
+캐시가 부족합니다. 무료 캐시 포인트를 입력해 주시기 바랍니다.
+You do not have enough Kafra Credit Points. Please enter whether you have free credit points.
+*/
+ MSG_BUY_TO_FREE_POINT = 0x531,
+/*20070904 to latest
+파티 가입요청
+Request to Join Party
+*/
+ MSG_REQ_JOIN_PARTY3 = 0x532,
+#endif
+#if PACKETVER >= 20070912
+/*20070912 to latest
+공성 정보 메시지 표시
+Display WOE Info
+*/
+ MSG_VIEW_SIEGE_INFO_MSG = 0x533,
+/*20070912 to latest
+메모리얼던젼 '%s'의 예약이 취소 되었습니다.
+Memorial Dungeon %s's reservation has been canceled.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_SUCCESS = 0x534,
+/*20070912 to latest
+메모리얼던젼 '%s' 생성에 실패하였습니다. 다시 시도 하세요.
+Failed to create Memorial Dungeon %s. Please try again.
+*/
+ MSG_MDUNGEON_CREATE_FAIL = 0x535,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 스킬입니다.
+This skill cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_SKILL_AREA = 0x536,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 아이템입니다.
+This item cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_USEITEM_AREA = 0x537,
+#endif
+#if PACKETVER >= 20070918
+/*20070918 to latest
+메모리얼 던전
+Memorial Dungeon
+*/
+ MSG_MEMORIAL_DUN = 0x538,
+/*20070918 to latest
+%s 대기중
+%s in Standby
+*/
+ MSG_MEMORIAL_DUN_WAITING = 0x539,
+/*20070918 to latest
+%s 입장 가능
+%s Available
+*/
+ MSG_MEMORIAL_DUN_READY = 0x53a,
+/*20070918 to 20071120
+%s 내부
+20071127 to latest
+%s 진행중
+%s in Progress
+*/
+ MSG_MEMORIAL_DUN_IN = 0x53b,
+/*20070918 to latest
+시간 안에 입장하지 않아 메모리얼 던전이 사라졌습니다.
+No one entered the Memorial Dungeon within its duration; the dungeon has disappeared.
+*/
+ MSG_MEMORIAL_DUN_OUT1 = 0x53c,
+/*20070918 to latest
+이용하시려면 이용 신청을 처음부터 다시 해주시기 바랍니다.
+Please apply for dungeon entry again to play in this dungeon.
+*/
+ MSG_MEMORIAL_DUN_OUT2 = 0x53d,
+/*20070918 to latest
+대기 순위 : ^ff0000%d^000000
+Your Standby Priority: ^ff0000%d^000000
+*/
+ MSG_MEMORIAL_DUN_PRIORITY = 0x53e,
+/*20070918 to latest
+^ff0000%s^000000 내에 입장하지 않을 경우 신청하신 던전이 삭제 됩니다.
+The requested dungeon will be removed if you do not enter within ^ff0000%s^000000.
+*/
+ MSG_MEMORIAL_DUN_NOTIFY = 0x53f,
+/*20070918 to latest
+던전 미션 제한 시간 :
+Dungeon Mission Time Limit:
+*/
+ MSG_MEMORIAL_DUN_NOTIFY2 = 0x540,
+/*20070918 to latest
+메모리얼 던전 예약이 취소되었습니다.
+The Memorial Dungeon reservation has been canceled.
+*/
+ MSG_MEMORIAL_DUN_CANCEL = 0x541,
+/*20070918 to latest
+메모리얼 던전이 유지 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon duration expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_LIVE_TIME_OUT = 0x542,
+/*20070918 to latest
+메모리얼 던전이 입장 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon's entry time limit expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_ENTER_TIME_OUT = 0x543,
+/*20070918 to latest
+메모리얼 던전이 삭제 되었습니다.
+The Memorial Dungeon has been removed.
+*/
+ MSG_MEMORIAL_DUN_DESTROY_REQUEST = 0x544,
+/*20070918 to 20191218
+메모리얼 던전에 시스템 오류가 발생하였습니다. 정상적인 게임 진행을 위해 재접속을 해주십시오.
+A system error has occurred in the Memorial Dungeon. Please relog in to the game to continue playing.
+20191224 to latest
+메모리얼 던전에 통신 장애가 발생하였습니다. 정상적인 게임 진행을 위해 잠시 후, 재접속을 해주십시오.
+*/
+ MSG_MEMORIAL_DUN_ERROR = 0x545,
+/*20070918 to latest
+사용할 수 없는 슬롯입니다.
+This slot is not usable.
+*/
+ MSG_FR_INVALID_SLOT = 0x546,
+/*20070918 to latest
+Base Level이 15를 넘었습니다.
+Your Base Level is over 15.
+*/
+ MSG_FR_BASELVL = 0x547,
+/*20070918 to latest
+Job Level이 15를 넘었습니다.
+Your Job Level is over 15.
+*/
+ MSG_FR_INVALID_JOBLV = 0x548,
+/*20070918 to latest
+해당슬롯 캐릭터에 직업군의 상인이므로 게임을 할 수 없습니다.
+You cannot play the Merchant class character in this slot.
+*/
+ MSG_FR_JOB = 0x549,
+/*20070918 to latest
+추후 사용예정
+Not Yet Implemented
+*/
+ MSG_FR_MAP = 0x54a,
+/*20070918 to latest
+만들수 있는 케릭터 슬롯이 아닙니다.
+You are not eligible to open the Character Slot.
+*/
+ MSG_FR_ERR_MKCHAR_INVALID_SLOT = 0x54b,
+/*20070918 to latest
+삭제할 수 없는 케릭터 입니다.
+This character cannot be deleted.
+*/
+ MSG_FR_ERR_DELCHAR_INVALID_SLOT = 0x54c,
+/*20070918 to latest
+상대방의 장비창이 공개되어 있지 않습니다.
+This character's equipment information is not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSED = 0x54d,
+/*20070918 to latest
+장비창을 공개하지 않습니다.
+Equipment information not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSE = 0x54e,
+/*20070918 to latest
+장비창을 공개합니다.
+Equipment information open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_ACCEPT = 0x54f,
+/*20070918 to latest
+(%s)님 장비창 보기
+Check %s's Equipment Info
+*/
+ MSG_REQ_VIEW_OTHERUSER = 0x550,
+/*20070918 to latest
+%s의 장착아이템
+'%s's Equipment
+*/
+ MSG_OTHERUSER_EQUIPED_ITEM = 0x551,
+/*20070918 to latest
+장비창 공개
+Show Equip
+*/
+ MSG_OPEN_EQUIPED_ITEM = 0x552,
+#endif
+#if PACKETVER >= 20071002
+/*20071002 to latest
+프리미엄 서비스를 이용해 주시기 바랍니다.
+This service is only available for premium users.
+*/
+ MSG_NEED_PREMIUM_SERVICE = 0x553,
+/*20071002 to latest
+무료 사용자는 최대 50000제니까지 소유할 수 있습니다.
+Free Trial users can only hold up to 50,000 zeny.
+*/
+ MSG_FR_INVALID_MONEY = 0x554,
+#endif
+#if PACKETVER >= 20071009
+/*20071009 to latest
+전장채팅 상태가 되었습니다.
+Battlefield Chat has been activated.
+*/
+ MSG_BATTLECHAT_ON = 0x555,
+/*20071009 to latest
+전장채팅 상태가 해제되었습니다.
+Battlefield Chat has been deactivated.
+*/
+ MSG_BATTLECHAT_OFF = 0x556,
+#endif
+#if PACKETVER >= 20071017
+/*20071017 to latest
+용병정보 - 몬스터타입
+Mercenary Info - Monster Type
+*/
+ MSG_MER_INFO_TYPE_MONSTER = 0x557,
+#endif
+#if PACKETVER >= 20071106
+/*20071106 to latest
+전체 맵 보기
+World Map
+*/
+ MSG_RO_MAP = 0x558,
+#endif
+#if PACKETVER >= 20071127
+/*20071127 to latest
+메모리얼던젼이 CLOSE 상태입니다.
+The Memorial Dungeon is now closed.
+*/
+ MSG_MEMORIAL_DUN_CLOSE = 0x559,
+#endif
+#if PACKETVER >= 20071204
+/*20071204 to latest
+^ff0000^ff0000용병을 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+^ff0000Deleting a Mercenary Soldier^000000 will also delete his growth history. Do you really want to proceed with the deletion?
+*/
+ MSG_DELETE_MER = 0x55a,
+#endif
+#if PACKETVER >= 20071211
+/*20071211 to latest
+메모리얼던젼이 OPEN 상태입니다.
+The Memorial Dungeon is now open.
+*/
+ MSG_MEMORIAL_DUN_OPEN = 0x55b,
+#endif
+#if PACKETVER >= 20080108
+/*20080108 to latest
+위의 계정은 아직 통신 안전 키에 연결되지 않았습니다. 먼저 안전 키를 해제하신 뒤 게임에 접속해 주십시오.
+This account has not been confirmed by connecting to the safe communication key. Please connect to the key first, and then log into the game.
+*/
+ MSG_PHONE_BLOCK = 0x55c,
+/*20080108 to latest
+한 아이피로 접속 가능한 유저수를 초과하였습니다.
+The number of accounts connected to this IP has exceeded the limit.
+*/
+ MSG_BAN_PC_IP_LIMIT_ACCESS = 0x55d,
+#endif
+#if PACKETVER >= 20080219
+/*20080219 to latest
+새로운 퀘스트를 받았습니다
+You have received a new quest.
+*/
+ MSG_QUESTGET = 0x55e,
+#endif
+#if PACKETVER >= 20080401
+/*20080401 to latest
+^777777습득조건 :
+^CC3399Requirement:
+*/
+ MSG_FINDTEXT_TO_SKILLDES = 0x55f,
+/*20080401 to latest
+스킬 설명 보기
+View Skill Info
+*/
+ MSG_VIEW_SKILL_DESCRIPT = 0x560,
+#endif
+#if PACKETVER >= 20080408
+/*20080408 to latest
+사용된 스킬 포인트는 다시 되돌릴 수 없습니다. 적용하시겠습니까?
+Once used, skill points cannot be re-allocated. Would you like to use the skill points?
+*/
+ MSG_APPLY_SKILL_UP = 0x561,
+/*20080408 to latest
+노비스·1차직업
+1st
+*/
+ MSG_1TABNAME_SKILLWND = 0x562,
+/*20080408 to latest
+2차·전승직업
+2nd
+*/
+ MSG_2TABNAME_SKILLWND = 0x563,
+/*20080408 to 20080514
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭시간 : %s
+20080520 to latest
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭종료시간 : %s
+This account has been used for illegal program or hacking program. Block Time: %s
+20081210 to 20081218
+불법프로그램을 사용하였거나 해킹을 시도한 계정이거나 그라비티 이전을 신청한 한게임 계정입니다. 블럭종료시간 : %s
+*/
+ MSG_RE17 = 0x564,
+/*20080408 to latest
+불법프로그램이 실행, 바이러스 감염, 또는 해킹툴이 설치되어 있을 가능성이 있습니다. 정상 클라이언트를 실행하여 주시기 바랍니다. 함께 만드는 밝은 라그나로크가 될 수 있도록 노력하고 있습니다.
+The possibility of exposure to illegal program, PC virus infection or Hacking Tool has been detected. Please execute licensed client. Our team is trying to make a best environment for Ro players.
+*/
+ MSG_RE18 = 0x565,
+#endif
+#if PACKETVER >= 20080415
+/*20080415 to latest
+당신은 지금 건강한 게임 시간 대에 있습니다, 즐거운 게임이 되시길 바랍니다
+You are currently playing in the best game environment. Please enjoy the Ragnarok.
+*/
+ MSG_WARNING_MSG3 = 0x566,
+/*20080415 to 20100720
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.5배로 증가합니다.
+20100727 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.25배로 증가합니다.
+Job Exp points from hunting monsters are increased by 50% for 30 minutes.
+*/
+ MSG_PLUSONLYJOBEXP = 0x567,
+/*20080415 to 20091110
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.25배로 증가합니다.
+20091117 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.2배로 증가합니다.
+Exp points from hunting monsters are increased by 25% for 30 minutes.
+*/
+ MSG_PLUSEXP14532 = 0x568,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 2배로 증가합니다.
+EXP points from hunting monsters are increased by 100%% for 30 minutes.
+*/
+ MSG_PLUSEXP14533 = 0x569,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 60분간 1.5배로 증가합니다.
+EXP points from hunting monsters are increased by 50% for 60 minutes.
+*/
+ MSG_PLUSEXP12312 = 0x56a,
+#endif
+#if PACKETVER >= 20080520
+/*20080520 to latest
+이 맵에서는 파티를 결성할 수 없습니다.
+Unable to organize a party in this map.
+*/
+ MSG_NOPARTY = 0x56b,
+/*20080520 to latest
+(%s)님은 파티에 참여할 수 없는 맵에 있습니다.
+(%s) are currently in restricted map to join a party.
+*/
+ MSG_NOPARTY2 = 0x56c,
+#endif
+#if PACKETVER >= 20080528
+/*20080528 to 20080603
+간편아이템샵.
+20080610 to latest
+간편아이템샵
+Simple Item Shop
+*/
+ MSG_SIMPLE_CASH_SHOP = 0x56d,
+/*20080528 to latest
+소지 한코인 : %d 한코인
+Han Coin: %d Han Coin
+*/
+ MSG_SIMPLE_POINT_SHOP_NHN = 0x56e,
+/*20080528 to latest
+소지 캐시 : %d 캐시
+RoK Point: %d RoK Point
+*/
+ MSG_SIMPLE_POINT_SHOP = 0x56f,
+/*20080528 to latest
+무료 캐시 : %d 캐시
+Free Cash: %d Cash
+*/
+ MSG_SIMPLE_POINT_SHOP2 = 0x570,
+#endif
+#if PACKETVER >= 20080715
+/*20080715 to latest
+본서버 유저는 프리서버에 접속할수 없습니다.
+An user of this server cannot connect to free server
+*/
+ MSG_MAIN_USER_CANONT_LOGIN_FREE_SERVER = 0x571,
+/*20080715 to latest
+유효기간이 지난 비밀번호 입니다. 다시 로그인하여주십시오.
+Your password has expired. Please log in again
+*/
+ MSG_INVALID_ONETIMELIMIT = 0x572,
+#endif
+#if PACKETVER >= 20080903
+/*20080903 to latest
+3차직업
+3rd
+*/
+ MSG_3TABNAME_SKILLWND = 0x573,
+#endif
+#if PACKETVER >= 20080917
+/*20080917 to latest
+이 스킬을 사용할 수 없는 대상입니다.
+This skill can't be used on that target.
+*/
+ MSG_USESKILL_FAIL_TOTARGET = 0x574,
+/*20080917 to latest
+안실라 소유 개수가 초과하여 스킬을 사용할 수 없습니다.
+You can't use skill because you have exceeded the number Ancilla possession limit
+*/
+ MSG_USESKILL_FAIL_ANCILLA_NUMOVER = 0x575,
+/*20080917 to latest
+성수가 필요합니다.
+Unable to use the skill to exceed the number of Ancilla.
+*/
+ MSG_USESKILL_FAIL_HOLYWATER = 0x576,
+/*20080917 to latest
+안실라가 필요합니다.
+Holy water is required.
+*/
+ MSG_USESKILL_FAIL_ANCILLA = 0x577,
+/*20080917 to latest
+일정거리 내에 중복될 수 없습니다.
+Ancilla is required.
+*/
+ MSG_USESKILL_FAIL_DUPLICATE_RANGEIN = 0x578,
+/*20080917 to latest
+이 스킬을 사용하기 위해서는 다른 스킬이 필요합니다.
+Cannot be duplicated within a certain distance.
+*/
+ MSG_USESKILL_FAIL_NEED_OTHER_SKILL = 0x579,
+#endif
+#if PACKETVER >= 20080924
+/*20080924 to latest
+이 맵에서는 채팅을 할 수 없습니다.
+This skill requires other skills to be used.
+*/
+ MSG_NO_CHATTING = 0x57a,
+#endif
+#if PACKETVER >= 20081001
+/*20081001 to latest
+3시간이 지났습니다.
+Chat is not allowed in this map
+*/
+ MSG_VET_3HOUR = 0x57b,
+/*20081001 to latest
+5시간이 지났습니다.
+3 hours have passed.
+*/
+ MSG_VET_5HOUR = 0x57c,
+#endif
+#if PACKETVER >= 20081008
+/*20081008 to latest
+게임가드 초기화 에러 또는 구버전의 게임가드 파일입니다. 게임가드 셋업파일을 다시 설치하고 게임을 실행해 보시기 바랍니다.
+5 hours have passed.
+*/
+ MSG_NPGAMEMON_ERROR_GAMEGUARD = 0x57d,
+/*20081008 to latest
+ini 파일이 없거나 변조되었습니다. 게임가드 셋업파일을 설치하면 해결 할 수 있습니다.
+Game guard initialization error or previous version game guard file is installed. Please re-install the setup file and try again
+*/
+ MSG_NPGMUP_ERROR_PARAM = 0x57e,
+/*20081008 to latest
+게임가드와 충돌 프로그램이 발견되었습니다.
+Either ini file is missing or altered. Install game guard setup file to fix the problem
+*/
+ MSG_NPGG_ERROR_COLLISION = 0x57f,
+#endif
+#if PACKETVER >= 20081112
+/*20081112 to latest
+잘못된 클라이언트입니다. 정상적인 클라이언트를 실행하여 주십시요.
+There is a program found that conflicts with game guard
+*/
+ MSG_PROOF_ERROR = 0x580,
+#endif
+#if PACKETVER >= 20081203
+/*20081203 to latest
+모바일 인증을 받아주시기 바랍니다.
+Incorrect client. Please run a normal client
+*/
+ MSG_MOBILE_LOCKSERVER = 0x581,
+#endif
+#if PACKETVER >= 20081210
+/*20081210 to latest
+모바일 인증에 실패하였습니다.
+Thank you to accept mobile authentication.
+*/
+ MSG_FAILED_MOBILE_LOCKSERVER = 0x582,
+#endif
+#if PACKETVER >= 20081217
+/*20081217 to latest
+이스킬은 혼자서 사용할수 없습니다.
+This skill can't be used alone
+*/
+ MSG_USESKILL_FAIL_NEED_HELPER = 0x583,
+/*20081217 to latest
+이스킬은 특정방향으로만 사용할수 있습니다.
+This skill can be used to certain direction only
+*/
+ MSG_USESKILL_FAIL_INVALID_DIR = 0x584,
+/*20081217 to latest
+더이상 소환할수 없습니다.
+Cannot summon spheres anymore.
+*/
+ MSG_USESKILL_FAIL_SUMMON = 0x585,
+/*20081217 to 20130710
+소환된 구체가 존재하지 않습니다.
+20130717 to latest
+소환된 구체가 존재하지 않거나 부족합니다.
+There is no summoned sphere or you do not have enough sphere.
+*/
+ MSG_USESKILL_FAIL_SUMMON_NONE = 0x586,
+/*20081217 to latest
+사용가능한 모방스킬이 존재하지 않습니다.
+There is no imitation skills available.
+*/
+ MSG_USESKILL_FAIL_IMITATION_SKILL_NONE = 0x587,
+/*20081217 to latest
+이 스킬은 중복해서 사용할수 없습니다.
+You can't reuse this skill
+*/
+ MSG_USESKILL_FAIL_DUPLICATE = 0x588,
+/*20081217 to latest
+스킬을 사용할수 없는 상태입니다.
+Skill can't be used in this state
+*/
+ MSG_USESKILL_FAIL_CONDITION = 0x589,
+/*20081217 to latest
+아이템별 최대 소지량을 초과하여 가질 수 없습니다.
+You have exceeded the maximum amount of possession of another item.
+*/
+ MSG_PICKUP_MAXCOUNT_LIMIT = 0x58a,
+#endif
+#if PACKETVER >= 20090204
+/*20090204 to latest
+관리자 권한이 없습니다. 프로그램 최초 실행은 관리자 권한으로 실행하셔야 합니다.
+No administrative privileges. Must first run the program with administrator privileges.
+*/
+ MSG_NPK_ERROR_NOTADMIN = 0x58b,
+/*20090204 to latest
+nProtect KeyCrypt 드라이버 버전이 맞지 않습니다. 시스템 재 부팅 후에 새로 실행 시켜 주십시오.
+nProtect KeyCrypt not the same. Please restart the program and the computer first.
+*/
+ MSG_NPK_ERROR_DRIVERVERSION = 0x58c,
+/*20090204 to latest
+WindowXP 호환성 모드를 사용하고 계십니다. 현재 프로그램에서 호환성 모드를 제거하였습니다. 프로그램을 새로 시작해 주십시오.
+Currently wearing WindowXP Compatibility Mode. The program now removes Compatibility Mode. Please restart the program.
+*/
+ MSG_NPK_ERROR_VERIFYVERSION = 0x58d,
+/*20090204 to latest
+PS/2 키로거가 존재합니다.
+PS/2 keyloggers exist.
+*/
+ MSG_DETECT_PS2KEYLOGGER = 0x58e,
+/*20090204 to latest
+USB 키보드 드라이버 해킹 시도가 탐지되었습니다.
+USB Keylogging attempt was detected.
+*/
+ MSG_DETECT_USBKEYLOGGER = 0x58f,
+/*20090204 to latest
+HHD 모니터링 툴이 탐지되었습니다.
+HHD monitoring tool has been detected.
+*/
+ MSG_DETECT_HHDUSBH = 0x590,
+/*20090204 to latest
+페인트붓이 필요합니다.
+Paintbrush is required.
+*/
+ MSG_USESKILL_FAIL_PAINTBRUSH = 0x591,
+/*20090204 to 20090401
+그림물감이 필요합니다.
+20090406 to latest
+서페이스페인트가 필요합니다.
+Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_SURFACE_PAINTS = 0x592,
+/*20090204 to latest
+지정한 위치에 스킬을 사용할수 없습니다.
+Use the skills that are not at the specified location.
+*/
+ MSG_USESKILL_FAIL_POS = 0x593,
+/*20090204 to latest
+도우미의 SP가 부족합니다.
+Not enough SP.
+*/
+ MSG_USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 0x594,
+#endif
+#if PACKETVER >= 20090211
+/*20090211 to 20090218
+생성 가능 캐릭터 수는 9개입니다!!(임시)
+20090225 to latest
+캐릭터 선택창의 캐릭터가 %d개를 초과하면 게임에 접속할 수 없습니다. 불필요한 캐릭터를 삭제해주십시오.
+Character %d is character selection window cannot connect to the game that exceeds the total. Please remove unwanted characters.
+*/
+ MSG_BAN_OVER_CHARACTER_LIST = 0x595,
+#endif
+#if PACKETVER >= 20090225
+/*20090225 to latest
+목캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_NECK_CANDY = 0x596,
+/*20090225 to latest
+안타까운눈물이 필요합니다.
+Painful Tears is required.
+*/
+ MSG_USESKILL_FAIL_II_MISERABLE_TEAR = 0x597,
+/*20090225 to latest
+목 보호 캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_PROTECT_NECK_CANDY = 0x598,
+/*20090225 to latest
+웨폰 블로킹의 연계로만 사용가능합니다.
+Cooperation is only available with Weapon Blocking.
+*/
+ MSG_USESKILL_FAIL_GC_WEAPONBLOCKING = 0x599,
+/*20090225 to latest
+길로틴크로스의 독을 바른 무기가 필요합니다.
+Poisoned weapons is required.
+*/
+ MSG_USESKILL_FAIL_GC_POISONINGWEAPON = 0x59a,
+#endif
+#if PACKETVER >= 20090304
+/*20090304 to latest
+마도기어 탑승시에만 사용가능합니다.
+Item can only be used when Mado Gear is mounted.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR = 0x59b,
+/*20090304 to latest
+발칸블릿이 필요합니다.
+Vulcan Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_VULCANBULLET = 0x59c,
+/*20090304 to latest
+마도기어 연료가 필요합니다.
+Mado Gear Fuel is required.
+*/
+ MSG_USESKILL_FAIL_II_FUELGAS = 0x59d,
+/*20090304 to latest
+액체냉각탄이 필요합니다.
+Liquid Cold Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_COLDSLOWERBULLET = 0x59e,
+/*20090304 to latest
+캐논볼을 장전 하세요.
+Please load a Cannon Ball.
+*/
+ MSG_USESKILL_FAIL_CANONBALL = 0x59f,
+/*20090304 to latest
+미도기어 가속장치를 착용하세요.
+Please equipped with a Mado Gear Accelerator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 0x5a0,
+/*20090304 to latest
+호버링부스터를 착용하세요.
+Please equipped with a Hovering Booster.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 0x5a1,
+/*20090304 to latest
+[톡신] 독 효과가 무기에 적용되었습니다.
+[Toxin] Poison effect was applied to the weapon.
+*/
+ MSG_TOXIN = 0x5a2,
+/*20090304 to latest
+[패럴라이즈] 독 효과가 무기에 적용되었습니다.
+[Paralysis] Poison effect was applied to the weapon.
+*/
+ MSG_PARALYZE = 0x5a3,
+/*20090304 to latest
+[베놈블리드] 독 효과가 무기에 적용되었습니다.
+[Fatigue] Poison effect was applied to the weapon.
+*/
+ MSG_VENOMBLEED = 0x5a4,
+/*20090304 to latest
+[매직 머쉬룸] 독 효과가 무기에 적용되었습니다.
+[Laughing] Poison effect was applied to the weapon.
+*/
+ MSG_MAGICMUSHROOM = 0x5a5,
+/*20090304 to latest
+[데스 허트] 독 효과가 무기에 적용되었습니다.
+[Disheart] Poison effect was applied to the weapon.
+*/
+ MSG_DEATHHURT = 0x5a6,
+/*20090304 to latest
+[파이렉시아] 독 효과가 무기에 적용되었습니다.
+[Pyrexia] Poison effect was applied to the weapon.
+*/
+ MSG_PHYREXIA = 0x5a7,
+/*20090304 to latest
+[오블리비언 커즈] 독 효과가 무기에 적용되었습니다.
+[Oblivion] Poison effect was applied to the weapon.
+*/
+ MSG_OBLIANCURSE = 0x5a8,
+/*20090304 to latest
+[리치 엔드] 독 효과가 무기에 적용되었습니다.
+[Leech] Poison effect was applied to the weapon.
+*/
+ MSG_RICHEND = 0x5a9,
+#endif
+#if PACKETVER >= 20090311
+/*20090311 to latest
+호버링상태에서만 사용가능합니다.
+Can only be used in Hovering state.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_HOVERING = 0x5aa,
+/*20090311 to latest
+자폭장치를 장착하세요.
+Please equip a Self-Destruct Mechanism.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 0x5ab,
+/*20090311 to latest
+셰이프쉬프터를 장착하세요.
+Please equip a Shape Shift.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 0x5ac,
+/*20090311 to latest
+길로틴독이 필요합니다.
+Guillotine Cross Poison is required.
+*/
+ MSG_USESKILL_FAIL_GUILLONTINE_POISON = 0x5ad,
+/*20090311 to latest
+냉각장치를 장착하세요.
+Please equipped with a Cooling System.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 0x5ae,
+/*20090311 to latest
+자기장필드생성기를 착용하세요.
+Please equipped with a Magnetic Field Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 0x5af,
+/*20090311 to latest
+베리어생성기를 착용하세요.
+Please equipped with a Barrier Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 0x5b0,
+/*20090311 to latest
+광학미채발생기를 착용하세요.
+Please equipped with a Optical Camouflage Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 0x5b1,
+/*20090311 to latest
+리페어키트를 착용하세요.
+Please equipped with a Repair Kit.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 0x5b2,
+/*20090311 to latest
+몽키 스패너가 필요합니다.
+Monkey Wrench is required.
+*/
+ MSG_USESKILL_FAIL_II_MONKEY_SPANNER = 0x5b3,
+#endif
+#if PACKETVER >= 20090312
+/*20090312 to 20090312
+'%s' 시전 시간까지 약 %d 분 남았습니다.
+20090318 to latest
+[%s] 스킬을 시전 할 수 없습니다.
+[%s] Cannot use the skills due to cooldown delay.
+*/
+ MSG_SKILLINTERVAL2 = 0x5b4,
+#endif
+#if PACKETVER >= 20090318
+/*20090318 to latest
+%d레벨 이상은 삭제가 불가능합니다.
+Deletion is impossible for over level %d
+*/
+ MSG_LEMIT_DELETE_LEVEL = 0x5b5,
+/*20090318 to 20110614
+마도기어 탑승시에는 사용할수 없습니다.
+20110620 to latest
+마도기어 탑승시에는 사용 할 수 없습니다.
+Can't be used while on Magic Gear.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_RIDE = 0x5b6,
+#endif
+#if PACKETVER >= 20090325
+/*20090325 to latest
+드래곤 내리기
+Dismount Dragon
+*/
+ MSG_DRAGONOFF = 0x5b7,
+/*20090325 to latest
+마도기어 내리기
+Dismount Magic Gear
+*/
+ MSG_MADOOFF = 0x5b8,
+#endif
+#if PACKETVER >= 20090401
+/*20090401 to latest
+소비
+I
+*/
+ MSG_STORE_TABNAME_0 = 0x5b9,
+/*20090401 to latest
+캐쉬
+Cash
+*/
+ MSG_STORE_TABNAME_1 = 0x5ba,
+/*20090401 to latest
+방어구
+Armors
+*/
+ MSG_STORE_TABNAME_2 = 0x5bb,
+/*20090401 to latest
+무기
+Weapons
+*/
+ MSG_STORE_TABNAME_3 = 0x5bc,
+/*20090401 to latest
+투사체
+Ammo
+*/
+ MSG_STORE_TABNAME_4 = 0x5bd,
+/*20090401 to latest
+카드
+Card
+*/
+ MSG_STORE_TABNAME_5 = 0x5be,
+/*20090401 to latest
+기타
+Other
+*/
+ MSG_STORE_TABNAME_6 = 0x5bf,
+/*20090401 to latest
+클라이언트 응답시간이 초과되어 연결이 끊어집니다.
+Client response time has passed so connection is terminated
+*/
+ MSG_ERROR_HS_TIMEOUT = 0x5c0,
+/*20090401 to latest
+핵쉴드 파일의 버전이 맞지 않습니다. 클라이언트를 재설치 해주십시오.
+Incorrect version of hack shield file. Please reinstall the client
+*/
+ MSG_ERROR_DIFF_CLIENT = 0x5c1,
+#endif
+#if PACKETVER >= 20090406
+/*20090406 to latest
+마법서가 필요합니다.
+[Magic Book] is required.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK = 0x5c2,
+/*20090406 to latest
+마법서가 너무 어려워서 졸음이 몰려온다.
+Feel sleepy since Magic Book is too difficult to understand.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 0x5c3,
+/*20090406 to latest
+보존포인트가 부족합니다.
+Not enough saved point.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 0x5c4,
+/*20090406 to latest
+더이상 마법서를 읽을수 없습니다.
+Can't read a Magic Book anymore.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_READING = 0x5c5,
+/*20090406 to latest
+페이스페인트가 필요합니다.
+Face Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_FACE_PAINTS = 0x5c6,
+/*20090406 to latest
+분장용붓이 필요합니다.
+Brush is required.
+*/
+ MSG_USESKILL_FAIL_II_MAKEUP_BRUSH = 0x5c7,
+#endif
+#if PACKETVER >= 20090408
+/*20090408 to latest
+대기 시간이 초과하였습니다. 다시 로그인 해주십시오.
+Waiting time has passed. Please log in again
+*/
+ MSG_MOBILE_TIMEOVER = 0x5c8,
+/*20090408 to latest
+위험! 이미 동일한 계정이 로그인 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is already logged in. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_ANOTHER_LOGIN = 0x5c9,
+/*20090408 to latest
+위험! 현재 동일한 계정이 모바일 인증 대기 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is waiting for mobile verification. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_WAITING_STATE = 0x5ca,
+#endif
+#if PACKETVER >= 20090506
+/*20090506 to latest
+게임 옵션창
+Game setting window
+*/
+ MSG_ESC_OPTIONWND = 0x5cb,
+/*20090506 to latest
+그래픽 설정
+Graphics Settings
+*/
+ MSG_GRAPHIC_OPTIONWND = 0x5cc,
+/*20090506 to latest
+사운드 설정
+Sound Settings
+*/
+ MSG_SOUND_OPTIONWND = 0x5cd,
+#endif
+#if PACKETVER >= 20090514
+/*20090514 to latest
+변경 할 단축키를 누르거나, 'ESC'키를 눌러 삭제 해 주세요.
+Press a key to assign. Pressing 'ESC' will remove the assigned key.
+*/
+ MSG_HOTKEYWND_NOTICE1 = 0x5ce,
+/*20090514 to latest
+단일 키로 지정 할 수 없는 키입니다.
+Unable to specify a single key.
+*/
+ MSG_HOTKEYWND_NOTICE2 = 0x5cf,
+/*20090514 to latest
+지정 할 수 없는 키입니다.
+Unable to specify the key assigned.
+*/
+ MSG_HOTKEYWND_NOTICE3 = 0x5d0,
+/*20090514 to latest
+'%s'에 사용된 단축키와 중복됩니다. 바꾸시겠습니까?
+Duplicated with ['%s']. Do you still want to change?
+*/
+ MSG_HOTKEYWND_NOTICE4 = 0x5d1,
+/*20090514 to latest
+저장된 단축키 조합이 초기화 됩니다. 초기화 하시겠습니까?
+Initialization is stored in the shortcut key settings. Do you want to initialized?
+*/
+ MSG_HOTKEYWND_NOTICE5 = 0x5d2,
+/*20090514 to latest
+스킬바
+Skill Bar
+*/
+ MSG_HOTKEYWND_TAB1 = 0x5d3,
+/*20090514 to latest
+인터페이스
+Interface
+*/
+ MSG_HOTKEYWND_TAB2 = 0x5d4,
+/*20090514 to latest
+이모션
+Macros
+*/
+ MSG_HOTKEYWND_TAB3 = 0x5d5,
+/*20090514 to latest
+단축키 설정 창
+Shortcut Settings
+*/
+ MSG_HOTKEYWND_TITLE = 0x5d6,
+#endif
+#if PACKETVER >= 20090520
+/*20090520 to latest
+배경음
+BGM
+*/
+ MSG_BGM = 0x5d7,
+/*20090520 to latest
+효과음
+Effect
+*/
+ MSG_SOUND = 0x5d8,
+/*20090520 to latest
+스킨
+Skin
+*/
+ MSG_SKIN = 0x5d9,
+/*20090520 to latest
+채팅방 입장음만 소리남 On
+Chat room entrance sound on
+*/
+ MSG_TINGONLY_ON = 0x5da,
+/*20090520 to latest
+채팅방 입장음만 소리남 Off
+Chat room entrance sound off
+*/
+ MSG_TINGONLY_OFF = 0x5db,
+/*20090520 to latest
+/tingonly : 채팅방 입장음만 들을수있게됩니다
+/tingonly: you can hear only sound like a chat room entry.
+*/
+ MSG_EXPLAIN_TINGONLY = 0x5dc,
+/*20090520 to latest
+/주먹
+/rock
+*/
+ MSG_EMOTION_ROCK = 0x5dd,
+/*20090520 to latest
+/가위
+/scissors
+*/
+ MSG_EMOTION_SCISSOR = 0x5de,
+/*20090520 to latest
+/보
+/paper
+*/
+ MSG_EMOTION_WRAP = 0x5df,
+/*20090520 to latest
+/러브
+/love
+*/
+ MSG_EMOTION_LUV = 0x5e0,
+/*20090520 to latest
+/mobile
+*/
+ MSG_EMOTION_MOBILE = 0x5e1,
+/*20090520 to latest
+/mail
+*/
+ MSG_EMOTION_MAIL = 0x5e2,
+/*20090520 to latest
+/antenna0
+*/
+ MSG_EMOTION_ANTENNA0 = 0x5e3,
+/*20090520 to latest
+/antenna1
+*/
+ MSG_EMOTION_ANTENNA1 = 0x5e4,
+/*20090520 to latest
+/antenna2
+*/
+ MSG_EMOTION_ANTENNA2 = 0x5e5,
+/*20090520 to latest
+/antenna3
+*/
+ MSG_EMOTION_ANTENNA3 = 0x5e6,
+/*20090520 to latest
+/hum
+*/
+ MSG_EMOTION_HUM2 = 0x5e7,
+/*20090520 to latest
+/abs
+*/
+ MSG_EMOTION_ABS = 0x5e8,
+/*20090520 to latest
+/oops
+*/
+ MSG_EMOTION_OOPS = 0x5e9,
+/*20090520 to latest
+/spit
+*/
+ MSG_EMOTION_SPIT = 0x5ea,
+/*20090520 to latest
+/ene
+*/
+ MSG_EMOTION_ENE = 0x5eb,
+/*20090520 to latest
+/panic
+*/
+ MSG_EMOTION_PANIC = 0x5ec,
+/*20090520 to latest
+/whisp
+*/
+ MSG_EMOTION_WHISP = 0x5ed,
+#endif
+#if PACKETVER >= 20090527
+/*20090527 to latest
+지정안함
+Not Assigned
+*/
+ MSG_HOTKEY_NOTHING = 0x5ee,
+#endif
+#if PACKETVER >= 20090603
+/*20090603 to latest
+카트장착시에만 사용가능합니다.
+Only available when cart is mounted.
+*/
+ MSG_USESKILL_FAIL_CART = 0x5ef,
+/*20090603 to latest
+[가시나무 씨앗]이 필요합니다.
+[Thorny Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_THORNS_SEED = 0x5f0,
+/*20090603 to latest
+[흡혈 식물 씨앗]이 필요합니다.
+[Bloodsucker Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 0x5f1,
+/*20090603 to latest
+더이상 시전할수 없습니다.
+Cannot be used anymore.
+*/
+ MSG_USESKILL_FAIL_NO_MORE_SPELL = 0x5f2,
+/*20090603 to latest
+[폭탄버섯포자]가 필요합니다.
+[Bomb Mushroom Spore] is required.
+*/
+ MSG_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 0x5f3,
+/*20090603 to latest
+[화염병]이 필요합니다.
+[Fire Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_GASOLINE_BOOMB = 0x5f4,
+/*20090603 to latest
+[기름병]이 필요합니다.
+[Oil Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_OIL_BOTTLE = 0x5f5,
+/*20090603 to latest
+[폭발가루]가 필요합니다.
+[Explosive Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_EXPLOSION_POWDER = 0x5f6,
+/*20090603 to latest
+[연막가루]가 필요합니다.
+[Smokescreen Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_SMOKE_POWDER = 0x5f7,
+/*20090603 to latest
+[최루가스]가 필요합니다.
+[Tear Gas] is required.
+*/
+ MSG_USESKILL_FAIL_II_TEAR_GAS = 0x5f8,
+/*20090603 to latest
+[염산병]이 필요합니다.
+[Acid Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 0x5f9,
+/*20090603 to latest
+[식인식물병]이 필요합니다.
+[Bottom Man-Eating Plant] is required.
+*/
+ MSG_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 0x5fa,
+/*20090603 to latest
+[만드라고라의 화분]이 필요합니다.
+[Pot of Mandragora] is required.
+*/
+ MSG_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 0x5fb,
+/*20090603 to latest
+파티장 위임
+Party delegation
+*/
+ MSG_YIELD_PARTYMASTER = 0x5fc,
+/*20090603 to latest
+정말 파티장을 위임하시겠습니까?
+Do you want to delegate the real party?
+*/
+ MSG_DO_YOU_REALLY_WANT_YIELD_PARTYMASTER = 0x5fd,
+/*20090603 to latest
+파티장을 위임 할 수 없습니다.
+Party cannot be delegated.
+*/
+ MSG_CANNOT_YIELD_PARTYMASTER = 0x5fe,
+/*20090603 to latest
+변경불가
+Immutable
+*/
+ MSG_FAILED_CHANGE = 0x5ff,
+#endif
+#if PACKETVER >= 20090610
+/*20090610 to latest
+[%s]가 %d개 필요합니다.
+[%s] required '%d' amount.
+*/
+ MSG_USESKILL_FAIL_NEED_ITEM = 0x600,
+/*20090610 to latest
+제련 수치가 하향 조정 되었습니다.
+Is now refining the value lowered.
+*/
+ MSG_ITEM_REFINING_DOWNGRADE = 0x601,
+/*20090610 to latest
+[%s]를 장비하고 있어야 사용할 수 있습니다
+Need to put on [%s] in order to use.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT = 0x602,
+#endif
+#if PACKETVER >= 20090617
+/*20090617 to 20090922
+전장 리스트
+20090929 to latest
+전장 입장 설정
+Battle field entrance setting
+*/
+ MSG_BATTLEFIELD_LIST = 0x603,
+/*20090617 to 20090929
+전장 - [%s] 신청 하시겠습니까?
+20091006 to latest
+% 전장으로 이동 할 수 없는 상태가 되어 전장 신청이 취소 되었습니다.
+Battlefield - [%s] you sign up?
+*/
+ MSG_CANNOT_JOINTO_BATTLEFIELD = 0x604,
+/*20090617 to 20090715
+전장 - [%s] 입장 신청이 완료되었습니다.
+20090722 to 20090929
+입장 신청이 완료되었습니다.
+20091006 to 20100928
+
+20101005 to latest
+
+Current admission application state.
+*/
+ MSG_COMPLETED_JOINTO_BATTLEFIELD = 0x605,
+/*20090617 to 20090624
+전장 - [%s] 입장 하실 수 없습니다.
+20090701 to 20090715
+전장 - [%s] 에 입장 할 수 없는 상태이므로 등록이 취소 되었습니다.
+20090722 to 20090929
+에 입장 할 수 없는 상태이므로 등록이 취소 되었습니다.
+20091006 to latest
+% 전장 입장이 보류 되었습니다. 다른 플레이어를 기다립니다.
+It was unregistered and not be able to enter the state.
+*/
+ MSG_DIFFER_JOINTO_BATTLEFIELD = 0x606,
+/*20090617 to 20090929
+현재 입장 신청 상태입니다.
+20091006 to 20100928
+
+20101005 to latest
+
+Current admission application state.
+*/
+ MSG_STATUS_JOINTO_BATTLEFIELD = 0x607,
+/*20090617 to 20090929
+입장 신청을 취소하시겠습니까?
+20091006 to 20100616
+%s 전장 신청을 정말로 취소하시겠습니까?
+20100622 to latest
+확인 단추를 누르면 전장 신청이 취소됩니다. 아래 단추를 클릭해 주세요.
+Do you want to cancel the admission application?
+*/
+ MSG_REQ_CANCEL_JOINTO_BATTLEFIELD = 0x608,
+/*20090617 to 20090715
+전장 - [%s] 입장 신청이 취소되었습니다.
+20090722 to 20090929
+입장 신청이 취소되었습니다.
+20091006 to latest
+%s 전장 입장 신청이 취소되었습니다.
+Admission request has been cancelled.
+*/
+ MSG_CANCEL_JOINTO_BATTLEFIELD = 0x609,
+/*20090617 to 20090929
+곧 전장으로 이동 합니다.
+20091006 to latest
+잠시후 %s 전장으로 이동 합니다. 공간 이동을 위한 안정적인 상태를 확보해 주시길 바랍니다. (거래 및 공간 이동 기능 일시 중지됨)
+Go to the battlefield quickly.
+*/
+ MSG_MOVETO_BATTLEFIELD = 0x60a,
+/*20090617 to 20091028
+전장 - [%s]
+20091103 to latest
+전장 명칭
+Battlefield - [%s]
+*/
+ MSG_BATTLEFIELD_NAME = 0x60b,
+#endif
+#if PACKETVER >= 20090624
+/*20090624 to latest
+정말 이동 하시겠습니까?
+Do you really want to go back to your savepoint?
+*/
+ MSG_MOVETO_SAVEPOINT = 0x60c,
+/*20090624 to latest
+파티원 찾기 메세지
+Search Message for Party Members
+*/
+ MSG_VIEW_SEEK_PARTY = 0x60d,
+/*20090624 to latest
+파티원 찾기 메세지 옵션이 꺼져있습니다.
+Message option is off the search party members.
+*/
+ MSG_UNVIEW_SEEK_PARTY = 0x60e,
+/*20090624 to latest
+10초간 파티 지원 딜레이가 걸려있습니다.
+10 seconds delay of party support is in effect
+*/
+ MSG_SEEK_PARTY_DEALY = 0x60f,
+#endif
+#if PACKETVER >= 20090701
+/*20090701 to latest
+ 파티장은 '%s' 님 입니다.
+Party leader is '%s'.
+*/
+ MSG_NOTIFY_PARTY_ROLE_MASTER = 0x610,
+/*20090701 to 20090715
+전장 - [%s] : 시스템 오류로 입장 할 수 없습니다.
+20090722 to latest
+시스템 오류로 입장 할 수 없습니다.
+Unable to enter due to system error.
+*/
+ MSG_ERROR_SYSTEM_ERROR_BATTLEFIELD = 0x611,
+/*20090701 to 20090715
+전장 - [%s] : 대기 인원 수 초과로 입장 할 수 없습니다.
+20090722 to latest
+대기 인원 수 초과로 입장 할 수 없습니다.
+Cannot wait to enter the number of excess.
+*/
+ MSG_ERROR_FULL_ESROOM_BATTLEFIELD = 0x612,
+/*20090701 to 20090715
+전장 - [%s] : 이미 신청 되었습니다.
+20090722 to latest
+이미 신청 되었습니다.
+Has already been applied.
+*/
+ MSG_ERROR_DOUBLE_OFFER_BATTLEFIELD = 0x613,
+/*20090701 to 20090715
+전장 - [%s] : 대기 시간이 초과되어 등록이 취소 되었습니다.
+20090722 to latest
+대기 시간이 초과되어 등록이 취소 되었습니다.
+Registration has been cancelled because of the excessive waiting time.
+*/
+ MSG_ERROR_WAIT_TIMEOUT_BATTLEFIELD = 0x614,
+/*20090701 to 20090715
+전장 - [%s] : 입장 조건이 맞지 않아, 등록이 취소 되었습니다.
+20090722 to latest
+입장 조건이 맞지 않아, 등록이 취소 되었습니다.
+Unregistered because admission requirements are not matching.
+*/
+ MSG_ERROR_BATTLEFILD_ENTER_BATTLEFIELD = 0x615,
+/*20090701 to 20090715
+전장 - [%s] : 오류가 발생하여 등록이 취소 되었습니다.
+20090722 to latest
+오류가 발생하여 등록이 취소 되었습니다.
+Was unregistered and error.
+*/
+ MSG_ERROR_DROP_ENTRANCESTATION_BATTLEFIELD = 0x616,
+#endif
+#if PACKETVER >= 20090708
+/*20090708 to latest
+[%s]의 연계 스킬입니다.
+The skill need [%s].
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL = 0x617,
+/*20090708 to latest
+특정스킬 의 연계 스킬입니다.
+The skill need a particular skill.
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL2 = 0x618,
+/*20090708 to latest
+기구체 %d 개가 필요합니다
+Requires %d mind bullets
+*/
+ MSG_USESKILL_FAIL_SPIRITS = 0x619,
+/*20090708 to 20090708
+기구체 %d 개가 필요합니다
+Requires %d mind bullets
+20090715 to latest
+기구체가 필요합니다
+Mind Bullet is required.
+*/
+ MSG_USESKILL_FAIL_SPIRITS2 = 0x61a,
+#endif
+#if PACKETVER >= 20090729
+/*20090729 to latest
+최대 소지량 보다 많은 룬스톤을 제작할 수 없습니다.
+Cannot create rune stone more than the maximum amount.
+*/
+ MSG_RUNESTONE_MAKEERROR_OVERCOUNT = 0x61b,
+/*20090729 to latest
+전장 리스트를 받을 수 없는 상태입니다. 확인 후 다시 시도 해 주세요.
+Not able to receive battle field list. Please check and try again
+*/
+ MSG_ERROR_LIST_OPEN_BATTLEFIELD = 0x61c,
+/*20090729 to latest
+레벨이 부족하여 입장 할 수 없습니다.
+Level is not high enough to enter
+*/
+ MSG_ERROR_LEVEL_LIMIT_BATTLEFIELD = 0x61d,
+#endif
+#if PACKETVER >= 20090805
+/*20090805 to latest
+ 1차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' points in your 1st Tab.
+*/
+ MSG_UPGRADESKILLERROR_MORE_FIRSTJOBSKILL = 0x61e,
+#endif
+#if PACKETVER >= 20091013
+/*20091013 to latest
+ 1차 혹은 2차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' remaining points in your 2nd Tab. 1st Tab is already done.
+*/
+ MSG_UPGRADESKILLERROR_MORE_SECONDJOBSKILL = 0x61f,
+/*20091013 to latest
+변환 가능한 아이템
+Items available for conversion
+*/
+ MSG_ITEMSYOUCANCHANGE = 0x620,
+/*20091013 to latest
+변환할 아이템
+Insert items to convert
+*/
+ MSG_ITEMS_FOR_CHANGE = 0x621,
+/*20091013 to latest
+변환이 불가능한 조합 입니다.
+Inconvertible combination
+*/
+ MSG_SKILL_RECIPE_NOTEXIST = 0x622,
+/*20091013 to latest
+인벤토리의 무게가 너무 무겁습니다.
+Inventory weight is too much
+*/
+ MSG_SKILL_INVENTORY_WEIGHT_OVER = 0x623,
+/*20091013 to latest
+인벤토리를 공간을 확보해주세요.
+Please secure some room in the inventory
+*/
+ MSG_SKILL_INVENTORY_KINDCNT_OVER = 0x624,
+/*20091013 to latest
+재료가 존재하지 않습니다.
+Material doesn't exist
+*/
+ MSG_SKILL_MATERIAL_FAIL = 0x625,
+/*20091013 to latest
+성공하였습니다.
+Successful.
+*/
+ MSG_SKILL_SUCCESS = 0x626,
+/*20091013 to latest
+실패 하였습니다.
+Failed.
+*/
+ MSG_SKILL_FAIL = 0x627,
+/*20091013 to latest
+실패하여 모든 재료가 사라졌습니다.
+all materials are gone due to failure
+*/
+ MSG_SKILL_FAIL_MATERIAL_DESTROY = 0x628,
+/*20091013 to latest
+지정하신 탭 이름이 너무 길어 변경 할 수 없습니다.
+unable to change the name of the specified tab, because it's too long.
+*/
+ MSG_FAILED_CHANGE_TABNAME = 0x629,
+/*20091013 to latest
+더 이상 추가 할 수 없습니다.
+Cannot add more.
+*/
+ MSG_FAILED_ADD_TAB = 0x62a,
+/*20091013 to latest
+인증에 실패 했습니다.
+Authentication failed.
+*/
+ MSG_FAILED_LOCKSERVER = 0x62b,
+/*20091013 to 20101012
+봇 체크
+20101019 to 20101019
+자동 로그인 방지
+20101026 to latest
+자동 입력 방지
+Bot checks
+*/
+ MSG_BOT_CHECK = 0x62c,
+/*20091013 to latest
+감정이 않된 아이템은 재료로 사용할 수 없습니다.
+Items cannot be used in materials cannot be emotional.
+*/
+ MSG_SKILL_FAIL_MATERIAL_IDENTITY = 0x62d,
+/*20091013 to latest
+접속하신 IP는 라그나로크 온라인 이용이 불가능 합니다. 고객 지원 센터 또는 홈페이지로 문의 해 주십시오.
+It is impossible to connect using this IP in Ragnarok Online. Please contact the customer support center or home.
+*/
+ MSG_BAN_IP_BLOCK = 0x62e,
+/*20091013 to latest
+비밀번호가 6회 이상 잘못 입력되어 잠시 동안 접속이 제한됩니다. 고객님의 개인정보를 다시 한 번 확인해 주시길 바랍니다.
+You have entered a wrong password for more than six times, please check your personal information again.
+*/
+ MSG_BAN_INVALID_PWD_CNT = 0x62f,
+/*20091013 to latest
+합성에 사용한 아이템은 소모됩니다. 괜찮겠습니까?
+Consumption items are used in the synthesis. Are you sure?
+*/
+ MSG_MIX_ACCEPT = 0x630,
+/*20091013 to latest
+왼쪽에 보이는 글자 및 숫자조합을 입력해주세요.
+Please input the captcha code found at your left side.
+*/
+ MSG_BOT_CHECK_NOTIC = 0x631,
+/*20091013 to latest
+전장 설명 -
+Describes the battlefield --
+*/
+ MSG_DESCRIBE_BATTLEFIELD = 0x632,
+/*20091013 to latest
+입장 대기 상태 -
+Waiting for admission --
+*/
+ MSG_BATTLEFIELD_STATUS = 0x633,
+/*20091013 to latest
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_HELP = 0x634,
+#endif
+#if PACKETVER >= 20091015
+/*20091015 to latest
+죄송합니다. 해당 직업의 캐릭터는 현재 테스트를 위해서 접속이 금지됩니다.
+Sorry the character you are trying to use is banned for testing connection.
+*/
+ MSG_BAN_NOT_ALLOWED_JOBCLASS = 0x635,
+#endif
+#if PACKETVER >= 20091027
+/*20091027 to latest
+모든 장비 해제
+Remove all equipment
+*/
+ MSG_REMOVE_EQUIPEDITEM = 0x636,
+#endif
+#if PACKETVER >= 20091103
+/*20091103 to latest
+미니 아이콘
+Mini Icon
+*/
+ MSG_MINI_ICON = 0x637,
+/*20091103 to latest
+진영 A : 진영 B
+Camp A: Camp B
+*/
+ MSG_BATTLEFIELD_TEAM = 0x638,
+/*20091103 to 20100616
+대기 상태
+20100622 to latest
+대기열
+Wait
+*/
+ MSG_WAIT_STATUS = 0x639,
+/*20091103 to latest
+전장 신청 취소 알림
+cancellation notice of Battlefield registration.
+*/
+ MSG_NOTIFY_BATTLEFIELD_CANCEL = 0x63a,
+/*20091103 to latest
+전장 필요 인원
+Required field for staff
+*/
+ MSG_BATTLEFIELD_COUNT = 0x63b,
+/*20091103 to latest
+전장 A 대기 인원
+Battlefield staff A is waiting.
+*/
+ MSG_BATTLEFIELD_ATEAM_COUNT = 0x63c,
+/*20091103 to latest
+전장 B 대기 인원
+Battlefield staff B is waiting.
+*/
+ MSG_BATTLEFIELD_BTEAM_COUNT = 0x63d,
+/*20091103 to latest
+내 대기 상황 : %d(진영 A)
+Waiting for my situation: %d (Camp A)
+*/
+ MSG_BATTLEFIELD_ATEAM_WAIT = 0x63e,
+/*20091103 to latest
+내 대기 상황 : %d(진영 B)
+Waiting for my situation: %d (Camp B)
+*/
+ MSG_BATTLEFIELD_BTEAM_WAIT = 0x63f,
+/*20091103 to latest
+전장 아이콘을 보여줍니다.
+Battlefield display icon.
+*/
+ MSG_SHOW_BATTLEFIELD_ICON = 0x640,
+/*20091103 to latest
+전장 아이콘을 보여주지 않습니다.
+Does not display the icon field.
+*/
+ MSG_DONT_SHOW_BATTLEFIELD_ICON = 0x641,
+/*20091103 to latest
+전장 이동 알림
+Field notification was moved.
+*/
+ MSG_NOTIFY_BATTLEFIELD_MOVE = 0x642,
+/*20091103 to latest
+전장 입장 보류 알림
+Admission pending notification of the battlefield
+*/
+ MSG_NOTIFY_BATTLEFIELD_DEFER = 0x643,
+/*20091103 to latest
+누군가
+Anyone
+*/
+ MSG_WHO_IS = 0x644,
+/*20091103 to latest
+ [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] deal '%d' damage on you.
+*/
+ MSG_I_RECEIVED_DAMAGE = 0x645,
+/*20091103 to 20091104
+ [%s]가 [%s](으)로부터 '%d'의 데미지를 받았습니다.
+20091110 to latest
+ [%s]님이 [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] received damage from [%s] with '%d' damage.
+*/
+ MSG_PARTY_RECEIVED_DAMAGE = 0x646,
+/*20091103 to latest
+ [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] received '%d' damage.
+*/
+ MSG_I_GAVE_DAMAGE = 0x647,
+/*20091103 to 20091104
+ [%s님]가 [%s]에게 '%d'의 데미지를 주었습니다.
+20091110 to latest
+ [%s]님이 [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] deal damage to [%s] with '%d' damage.
+*/
+ MSG_PARTY_GAVE_DAMAGE = 0x648,
+/*20091103 to latest
+%s %d 개 드롭
+You dropped '%s' (%d).
+*/
+ MSG_DROP_ITEM = 0x649,
+/*20091103 to latest
+ [%s]퀘스트의 [%s]몬스터를 처치하였습니다. (%d/%d)
+[%s] Quest - defeated [%s] progress (%d/%d)
+*/
+ MSG_CLEAR_QUEST_MONSTER = 0x64a,
+/*20091103 to latest
+%s 퀘스트가 삭제 되었습니다.
+The Quest '%s' has been removed.
+*/
+ MSG_DELETE_QUEST = 0x64b,
+/*20091103 to latest
+[%s]님이
+[%s] has
+*/
+ MSG_NOTIFY_WHO = 0x64c,
+/*20091103 to latest
+'%d'의 경험치를
+You acquired '%d' Experience Points
+*/
+ MSG_NOTIFY_EXP = 0x64d,
+/*20091103 to latest
+'%d'의 잡경험치를
+You acquired '%d' Job Experience Points
+*/
+ MSG_NOTIFY_JOBEXP = 0x64e,
+/*20091103 to latest
+획득했습니다.
+ gained.
+*/
+ MSG_GET = 0x64f,
+/*20091103 to latest
+상실했습니다.
+ has lost.
+*/
+ MSG_LOSS = 0x650,
+/*20091103 to latest
+ [%s](으)로부터 '%d'의 코인을 스틸했습니다.
+From [%s], '%d' coins were stolen.
+*/
+ MSG_NOTIFY_STEAL_COIN = 0x651,
+/*20091103 to latest
+전투 메시지
+Battle Message
+*/
+ MSG_VIEW_COMBAT_MSG = 0x652,
+/*20091103 to latest
+파티원 전투 메시지
+Display Party Battle Message
+*/
+ MSG_VIEW_PARTY_COMBAT_MSG = 0x653,
+/*20091103 to latest
+획득 경험치
+Display Experience Message
+*/
+ MSG_VIEW_GETTING_EXP_MSG = 0x654,
+/*20091103 to latest
+파티원의 획득 경험치
+Display Party Experience Message
+*/
+ MSG_VIEW_PARTY_GETTING_EXP_MSG = 0x655,
+/*20091103 to latest
+퀘스트 정보 표시
+Display Quest Info Message
+*/
+ MSG_VIEW_QUEST_INFO_MSG = 0x656,
+/*20091103 to latest
+전장 정보 표시
+Display Battlefield Message
+*/
+ MSG_VIEW_BATTLEFIELD_INFO_MSG = 0x657,
+#endif
+#if PACKETVER >= 20091104
+/*20091104 to latest
+[%s]에게
+[%s]
+*/
+ MSG_NOTIFY_TARGET_WHO = 0x658,
+/*20091104 to 20091104
+[%s] 스킬을 캐스팅합니다.
+20091110 to latest
+[%s] 스킬을 사용합니다.
+Casts [%s] skill.
+*/
+ MSG_NOTIFY_SKILL_TO_TARGET = 0x659,
+#endif
+#if PACKETVER >= 20091110
+/*20091110 to latest
+기능제한상태
+Activate lock function
+*/
+ MSG_LOCK_MOUSE = 0x65a,
+/*20091110 to latest
+기능제한해제상태
+Deactivate lock function
+*/
+ MSG_UNLOCK_MOUSE = 0x65b,
+#endif
+#if PACKETVER >= 20091201
+/*20091201 to latest
+[%s]님이 [%s](으)로부터 '%s' 를 획득 했습니다.
+Citizens of Midgard, Lady Luck shines upon [%s] !! [%s] has awarded the player with '%s' !!
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN = 0x65c,
+#endif
+#if PACKETVER >= 20091208
+/*20091208 to latest
+소드맨
+Swordman
+*/
+ MSG_JOB_SWORDMAN = 0x65d,
+/*20091208 to latest
+매지션
+Magician
+*/
+ MSG_JOB_MAGICIAN = 0x65e,
+/*20091208 to latest
+아처
+Archer
+*/
+ MSG_JOB_ARCHER = 0x65f,
+/*20091208 to latest
+어콜라이트
+Acolyte
+*/
+ MSG_JOB_ACOLYTE = 0x660,
+/*20091208 to latest
+머첸트
+Merchant
+*/
+ MSG_JOB_MERCHANT = 0x661,
+/*20091208 to latest
+씨프
+Thief
+*/
+ MSG_JOB_THIEF = 0x662,
+/*20091208 to latest
+나이트
+Knight
+*/
+ MSG_JOB_KNIGHT = 0x663,
+/*20091208 to latest
+프리스트
+Priest
+*/
+ MSG_JOB_PRIEST = 0x664,
+/*20091208 to latest
+위저드
+Wizard
+*/
+ MSG_JOB_WIZARD = 0x665,
+/*20091208 to latest
+블랙스미스
+Black Smith
+*/
+ MSG_JOB_BLACKSMITH = 0x666,
+/*20091208 to latest
+헌터
+Hunter
+*/
+ MSG_JOB_HUNTER = 0x667,
+/*20091208 to latest
+어새신
+Assasin
+*/
+ MSG_JOB_ASSASSIN = 0x668,
+/*20091208 to latest
+크루세이더
+Crusader
+*/
+ MSG_JOB_CRUSADER = 0x669,
+/*20091208 to latest
+몽크
+Monk
+*/
+ MSG_JOB_MONK = 0x66a,
+/*20091208 to latest
+세이지
+Sage
+*/
+ MSG_JOB_SAGE = 0x66b,
+/*20091208 to latest
+로그
+Rogue
+*/
+ MSG_JOB_ROGUE = 0x66c,
+/*20091208 to latest
+알케미스트
+Alchemist
+*/
+ MSG_JOB_ALCHEMIST = 0x66d,
+/*20091208 to latest
+바드
+Bard
+*/
+ MSG_JOB_BARD = 0x66e,
+/*20091208 to latest
+댄서
+Dancer
+*/
+ MSG_JOB_DANCER = 0x66f,
+/*20091208 to 20100310
+룬나이트
+20100316 to latest
+룬 나이트
+Rune Knight
+*/
+ MSG_JOB_RUNE_KNIGHT = 0x670,
+/*20091208 to latest
+워록
+Warlock
+*/
+ MSG_JOB_WARLOCK = 0x671,
+/*20091208 to latest
+레인져
+Ranger
+*/
+ MSG_JOB_RANGER = 0x672,
+/*20091208 to 20100310
+아크비숍
+20100316 to latest
+아크 비숍
+Arc Bishop
+*/
+ MSG_JOB_ARCHBISHOP = 0x673,
+/*20091208 to latest
+미케닉
+Mechanic
+*/
+ MSG_JOB_MECHANIC = 0x674,
+/*20091208 to 20100310
+길로틴크로스
+20100316 to latest
+길로틴 크로스
+Guillotine Cross
+*/
+ MSG_JOB_GUILLOTINE_CROSS = 0x675,
+/*20091208 to latest
+로얄가드
+Royal Guard
+*/
+ MSG_JOB_ROYAL_GUARD = 0x676,
+/*20091208 to latest
+소서러
+Sorcerer
+*/
+ MSG_JOB_SORCERER = 0x677,
+/*20091208 to latest
+민스트럴
+Minstrel
+*/
+ MSG_JOB_MINSTREL = 0x678,
+/*20091208 to latest
+원더러
+Wanderer
+*/
+ MSG_JOB_WANDERER = 0x679,
+/*20091208 to latest
+수라
+Sura
+*/
+ MSG_JOB_SURA = 0x67a,
+/*20091208 to latest
+제네릭
+Genetic
+*/
+ MSG_JOB_GENETIC = 0x67b,
+/*20091208 to 20100310
+쉐도우체이서
+20100316 to latest
+쉐도우 체이서
+Shadow Chaser
+*/
+ MSG_JOB_SHADOW_CHASER = 0x67c,
+/*20091208 to 20100113
+소드맨_하이
+20100119 to latest
+소드맨 하이
+High Swordman
+*/
+ MSG_JOB_SWORDMAN_H = 0x67d,
+/*20091208 to 20100113
+매지션_하이
+20100119 to latest
+매지션 하이
+High Magician
+*/
+ MSG_JOB_MAGICIAN_H = 0x67e,
+/*20091208 to 20100113
+아처_하이
+20100119 to latest
+아처 하이
+High Archer
+*/
+ MSG_JOB_ARCHER_H = 0x67f,
+/*20091208 to 20100113
+어콜라이트_하이
+20100119 to latest
+어콜라이트 하이
+High Acolyte
+*/
+ MSG_JOB_ACOLYTE_H = 0x680,
+/*20091208 to 20100113
+머첸트_하이
+20100119 to latest
+머첸트 하이
+High Merchant
+*/
+ MSG_JOB_MERCHANT_H = 0x681,
+/*20091208 to 20100113
+시프_하이
+20100119 to 20100223
+시프 하이
+20100302 to latest
+씨프 하이
+High Thief
+*/
+ MSG_JOB_THIEF_H = 0x682,
+/*20091208 to latest
+로드나이트
+Lord Knight
+*/
+ MSG_JOB_KNIGHT_H = 0x683,
+/*20091208 to latest
+하이프리스트
+High Priest
+*/
+ MSG_JOB_PRIEST_H = 0x684,
+/*20091208 to latest
+하이위저드
+High Wizard
+*/
+ MSG_JOB_WIZARD_H = 0x685,
+/*20091208 to latest
+화이트스미스
+White Smith
+*/
+ MSG_JOB_BLACKSMITH_H = 0x686,
+/*20091208 to latest
+스나이퍼
+Sniper
+*/
+ MSG_JOB_HUNTER_H = 0x687,
+/*20091208 to latest
+어새신크로스
+Assasin Cross
+*/
+ MSG_JOB_ASSASSIN_H = 0x688,
+/*20091208 to latest
+팔라딘
+Paladin
+*/
+ MSG_JOB_CRUSADER_H = 0x689,
+/*20091208 to latest
+챔피온
+Champion
+*/
+ MSG_JOB_MONK_H = 0x68a,
+/*20091208 to latest
+프로페서
+Professor
+*/
+ MSG_JOB_SAGE_H = 0x68b,
+/*20091208 to latest
+스토커
+Stalker
+*/
+ MSG_JOB_ROGUE_H = 0x68c,
+/*20091208 to latest
+크리에이터
+Creator
+*/
+ MSG_JOB_ALCHEMIST_H = 0x68d,
+/*20091208 to latest
+클로운
+Clown
+*/
+ MSG_JOB_BARD_H = 0x68e,
+/*20091208 to latest
+집시
+Gypsy
+*/
+ MSG_JOB_DANCER_H = 0x68f,
+/*20091208 to latest
+노비스
+Wedding
+*/
+ MSG_JOB_NOVICE = 0x690,
+/*20091208 to latest
+하이노비스
+High Novice
+*/
+ MSG_JOB_NOVICE_H = 0x691,
+/*20091208 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_JOB_SUPERNOVICE = 0x692,
+/*20091208 to latest
+건슬링거
+Gunslinger
+*/
+ MSG_JOB_GUNSLINGER = 0x693,
+/*20091208 to latest
+닌자
+Ninja
+*/
+ MSG_JOB_NINJA = 0x694,
+/*20091208 to 20100105
+태권소녀,태권소년
+20100112 to 20100310
+태권소년소녀
+20100316 to latest
+태권소년/소녀
+Taekwon F/M
+*/
+ MSG_JOB_TAEKWON = 0x695,
+/*20091208 to latest
+권성
+Star Gladiator
+*/
+ MSG_JOB_STAR = 0x696,
+/*20091208 to latest
+소울링커
+Soul Linker
+*/
+ MSG_JOB_LINKER = 0x697,
+/*20091208 to latest
+파티모집
+Party Recruitment
+*/
+ MSG_SEEK_PARTY_MEMBER = 0x698,
+/*20091208 to 20100310
+파티 부킹 리스트
+20100316 to latest
+파티 모집 리스트
+Party Booking List
+*/
+ MSG_SEEK_PARTY_LIST = 0x699,
+/*20091208 to latest
+파티 모집 중
+Recruiting Party
+*/
+ MSG_SEEK_PARTY_CHECK = 0x69a,
+#endif
+#if PACKETVER >= 20091215
+/*20091215 to latest
+[활]을 장착한 상태여야 합니다.
+[Bow] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_BOW = 0x69b,
+/*20091215 to latest
+[악기/채찍]을 장착한 상태여야 합니다.
+[Musical Instrument/Whip] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_INSTRUMENT_WHIP = 0x69c,
+/*20091215 to latest
+영문과 숫자만 사용가능합니다.
+Only alphanumeric characters are allowed.
+*/
+ MSG_BAD_CHAR = 0x69d,
+/*20091215 to latest
+알림
+Notice
+*/
+ MSG_ALRAM = 0x69e,
+/*20091215 to latest
+상점 정보가 정확하지 않아 아이템 구매가 실패하였습니다.
+Item purchase failed due to incorrect shop information.
+*/
+ MSG_FAIL_BUY_ITEM_INVALID_MCSTORE = 0x69f,
+#endif
+#if PACKETVER >= 20100105
+/*20100105 to latest
+소지 아이템 창에서 버릴 수 있습니다.
+Item cannot be discarded from the window.
+*/
+ MSG_CAN_DROP_ITEM_TO_ITEMWND = 0x6a0,
+#endif
+#if PACKETVER >= 20100112
+/*20100112 to latest
+시간
+Time
+*/
+ MSG_TIME = 0x6a1,
+/*20100112 to latest
+맵
+Map
+*/
+ MSG_MAP = 0x6a2,
+/*20100112 to latest
+거래 상태에서는 아이템 사용 및 장비 착용/해제를 할 수 없습니다.
+You can't use, equip or disarm items when you're trading.
+*/
+ MSG_CANT_USE_WHEN_OPENED_EXCHANGEWND = 0x6a3,
+/*20100112 to latest
+미지정값
+Unspecified value
+*/
+ MSG_HOTKEY_UNKOWN = 0x6a4,
+#endif
+#if PACKETVER >= 20100126
+/*20100126 to latest
+/stateinfo : 상태 아이콘에 대한 설명을 보여줍니다. On Off
+/stateinfo: Shows the description of status icons. On Off
+*/
+ MSG_EXPLAIN_STATEINFO = 0x6a5,
+/*20100126 to latest
+상태 정보 On : 상태 아이콘에 대한 설명이 표시됩니다.
+Status Information On: Status icon description is enabled.
+*/
+ MSG_SHOW_STATEINFO_ON = 0x6a6,
+/*20100126 to latest
+상태 정보 Off: 상태 아이콘에 대한 설명이 표시되지 않습니다.
+Status Information Off: Status icon description is disabled.
+*/
+ MSG_SHOW_STATEINFO_OFF = 0x6a7,
+/*20100126 to 20100126
+같은 아이템은 한번에 %d개 이상은 살수 없습니다.
+20100202 to latest
+같은 아이템은 한번에 %d개 이상은 살 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_BUY_ITEM2 = 0x6a8,
+#endif
+#if PACKETVER >= 20100202
+/*20100202 to latest
+같은 아이템은 한번에 %d개 이상은 팔 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_SELL_ITEM = 0x6a9,
+/*20100202 to 20100203
+총 구매 가능 개수는 %d개 입니다.
+20100209 to latest
+해당 아이템의 총 구매 가능 개수는 %d개 입니다.
+Can purchase upto %d pieces of the same item at a time.
+*/
+ MSG_CAN_BUY_ITEM_NUM = 0x6aa,
+#endif
+#if PACKETVER >= 20100209
+/*20100209 to latest
+설정한 내용은 정상 종료 시 [%s\%s]에 저장됩니다.
+User customized key is saved to [%s\%s]
+*/
+ MSG_SAVE_HOTKEY_TO_FILE = 0x6ab,
+#endif
+#if PACKETVER >= 20100216
+/*20100216 to latest
+[%s] 님은 현재 교환 신청을 받을 수 없는 상태입니다.
+[%s] is currently on trade and cannot accept the request.
+*/
+ MSG_CHARACTER_IS_BUSY = 0x6ac,
+#endif
+#if PACKETVER >= 20100309
+/*20100309 to latest
+RO_HELP
+RO_HELP.
+*/
+ MSG_RO_HELP = 0x6ad,
+#endif
+#if PACKETVER >= 20100316
+/*20100316 to latest
+모루가 존재 하지 않습니다.
+Anvil does not exist.
+*/
+ MSG_HAVENOT_ANVIL = 0x6ae,
+/*20100316 to latest
+노비스 레벨 10 이하는 귓속말이 금지됩니다
+Novice below level 10 is not allowed to whisper.
+*/
+ MSG_WHISPER_BLOCK_NOVICE_LEVEL10 = 0x6af,
+#endif
+#if PACKETVER >= 20100323
+/*20100323 to latest
+공격
+Attack
+*/
+ MSG_JOB_ATTACKER = 0x6b0,
+/*20100323 to latest
+방어
+Defense
+*/
+ MSG_JOB_TANKER = 0x6b1,
+/*20100323 to latest
+회복
+Consumables
+*/
+ MSG_JOB_HEALER = 0x6b2,
+/*20100323 to latest
+보조
+Support
+*/
+ MSG_JOB_ASSISTANCE = 0x6b3,
+/*20100323 to latest
+파티 모집 관련 명령어
+Party recruitment related command
+*/
+ MSG_DESCRIBE_PARTY_BOOKING = 0x6b4,
+#endif
+#if PACKETVER >= 20100330
+/*20100330 to latest
+길드 동맹신청이 불가능합니다
+Guild alliance application is not possible.
+*/
+ MSG_GUILD_ALLY_REQUEST_DISABLE = 0x6b5,
+/*20100330 to latest
+길드 적대신청이 불가능합니다
+Guild hostility application is not possible.
+*/
+ MSG_GUILD_HOSTILE_REQUEST_DISABLE = 0x6b6,
+/*20100330 to latest
+아지트맵에서는 친구추가가 불가능합니다
+Adding friends is not possible in this map.
+*/
+ MSG_FRIEND_ADD_FALSE_AGIT = 0x6b7,
+#endif
+#if PACKETVER >= 20100406
+/*20100406 to latest
+구매노점 개설
+Buying Store Window
+*/
+ MSG_BUYINGSTORE_MAKEWND_TITLE = 0x6b8,
+/*20100406 to latest
+구매가 :
+Price:
+*/
+ MSG_BUYINGSTORE_MAKEWND_PRICE = 0x6b9,
+/*20100406 to latest
+소지액 :
+Money:
+*/
+ MSG_BUYINGSTORE_MAKEWND_MYZENY = 0x6ba,
+/*20100406 to latest
+구매 한도액
+Purchase Zeny Limit
+*/
+ MSG_BUYINGSTORE_MAKEWND_LIMITZENY = 0x6bb,
+/*20100406 to 20100414
+판매 가능한 아이템 목록
+Available items:
+20100420 to latest
+구매할 아이템을 등록하지 않았습니다. 구매하실 아이템을 등록해 주세요
+Please register the item first that has to be purchased.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADDITEM = 0x6bc,
+/*20100406 to 20100414
+나의 구매노점
+Purchase list:
+20100420 to latest
+%s 아이템의 가격을 입력해 주세요.
+Enter the price for item %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTPRICE = 0x6bd,
+/*20100406 to 20100414
+구매 노점
+Wanted items
+20100420 to latest
+%s 아이템의 가격을 9999만 Zeny이하로 입력해 주세요.
+Enter the price for item %s. It has to be below 99990000 Zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTPRICE = 0x6be,
+/*20100406 to 20100414
+제한금액 : %d Zeny
+20100420 to latest
+%s 아이템의 구매수량을 입력해 주세요.
+Enter the item number for %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTNUM = 0x6bf,
+/*20100406 to 20100414
+%s %s Zeny %d 개
+Buying %s for %s Zeny. Amount: %d.
+20100420 to latest
+%s 아이템의 소지수량과 구매수량의 합이 9999개 이상입니다. 9999개 이하의 수량을 입력해 주세요.
+The sum of purchasing and belonging items is over 9999. The sum has to be bellow 9999.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTNUM = 0x6c0,
+/*20100406 to 20100414
+%s : %s Zeny => %s EA
+%s: %s Zeny => %s ea.
+20100420 to latest
+중복된 아이템이 존재합니다.
+You have duplicate items in your purchase list.
+*/
+ MSG_BUYINGSTORE_MAKEWND_DUPLICATEITEM = 0x6c1,
+/*20100406 to 20100414
+%s %d 개 구매.
+20100420 to latest
+제한 금액을 입력해 주세요
+Enter the limited price.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTLIMITZENY = 0x6c2,
+/*20100406 to 20100414
+아이템을 모두 구매했습니다.
+You purchased all items.
+20100420 to latest
+입력한 제한금액이 소지금액을 초과합니다. 다시 설정해 주세요
+You have entered a greater amount of zeny than you have. Please check your zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTLIMITZENY = 0x6c3,
+/*20100406 to 20100414
+해당 아이템의 총 판매 가능 개수는 %d개 입니다.
+The max. number of items you can sell is %d.
+20100420 to latest
+%s : %s Zeny => %s EA
+%s: %s Zeny => %s ea.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ITEMLIST = 0x6c4,
+/*20100406 to 20100414
+가격이 0 Zeny인 아이템이 존재합니다. 가격을 입력해 주세요.
+20100420 to latest
+구매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORBUYITEMLIST = 0x6c5,
+/*20100406 to 20100414
+가격이 9999만 Zeny이상인 아이템이 존재합니다. 9999만 Zeny 이하의 가격을 입력해 주세요.
+20100420 to latest
+나의 구매노점
+Purchase list:
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_TITLE = 0x6c6,
+/*20100406 to 20100414
+구매수량이 0 개인 아이템이 존재합니다. 수량을 입력해 주세요.
+20100420 to 20110208
+제한금액 : %d Zeny
+20110210 to latest
+제한금액 : %s Zeny
+Price limit: %s Zeny
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_LIMITZENY = 0x6c7,
+/*20100406 to 20100414
+구매수량이 9999개 이상인 아이템이 존재합니다. 9999개 이하의 수량을 입력해 주세요.
+20100420 to latest
+%s %s Zeny %d 개
+Buying %s for %s Zeny. Amount: %d.
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_ITEMINFO = 0x6c8,
+/*20100406 to 20100414
+중복된 아이템이 존재합니다.
+You have duplicate items in your purchase list.
+20100420 to latest
+구매 노점
+Wanted items
+*/
+ MSG_BUYINGSTORE_SHOPWND_TITLE = 0x6c9,
+/*20100406 to 20100414
+구매상점 열기에 실패했습니다.
+20100420 to latest
+판매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORSELLWND_TITLE = 0x6ca,
+/*20100406 to 20100414
+구매상점 열기에 실패했습니다.
+20100420 to latest
+해당 아이템의 총 판매 가능 개수는 %d개 입니다.
+The max. number of items you can sell is %d.
+*/
+ MSG_BUYINGSTORE_SELLWND_LIMITNUM = 0x6cb,
+/*20100406 to 20100414
+구매가능한 최대 갯수를 초과하였습니다.
+20100420 to 20110208
+구매자의 잔액이 부족하니 다시 설정해 주세요
+20110210 to latest
+구매노점의 제한금액을 초과하여 판매할 수 없습니다.
+Buyer has insufficient money, lower the amount of items you're selling.
+*/
+ MSG_BUYINGSTORE_SELLWND_LACKBUYERZENY = 0x6cc,
+/*20100406 to 20100414
+남은 잔액으로 아이템 구매가 불가능 합니다.
+20100420 to latest
+구매상점 개설에 실패했습니다.
+Failed to open purchase shop.
+*/
+ MSG_BUYINGSTORE_OPEN_FAILED = 0x6cd,
+#endif
+#if PACKETVER >= 20100413
+/*20100413 to 20100414
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+20100420 to latest
+아이템의 총 무게가 %d 만큼 소지 한계량을 초과합니다. 다시 설정해 주세요.
+You exceed the total amount of items.
+*/
+ MSG_BUYINGSTORE_OVERWEIGHT = 0x6ce,
+/*20100413 to 20100414
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+20100420 to latest
+제한금액만큼의 아이템을 모두 구매하였습니다.
+You have purchased all items within the limited price.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERLIMITZENY = 0x6cf,
+#endif
+#if PACKETVER >= 20100420
+/*20100420 to latest
+아이템을 모두 구매했습니다.
+You purchased all items.
+*/
+ MSG_BUYINGSTORE_TRADE_BUYCOMPLETE = 0x6d0,
+/*20100420 to latest
+구매자의 잔액이 부족하여 거래가 실패하였습니다.
+Failed to deal because you have not enough Zeny.
+*/
+ MSG_BUYINGSTORE_TRADE_LACKBUYERZENY = 0x6d1,
+/*20100420 to latest
+%s %d개를 %dz에 판매하였습니다.
+You have sold %s. Amount: %d. Total Zeny: %dz
+*/
+ MSG_BUYINGSTORE_TRADE_SELLCOMPLETE = 0x6d2,
+/*20100420 to latest
+%s 아이템은 희망 구매갯수보다 수량이 많아 판매하지 못하였습니다
+%s item could not be sold because you do not have the wanted amount of items.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERCOUNT = 0x6d3,
+/*20100420 to latest
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+20130807 to 20130814
+판매할 아이템을 등록하지 않았습니다. 판매하실 아이템을 등록해 주세요
+Has not registered to sell the item. Please register to sell the item
+*/
+ MSG_USESKILL_FAIL_EL_SUMMON = 0x6d4,
+/*20100420 to latest
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+20130807 to 20130814
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+*/
+ MSG_AGAINSTSERVERSIEGEWARFARE_RESTRICTION = 0x6d5,
+/*20100420 to latest
+OTP 비밀번호는 6자리 입니다.
+OTP password is 6 digits long.
+20130807 to 20130814
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+*/
+ MSG_OTP_MUST_6_CHAR = 0x6d6,
+/*20100420 to latest
+OTP 정보가 없습니다. 관리자에게 문의하시기 바랍니다.
+OTP information is unavailable. Please contact your administrator.
+20130807 to 20130814
+OTP 비밀번호는 6자리 입니다.
+OTP password is 6 digits long.
+*/
+ MSG_DB_ERROR = 0x6d7,
+/*20100420 to latest
+OTP 인증에 실패 했습니다.
+OTP authentication failed.
+20130807 to 20130814
+OTP 정보가 없습니다. 관리자에게 문의하시기 바랍니다.
+OTP information is unavailable. Please contact your administrator.
+*/
+ MSG_OTP_FAILED = 0x6d8,
+/*20100420 to latest
+파티광고가 추가되었습니다
+Party ad has been added.
+20130807 to 20130814
+OTP 인증에 실패 했습니다.
+OTP authentication failed.
+*/
+ MSG_PARTY_BOOKING_NOTIFY = 0x6d9,
+/*20100420 to 20110718
+파티원 모집 중
+20110726 to latest
+모집 중
+Recruit party members
+20130807 to 20130814
+파티광고가 추가되었습니다
+Party ad has been added.
+*/
+ MSG_PARTY_BOOKING_REQURT = 0x6da,
+/*20100420 to latest
+역할
+Roles
+20130807 to 20130814
+모집 중
+Recruit party members
+*/
+ MSG_PARTY_BOOKING_TYPE = 0x6db,
+/*20100420 to latest
+1차 직업
+1st Jobs
+20130807 to 20130814
+역할
+Roles
+*/
+ MSG_PARTY_BOOKING_TYPE_1 = 0x6dc,
+/*20100420 to latest
+2차 직업
+2nd Jobs
+20130807 to 20130814
+1차 직업
+1st Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_2 = 0x6dd,
+/*20100420 to latest
+3-1차 직업
+3-1 Classes
+20130807 to 20130814
+2차 직업
+2nd Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_3_1 = 0x6de,
+/*20100420 to latest
+3-2차 직업
+3-2 Classes
+20130807 to 20130814
+3-1차 직업
+3-1 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_3_2 = 0x6df,
+/*20100420 to latest
+전승 1차 직업
+1st Job High
+20130807 to 20130814
+3-2차 직업
+3-2 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_1PLUS = 0x6e0,
+/*20100420 to latest
+전승 2차 직업
+2nd Jobs High
+20130807 to 20130814
+전승 1차 직업
+1st Job High
+*/
+ MSG_PARTY_BOOKING_TYPE_2PLUS = 0x6e1,
+/*20100420 to latest
+기타 직업군
+Other Jobs
+20130807 to 20130814
+전승 2차 직업
+2nd Jobs High
+*/
+ MSG_PARTY_BOOKING_TYPE_ETC = 0x6e2,
+/*20100420 to latest
+모집 하기
+Recruit
+20130807 to 20130814
+기타 직업군
+Other Jobs
+*/
+ MSG_PARTY_BOOKING_REQURTING = 0x6e3,
+/*20100420 to latest
+파티원을 모집합니다.
+Open party recruitment window.
+20130807 to 20130814
+모집 하기
+Recruit
+*/
+ MSG_PARTY_BOOKING_REQURT_TIP = 0x6e4,
+/*20100420 to 20110718
+검색중 -
+20110726 to latest
+검색 중 -
+Searching -
+20130807 to 20130814
+파티원을 모집합니다.
+Open party recruitment window.
+*/
+ MSG_PARTY_BOOKING_SEARCH = 0x6e5,
+/*20100420 to latest
+모두 선택
+Select All
+20130807 to 20130814
+검색 중 -
+Searching -
+*/
+ MSG_PARTY_BOOKING_ALL_SELECT = 0x6e6,
+/*20100420 to latest
+최소한 하나의 직업이 모집 중이어야 합니다.
+Recruitment of at least one job must be running.
+20130807 to 20130814
+모두 선택
+Select All
+*/
+ MSG_PARTY_BOOKING_ERR1 = 0x6e7,
+/*20100420 to latest
+최소 1개이상의 직업을 선택해 주셔야 합니다.
+You have to select atleast 1 or more jobs.
+20130807 to 20130814
+최소한 하나의 직업이 모집 중이어야 합니다.
+Recruitment of at least one job must be running.
+*/
+ MSG_PARTY_BOOKING_ERR2 = 0x6e8,
+/*20100420 to latest
+선택된 직업은 %d개입니다. 최대 6개까지만 직업을 선택할 수 있습니다.
+You have selected %d Jobs. You can only select up to 6 different jobs.
+20130807 to 20130814
+최소 1개이상의 직업을 선택해 주셔야 합니다.
+You have to select atleast 1 or more jobs.
+*/
+ MSG_PARTY_BOOKING_ERR3 = 0x6e9,
+/*20100420 to latest
+레벨에 숫자 이외의 문자는 들어갈 수 없습니다.
+Only numeric characters are allowed.
+20130807 to 20130814
+선택된 직업은 %d개입니다. 최대 6개까지만 직업을 선택할 수 있습니다.
+You have selected %d Jobs. You can only select up to 6 different jobs.
+*/
+ MSG_PARTY_BOOKING_ERR4 = 0x6ea,
+/*20100420 to latest
+레벨은 1~150 사이의 숫자를 입력해 주세요.
+Please enter levels between 1~150.
+20130807 to 20130814
+레벨에 숫자 이외의 문자는 들어갈 수 없습니다.
+Only numeric characters are allowed.
+*/
+ MSG_PARTY_BOOKING_ERR5 = 0x6eb,
+#endif
+#if PACKETVER >= 20100511
+/*20100511 to latest
+ 해당 맵에서는 의상 장비가 보이지 않습니다.
+Nothing found in the selected map.
+20130807 to 20130814
+레벨은 1~150 사이의 숫자를 입력해 주세요.
+Please enter levels between 1~150.
+*/
+ MSG_DISABLE_COSTUMEITEM_MAP = 0x6ec,
+#endif
+#if PACKETVER >= 20100525
+/*20100525 to latest
+아이템을 착용할 수 있는 레벨이 아닙니다.
+You cannot equip this item with your current level.
+20130807 to 20130814
+ 해당 맵에서는 의상 장비가 보이지 않습니다.
+Nothing found in the selected map.
+*/
+ MSG_CANNOT_EQUIP_ITEM_LEVEL = 0x6ed,
+/*20100525 to latest
+아이템을 사용할 수 있는 레벨이 아닙니다.
+You cannot use this item with your current level.
+20130807 to 20130814
+아이템을 착용할 수 있는 레벨이 아닙니다.
+You cannot equip this item with your current level.
+*/
+ MSG_CANNOT_USE_ITEM_LEVEL = 0x6ee,
+#endif
+#if PACKETVER >= 20100601
+/*20100601 to latest
+ 채팅모드 OnOff 활성화
+Enable Battlemode
+20130807 to 20130814
+아이템을 사용할 수 있는 레벨이 아닙니다.
+You cannot use this item with your current level.
+*/
+ MSG_CHATMODE_ONOFF = 0x6ef,
+/*20100601 to latest
+탭사이즈 크기가 초과되어 추가할 수 없습니다.
+Failed to add because you have reached the limit.
+20130807 to 20130814
+ 채팅모드 OnOff 활성화
+Enable Battlemode
+*/
+ MSG_OVER_TABSIZE = 0x6f0,
+/*20100601 to 20100601
+ 창 표시 정보.
+20100608 to latest
+ 창 표시 정보
+Window Sign Information
+20130807 to 20130814
+탭사이즈 크기가 초과되어 추가할 수 없습니다.
+Failed to add because you have reached the limit.
+*/
+ MSG_SET_CHATINFO = 0x6f1,
+#endif
+#if PACKETVER >= 20100608
+/*20100608 to latest
+판매
+Sell
+20130807 to 20130814
+ 창 표시 정보
+Window Sign Information
+*/
+ MSG_SELL = 0x6f2,
+/*20100608 to latest
+구매
+Purchase
+20130807 to 20130814
+판매
+Sell
+*/
+ MSG_BUY = 0x6f3,
+/*20100608 to latest
+노점 검색
+Search for Vends
+20130807 to 20130814
+구매
+Purchase
+*/
+ MSG_SEARCH_STOREINFO = 0x6f4,
+/*20100608 to latest
+노점 이름
+Shop Name
+20130807 to 20130814
+노점 검색
+Search for Vends
+*/
+ MSG_STORE_NAME = 0x6f5,
+/*20100608 to latest
+수량
+Quantity
+20130807 to 20130814
+노점 이름
+Shop Name
+*/
+ MSG_SEARCH_ITEM_COUNT = 0x6f6,
+/*20100608 to latest
+가격
+Cost
+20130807 to 20130814
+수량
+Quantity
+*/
+ MSG_SEARCH_ITEM_PRICE = 0x6f7,
+/*20100608 to latest
+검색 결과가 너무 많습니다. 검색어를 자세히 입력 해 주세요.
+Too much results have been found. Please do a more precisely search.
+20130807 to 20130814
+가격
+Cost
+*/
+ MSG_SSI_FAILED_OVER_MAXCOUNT = 0x6f8,
+/*20100608 to latest
+해당 노점을 여시겠습니까?
+Do you want to open a street stall?
+20130807 to 20130814
+검색 결과가 너무 많습니다. 검색어를 자세히 입력 해 주세요.
+Too much results have been found. Please do a more precisely search.
+*/
+ MSG_OPEN_SEARCH_STORE = 0x6f9,
+/*20100608 to latest
+SSO 인증에 실패하였습니다.
+Failed to recognize SSO.
+20130807 to 20130814
+해당 노점을 여시겠습니까?
+Do you want to open a street stall?
+*/
+ MSG_SSO_FAILED = 0x6fa,
+#endif
+#if PACKETVER >= 20100615
+/*20100615 to latest
+현재 해당지역으로 이동 할 수 없습니다
+Cannot move to the applied area.
+20130807 to 20130814
+SSO 인증에 실패하였습니다.
+Failed to recognize SSO.
+*/
+ MSG_ZONE_MOVE_FAIL = 0x6fb,
+/*20100615 to 20100622
+포함 검색
+20100629 to latest
+단어가 포함된 아이템 검색
+searching item including the word
+20130807 to 20130814
+현재 해당지역으로 이동 할 수 없습니다
+Cannot move to the applied area.
+*/
+ MSG_SEARCH_INCLUDED = 0x6fc,
+/*20100615 to latest
+탈퇴한 유저입니다.
+User has been expelled.
+20130807 to 20130814
+단어가 포함된 아이템 검색
+searching item including the word
+*/
+ MSG_WITHDREW_USERS = 0x6fd,
+/*20100615 to latest
+게임 이용에 동의하지 않았습니다.
+You have not accepted the user agreements yet.
+20130807 to 20130814
+탈퇴한 유저입니다.
+User has been expelled.
+*/
+ MSG_DIDNOT_AGREE = 0x6fe,
+/*20100615 to latest
+존재 하지 않는 계정입니다.
+You will not be disconnect from the game.
+20130807 to 20130814
+게임 이용에 동의하지 않았습니다.
+You have not accepted the user agreements yet.
+*/
+ MSG_ACCOUNT_DOESNOT_EXIST = 0x6ff,
+/*20100615 to latest
+본 게임은 12세 이용가입니다.
+It is available only for 12 hours.
+20130807 to 20130814
+존재 하지 않는 계정입니다.
+You will not be disconnect from the game.
+*/
+ MSG_AGE_RESTRICTIONS = 0x700,
+#endif
+#if PACKETVER >= 20100616
+/*20100616 to latest
+계정도용 조사를 위한 블럭상태입니다.
+Your account is blocked due to illegal use of the game account.
+20130807 to 20130814
+본 게임은 12세 이용가입니다.
+It is available only for 12 hours.
+*/
+ MSG_ACCOUNT_BLOCK = 0x701,
+/*20100616 to latest
+버그조사를 위한 블럭상태입니다.
+Your account is blocked because there may exist a bug with your account.
+20130807 to 20130814
+계정도용 조사를 위한 블럭상태입니다.
+Your account is blocked due to illegal use of the game account.
+*/
+ MSG_BUG_BLOCK = 0x702,
+#endif
+#if PACKETVER >= 20100622
+/*20100622 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 75% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 75% for 30 minutes.
+20130807 to 20130814
+버그조사를 위한 블럭상태입니다.
+Your account is blocked because there may exist a bug with your account.
+*/
+ MSG_PLUSEXP75 = 0x703,
+/*20100622 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 50% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 50% for 30 minutes.
+20130807 to 20130814
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 75% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 75% for 30 minutes.
+*/
+ MSG_PLUSEXP50 = 0x704,
+/*20100622 to 20100622
+상점 정보가 정확하지 않아 상점을 열 수 없습니다.
+20100629 to latest
+판매(구매) 정보가 없습니다.
+No sales information.
+20130807 to 20130814
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 50% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 50% for 30 minutes.
+*/
+ MSG_FAIL_OPEN_STORE = 0x705,
+/*20100622 to latest
+더 이상 검색 할 수 없습니다.
+Failed to search any further.
+20130807 to 20130814
+판매(구매) 정보가 없습니다.
+No sales information.
+*/
+ MSG_SSI_FAILED_SEARCH_CNT = 0x706,
+/*20100622 to 20100622
+검색이 실패하였습니다.
+20100629 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+20130807 to 20130814
+더 이상 검색 할 수 없습니다.
+Failed to search any further.
+*/
+ MSG_SSI_FAILED_ITEM_DOES_NOT_EXIST = 0x707,
+/*20100622 to latest
+아직 검색 할 수 없습니다.
+Cannot search yet.
+20130807 to 20130814
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_SSI_FAILED_LIMIT_SERACH_TIME = 0x708,
+#endif
+#if PACKETVER >= 20100629
+/*20100629 to 20100707
+카드 이름, 접두사, 접미사
+20100713 to latest
+카드 이름 또는 접두사(접미사)를 입력하세요
+Enter the card name or prefix/suffix.
+20130807 to 20130814
+아직 검색 할 수 없습니다.
+Cannot search yet.
+*/
+ MSG_SSI_TOOLTIP_OF_SERACHING_THE_CARD = 0x709,
+/*20100629 to latest
+남은 검색 횟수 : %d
+Searches left: %d
+20130807 to 20130814
+카드 이름 또는 접두사(접미사)를 입력하세요
+Enter the card name or prefix/suffix.
+*/
+ MSG_SSI_REST_OF_NUMBER_OF_SEARCHES = 0x70a,
+/*20100629 to latest
+검색 된 노점이 없습니다.
+No result has been found.
+20130807 to 20130814
+남은 검색 횟수 : %d
+Searches left: %d
+*/
+ MSG_SSI_FAILED_SEARCH_STORE = 0x70b,
+/*20100629 to latest
+아이템 가격 범위가 잘못되었습니다.
+The item price is too high.
+20130807 to 20130814
+검색 된 노점이 없습니다.
+No result has been found.
+*/
+ MSG_SSI_FAILED_PRICE_ISNOT_VALID = 0x70c,
+/*20100629 to latest
+일반 장비
+Normal Gear
+20130807 to 20130814
+아이템 가격 범위가 잘못되었습니다.
+The item price is too high.
+*/
+ MSG_GENERAL_EQUIPMENT = 0x70d,
+/*20100629 to latest
+의상 장비
+Costume
+20130807 to 20130814
+일반 장비
+Normal Gear
+*/
+ MSG_COSTUME_EQUIPMENT = 0x70e,
+#endif
+#if PACKETVER >= 20100713
+/*20100713 to latest
+분
+minute
+20130807 to 20130814
+의상 장비
+Costume
+*/
+ MSG_MINUTE = 0x70f,
+/*20100713 to latest
+초
+second
+20130807 to 20130814
+분
+minute
+*/
+ MSG_SECOND = 0x710,
+/*20100713 to latest
+아이템 명을 입력해 주세요.
+Please enter the name of the item.
+20130807 to 20130814
+초
+second
+*/
+ MSG_SSI_FAILED_ENTER_THE_NAME_OF_ITEM = 0x711,
+/*20100713 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+20130807 to 20130814
+아이템 명을 입력해 주세요.
+Please enter the name of the item.
+*/
+ MSG_SSI_FAILED_NAME_OF_ITEM_DOES_NOT_EXIST = 0x712,
+#endif
+#if PACKETVER >= 20100720
+/*20100720 to latest
+진입가능한 맵이 존재하지 않습니다.
+The map is not available.
+20130807 to 20130814
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_NOT_EXIST_ENTRYMAP = 0x713,
+/*20100720 to latest
+해당 카드 이름이나 접두사(접미사)는 존재하지 않습니다.
+The selected name or prefix/suffix does not exist.
+20130807 to 20130814
+진입가능한 맵이 존재하지 않습니다.
+The map is not available.
+*/
+ MSG_SSI_FAILED_NAME_OF_CARD_DOES_NOT_EXIST = 0x714,
+#endif
+#if PACKETVER >= 20100727
+/*20100727 to latest
+ 한번에 구매 가능 종류는 10개입니다.
+You can purchase up to 10 items.
+20130807 to 20130814
+해당 카드 이름이나 접두사(접미사)는 존재하지 않습니다.
+The selected name or prefix/suffix does not exist.
+*/
+ MSG_CASH_FAILED_TOTAL_CNT = 0x715,
+/*20100727 to latest
+ 일부 아이템의 구매가 실패하였습니다.
+Some items could not be purchased.
+20130807 to 20130814
+ 한번에 구매 가능 종류는 10개입니다.
+You can purchase up to 10 items.
+*/
+ MSG_CASH_FAILED_BUY_SOME = 0x716,
+#endif
+#if PACKETVER >= 20100730
+/*20100730 to latest
+생년월일 6자리를 입력하세요.(예시:801122)
+Enter your 6-digit DOB(YYMMDD) (e.g: 801122)
+20130807 to 20130814
+ 일부 아이템의 구매가 실패하였습니다.
+Some items could not be purchased.
+*/
+ MSG_ENTER_PEOPLE_BIRTH = 0x717,
+/*20100730 to latest
+알 수 없는 오류가 발생하였습니다.
+Now Logging Out.
+20130807 to 20130814
+생년월일 6자리를 입력하세요.(예시:801122)
+Enter your 6-digit DOB(YYMMDD) (e.g: 801122)
+*/
+ MSG_RESULT_FAIL_UNKNOWN = 0x718,
+/*20100730 to latest
+데이타 베이스 오류가 발생하였습니다.
+A database error has occurred.
+20130807 to 20130814
+알 수 없는 오류가 발생하였습니다.
+Now Logging Out.
+*/
+ MSG_RESULT_FAIL_DATABASE = 0x719,
+/*20100730 to latest
+캐릭터를 삭제하기 위해서는 길드에서 탈퇴 해야 합니다.
+Please leave your guild first in order to remove your character.
+20130807 to 20130814
+데이타 베이스 오류가 발생하였습니다.
+A database error has occurred.
+*/
+ MSG_RESULT_FAIL_GUILD = 0x71a,
+/*20100730 to latest
+캐릭터를 삭제하기 위해서는 파티에서 탈퇴 해야 합니다.
+Please leave your party first in order to remove your character.
+20130807 to 20130814
+캐릭터를 삭제하기 위해서는 길드에서 탈퇴 해야 합니다.
+Please leave your guild first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_PARTY = 0x71b,
+/*20100730 to latest
+시스템 설정으로 인해 삭제할 수 없습니다.
+You cannot delete this character because the delete time has not expired yet.
+20130807 to 20130814
+캐릭터를 삭제하기 위해서는 파티에서 탈퇴 해야 합니다.
+Please leave your party first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_CONFIGURATION = 0x71c,
+/*20100730 to latest
+아직 삭제 가능 시간이 아닙니다.
+You cannot delete this character at the moment.
+20130807 to 20130814
+시스템 설정으로 인해 삭제할 수 없습니다.
+You cannot delete this character because the delete time has not expired yet.
+*/
+ MSG_RESULT_FAIL_DATE = 0x71d,
+/*20100730 to latest
+생년월일이 일치하지 않습니다.
+Your entered birthday does not match.
+20130807 to 20130814
+아직 삭제 가능 시간이 아닙니다.
+You cannot delete this character at the moment.
+*/
+ MSG_RESULT_FAIL_BIRTH = 0x71e,
+/*20100730 to latest
+친밀도가 부족합니다.
+You lack of familiarity.
+20130807 to 20130814
+생년월일이 일치하지 않습니다.
+Your entered birthday does not match.
+*/
+ MSG_USESKILL_FAIL_RELATIONGRADE = 0x71f,
+/*20100730 to latest
+스타일체인지 파이터 상태에서만 사용가능합니다.
+This is only available on style change for fighting classes.
+20130807 to 20130814
+친밀도가 부족합니다.
+You lack of familiarity.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 0x720,
+/*20100730 to latest
+스타일체인지 그래플러 상태에서만 사용가능합니다.
+This is only available on style change for novice.
+20130807 to 20130814
+스타일체인지 파이터 상태에서만 사용가능합니다.
+This is only available on style change for fighting classes.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 0x721,
+#endif
+#if PACKETVER >= 20100817
+/*20100817 to latest
+파티등록실패
+Party Registration failed.
+20130807 to 20130814
+스타일체인지 그래플러 상태에서만 사용가능합니다.
+This is only available on style change for novice.
+*/
+ MSG_PARTY_REGISTRATION_FAILED = 0x722,
+/*20100817 to latest
+검색된 조건의 리스트가 없습니다.
+results have been found.
+20130807 to 20130814
+파티등록실패
+Party Registration failed.
+*/
+ MSG_PARTY_SEARCH_FAILED = 0x723,
+/*20100817 to latest
+광고삭제에 실패했습니다.
+Failed to remove result.
+20130807 to 20130814
+검색된 조건의 리스트가 없습니다.
+results have been found.
+*/
+ MSG_PARTY_AD_DELETE_FAILED = 0x724,
+/*20100817 to latest
+조건에 맞는 광고가 없어 실패했습니다.
+No results have been found.
+20130807 to 20130814
+광고삭제에 실패했습니다.
+Failed to remove result.
+*/
+ MSG_PARTY_NOT_EXIST_AD = 0x725,
+#endif
+#if PACKETVER >= 20100824
+/*20100824 to latest
+결제 정보가 없습니다.
+No payment information has been found.
+20130807 to 20130814
+조건에 맞는 광고가 없어 실패했습니다.
+No results have been found.
+*/
+ MSG_REFUSE_SSO_NOT_PAY_USER = 0x726,
+/*20100824 to latest
+교환 시 스크린샷 찍기
+Screenshot Trade
+20130807 to 20130814
+결제 정보가 없습니다.
+No payment information has been found.
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE = 0x727,
+/*20100824 to latest
+[거래_%s]
+[Trade_%s]
+20130807 to 20130814
+교환 시 스크린샷 찍기
+Screenshot Trade
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE_CHARNAME = 0x728,
+#endif
+#if PACKETVER >= 20100914
+/*20100914 to 20180131
+사망으로 인해 신생명보험서가 자동 소비되었습니다
+20130807 to 20130814
+[거래_%s]
+[Trade_%s]
+20180207 to latest
+사망 시 소지한 아이템으로 경험치 손실을 막았습니다.
+Death due to the auto insurance young people are spending.
+*/
+ MSG_NOTIFY_NEO_INSURANCE_ITEM_USE = 0x729,
+/*20100914 to latest
+대화
+Chat Dialog
+20130807 to 20130814
+사망으로 인해 신생명보험서가 자동 소비되었습니다
+*/
+ MSG_TALK = 0x72a,
+#endif
+#if PACKETVER >= 20101019
+/*20101019 to latest
+중복사용이 불가능합니다.
+Redundant is not available.
+20130807 to 20130814
+대화
+Chat Dialog
+*/
+ MSG_MACRO_DUPLICATE = 0x72b,
+/*20101019 to latest
+사용제한이 걸려있습니다.
+Use the limit that has been set.
+20130807 to 20130814
+중복사용이 불가능합니다.
+Redundant is not available.
+*/
+ MSG_MACRO_POSTDELAY = 0x72c,
+/*20101019 to latest
+현재 사용제한이 걸려 있지 않습니다.
+No user restrictions are set.
+20130807 to 20130814
+사용제한이 걸려있습니다.
+Use the limit that has been set.
+*/
+ MSG_MACRO_NOT_POSTDELAY = 0x72d,
+/*20101019 to latest
+예기치 못한 사유로 인해 접속이 실패하였습니다. 관리자에게 문의해 주시기 바랍니다.
+Connection has failed. Please contact your administrator.
+20130807 to 20130814
+현재 사용제한이 걸려 있지 않습니다.
+No user restrictions are set.
+*/
+ MSG_SSO_ERROR_MSG = 0x72e,
+/*20101019 to latest
+접속 정보 인증 실패하였습니다.
+Failed to authenticate.
+20130807 to 20130814
+예기치 못한 사유로 인해 접속이 실패하였습니다. 관리자에게 문의해 주시기 바랍니다.
+Connection has failed. Please contact your administrator.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_TOKEN = 0x72f,
+/*20101019 to latest
+가입하지 않은 사용자입니다.
+User is offline.
+20130807 to 20130814
+접속 정보 인증 실패하였습니다.
+Failed to authenticate.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_USER = 0x730,
+/*20101019 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+20130807 to 20130814
+가입하지 않은 사용자입니다.
+User is offline.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_AGE = 0x731,
+/*20101019 to latest
+구매하기
+Buy
+20130807 to 20130814
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_NC_BUY = 0x732,
+/*20101019 to latest
+장바구니 비우기
+Cancel.
+20130807 to 20130814
+구매하기
+Buy
+*/
+ MSG_NC_BLANK = 0x733,
+/*20101019 to latest
+첫 페이지
+First page
+20130807 to 20130814
+장바구니 비우기
+Cancel.
+*/
+ MSG_NC_FIRSTPAGE = 0x734,
+/*20101019 to latest
+마지막 페이지
+Last page
+20130807 to 20130814
+첫 페이지
+First page
+*/
+ MSG_NC_LASTPAGE = 0x735,
+/*20101019 to latest
+신규
+New
+20130807 to 20130814
+마지막 페이지
+Last page
+*/
+ MSG_NC_CAT1 = 0x736,
+/*20101019 to latest
+인기
+Headgears
+20130807 to 20130814
+신규
+New
+*/
+ MSG_NC_CAT2 = 0x737,
+/*20101019 to latest
+한정
+Limited
+20130807 to 20130814
+인기
+Headgears
+*/
+ MSG_NC_CAT3 = 0x738,
+/*20101019 to latest
+임대장비
+Rental Items
+20130807 to 20130814
+한정
+Limited
+*/
+ MSG_NC_CAT4 = 0x739,
+/*20101019 to latest
+영구장비
+Equipments
+20130807 to 20130814
+임대장비
+Rental Items
+*/
+ MSG_NC_CAT5 = 0x73a,
+/*20101019 to latest
+버프
+Scrolls
+20130807 to 20130814
+영구장비
+Equipments
+*/
+ MSG_NC_CAT6 = 0x73b,
+/*20101019 to latest
+회복
+Consumables
+20130807 to 20130814
+버프
+Scrolls
+*/
+ MSG_NC_CAT7 = 0x73c,
+/*20101019 to latest
+기타
+Other
+20130807 to 20130814
+회복
+Consumables
+*/
+ MSG_NC_CAT8 = 0x73d,
+/*20101019 to latest
+가격
+Cost
+20130807 to 20130814
+기타
+Other
+*/
+ MSG_NC_COST = 0x73e,
+/*20101019 to latest
+수량
+Quantity
+20130807 to 20130814
+가격
+Cost
+*/
+ MSG_NC_NUM = 0x73f,
+/*20101019 to latest
+개
+Total
+20130807 to 20130814
+수량
+Quantity
+*/
+ MSG_NC_COUNT = 0x740,
+/*20101019 to latest
+무료 캐시 : %s C
+Free Cash: %s C
+20130807 to 20130814
+개
+Total
+*/
+ MSG_NC_FREECASH = 0x741,
+/*20101019 to latest
+소지 캐시 : %s C
+CashPoints: %s C
+20130807 to 20130814
+무료 캐시 : %s C
+Free Cash: %s C
+*/
+ MSG_NC_CASH = 0x742,
+/*20101019 to latest
+이 지역에서는 몬스터 소환이 불가능합니다.
+You cannot summon a monster in this area.
+20130807 to 20130814
+소지 캐시 : %s C
+CashPoints: %s C
+*/
+ MSG_CALLMONSTER_FAIL_AREA = 0x743,
+#endif
+#if PACKETVER >= 20101109
+/*20101109 to latest
+무료캐시 사용량이 전체 금액을 초과하고있습니다
+Exceeded total free cash
+20130807 to 20130814
+이 지역에서는 몬스터 소환이 불가능합니다.
+You cannot summon a monster in this area.
+*/
+ MSG_BUY_CASH_FAIL2 = 0x744,
+/*20101109 to latest
+ 설정한 내용이 [SaveData_ExMacro%d]에 저장됩니다.
+%d seconds left until you can use
+20130807 to 20130814
+무료캐시 사용량이 전체 금액을 초과하고있습니다
+Exceeded total free cash
+*/
+ MSG_MACRO_SAVE_DATA = 0x745,
+#endif
+#if PACKETVER >= 20101123
+/*20101123 to latest
+약 %d 초 후에 사용할 수 있습니다
+Content has been saved in [SaveData_ExMacro%d]
+20130807 to 20130814
+ 설정한 내용이 [SaveData_ExMacro%d]에 저장됩니다.
+%d seconds left until you can use
+*/
+ MSG_ITEM_REUSE_LIMIT_SECOND = 0x746,
+#endif
+#if PACKETVER >= 20101207
+/*20101207 to latest
+[창]을 장착한 상태여야 합니다.
+~ [Windows] must be equipped with.
+20130807 to 20130814
+약 %d 초 후에 사용할 수 있습니다
+Content has been saved in [SaveData_ExMacro%d]
+*/
+ MSG_FAIL_NEED_EQUIPPED_SPEAR = 0x747,
+#endif
+#if PACKETVER >= 20101214
+/*20101214 to latest
+드래곤 탑승시에만 사용가능합니다.
+Available only on the dragon.
+20130807 to 20130814
+[창]을 장착한 상태여야 합니다.
+~ [Windows] must be equipped with.
+*/
+ MSG_USESKILL_FAIL_DRAGON = 0x748,
+/*20101214 to latest
+본 서버에 접속할 수 있는 정원이 초과되어 진입이 불가능 합니다.
+Unable to proceed due to exceeding capacity.
+20130807 to 20130814
+드래곤 탑승시에만 사용가능합니다.
+Available only on the dragon.
+*/
+ MSG_OVER_CONNECT_USER = 0x749,
+#endif
+#if PACKETVER >= 20101228
+/*20101228 to latest
+실명 인증이 되지 않았습니다. 실명인증 사이트로 이동합니다
+Real name has not been verified. Go to name verification site.
+20130807 to 20130814
+본 서버에 접속할 수 있는 정원이 초과되어 진입이 불가능 합니다.
+Unable to proceed due to exceeding capacity.
+*/
+ MSG_AUTHENTICATE = 0x74a,
+#endif
+#if PACKETVER >= 20110104
+/*20110104 to latest
+저장 할 슬롯을 선택 해 주세요
+Please select slot you are going to save.
+20130807 to 20130814
+실명 인증이 되지 않았습니다. 실명인증 사이트로 이동합니다
+Real name has not been verified. Go to name verification site.
+*/
+ MSG_SELECT_SAVESLOT = 0x74b,
+#endif
+#if PACKETVER >= 20110111
+/*20110111 to latest
+%s, 축하드립니다. '%s' 를 얻으셨습니다!
+Congratulation %s, Acquired '%s' !
+20130807 to 20130814
+저장 할 슬롯을 선택 해 주세요
+Please select slot you are going to save.
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN2 = 0x74c,
+#endif
+#if PACKETVER >= 20110118
+/*20110118 to latest
+그루미상태에서는 사용할 수 없습니다
+Unable to use in gloomy state
+20130807 to 20130814
+%s, 축하드립니다. '%s' 를 얻으셨습니다!
+Congratulation %s, Acquired '%s' !
+*/
+ MSG_NOTUSE_GROOMY = 0x74d,
+#endif
+#if PACKETVER >= 20110210
+/*20110210 to latest
+구매물품의 합계금액이 케릭터가 소지할 수 있는 최대 금액을 초과하였습니다
+Purchased products has exceeded the total price.
+20130807 to 20130814
+그루미상태에서는 사용할 수 없습니다
+Unable to use in gloomy state
+*/
+ MSG_BUYINGSTORE_OVERFLOW_MONEY = 0x74e,
+#endif
+#if PACKETVER >= 20110215
+/*20110215 to latest
+현재 맵에서는 파티 가입이 불가능합니다.
+Cannot join a party in this map.
+20130807 to 20130814
+구매물품의 합계금액이 케릭터가 소지할 수 있는 최대 금액을 초과하였습니다
+Purchased products has exceeded the total price.
+*/
+ MSG_PREVENT_PARTY_JOIN = 0x74f,
+/*20110215 to latest
+현재 맵에서는 파티 탈퇴가 불가능합니다.
+Cannot leave a party in this map.
+20130807 to 20130814
+현재 맵에서는 파티 가입이 불가능합니다.
+Cannot join a party in this map.
+*/
+ MSG_PREVENT_PARTY_LEAVE = 0x750,
+/*20110215 to latest
+현재 맵에서는 파티 추방이 불가능합니다.
+Cannot withdraw/break the party in this map.
+20130807 to 20130814
+현재 맵에서는 파티 탈퇴가 불가능합니다.
+Cannot leave a party in this map.
+*/
+ MSG_PREVENT_PARTY_EXPEL = 0x751,
+/*20110215 to latest
+실제 성명
+Real Name
+20130807 to 20130814
+현재 맵에서는 파티 추방이 불가능합니다.
+Cannot withdraw/break the party in this map.
+*/
+ MSG_SDO_REALNAME = 0x752,
+/*20110215 to latest
+신분증 번호
+ID Number
+20130807 to 20130814
+실제 성명
+Real Name
+*/
+ MSG_SDO_ID_NUMBER = 0x753,
+/*20110215 to latest
+이메일
+E-mail
+20130807 to 20130814
+신분증 번호
+ID Number
+*/
+ MSG_SDO_EMAIL = 0x754,
+/*20110215 to latest
+입력이 올바르지 않습니다
+Invalid input
+20130807 to 20130814
+이메일
+E-mail
+*/
+ MSG_SDO_WRONG_VALUE = 0x755,
+#endif
+#if PACKETVER >= 20110222
+/*20110222 to 20130508
+상대방에게 제니 지급에 실패했습니다.
+20130515 to latest
+상대 캐릭터가 최대 보유제니량을 초과하여 거래가 불가능합니다.
+Failed to send the zeny
+20130807 to 20130814
+입력이 올바르지 않습니다
+Invalid input
+*/
+ MSG_MCSTORE_FAIL_SELLER_MONEY_GIVE = 0x756,
+/*20110222 to latest
+해당 직업이 아닙니다.
+This is not a relevant job
+20130807 to 20130814
+상대 캐릭터가 최대 보유제니량을 초과하여 거래가 불가능합니다.
+Failed to send the zeny
+*/
+ MSG_INVALID_CLASS = 0x757,
+/*20110222 to latest
+해당 성별이 아닙니다.
+This is not a relevant gender
+20130807 to 20130814
+해당 직업이 아닙니다.
+This is not a relevant job
+*/
+ MSG_INVALID_GENDER = 0x758,
+/*20110222 to latest
+유저님의 정보가 인증에 성공했습니다.
+User information identification was successful.
+20130807 to 20130814
+해당 성별이 아닙니다.
+This is not a relevant gender
+*/
+ MSG_SUCCESS_AUTHENTICATE = 0x759,
+/*20110222 to latest
+이름이 일치하지 않습니다. 재작성 해주세요.
+Name does not match. Please retry.
+20130807 to 20130814
+유저님의 정보가 인증에 성공했습니다.
+User information identification was successful.
+*/
+ MSG_INVALID_REALNAME = 0x75a,
+/*20110222 to latest
+신분증 번호가 일치하지 않습니다. 재작성 해주세요.
+ID number does not match. Please retry.
+20130807 to 20130814
+이름이 일치하지 않습니다. 재작성 해주세요.
+Name does not match. Please retry.
+*/
+ MSG_INVALID_IDNUMBER = 0x75b,
+/*20110222 to latest
+현재 서비스에 이상이 있으니 잠시 후 재시도 해주세요.
+Service is currently unavailable. Please try again later.
+20130807 to 20130814
+신분증 번호가 일치하지 않습니다. 재작성 해주세요.
+ID number does not match. Please retry.
+*/
+ MSG_INVALID_AUTHENTICATE = 0x75c,
+#endif
+#if PACKETVER >= 20110224
+/*20110224 to latest
+ 탑승 상태에서는 공격을 할 수 없습니다.
+Unable to attack while riding.
+20130807 to 20130814
+현재 서비스에 이상이 있으니 잠시 후 재시도 해주세요.
+Service is currently unavailable. Please try again later.
+*/
+ MSG_CANNOT_ATTACK_IN_RIDING_STATE = 0x75d,
+/*20110224 to latest
+ 탑승 상태에서는 스킬 시전을 할 수 없습니다.
+Unable to cast the skill while riding.
+20130807 to 20130814
+ 탑승 상태에서는 공격을 할 수 없습니다.
+Unable to attack while riding.
+*/
+ MSG_CANNOT_USE_SKILL_IN_RIDING_STATE = 0x75e,
+#endif
+#if PACKETVER >= 20110228
+/*20110228 to 20110228
+비밀번호는 4자리 이상 6자리이하여야만 합니다.
+20110308 to latest
+비밀번호는 4자리이하여야만 합니다.
+Pin number should be 4~6 characters.
+20130807 to 20130814
+ 탑승 상태에서는 스킬 시전을 할 수 없습니다.
+Unable to cast the skill while riding.
+*/
+ MSG_STORE_PASSWORD_4_6 = 0x75f,
+/*20110228 to 20110228
+로그인에 성공했습니다.
+20110308 to latest
+보안 인증에 성공했습니다.
+Secured authentication is successful.
+20130807 to 20130814
+비밀번호는 4자리이하여야만 합니다.
+Pin number should be 4~6 characters.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_SUCCESS = 0x760,
+/*20110228 to 20110228
+세컨드 패스워드의 생성에 성공했습니다.
+20110308 to latest
+보안 패스워드의 생성에 성공했습니다.
+Succeeded in creating 2nd password.
+20130807 to 20130814
+보안 인증에 성공했습니다.
+Secured authentication is successful.
+*/
+ MSG_SECOND_PASSWORD_MAKE_SUCCESS = 0x761,
+/*20110228 to 20110228
+세컨드 패스워드를 삭제했습니다.
+20110308 to latest
+보안 패스워드를 삭제했습니다.
+2nd password has been deleted.
+20130807 to 20130814
+보안 패스워드의 생성에 성공했습니다.
+Succeeded in creating 2nd password.
+*/
+ MSG_SECOND_PASSWORD_DEL_SUCCESS = 0x762,
+/*20110228 to 20110228
+세컨드 패스워드를 수정했습니다.
+20110308 to latest
+보안 패스워드를 수정했습니다.
+2nd password has been corrected.
+20130807 to 20130814
+보안 패스워드를 삭제했습니다.
+2nd password has been deleted.
+*/
+ MSG_SECOND_PASSWORD_EDIT_SUCCESS = 0x763,
+/*20110228 to 20110228
+로그인에 실패했습니다.
+20110308 to latest
+잘못된 패스워드입니다.(%d회남음)
+Password is incorrect.
+20130807 to 20130814
+보안 패스워드를 수정했습니다.
+2nd password has been corrected.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_FAILED = 0x764,
+/*20110228 to 20110228
+세컨드 패스워드의 생성에 실패했습니다.
+20110308 to latest
+보안 패스워드의 생성에 실패했습니다.
+Failed to create 2nd password.
+20130807 to 20130814
+잘못된 패스워드입니다.(%d회남음)
+Password is incorrect.
+*/
+ MSG_SECOND_PASSWORD_MAKE_FAILED = 0x765,
+/*20110228 to 20110228
+세컨드 패스워드 삭제에 실패했습니다.
+20110308 to latest
+보안 패스워드 삭제에 실패했습니다.
+Failed to delete 2nd password.
+20130807 to 20130814
+보안 패스워드의 생성에 실패했습니다.
+Failed to create 2nd password.
+*/
+ MSG_SECOND_PASSWORD_DEL_FAILED = 0x766,
+/*20110228 to 20110228
+세컨드 패스워드의 수정에 실패했습니다.
+20110308 to latest
+보안 패스워드의 수정에 실패했습니다.
+Failed to correct 2nd password.
+20130807 to 20130814
+보안 패스워드 삭제에 실패했습니다.
+Failed to delete 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_FAILED = 0x767,
+/*20110228 to 20110228
+세컨드 비밀번호에는 제한된 번호를 사용할수 없습니다.
+20110308 to latest
+입력하신패스워드는 사용하실수없습니다.
+Unable to use restricted number in 2nd password.
+20130807 to 20130814
+보안 패스워드의 수정에 실패했습니다.
+Failed to correct 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_RESTRICT_PW = 0x768,
+/*20110228 to latest
+주민등록번호는 사용할수없습니다.
+Unable to use your KSSN number.
+20130807 to 20130814
+입력하신패스워드는 사용하실수없습니다.
+Unable to use restricted number in 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_PERSONALNUM_PW = 0x769,
+/*20110228 to 20110228
+보안번호
+20110308 to latest
+이미 패스워드가 존재합니다.
+~There is already a password.
+20130807 to 20130814
+주민등록번호는 사용할수없습니다.
+Unable to use your KSSN number.
+*/
+ MSG_SECOND_PASSWORD_MAKE_DUPLICATED_PW = 0x76a,
+/*20110228 to 20110228
+비밀번호 입력 (4~6자리)
+20110308 to latest
+보안 패스워드
+Security Code
+20130807 to 20130814
+이미 패스워드가 존재합니다.
+~There is already a password.
+*/
+ MSG_SECOND_PASSWORD = 0x76b,
+/*20110228 to 20110228
+ITEM
+20110308 to latest
+계정보안을 위하여 추가적인 패스워드 설정을 권장합니다.
+Account for the additional password security settings are recommended.
+20130807 to 20130814
+보안 패스워드
+Security Code
+*/
+ MSG_SECOND_PASSWORD_INPUT = 0x76c,
+/*20110228 to 20110228
+SKILL
+20110308 to latest
+보안 패스워드 사용을 하지 않습니다.
+Do not use secure password.
+20130807 to 20130814
+계정보안을 위하여 추가적인 패스워드 설정을 권장합니다.
+Account for the additional password security settings are recommended.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_SUCCESS = 0x76d,
+/*20110228 to 20110228
+TACTIC
+20110308 to latest
+보안 패스워드 사용설정에 실패했습니다.
+Use the set security password failed.
+20130807 to 20130814
+보안 패스워드 사용을 하지 않습니다.
+Do not use secure password.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_FAILED = 0x76e,
+/*20110228 to 20110228
+ETC
+20110308 to latest
+보안 패스워드를 사용합니다. 다음로그인부터 적용됩니다.
+Use secure passwords. Will be applied to your next login.
+20130807 to 20130814
+보안 패스워드 사용설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_SUCCESS = 0x76f,
+/*20110228 to 20110228
+COMBAT
+20110308 to latest
+보안 패스워드 사용 설정에 실패했습니다.
+Use the set security password failed.
+20130807 to 20130814
+보안 패스워드를 사용합니다. 다음로그인부터 적용됩니다.
+Use secure passwords. Will be applied to your next login.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_FAILED = 0x770,
+/*20110228 to 20110228
+NON-COMBAT
+20110308 to latest
+계정보안을 위하여 추가적인 패스워드를 설정합니다.
+Added to the security of your account password is set.
+20130807 to 20130814
+보안 패스워드 사용 설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWORD_INFO_1 = 0x771,
+/*20110228 to 20110228
+BUFF
+20110308 to latest
+아래의 숫자버튼을 마우스를 이용하여 4자리를 클릭하세요.
+Use the mouse to enter the 4-digit password below.
+20130807 to 20130814
+계정보안을 위하여 추가적인 패스워드를 설정합니다.
+Added to the security of your account password is set.
+*/
+ MSG_SECOND_PASSWORD_INFO_2 = 0x772,
+/*20110228 to 20110228
+AUTO EQUIPED
+20110308 to latest
+3회이상 잘못된패스워드 입력으로, 종료됩니다.
+Typing an incorrect password 3 times will shut down the client.
+20130807 to 20130814
+아래의 숫자버튼을 마우스를 이용하여 4자리를 클릭하세요.
+Use the mouse to enter the 4-digit password below.
+*/
+ MSG_SECOND_PASSWORD_INFO_3 = 0x773,
+/*20110228 to 20110228
+1st. ATTACK
+20110308 to latest
+ITEM
+20130807 to 20130814
+3회이상 잘못된패스워드 입력으로, 종료됩니다.
+Typing an incorrect password 3 times will shut down the client.
+*/
+ MSG_MACRO_ITEM = 0x774,
+/*20110228 to 20110228
+ATTACK
+20110308 to latest
+SKILL
+20130807 to 20130814
+ITEM
+*/
+ MSG_MACRO_SKILL = 0x775,
+/*20110228 to 20110228
+Next attack time :
+20110308 to latest
+TACTIC
+20130807 to 20130814
+SKILL
+*/
+ MSG_MACRO_TACTIC = 0x776,
+/*20110228 to 20110228
+When died
+20110308 to latest
+ETC
+20130807 to 20130814
+TACTIC
+*/
+ MSG_MACRO_ETC = 0x777,
+/*20110228 to 20110228
+When invited to a party
+When invited to the party
+20110308 to latest
+COMBAT
+20130807 to 20130814
+ETC
+*/
+ MSG_MACRO_COMBAT = 0x778,
+/*20110228 to 20110228
+Pickup Item
+20110308 to latest
+NON-COMBAT
+20130807 to 20130814
+COMBAT
+*/
+ MSG_MACRO_NON_COMBAT = 0x779,
+/*20110228 to 20110228
+Over 85% Weight
+20110308 to latest
+BUFF
+20130807 to 20130814
+NON-COMBAT
+*/
+ MSG_MACRO_BUFF = 0x77a,
+#endif
+#if PACKETVER >= 20110308
+/*20110308 to latest
+AUTO EQUIPED
+20130807 to 20130814
+BUFF
+*/
+ MSG_MACRO_AUTO_EQUIPED = 0x77b,
+/*20110308 to latest
+1st. ATTACK
+20130807 to 20130814
+AUTO EQUIPED
+*/
+ MSG_MACRO_1ST_ATTACK = 0x77c,
+/*20110308 to latest
+ATTACK
+20130807 to 20130814
+1st. ATTACK
+*/
+ MSG_MACRO_ATTACK = 0x77d,
+/*20110308 to latest
+Next attack time :
+20130807 to 20130814
+ATTACK
+*/
+ MSG_MACRO_NEXT_ATK_TIME = 0x77e,
+/*20110308 to latest
+When died
+20130807 to 20130814
+Next attack time :
+*/
+ MSG_MACRO_WHEN_DIED = 0x77f,
+/*20110308 to latest
+When invited to a party
+When invited to the party
+20130807 to 20130814
+When died
+*/
+ MSG_MACRO_WHEN_INVITED_PARTY = 0x780,
+/*20110308 to latest
+Pickup Item
+20130807 to 20130814
+When invited to a party
+When invited to the party
+*/
+ MSG_MACRO_PICKUP_ITEM = 0x781,
+/*20110308 to latest
+Over 85% Weight
+20130807 to 20130814
+Pickup Item
+*/
+ MSG_MACRO_OVERWEIGHT = 0x782,
+/*20110308 to latest
+진행중이던 작업(NPC대화,제조...)을 종료후에 다시 시도하세요.
+Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+20130807 to 20130814
+Over 85% Weight
+*/
+ MSG_BUSY = 0x783,
+/*20110308 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 %d분간 %.2f배로 증가합니다.
+Monster Job hunting experience that you can get through the doubling of %d is %.2f minutes.
+20130807 to 20130814
+진행중이던 작업(NPC대화,제조...)을 종료후에 다시 시도하세요.
+Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+*/
+ MSG_PLUSONLYJOBEXP2 = 0x784,
+#endif
+#if PACKETVER >= 20110315
+/*20110315 to 20110405
+ExMacro_SaveData%d
+20110412 to latest
+SaveData_ExMacro%d
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 %d분간 %.2f배로 증가합니다.
+Monster Job hunting experience that you can get through the doubling of %d is %.2f minutes.
+*/
+ MSG_MACRO_SAVE = 0x785,
+/*20110315 to latest
+ 설정한 내용이 [%s]에 저장됩니다.
+Settings for [%s] are stored in.
+20130807 to 20130814
+SaveData_ExMacro%d
+*/
+ MSG_MACRO_SAVE_DATA2 = 0x786,
+#endif
+#if PACKETVER >= 20110322
+/*20110322 to latest
+보안레벨
+Security level
+20130807 to 20130814
+ 설정한 내용이 [%s]에 저장됩니다.
+Settings for [%s] are stored in.
+*/
+ MSG_SECOND_PASSWORD_LEVEL = 0x787,
+#endif
+#if PACKETVER >= 20110412
+/*20110412 to latest
+현재 캐릭터는 파티 또는 길드에 가입되어 있어서 삭제가 불가능합니다.
+The current character is a party or join the guild can not be deleted.
+20130807 to 20130814
+보안레벨
+Security level
+*/
+ MSG_RESULT_FAIL_CHAR_DELETE = 0x788,
+#endif
+#if PACKETVER >= 20110523
+/*20110523 to latest
+벽이나 물체 근처에서만 사용 할 수 있습니다.
+Objects can be used only near the wall.
+20130807 to 20130814
+현재 캐릭터는 파티 또는 길드에 가입되어 있어서 삭제가 불가능합니다.
+The current character is a party or join the guild can not be deleted.
+*/
+ MSG_USESKILL_FAIL_NEER_WALL = 0x789,
+#endif
+#if PACKETVER >= 20110531
+/*20110531 to latest
+%s : 레벨 %d %s 파티구합니다.
+%s: Level %d %s party to obtain level.
+20130807 to 20130814
+벽이나 물체 근처에서만 사용 할 수 있습니다.
+Objects can be used only near the wall.
+*/
+ MSG_SEEK_PARTY_SET = 0x78a,
+/*20110531 to latest
+탑승 중인 상태에서는 고삐 아이템을 사용할 수 없습니다.
+While boarding reins is not available for items.
+20130807 to 20130814
+%s : 레벨 %d %s 파티구합니다.
+%s: Level %d %s party to obtain level.
+*/
+ MSG_FAIELD_RIDING_OVERLAPPED = 0x78b,
+#endif
+#if PACKETVER >= 20110620
+/*20110620 to latest
+이 스킬은 1%의 경험치가 필요합니다.
+This skill requires 1% experience.
+20130807 to 20130814
+탑승 중인 상태에서는 고삐 아이템을 사용할 수 없습니다.
+While boarding reins is not available for items.
+*/
+ MSG_USESKILL_FAIL_NEED_EXP_1PERCENT = 0x78c,
+#endif
+#if PACKETVER >= 20110627
+/*20110627 to latest
+경 험 치 :
+Experience value:
+20130807 to 20130814
+이 스킬은 1%의 경험치가 필요합니다.
+This skill requires 1% experience.
+*/
+ MSG_EXP_MSG = 0x78d,
+/*20110627 to latest
+드 롭 율 :
+Drop rate:
+20130807 to 20130814
+경 험 치 :
+Experience value:
+*/
+ MSG_DROP_MSG = 0x78e,
+/*20110627 to latest
+사망페널티 :
+Death Penalty:
+20130807 to 20130814
+드 롭 율 :
+Drop rate:
+*/
+ MSG_DEATH_MSG = 0x78f,
+/*20110627 to 20110711
+%d%% (PC방 %d%% + 프리미엄 %d%% + %s서버 %d%%)
+20110713 to latest
+%d%% (PC방 %d%% + TPLUS %d%% + 프리미엄 %d%% + %s서버 %d%%)
+%d%% (PCroom %d%% + TPLUS %d%% + Premium %d%% + %s Server %d%%)
+20130807 to 20130814
+사망페널티 :
+Death Penalty:
+*/
+ MSG_BASIC_EXP_MSG = 0x790,
+/*20110627 to latest
+ 합창스킬을 시전할 파티원의 SP량이 부족합니다.
+Amount of party members to cast the skill Chorus SP is low.
+20130807 to 20130814
+%d%% (PC방 %d%% + TPLUS %d%% + 프리미엄 %d%% + %s서버 %d%%)
+%d%% (PCroom %d%% + TPLUS %d%% + Premium %d%% + %s Server %d%%)
+*/
+ MSG_USESKILL_FAIL_CHORUS_SP_INSUFFICIENT = 0x791,
+#endif
+#if PACKETVER >= 20110705
+/*20110705 to latest
+상대 캐릭터의 소지 아이템 종류의 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the items can not trade because amount is exceeded.
+20130807 to 20130814
+ 합창스킬을 시전할 파티원의 SP량이 부족합니다.
+Amount of party members to cast the skill Chorus SP is low.
+*/
+ MSG_CHARACTER_IS_OVER_COUNT = 0x792,
+/*20110705 to latest
+상대 캐릭터의 해당 아이템의 소지 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the item amount which exceeds makes it impossible to trade.
+20130807 to 20130814
+상대 캐릭터의 소지 아이템 종류의 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the items can not trade because amount is exceeded.
+*/
+ MSG_CHARACTER_IS_EACHITEM_OVER_COUNT = 0x793,
+/*20110705 to latest
+해당 아이템의 소지 한계량 초과로 구입이 불가능합니다.
+Amounts are exceeded the possession of the item is not available for purchase.
+20130807 to 20130814
+상대 캐릭터의 해당 아이템의 소지 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the item amount which exceeds makes it impossible to trade.
+*/
+ MSG_PURCHASE_FAIL_EACHITEM_COUNT = 0x794,
+/*20110705 to 20110705
+잠시후에 다시 시도해주세요.
+20110711 to latest
+광고 등록 대기중입니다.
+Advertising is pending registration.
+20130807 to 20130814
+해당 아이템의 소지 한계량 초과로 구입이 불가능합니다.
+Amounts are exceeded the possession of the item is not available for purchase.
+*/
+ MSG_PARTY_FAILED_TIMEOUT = 0x795,
+/*20110705 to latest
+아래의 파일과 텍스트내용을 함께
+라그나로크 공식홈페이지 -> 고객센터 -> 문의하기를
+이용하여 보내주시기 바랍니다.
+With the following files and text content Ragnarok Official Website -> Support -> Contact Us to submit your comments by:
+20130807 to 20130814
+광고 등록 대기중입니다.
+Advertising is pending registration.
+*/
+ MSG_UNEXCEPTION_MSG1ST = 0x796,
+#endif
+#if PACKETVER >= 20110718
+/*20110718 to latest
+빌링시스템에 오류가 발생햇습니다(%d)
+Has caused an error in billing system(%d)
+20130807 to 20130814
+아래의 파일과 텍스트내용을 함께
+라그나로크 공식홈페이지 -> 고객센터 -> 문의하기를
+이용하여 보내주시기 바랍니다.
+With the following files and text content Ragnarok Official Website -> Support -> Contact Us to submit your comments by:
+*/
+ MSG_INGAMBA_BILLING_ZSVR_ERROR = 0x797,
+/*20110718 to latest
+룬 아이템 소유 개수가 초과 되어 구매가 실패 하였습니다.
+Failed purchase of runes, items exceed the maximum number that can be held.
+20130807 to 20130814
+빌링시스템에 오류가 발생햇습니다(%d)
+Has caused an error in billing system(%d)
+*/
+ MSG_CASH_FAILED_RUNE_OVERCOUNT = 0x798,
+/*20110718 to latest
+개별 아이템 개수가 초과 되어 구매가 실패 하였습니다.
+Exceeded the number of individual items, purchase failed.
+20130807 to 20130814
+룬 아이템 소유 개수가 초과 되어 구매가 실패 하였습니다.
+Failed purchase of runes, items exceed the maximum number that can be held.
+*/
+ MSG_CASH_FAILED_EACHITEM_OVERCOUNT = 0x799,
+/*20110718 to latest
+알 수 없는 오류가 발생하여 구매가 실패 하였습니다.
+Purchase failed due to an unknown error.
+20130807 to 20130814
+개별 아이템 개수가 초과 되어 구매가 실패 하였습니다.
+Exceeded the number of individual items, purchase failed.
+*/
+ MSG_CASH_FAILED_UNKOWN = 0x79a,
+/*20110718 to latest
+잠시 후 다시 시도해 주십시오.
+Please try again later.
+20130807 to 20130814
+알 수 없는 오류가 발생하여 구매가 실패 하였습니다.
+Purchase failed due to an unknown error.
+*/
+ MSG_CASH_FAILED_BUSY = 0x79b,
+/*20110718 to latest
+ 쿠나이 아이템을 장착 한 상태에서만 사용 가능합니다.
+Kunai must be equipped to use this skill.
+20130807 to 20130814
+잠시 후 다시 시도해 주십시오.
+Please try again later.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT_KUNAI = 0x79c,
+#endif
+#if PACKETVER >= 20110726
+/*20110726 to latest
+모집할 최소레벨값을 입력해주세요.
+Please enter the value of the minimum level to be recruited.
+20130807 to 20130814
+ 쿠나이 아이템을 장착 한 상태에서만 사용 가능합니다.
+Kunai must be equipped to use this skill.
+*/
+ MSG_SEEK_PARTY_LEVEL_HELP = 0x79d,
+#endif
+#if PACKETVER >= 20110802
+/*20110802 to latest
+존다기획사NPC 에게 아이템이 수령이 불가능합니다. 소지창의 여유공간을 확보해주세요.
+Jonda agency receipt of the item to the NPC is not possible. Gaining possession of the free space of the window.
+20130807 to 20130814
+모집할 최소레벨값을 입력해주세요.
+Please enter the value of the minimum level to be recruited.
+*/
+ MSG_FAILED_GET_ITEM_FROM_ZONEDA = 0x79e,
+#endif
+#if PACKETVER >= 20110809
+/*20110809 to latest
+이 스킬은 공성전에서만 사용 가능합니다.
+This skill is only available in the siege.
+20130807 to 20130814
+존다기획사NPC 에게 아이템이 수령이 불가능합니다. 소지창의 여유공간을 확보해주세요.
+Jonda agency receipt of the item to the NPC is not possible. Gaining possession of the free space of the window.
+*/
+ MSG_USESKILL_FAIL_SIZE = 0x79f,
+/*20110809 to latest
+이 스킬은 플레이어에게만 사용 가능합니다.
+This skill is available only to the player.
+20130807 to 20130814
+이 스킬은 공성전에서만 사용 가능합니다.
+This skill is only available in the siege.
+*/
+ MSG_USESKILL_FAIL_TOTARGET_PLAYER = 0x7a0,
+/*20110809 to latest
+착용이 금지 된 상태로 착용 할 수 없습니다.
+Forbidden to wear the state can not be worn.
+20130807 to 20130814
+이 스킬은 플레이어에게만 사용 가능합니다.
+This skill is available only to the player.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM_FORBID = 0x7a1,
+/*20110809 to latest
+현재 위치에서는 상점 및 채팅방의 생성이 불가능합니다.
+Current location of the shop and chat room creation is disabled.
+20130807 to 20130814
+착용이 금지 된 상태로 착용 할 수 없습니다.
+Forbidden to wear the state can not be worn.
+*/
+ MSG_USESKILL_FAIL_THERE_ARE_NPC_AROUND = 0x7a2,
+#endif
+#if PACKETVER >= 20110816
+/*20110816 to latest
+Elapsed time: %d:%d:%d / %d:%d:%d
+20130807 to 20130814
+현재 위치에서는 상점 및 채팅방의 생성이 불가능합니다.
+Current location of the shop and chat room creation is disabled.
+*/
+ MSG_REPLAY_ELAPSEDTIME = 0x7a3,
+/*20110816 to latest
+Speed : X 1/4
+20130807 to 20130814
+Elapsed time: %d:%d:%d / %d:%d:%d
+*/
+ MSG_REPLAY_SPEED1_4 = 0x7a4,
+/*20110816 to latest
+Speed : X 1/2
+20130807 to 20130814
+Speed : X 1/4
+*/
+ MSG_REPLAY_SPEED1_2 = 0x7a5,
+/*20110816 to latest
+Speed : X 1
+20130807 to 20130814
+Speed : X 1/2
+*/
+ MSG_REPLAY_SPEED1 = 0x7a6,
+/*20110816 to latest
+Speed : X 2
+20130807 to 20130814
+Speed : X 1
+*/
+ MSG_REPLAY_SPEED2 = 0x7a7,
+/*20110816 to latest
+Speed : X 4
+20130807 to 20130814
+Speed : X 2
+*/
+ MSG_REPLAY_SPEED4 = 0x7a8,
+/*20110816 to latest
+Speed : X 8
+20130807 to 20130814
+Speed : X 4
+*/
+ MSG_REPLAY_SPEED8 = 0x7a9,
+/*20110816 to latest
+Speed : X 16
+20130807 to 20130814
+Speed : X 8
+*/
+ MSG_REPLAY_SPEED16 = 0x7aa,
+/*20110816 to latest
+Speed : 알수없음
+Speed: Unknown
+20130807 to 20130814
+Speed : X 16
+*/
+ MSG_REPLAY_SPEEDUNKNOWN = 0x7ab,
+/*20110816 to latest
+Service Info : %s
+20130807 to 20130814
+Speed : 알수없음
+Speed: Unknown
+*/
+ MSG_REPLAY_CHRVICEINFO = 0x7ac,
+/*20110816 to latest
+Character Name : %s
+20130807 to 20130814
+Service Info : %s
+*/
+ MSG_REPLAY_CHARACTERNAME = 0x7ad,
+/*20110816 to latest
+Map Name : %s
+20130807 to 20130814
+Character Name : %s
+*/
+ MSG_REPLAY_MAPNAME = 0x7ae,
+/*20110816 to latest
+Record Time: %d-%01d-%01d %d: %02d: %02d
+20130807 to 20130814
+Map Name : %s
+*/
+ MSG_REPLAY_RECORDTIME = 0x7af,
+/*20110816 to latest
+Play Time: %02d: %02d: %02d
+20130807 to 20130814
+Record Time: %d-%01d-%01d %d: %02d: %02d
+*/
+ MSG_REPLAY_PLAYTIME = 0x7b0,
+/*20110816 to latest
+No Replay File.
+20130807 to 20130814
+Play Time: %02d: %02d: %02d
+*/
+ MSG_REPLAY_NOREPLAYFILE = 0x7b1,
+/*20110816 to latest
+Server No Matching
+20130807 to 20130814
+No Replay File.
+*/
+ MSG_REPLAY_SERVERNOMATCH = 0x7b2,
+/*20110816 to latest
+Replay Option Setting
+20130807 to 20130814
+Server No Matching
+*/
+ MSG_REPLAY_REPLAYOPTIONSETTING = 0x7b3,
+/*20110816 to latest
+파일 이름을 입력하세요.
+Enter File Name
+20130807 to 20130814
+Replay Option Setting
+*/
+ MSG_REPLAY_ENTERTHEFILENAME = 0x7b4,
+/*20110816 to latest
+Set Replay Save Data
+20130807 to 20130814
+파일 이름을 입력하세요.
+Enter File Name
+*/
+ MSG_REPLAY_SETREPLAYSAVEDATA = 0x7b5,
+/*20110816 to latest
+Set Rec Option
+20130807 to 20130814
+Set Replay Save Data
+*/
+ MSG_REPLAY_SETRECOPTION = 0x7b6,
+/*20110816 to latest
+%.1f %% Pos☞:%d:%d:%d
+%.1f % Pos->:%d:%d:%d
+20130807 to 20130814
+Set Rec Option
+*/
+ MSG_REPLAY_GAGEPOS1 = 0x7b7,
+/*20110816 to latest
+%.1f %% Pos☞:이동불가
+%.1f % Pos->:cannot move
+20130807 to 20130814
+%.1f %% Pos☞:%d:%d:%d
+%.1f % Pos->:%d:%d:%d
+*/
+ MSG_REPLAY_GAGEPOS2 = 0x7b8,
+/*20110816 to latest
+Start
+20130807 to 20130814
+%.1f %% Pos☞:이동불가
+%.1f % Pos->:cannot move
+*/
+ MSG_REPLAY_START = 0x7b9,
+/*20110816 to latest
+Stop
+20130807 to 20130814
+Start
+*/
+ MSG_REPLAY_STOP = 0x7ba,
+/*20110816 to latest
+Input FileName -> Start
+20130807 to 20130814
+Stop
+*/
+ MSG_REPLAY_START2 = 0x7bb,
+/*20110816 to latest
+Open Option
+Open Options
+20130807 to 20130814
+Input FileName -> Start
+*/
+ MSG_REPLAY_OPENOPTION = 0x7bc,
+/*20110816 to latest
+Close Option
+Close Options
+20130807 to 20130814
+Open Option
+Open Options
+*/
+ MSG_REPLAY_CLOSEOPION = 0x7bd,
+/*20110816 to latest
+End
+20130807 to 20130814
+Close Option
+Close Options
+*/
+ MSG_REPLAY_END = 0x7be,
+/*20110816 to latest
+Time
+20130807 to 20130814
+End
+*/
+ MSG_REPLAY_TIME = 0x7bf,
+/*20110816 to latest
+파티&친구
+Party & Friends
+20130807 to 20130814
+Time
+*/
+ MSG_REPLAY_PARTYFRIEND = 0x7c0,
+/*20110816 to latest
+채팅
+Chat
+20130807 to 20130814
+파티&친구
+Party & Friends
+*/
+ MSG_REPLAY_CHAT = 0x7c1,
+/*20110816 to latest
+단축키
+Shortcuts
+20130807 to 20130814
+채팅
+Chat
+*/
+ MSG_REPLAY_SHORTCUTS = 0x7c2,
+/*20110816 to latest
+자동 파일명 생성
+Automatic filename generation
+20130807 to 20130814
+단축키
+Shortcuts
+*/
+ MSG_REPLAY_AUTOMATICFILENAME = 0x7c3,
+/*20110816 to latest
+파일 중복 채크
+Checking for duplicate files
+20130807 to 20130814
+자동 파일명 생성
+Automatic filename generation
+*/
+ MSG_REPLAY_CHECKINGFILE = 0x7c4,
+/*20110816 to latest
+동일한 파일이 존재 합니다.
+The same file exists already.
+20130807 to 20130814
+파일 중복 채크
+Checking for duplicate files
+*/
+ MSG_REPLAY_THESAMEFILEEXISTS = 0x7c5,
+/*20110816 to latest
+Record Start
+20130807 to 20130814
+동일한 파일이 존재 합니다.
+The same file exists already.
+*/
+ MSG_REPLAY_RECORDSTART = 0x7c6,
+/*20110816 to latest
+ is Saved.
+Recording saved
+20130807 to 20130814
+Record Start
+*/
+ MSG_REPLAY_RECORDEND = 0x7c7,
+#endif
+#if PACKETVER >= 20110823
+/*20110823 to latest
+Weight : %3d / %3d
+20130807 to 20130814
+ is Saved.
+Recording saved
+*/
+ MSG_WEIGHT = 0x7c8,
+/*20110823 to latest
+Total : %s C
+Total: %s EUR
+20130807 to 20130814
+Weight : %3d / %3d
+*/
+ MSG_TOTAL = 0x7c9,
+/*20110823 to latest
+[수리검]을 장착한 상태여야 합니다.
+[Shuriken] must be equipped.
+20130807 to 20130814
+Total : %s C
+Total: %s EUR
+*/
+ MSG_FAIL_NEED_EQUIPPED_SYURIKEN = 0x7ca,
+#endif
+#if PACKETVER >= 20110831
+/*20110831 to latest
+Base Lv. %d
+20130807 to 20130814
+[수리검]을 장착한 상태여야 합니다.
+[Shuriken] must be equipped.
+*/
+ MSG__BASIC_MSG_BASE = 0x7cb,
+/*20110831 to latest
+Job Lv. %d
+20130807 to 20130814
+Base Lv. %d
+*/
+ MSG__BASIC_MSG_JOB = 0x7cc,
+/*20110831 to latest
+Zeny : %s
+20130807 to 20130814
+Job Lv. %d
+*/
+ MSG_BASIC_MSG_ZENY = 0x7cd,
+/*20110831 to latest
+Trilinear
+20130807 to 20130814
+Zeny : %s
+*/
+ MSG_GRAPHIC_MSG_TRILINEAR = 0x7ce,
+/*20110831 to latest
+attack
+20130807 to 20130814
+Trilinear
+*/
+ MSG_GRAPHIC_MSG_ATTACK = 0x7cf,
+/*20110831 to latest
+skill
+20130807 to 20130814
+attack
+*/
+ MSG_GRAPHIC_MSG_SKILL = 0x7d0,
+/*20110831 to latest
+item
+20130807 to 20130814
+skill
+*/
+ MSG_GRAPHIC_MSG_ITEM = 0x7d1,
+/*20110831 to latest
+NoCtrl
+Ctrl
+20130807 to 20130814
+item
+*/
+ MSG_GRAPHIC_MSG_NOCTRL = 0x7d2,
+/*20110831 to latest
+전장
+More
+20130807 to 20130814
+NoCtrl
+Ctrl
+*/
+ MSG_GRAPHIC_MSG_BATTLE = 0x7d3,
+/*20110831 to latest
+(Character/Total Slot)
+(Characters/Total slots)
+20130807 to 20130814
+전장
+More
+*/
+ MSG_CHARACTER_MSG_CHARACTERTOTALSLOT = 0x7d4,
+/*20110831 to latest
+Premium Service
+VIP Service
+20130807 to 20130814
+(Character/Total Slot)
+(Characters/Total slots)
+*/
+ MSG_CHARACTER_MSG_PREMIUMSERVICE = 0x7d5,
+/*20110831 to latest
+Premium
+VIP
+20130807 to 20130814
+Premium Service
+VIP Service
+*/
+ MSG_CHARACTER_MSG_PREMIUM = 0x7d6,
+/*20110831 to latest
+Service
+20130807 to 20130814
+Premium
+VIP
+*/
+ MSG_CHARACTER_MSG_SERVICE = 0x7d7,
+/*20110831 to latest
+Billing Service
+VIP
+20130807 to 20130814
+Service
+*/
+ MSG_CHARACTER_MSG_BILLINGSERVICE = 0x7d8,
+/*20110831 to latest
+Billing
+VIP
+20130807 to 20130814
+Billing Service
+VIP
+*/
+ MSG_CHARACTER_MSG_BILLING = 0x7d9,
+/*20110831 to latest
+Command List
+20130807 to 20130814
+Billing
+VIP
+*/
+ MSG_MSG_COMMANDLIST = 0x7da,
+/*20110831 to latest
+LEVEL
+20130807 to 20130814
+Command List
+*/
+ MSG_SEEK_PARTY_LEVEL = 0x7db,
+/*20110831 to latest
+MAP
+20130807 to 20130814
+LEVEL
+*/
+ MSG_SEEK_PARTY_MAP = 0x7dc,
+/*20110831 to latest
+JOB
+20130807 to 20130814
+MAP
+*/
+ MSG_SEEK_PARTY_JOB = 0x7dd,
+#endif
+#if PACKETVER >= 20110906
+/*20110906 to latest
+Not Available
+20130807 to 20130814
+JOB
+*/
+ MSG_MSG_NOTAVAILABLE = 0x7de,
+#endif
+#if PACKETVER >= 20110920
+/*20110920 to 20110929
+[수호 천사의 보호] 스킬은 만렙일 경우, 경험치 100% 이상일 때는 사용할 수 없습니다.
+20111004 to latest
+[수호 천사의 보호] 만렙일 경우 사용할 수 없습니다.
+[Protection of Guardian Angel] You can't use it when you reach the highest level.
+20130807 to 20130814
+Not Available
+*/
+ MSG_MSG_SUPERNOVICE_CHOPOKGI_CAPPEDLEVEL = 0x7df,
+#endif
+#if PACKETVER >= 20110928
+/*20110928 to latest
+정말 이동하시겠습니까?
+Do you really want to move?
+20130807 to 20130814
+[수호 천사의 보호] 만렙일 경우 사용할 수 없습니다.
+[Protection of Guardian Angel] You can't use it when you reach the highest level.
+*/
+ MSG_CHANGE_CHARACTER_SLOT = 0x7e0,
+/*20110928 to latest
+캐릭터 슬롯 이동에 실패했습니다.
+Failed to move Char slot.
+20130807 to 20130814
+정말 이동하시겠습니까?
+Do you really want to move?
+*/
+ MSG_CHANGE_CHARACTER_SLOT_FAILED = 0x7e1,
+#endif
+#if PACKETVER >= 20111004
+/*20111004 to latest
+캐릭터 이름이 잘못 되었습니다.
+Character name is invalid.
+20130807 to 20130814
+캐릭터 슬롯 이동에 실패했습니다.
+Failed to move Char slot.
+*/
+ MSG_CHARACTERNAME_ERROR = 0x7e2,
+/*20111004 to latest
+퀘스트보기창
+Show Quest
+20130807 to 20130814
+캐릭터 이름이 잘못 되었습니다.
+Character name is invalid.
+*/
+ MSG_QUEST_DISPLAY_ONOFF = 0x7e3,
+#endif
+#if PACKETVER >= 20111017
+/*20111017 to 20111021
+정말 탭을 제거하시겠습니까?
+20111025 to 20111116
+청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000됩니다.
+20111122 to latest
+ 청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 만 16세 미만 고객님들의 게임 이용이 제한됩니다.
+Depending on the protection of youth, and 0:00 to 6:00 while under the age of 16 of your game use is limited.
+20130807 to 20130814
+퀘스트보기창
+Show Quest
+*/
+ MSG_SHUTDOWN_ALERT_MSG = 0x7e4,
+/*20111017 to 20111021
+더이상 탭을 제거할 수 없습니다.
+20111025 to latest
+청소년 보호법에 따라, 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000되며, 게임을 종료합니다.
+Depending on the protection of youth, 0:00 to 6:00 ^ff0000 under the age of 16 ^000000 limit your use of the game and the game ends.
+20130807 to 20130814
+ 청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 만 16세 미만 고객님들의 게임 이용이 제한됩니다.
+Depending on the protection of youth, and 0:00 to 6:00 while under the age of 16 of your game use is limited.
+*/
+ MSG_BAN_SHUTDOWN_TEENAGER = 0x7e5,
+/*20111017 to 20111021
+더이상 탭을 추가할 수 없습니다.
+20111025 to latest
+캐릭터 이름을 변경하기 위해서는 길드에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the guild.
+20130807 to 20130814
+청소년 보호법에 따라, 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000되며, 게임을 종료합니다.
+Depending on the protection of youth, 0:00 to 6:00 ^ff0000 under the age of 16 ^000000 limit your use of the game and the game ends.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_GUILD = 0x7e6,
+#endif
+#if PACKETVER >= 20111025
+/*20111025 to latest
+캐릭터 이름을 변경하기 위해서는 파티에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the party.
+20130807 to 20130814
+캐릭터 이름을 변경하기 위해서는 길드에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the guild.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_PARTY = 0x7e7,
+/*20111025 to latest
+알 수 없는 오류로 캐릭터 이름 변경이 실패 하였습니다.
+Character name change failed, due an unknown error.
+20130807 to 20130814
+캐릭터 이름을 변경하기 위해서는 파티에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the party.
+*/
+ MSG_FAILED_RENAME_UNKOWN = 0x7e8,
+#endif
+#if PACKETVER >= 20111101
+/*20111101 to latest
+이미 캐릭터 슬롯변경이 가능한 상태입니다.(%d)
+Ready to change character slot in.(%d)
+20130807 to 20130814
+알 수 없는 오류로 캐릭터 이름 변경이 실패 하였습니다.
+Character name change failed, due an unknown error.
+*/
+ MSG_CHARSLOT_CHANGE_DUPLICATE = 0x7e9,
+/*20111101 to latest
+이미 캐릭터 이름변경이 가능한 상태입니다.(%d)
+Ready to change character name in.(%d)
+20130807 to 20130814
+이미 캐릭터 슬롯변경이 가능한 상태입니다.(%d)
+Ready to change character slot in.(%d)
+*/
+ MSG_CHARNAME_CHANGE_DUPLICATE = 0x7ea,
+/*20111101 to latest
+변경하려는 이름의 길이가 최대크기를 초과하여 캐릭터 이름 변경이 실패 하였습니다.
+Length exceeds the maximum size of the character name you want to change.
+20130807 to 20130814
+이미 캐릭터 이름변경이 가능한 상태입니다.(%d)
+Ready to change character name in.(%d)
+*/
+ MSG_FAILED_RENAME_OVER_LENGTH = 0x7eb,
+/*20111101 to latest
+사용할 수 없는 단어가 포함되어 캐릭터 이름 변경이 실패 하였습니다.
+Name contains invalid characters. Character name change failed.
+20130807 to 20130814
+변경하려는 이름의 길이가 최대크기를 초과하여 캐릭터 이름 변경이 실패 하였습니다.
+Length exceeds the maximum size of the character name you want to change.
+*/
+ MSG_FAILED_RENAME_PREVENTNAM = 0x7ec,
+/*20111101 to latest
+이름 변경이 금지된 상태이므로 캐릭터 이름 변경이 실패 하였습니다.
+The name change is prohibited. Character name change failed.
+20130807 to 20130814
+사용할 수 없는 단어가 포함되어 캐릭터 이름 변경이 실패 하였습니다.
+Name contains invalid characters. Character name change failed.
+*/
+ MSG_FAILED_RENAME_FORBIDDEN = 0x7ed,
+#endif
+#if PACKETVER >= 20111108
+/*20111108 to latest
+완료
+Complete
+20130807 to 20130814
+이름 변경이 금지된 상태이므로 캐릭터 이름 변경이 실패 하였습니다.
+The name change is prohibited. Character name change failed.
+*/
+ MSG_COMPLETE_HUNTING_QUEST = 0x7ee,
+#endif
+#if PACKETVER >= 20111114
+/*20111114 to 20111116
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 %d분간 %d%% 증가합니다.
+20111122 to latest
+ %d분간 얻을 수 있는 경험치가 %d%% 증가합니다.
+During %d minutes your Exp will increase by %d%%.
+20130807 to 20130814
+완료
+Complete
+*/
+ MSG_PLUSEXP_VALUE = 0x7ef,
+/*20111114 to latest
+소환까지 %02d초남았습니다.
+%02d seconds left until summon.
+20130807 to 20130814
+ %d분간 얻을 수 있는 경험치가 %d%% 증가합니다.
+During %d minutes your Exp will increase by %d%%.
+*/
+ MSG_PARTY_RECALL_TIME = 0x7f0,
+/*20111114 to latest
+파티장이 당신을 %s (%s) 로 소환합니다.소환시 %d zeny가 소모됩니다.
+Your party leader summons you to %s (%s). Warp costs %d Zeny.
+20130807 to 20130814
+소환까지 %02d초남았습니다.
+%02d seconds left until summon.
+*/
+ MSG_PARTY_RECALL_INFO = 0x7f1,
+/*20111114 to latest
+소환대상
+Summon target
+20130807 to 20130814
+파티장이 당신을 %s (%s) 로 소환합니다.소환시 %d zeny가 소모됩니다.
+Your party leader summons you to %s (%s). Warp costs %d Zeny.
+*/
+ MSG_RECALL_TARGET = 0x7f2,
+/*20111114 to latest
+차단목록
+Block List
+20130807 to 20130814
+소환대상
+Summon target
+*/
+ MSG_PARTY_BLACKLIST = 0x7f3,
+/*20111114 to 20120209
+파티 광고를 등록하기 위해 1000제니가 소모됩니다.
+20120214 to latest
+파티 광고를 등록하기 위해 %d제니가 소모됩니다.
+%d Zeny will be spent for making party ad.
+20130807 to 20130814
+차단목록
+Block List
+*/
+ MSG_PARTY_CF_PAY = 0x7f4,
+/*20111114 to latest
+파티 광고를 하기 위한 제니가 부족합니다.
+Insufficient Zeny for making party ad.
+20130807 to 20130814
+파티 광고를 등록하기 위해 %d제니가 소모됩니다.
+%d Zeny will be spent for making party ad.
+*/
+ MSG_PARTY_CF_PAY_SHORTAGE_COST = 0x7f5,
+/*20111114 to latest
+)님 파티 가입승인
+) party: accept invitation
+20130807 to 20130814
+파티 광고를 하기 위한 제니가 부족합니다.
+Insufficient Zeny for making party ad.
+*/
+ MSG_PARTY_ADD_OK = 0x7f6,
+/*20111114 to latest
+)님 파티 가입거부
+) party: decline invitation
+20130807 to 20130814
+)님 파티 가입승인
+) party: accept invitation
+*/
+ MSG_PARTY_ADD_REFUSES = 0x7f7,
+/*20111114 to latest
+)님 장비창보기
+) party: show equipment window
+20130807 to 20130814
+)님 파티 가입거부
+) party: decline invitation
+*/
+ MSG_PARTY_ITEM_VIEW = 0x7f8,
+/*20111114 to latest
+한글18글자,영문36글자 입력가능
+Up to 36 english letters can be entered
+20130807 to 20130814
+)님 장비창보기
+) party: show equipment window
+*/
+ MSG_SEEK_PARTY_MEMO_HELP = 0x7f9,
+/*20111114 to latest
+지원하기
+Enter
+20130807 to 20130814
+한글18글자,영문36글자 입력가능
+Up to 36 english letters can be entered
+*/
+ MSG_PARTY_REQUEST = 0x7fa,
+/*20111114 to latest
+1:1대화하기
+1:1 Chat
+20130807 to 20130814
+지원하기
+Enter
+*/
+ MSG_DIRECT_CHAT = 0x7fb,
+/*20111114 to latest
+차단하기
+Block
+20130807 to 20130814
+1:1대화하기
+1:1 Chat
+*/
+ MSG_ADD_BLACKLIST = 0x7fc,
+#endif
+#if PACKETVER >= 20111122
+/*20111122 to latest
+파티장에게 소환되기 위한 제니가 부족합니다.
+Insufficient Zeny for recall.
+20130807 to 20130814
+차단하기
+Block
+*/
+ MSG_PARTY_RECRUIT_NOT_RECALL_PAY = 0x7fd,
+/*20111122 to latest
+메모란에 파티광고를 써주세요.
+Input your party ad.
+20130807 to 20130814
+파티장에게 소환되기 위한 제니가 부족합니다.
+Insufficient Zeny for recall.
+*/
+ MSG_PARTY_RECRUIT_MEMO_ERROR = 0x7fe,
+/*20111122 to latest
+파티장만이 파티광고를 등록할수있습니다.
+Only party leader can register party ad.
+20130807 to 20130814
+메모란에 파티광고를 써주세요.
+Input your party ad.
+*/
+ MSG_PARTY_RECRUIT_ERROR = 0x7ff,
+/*20111122 to latest
+이미 지원한 파티광고입니다.
+You have already accepted this ad.
+20130807 to 20130814
+파티장만이 파티광고를 등록할수있습니다.
+Only party leader can register party ad.
+*/
+ MSG_PARTY_REFUSE_ERROR = 0x800,
+/*20111122 to latest
+내용
+For
+20130807 to 20130814
+이미 지원한 파티광고입니다.
+You have already accepted this ad.
+*/
+ MSG_PARTY_RECRUIT_INFO = 0x801,
+/*20111122 to latest
+장비
+E
+20130807 to 20130814
+내용
+For
+*/
+ MSG_INVENTORY_TABNAME_1 = 0x802,
+/*20111122 to latest
+개인
+F
+20130807 to 20130814
+장비
+E
+*/
+ MSG_INVENTORY_TABNAME_3 = 0x803,
+/*20111122 to latest
+ 아이템 버리기 잠금
+ Drop Lock: On/Off
+20130807 to 20130814
+개인
+F
+*/
+ MSG_ITEM_DROP_LOCK = 0x804,
+/*20111122 to latest
+파티원 찾기 알람
+Party Alarm
+20130807 to 20130814
+ 아이템 버리기 잠금
+ Drop Lock: On/Off
+*/
+ MSG_PARTY_RECRUIT_ALRAM = 0x805,
+#endif
+#if PACKETVER >= 20111207
+/*20111207 to latest
+파티결성
+Create Party
+20130807 to 20130814
+파티원 찾기 알람
+Party Alarm
+*/
+ MSG_CREATE_PARTY = 0x806,
+/*20111207 to latest
+파티탈퇴
+Leave Party
+20130807 to 20130814
+파티결성
+Create Party
+*/
+ MSG_WITHDRAW_PARTY = 0x807,
+/*20111207 to latest
+파티초대
+Party Invitation
+20130807 to 20130814
+파티탈퇴
+Leave Party
+*/
+ MSG_INVITE_PARTY = 0x808,
+/*20111207 to latest
+파티 이름 등록
+Party Name:
+20130807 to 20130814
+파티초대
+Party Invitation
+*/
+ MSG_PUT_PARTY_NAME_IN = 0x809,
+/*20111207 to latest
+초대할 캐릭터 이름
+Player Name:
+20130807 to 20130814
+파티 이름 등록
+Party Name:
+*/
+ MSG_PUT_PLAYER_NAME_IN = 0x80a,
+/*20111207 to latest
+님께 파티가입 요청을 보냈습니다.
+ has recieved an invitation to join your party.
+20130807 to 20130814
+초대할 캐릭터 이름
+Player Name:
+*/
+ MSG_CHARACTER_PARTY_INVITATION_TO_JOIN = 0x80b,
+/*20111207 to latest
+님께서 파티가입을 거절했습니다.
+ rejected your party invitation.
+20130807 to 20130814
+님께 파티가입 요청을 보냈습니다.
+ has recieved an invitation to join your party.
+*/
+ MSG_CHARACTER_REJECT_PARTY_INVITATION = 0x80c,
+/*20111207 to latest
+님께서 파티가입을 수락했습니다.
+ accepted your party invitation.
+20130807 to 20130814
+님께서 파티가입을 거절했습니다.
+ rejected your party invitation.
+*/
+ MSG_CHARACTER_ACCEPT_PARTY_INVITATION = 0x80d,
+/*20111207 to latest
+이미 파티모집중입니다.
+Recruitment is already a party.
+20130807 to 20130814
+님께서 파티가입을 수락했습니다.
+ accepted your party invitation.
+*/
+ MSG_PARTY_RECRUIT_ERROR1 = 0x80e,
+/*20111207 to latest
+이전 검색과 같은 조건입니다.
+Same conditions such as the previous search.
+20130807 to 20130814
+이미 파티모집중입니다.
+Recruitment is already a party.
+*/
+ MSG_PARTY_RECRUIT_ERROR2 = 0x80f,
+/*20111207 to latest
+길드 탈퇴 후 사용 가능합니다.
+Guild after withdrwal.
+20130807 to 20130814
+이전 검색과 같은 조건입니다.
+Same conditions such as the previous search.
+*/
+ MSG_CHARNAME_CHANGE_FILED_GUILDMEMBER = 0x810,
+/*20111207 to latest
+파티 탈퇴 후 사용 가능합니다.
+Party after secession.
+20130807 to 20130814
+길드 탈퇴 후 사용 가능합니다.
+Guild after withdrwal.
+*/
+ MSG_CHARNAME_CHANGE_FILED_PARTYMEMBER = 0x811,
+/*20111207 to latest
+소환 유저가 소환이 안되는 맵에 있습니다.
+The player can not be summoned to this map.
+20130807 to 20130814
+파티 탈퇴 후 사용 가능합니다.
+Party after secession.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR1 = 0x812,
+/*20111207 to 20120229
+파티장이 있는 맵에서는 소환이 안됩니다.
+20120307 to latest
+현재 파티장이 있는 맵에서는 소환이 안됩니다.
+Party Leader is on a map that is restricted to summon players.
+20130807 to 20130814
+소환 유저가 소환이 안되는 맵에 있습니다.
+The player can not be summoned to this map.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR2 = 0x813,
+/*20111207 to latest
+소환거부되었습니다.
+Summon has been denied.
+20130807 to 20130814
+현재 파티장이 있는 맵에서는 소환이 안됩니다.
+Party Leader is on a map that is restricted to summon players.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR3 = 0x814,
+/*20111207 to latest
+소환을 할 수 없습니다.
+Can not be summoned.
+20130807 to 20130814
+소환거부되었습니다.
+Summon has been denied.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR4 = 0x815,
+/*20111207 to latest
+파티초대는 파티장만 가능합니다.
+Only the leader can invite.
+20130807 to 20130814
+소환을 할 수 없습니다.
+Can not be summoned.
+*/
+ MSG_YOU_ARE_NOT_PARTYMASTER = 0x816,
+#endif
+#if PACKETVER >= 20111213
+/*20111213 to latest
+검색할 아이템명 입력 :
+Search item:
+20130807 to 20130814
+파티초대는 파티장만 가능합니다.
+Only the leader can invite.
+*/
+ MSG_NC_ITEM_SEARCH = 0x817,
+/*20111213 to latest
+캐릭터명을 입력하셔야 합니다.
+You must enter a character name.
+20130807 to 20130814
+검색할 아이템명 입력 :
+Search item:
+*/
+ MSG_PLEASE_PUT_CHARACTER_NAME_IN = 0x818,
+/*20111213 to latest
+파티이름을 입력하셔야 합니다.
+You must enter the name of the party.
+20130807 to 20130814
+캐릭터명을 입력하셔야 합니다.
+You must enter a character name.
+*/
+ MSG_PLEASE_PUT_PARTY_NAME_IN = 0x819,
+#endif
+#if PACKETVER >= 20111220
+/*20111220 to latest
+길드 도우미
+Guild Creation Window
+20130807 to 20130814
+파티이름을 입력하셔야 합니다.
+You must enter the name of the party.
+*/
+ MSG_GUILD_HELPER = 0x81a,
+/*20111220 to latest
+가입되어 있는 길드가 없습니다.
+Join a guild or start your own!
+20130807 to 20130814
+길드 도우미
+Guild Creation Window
+*/
+ MSG_NO_GUILD_CURRENTLY_PARTICIPATED_IN = 0x81b,
+/*20111220 to latest
+길드 결성
+Create Guild
+20130807 to 20130814
+가입되어 있는 길드가 없습니다.
+Join a guild or start your own!
+*/
+ MSG_CREATE_GUILD = 0x81c,
+/*20111220 to latest
+생성할 길드 이름
+Guild Name
+20130807 to 20130814
+길드 결성
+Create Guild
+*/
+ MIS_PUT_GUILD_NAME_IN = 0x81d,
+/*20111220 to latest
+길드 결성 도움말
+Guild System
+20130807 to 20130814
+생성할 길드 이름
+Guild Name
+*/
+ MIS_GUILD_TIP = 0x81e,
+/*20111220 to latest
+길드 시스템이란
+What is the guild system
+20130807 to 20130814
+길드 결성 도움말
+Guild System
+*/
+ MIS_GUILD_SYSTEM = 0x81f,
+/*20111220 to latest
+길드이름을 입력하셔야 합니다.
+You must enter the name of your guild.
+20130807 to 20130814
+길드 시스템이란
+What is the guild system
+*/
+ MSG_PLEASE_PUT_GUILD_NAME_IN = 0x820,
+#endif
+#if PACKETVER >= 20111227
+/*20111227 to latest
+지원한 파티에서 거부당했습니다.
+Supported at the party was rejected.
+20130807 to 20130814
+길드이름을 입력하셔야 합니다.
+You must enter the name of your guild.
+*/
+ MSG_PARTY_RECRUIT_REFUSE_VOLUNTEER = 0x821,
+#endif
+#if PACKETVER >= 20120103
+/*20120103 to latest
+서비스 선택.
+Select Service:
+20130807 to 20130814
+지원한 파티에서 거부당했습니다.
+Supported at the party was rejected.
+*/
+ MSG_SERVICESELECT = 0x822,
+/*20120103 to latest
+탈출 가능한 지역.
+Possible escape area.
+20130807 to 20130814
+서비스 선택.
+Select Service:
+*/
+ MSG_SHOW_MAPNAMETITLE = 0x823,
+/*20120103 to latest
+Replay File List
+20130807 to 20130814
+탈출 가능한 지역.
+Possible escape area.
+*/
+ MSG_REPLAY_STR_REPLAYFILELIST = 0x824,
+/*20120103 to latest
+File info
+20130807 to 20130814
+Replay File List
+*/
+ MSG_REPLAY_STR_FILEINFO = 0x825,
+/*20120103 to latest
+File List
+20130807 to 20130814
+File info
+*/
+ MSG_REPLAY_STR_FILELIST = 0x826,
+#endif
+#if PACKETVER >= 20120117
+/*20120117 to latest
+%s 아이템은 거래가 불가능 합니다.
+%s Item deal not possible.
+20130807 to 20130814
+File List
+*/
+ MSG_NOT_MOVEABLE_TRADE = 0x827,
+#endif
+#if PACKETVER >= 20120207
+/*20120207 to latest
+길드해체
+Disband the Guild
+20130807 to 20130814
+%s 아이템은 거래가 불가능 합니다.
+%s Item deal not possible.
+*/
+ MSG_GUILD_DISBAND = 0x828,
+/*20120207 to latest
+해체할 길드 이름
+Enter Guild Name
+20130807 to 20130814
+길드해체
+Disband the Guild
+*/
+ MSG_PUT_DISBAND_GUILDNAME = 0x829,
+#endif
+#if PACKETVER >= 20120214
+/*20120214 to latest
+접속하지 않았거나 존재하지 않는 캐릭터입니다.
+The character is not online or does not exist.
+20130807 to 20130814
+해체할 길드 이름
+Enter Guild Name
+*/
+ MSG_JOINGUILD_NOTEXIST_USER = 0x82a,
+#endif
+#if PACKETVER >= 20120228
+/*20120228 to latest
+팔콘 호출에 실패하였습니다.
+Failed to call Falcon.
+20130807 to 20130814
+접속하지 않았거나 존재하지 않는 캐릭터입니다.
+The character is not online or does not exist.
+*/
+ MSG_FAILED_SET_EFFECT_BIRD = 0x82b,
+#endif
+#if PACKETVER >= 20120307
+/*20120307 to 20120320
+%d%% ( 프리미엄 %d%% + %s서버 %d%% )
+20120328 to latest
+%d%% ( 기본 100%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%%(default 100%%+ Premium%d%%+%s Server%d%%)
+20130807 to 20130814
+팔콘 호출에 실패하였습니다.
+Failed to call Falcon.
+*/
+ MSG_BASIC_EXP_MSG_BRZ = 0x82c,
+/*20120307 to latest
+해당 유저는 현재 공성전에 참가하고 있습니다.
+This user is currently participating in the siege.
+20130807 to 20130814
+%d%% ( 기본 100%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%%(default 100%%+ Premium%d%%+%s Server%d%%)
+*/
+ MSG_JOINGUILD_TARGET_USER_IN_SIEGEMAP = 0x82d,
+/*20120307 to latest
+동일한 맵에서만 파티장 변경이 가능합니다.
+It is only possible to change the party leader while on the same map.
+20130807 to 20130814
+해당 유저는 현재 공성전에 참가하고 있습니다.
+This user is currently participating in the siege.
+*/
+ MSG_PARTY_MASTER_CHANGE_SAME_MAP = 0x82e,
+/*20120307 to latest
+현재 지역에서는 파티장 변경이 불가능합니다.
+In the current region it is not possible to change the party.
+20130807 to 20130814
+동일한 맵에서만 파티장 변경이 가능합니다.
+It is only possible to change the party leader while on the same map.
+*/
+ MSG_CANNOT_PARTY_MASTER_CHANGE_IN_MAP = 0x82f,
+/*20120307 to latest
+그리폰 내리기
+Gryphon making
+20130807 to 20130814
+현재 지역에서는 파티장 변경이 불가능합니다.
+In the current region it is not possible to change the party.
+*/
+ MSG_ROYAL_CHIKENOFF = 0x830,
+/*20120307 to 20120307
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+20120314 to latest
+%d월 %d일 %d시 %d분 %d초
+Delete: %d/%d - %d:%d:%d
+20130807 to 20130814
+그리폰 내리기
+Gryphon making
+*/
+ MSG_TIME_TYPE3 = 0x831,
+#endif
+#if PACKETVER >= 20120314
+/*20120314 to latest
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+20130807 to 20130814
+%d월 %d일 %d시 %d분 %d초
+Delete: %d/%d - %d:%d:%d
+*/
+ MSG_JOINGUILD_REQ_USER_IN_SIEGEMAP = 0x832,
+/*20120314 to latest
+전장에 입장 대기를 신청하셨습니다.
+You are now in the battlefield queue.
+20130807 to 20130814
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+*/
+ MSG_BATTLEFIELD_MSG_REQUEST_JOINWAIT = 0x833,
+/*20120314 to latest
+인원이 가득 찼습니다.
+Queuing has finished.
+20130807 to 20130814
+전장에 입장 대기를 신청하셨습니다.
+You are now in the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_FULL = 0x834,
+/*20120314 to latest
+확인되지 않은 전장명입니다.
+Invalid name of the battlefield.
+20130807 to 20130814
+인원이 가득 찼습니다.
+Queuing has finished.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_NAME = 0x835,
+/*20120314 to latest
+확인되지 않은 신청타입입니다.
+Invalid type of application.
+20130807 to 20130814
+확인되지 않은 전장명입니다.
+Invalid name of the battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_TYPE = 0x836,
+/*20120314 to latest
+최대 인원을 초과하였습니다.
+People count exceeded.
+20130807 to 20130814
+확인되지 않은 신청타입입니다.
+Invalid type of application.
+*/
+ MSG_BATTLEFIELD_MSG_MAXOVER = 0x837,
+/*20120314 to latest
+입장 레벨이 맞지 않습니다.
+Your level doesn't fit this battlefield rules.
+20130807 to 20130814
+최대 인원을 초과하였습니다.
+People count exceeded.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_NOTLEVEL = 0x838,
+/*20120314 to latest
+중복 신청하셨습니다.
+Duplicate application.
+20130807 to 20130814
+입장 레벨이 맞지 않습니다.
+Your level doesn't fit this battlefield rules.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_OVERLAP = 0x839,
+/*20120314 to latest
+재접속후 다시 신청하여 주시기 바랍니다.
+After reconnecting, please re-apply.
+20130807 to 20130814
+중복 신청하셨습니다.
+Duplicate application.
+*/
+ MSG_BATTLEFIELD_MSG_RESTART = 0x83a,
+/*20120314 to latest
+직업이 맞지 않습니다.
+Your class can't participate in this battlefield.
+20130807 to 20130814
+재접속후 다시 신청하여 주시기 바랍니다.
+After reconnecting, please re-apply.
+*/
+ MSG_BATTLEFIELD_MSG_NOTJOB = 0x83b,
+/*20120314 to latest
+파티장이나 길드장만이 신청할 수 있습니다.
+Only party leader / guild master can apply.
+20130807 to 20130814
+직업이 맞지 않습니다.
+Your class can't participate in this battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_ONLYBOSS = 0x83c,
+/*20120314 to latest
+전장을 이용 중인 팀원이 있어 신청이 불가능 합니다.
+You can't apply while your team member is already on a battlefield.
+20130807 to 20130814
+파티장이나 길드장만이 신청할 수 있습니다.
+Only party leader / guild master can apply.
+*/
+ MSG_BATTLEFIELD_MSG_BUSY_PARTYMEMBER = 0x83d,
+/*20120314 to latest
+전장 입장 대기가 취소되었습니다.
+You have left the battlefield queue.
+20130807 to 20130814
+전장을 이용 중인 팀원이 있어 신청이 불가능 합니다.
+You can't apply while your team member is already on a battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOINWAIT = 0x83e,
+/*20120314 to latest
+잘못된 전장명 입니다.
+Wrong battlefield name.
+20130807 to 20130814
+전장 입장 대기가 취소되었습니다.
+You have left the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_WRONG_NAME = 0x83f,
+/*20120314 to latest
+전장 입장 대기 순위에 없습니다.
+You are not in the battlefield queue list
+20130807 to 20130814
+잘못된 전장명 입니다.
+Wrong battlefield name.
+*/
+ MSG_BATTLEFIELD_MSG_NOTRANK = 0x840,
+/*20120314 to latest
+선택하신 전장은 현재 이용하실 수 없으므로 대기가 취소됩니다.
+The selected arena is unavailable; your application has been cancelled
+20130807 to 20130814
+전장 입장 대기 순위에 없습니다.
+You are not in the battlefield queue list
+*/
+ MSG_BATTLEFIELD_MSG_FAIL_CHOICE = 0x841,
+/*20120314 to latest
+전장 입장을 취소하였습니다.
+You have left the queue
+20130807 to 20130814
+선택하신 전장은 현재 이용하실 수 없으므로 대기가 취소됩니다.
+The selected arena is unavailable; your application has been cancelled
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOIN = 0x842,
+/*20120314 to latest
+전장에 입장하시겠습니까?
+Are you sure you want to join a battleground?
+20130807 to 20130814
+전장 입장을 취소하였습니다.
+You have left the queue
+*/
+ MSG_BATTLEFIELD_MSG_DOYOU_JOIN = 0x843,
+/*20120314 to latest
+전장 입장 신청 시스템
+[Battlefield application rules]
+20130807 to 20130814
+전장에 입장하시겠습니까?
+Are you sure you want to join a battleground?
+*/
+ MSG_BATTLEFIELD_HELP1 = 0x844,
+/*20120314 to latest
+입장 신청 및 전장으로의 공간이동 불가 상황
+Application and position into the battlefield cannot be applied under this circumtances
+20130807 to 20130814
+전장 입장 신청 시스템
+[Battlefield application rules]
+*/
+ MSG_BATTLEFIELD_HELP2 = 0x845,
+/*20120314 to latest
+1. 여러 종류의 전장을 동시에 신청할 수 없습니다.
+1. Different types of battle can not be applied simultaneously.
+20130807 to 20130814
+입장 신청 및 전장으로의 공간이동 불가 상황
+Application and position into the battlefield cannot be applied under this circumtances
+*/
+ MSG_BATTLEFIELD_HELP3 = 0x846,
+/*20120314 to latest
+2. 개인 / 파티 / 길드 전장을 동시에 신청할 수 없습니다.
+2. Personal / party / guild battle can not be applied simultaneously.
+20130807 to 20130814
+1. 여러 종류의 전장을 동시에 신청할 수 없습니다.
+1. Different types of battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP4 = 0x847,
+/*20120314 to latest
+3. 파티 전장 신청은 파티장만 신청할 수 있으며,
+3. Parties can only be applied by their party leaders.
+20130807 to 20130814
+2. 개인 / 파티 / 길드 전장을 동시에 신청할 수 없습니다.
+2. Personal / party / guild battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP5 = 0x848,
+/*20120314 to latest
+오프라인중이거나 오프라인 된 파티원은 대기열에서 누락됩니다.
+Offline party members won't proceed to the queue.
+20130807 to 20130814
+3. 파티 전장 신청은 파티장만 신청할 수 있으며,
+3. Parties can only be applied by their party leaders.
+*/
+ MSG_BATTLEFIELD_HELP6 = 0x849,
+/*20120314 to latest
+4. 전장 신청은 전장 맵을 제외한 모든 곳에서 신청 가능하나,
+4. You can add request to enter the arena from any map except for those who don't allow teleport/warp.
+20130807 to 20130814
+오프라인중이거나 오프라인 된 파티원은 대기열에서 누락됩니다.
+Offline party members won't proceed to the queue.
+*/
+ MSG_BATTLEFIELD_HELP7 = 0x84a,
+/*20120314 to latest
+입장한 위치가 마을, 필드, 일반 던전이 아닐 경우 복귀 시 캐릭터 저장 좌표로 이동 됩니다.
+When the battle is finished your character will be returned to the current spot or (if it's not possible) to the save point.
+20130807 to 20130814
+4. 전장 신청은 전장 맵을 제외한 모든 곳에서 신청 가능하나,
+4. You can add request to enter the arena from any map except for those who don't allow teleport/warp.
+*/
+ MSG_BATTLEFIELD_HELP8 = 0x84b,
+/*20120314 to latest
+5. 전장의 보상 및 기타 서비스는 각 마을에 위치한 전장 모병관을 통해 전장 대기실에서 이용해 주십시오.
+5. You can view and choose rewards in the arena waiting room.
+20130807 to 20130814
+입장한 위치가 마을, 필드, 일반 던전이 아닐 경우 복귀 시 캐릭터 저장 좌표로 이동 됩니다.
+When the battle is finished your character will be returned to the current spot or (if it's not possible) to the save point.
+*/
+ MSG_BATTLEFIELD_HELP9 = 0x84c,
+/*20120314 to latest
+전장 입장 신청 도움말
+Request help battle position
+20130807 to 20130814
+5. 전장의 보상 및 기타 서비스는 각 마을에 위치한 전장 모병관을 통해 전장 대기실에서 이용해 주십시오.
+5. You can view and choose rewards in the arena waiting room.
+*/
+ MSG_BATTLEFIELD_HELP10 = 0x84d,
+/*20120314 to latest
+%s 전장이 시작됩니다.
+%s battle begins.
+20130807 to 20130814
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_START = 0x84e,
+/*20120314 to latest
+전장으로 이동하시겠습니까?
+Do you want to enter the arena?
+20130807 to 20130814
+%s 전장이 시작됩니다.
+%s battle begins.
+*/
+ MSG_BATTLEFIELD_DOYOU_MOVE = 0x84f,
+/*20120314 to latest
+[주의]
+[Note]
+20130807 to 20130814
+전장으로 이동하시겠습니까?
+Do you want to enter the arena?
+*/
+ MSG_BATTLEFIELD_WARNINGMSG1 = 0x850,
+/*20120314 to latest
+현재 위치가 마을, 필드 혹은 일반던전이
+When the battle is finished your character will
+20130807 to 20130814
+[주의]
+[Note]
+*/
+ MSG_BATTLEFIELD_WARNINGMSG2 = 0x851,
+/*20120314 to latest
+아닐 경우 전장 종료 후 저장된 위치로
+be returned to the current spot or (if it's not
+20130807 to 20130814
+현재 위치가 마을, 필드 혹은 일반던전이
+When the battle is finished your character will
+*/
+ MSG_BATTLEFIELD_WARNINGMSG3 = 0x852,
+/*20120314 to latest
+되돌아가게 됩니다.
+possible) to the save point.
+20130807 to 20130814
+아닐 경우 전장 종료 후 저장된 위치로
+be returned to the current spot or (if it's not
+*/
+ MSG_BATTLEFIELD_WARNINGMSG4 = 0x853,
+/*20120314 to latest
+다른 이의 요청 결과를 기다리고 있습니다.
+Waiting for the opponents.
+20130807 to 20130814
+되돌아가게 됩니다.
+possible) to the save point.
+*/
+ MSG_BATTLEFIELD_WAIT_PLAYER = 0x854,
+/*20120314 to latest
+전장 입장 요청
+Battlefield position request
+20130807 to 20130814
+다른 이의 요청 결과를 기다리고 있습니다.
+Waiting for the opponents.
+*/
+ MSG_BATTLEFIELD_REQUEST_JOIN = 0x855,
+/*20120314 to latest
+수락대기시간:%d초
+Accept standby time:%d seconds
+20130807 to 20130814
+전장 입장 요청
+Battlefield position request
+*/
+ MSG_BATTLEFIELD_WAITTIME_D = 0x856,
+/*20120314 to latest
+입장 대기 상태
+Standby position
+20130807 to 20130814
+수락대기시간:%d초
+Accept standby time:%d seconds
+*/
+ MSG_BATTLEFIELD_STATE_JOINWAIT = 0x857,
+/*20120314 to latest
+전장 명칭: %s
+Battlefield name:%s
+20130807 to 20130814
+입장 대기 상태
+Standby position
+*/
+ MSG_BATTLEFIELD_NAME_S = 0x858,
+/*20120314 to latest
+전장 필요 인원: %d
+Persons required:%d
+20130807 to 20130814
+전장 명칭: %s
+Battlefield name:%s
+*/
+ MSG_BATTLEFIELD_MEMBER_D = 0x859,
+/*20120314 to latest
+내 대기순번: %d
+Your position:%d
+20130807 to 20130814
+전장 필요 인원: %d
+Persons required:%d
+*/
+ MSG_BATTLEFIELD_MYRANK_D = 0x85a,
+/*20120314 to latest
+명칭 :
+Name:
+20130807 to 20130814
+내 대기순번: %d
+Your position:%d
+*/
+ MSG_BATTLEFIELD_DP_TITLE = 0x85b,
+/*20120314 to latest
+목표 :
+Goal:
+20130807 to 20130814
+명칭 :
+Name:
+*/
+ MSG_BATTLEFIELD_DP_AIM = 0x85c,
+/*20120314 to latest
+전장의 인원 구성 :
+Format:
+20130807 to 20130814
+목표 :
+Goal:
+*/
+ MSG_BATTLEFIELD_DP_MEMBER = 0x85d,
+/*20120314 to latest
+참여조건 :
+Level:
+20130807 to 20130814
+전장의 인원 구성 :
+Format:
+*/
+ MSG_BATTLEFIELD_DP_REQUIRED = 0x85e,
+/*20120314 to latest
+보상(승) :
+Win:
+20130807 to 20130814
+참여조건 :
+Level:
+*/
+ MSG_BATTLEFIELD_DP_WIN = 0x85f,
+/*20120314 to latest
+보상(무) :
+Draw:
+20130807 to 20130814
+보상(승) :
+Win:
+*/
+ MSG_BATTLEFIELD_DP_DRAW = 0x860,
+/*20120314 to latest
+보상(패) :
+Loss:
+20130807 to 20130814
+보상(무) :
+Draw:
+*/
+ MSG_BATTLEFIELD_DP_LOSS = 0x861,
+/*20120314 to latest
+전장을 개인으로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the individuals battle?
+20130807 to 20130814
+보상(패) :
+Loss:
+*/
+ MSG_BATTLEFIELD_DOYOU_SINGLE = 0x862,
+/*20120314 to latest
+전장을 파티로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the parties battle?
+20130807 to 20130814
+전장을 개인으로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the individuals battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_PALTY = 0x863,
+/*20120314 to latest
+전장을 길드로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the guilds battle?
+20130807 to 20130814
+전장을 파티로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the parties battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_GUILD = 0x864,
+/*20120314 to latest
+전장 목록
+Battleground List
+20130807 to 20130814
+전장을 길드로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the guilds battle?
+*/
+ MSG_BATTLEFIELD_LIST2 = 0x865,
+/*20120314 to latest
+%d VS %d
+20130807 to 20130814
+전장 목록
+Battleground List
+*/
+ MSG_BATTLEFIELD_D_VS_D = 0x866,
+/*20120314 to latest
+Base LV %d 이하
+LV %d and lower
+20130807 to 20130814
+%d VS %d
+*/
+ MSG_BATTLEFIELD_LEVELDOWN_D = 0x867,
+/*20120314 to latest
+Base LV %d 이상
+LV %d and higher
+20130807 to 20130814
+Base LV %d 이하
+LV %d and lower
+*/
+ MSG_BATTLEFIELD_LEVELUP_D = 0x868,
+/*20120314 to latest
+Base LV %d ~ %d
+LV %d ~ %d
+20130807 to 20130814
+Base LV %d 이상
+LV %d and higher
+*/
+ MSG_BATTLEFIELD_LEVEL_D_D = 0x869,
+/*20120314 to latest
+제한 없음
+No restrictions
+20130807 to 20130814
+Base LV %d ~ %d
+LV %d ~ %d
+*/
+ MSG_BATTLEFIELD_LIMITLESS = 0x86a,
+/*20120314 to latest
+[해당 맵에서는 신청하실 수 없습니다.]
+[You can't apply on this map.]
+20130807 to 20130814
+제한 없음
+No restrictions
+*/
+ MSG_BATTLEFIELD_MSG_NOT_JOINMAP = 0x86b,
+/*20120314 to latest
+[전장 재신청까지 약 1분의 대기시간을 필요로 합니다.]
+[You must wait about 1 minute to apply.]
+20130807 to 20130814
+[해당 맵에서는 신청하실 수 없습니다.]
+[You can't apply on this map.]
+*/
+ MSG_BATTLEFIELD_MSG_WAIT_1MM = 0x86c,
+/*20120314 to latest
+[파티에 먼저 가입하셔야 합니다.]
+[You must be in a party.]
+20130807 to 20130814
+[전장 재신청까지 약 1분의 대기시간을 필요로 합니다.]
+[You must wait about 1 minute to apply.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_PALTYJOIN = 0x86d,
+/*20120314 to latest
+[파티장만 신청 가능합니다.]
+[Only party leader can apply.]
+20130807 to 20130814
+[파티에 먼저 가입하셔야 합니다.]
+[You must be in a party.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_PALTYBOSS = 0x86e,
+/*20120314 to latest
+[접속되어있는 파티인원수가 많습니다.]
+[Too many party members online.]
+20130807 to 20130814
+[파티장만 신청 가능합니다.]
+[Only party leader can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_PARTYMEMBER = 0x86f,
+/*20120314 to latest
+[길드에 먼저 가입하셔야 합니다.]
+[You must be in a guild.]
+20130807 to 20130814
+[접속되어있는 파티인원수가 많습니다.]
+[Too many party members online.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_GUILDJOIN = 0x870,
+/*20120314 to latest
+[길드장만 신청 가능합니다.]
+[Only guild master can apply.]
+20130807 to 20130814
+[길드에 먼저 가입하셔야 합니다.]
+[You must be in a guild.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_GUILDBOSS = 0x871,
+/*20120314 to latest
+[접속되어있는 길드인원수가 많습니다.]
+[Too many guild members online.]
+20130807 to 20130814
+[길드장만 신청 가능합니다.]
+[Only guild master can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_GUILDMEMBER = 0x872,
+/*20120314 to 20120314
+아이템 합치기
+20120320 to latest
+이동예약
+Moving Book
+20130807 to 20130814
+[접속되어있는 길드인원수가 많습니다.]
+[Too many guild members online.]
+*/
+ MSG_RESERVE_CHANGE_CHARACTER_SLOT = 0x873,
+/*20120314 to 20120314
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+20120320 to latest
+이동
+Move
+20130807 to 20130814
+이동예약
+Moving Book
+*/
+ MSG_CHARACTER_SLOT_CHANGE = 0x874,
+/*20120314 to 20120314
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+20120320 to latest
+이름변경
+Rename
+20130807 to 20130814
+이동
+Move
+*/
+ MSG_CHANGE_CHARACTER_NAME = 0x875,
+/*20120314 to 20120314
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+20120320 to latest
+Make Character
+Create Character
+20130807 to 20130814
+이름변경
+Rename
+*/
+ MSG_MSG_MAKECHARCTER = 0x876,
+/*20120314 to 20120314
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+20120320 to latest
+http://ro.game.gnjoy.com/
+20130807 to 20130814
+Make Character
+Create Character
+*/
+ MSG_UAE_URL = 0x877,
+#endif
+#if PACKETVER >= 20120320
+/*20120320 to latest
+(%s) Server
+20130807 to 20130814
+http://ro.game.gnjoy.com/
+*/
+ MSG_UAE_SERVERSTR = 0x878,
+/*20120320 to 20120328
+아이템 합치기
+20120404 to latest
+아이템 병합(모두선택 Ctrl+클릭)
+Item Merge
+20130807 to 20130814
+(%s) Server
+*/
+ MSG_MERGE_ITEM = 0x879,
+/*20120320 to latest
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+20130807 to 20130814
+아이템 병합(모두선택 Ctrl+클릭)
+Item Merge
+*/
+ MSG_SELECT_ITEM_TO_MERGE = 0x87a,
+/*20120320 to latest
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+20130807 to 20130814
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+*/
+ MSG_MERGE_ITEM_SUCCESS = 0x87b,
+/*20120320 to latest
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+20130807 to 20130814
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_MERGE = 0x87c,
+/*20120320 to latest
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+20130807 to 20130814
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+*/
+ MSG_MERGE_ITEM_FAILED_MAX_COUNT = 0x87d,
+#endif
+#if PACKETVER >= 20120328
+/*20120328 to latest
+좌로 회전
+Rotate left
+20130807 to 20130814
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+*/
+ MSG_CHARACTER_LEFT_ROLL = 0x87e,
+/*20120328 to latest
+우로 회전
+Rotate right
+20130807 to 20130814
+좌로 회전
+Rotate left
+*/
+ MSG_CHARACTER_RIGHT_ROLL = 0x87f,
+/*20120328 to latest
+(%s)님의 이전서버 정보보기
+(%s) to view the old server information
+20130807 to 20130814
+우로 회전
+Rotate right
+*/
+ MSG_VIEW_BEFORE_WORLDINFO = 0x880,
+/*20120328 to latest
+기존 서버 정보
+Existing server information
+20130807 to 20130814
+(%s)님의 이전서버 정보보기
+(%s) to view the old server information
+*/
+ MSG_VIEW_BEFORE_WORLDINFO_TITLE = 0x881,
+/*20120328 to latest
+^ff0000기존 서버 : ^0000ff
+^ff0000Existing server: ^0000ff
+20130807 to 20130814
+기존 서버 정보
+Existing server information
+*/
+ MSG_VIEW_BEFORE_SERVERINFO = 0x882,
+/*20120328 to latest
+^ff0000기존 캐릭명 : ^0000ff
+^ff0000Existing character: ^0000ff
+20130807 to 20130814
+^ff0000기존 서버 : ^0000ff
+^ff0000Existing server: ^0000ff
+*/
+ MSG_VIEW_BEFORE_CHARNAME = 0x883,
+/*20120328 to latest
+공격한 몬스터의 HP가 표시됩니다.
+Show monster HP bar when attacking.
+20130807 to 20130814
+^ff0000기존 캐릭명 : ^0000ff
+^ff0000Existing character: ^0000ff
+*/
+ MSG_MONSTER_HP_ON = 0x884,
+/*20120328 to 20120328
+공격한 몬스터의 HP가 표시되지 않습니다..
+20120404 to latest
+공격한 몬스터의 HP가 표시되지 않습니다.
+Hide monster HP bar when attacking.
+20130807 to 20130814
+공격한 몬스터의 HP가 표시됩니다.
+Show monster HP bar when attacking.
+*/
+ MSG_MONSTER_HP_OFF = 0x885,
+#endif
+#if PACKETVER >= 20120404
+/*20120404 to latest
+병합 가능한 아이템이 존재하지 않습니다
+Merge does not exist as an item
+20130807 to 20130814
+공격한 몬스터의 HP가 표시되지 않습니다.
+Hide monster HP bar when attacking.
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_EXIST = 0x886,
+/*20120404 to latest
+병합 가능한 아이템이 존재하지 않습니다.
+Merge items available does not exist.
+20130807 to 20130814
+병합 가능한 아이템이 존재하지 않습니다
+Merge does not exist as an item
+*/
+ MSG_NOT_EXIST_MERGE_ITEM = 0x887,
+/*20120404 to latest
+진행중
+Act
+20130807 to 20130814
+병합 가능한 아이템이 존재하지 않습니다.
+Merge items available does not exist.
+*/
+ MSG_QUESTUI_TAB_PROCESS = 0x888,
+/*20120404 to latest
+보류중
+Pen
+20130807 to 20130814
+진행중
+Act
+*/
+ MSG_QUESTUI_TAB_HOLD = 0x889,
+/*20120404 to latest
+추천
+Rec
+20130807 to 20130814
+보류중
+Pen
+*/
+ MSG_QUESTUI_TAB_BEST = 0x88a,
+/*20120404 to latest
+에피소드
+Episode
+20130807 to 20130814
+추천
+Rec
+*/
+ MSG_QUESTUI_TAB_EPISODE = 0x88b,
+/*20120404 to latest
+로컬
+Loc
+20130807 to 20130814
+에피소드
+Episode
+*/
+ MSG_QUESTUI_TAB_LOCAL = 0x88c,
+/*20120404 to latest
+이벤트
+Evt
+20130807 to 20130814
+로컬
+Loc
+*/
+ MSG_QUESTUI_TAB_EVENT = 0x88d,
+/*20120404 to latest
+신규
+New
+20130807 to 20130814
+이벤트
+Evt
+*/
+ MSG_QUESTUI_TAB_NEW = 0x88e,
+/*20120404 to latest
+사냥몬스터
+Monsters to kill
+20130807 to 20130814
+신규
+New
+*/
+ MSG_QUESTUI_HUNTMONSTER = 0x88f,
+/*20120404 to latest
+보상아이템
+Rewards
+20130807 to 20130814
+사냥몬스터
+Monsters to kill
+*/
+ MSG_QUESTUI_REWARDITEM = 0x890,
+/*20120404 to latest
+필요아이템
+Required Items
+20130807 to 20130814
+보상아이템
+Rewards
+*/
+ MSG_QUESTUI_NEEDITEM = 0x891,
+/*20120404 to latest
+제한시간
+Time Limit
+20130807 to 20130814
+필요아이템
+Required Items
+*/
+ MSG_QUESTUI_TIMELIMIT = 0x892,
+/*20120404 to latest
+마감시간
+Deadline
+20130807 to 20130814
+제한시간
+Time Limit
+*/
+ MSG_QUESTUI_CLOSINGTIME = 0x893,
+#endif
+#if PACKETVER >= 20120417
+/*20120417 to latest
+검색
+Search
+20130807 to 20130814
+마감시간
+Deadline
+*/
+ MSG_NAVIGATION_SEARCH = 0x894,
+/*20120417 to latest
+목표로 안내
+Navigation
+20130807 to 20130814
+검색
+Search
+*/
+ MSG_NAVIGATION_TARGETGO = 0x895,
+/*20120417 to latest
+길 정보
+Back to Navigation
+20130807 to 20130814
+목표로 안내
+Navigation
+*/
+ MSG_NAVIGATION_ROUTEINFO = 0x896,
+/*20120417 to latest
+검색 정보
+Find Information
+20130807 to 20130814
+길 정보
+Back to Navigation
+*/
+ MSG_NAVIGATION_SEARCHINFO = 0x897,
+/*20120417 to latest
+보기 모드 변경
+Toggle Minimap
+20130807 to 20130814
+검색 정보
+Find Information
+*/
+ MSG_NAVIGATION_VIEWCHANGE = 0x898,
+/*20120417 to 20130109
+안내 지시 색상 변경
+20130115 to latest
+외부 길정보 파일 읽기
+Read Information from External File
+20130807 to 20130814
+보기 모드 변경
+Toggle Minimap
+*/
+ MSG_NAVIGATION_LIGHTCHANGE = 0x899,
+/*20120417 to latest
+종료
+Exit
+20130807 to 20130814
+외부 길정보 파일 읽기
+Read Information from External File
+*/
+ MSG_NAVIGATION_END = 0x89a,
+/*20120417 to latest
+기본 UI로 변경
+Change the Default UI
+20130807 to 20130814
+종료
+Exit
+*/
+ MSG_NAVIGATION_BASE = 0x89b,
+/*20120417 to latest
+간편 UI로 변경
+Change to Default UI
+20130807 to 20130814
+기본 UI로 변경
+Change the Default UI
+*/
+ MSG_NAVIGATION_MINI = 0x89c,
+/*20120417 to latest
+도움말
+Help
+20130807 to 20130814
+간편 UI로 변경
+Change to Default UI
+*/
+ MSG_NAVIGATION_HELP = 0x89d,
+/*20120417 to latest
+ALL
+20130807 to 20130814
+도움말
+Help
+*/
+ MSG_NAVIGATION_ALL = 0x89e,
+/*20120417 to latest
+Map
+20130807 to 20130814
+ALL
+*/
+ MSG_NAVIGATION_MAP = 0x89f,
+/*20120417 to latest
+Npc
+20130807 to 20130814
+Map
+*/
+ MSG_NAVIGATION_NPC = 0x8a0,
+/*20120417 to latest
+Mob
+20130807 to 20130814
+Npc
+*/
+ MSG_NAVIGATION_MOB = 0x8a1,
+/*20120417 to latest
+검색 단어 설정 (Ex: 단어 단어 ...
+Enter search string... (Ex: word word ...)
+20130807 to 20130814
+Mob
+*/
+ MSG_NAVIGATION_SETSTRING = 0x8a2,
+/*20120417 to latest
+Scroll
+20130807 to 20130814
+검색 단어 설정 (Ex: 단어 단어 ...
+Enter search string... (Ex: word word ...)
+*/
+ MSG_NAVIGATION_SCROLL = 0x8a3,
+/*20120417 to latest
+던전이동 스크롤 사용 적용
+Use Scroll?
+20130807 to 20130814
+Scroll
+*/
+ MSG_NAVIGATION_USESCROLL = 0x8a4,
+/*20120417 to latest
+Service
+20130807 to 20130814
+던전이동 스크롤 사용 적용
+Use Scroll?
+*/
+ MSG_NAVIGATION_SERVICE = 0x8a5,
+/*20120417 to latest
+위치 이동 서비스 허용
+Use Kafra Warp?
+20130807 to 20130814
+Service
+*/
+ MSG_NAVIGATION_USESERVICE = 0x8a6,
+/*20120417 to latest
+Plane
+20130807 to 20130814
+위치 이동 서비스 허용
+Use Kafra Warp?
+*/
+ MSG_NAVIGATION_PLANE = 0x8a7,
+/*20120417 to latest
+비공정 이동 적용
+Use Airship?
+20130807 to 20130814
+Plane
+*/
+ MSG_NAVIGATION_USEPLANE = 0x8a8,
+/*20120417 to latest
+>> 목표 정보를 읽지 못함!
+>> Failed to read the target information.
+20130807 to 20130814
+비공정 이동 적용
+Use Airship?
+*/
+ MSG_NAVIGATION_TARGETUNKNOWN = 0x8a9,
+/*20120417 to latest
+<< 안내중 >>
+>> Destination <<
+20130807 to 20130814
+>> 목표 정보를 읽지 못함!
+>> Failed to read the target information.
+*/
+ MSG_NAVIGATION_GOING = 0x8aa,
+/*20120417 to latest
+<< 검색중... >>
+<< Goal >>
+20130807 to 20130814
+<< 안내중 >>
+>> Destination <<
+*/
+ MSG_NAVIGATION_SEARCHING = 0x8ab,
+/*20120417 to latest
+-----------
+20130807 to 20130814
+<< 검색중... >>
+<< Goal >>
+*/
+ MSG_NAVIGATION_UN = 0x8ac,
+/*20120417 to latest
+Navigation
+20130807 to 20130814
+-----------
+*/
+ MSG_NAVIGATION_NAVI = 0x8ad,
+/*20120417 to latest
+== 검색 결과(%d)==
+= Found (%d) ==
+20130807 to 20130814
+Navigation
+*/
+ MSG_NAVIGATION_SEARCHRESULT_D = 0x8ae,
+/*20120417 to latest
+Npc)%s:%s
+20130807 to 20130814
+== 검색 결과(%d)==
+= Found (%d) ==
+*/
+ MSG_NAVIGATION_NPC_S_S = 0x8af,
+/*20120417 to latest
+Mob)%s:%s
+20130807 to 20130814
+Npc)%s:%s
+*/
+ MSG_NAVIGATION_MOB_S_S = 0x8b0,
+/*20120417 to latest
+Map)%s
+20130807 to 20130814
+Mob)%s:%s
+*/
+ MSG_NAVIGATION_MAP_S = 0x8b1,
+/*20120417 to latest
+======== 결과 정보 ==========
+======== Results ==========
+20130807 to 20130814
+Map)%s
+*/
+ MSG_NAVIGATION_RESULTINFO = 0x8b2,
+/*20120417 to latest
+거리 : %d Sell %d WarpMove
+Dist %d Cell %d WarpMove
+20130807 to 20130814
+======== 결과 정보 ==========
+======== Results ==========
+*/
+ MSG_NAVIGATION_LENGTH = 0x8b3,
+/*20120417 to latest
+목표맵: %s(%s)
+Coords %s(%s)
+20130807 to 20130814
+거리 : %d Sell %d WarpMove
+Dist %d Cell %d WarpMove
+*/
+ MSG_NAVIGATION_TARGETMAP_S_S = 0x8b4,
+/*20120417 to latest
+목표 : %s(%d, %d)
+Goal:%s (%d,%d)
+20130807 to 20130814
+목표맵: %s(%s)
+Coords %s(%s)
+*/
+ MSG_NAVIGATION_TARGET_S_D_D = 0x8b5,
+/*20120417 to latest
+보스
+Boss
+20130807 to 20130814
+목표 : %s(%d, %d)
+Goal:%s (%d,%d)
+*/
+ MSG_NAVIGATION_BOSS = 0x8b6,
+/*20120417 to latest
+일반
+General
+20130807 to 20130814
+보스
+Boss
+*/
+ MSG_NAVIGATION_NORMAL = 0x8b7,
+/*20120417 to latest
+목표 : %s(%s)
+Goal:
+20130807 to 20130814
+일반
+General
+*/
+ MSG_NAVIGATION_TARGET_S_S = 0x8b8,
+/*20120417 to latest
+목표: (%d, %d)
+Goal: (%d, %d)
+20130807 to 20130814
+목표 : %s(%s)
+Goal:
+*/
+ MSG_NAVIGATION_TARGET_D_D = 0x8b9,
+/*20120417 to latest
+======= 길 안내 정보 =======
+======= Guidance =======
+20130807 to 20130814
+목표: (%d, %d)
+Goal: (%d, %d)
+*/
+ MSG_NAVIGATION_GOINFO = 0x8ba,
+/*20120417 to latest
+%2d) Item:%s => %s 사용!
+%2d) Item:%s => %s Use!
+20130807 to 20130814
+======= 길 안내 정보 =======
+======= Guidance =======
+*/
+ MSG_NAVIGATION_ITEM_S_S = 0x8bb,
+/*20120417 to latest
+%2d) %s(%d,%d)=>(%d,%d)
+20130807 to 20130814
+%2d) Item:%s => %s 사용!
+%2d) Item:%s => %s Use!
+*/
+ MSG_NAVIGATION_D_S_D_D_D_D = 0x8bc,
+/*20120417 to latest
+E%2d) %s(%d,%d)=>(%d,%d)
+20130807 to 20130814
+%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_E_D_S_D_D_D_D = 0x8bd,
+/*20120417 to latest
+E%2d) %s
+20130807 to 20130814
+E%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_E_D_S = 0x8be,
+/*20120417 to latest
+안내중 입니다! 종료 하시겠습니까?
+Do you want to cancel navigation?
+20130807 to 20130814
+E%2d) %s
+*/
+ MSG_NAVIGATION_GOEXIT = 0x8bf,
+/*20120417 to latest
+내비게이션 도움말
+How to Use Navigation
+20130807 to 20130814
+안내중 입니다! 종료 하시겠습니까?
+Do you want to cancel navigation?
+*/
+ MSG_NAVIGATION_HELPTITLE = 0x8c0,
+/*20120417 to latest
+------------------- 명령어 --------------------
+------------------- Instruction --------------------
+20130807 to 20130814
+내비게이션 도움말
+How to Use Navigation
+*/
+ MSG_NAVIGATION_HELP1 = 0x8c1,
+/*20120417 to latest
+1. /navigation /navi
+1) /Navigation or /navi
+20130807 to 20130814
+------------------- 명령어 --------------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP2 = 0x8c2,
+/*20120417 to 20120417
+ ex)/navi prontera 100 100 -> 맵이름, 100, 100
+20120424 to latest
+ ex)/navi prontera 100/100 -> 맵이름, 100/100
+ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+20130807 to 20130814
+1. /navigation /navi
+1) /Navigation or /navi
+*/
+ MSG_NAVIGATION_HELP3 = 0x8c3,
+/*20120417 to 20120417
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+20120424 to latest
+ 기본 명령어는 제니, 비공정 검색을 기본으로 합니다.
+2) /Navigation2 or /navi2
+20130807 to 20130814
+ ex)/navi prontera 100/100 -> 맵이름, 100/100
+ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP4 = 0x8c4,
+/*20120417 to 20120417
+ ex) /navi2 prontera 100090 111
+20120424 to latest
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+20130807 to 20130814
+ 기본 명령어는 제니, 비공정 검색을 기본으로 합니다.
+2) /Navigation2 or /navi2
+*/
+ MSG_NAVIGATION_HELP5 = 0x8c5,
+/*20120417 to 20120417
+-> 맵이름, 위치(100 90), scrool/ zeny/ plane (1:사용함 0: 사용안함)
+20120424 to latest
+ ex) /navi2 prontera 100/100 1/1/1
+-> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+20130807 to 20130814
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+*/
+ MSG_NAVIGATION_HELP6 = 0x8c6,
+/*20120417 to 20120417
+※ /navi2 의 경우 반드시 위치 좌표를 붙여서 3 자리로 적어야 한다
+20120424 to latest
+-> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+20130807 to 20130814
+ ex) /navi2 prontera 100/100 1/1/1
+-> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP7 = 0x8c7,
+/*20120417 to 20120417
+3. /$$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+20120424 to latest
+3. $$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+3) /$$ Output all the items (Can take a while...)
+20130807 to 20130814
+-> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP8 = 0x8c8,
+/*20120417 to 20120417
+4. /$$lv30 해당 레벨의 몬스터 출력
+20120424 to latest
+4. $$lv30 해당 레벨의 몬스터 출력
+4) /$$ Lv30 monsters are placed in the output
+20130807 to 20130814
+3. $$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+3) /$$ Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP9 = 0x8c9,
+/*20120417 to 20120417
+5. /$$lv20~30 해당 레벨 범위의 몬스터 출력
+20120424 to latest
+5. $$lv20~30 해당 레벨 범위의 몬스터 출력
+5) /$$ Lv20~30 monsters in that level range are placed in the output
+20130807 to 20130814
+4. $$lv30 해당 레벨의 몬스터 출력
+4) /$$ Lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP10 = 0x8ca,
+/*20120417 to latest
+------------------- 설명 --------------------
+------------------- Description --------------------
+20130807 to 20130814
+5. $$lv20~30 해당 레벨 범위의 몬스터 출력
+5) /$$ Lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_NAVIGATION_HELP11 = 0x8cb,
+/*20120417 to latest
+1.검색 종류는 전체, 맵, Npc, 몬스터 으로 분류 된다.
+1) One can search for monsters, npcs, maps, or all at once
+20130807 to 20130814
+------------------- 설명 --------------------
+------------------- Description --------------------
+*/
+ MSG_NAVIGATION_HELP12 = 0x8cc,
+/*20120417 to latest
+2.명령어로 검색한다. 규칙은 검색 하려는 문자열이 모두 포함된 정보를 출력 한다.
+2) You can press the search button to get results. It will out put the results depending on what rule you choose
+20130807 to 20130814
+1.검색 종류는 전체, 맵, Npc, 몬스터 으로 분류 된다.
+1) One can search for monsters, npcs, maps, or all at once
+*/
+ MSG_NAVIGATION_HELP13 = 0x8cd,
+/*20120417 to latest
+ ex) 프론 카프 -> 검색 결과 프론테라의 카프라를 모두 출력 한다.
+ex) Drop down box -> Select "Npc", then type in the box "Kafra". Results will now be displayed
+20130807 to 20130814
+2.명령어로 검색한다. 규칙은 검색 하려는 문자열이 모두 포함된 정보를 출력 한다.
+2) You can press the search button to get results. It will out put the results depending on what rule you choose
+*/
+ MSG_NAVIGATION_HELP14 = 0x8ce,
+/*20120417 to latest
+3.리스트에서 항목을 선택하면 정보가 출력된다.
+3) When you select an item from a list, information about it are displayed.
+20130807 to 20130814
+ ex) 프론 카프 -> 검색 결과 프론테라의 카프라를 모두 출력 한다.
+ex) Drop down box -> Select "Npc", then type in the box "Kafra". Results will now be displayed
+*/
+ MSG_NAVIGATION_HELP15 = 0x8cf,
+/*20120417 to latest
+ 출력 되고 있는 목표가 있을때 안내 버튼을 클릭하면 해당 목표로 길을 안내 한다.
+-> When button is clicked, it will point you towards your destination if available
+20130807 to 20130814
+3.리스트에서 항목을 선택하면 정보가 출력된다.
+3) When you select an item from a list, information about it are displayed.
+*/
+ MSG_NAVIGATION_HELP16 = 0x8d0,
+/*20120417 to latest
+4.scrool/ zeny/ plane 상자를 원하는 만큼 체크하여 더 빠른 경로를 안내 받을 수 있다.
+4) Scroll | Zeny | Plane options can be checked to find a faster route
+20130807 to 20130814
+ 출력 되고 있는 목표가 있을때 안내 버튼을 클릭하면 해당 목표로 길을 안내 한다.
+-> When button is clicked, it will point you towards your destination if available
+*/
+ MSG_NAVIGATION_HELP17 = 0x8d1,
+/*20120417 to latest
+5.안내 버튼이 눌러지면 결과 리스트창은 길안내 리스트 장으로 변경 된다.
+5) Guide button is pressed, the result list window displays where routes can change direction
+20130807 to 20130814
+4.scrool/ zeny/ plane 상자를 원하는 만큼 체크하여 더 빠른 경로를 안내 받을 수 있다.
+4) Scroll | Zeny | Plane options can be checked to find a faster route
+*/
+ MSG_NAVIGATION_HELP18 = 0x8d2,
+/*20120417 to latest
+6.검색 리스트창 하단 버튼을 이용하여
+6) Using the button below, search results can be found
+20130807 to 20130814
+5.안내 버튼이 눌러지면 결과 리스트창은 길안내 리스트 장으로 변경 된다.
+5) Guide button is pressed, the result list window displays where routes can change direction
+*/
+ MSG_NAVIGATION_HELP19 = 0x8d3,
+/*20120417 to latest
+ [결과 리스트 창] <-> [길 안내 정보 창] 으로 보기 모드 변경 가능하다.
+-> [Results List Window] <-> [View Modes can be switched]
+20130807 to 20130814
+6.검색 리스트창 하단 버튼을 이용하여
+6) Using the button below, search results can be found
+*/
+ MSG_NAVIGATION_HELP20 = 0x8d4,
+/*20120417 to latest
+Level:%d (보스)
+Level:%d (Boss)
+20130807 to 20130814
+ [결과 리스트 창] <-> [길 안내 정보 창] 으로 보기 모드 변경 가능하다.
+-> [Results List Window] <-> [View Modes can be switched]
+*/
+ MSG_NAVIGATION_LEVEL_D_BOSS = 0x8d5,
+/*20120417 to latest
+Level:%d (일반)
+Level:%d (Mob)
+20130807 to 20130814
+Level:%d (보스)
+Level:%d (Boss)
+*/
+ MSG_NAVIGATION_LEVEL_D_NORMAL = 0x8d6,
+/*20120417 to latest
+수속성%d
+Water %d
+20130807 to 20130814
+Level:%d (일반)
+Level:%d (Mob)
+*/
+ MSG_NAVIGATION_PROPERTY1 = 0x8d7,
+/*20120417 to latest
+지속성%d
+Earth %d
+20130807 to 20130814
+수속성%d
+Water %d
+*/
+ MSG_NAVIGATION_PROPERTY2 = 0x8d8,
+/*20120417 to latest
+화속성%d
+Fire %d
+20130807 to 20130814
+지속성%d
+Earth %d
+*/
+ MSG_NAVIGATION_PROPERTY3 = 0x8d9,
+/*20120417 to latest
+풍속성%d
+Wind %d
+20130807 to 20130814
+화속성%d
+Fire %d
+*/
+ MSG_NAVIGATION_PROPERTY4 = 0x8da,
+/*20120417 to latest
+독속성%d
+Poison %d
+20130807 to 20130814
+풍속성%d
+Wind %d
+*/
+ MSG_NAVIGATION_PROPERTY5 = 0x8db,
+/*20120417 to latest
+성속성%d
+Holy %d
+20130807 to 20130814
+독속성%d
+Poison %d
+*/
+ MSG_NAVIGATION_PROPERTY6 = 0x8dc,
+/*20120417 to latest
+암속성%d
+Shadow %d
+20130807 to 20130814
+성속성%d
+Holy %d
+*/
+ MSG_NAVIGATION_PROPERTY7 = 0x8dd,
+/*20120417 to latest
+염속성%d
+Ghost %d
+20130807 to 20130814
+암속성%d
+Shadow %d
+*/
+ MSG_NAVIGATION_PROPERTY8 = 0x8de,
+/*20120417 to latest
+언데드%d
+Undead %d
+20130807 to 20130814
+염속성%d
+Ghost %d
+*/
+ MSG_NAVIGATION_PROPERTY9 = 0x8df,
+/*20120417 to latest
+무속성%d
+Neutral %d
+20130807 to 20130814
+언데드%d
+Undead %d
+*/
+ MSG_NAVIGATION_PROPERTY0 = 0x8e0,
+/*20120417 to latest
+중형
+Medium
+20130807 to 20130814
+무속성%d
+Neutral %d
+*/
+ MSG_NAVIGATION_SCALE1 = 0x8e1,
+/*20120417 to latest
+대형
+Large
+20130807 to 20130814
+중형
+Medium
+*/
+ MSG_NAVIGATION_SCALE2 = 0x8e2,
+/*20120417 to latest
+소형
+Small
+20130807 to 20130814
+대형
+Large
+*/
+ MSG_NAVIGATION_SCALE0 = 0x8e3,
+/*20120417 to latest
+불사형
+Undead
+20130807 to 20130814
+소형
+Small
+*/
+ MSG_NAVIGATION_RACE1 = 0x8e4,
+/*20120417 to latest
+동물형
+Brute
+20130807 to 20130814
+불사형
+Undead
+*/
+ MSG_NAVIGATION_RACE2 = 0x8e5,
+/*20120417 to latest
+식물형
+Plant
+20130807 to 20130814
+동물형
+Brute
+*/
+ MSG_NAVIGATION_RACE3 = 0x8e6,
+/*20120417 to latest
+곤충형
+Insect
+20130807 to 20130814
+식물형
+Plant
+*/
+ MSG_NAVIGATION_RACE4 = 0x8e7,
+/*20120417 to latest
+어패형
+Fish
+20130807 to 20130814
+곤충형
+Insect
+*/
+ MSG_NAVIGATION_RACE5 = 0x8e8,
+/*20120417 to latest
+악마형
+Demon
+20130807 to 20130814
+어패형
+Fish
+*/
+ MSG_NAVIGATION_RACE6 = 0x8e9,
+/*20120417 to latest
+인간형
+Demi-Human
+20130807 to 20130814
+악마형
+Demon
+*/
+ MSG_NAVIGATION_RACE7 = 0x8ea,
+/*20120417 to latest
+천사형
+Angel
+20130807 to 20130814
+인간형
+Demi-Human
+*/
+ MSG_NAVIGATION_RACE8 = 0x8eb,
+/*20120417 to latest
+용족
+Dragon
+20130807 to 20130814
+천사형
+Angel
+*/
+ MSG_NAVIGATION_RACE9 = 0x8ec,
+/*20120417 to latest
+무형
+Formless
+20130807 to 20130814
+용족
+Dragon
+*/
+ MSG_NAVIGATION_RACE0 = 0x8ed,
+/*20120417 to latest
+%s 이동 클릭
+Click to move %s
+20130807 to 20130814
+무형
+Formless
+*/
+ MSG_NAVIGATION_MOVECLICK = 0x8ee,
+/*20120417 to latest
+Npc 이동 서비스 이용
+Move to the Kafra Service Npc
+20130807 to 20130814
+%s 이동 클릭
+Click to move %s
+*/
+ MSG_NAVIGATION_NPCMOVE = 0x8ef,
+/*20120417 to latest
+NPC 클릭
+Click the NPC
+20130807 to 20130814
+Npc 이동 서비스 이용
+Move to the Kafra Service Npc
+*/
+ MSG_NAVIGATION_NPCCLICK = 0x8f0,
+/*20120417 to latest
+%s 이동
+Move %s
+20130807 to 20130814
+NPC 클릭
+Click the NPC
+*/
+ MSG_NAVIGATION_S_MOVE = 0x8f1,
+/*20120417 to latest
+비공정 이동
+Move to the Airship Service
+20130807 to 20130814
+%s 이동
+Move %s
+*/
+ MSG_NAVIGATION_PLANEMOVE = 0x8f2,
+/*20120417 to latest
+워프 이용
+By Warp
+20130807 to 20130814
+비공정 이동
+Move to the Airship Service
+*/
+ MSG_NAVIGATION_WARPUSE = 0x8f3,
+/*20120417 to latest
+도착점 : ( %d %d )
+End Points: (%d %d)
+20130807 to 20130814
+워프 이용
+By Warp
+*/
+ MSG_NAVIGATION_TARGETPOINT_D_D = 0x8f4,
+/*20120417 to 20170517
+네비게이션이 지원 되지 않는 지역 입니다.
+20130807 to 20130814
+도착점 : ( %d %d )
+End Points: (%d %d)
+20170524 to latest
+내비게이션이 지원 되지 않는 지역 입니다.
+That does not support the navigation area
+*/
+ MSG_NAVIGATION_UNKNOWNMAP = 0x8f5,
+/*20120417 to latest
+찾고자 하는 목적이 불분명 합니다.
+The purpose is unclear
+20130807 to 20130814
+네비게이션이 지원 되지 않는 지역 입니다.
+*/
+ MSG_NAVIGATION_RS_UNKNOWN = 0x8f6,
+/*20120417 to latest
+매칭이 맞지 않는 맵이다.
+Does not meet the map requirement
+20130807 to 20130814
+찾고자 하는 목적이 불분명 합니다.
+The purpose is unclear
+*/
+ MSG_NAVIGATION_RS_NOTSAMEMAP = 0x8f7,
+/*20120417 to latest
+출발 지역에 대한 정보 설정 실패!
+Information Failure | Change settings
+20130807 to 20130814
+매칭이 맞지 않는 맵이다.
+Does not meet the map requirement
+*/
+ MSG_NAVIGATION_RS_FAILSTARTDATA = 0x8f8,
+/*20120417 to latest
+도착 지점에 대한 정보 설정 실패!
+Failed to set info for location!
+20130807 to 20130814
+출발 지역에 대한 정보 설정 실패!
+Information Failure | Change settings
+*/
+ MSG_NAVIGATION_RS_FAILTARGET = 0x8f9,
+/*20120417 to latest
+길 찾기 실패
+Failed to find a path
+20130807 to 20130814
+도착 지점에 대한 정보 설정 실패!
+Failed to set info for location!
+*/
+ MSG_NAVIGATION_RS_FAILROUTE = 0x8fa,
+/*20120417 to latest
+플레이어 위치 찾기 실패
+Failed to find players
+20130807 to 20130814
+길 찾기 실패
+Failed to find a path
+*/
+ MSG_NAVIGATION_RS_FAILPLAYER = 0x8fb,
+/*20120417 to latest
+내비게이션에 정보가 없습니다.
+No Information
+20130807 to 20130814
+플레이어 위치 찾기 실패
+Failed to find players
+*/
+ MSG_NAVIGATION_RS_NODATA = 0x8fc,
+/*20120417 to latest
+해당 맵은 길찾기가 지원 되지 않는 맵입니다.
+Map doesn't support directions
+20130807 to 20130814
+내비게이션에 정보가 없습니다.
+No Information
+*/
+ MSG_NAVIGATION_RS_MAPNOTNAVIGATION = 0x8fd,
+/*20120417 to latest
+목표를 지정 하시기 바랍니다.
+Please specify target goals.
+20130807 to 20130814
+해당 맵은 길찾기가 지원 되지 않는 맵입니다.
+Map doesn't support directions
+*/
+ MSG_NAVIGATION_RS_FAILTARGETROUTE = 0x8fe,
+/*20120417 to latest
+도착.
+Found
+20130807 to 20130814
+목표를 지정 하시기 바랍니다.
+Please specify target goals.
+*/
+ MSG_NAVIGATION_RS_SUCCESS = 0x8ff,
+/*20120417 to latest
+길 안내가 시작 되었습니다.
+Directions were started
+20130807 to 20130814
+도착.
+Found
+*/
+ MSG_NAVIGATION_RS_START = 0x900,
+/*20120417 to latest
+찾고자 하는 몬스터가 있는 맵 입니다.
+Is the map that your looking for mob
+20130807 to 20130814
+길 안내가 시작 되었습니다.
+Directions were started
+*/
+ MSG_NAVIGATION_RS_MOBTARGETMAP = 0x901,
+/*20120417 to latest
+찾고자 하는 맵이 해당 맵 입니다.
+Map appears on the guide you are looking for
+20130807 to 20130814
+찾고자 하는 몬스터가 있는 맵 입니다.
+Is the map that your looking for mob
+*/
+ MSG_NAVIGATION_RS_TARGETMAP = 0x902,
+/*20120417 to latest
+아이템을 사용하여 이동하여 주시기 바랍니다.
+Please navigate using the item
+20130807 to 20130814
+찾고자 하는 맵이 해당 맵 입니다.
+Map appears on the guide you are looking for
+*/
+ MSG_NAVIGATION_RS_SCROLL = 0x903,
+/*20120417 to latest
+안내하는 위치로 이동하시기 바랍니다.
+Please follow the instruction to reach your destination.
+20130807 to 20130814
+아이템을 사용하여 이동하여 주시기 바랍니다.
+Please navigate using the item
+*/
+ MSG_NAVIGATION_RS_ROUTE_SUCCESS = 0x904,
+/*20120417 to latest
+목표 맵에 도착하였습니다.
+Arrived at the target map
+20130807 to 20130814
+안내하는 위치로 이동하시기 바랍니다.
+Please follow the instruction to reach your destination.
+*/
+ MSG_NAVIGATION_RS_MAPTMAP_SUCCESS = 0x905,
+/*20120417 to latest
+찾고자 하는 Npc가 있는 맵에 도착 하였습니다. Npc로 이동하시기 바랍니다.
+Arrived on the map that has the Npc your looking for. Go to that NPC
+20130807 to 20130814
+목표 맵에 도착하였습니다.
+Arrived at the target map
+*/
+ MSG_NAVIGATION_RS_NPCTMAP_SUCCESS = 0x906,
+/*20120417 to latest
+찾고자 하는 Mob이 서식하는 맵에 도착 하였습니다.
+You have arrived at the mob you were looking for
+20130807 to 20130814
+찾고자 하는 Npc가 있는 맵에 도착 하였습니다. Npc로 이동하시기 바랍니다.
+Arrived on the map that has the Npc your looking for. Go to that NPC
+*/
+ MSG_NAVIGATION_RS_MOBTMAP_SUCCESS = 0x907,
+/*20120417 to latest
+이전과 동일한 목표 입니다.
+You have reached your goal
+20130807 to 20130814
+찾고자 하는 Mob이 서식하는 맵에 도착 하였습니다.
+You have arrived at the mob you were looking for
+*/
+ MSG_NAVIGATION_RS_POSTMAP_SUCCESS = 0x908,
+/*20120417 to latest
+가리키는 방향으로 가시기 바랍니다.
+Please go to indicated direction.
+20130807 to 20130814
+이전과 동일한 목표 입니다.
+You have reached your goal
+*/
+ MSG_NAVIGATION_RS_SAMETARGET = 0x909,
+/*20120417 to latest
+목표가 여기 입니다.
+The goal has been reached
+20130807 to 20130814
+가리키는 방향으로 가시기 바랍니다.
+Please go to indicated direction.
+*/
+ MSG_NAVIGATION_RS_HERE = 0x90a,
+/*20120417 to latest
+Navigation >: %s
+20130807 to 20130814
+목표가 여기 입니다.
+The goal has been reached
+*/
+ MSG_NAVIGATION_PRINT_S = 0x90b,
+/*20120417 to latest
+Navigation >: 안내하는 %s(을)를 이용하여
+Navigation >: Talk to Guide "%s" (A)
+20130807 to 20130814
+Navigation >: %s
+*/
+ MSG_NAVIGATION_PRINT_GO_S = 0x90c,
+/*20120417 to latest
+Navigation >: 맵(%s)으로 이동하시기 바랍니다
+Navigation >: Move to (%s) map
+20130807 to 20130814
+Navigation >: 안내하는 %s(을)를 이용하여
+Navigation >: Talk to Guide "%s" (A)
+*/
+ MSG_NAVIGATION_PRINT_MAP_S = 0x90d,
+/*20120417 to latest
+Navigation >: 맵(%s)을 선택하여 이동 하시기 바랍니다
+Navigation >: Choose (%s) Map from Kafra
+20130807 to 20130814
+Navigation >: 맵(%s)으로 이동하시기 바랍니다
+Navigation >: Move to (%s) map
+*/
+ MSG_NAVIGATION_PRINT_SELECTMAP_S = 0x90e,
+/*20120417 to latest
+Navigation >: 비공정으로 이동 하시기 바랍니다
+Navigation >: Please go to the AirShip
+20130807 to 20130814
+Navigation >: 맵(%s)을 선택하여 이동 하시기 바랍니다
+Navigation >: Choose (%s) Map from Kafra
+*/
+ MSG_NAVIGATION_PRINT_PLANE = 0x90f,
+/*20120417 to latest
+Navigation >: 워프를 이용하여 다음 지역으로 이동하시기 바랍니다.
+Navigation >: Get to your destination by using WarpPortal
+20130807 to 20130814
+Navigation >: 비공정으로 이동 하시기 바랍니다
+Navigation >: Please go to the AirShip
+*/
+ MSG_NAVIGATION_PRINT_WARP = 0x910,
+/*20120417 to latest
+Item:
+20130807 to 20130814
+Navigation >: 워프를 이용하여 다음 지역으로 이동하시기 바랍니다.
+Navigation >: Get to your destination by using WarpPortal
+*/
+ MSG_NAVIGATION_PRINT_ITEM = 0x911,
+/*20120417 to latest
+$$
+20130807 to 20130814
+Item:
+*/
+ MSG_NAVIGATION_ZZ = 0x912,
+/*20120417 to latest
+$$lv
+20130807 to 20130814
+$$
+*/
+ MSG_NAVIGATION_ZZLV = 0x913,
+/*20120417 to latest
+~
+20130807 to 20130814
+$$lv
+*/
+ MSG_NAVIGATION_ZZLIMIT = 0x914,
+/*20120417 to latest
+$$all
+20130807 to 20130814
+~
+*/
+ MSG_NAVIGATION_ZZALL = 0x915,
+#endif
+#if PACKETVER >= 20120424
+/*20120424 to latest
+구매 확인서
+Confirm Deal
+20130807 to 20130814
+$$all
+*/
+ MSG_SHOP_ITEM_BAY_TITLE = 0x916,
+/*20120424 to latest
+구입하려는 아이템들의 총가격은
+Below is the total cost:
+20130807 to 20130814
+구매 확인서
+Confirm Deal
+*/
+ MSG_SHOP_ITEM_BAY_MAG1 = 0x917,
+/*20120424 to latest
+Zeny 입니다.
+ Zeny to complete the transaction.
+20130807 to 20130814
+구입하려는 아이템들의 총가격은
+Below is the total cost:
+*/
+ MSG_SHOP_ITEM_BAY_MAG2 = 0x918,
+/*20120424 to latest
+구입하시겠습니까?
+Press buy to confirm.
+20130807 to 20130814
+Zeny 입니다.
+ Zeny to complete the transaction.
+*/
+ MSG_SHOP_ITEM_BAY_MAG3 = 0x919,
+#endif
+#if PACKETVER >= 20120503
+/*20120503 to 20120529
+%.3f%% (PC방 %.3f%% + TPLUS %.3f%% + 프리미엄 %.3f%% + %s서버 %.3f%%)
+20120604 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + 프리미엄 %.1f%% + %s서버 %.1f%%)
+%.1f% (PCRoom %.1f% + TPLUS %.1f% + Premium %.1f% + %sServer %.1f%)
+20130807 to 20130814
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BASIC_EXP_MSG2 = 0x91a,
+#endif
+#if PACKETVER >= 20120508
+/*20120508 to latest
+카드 북
+Card Book
+20130807 to 20130814
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + 프리미엄 %.1f%% + %s서버 %.1f%%)
+%.1f% (PCRoom %.1f% + TPLUS %.1f% + Premium %.1f% + %sServer %.1f%)
+*/
+ MSG_CARDWIN = 0x91b,
+#endif
+#if PACKETVER >= 20120515
+/*20120515 to latest
+%d%% [ ( 기본 100%% + %s서버 %d%% ) * 활성 %.1f ]
+%d%% [ ( Basic 100%% + %sServer %d%% ) * Active %.1f ]
+20130807 to 20130814
+카드 북
+Card Book
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN = 0x91c,
+/*20120515 to latest
+%d%% [ 기본 100%% + %s서버 %d%% ]
+%d%% [ Basic 100%% + %sServer %d%% ]
+20130807 to 20130814
+%d%% [ ( 기본 100%% + %s서버 %d%% ) * 활성 %.1f ]
+%d%% [ ( Basic 100%% + %sServer %d%% ) * Active %.1f ]
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN_DEATH = 0x91d,
+#endif
+#if PACKETVER >= 20120522
+/*20120522 to latest
+이곳은 PK 지역입니다. 미성년자는 자발적으로 떠나주시기 바랍니다.
+This is PK region. Minors,Please leave immediately.
+20130807 to 20130814
+%d%% [ 기본 100%% + %s서버 %d%% ]
+%d%% [ Basic 100%% + %sServer %d%% ]
+*/
+ MSG_CAUTION_PKZONE = 0x91e,
+/*20120522 to latest
+피로도
+Fatigue
+20130807 to 20130814
+이곳은 PK 지역입니다. 미성년자는 자발적으로 떠나주시기 바랍니다.
+This is PK region. Minors,Please leave immediately.
+*/
+ MSG_FATIGUE = 0x91f,
+/*20120522 to 20120529
+건강상태 이며 게임수익은 100%%입니다.
+20120604 to latest
+건강상태 이며 게임수익은 100%입니다.
+Health and gaming revenue is 100%%.
+20130807 to 20130814
+피로도
+Fatigue
+*/
+ MSG_FATIGUE_LEVEL_ZERO = 0x920,
+/*20120522 to 20120529
+지금은 피로상태이므로 손님의 게임수익은 50%% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+20120604 to latest
+지금은 피로상태이므로 손님의 게임수익은 50% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+Fatigue because it is now a guest of the gaming revenue is down 50 percent.Hope for the proper health
+20130807 to 20130814
+건강상태 이며 게임수익은 100%입니다.
+Health and gaming revenue is 100%%.
+*/
+ MSG_FATIGUE_LEVEL_HALF = 0x921,
+/*20120522 to 20120529
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+20120604 to latest
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+Now because it is a non-health to the health of the guests want to offline games. If you still are online gaming revenue because the damage to the health of the game falls to 0% again after 5 hours will be restored offline.
+20130807 to 20130814
+지금은 피로상태이므로 손님의 게임수익은 50% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+Fatigue because it is now a guest of the gaming revenue is down 50 percent.Hope for the proper health
+*/
+ MSG_FATIGUE_LEVEL_FULL = 0x922,
+/*20120522 to latest
+접속시간 %d 분이 되었습니다.
+Online since %d minutes
+20130807 to 20130814
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+Now because it is a non-health to the health of the guests want to offline games. If you still are online gaming revenue because the damage to the health of the game falls to 0% again after 5 hours will be restored offline.
+*/
+ MSG_FATIGUE_MESSAGE0 = 0x923,
+/*20120522 to latest
+접속시간 %d 시간이 되었습니다.
+Online Time: %d
+20130807 to 20130814
+접속시간 %d 분이 되었습니다.
+Online since %d minutes
+*/
+ MSG_FATIGUE_MESSAGE1 = 0x924,
+/*20120522 to latest
+접속시간 %d 시간 %d 분이 되었습니다.
+Online since %d hours and %d minutes
+20130807 to 20130814
+접속시간 %d 시간이 되었습니다.
+Online Time: %d
+*/
+ MSG_FATIGUE_MESSAGE2 = 0x925,
+/*20120522 to latest
+/monsterhp : 공격한 몬스터의 HP정보를 표시합니다. On Off
+/monsterhp: Show the hp of attacked monster. On off
+20130807 to 20130814
+접속시간 %d 시간 %d 분이 되었습니다.
+Online since %d hours and %d minutes
+*/
+ MSG_EXPLAIN_MONSTERHP = 0x926,
+#endif
+#if PACKETVER >= 20120529
+/*20120529 to latest
+스킬포인트 :
+Skill Points:
+20130807 to 20130814
+/monsterhp : 공격한 몬스터의 HP정보를 표시합니다. On Off
+/monsterhp: Show the hp of attacked monster. On off
+*/
+ MSG_SKILLPOINT2 = 0x927,
+#endif
+#if PACKETVER >= 20120604
+/*20120604 to latest
+인증서버로 부터의 응답이 없습니다. 다시 시도해 주세요
+There is no response from the authentification server. Please try again
+20130807 to 20130814
+스킬포인트 :
+Skill Points:
+*/
+ MSG_BAN_BILLING_SERVER_ERROR = 0x928,
+#endif
+#if PACKETVER >= 20120612
+/*20120612 to latest
+암호를 변경하여 주시기 바랍니다.
+Please change your password
+20130807 to 20130814
+인증서버로 부터의 응답이 없습니다. 다시 시도해 주세요
+There is no response from the authentification server. Please try again
+*/
+ MSG_REFUSE_CHANGE_PASSWD_FORCE = 0x929,
+/*20120612 to latest
+http://www.ragnarok.co.kr
+20130807 to 20130814
+암호를 변경하여 주시기 바랍니다.
+Please change your password
+*/
+ MSG_REFUSE_CHANGE_PASSWD_SITE = 0x92a,
+/*20120612 to latest
+고객님께서는 현재 접속금지 시간입니다.
+Guest access is prohibited
+20130807 to 20130814
+http://www.ragnarok.co.kr
+*/
+ MSG_PLANNED_TIME_SHUTDOWN = 0x92b,
+/*20120612 to latest
+셧다운제도에 의해 고객님의 게임제한 시간은 %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d에 게임이 종료될 예정입니다.
+Your System is been Shutdown, %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d is the end time.
+20130807 to 20130814
+고객님께서는 현재 접속금지 시간입니다.
+Guest access is prohibited
+*/
+ MSG_SHOUTDOWN_TIME = 0x92c,
+#endif
+#if PACKETVER >= 20120626
+/*20120626 to latest
+고객님의 계정은 선택적 셧다운이 적용된 계정이며, 잔여시간은 %1.2d시간 %1.2d분입니다. 게임 이용에 참고해주시기 바랍니다.
+Selected System Shutdown is activated in your account,Time Left: %1.2d hours %1.2d minutes.
+20130807 to 20130814
+셧다운제도에 의해 고객님의 게임제한 시간은 %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d에 게임이 종료될 예정입니다.
+Your System is been Shutdown, %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d is the end time.
+*/
+ MSG_PARTIAL_SHOUTDOWN_TIME = 0x92d,
+#endif
+#if PACKETVER >= 20120702
+/*20120702 to latest
+리플레이
+Replay
+20130807 to 20130814
+고객님의 계정은 선택적 셧다운이 적용된 계정이며, 잔여시간은 %1.2d시간 %1.2d분입니다. 게임 이용에 참고해주시기 바랍니다.
+Selected System Shutdown is activated in your account,Time Left: %1.2d hours %1.2d minutes.
+*/
+ MSG_MENU_REPLAYWND = 0x92e,
+/*20120702 to latest
+매크로
+Macro
+20130807 to 20130814
+리플레이
+Replay
+*/
+ MSG_MENU_MACROWND = 0x92f,
+/*20120702 to latest
+Webbrowser
+20130807 to 20130814
+매크로
+Macro
+*/
+ MSG_MENU_WEBBROWSERWND = 0x930,
+/*20120702 to 20170517
+네비게이션
+20130807 to 20130814
+Webbrowser
+20170524 to latest
+내비게이션
+Navigation
+*/
+ MSG_MENU_NAVIGATIONWND = 0x931,
+/*20120702 to latest
+UAEURL
+20130807 to 20130814
+네비게이션
+*/
+ MSG_MENU_UAEURLWND = 0x932,
+/*20120702 to latest
+ 클랜정보
+Clan Information
+20130807 to 20130814
+UAEURL
+*/
+ MSG_CLAN_INFOMANAGE = 0x933,
+/*20120702 to latest
+클랜레벨
+Clan Level
+20130807 to 20130814
+ 클랜정보
+Clan Information
+*/
+ MSG_CLAN_LEVEL = 0x934,
+/*20120702 to latest
+클랜명
+Clan Name
+20130807 to 20130814
+클랜레벨
+Clan Level
+*/
+ MSG_CLAN_NAME = 0x935,
+/*20120702 to latest
+클랜마크
+Clan Mark
+20130807 to 20130814
+클랜명
+Clan Name
+*/
+ MSG_CLAN_MARK = 0x936,
+/*20120702 to latest
+동맹클랜
+Ally Clan
+20130807 to 20130814
+클랜마크
+Clan Mark
+*/
+ MSG_ALLY_CLAN = 0x937,
+/*20120702 to 20130529
+적대길드
+Antagonists
+20130605 to latest
+적대클랜
+Antagonist Clan
+20130807 to 20130814
+동맹클랜
+Ally Clan
+*/
+ MSG_HOSTILITY_CLAN = 0x938,
+/*20120702 to latest
+클랜에게 보냄
+Send to Clan
+20130807 to 20130814
+적대클랜
+Antagonist Clan
+*/
+ MSG_SEND_TO_CLAN = 0x939,
+/*20120702 to latest
+마스터이름
+ClanMaster Name
+20130807 to 20130814
+클랜에게 보냄
+Send to Clan
+*/
+ MSG_CLAN_MASTER_NAME = 0x93a,
+/*20120702 to latest
+조합원수
+Number of Members
+20130807 to 20130814
+마스터이름
+ClanMaster Name
+*/
+ MSG_CLAN_NUM_MEMBER = 0x93b,
+/*20120702 to 20120702
+조합원 평균레벨
+Avg.lvl of Guildsmen
+20120710 to latest
+관리영지
+Castles Owned
+20130807 to 20130814
+조합원수
+Number of Members
+*/
+ MSG_CLAN_MANAGE_LAND = 0x93c,
+/*20120702 to 20130814
+관리영지
+Castles Owned
+20120716 to latest
+클랜 채팅 메시지 표시
+Clan Chat Messages
+*/
+ MSG_VIEW_CLAN_MSG = 0x93d,
+#endif
+#if PACKETVER >= 20120716
+/*20120716 to latest
+충전 페이지로 이동합니다.
+Go to Page Charged.
+20130807 to 20130814
+클랜 채팅 메시지 표시
+Clan Chat Messages
+*/
+ MSG_TWWAB_WARRING = 0x93e,
+/*20120716 to 20120716
+http://ro.game.gnjoy.com/
+20120724 to latest
+https://gfb.gameflier.com/Billing/ingame/index_new.asp?
+20130807 to 20130814
+충전 페이지로 이동합니다.
+Go to Page Charged.
+*/
+ MSG_TWWAB_URL = 0x93f,
+#endif
+#if PACKETVER >= 20120724
+/*20120724 to latest
+캐릭터 만들기
+Create char
+20130807 to 20130814
+https://gfb.gameflier.com/Billing/ingame/index_new.asp?
+*/
+ MSG_STR_MAKECHARACTER = 0x940,
+/*20120724 to latest
+캐릭명이 일치하지 않습니다.
+Name does not match
+20130807 to 20130814
+캐릭터 만들기
+Create char
+*/
+ MSG_CHR_DELETE_RESERVED_FAIL_CHARNAME = 0x941,
+/*20120724 to latest
+캐릭터명을 입력하세요
+Enter the name of character
+20130807 to 20130814
+캐릭명이 일치하지 않습니다.
+Name does not match
+*/
+ MSG_CHR_DELETE_RESERVED_INPUTCONFIRMSTR_WND_TITLE = 0x942,
+/*20120724 to 20120822
+/bufftimer : 버프에 쿨타이머를 표시합니다. On Off
+20120830 to latest
+성별 선택 창
+Sex Selection Window
+20130807 to 20130814
+캐릭터명을 입력하세요
+Enter the name of character
+*/
+ MSG_SELECT_SEX = 0x943,
+/*20120724 to 20120822
+버프에 쿨타이머가 표시됩니다.
+20120830 to latest
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+20130807 to 20130814
+성별 선택 창
+Sex Selection Window
+*/
+ MSG_SPRITE_ALTER = 0x944,
+/*20120724 to 20120822
+버프에 쿨타이머가 표시되지 않습니다.
+20120830 to latest
+해당 아이템을 개봉하여 획득되는 아이템들은 캐릭터 귀속 아이템 (창고이동 불가능) 입니다. 본 캐릭터에 사용하시는 것이 맞으신지 확인해주시기 바랍니다. 상자를 개봉하시겠습니까?
+Items obtained by opening the item is character bounded (can not move to storage). Do you want to open the box?
+20130807 to 20130814
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+*/
+ MSG_CONFIRM_TO_OPEN_EVENT_ITEM = 0x945,
+#endif
+#if PACKETVER >= 20120808
+/*20120808 to 20120822
+성별 선택 창
+Sex Selection Window
+20120925 to latest
+게임 설정
+Game Settings
+20130807 to 20130814
+해당 아이템을 개봉하여 획득되는 아이템들은 캐릭터 귀속 아이템 (창고이동 불가능) 입니다. 본 캐릭터에 사용하시는 것이 맞으신지 확인해주시기 바랍니다. 상자를 개봉하시겠습니까?
+Items obtained by opening the item is character bounded (can not move to storage). Do you want to open the box?
+*/
+ MSG_GAME_SETTING = 0x946,
+#endif
+#if PACKETVER >= 20120822
+/*20120822 to 20120822
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+20120925 to latest
+게임 시스템
+Game System
+20130807 to 20130814
+게임 설정
+Game Settings
+*/
+ MSG_SYSTEM_SETTING = 0x947,
+#endif
+#if PACKETVER >= 20120925
+/*20120925 to latest
+게임 커맨드
+Game Commands
+20130807 to 20130814
+게임 시스템
+Game System
+*/
+ MSG_COMMAND_SETTING = 0x948,
+/*20120925 to 20120926
+게임 커맨드 리스트
+20121010 to latest
+게임 커맨드 ON/OFF
+Game Command ON/OFF
+20130807 to 20130814
+게임 커맨드
+Game Commands
+*/
+ MSG_COMMAND_LIST = 0x949,
+/*20120925 to latest
+매크로
+Macro
+20130807 to 20130814
+게임 커맨드 ON/OFF
+Game Command ON/OFF
+*/
+ MSG_MACRO_LIST = 0x94a,
+/*20120925 to latest
+이지역은 아이템교환이 금지 되어 있습니다
+Trading is prohibited in this Map
+20130807 to 20130814
+매크로
+Macro
+*/
+ MSG_EXCHANGEITEM_DENY_MAP = 0x94b,
+/*20120925 to latest
+이지역은 카트이용이 금지 되어 있습니다
+Vending is prohibited in this Map
+20130807 to 20130814
+이지역은 아이템교환이 금지 되어 있습니다
+Trading is prohibited in this Map
+*/
+ MSG_CART_USE_DENY_MAP = 0x94c,
+#endif
+#if PACKETVER >= 20121010
+/*20121010 to latest
+이지역은 태양과달과별의 기적 효과가 발생하지 않습니다.
+In this Map,Effect of Mirace of Sun and Moon is nullified.
+20130807 to 20130814
+이지역은 카트이용이 금지 되어 있습니다
+Vending is prohibited in this Map
+*/
+ MSG_BLOCK_SUNMOONSTAR_MIRACLE = 0x94d,
+/*20121010 to latest
+랭킹 보드
+Ranking Board
+20130807 to 20130814
+이지역은 태양과달과별의 기적 효과가 발생하지 않습니다.
+In this Map,Effect of Mirace of Sun and Moon is nullified.
+*/
+ MSG_RANKING_BOARD = 0x94e,
+/*20121010 to latest
+순위
+Rank
+20130807 to 20130814
+랭킹 보드
+Ranking Board
+*/
+ MSG_RANKING_NUMBER = 0x94f,
+/*20121010 to latest
+이름
+Name
+20130807 to 20130814
+순위
+Rank
+*/
+ MSG_RANKING_NAME = 0x950,
+/*20121010 to latest
+포인트
+Points
+20130807 to 20130814
+이름
+Name
+*/
+ MSG_RANKING_POINT = 0x951,
+/*20121010 to latest
+BlackSmith
+20130807 to 20130814
+포인트
+Points
+*/
+ MSG_RANKING_BLACKSMITH = 0x952,
+/*20121010 to latest
+Alchemist
+20130807 to 20130814
+BlackSmith
+*/
+ MSG_RANKING_ALCHEMIST = 0x953,
+/*20121010 to latest
+Taekwon
+20130807 to 20130814
+Alchemist
+*/
+ MSG_RANKING_TAEKWON = 0x954,
+/*20121010 to latest
+Killer
+20130807 to 20130814
+Taekwon
+*/
+ MSG_RANKING_KILLER = 0x955,
+/*20121010 to 20121010
+Munak
+20121017 to 20121107
+1 vs 1
+20121114 to latest
+7 vs 7
+20130807 to 20130814
+Killer
+*/
+ MSG_RANKING_BATTLE_7VS7_ALL = 0x956,
+/*20121010 to 20121010
+DeathKnight
+20121017 to 20130814
+7 vs 7
+20121114 to latest
+RuneKnight
+*/
+ MSG_RANKING_RUNE_KNIGHT = 0x957,
+/*20121010 to 20121010
+Collector
+20121017 to 20121107
+Select Ranking Type
+20121114 to latest
+Warlock
+20130807 to 20130814
+RuneKnight
+*/
+ MSG_RANKING_WARLOCK = 0x958,
+/*20121010 to 20121010
+Select Ranking Type
+20121017 to 20121107
+Ranking Type
+20121114 to latest
+Ranger
+20130807 to 20130814
+Warlock
+*/
+ MSG_RANKING_RANGER = 0x959,
+/*20121010 to 20121010
+Ranking Type
+20121114 to latest
+Mechanic
+20130807 to 20130814
+Ranger
+*/
+ MSG_RANKING_MECHANIC = 0x95a,
+#endif
+#if PACKETVER >= 20121114
+/*20121114 to latest
+GuillotineCross
+20130807 to 20130814
+Mechanic
+*/
+ MSG_RANKING_GUILLOTINE_CROSS = 0x95b,
+/*20121114 to latest
+Archbishop
+20130807 to 20130814
+GuillotineCross
+*/
+ MSG_RANKING_ARCHBISHOP = 0x95c,
+/*20121114 to latest
+RoyalGuard
+20130807 to 20130814
+Archbishop
+*/
+ MSG_RANKING_ROYAL_GUARD = 0x95d,
+/*20121114 to latest
+Sorcerer
+20130807 to 20130814
+RoyalGuard
+*/
+ MSG_RANKING_SORCERER = 0x95e,
+/*20121114 to latest
+Minstrel
+20130807 to 20130814
+Sorcerer
+*/
+ MSG_RANKING_MINSTREL = 0x95f,
+/*20121114 to latest
+Wanderer
+20130807 to 20130814
+Minstrel
+*/
+ MSG_RANKING_WANDERER = 0x960,
+/*20121114 to latest
+Genetic
+20130807 to 20130814
+Wanderer
+*/
+ MSG_RANKING_GENETIC = 0x961,
+/*20121114 to latest
+ShadowChaser
+20130807 to 20130814
+Genetic
+*/
+ MSG_RANKING_SHADOW_CHASER = 0x962,
+/*20121114 to latest
+Sura
+20130807 to 20130814
+ShadowChaser
+*/
+ MSG_RANKING_SURA = 0x963,
+/*20121114 to latest
+Kagerou
+20130807 to 20130814
+Sura
+*/
+ MSG_RANKING_KAGEROU = 0x964,
+/*20121114 to latest
+Oboro
+20130807 to 20130814
+Kagerou
+*/
+ MSG_RANKING_OBORO = 0x965,
+/*20121114 to latest
+Select Ranking Type
+20130807 to 20130814
+Oboro
+*/
+ MSG_RANKING_SELECT = 0x966,
+/*20121114 to latest
+Ranking Type
+20130807 to 20130814
+Select Ranking Type
+*/
+ MSG_RANKING_TYPE = 0x967,
+/*20121114 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dSeconds
+20130807 to 20130814
+Ranking Type
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_SEC = 0x968,
+/*20121114 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d분 %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dMinutes %d Seconds
+20130807 to 20130814
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dSeconds
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_MIN = 0x969,
+/*20121114 to latest
+CBT 초청 유저가 아닙니다
+CBT is not an invited user
+20130807 to 20130814
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d분 %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dMinutes %d Seconds
+*/
+ MSG_CBT_ACTIVE_USER_CHECK = 0x96a,
+#endif
+#if PACKETVER >= 20121128
+/*20121128 to latest
+ -------------- Navigation 명령어 --------------
+------------------- Instruction --------------------
+20130807 to 20130814
+CBT 초청 유저가 아닙니다
+CBT is not an invited user
+*/
+ MSG_NAVIGATION_HELP_1 = 0x96b,
+/*20121128 to latest
+/navigation /navi : /navi yuno 100/100 ->> 맵이름, 위치(100/100)
+1) /Navigation or /navi ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+20130807 to 20130814
+ -------------- Navigation 명령어 --------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP_2 = 0x96c,
+/*20121128 to latest
+/navigation2 /navi2 : /navi2 yuno 100/100 1/1/1 ->> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+2) /Navigation2 or /navi2 ex) /navi2 prontera 100 111 -> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+20130807 to 20130814
+/navigation /navi : /navi yuno 100/100 ->> 맵이름, 위치(100/100)
+1) /Navigation or /navi ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP_3 = 0x96d,
+/*20121128 to latest
+ -------------- Navigation 검색창 명령어 -------
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+20130807 to 20130814
+/navigation2 /navi2 : /navi2 yuno 100/100 1/1/1 ->> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+2) /Navigation2 or /navi2 ex) /navi2 prontera 100 111 -> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP_4 = 0x96e,
+/*20121128 to latest
+$$all : 모든 항목 출력 (Type 구분자에서 출력 종류를 나눌수 있다.)
+3) $$all Output all the items (Can take a while...)
+20130807 to 20130814
+ -------------- Navigation 검색창 명령어 -------
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP_5 = 0x96f,
+/*20121128 to latest
+$$lv30 : 해당 레벨의 몬스터 출력 (숫자는 변경 가능)
+4) $$lv30 monsters are placed in the output
+20130807 to 20130814
+$$all : 모든 항목 출력 (Type 구분자에서 출력 종류를 나눌수 있다.)
+3) $$all Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP_6 = 0x970,
+/*20121128 to latest
+$$lv20~30 : 해당 레벨 범위의 몬스터 출력 (숫자는 변경 가능)
+5) $$lv20~30 monsters in that level range are placed in the output
+20130807 to 20130814
+$$lv30 : 해당 레벨의 몬스터 출력 (숫자는 변경 가능)
+4) $$lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP_7 = 0x971,
+/*20121128 to latest
+1 vs 1
+20130807 to 20130814
+$$lv20~30 : 해당 레벨 범위의 몬스터 출력 (숫자는 변경 가능)
+5) $$lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_RANKING_BATTLE_1VS1_ALL = 0x972,
+#endif
+#if PACKETVER >= 20121205
+/*20121205 to latest
+특수 장비
+Special Gear
+20130807 to 20130814
+1 vs 1
+*/
+ MSG_SHADOW_EQUIPMENT = 0x973,
+#endif
+#if PACKETVER >= 20130109
+/*20130109 to latest
+%d 번째 캐릭터의 직업 정보가 이상합니다. 고객센터로 문의 부탁 드립니다. ErrorCode(%d)
+%d First character of the profession is more than information. Please contact the Customer Care Center. ErrorCode(%d)
+20130807 to 20130814
+특수 장비
+Special Gear
+*/
+ MSG_CHARACTERERROR_JOB = 0x974,
+#endif
+#if PACKETVER >= 20130115
+/*20130115 to latest
+(%s) %d / %d
+20130807 to 20130814
+%d 번째 캐릭터의 직업 정보가 이상합니다. 고객센터로 문의 부탁 드립니다. ErrorCode(%d)
+%d First character of the profession is more than information. Please contact the Customer Care Center. ErrorCode(%d)
+*/
+ MSG_NAVIGATION_ALL_S = 0x975,
+/*20130115 to latest
+%s-%s(%d/%d)
+20130807 to 20130814
+(%s) %d / %d
+*/
+ MSG_NAVIGATION_ALL_SD = 0x976,
+#endif
+#if PACKETVER >= 20130121
+/*20130121 to latest
+접속자 수 초과로 서버에 더이상 접속할 수 없습니다.
+Server Exceeded the maximum number of users,Cannot Connect anymore users.
+20130807 to 20130814
+%s-%s(%d/%d)
+*/
+ MSG_REFUSE_OVER_USERLIMIT = 0x977,
+/*20130121 to latest
+서버접속 실패 (%d)
+Server Connection Failed (%d)
+20130807 to 20130814
+접속자 수 초과로 서버에 더이상 접속할 수 없습니다.
+Server Exceeded the maximum number of users,Cannot Connect anymore users.
+*/
+ MSG_REFUSE_ERRORCODE = 0x978,
+/*20130121 to latest
+로그인 허용시간 초과
+Login Timeout Permitted
+20130807 to 20130814
+서버접속 실패 (%d)
+Server Connection Failed (%d)
+*/
+ MSG_REFUSE_DISCONNECT_KEEP_TIME = 0x979,
+/*20130121 to latest
+로그인 중 인증서버로부터 인증이 실패하였습니다.
+Login Authentication Failed from Authentication Server.
+20130807 to 20130814
+로그인 허용시간 초과
+Login Timeout Permitted
+*/
+ MSG_REFUSE_WEB_AUTH_FAILED = 0x97a,
+#endif
+#if PACKETVER >= 20130206
+/*20130206 to latest
+길드이름에 공백문자를 사용할 수 없습니다.
+Guild Cannot use Space in the name.
+20130807 to 20130814
+로그인 중 인증서버로부터 인증이 실패하였습니다.
+Login Authentication Failed from Authentication Server.
+*/
+ MSG_GUILDNAME_CHECK = 0x97b,
+#endif
+#if PACKETVER >= 20130215
+/*20130215 to latest
+고객님 안녕하세요!
+Hey,Hello There
+20130807 to 20130814
+길드이름에 공백문자를 사용할 수 없습니다.
+Guild Cannot use Space in the name.
+*/
+ MSG_BILLING_CHN_1 = 0x97c,
+/*20130215 to latest
+고객님의 이용 시간은 %d년 %d 월 %d일 %d:%d 에 종료됩니다.
+Available Time will End on %d month %d hour %d:%d
+20130807 to 20130814
+고객님 안녕하세요!
+Hey,Hello There
+*/
+ MSG_BILLING_CHN_2 = 0x97d,
+/*20130215 to latest
+고객님의 이용 시간은 아직 많이 남았으니 안심하고 플레이하세요!
+You've lot of time,Play in Peace.
+20130807 to 20130814
+고객님의 이용 시간은 %d년 %d 월 %d일 %d:%d 에 종료됩니다.
+Available Time will End on %d month %d hour %d:%d
+*/
+ MSG_BILLING_CHN_3 = 0x97e,
+/*20130215 to latest
+고객님의 이용 시간은 이번 주 내로 종료 됩니다. 종료 전에 충전을 하시기 바랍니다.
+Your hours will be terminated within this week. Please Charge before termination.
+20130807 to 20130814
+고객님의 이용 시간은 아직 많이 남았으니 안심하고 플레이하세요!
+You've lot of time,Play in Peace.
+*/
+ MSG_BILLING_CHN_4 = 0x97f,
+/*20130215 to latest
+고객님의 이용 시간은 24시간 내에 종료됩니다. 빨리 충전하시기 바랍니다.
+Your hours will be terminated within 24 hours.Please Charge Quickly.
+20130807 to 20130814
+고객님의 이용 시간은 이번 주 내로 종료 됩니다. 종료 전에 충전을 하시기 바랍니다.
+Your hours will be terminated within this week. Please Charge before termination.
+*/
+ MSG_BILLING_CHN_5 = 0x980,
+/*20130215 to latest
+현재 고객님의 이용 시간은 %d시간 남았습니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d hours.Charge the game for uninterrupted play.
+20130807 to 20130814
+고객님의 이용 시간은 24시간 내에 종료됩니다. 빨리 충전하시기 바랍니다.
+Your hours will be terminated within 24 hours.Please Charge Quickly.
+*/
+ MSG_BILLING_CHN_6 = 0x981,
+/*20130215 to latest
+현재 고객님의 이용 시간은 %d분 남았습니다. 이용시간이 끝난 후 강제적으로 종료됩니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d minutes.Charge the game for uninterrupted play.
+20130807 to 20130814
+현재 고객님의 이용 시간은 %d시간 남았습니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d hours.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_7 = 0x982,
+/*20130215 to latest
+고객님의 이용 시간은 %d시간 %d분 남았습니다.
+Time Left: %d hours %d minutes
+20130807 to 20130814
+현재 고객님의 이용 시간은 %d분 남았습니다. 이용시간이 끝난 후 강제적으로 종료됩니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d minutes.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_8 = 0x983,
+/*20130215 to latest
+%d%% ( 기본 100%% + PC방 %d%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%% ( Basic 100%% + PCRoom %d%% + Premium %d%% + %sServer %d%% )
+20130807 to 20130814
+고객님의 이용 시간은 %d시간 %d분 남았습니다.
+Time Left: %d hours %d minutes
+*/
+ MSG_BASIC_EXP_MSG_THAI = 0x984,
+/*20130215 to latest
+고객님의 이용 시간은 %d시간 %d분 후에 종료됩니다.
+After %d hours %d minutes, your game will be terminated.
+20130807 to 20130814
+%d%% ( 기본 100%% + PC방 %d%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%% ( Basic 100%% + PCRoom %d%% + Premium %d%% + %sServer %d%% )
+*/
+ MSG_CHN_BILLING_EXPIRE_TIME = 0x985,
+#endif
+#if PACKETVER >= 20130220
+/*20130220 to latest
+유저님의 계정은 영구 접속금지 되였습니다
+This Account is permanently Banned.
+20130807 to 20130814
+고객님의 이용 시간은 %d시간 %d분 후에 종료됩니다.
+After %d hours %d minutes, your game will be terminated.
+*/
+ MSG_CHN_BLOCK_FOREVER = 0x986,
+/*20130220 to latest
+유저님의 계정은 접속금지 되였습니다
+ 해지 시간 : %04d-%02d-%02d %02d:%02d
+This Account is banned.
+Termination Time:%04d-%02d-%02d %02d:%02d
+20130807 to 20130814
+유저님의 계정은 영구 접속금지 되였습니다
+This Account is permanently Banned.
+*/
+ MSG_CHN_BLOCK = 0x987,
+#endif
+#if PACKETVER >= 20130227
+/*20130227 to latest
+몬스터(Tab)
+Monster(Tab)
+20130807 to 20130814
+유저님의 계정은 접속금지 되였습니다
+ 해지 시간 : %04d-%02d-%02d %02d:%02d
+This Account is banned.
+Termination Time:%04d-%02d-%02d %02d:%02d
+*/
+ MSG_WORLDMAP_MSG1 = 0x988,
+/*20130227 to latest
+맵(Alt)
+Map(Alt)
+20130807 to 20130814
+몬스터(Tab)
+Monster(Tab)
+*/
+ MSG_WORLDMAP_MSG2 = 0x989,
+/*20130227 to latest
+안내 정보
+Product Information
+20130807 to 20130814
+맵(Alt)
+Map(Alt)
+*/
+ MSG_WORLDMAP_MSG3 = 0x98a,
+/*20130227 to latest
+검색 정보
+Find Information
+20130807 to 20130814
+안내 정보
+Product Information
+*/
+ MSG_WORLDMAP_MSG4 = 0x98b,
+/*20130227 to latest
+비공정
+AirShip
+20130807 to 20130814
+검색 정보
+Find Information
+*/
+ MSG_WORLDMAP_MSG5 = 0x98c,
+/*20130227 to latest
+카프라
+Kafra
+20130807 to 20130814
+비공정
+AirShip
+*/
+ MSG_WORLDMAP_MSG6 = 0x98d,
+/*20130227 to latest
+(도착)
+(Arrival)
+20130807 to 20130814
+카프라
+Kafra
+*/
+ MSG_WORLDMAP_MSG7 = 0x98e,
+#endif
+#if PACKETVER >= 20130313
+/*20130313 to latest
+Mob)%s:%s(%s)
+20130807 to 20130814
+(도착)
+(Arrival)
+*/
+ MSG_NAVIGATION_MOB_S_S_S = 0x98f,
+/*20130313 to latest
+분포도:%s
+Distribution:%s
+20130807 to 20130814
+Mob)%s:%s(%s)
+*/
+ MSG_NAVIGATION_NUM = 0x990,
+/*20130313 to latest
+매우많음
+Very Plenty
+20130807 to 20130814
+분포도:%s
+Distribution:%s
+*/
+ MSG_NAVIGATION_NUM1 = 0x991,
+/*20130313 to latest
+많음
+Plenty
+20130807 to 20130814
+매우많음
+Very Plenty
+*/
+ MSG_NAVIGATION_NUM2 = 0x992,
+/*20130313 to latest
+보통
+Normal
+20130807 to 20130814
+많음
+Plenty
+*/
+ MSG_NAVIGATION_NUM3 = 0x993,
+/*20130313 to latest
+적음
+Low
+20130807 to 20130814
+보통
+Normal
+*/
+ MSG_NAVIGATION_NUM4 = 0x994,
+/*20130313 to latest
+매우적음
+Very Low
+20130807 to 20130814
+적음
+Low
+*/
+ MSG_NAVIGATION_NUM5 = 0x995,
+#endif
+#if PACKETVER >= 20130320
+/*20130320 to latest
+은행을 이용할 수 없습니다. 잠시 후 다시 시도하세요.
+The bank is not available. Please try again in a few minutes.
+20130807 to 20130814
+매우적음
+Very Low
+*/
+ MSG_BANK_SYSTEM_ERROR = 0x996,
+/*20130320 to latest
+은행 잔고가 부족합니다.
+Bank balance is low.
+20130807 to 20130814
+은행을 이용할 수 없습니다. 잠시 후 다시 시도하세요.
+The bank is not available. Please try again in a few minutes.
+*/
+ MSG_BANK_WITHDRAW_NO_MONEY = 0x997,
+#endif
+#if PACKETVER >= 20130327
+/*20130327 to latest
+보유한 Zeny 가 부족해서 입금할 수 없습니다.
+You don't have enough zeny
+20130807 to 20130814
+은행 잔고가 부족합니다.
+Bank balance is low.
+*/
+ MSG_BANK_DEPOSIT_NO_MONEY = 0x998,
+/*20130327 to latest
+1 Zeny 이상 입금 가능합니다.
+Minimum Deposit Amount: 1 zeny
+20130807 to 20130814
+보유한 Zeny 가 부족해서 입금할 수 없습니다.
+You don't have enough zeny
+*/
+ MSG_BANK_DEPOSIT_ZERO = 0x999,
+/*20130327 to latest
+1 Zeny 이상 출금 가능합니다.
+Minimum Withdrawal Amount: 1 zeny
+20130807 to 20130814
+1 Zeny 이상 입금 가능합니다.
+Minimum Deposit Amount: 1 zeny
+*/
+ MSG_BANK_WITHDRAW_ZERO = 0x99a,
+/*20130327 to 20130605
+보유 Zeny 는 21 억을 넘을 수 없습니다.
+20130605 to latest
+보유 Zeny 는 2,147,483,647 Zeny를 넘을 수 없습니다.
+You cannot hold more than 2,147,483,647 Zeny
+20130807 to 20130814
+1 Zeny 이상 출금 가능합니다.
+Minimum Withdrawal Amount: 1 zeny
+*/
+ MSG_BANK_OVER_INT_MAX = 0x99b,
+/*20130327 to latest
+your account is lock by mobil otp
+your account is lock by mobile otp
+20130807 to 20130814
+보유 Zeny 는 2,147,483,647 Zeny를 넘을 수 없습니다.
+You cannot hold more than 2,147,483,647 Zeny
+*/
+ MSG_REFUSE_MOTP_LOCK = 0x99c,
+/*20130327 to latest
+MOTP auth fail
+20130807 to 20130814
+your account is lock by mobil otp
+your account is lock by mobile otp
+*/
+ MSG_REFUSE_MOTP_AUTH_FAIL = 0x99d,
+/*20130327 to latest
+%d분간 몬스터에게 얻을 수 있는 Job경험치가 %d%% 증가합니다.
+For %d minutes,Job Experience obtained from monster is increased by %d%%
+20130807 to 20130814
+MOTP auth fail
+*/
+ MSG_JOBPLUSEXP_VALUE = 0x99e,
+#endif
+#if PACKETVER >= 20130410
+/*20130410 to 20130410
+소지 Zeny : %d Zeny
+20130417 to latest
+소지 Zeny : %s Zeny
+Current Zeny: %s Zeny
+20130807 to 20130814
+%d분간 몬스터에게 얻을 수 있는 Job경험치가 %d%% 증가합니다.
+For %d minutes,Job Experience obtained from monster is increased by %d%%
+*/
+ MSG_BANK_MY_ZENY = 0x99f,
+/*20130410 to latest
+Zeny
+20130807 to 20130814
+소지 Zeny : %s Zeny
+Current Zeny: %s Zeny
+*/
+ MSG_BANK_ZENY = 0x9a0,
+/*20130410 to 20130515
+* 최대 21억 Zeny까지만 보관이 가능합니다.
+20130522 to 20130605
+최대 2,147,483,647억 Zeny까지만 보관이 가능합니다.
+20130605 to 20130605
+최대 2,147,483,647 Zeny까지만 보관이 가능합니다.
+20130612 to latest
+최대 2,147,483,647 Zeny 까지만 보관이 가능합니다.
+The Maximum amount is 2,147,483,647 Zeny
+20130807 to 20130814
+Zeny
+*/
+ MSG_BANK_WARNING = 0x9a1,
+#endif
+#if PACKETVER >= 20130515
+/*20130515 to latest
+총알이 부족합니다.
+Insufficient bullet
+20130807 to 20130814
+최대 2,147,483,647 Zeny 까지만 보관이 가능합니다.
+The Maximum amount is 2,147,483,647 Zeny
+*/
+ MSG_NEED_MORE_BULLET = 0x9a2,
+/*20130515 to latest
+10억제니 이상 입력하셔도 가격은 10억 제니로 판매됩니다.
+You entered more than 1 Billion Zeny, the price will be set to 1 Billion Zeny.
+20130807 to 20130814
+총알이 부족합니다.
+Insufficient bullet
+*/
+ MSG_OVERPRICE_MAX = 0x9a3,
+#endif
+#if PACKETVER >= 20130605
+/*20130605 to latest
+AuthTicket is Not Vaild
+AuthTicket is Not Valid
+20130807 to 20130814
+10억제니 이상 입력하셔도 가격은 10억 제니로 판매됩니다.
+You entered more than 1 Billion Zeny, the price will be set to 1 Billion Zeny.
+*/
+ MSG_NOT_VALID_AUTH_TICKET = 0x9a4,
+/*20130605 to 20130605
+ErrorCode : %d, ErrorValue : %d
+20130612 to latest
+ErrorCategory : %d, ErrorCode : %d (%d,%d,%d,%d)
+ErrorCode : %d, ErrorValue : %d
+20130807 to 20130814
+AuthTicket is Not Vaild
+AuthTicket is Not Valid
+*/
+ MSG_STEAMAGENCY_ERROR = 0x9a5,
+#endif
+#if PACKETVER >= 20130618
+/*20130618 to 20130618
+%d%% ( Primary 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+20130626 to latest
+%d%% ( Basic 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+%d%% ( Basic 100%% + Premium %d%% + Internet cafe %d%% + %s Server %d%% )
+20130807 to 20130814
+ErrorCategory : %d, ErrorCode : %d (%d,%d,%d,%d)
+ErrorCode : %d, ErrorValue : %d
+*/
+ MSG_BASIC_EXP_MSG_INDONESIA = 0x9a6,
+/*20130618 to 20130925
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d분간 %d배로 증가합니다.
+20130807 to 20130814
+%d%% ( Basic 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+%d%% ( Basic 100%% + Premium %d%% + Internet cafe %d%% + %s Server %d%% )
+20130925 to latest
+ %d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE = 0x9a7,
+/*20130618 to 20130925
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d시 %.2d분간 %d배로 증가합니다.
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d분간 %d배로 증가합니다.
+20130925 to latest
+ %d시 %.2d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dhour %.2dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE_1 = 0x9a8,
+#endif
+#if PACKETVER >= 20130626
+/*20130626 to latest
+%s 의 가격이
+The price of^0000FF %s^000000
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d시 %.2d분간 %d배로 증가합니다.
+*/
+ MSG_WARNING_PRICE1 = 0x9a9,
+/*20130626 to latest
+100000000
+20130807 to 20130814
+%s 의 가격이
+The price of^0000FF %s^000000
+*/
+ MSG_WARNING_PRICE2 = 0x9aa,
+/*20130626 to latest
+ ^ff0000%d^0000ff억
+ is over ^FF0000%d^0000FF Billion^000000 Zeny and
+20130807 to 20130814
+100000000
+*/
+ MSG_WARNING_PRICE3 = 0x9ab,
+/*20130626 to latest
+10000000
+20130807 to 20130814
+ ^ff0000%d^0000ff억
+ is over ^FF0000%d^0000FF Billion^000000 Zeny and
+*/
+ MSG_WARNING_PRICE4 = 0x9ac,
+/*20130626 to latest
+ ^ff0000%d^0000ff천만
+ more than^FF0000 %d0^0000FF Million^000000 Zeny
+20130807 to 20130814
+10000000
+*/
+ MSG_WARNING_PRICE5 = 0x9ad,
+/*20130626 to latest
+^0000ffZeny 이상^000000입니다.
+입력금액이 맞습니까?
+. Is this correct?
+20130807 to 20130814
+ ^ff0000%d^0000ff천만
+ more than^FF0000 %d0^0000FF Million^000000 Zeny
+*/
+ MSG_WARNING_PRICE6 = 0x9ae,
+/*20130626 to latest
+천만Zeny이상 안전확인
+Safety check for more than 10m Zeny
+20130807 to 20130814
+^0000ffZeny 이상^000000입니다.
+입력금액이 맞습니까?
+. Is this correct?
+*/
+ MSG_WARNING_PRICE7 = 0x9af,
+/*20130626 to latest
+https://www.warpportal.com/account/login.aspx?ReturnUrl=%2faccount%2fpayment.aspx
+20130807 to 20130814
+천만Zeny이상 안전확인
+Safety check for more than 10m Zeny
+*/
+ MSG_AMERICA_CASHSHOP_URL = 0x9b0,
+/*20130626 to 20131023
+https://kepler.warpportal.com/steam/purchase/?step=1&steamid=76561198071003044&game=rose&accountname=khanhtest111&lang=en
+20130807 to 20130814
+https://www.warpportal.com/account/login.aspx?ReturnUrl=%2faccount%2fpayment.aspx
+20131030 to latest
+https://kepler.warpportal.com/ro1/purchase/?step=1&steamid=%lld&accountname=
+https://kepler.warpportal.com/ror/purchase/?step=1&steamid=%lld&accountname=
+*/
+ MSG_AMERICA_CASHSHOP_URL_STEAM = 0x9b1,
+/*20130626 to latest
+지상의 끝, 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 생겨난 거대한 균열, 그리고 근원을 알 수 없는 미궁숲.
+A giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim, and you do not know the source of the labyrinth forest.
+20130807 to 20130814
+https://kepler.warpportal.com/steam/purchase/?step=1&steamid=76561198071003044&game=rose&accountname=khanhtest111&lang=en
+*/
+ MSG_QUEST_INFO_01 = 0x9b2,
+/*20130626 to latest
+이것은 여행의 끝을 알리는 표식인가, 새로운 세계를 여는 지표인가! 수호자는 노랫말 같은 유혹에 점차 넋을 잃어가고 있었다.
+This is a marker indicating the end of the trip, a new world is opening indicators! Guardian, such as the lyrics to the temptation was gradually losing the soul.
+20130807 to 20130814
+지상의 끝, 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 생겨난 거대한 균열, 그리고 근원을 알 수 없는 미궁숲.
+A giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim, and you do not know the source of the labyrinth forest.
+*/
+ MSG_QUEST_INFO_02 = 0x9b3,
+/*20130626 to latest
+수천 년의 세월이 흐르는 동안, 그 스스로가 홀로 안간힘을 쓰며 지켜낸 것이 무엇이었는지, 봉인 되어 긴 시간을 갇혀버린 것은 오히려 자신이 아니었는지 혼란을 느끼고 있었다.
+For thousands of years, a mysterious melody has mesmerized the guardian. After a millennia of slumber, the guardian became confused about what he had been protecting all these years, and began to suspect that he might be the one who has been sealed and hidden away.
+20130807 to 20130814
+이것은 여행의 끝을 알리는 표식인가, 새로운 세계를 여는 지표인가! 수호자는 노랫말 같은 유혹에 점차 넋을 잃어가고 있었다.
+This is a marker indicating the end of the trip, a new world is opening indicators! Guardian, such as the lyrics to the temptation was gradually losing the soul.
+*/
+ MSG_QUEST_INFO_03 = 0x9b4,
+/*20130626 to latest
+유혹의 노랫말이 최고조에 이르렀을 때, 지상의 끝 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 거대한 균열이 생겨났고, 그로 인해 두 세계간의 왕래가 끊기면서 사람들은 큰 불편을 겪게 되었다.
+When the melody reached its peak, a giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim. As a result, the two worlds were cut off from each other, causing a big problem for the people.
+20130807 to 20130814
+수천 년의 세월이 흐르는 동안, 그 스스로가 홀로 안간힘을 쓰며 지켜낸 것이 무엇이었는지, 봉인 되어 긴 시간을 갇혀버린 것은 오히려 자신이 아니었는지 혼란을 느끼고 있었다.
+For thousands of years, a mysterious melody has mesmerized the guardian. After a millennia of slumber, the guardian became confused about what he had been protecting all these years, and began to suspect that he might be the one who has been sealed and hidden away.
+*/
+ MSG_QUEST_INFO_04 = 0x9b5,
+/*20130626 to latest
+비프로스트의 통로는 이제 미궁숲 뿐. 근원조차 알 수 없는 그곳을 무사히 통과 한 사람은 지금까지 아무도 없었다.
+Now, the only way to get to Bifrost is through the Labyrinth Forest. Nobody knows how the forest came to exist, and nobody has ever come out of it alive...
+20130807 to 20130814
+유혹의 노랫말이 최고조에 이르렀을 때, 지상의 끝 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 거대한 균열이 생겨났고, 그로 인해 두 세계간의 왕래가 끊기면서 사람들은 큰 불편을 겪게 되었다.
+When the melody reached its peak, a giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim. As a result, the two worlds were cut off from each other, causing a big problem for the people.
+*/
+ MSG_QUEST_INFO_05 = 0x9b6,
+/*20130626 to latest
+숱한 모험가들을 집어 삼킨 혼돈의 지옥, 미궁숲은 그 속을 방황하는 이름 모를 여인의 마음처럼 더욱 깊고 혼란스럽게 확장되고 있었다.
+Swallowed countless adventurers to put a hell of confusion, wandering in the forest labyrinth of nowhere, like the heart of a woman was being extend deeper confusion.
+20130807 to 20130814
+비프로스트의 통로는 이제 미궁숲 뿐. 근원조차 알 수 없는 그곳을 무사히 통과 한 사람은 지금까지 아무도 없었다.
+Now, the only way to get to Bifrost is through the Labyrinth Forest. Nobody knows how the forest came to exist, and nobody has ever come out of it alive...
+*/
+ MSG_QUEST_INFO_06 = 0x9b7,
+#endif
+#if PACKETVER >= 20130717
+/*20130717 to latest
+숫자만 입력 가능합니다.
+You can enter only numbers.
+20130807 to 20130814
+숱한 모험가들을 집어 삼킨 혼돈의 지옥, 미궁숲은 그 속을 방황하는 이름 모를 여인의 마음처럼 더욱 깊고 혼란스럽게 확장되고 있었다.
+Swallowed countless adventurers to put a hell of confusion, wandering in the forest labyrinth of nowhere, like the heart of a woman was being extend deeper confusion.
+*/
+ MSG_BANK_CHECK_NUM = 0x9b8,
+#endif
+#if PACKETVER >= 20130724
+/*20130724 to latest
+교환창 또는 상점이 활성화 된 상태에서는 입출금을 하실수 없습니다.
+Exchange or store window is active and can not register the withdrawal.
+20130807 to 20130814
+숫자만 입력 가능합니다.
+You can enter only numbers.
+*/
+ MSG_BANK_PROHIBIT = 0x9b9,
+#endif
+#if PACKETVER >= 20130731
+/*20130731 to latest
+바로가기
+Go to
+20130807 to 20130814
+교환창 또는 상점이 활성화 된 상태에서는 입출금을 하실수 없습니다.
+Exchange or store window is active and can not register the withdrawal.
+*/
+ MSG_QUEST_INFO_00 = 0x9ba,
+/*20130731 to latest
+아이템 비교
+Item Compare
+20130807 to 20130814
+바로가기
+Go to
+*/
+ MSG_ITEM_COMPARISON = 0x9bb,
+#endif
+#if PACKETVER >= 20130807
+/*20130807 to 20130814
+아이템 비교
+Item Compare
+20130821 to latest
+현재 장착하려고 하는 총기가 장착하고 있는 탄환에 맞지 않습니다
+Now you are trying to mount the gun equipped with bullet does not meet
+*/
+ MSG_WRONG_GUN = 0x9bc,
+/*20130807 to 20130814
+현재 장착하려고 하는 총기가 장착하고 있는 탄환에 맞지 않습니다
+Now you are trying to mount the gun equipped with bullet does not meet
+20130821 to latest
+현재 장착하려고 하는 탄환이 장착하고 있는 총기와 맞지 않습니다
+Now you are trying to mount the guns and bullets will not fit mounted
+*/
+ MSG_WRONG_BULLET = 0x9bd,
+/*20130807 to 20130814
+현재 장착하려고 하는 탄환이 장착하고 있는 총기와 맞지 않습니다
+Now you are trying to mount the guns and bullets will not fit mounted
+20130821 to latest
+판매할 아이템을 등록하지 않았습니다. 판매하실 아이템을 등록해 주세요
+Has not registered to sell the item. Please register to sell the item
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADD_GOODS = 0x9be,
+#endif
+#if PACKETVER >= 20130821
+/*20130821 to latest
+ITEM
+*/
+ MSG_ITEM_IN_MAIL_SYSTEM = 0x9bf,
+#endif
+#if PACKETVER >= 20130828
+/*20130828 to 20130911
+길드 창고를 이용할 수 없습니다. 잠시 후 이용해주세요.
+20130917 to latest
+길드 창고를 이용할 수 없습니다.
+Guild storage is not available.
+*/
+ MSG_GUILD_STORAGE_OPEN_ERROR = 0x9c0,
+/*20130828 to latest
+길드에 가입되어 있지 않습니다. 가입 후 이용해주세요.
+Guild is not subscribed to. After signing up, please use
+*/
+ MSG_GUILD_STORAGE_OPEN_NO_JOIN_GUILD = 0x9c1,
+/*20130828 to latest
+다른 길드원이 사용중입니다. 잠시 후 이용해주세요.
+Two other guild members are in use. Please use it after a while.
+*/
+ MSG_GUILD_STORAGE_WARNING_USING_ANOTHER_MEMBER = 0x9c2,
+/*20130828 to latest
+창고권한
+Storage Permission
+*/
+ MSG_GUILD_STORAGE_PERMISSON = 0x9c3,
+/*20130828 to latest
+길드창고
+Guild Storage
+*/
+ MSG_GUILD_STORAGE_TITLE = 0x9c4,
+/*20130828 to 20130828
+길드창고의 사용 권한이 없습니다. 길드 마스터에게 요청하세요.
+20130904 to latest
+길드창고의 사용 권한이 없습니다.
+You do not have permission to use guild storage.
+*/
+ MSG_GUILD_STORAGE_PERMISSON_WARNING_MSG = 0x9c5,
+#endif
+#if PACKETVER >= 20130917
+/*20130917 to latest
+한정판매 등록창
+Limited Sale Registration Window
+*/
+ MSG_BARGAINSALE_TOOLWND_TITLE = 0x9c6,
+/*20130917 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NAME = 0x9c7,
+/*20130917 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NUMBER = 0x9c8,
+/*20130917 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_COUNT = 0x9c9,
+/*20130917 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_STARTTIME = 0x9ca,
+/*20130917 to latest
+판매할 시간
+Time to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_PERIODTIME = 0x9cb,
+/*20130917 to latest
+판매할 갯수를 입력해 주세요
+Please enter number you want to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_COUNT_MSG = 0x9cc,
+/*20130917 to latest
+판매 시작시간을 입력해 주세요
+Enter start time of sale
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_STARTTIME_MSG = 0x9cd,
+/*20130917 to latest
+판매 시작시간의 범위가 맞지 않습니다
+Start time does not match the scope of sales.
+*/
+ MSG_BARGAINSALE_TOOLWND_WRONG_RANGE_MSG = 0x9ce,
+/*20130917 to latest
+판매할 시간을 입력해 주세요
+Please enter the time
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_PERIODTIME_MSG = 0x9cf,
+/*20130917 to latest
+Item DB Name을 입력해 주세요
+Please enter the Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_ITEMDBNAME_MSG = 0x9d0,
+/*20130917 to latest
+Item ID 조회에 실패하였습니다. 확인 후 다시 시도해 주시기 바랍니다
+Item ID lookup failed. Please try again later
+*/
+ MSG_BARGAINSALE_TOOLWND_ITEMID_CHECK_FAILED_MSG = 0x9d1,
+/*20130917 to latest
+>> ItemName : %s / Price : %dc / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName: %s / Price: %dc / Quantity: %d / TimeOfSale: %dMonth:%dDay:%dMinute:%dSecond ~ %dMonth:%dDay:%dMinute:%dSecond
+*/
+ MSG_BARGAINSALE_TOOLWND_RESULT_FORMAT = 0x9d2,
+/*20130917 to latest
+등록에 성공하였습니다
+Registration successful
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_SUCCESS_MSG = 0x9d3,
+/*20130917 to latest
+등록에 실패하였습니다. 다시 시도해 주시기 바랍니다.
+Registration failure. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_FAILED_MSG = 0x9d4,
+/*20130917 to latest
+이미 등록된 아이템이 있습니다. 다시 시도해 주시기 바랍니다.
+Item has already been registered. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_ALREADY_REGISTERED_MSG = 0x9d5,
+/*20130917 to latest
+아이템 삭제에 실패 하였습니다. 다시 시도해 주시기 바랍니다.
+Failed to delete the item. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_FAILED_MSG = 0x9d6,
+/*20130917 to latest
+%s 아이템이 삭제되었습니다.
+%s item has been deleted.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_SUCCESS_MSG = 0x9d7,
+/*20130917 to latest
+특가
+Special
+*/
+ MSG_BARGAINSALE_CASHSHOP_TAB_NAME = 0x9d8,
+/*20130917 to latest
+한정판매 아이템 판매수량 갱신
+Sales limited sale item update
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_BTN_TOOLTIP = 0x9d9,
+/*20130917 to latest
+판매종료
+Discontinued
+*/
+ MSG_BARGAINSALE_CASHSHOP_TIMER = 0x9da,
+/*20130917 to latest
+수량갱신이 필요합니다
+Quantity update is required
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_MSG = 0x9db,
+/*20130917 to latest
+재고가 부족하여 %d 개 만큼만 구입합니다
+The %d is out of stock or to buy as much as
+*/
+ MSG_BARGAINSALE_CASHSHOP_CHECK_COUNT_MSG = 0x9dc,
+/*20130917 to latest
+%s 아이템의 특가판매가 시작되었습니다
+%s Items are on sale
+*/
+ MSG_BARGAINSALE_START_MSG = 0x9dd,
+/*20130917 to latest
+%s 아이템의 매진 또는 판매시간만료로 인해 한정판매가 종료되었습니다
+%s time-out or sale of the items sold has been shut down due to the limited sales
+*/
+ MSG_BARGAINSALE_CLOSE_MSG = 0x9de,
+/*20130917 to latest
+/한정판매
+/limitedsale
+*/
+ MSG_BARGAINSALE_TOOLWND_CALL = 0x9df,
+#endif
+#if PACKETVER >= 20131002
+/*20131002 to latest
+http://www.ragnarokeurope.com/news/home-r70.html
+*/
+ MSG_FRANCE_CASHSHOP_URL = 0x9e0,
+/*20131002 to latest
+http://www.ragnarokeurope.com/index.php?rubrique=70&Steam
+*/
+ MSG_FRANCE_CASHSHOP_URL_STEAM = 0x9e1,
+#endif
+#if PACKETVER >= 20131016
+/*20131016 to latest
+구입에 성공한 품목
+Item purchase successful
+*/
+ MSG_PARA_RESULT_TITLE = 0x9e2,
+/*20131016 to latest
+주문량이 재고량을 초과하였습니다.
+You do not have enough items.
+*/
+ MSG_PARA_WRONG_PURCHASE_COUNT_MSG = 0x9e3,
+/*20131016 to latest
+초대할수 없는 케릭터 이름입니다.
+Name of the character that cannot be invited.
+*/
+ MSG_PARTY_INVITE = 0x9e4,
+/*20131016 to latest
+길드초대할수 없는 케릭터 이름입니다.
+You cannot invite the character to the guild.
+*/
+ MSG_GUILD_INVITE = 0x9e5,
+/*20131016 to latest
+일부 품목은 이미 판매되어 구입에 실패하였습니다.
+Item already Sold,Purchase Failed.
+*/
+ MSG_PARA_PURCHASE_ITEM_FAIL = 0x9e6,
+#endif
+#if PACKETVER >= 20131030
+/*20131030 to latest
+현재 위치에서 워프 장소를 기억 할 수 없습니다.
+The warp spot cannot be memorized in current position.
+*/
+ MSG_NOWARPSKILL2 = 0x9e7,
+/*20131030 to latest
+무게가 초과되어 아이템을 구매할 수 없습니다.
+Cannot purchase item, You exceeded the weight.
+*/
+ MSG_PARA_PURCHASE_ITEM_WEIGHT = 0x9e8,
+/*20131030 to latest
+No.
+*/
+ MSG_GUILD_STORAGE_NUMBER = 0x9e9,
+/*20131030 to latest
+아이템
+Item
+*/
+ MSG_GUILD_STORAGE_ITEM = 0x9ea,
+/*20131030 to latest
+개수
+Number
+*/
+ MSG_GUILD_STORAGE_ITEM_COUNT = 0x9eb,
+/*20131030 to latest
+이름
+Name
+*/
+ MSG_GUILD_STORAGE_USER_NAME = 0x9ec,
+/*20131030 to latest
+시간
+Time
+*/
+ MSG_GUILD_STORAGE_LOG_TIME = 0x9ed,
+/*20131030 to latest
+입/출
+Input/Output
+*/
+ MSG_GUILD_STORAGE_ITEM_IN_OUT = 0x9ee,
+/*20131030 to latest
+로그가 존재하지 않습니다.
+Log does not exist.
+*/
+ MSG_GUILD_STORAGE_LOG_FINISH = 0x9ef,
+/*20131030 to latest
+전 체
+Entire
+*/
+ MSG_GUILD_STORAGE_LOG_ALL = 0x9f0,
+/*20131030 to latest
+넣 기
+Insert Symbol
+*/
+ MSG_GUILD_STORAGE_LOG_IN = 0x9f1,
+/*20131030 to latest
+빼 기
+Remaining Time
+*/
+ MSG_GUILD_STORAGE_LOG_OUT = 0x9f2,
+#endif
+#if PACKETVER >= 20131106
+/*20131106 to latest
+길드 창고 내역
+Guild Storage Logs
+*/
+ MSG_GUILD_STORAGE_LOG_WND_NAME = 0x9f3,
+/*20131106 to latest
+내역은 최근 100개만 표시됩니다.
+100 entries are displayed.
+*/
+ MSG_GUILD_STORAGE_LOG_CAUTION = 0x9f4,
+#endif
+#if PACKETVER >= 20131120
+/*20131120 to 20131120
+%s : +%d
+20131127 to latest
+길드창고의 사용 시간 2분이 경과되어 자동으로 종료됩니다.
+Guild Storage is open only for 2 minutes, and will close automatically.
+*/
+ MSG_GUILD_STORAGE_CLOSE_TIMEOUT = 0x9f5,
+#endif
+#if PACKETVER >= 20131204
+/*20131204 to latest
+Incorrect GameSamba ID. Please Try Again.
+*/
+ MSG_INCORRECT_GAMESAMBEID = 0x9f6,
+/*20131204 to latest
+%s [%d옵션] : %d 개
+%s [%d Option]: %d Quantity
+*/
+ MSG_EA5 = 0x9f7,
+#endif
+#if PACKETVER >= 20131211
+/*20131211 to latest
+코인이 필요합니다.
+Requires a Coin.
+*/
+ MSG_USESKILL_FAIL_COINTS = 0x9f8,
+/*20131211 to latest
+코인이 %d 개가 필요합니다.
+%d Coins are required.
+*/
+ MSG_USESKILL_FAIL_COINTS_NUM = 0x9f9,
+/*20131211 to latest
+개틀링건 계열의 총기류를 장착한 상태여야 합니다.
+Gatling Gun should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GATLING = 0x9fa,
+/*20131211 to latest
+샷건 계열의 총기류를 장착한 상태여야 합니다.
+Shotguns should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_SHOTGUN = 0x9fb,
+/*20131211 to latest
+라이플 계열의 총기류를 장착한 상태여야 합니다.
+Rifle should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_RIFLE = 0x9fc,
+/*20131211 to latest
+리볼버 계열의 총기류를 장착한 상태여야 합니다.
+Pair of Revolver should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_HANDGUN = 0x9fd,
+/*20131211 to latest
+성속성 블릿을 장착해야 합니다
+[Silver Bullet] weapon class must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_PROPERTY_SAINT_BULLET = 0x9fe,
+/*20131211 to latest
+아이템 판매 내역
+Item Sell History
+*/
+ MSG_MERCHANT_SOLD_ITEM_LOG = 0x9ff,
+/*20131211 to latest
+아이템 구매 내역
+Item Purchase History
+*/
+ MSG_MERCHANT_ITEM_BUY_LOG = 0xa00,
+#endif
+#if PACKETVER >= 20131218
+/*20131218 to latest
+그레네이드런쳐 계열의 총기류를 장착한 상태여야 합니다.
+Grenade Launcher should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GRANADE = 0xa01,
+/*20131218 to latest
+[히트배럴],[매드니스 캔슬러],[플래티넘 알터] 의 효과들은 중첩하여 사용할 수 없습니다.
+[Heat barrel],[Last Stand],[Platinum Alter] cannot be used while sitting.
+*/
+ MSG_FAIL_DUPLICATE_HEAT_BARREL_GS_MADNESSCANCEL_P_ALTER = 0xa02,
+#endif
+#if PACKETVER >= 20131223
+/*20131223 to latest
+현재 맵에서는 사용할 수 없는 스킬입니다.
+Cannot use skill in this map.
+*/
+ MSG_USESKILL_FAIL_MAP = 0xa03,
+#endif
+#if PACKETVER >= 20140108
+/*20140108 to latest
+길드 창고를 이용중인 경우 창고의 모든 아이템이 사라지게 됩니다.
+If you are using a guild storage, all items inside it will disappear.
+*/
+ MSG_GUILD_STORAGE_WARNING = 0xa04,
+#endif
+#if PACKETVER >= 20140115
+/*20140115 to latest
+http://ragnarok.gamesamba.com/paytest.html
+http://ragnarok.gamesamba.com/
+*/
+ MSG_AMERICA_CASHSHOP_URL_GAMESAMBA = 0xa05,
+/*20140115 to latest
+로그인을 위해 패스워드를 입력해주세요.
+Please enter a password to login.
+*/
+ MSG_SECOND_PASSWORD_INFO_4 = 0xa06,
+#endif
+#if PACKETVER >= 20140129
+/*20140129 to latest
+펫 진화
+Pet Evolution
+*/
+ MSG_PET_EVOLUTION = 0xa07,
+/*20140129 to latest
+진화 - %s
+Evolution - %s
+*/
+ MSG_PET_EVOLUTION_WITH_PET_NAME = 0xa08,
+/*20140129 to latest
+진화에는 다음의 재료가 필요합니다.
+Evolution requires the following ingredients:
+*/
+ MSG_PET_EVOLUTION_NEED_ITEM = 0xa09,
+/*20140129 to latest
+진화 하시겠습니까?
+Are you sure you want to evolve your pet?
+*/
+ MSG_DO_YOU_WANT_TO_EVOLVE_PET = 0xa0a,
+/*20140129 to latest
+알 수 없는 오류
+Unknown Error
+*/
+ MSG_PET_EVOLUTION_FAIL_UNKNOWN = 0xa0b,
+/*20140129 to latest
+소환된펫을 갖고 있지 않습니다.
+Pet Cannot be hatched.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOTEXIST_CALLPET = 0xa0c,
+/*20140129 to latest
+요청한 것이 펫알이 아닙니다.
+It is not requested petal.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOT_PETEGG = 0xa0d,
+/*20140129 to 20140205
+진화가 불가능한 요청입니다.
+20140212 to latest
+진화 재료가 부족합니다.
+Evolution material is low.
+*/
+ MSG_PET_EVOLUTION_FAIL_RECIPE = 0xa0e,
+/*20140129 to latest
+진화에 필요한 재료가 부족합니다.
+Insufficient materials for evolution.
+*/
+ MSG_PET_EVOLUTION_FAIL_MATERIAL = 0xa0f,
+/*20140129 to latest
+친밀도가 절친인 상태에서만 진화가 가능합니다.
+Loyal Intimacy is required to evolve.
+*/
+ MSG_PET_EVOLUTION_FAIL_RG_FAMILIAR = 0xa10,
+#endif
+#if PACKETVER >= 20140212
+/*20140212 to 20170830
+자동 먹이 주기
+20170906 to latest
+펫 자동 먹이 주기
+Automatic feeding
+*/
+ MSG_PET_AUTO_FEEDING = 0xa11,
+/*20140212 to latest
+펫에게 먹이를 주었습니다. '%s' 잔여량 %d개
+Feeding the pet. %d '%d' remaining
+*/
+ MSG_PET_AUTO_FEEDING_REST = 0xa12,
+/*20140212 to 20170830
+자동 먹이 주기 활성화 On
+20170906 to latest
+펫 자동 먹이 주기 활성화 On
+Automatic feeding turned On
+*/
+ MSG_PET_AUTO_FEEDING_ON = 0xa13,
+/*20140212 to 20170830
+자동 먹이 주기 활성화 Off
+20170906 to latest
+펫 자동 먹이 주기 활성화 Off
+Automatic feeding turned Off
+*/
+ MSG_PET_AUTO_FEEDING_OFF = 0xa14,
+/*20140212 to latest
+갱신
+Update
+*/
+ MSG_REFRESH = 0xa15,
+/*20140212 to 20140702
+%d 분전
+20140709 to latest
+%d 분 전
+%d minutes ago
+*/
+ MSG_TIME_LINE_MINUTE = 0xa16,
+/*20140212 to 20140702
+%d 시간전
+20140709 to latest
+%d 시간 전
+%d hours ago
+*/
+ MSG_TIME_LINE_HOUR = 0xa17,
+/*20140212 to 20140702
+%d 일전
+20140709 to latest
+%d 일 전
+%d days ago
+*/
+ MSG_TIME_LINE_DAY = 0xa18,
+#endif
+#if PACKETVER >= 20140319
+/*20140319 to latest
+%d%% ( Premium %d%% + %s Server )
+%d%%% ( Premium %d%%% + %s Server )
+*/
+ MSG_BASIC_EXP_MSG_PH = 0xa19,
+#endif
+#if PACKETVER >= 20140326
+/*20140326 to latest
+우편 발송
+Mailed
+*/
+ MSG_SEND_MAIL = 0xa1a,
+/*20140326 to latest
+메일이 전송되었습니다.
+Your mail has been sent.
+*/
+ MSG_MAIL_SENT = 0xa1b,
+/*20140326 to latest
+아이템이 인벤토리로 이동되었습니다.
+This item has been moved to the inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_SUCCEED = 0xa1c,
+/*20140326 to latest
+아이템 받기가 실패하였습니다.
+Failed to get items.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_FAILED = 0xa1d,
+/*20140326 to latest
+인벤토리를 비워주세요
+Please empty your inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_OVERWEIGHT = 0xa1e,
+/*20140326 to latest
+제니를 받았습니다.
+Zeny received.
+*/
+ MSG_GET_ZENY_FROM_MAIL_SUCCEED = 0xa1f,
+/*20140326 to latest
+제니 받기가 실패하였습니다.
+Failed to get zeny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_FAILED = 0xa20,
+/*20140326 to latest
+제니의 한계치를 넘었습니다.
+Exceeded the limits of zenny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_OVERAMOUNT = 0xa21,
+/*20140326 to latest
+아이템 첨부 성공
+Items attached success
+*/
+ MSG_SET_ITEMS_TO_MAIL_SUCCEED = 0xa22,
+/*20140326 to latest
+받는 사람의 이름이 반드시 들어가야 합니다.
+The name of the recipient must be included.
+*/
+ MSG_INVALID_MAIL_RECIEVER_INFO = 0xa23,
+/*20140326 to 20140416
+제목의 길이는 4자이상 이어야 합니다.
+20140423 to 20141001
+제목의 길이는 4자이상 16자 이하여야 합니다.
+20141008 to latest
+제목의 길이는 한글 2자~25자, 영문 4자~50자 이어야 합니다.
+The length of the title must be 4 to 50 characters long.
+*/
+ MSG_INVALID_MAIL_TITLE_INFO = 0xa24,
+/*20140326 to latest
+메일 전송이 실패하였습니다.
+Mail delivery failed.
+*/
+ MSG_FAILED_SEND_MAIL = 0xa25,
+/*20140326 to latest
+적절하지 못한 아이템으로 전송 실패하였습니다.
+Transmission has failed to inappropriate items.
+*/
+ MSG_FAILED_SEND_MAIL_ITEM = 0xa26,
+/*20140326 to latest
+받는 사람의 정보가 존재하지 않습니다.
+Information of the recipient does not exist.
+*/
+ MSG_FAIELD_SEND_MAIL_TO = 0xa27,
+#endif
+#if PACKETVER >= 20140402
+/*20140402 to latest
+%s [%d옵션]
+%s [%d Option]
+*/
+ MSG_EA6 = 0xa28,
+/*20140402 to latest
+레벨은 1~%d 사이의 숫자를 입력해 주세요.
+Level, enter a number between 1 and %d.
+*/
+ MSG_PARTY_BOOKING_ERR5R2 = 0xa29,
+#endif
+#if PACKETVER >= 20140409
+/*20140409 to latest
+소지창의 여유공간을 확보해주세요.
+Please free the window possessing space.
+*/
+ MSG_ITEM_WND_OVERFULL = 0xa2a,
+/*20140409 to 20140416
+수신자의 메일 보관 용량이 초과되었습니다.
+20140423 to latest
+메일 보내기 횟수가 초과되었습니다.
+Sending mail count exceeded.
+*/
+ MSG_FAILED_MAIL_LIMIT_CNT = 0xa2b,
+#endif
+#if PACKETVER >= 20140416
+/*20140416 to latest
+메일을 열 수 없습니다.
+You can not open the mail.
+*/
+ MSG_FAILED_TO_WRITE_MAIL = 0xa2c,
+/*20140416 to latest
+You are currently joined in CLan !!
+You currently belong to a clan.
+*/
+ MSG_JOINED_IN_CLAN = 0xa2d,
+/*20140416 to latest
+골드 PC방 마일리지 정보
+Gold PC rooms mileage information
+*/
+ MSG_GOLDPCCAFE_MILEAGE = 0xa2e,
+#endif
+#if PACKETVER >= 20140423
+/*20140423 to latest
+펫 액세서리를 해제해야 진화가 가능합니다.
+Unequip pet accessories first to start evolution
+*/
+ MSG_PET_EVOLUTION_FAIL_PET_ACC_OFF = 0xa2f,
+/*20140423 to 20140430
+ / %d 분후
+20140508 to 20140702
+%d 분후
+20140709 to latest
+%d 분 후
+%d minutes later
+*/
+ MSG_TIME_LINE_MINUTE2 = 0xa30,
+/*20140423 to 20140430
+ / %d 시간후
+20140508 to 20140702
+%d 시간후
+20140709 to latest
+%d 시간 후
+%d hours later
+*/
+ MSG_TIME_LINE_HOUR2 = 0xa31,
+/*20140423 to 20140430
+ / %d 일후
+20140508 to 20140702
+%d 일후
+20140709 to latest
+%d 일 후
+%d days later
+*/
+ MSG_TIME_LINE_DAY2 = 0xa32,
+/*20140423 to latest
+확인 버튼을 눌러 C-CODE를 확인하세요.
+Press the OK button to confirm the C-CODE.
+*/
+ MSG_INVALID_CCODE_INFO = 0xa33,
+/*20140423 to latest
+첨부된 물품을 획득 후 삭제가 가능합니다.
+After obtaining the attached article can be deleted.
+*/
+ MSG_FAILED_DELETE_MAIL = 0xa34,
+/*20140423 to latest
+현재 보유 제니 보다 많은 제니를 보낼 수 없습니다.
+You can not send any more zeny.
+*/
+ MSG_FAILED_SEND_MAIL_ZENY = 0xa35,
+/*20140423 to latest
+수수료 : %s Zeny
+Fee: %s Zeny
+*/
+ MSG_SEND_MAIL_COMMISSION = 0xa36,
+/*20140423 to latest
+받는 사람의 이름이 존재하지 않습니다.
+The recipient's name does not exist.
+*/
+ MSG_FAILE_MAIL_RECIEVER_INFO = 0xa37,
+#endif
+#if PACKETVER >= 20140430
+/*20140430 to latest
+E X P : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_EXPMSG = 0xa38,
+/*20140430 to latest
+DROP : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DROPMSG = 0xa39,
+/*20140430 to latest
+DEATH : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DEATHMSG = 0xa3a,
+#endif
+#if PACKETVER >= 20140514
+/*20140514 to 20140528
+보유 가능한 최대 마일리지 : %d
+20140605 to latest
+골드 PC방 마일리지는 최대 %d점까지 모을 수 있습니다.
+You can accumulate points of PC Gold-club up to %d points maximum.
+*/
+ MSG_MILEAGE_HELP = 0xa3b,
+#endif
+#if PACKETVER >= 20140521
+/*20140521 to 20140521
+아이템 버리기가 불 가능한 서버 입니다.
+Items discard is imposible in server.
+20140528 to latest
+해당 서버에서 사용 할 수 없는 기능 입니다
+This function can not be used on the server.
+*/
+ MSG_RESTRAINT_OF_TRADE_1 = 0xa3c,
+/*20140521 to latest
+수래 이용이 불 가능한 서버 입니다.
+Imposible to use in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_2 = 0xa3d,
+/*20140521 to latest
+옥션 이용이 불 가능한 서버 입니다.
+The auction is not available in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_3 = 0xa3e,
+/*20140521 to latest
+거래가 불 가능한 서버 입니다.
+The deal is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_4 = 0xa3f,
+/*20140521 to 20140521
+아이템 편지 보내기가 불 가능한 서버 입니다.
+20140528 to latest
+아이템 버리기가 불 가능한 서버 입니다.
+Items discard is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_5 = 0xa40,
+/*20140521 to latest
+상점 판매 기능을 사용할수 없습니다.
+Stores selling features are not available.
+*/
+ MSG_RESTRAINT_OF_TRADE_6 = 0xa41,
+/*20140521 to latest
+소환물의 SP가 부족합니다.
+The SP's summoned enough.
+*/
+ MSG_USESKILL_FAIL_SUMMON_SP_INSUFFICIENT = 0xa42,
+#endif
+#if PACKETVER >= 20140528
+/*20140528 to 20140702
+Weight : %s/%s
+20140709 to latest
+%s/%s
+*/
+ MSG_SEND_MAIL_WEIGHT = 0xa43,
+/*20140528 to latest
+메일 내용의 최대 길이는 1K 이하 입니다.
+The maximum length of the message content is 1K.
+*/
+ MSG_INVALID_MAIL_CONTENTS_INFO = 0xa44,
+/*20140528 to latest
+아이템 첨부 실패
+Failed to attach an item.
+*/
+ MSG_SET_ITEMS_TO_MAIL_FAILED = 0xa45,
+/*20140528 to latest
+메일에 첨부할수 있는 아이템의 무게가 초과되었습니다.
+The weight of the items that can be attached to mail has been exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVER_WEIGHT = 0xa46,
+#endif
+#if PACKETVER >= 20140611
+/*20140611 to latest
+이미 서비스 중입니다. 잠시 후 다시 시도해 주세요.
+Is already in service. Please try again in a few minutes.
+*/
+ MSG_DYNAMICNPC_FAIL_DUPLICATENAME = 0xa47,
+#endif
+#if PACKETVER >= 20140618
+/*20140618 to 20140924
+환상의 룰렛창을 열 수 없습니다.
+20141001 to latest
+행운의 룰렛창을 열 수 없습니다.
+Unable to open the window of Lucky Roulette.
+*/
+ MSG_FAILED_OPEN_ROULLETTE = 0xa48,
+/*20140618 to 20140924
+환상의 룰렛창을 닫을 수 없습니다.
+20141001 to latest
+행운의 룰렛창을 닫을 수 없습니다.
+Unable to close the window of the Lucky Roulette.
+*/
+ MSG_FAILED_CLOSE_ROULLETTE = 0xa49,
+/*20140618 to 20140924
+환상의 룰렛을 시작 할 수 없습니다.
+20141001 to latest
+행운의 룰렛을 시작 할 수 없습니다.
+You can not start a roulette wheel of fortune.
+*/
+ MSG_FAILED_GENERATE_ROULLETTE = 0xa4a,
+/*20140618 to 20140924
+환상의 룰렛을 시작하기 위해서는 포인트가 필요합니다.
+20141001 to latest
+행운의 룰렛을 시작하기 위해서는 포인트가 필요합니다.
+Points is required to play Lucky Roulette.
+*/
+ MSG_NOT_ENOUGH_ROULLETTE_POINT = 0xa4b,
+/*20140618 to latest
+당첨된 아이템을 수령할 수 없습니다.
+You can not receive a winning items.
+*/
+ MSG_FAILED_RECV_ITEM = 0xa4c,
+#endif
+#if PACKETVER >= 20140625
+/*20140625 to latest
+인벤토리에 아이템 개수가 초과되었습니다.
+The number of items in the inventory has been exceeded.
+*/
+ MSG_FAILED_RECV_ITEM_OVERCOUNT = 0xa4d,
+/*20140625 to latest
+무게가 초과하였습니다. 소지창의 여유공간을 확보해주세요.
+The weight has been exceeded. Please free up the possesion window.
+*/
+ MSG_FAILED_RECV_ITEM_OVERWEIGHT = 0xa4e,
+/*20140625 to latest
+노점 개설 실패.
+Failed to open stalls.
+*/
+ MSG_MERCHANTSHOP_MAKING_FAIL = 0xa4f,
+/*20140625 to latest
+룰렛이 돌고 있습니다. 경품을 확인 후에 다시 시도해주세요.
+The roulette wheel is spinning. Please try again after checking with prizes.
+*/
+ MSG_FAILED_CLOSE_ROULLETTEWND = 0xa50,
+#endif
+#if PACKETVER >= 20140702
+/*20140702 to 20140917
+환상의 룰렛
+20140924 to latest
+행운의 룰렛
+Lucky Roulette
+*/
+ MSG_ROULLETTE_WND = 0xa51,
+/*20140702 to latest
+아이템 판매 시 소리로 알림
+Notify when item sell out
+*/
+ MSG_SOUNDEFFECT_ITEMSELLWND = 0xa52,
+#endif
+#if PACKETVER >= 20140709
+/*20140709 to latest
+수수료를 확인해주세요.
+Please check the fees.
+*/
+ MSG_FAILED_SEND_MAIL_ITEMS = 0xa53,
+/*20140709 to 20140716
+유저이름확인
+20140723 to latest
+유저이름 확인
+Verify user name
+*/
+ MSG_CHECK_USER_NAME = 0xa54,
+/*20140709 to latest
+삭제 예정
+Schedule deletion
+*/
+ MSG_DELETE_DUE_DATE = 0xa55,
+#endif
+#if PACKETVER >= 20140723
+/*20140723 to latest
+달성과제
+Achievable challenge
+*/
+ MSG_ACHIEVEMENT_SYSTEM = 0xa56,
+/*20140723 to latest
+달성총점
+Achieve overall
+*/
+ MSG_ACHIEVEMENT_TOTAL_SCORE = 0xa57,
+/*20140723 to latest
+달성등급
+Achieve rank
+*/
+ MSG_ACHIEVEMENT_GRADE = 0xa58,
+/*20140723 to 20150217
+다음 보상박스까지 [%5d]점
+20150225 to latest
+다음 달성등급까지 [%5d]점
+The following compensation box until [% 5d] point
+*/
+ MSG_ACHIEVEMENT_SCORE_REQUIRED_TO_REWARD = 0xa59,
+/*20140723 to 20140723
+개요
+Overview
+20140730 to latest
+진척상황
+Progress
+*/
+ MSG_ACHIEVEMENT_SUMMARY_TITLE = 0xa5a,
+/*20140723 to 20140723
+일반
+General
+20140730 to latest
+최근 달성 업적
+Recent Achievements
+*/
+ MSG_ACHIEVEMENT_RECENT_ACHIEVEMENT = 0xa5b,
+/*20140723 to 20140723
+캐릭터
+Role
+20140730 to 20140924
+개다래 열매 품목
+20141001 to latest
+仙貝 품목
+Cracker Item
+*/
+ MSG_CASH_GEDARE1 = 0xa5c,
+/*20140723 to 20140723
+행동
+Action
+20140730 to 20140924
+개다래 열매 : %d / %d GD
+20141001 to latest
+仙貝 : %d / %d
+Cracker : %d / %d
+*/
+ MSG_CASH_GEDARE2 = 0xa5d,
+/*20140723 to 20140723
+전투
+Battle
+20140730 to 20140924
+개다래 열매가 부족합니다.
+20141001 to latest
+仙貝가 부족합니다.
+Cracker is low.
+*/
+ MSG_CASH_GEDARE_FAIL_MONEY = 0xa5e,
+/*20140723 to 20140723
+모험
+Adventure
+20140730 to 20140924
+%s GD
+20141001 to latest
+%s
+*/
+ MSG_CASH_GEDARE_MONEY = 0xa5f,
+/*20140723 to 20140723
+결투
+Duel
+20140813 to latest
+개요
+Overview
+*/
+ MSG_ACHIEVEMENT_TAB_SUMMARY = 0xa60,
+/*20140723 to 20140723
+수련
+Lily
+20140813 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL = 0xa61,
+/*20140723 to 20140723
+퀘스트
+Quest
+20140813 to latest
+캐릭터
+Role
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_CHARACTER = 0xa62,
+/*20140723 to 20140723
+에피소드
+Episode
+20140813 to latest
+행동
+Action
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_ACTION = 0xa63,
+/*20140723 to 20140723
+이벤트
+Evt
+20140813 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_REST = 0xa64,
+/*20140723 to 20140723
+활동
+20140813 to latest
+모험
+Adventure
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE = 0xa65,
+/*20140723 to 20140723
+커뮤니티
+20140813 to latest
+룬미드가츠
+Rune Midgarts
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_RUNEMIDGARTS = 0xa66,
+/*20140723 to 20140723
+제련
+Refining
+20140813 to latest
+슈발츠발드
+Schwartzvald
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_SCHWARZWALD = 0xa67,
+/*20140723 to 20140723
+경제
+20140813 to latest
+아루나펠츠
+Arunafeltz
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ARUNAFELTZ = 0xa68,
+/*20140723 to 20140723
+생활
+20140813 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ANOTHERWORLD = 0xa69,
+/*20140723 to 20140723
+축제
+20140813 to latest
+로컬라이징
+Localizing
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_LOCALIZING = 0xa6a,
+/*20140723 to 20140723
+위업
+Feat
+20140813 to latest
+던전
+Dungeon
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_DUNGEON = 0xa6b,
+/*20140723 to 20140723
+달성한 과제
+Achieved challenge
+20140813 to latest
+전투
+Battle
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE = 0xa6c,
+/*20140723 to 20140723
+진척상황
+Progress
+20140813 to latest
+결투
+Duel
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_PVP = 0xa6d,
+/*20140723 to 20140723
+최근 달성 업적
+Recent Achievements
+20140813 to latest
+수련
+Lily
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_TRAINING = 0xa6e,
+#endif
+#if PACKETVER >= 20140813
+/*20140813 to latest
+퀘스트
+Quest
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST = 0xa6f,
+/*20140813 to latest
+에피소드
+Episode
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_EPISODE = 0xa70,
+/*20140813 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_GENERAL = 0xa71,
+/*20140813 to latest
+메모리얼
+Memorial
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL = 0xa72,
+/*20140813 to latest
+미드가르드
+Midgard
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_MIDGARD = 0xa73,
+/*20140813 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_ANOTHERWORLD = 0xa74,
+/*20140813 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_REST = 0xa75,
+/*20140813 to latest
+위업
+Feat
+*/
+ MSG_ACHIEVEMENT_TAB_ACHIEVEMENT = 0xa76,
+/*20140813 to latest
+달성한 과제
+Achieved challenge
+*/
+ MSG_ACHIEVEMENT_TAB_TOTAL = 0xa77,
+/*20140813 to latest
+더 이상 추가할 수 없습니다.
+You cannot add anymore.
+*/
+ MSG_FAIL_ADD_ACHIEVEMENT_TRACING = 0xa78,
+/*20140813 to latest
+< %s > 달성하였습니다.
+< %S > achieved.
+*/
+ MSG_NOTICE_COMPLETE_ACHIEVEMENT = 0xa79,
+#endif
+#if PACKETVER >= 20140827
+/*20140827 to latest
+only otp user login allow
+Only OTP users are allowed
+*/
+ MSG_OTPUSER_ONLY = 0xa7a,
+#endif
+#if PACKETVER >= 20140917
+/*20140917 to latest
+이 버튼을 누를 시, 지정된 상품을 받게되며 룰렛은 초기화 됩니다.
+When this button pressed, you will receive a specified initialized roulette item.
+*/
+ MSG_GET_ROULLETE_PRIZE = 0xa7b,
+/*20140917 to latest
+이 버튼을 누를 시, 깜빡이는 화살표의 라인부터 룰렛을 시작 합니다.
+When this button pressed, the flashing arrows from the lines of the roulette wheel begins.
+*/
+ MSG_NOTICE_NEXT_ROULLETE_STAGE = 0xa7c,
+/*20140917 to latest
+칭호
+Style
+*/
+ MSG_TITLE_EQUIPMENT = 0xa7d,
+/*20140917 to latest
+칭호 해제
+Title release
+*/
+ MSG_TAKEOFF_TITLE = 0xa7e,
+/*20140917 to latest
+길드 생성을 할 수 없는 지역입니다.
+Can't create a Guild in this area.
+*/
+ MSG_GUILD_MAKE_GUILD_NOT_PERMITTED_MAP = 0xa7f,
+/*20140917 to latest
+길드 해체를 할 수 없는 지역입니다.
+Can't disband a Guild in this area.
+*/
+ MSG_GUILD_DISORGANIZE_GUILD_NOT_PERMITTED_MAP = 0xa80,
+/*20140917 to latest
+길드 가입을 할 수 없는 지역입니다.
+Can't join a Guild in this area.
+*/
+ MSG_GUILD_JOIN_GUILD_NOT_PERMITTED_MAP = 0xa81,
+/*20140917 to latest
+길드 탈퇴를 할 수 없는 지역입니다.
+Can't leave a Guild in this area.
+*/
+ MSG_GUILD_LEAVE_GUILD_NOT_PERMITTED_MAP = 0xa82,
+/*20140917 to latest
+길드원 추방을 할 수 없는 지역입니다.
+Can't deport a Guild in this area.
+*/
+ MSG_GUILD_EXPEL_GUILD_NOT_PERMITTED_MAP = 0xa83,
+/*20140917 to latest
+길드직위 변경을 할 수 없는 지역입니다.
+Can't change a Guild title in this area
+*/
+ MSG_GUILD_POSITION_CHANGE_NOT_PERMITTED_MAP = 0xa84,
+/*20140917 to latest
+아이템 소지량을 5칸이상 비워주세요
+Please empty at least 5 amount of possession in item window.
+*/
+ MSG_NOT_ENOUGH_SPACE_IN_ITEM_BODY = 0xa85,
+/*20140917 to latest
+E X P : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_EXPMSG = 0xa86,
+/*20140917 to latest
+DROP : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DROPMSG = 0xa87,
+/*20140917 to latest
+DEATH : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DEATHMSG = 0xa88,
+/*20140917 to latest
+첨부할 수 있는 아이템의 갯수가 초과되었습니다.
+The number of items that can be attached is exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVERCOUNT = 0xa89,
+/*20140917 to latest
+아이템 구매 시 소리로 알림
+Notify when item purchased
+*/
+ MSG_SOUNDEFFECT_ITEMBUYWND = 0xa8a,
+#endif
+#if PACKETVER >= 20140924
+/*20140924 to latest
+첨부할 수 없는 아이템입니다.
+Unable to attach the items.
+*/
+ MSG_ID_A8B = 0xa8b,
+#endif
+#if PACKETVER >= 20141001
+/*20141001 to latest
+꽝에 당첨되었으므로 다음 상위 단계의 룰렛을 돌리실 수 없습니다.
+Because you can not win a slam room and turn the roulette of the next higher step.
+*/
+ MSG_ID_A8C = 0xa8c,
+/*20141001 to latest
+답장쓰기
+Replying
+*/
+ MSG_ID_A8D = 0xa8d,
+/*20141001 to latest
+내용읽기
+Read more
+*/
+ MSG_ID_A8E = 0xa8e,
+/*20141001 to latest
+메일삭제
+Delete message
+*/
+ MSG_ID_A8F = 0xa8f,
+/*20141001 to latest
+仙貝 : %d
+Crackers : %d
+*/
+ MSG_ID_A90 = 0xa90,
+/*20141001 to latest
+%s %s 仙貝
+%s %s crackers
+*/
+ MSG_ID_A91 = 0xa91,
+/*20141001 to latest
+仙貝
+Crackers
+*/
+ MSG_ID_A92 = 0xa92,
+/*20141001 to latest
+Total : %d 仙貝
+Total : %d Crackers
+*/
+ MSG_ID_A93 = 0xa93,
+/*20141001 to latest
+%d -> %s 仙貝
+%d -> %s Crackers
+*/
+ MSG_ID_A94 = 0xa94,
+/*20141001 to latest
+%s 仙貝
+%s Crackers
+*/
+ MSG_ID_A95 = 0xa95,
+/*20141001 to latest
+ Current 仙貝 : %s
+ Current Crackers : %s
+*/
+ MSG_ID_A96 = 0xa96,
+/*20141001 to latest
+ %s : %s 仙貝
+ %s : %s Crackers
+*/
+ MSG_ID_A97 = 0xa97,
+/*20141001 to latest
+%10s 仙貝
+%10s Crackers
+*/
+ MSG_ID_A98 = 0xa98,
+/*20141001 to latest
+Total : %s 仙貝
+Total : %s Crackers
+*/
+ MSG_ID_A99 = 0xa99,
+/*20141001 to latest
+※수수료 3% / 최소 1仙貝의 수수료 차감
+* Commission 3% / Minimum 1 Crackers comission deducted
+*/
+ MSG_ID_A9A = 0xa9a,
+/*20141001 to latest
+仙貝 입니다.
+The Crackers.
+*/
+ MSG_ID_A9B = 0xa9b,
+/*20141001 to latest
+^0000ff仙貝 이상^000000입니다.
+입력금액이 맞습니까?
+^0000ff more than crackers^000000Did you enter the correct amount?
+*/
+ MSG_ID_A9C = 0xa9c,
+/*20141001 to latest
+10억仙貝이상 안전 확인
+Over than 10billions secure check
+*/
+ MSG_ID_A9D = 0xa9d,
+/*20141001 to latest
+10억 仙貝 이상 입력하셔도 가격은 10억 仙貝로 판매됩니다.
+If you fill over 1 billion, the price will be automatically set as 10 billion Xianbei.
+*/
+ MSG_ID_A9E = 0xa9e,
+/*20141001 to latest
+9,999仙貝 이상 입력하셔도 가격은 9,999仙貝로 판매됩니다.
+If you fill over 9,999 Xianbei, the price will automatically set as 9,999 Xianbei.
+*/
+ MSG_ID_A9F = 0xa9f,
+/*20141001 to latest
+가격이 0 仙貝인 아이템이 존재 합니다. 상점을 열수 없습니다!
+There are items priced 0 Xianbei. You cannot open vending.
+*/
+ MSG_ID_AA0 = 0xaa0,
+/*20141001 to latest
+상대 캐릭터가 최대 보유 仙貝량을 초과하여 거래가 불가능 합니다.
+The opponent is over the Xianbei limit. Trade failed.
+*/
+ MSG_ID_AA1 = 0xaa1,
+/*20141001 to latest
+%s 아이템의 가격을 10억仙貝 이하로 입력해 주세요.
+Please fill out %s item price less than 1 billion Xianbei.
+*/
+ MSG_ID_AA2 = 0xaa2,
+/*20141001 to latest
+%s : %s 仙貝 => %s EA
+%s: %s Xianbei => %s ea
+*/
+ MSG_ID_AA3 = 0xaa3,
+/*20141001 to latest
+제한 금액 : %s 仙貝
+Limited price: %s Xianbei
+*/
+ MSG_ID_AA4 = 0xaa4,
+/*20141001 to latest
+%s %s 仙貝 %d 개
+%s %s %d Xianbei
+*/
+ MSG_ID_AA5 = 0xaa5,
+/*20141001 to latest
+%s %d개를 %d 仙貝에 판매 하였습니다. 수수료는 3%% 입니다.
+%d %s are sold. In total %d Xianbei. 3%% charge will be imposed.
+*/
+ MSG_ID_AA6 = 0xaa6,
+#endif
+#if PACKETVER >= 20141008
+/*20141008 to latest
+RODEX
+*/
+ MSG_ID_AA7 = 0xaa7,
+/*20141008 to latest
+SEND
+*/
+ MSG_ID_AA8 = 0xaa8,
+/*20141008 to latest
+RECEIVE
+*/
+ MSG_ID_AA9 = 0xaa9,
+#endif
+#if PACKETVER >= 20141015
+/*20141015 to latest
+메일 작성창을 닫아주세요.
+Please close the mail compose window.
+*/
+ MSG_ID_AAA = 0xaaa,
+#endif
+#if PACKETVER >= 20141022
+/*20141022 to latest
+서버접근거부(A)
+Server access denied(A)
+*/
+ MSG_ID_AAB = 0xaab,
+/*20141022 to latest
+서버접근거부(B)
+Server access denied(B)
+*/
+ MSG_ID_AAC = 0xaac,
+#endif
+#if PACKETVER >= 20141112
+/*20141112 to latest
+장착된 화살/탄환 을 해제해야합니다.
+Unequipped Arrow/Ammunition.
+*/
+ MSG_ID_AAD = 0xaad,
+/*20141112 to latest
+인벤토리의 아이템이 소모되어 로덱스 쓰기창을 닫습니다.
+Consuming item in inventory will close mail compose window.
+*/
+ MSG_ID_AAE = 0xaae,
+#endif
+#if PACKETVER >= 20141119
+/*20141119 to latest
+소지하신 돋보기가 없습니다.
+Do not have Magnifier.
+*/
+ MSG_ID_AAF = 0xaaf,
+#endif
+#if PACKETVER >= 20141210
+/*20141210 to latest
+아이템을 버릴려면 메일 쓰기창을 닫아주세요.
+Close email window if you want to discard item.
+*/
+ MSG_ID_AB0 = 0xab0,
+/*20141210 to latest
+상대방이 친구 요청중입니다
+The opponent has already requested you to be a friend.
+*/
+ MSG_ID_AB1 = 0xab1,
+#endif
+#if PACKETVER >= 20141217
+/*20141217 to latest
+SCRIPT ERROR AID
+*/
+ MSG_ID_AB2 = 0xab2,
+/*20141217 to 20141231
+
+Errorfile : %s
+ErrorLine : %d 줄
+ErrorContext: %s
+20150107 to latest
+
+Errorfile : %s
+ErrorLine : %d 줄
+ErrorContent:
+*이전 줄 : %s
+*Errorline : %s
+*다음 줄:
+ %s
+
+Errorfile : %s
+ErrorLine : %d item
+ErrorContext: %s
+*/
+ MSG_ID_AB3 = 0xab3,
+#endif
+#if PACKETVER >= 20141224
+/*20141224 to latest
+ ^ff0000해당 아이템을 구매 하시겠습니까? %d포인트 및 %d 仙貝가 차감 됩니다.
+^ff0000Are you sure want to purchase the item? after confirmation will consume %d point and %d crackers.
+*/
+ MSG_ID_AB4 = 0xab4,
+/*20141224 to latest
+닫기
+Close
+*/
+ MSG_ID_AB5 = 0xab5,
+/*20141224 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_AB6 = 0xab6,
+/*20141224 to latest
+퀘스트 아이콘 보기
+View Quest icon
+*/
+ MSG_ID_AB7 = 0xab7,
+/*20141224 to latest
+편의시설
+Facility
+*/
+ MSG_ID_AB8 = 0xab8,
+/*20141224 to latest
+편의시설 아이콘 보기
+View Facility icon
+*/
+ MSG_ID_AB9 = 0xab9,
+/*20141224 to latest
+길드원/파티원
+Guild/Party
+*/
+ MSG_ID_ABA = 0xaba,
+/*20141224 to 20150311
+길드원/파티원 표시
+20150318 to latest
+길드원/파티원 보기
+Show Guild/Party
+*/
+ MSG_ID_ABB = 0xabb,
+/*20141224 to latest
+기록하기
+Record
+*/
+ MSG_ID_ABC = 0xabc,
+/*20141224 to latest
+보스몬스터
+Boss Monster
+*/
+ MSG_ID_ABD = 0xabd,
+/*20141224 to latest
+나
+I
+*/
+ MSG_ID_ABE = 0xabe,
+/*20141224 to latest
+삭제 하시겠습니까?
+Are you sure want to delete it?
+*/
+ MSG_ID_ABF = 0xabf,
+/*20141224 to latest
+퀘스트 NPC
+Quest NPC
+*/
+ MSG_ID_AC0 = 0xac0,
+/*20141224 to latest
+메모할 내용을 기록합니다
+Record content
+*/
+ MSG_ID_AC1 = 0xac1,
+/*20141224 to latest
+저장하기
+Store
+*/
+ MSG_ID_AC2 = 0xac2,
+/*20141224 to latest
+메모하기
+Record
+*/
+ MSG_ID_AC3 = 0xac3,
+#endif
+#if PACKETVER >= 20141231
+/*20141231 to latest
+%s [%d옵션] %d개
+%s [%d Property] %d ea
+*/
+ MSG_ID_AC4 = 0xac4,
+/*20141231 to latest
+%s [%d옵션] %s Zeny
+%s [%d Property] %s Zeny
+*/
+ MSG_ID_AC5 = 0xac5,
+/*20141231 to latest
+%s [%d옵션] %d %s %d -> %s %s
+%s [%d Property] %d %s %d -> %s %s
+*/
+ MSG_ID_AC6 = 0xac6,
+/*20141231 to latest
+%s [%d옵션] %d %s %s %s
+%s [%d Property] %d %s %s %s
+*/
+ MSG_ID_AC7 = 0xac7,
+/*20141231 to latest
+%s [%d옵션] %d -> %s %s
+%s [%d Property] %d -> %s %s
+*/
+ MSG_ID_AC8 = 0xac8,
+/*20141231 to latest
+%s [%d옵션] %s %s
+%s [%d Property] %s %s
+*/
+ MSG_ID_AC9 = 0xac9,
+#endif
+#if PACKETVER >= 20150107
+/*20150107 to latest
+최소 거래 단위 100 仙貝 이상으로 설정 하셔야 합니다.
+The minimum trading unit must be 100 crackers or more.
+*/
+ MSG_ID_ACA = 0xaca,
+#endif
+#if PACKETVER >= 20150114
+/*20150114 to latest
+머리 색
+Hair color
+*/
+ MSG_ID_ACB = 0xacb,
+/*20150114 to latest
+머리 모양
+Hair style
+*/
+ MSG_ID_ACC = 0xacc,
+/*20150114 to latest
+옷 색
+Cloth color
+*/
+ MSG_ID_ACD = 0xacd,
+/*20150114 to latest
+옷 모양
+Cloth pattern
+*/
+ MSG_ID_ACE = 0xace,
+#endif
+#if PACKETVER >= 20150217
+/*20150217 to latest
+지원되지 않는 맵 입니다.
+Unsupported Map.
+*/
+ MSG_ID_ACF = 0xacf,
+#endif
+#if PACKETVER >= 20150304
+/*20150304 to 20150325
+2147483647 Zeny 이하로 입력 하십시오.
+20150401 to latest
+2,147,483,647 Zeny 이하로 입력 하십시오.
+Enter Zeny Below 2,147,483,647.
+*/
+ MSG_ID_AD0 = 0xad0,
+/*20150304 to latest
+1 Zeny 이상 입력 하십시오.
+Please Enter atleast 1 zeny.
+*/
+ MSG_ID_AD1 = 0xad1,
+/*20150304 to latest
+보유한 Zeny 가 없습니다.
+You do not hold any zeny.
+*/
+ MSG_ID_AD2 = 0xad2,
+/*20150304 to latest
+제니 창고
+Zeny Storage
+*/
+ MSG_ID_AD3 = 0xad3,
+/*20150304 to latest
+창고보유액
+in Bank
+*/
+ MSG_ID_AD4 = 0xad4,
+/*20150304 to latest
+소지금
+on hand
+*/
+ MSG_ID_AD5 = 0xad5,
+/*20150304 to latest
+입금
+Deposit
+*/
+ MSG_ID_AD6 = 0xad6,
+/*20150304 to latest
+출금
+Withdraw
+*/
+ MSG_ID_AD7 = 0xad7,
+/*20150304 to latest
+1 z UP
+*/
+ MSG_ID_AD8 = 0xad8,
+/*20150304 to latest
+1 z Down
+*/
+ MSG_ID_AD9 = 0xad9,
+/*20150304 to latest
+Max
+*/
+ MSG_ID_ADA = 0xada,
+/*20150304 to latest
+입력값이 없습니다
+There is no Input value
+*/
+ MSG_ID_ADB = 0xadb,
+/*20150304 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_ADC = 0xadc,
+/*20150304 to latest
+입력값 필요
+Input Required
+*/
+ MSG_ID_ADD = 0xadd,
+/*20150304 to latest
+문자 입력 불가
+Numbers only
+*/
+ MSG_ID_ADE = 0xade,
+/*20150304 to latest
+최대 입력 초과
+Exceeded max input
+*/
+ MSG_ID_ADF = 0xadf,
+/*20150304 to latest
+최소 입력 미만
+Below Minimum Input
+*/
+ MSG_ID_AE0 = 0xae0,
+/*20150304 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_AE1 = 0xae1,
+/*20150304 to latest
+은행 잔고 부족
+Insufficient funds
+*/
+ MSG_ID_AE2 = 0xae2,
+/*20150304 to latest
+최대 보유 Zeny 초과
+Exceeded max zeny
+*/
+ MSG_ID_AE3 = 0xae3,
+#endif
+#if PACKETVER >= 20150311
+/*20150311 to latest
+드롭 X
+Drop X
+*/
+ MSG_ID_AE4 = 0xae4,
+/*20150311 to latest
+창고 X
+Storage X
+*/
+ MSG_ID_AE5 = 0xae5,
+/*20150311 to latest
+카트 X
+Cart X
+*/
+ MSG_ID_AE6 = 0xae6,
+/*20150311 to latest
+메일 X
+Mail X
+*/
+ MSG_ID_AE7 = 0xae7,
+/*20150311 to latest
+교환창 X
+Trade X
+*/
+ MSG_ID_AE8 = 0xae8,
+/*20150311 to latest
+경매장 X
+Auction X
+*/
+ MSG_ID_AE9 = 0xae9,
+/*20150311 to latest
+길드창고 X
+Guild Storage X
+*/
+ MSG_ID_AEA = 0xaea,
+/*20150311 to latest
+NPC에게 판매 X
+Sell to NPC X
+*/
+ MSG_ID_AEB = 0xaeb,
+/*20150311 to latest
+이동제한이 있는 아이템입니다.
+Item moves restriction.
+*/
+ MSG_ID_AEC = 0xaec,
+#endif
+#if PACKETVER >= 20150401
+/*20150401 to latest
+캐릭터를 생성해주세요!
+Please Create a Character!
+*/
+ MSG_ID_AED = 0xaed,
+#endif
+#if PACKETVER >= 20150415
+/*20150415 to latest
+장착된 투사체 아이템을 해제해야 합니다.
+You need to disarm the equipped projectiles.
+*/
+ MSG_ID_AEE = 0xaee,
+#endif
+#if PACKETVER >= 20150513
+/*20150513 to latest
+인원 초과로 메모리얼 던전에 입장 할 수 없습니다
+You cannot enter Memorial Dungeon with excess members
+*/
+ MSG_ID_AEF = 0xaef,
+/*20150513 to latest
+인원수 초과로 인해 메모리얼 던전 입장이 거부되었습니다
+Memorial Dungeon Access was denied due to exceeding number of players
+*/
+ MSG_ID_AF0 = 0xaf0,
+#endif
+#if PACKETVER >= 20150603
+/*20150603 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF1 = 0xaf1,
+/*20150603 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF2 = 0xaf2,
+/*20150603 to latest
+중복된 아이템이 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to multiple same item.
+*/
+ MSG_ID_AF3 = 0xaf3,
+/*20150603 to latest
+중복된 효과가 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to effect of same consumed item.
+*/
+ MSG_ID_AF4 = 0xaf4,
+#endif
+#if PACKETVER >= 20150701
+/*20150701 to latest
+화면 흔들림 효과 ON
+Flicker Effect ON
+*/
+ MSG_ID_AF5 = 0xaf5,
+/*20150701 to latest
+화면 흔들림 효과 OFF
+Flicker Effect OFF
+*/
+ MSG_ID_AF6 = 0xaf6,
+#endif
+#if PACKETVER >= 20150702
+/*20150702 to latest
+불법 프로그램 발견되었습니다
+Illegal Programs has been detected
+*/
+ MSG_ID_AF7 = 0xaf7,
+#endif
+#if PACKETVER >= 20150722
+/*20150722 to latest
+메일 보내기
+Send Mail
+*/
+ MSG_ID_AF8 = 0xaf8,
+#endif
+#if PACKETVER >= 20150729
+/*20150729 to latest
+E X P : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AF9 = 0xaf9,
+/*20150729 to latest
+DROP : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFA = 0xafa,
+/*20150729 to latest
+DEATH : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFB = 0xafb,
+#endif
+#if PACKETVER >= 20150826
+/*20150826 to 20180919
+ 해당 태그는 이름으로 사용하실 수 없습니다.
+Name with this tag cannot be used.
+20181002 to latest
+ 해당 내용은 이름으로 사용하실 수 없습니다.
+You cannot use the tag as a name.
+*/
+ MSG_ID_AFC = 0xafc,
+#endif
+#if PACKETVER >= 20150916
+/*20150916 to latest
+???? bdbac5b8c0cfb8b52098de
+Style Shop
+*/
+ MSG_ID_AFD = 0xafd,
+#endif
+#if PACKETVER >= 20151028
+/*20151028 to 20151125
+쿠폰 없음, 상점에서 구매해야해요.
+20151202 to latest
+쿠폰 없음. Cash Shop에서 아이템을 구매해 주세요.
+No serial number, Please visit the store to buy.
+*/
+ MSG_ID_AFE = 0xafe,
+/*20151028 to 20151125
+아이템창의 쿠폰 상자를 열어주세요
+20151202 to latest
+인벤토리에서 아이템 쿠폰 상자를 열어주세요.
+Please turn on Serial item number window box.
+*/
+ MSG_ID_AFF = 0xaff,
+/*20151028 to 20151125
+은행
+Bank
+20151202 to latest
+해당 스타일 정보를 삭제하시겠습니까?
+Bank
+*/
+ MSG_ID_B00 = 0xb00,
+/*20151028 to 20151125
+슬롯이 꽉 찼습니다. 캐릭터를 삭제 후 사용해 주시기 바랍니다
+20151202 to latest
+슬롯이 꽉 찼습니다. 내 스타일에서 캐릭터 삭제 후 사용해 주십시오.
+Slot is full, please delete a character.
+*/
+ MSG_ID_B01 = 0xb01,
+/*20151028 to 20151125
+사용하신 아이템은 되돌릴 수 없습니다. 적용하시겠습니까?
+20151202 to latest
+비용을 지불하고 현재 스타일을 적용하시겠습니까?
+(※ 비용은 반환되지 않습니다.)
+Item cannot be restored, are you sure want to apply it?
+*/
+ MSG_ID_B02 = 0xb02,
+#endif
+#if PACKETVER >= 20151104
+/*20151104 to 20151125
+관심 스타일로 등록되었습니다
+20151202 to latest
+현재 스타일을 저장하였습니다.
+Registered as the following style.
+*/
+ MSG_ID_B03 = 0xb03,
+/*20151104 to 20151125
+은행에 충분한 제니가 있습니다. 먼저 은행으로 가세요.
+20151202 to latest
+보유 Zeny 부족. 은행에 충분한 Zeny가 있습니다.
+There are plenty of golds in the bank, Please go to the bank now.
+*/
+ MSG_ID_B04 = 0xb04,
+#endif
+#if PACKETVER >= 20151118
+/*20151118 to latest
+으로 이동합니다.
+moving...
+*/
+ MSG_ID_B05 = 0xb05,
+/*20151118 to latest
+해당 국가의 영공통과에 대한 허가가 나지 않았습니다.
+You are not allowed to fly over the sovereign airspace of the country.
+*/
+ MSG_ID_B06 = 0xb06,
+/*20151118 to latest
+마나로 대기불안정이 계속되어 비공정 운행이 불가능합니다.
+Airship flight is temporarily unavailable due to atmospheric instability caused by magic.
+*/
+ MSG_ID_B07 = 0xb07,
+/*20151118 to latest
+개인 비공정
+Private airship
+*/
+ MSG_ID_B08 = 0xb08,
+/*20151118 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_B09 = 0xb09,
+/*20151118 to latest
+개인 비공정 이용에 필요한 제니가 부족합니다.
+Not enough Zeny to use the private airship.
+*/
+ MSG_ID_B0A = 0xb0a,
+/*20151118 to 20170920
+개인 비공정 이용에 필요한 통조림이 부족합니다.
+20170927 to latest
+개인 비공정 이용에 필요한 아이템이 부족합니다.
+Not enough Cans to use the private airship.
+*/
+ MSG_ID_B0B = 0xb0b,
+/*20151118 to latest
+개인 비공정을 이용할 수 있는 레벨이 아닙니다.
+You cannot meet the level to use the private airship.
+*/
+ MSG_ID_B0C = 0xb0c,
+/*20151118 to latest
+선택한 지점으론 개인비공정이 이동할 수 없습니다.
+You cannot move to the selected point by the private airship.
+*/
+ MSG_ID_B0D = 0xb0d,
+/*20151118 to latest
+현 지점에선 개인비공정을 이용할 수 없습니다.
+You cannot use the private airship where you are now.
+*/
+ MSG_ID_B0E = 0xb0e,
+#endif
+#if PACKETVER >= 20151125
+/*20151125 to 20151125
+악세사리
+Accessory
+20151202 to latest
+액세서리
+Accessory
+*/
+ MSG_ID_B0F = 0xb0f,
+/*20151125 to latest
+세컨드코스튬
+Second costume
+*/
+ MSG_ID_B10 = 0xb10,
+/*20151125 to 20151125
+즐겨찾기
+20151202 to latest
+내 스타일
+Wardrobe
+*/
+ MSG_ID_B11 = 0xb11,
+/*20151125 to 20151125
+염색을 할 수 없는 머리스타일입니다.
+20151202 to latest
+염색할 수 없는 헤어스타일입니다.
+This hairstyle cannot be dyed.
+*/
+ MSG_ID_B12 = 0xb12,
+/*20151125 to 20151125
+화살표를 눌러 마음에 드는 스타일을 선택할 수 있어요.
+20151202 to latest
+화살표를 눌러 마음에 드는 스타일을 선택해 보세요.
+Press an arrow to choose the style you want.
+*/
+ MSG_ID_B13 = 0xb13,
+#endif
+#if PACKETVER >= 20151202
+/*20151202 to 20151202
+스타일 새로운 스타일을 확인해 보세요.
+(※ 액세서리 구매 시 RODEX로 발송됩니다.)
+20151209 to latest
+새로운 스타일을 확인해 보세요.
+(※ 액세서리 구매 시 RODEX로 발송됩니다.)
+Come and see the new styles.
+(Purchased accessories will be sent via RODEX.)
+*/
+ MSG_ID_B14 = 0xb14,
+#endif
+#if PACKETVER >= 20151223
+/*20151223 to latest
+기본 스타일
+Basic style
+*/
+ MSG_ID_B15 = 0xb15,
+#endif
+#if PACKETVER >= 20160106
+/*20160106 to latest
+ 해당 스킬은 BaseLv %d 이상부터 스킬 포인트 투자가 가능합니다.
+You can level up the skill from the base Lv. %d.
+*/
+ MSG_ID_B16 = 0xb16,
+#endif
+#if PACKETVER >= 20160113
+/*20160113 to latest
+해당 특수기호는 이름에 사용하실 수 없습니다.
+Special symbol can't be used in name
+*/
+ MSG_ID_B17 = 0xb17,
+/*20160113 to latest
+MHP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxHP is to low to use this skill
+*/
+ MSG_ID_B18 = 0xb18,
+/*20160113 to latest
+MSP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxSP is to low to use this skill
+*/
+ MSG_ID_B19 = 0xb19,
+#endif
+#if PACKETVER >= 20160203
+/*20160203 to latest
+아이템 비교하기
+Compare items
+*/
+ MSG_ID_B1A = 0xb1a,
+/*20160203 to latest
+아이템 버리기 잠금
+Drop lock
+*/
+ MSG_ID_B1B = 0xb1b,
+#endif
+#if PACKETVER >= 20160224
+/*20160224 to latest
+스크린샷 파일이 첨부 되지 않았습니다.
+Screenshots are not attached
+*/
+ MSG_ID_B1C = 0xb1c,
+/*20160224 to 20160511
+SNS통신
+20160518 to 20160817
+TWITTER
+20160824 to latest
+Twitter
+*/
+ MSG_ID_B1D = 0xb1d,
+/*20160224 to latest
+일반
+General
+*/
+ MSG_ID_B1E = 0xb1e,
+/*20160224 to latest
+공지
+Notice
+*/
+ MSG_ID_B1F = 0xb1f,
+/*20160224 to latest
+반송
+Clear
+*/
+ MSG_ID_B20 = 0xb20,
+/*20160224 to latest
+새로고침
+Refresh
+*/
+ MSG_ID_B21 = 0xb21,
+/*20160224 to latest
+%d분
+%d minute
+*/
+ MSG_ID_B22 = 0xb22,
+/*20160224 to latest
+%d시간
+%d hour
+*/
+ MSG_ID_B23 = 0xb23,
+/*20160224 to latest
+%d일
+%d day
+*/
+ MSG_ID_B24 = 0xb24,
+/*20160224 to latest
+반송됨
+Returned
+*/
+ MSG_ID_B25 = 0xb25,
+/*20160224 to latest
+선택한 메일을 삭제하시겠습니까?
+Do you want to delete the message?
+*/
+ MSG_ID_B26 = 0xb26,
+#endif
+#if PACKETVER >= 20160302
+/*20160302 to latest
+위치표시
+Show information
+*/
+ MSG_ID_B27 = 0xb27,
+/*20160302 to latest
+확대
+Zoom In
+*/
+ MSG_ID_B28 = 0xb28,
+/*20160302 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_B29 = 0xb29,
+/*20160302 to latest
+맵보기
+Maximize
+*/
+ MSG_ID_B2A = 0xb2a,
+/*20160302 to latest
+월드보기
+Show world map
+*/
+ MSG_ID_B2B = 0xb2b,
+/*20160302 to latest
+아이템 소지 종류수
+Total possession item type
+*/
+ MSG_ID_B2C = 0xb2c,
+#endif
+#if PACKETVER >= 20160309
+/*20160309 to latest
+/minimap
+*/
+ MSG_ID_B2D = 0xb2d,
+/*20160309 to latest
+미니맵 버튼을 표시합니다
+Show minimap buttons
+*/
+ MSG_ID_B2E = 0xb2e,
+/*20160309 to latest
+미니맵 버튼을 표시하지 않습니다
+Hide minimap buttons
+*/
+ MSG_ID_B2F = 0xb2f,
+/*20160309 to latest
+길드 접속자 정렬
+Show guild member login status
+*/
+ MSG_ID_B30 = 0xb30,
+#endif
+#if PACKETVER >= 20160323
+/*20160323 to latest
+친밀도 : %s
+Intimacy: %s
+*/
+ MSG_ID_B31 = 0xb31,
+/*20160323 to latest
+확인 전
+Confirmation
+*/
+ MSG_ID_B32 = 0xb32,
+#endif
+#if PACKETVER >= 20160330
+/*20160330 to latest
+파티 이름
+Team name
+*/
+ MSG_ID_B33 = 0xb33,
+/*20160330 to latest
+파티장
+Leader
+*/
+ MSG_ID_B34 = 0xb34,
+/*20160330 to latest
+제한 시간 초과. 클라이언트를 종료합니다.
+Time limit exceeded. Closing the client
+*/
+ MSG_ID_B35 = 0xb35,
+/*20160330 to latest
+잘못된 입력입니다. 클라이언트를 종료합니다.
+Input error. Closing the client
+*/
+ MSG_ID_B36 = 0xb36,
+/*20160330 to latest
+정답 입니다. 보상으로 소정의 버프가 주어집니다.
+Incorrect input. A small buff has given to you
+*/
+ MSG_ID_B37 = 0xb37,
+/*20160330 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_B38 = 0xb38,
+/*20160330 to latest
+입력한 답이 [%s]가 맞습니까?
+Your entered answer is [%s]. Is it right?
+*/
+ MSG_ID_B39 = 0xb39,
+/*20160330 to latest
+선택된 이미지가 없습니다.
+Icon is unchecked
+*/
+ MSG_ID_B3A = 0xb3a,
+/*20160330 to latest
+잘못된 입력입니다. (남은 기회 %d번)
+Incorrect input (Remaining chance: %d)
+*/
+ MSG_ID_B3B = 0xb3b,
+/*20160330 to latest
+총 %d명의 유저를 신고하시겠습니까?
+Do you want to announce %d to player?
+*/
+ MSG_ID_B3C = 0xb3c,
+/*20160330 to latest
+유저에게 메시지를 보냈습니다.
+Message has been sent to player
+*/
+ MSG_ID_B3D = 0xb3d,
+/*20160330 to latest
+불법 프로그램 단속에 필요한 데이터가 미등록 상태입니다.
+Needed Data for Query illegal software are not signed.
+*/
+ MSG_ID_B3E = 0xb3e,
+/*20160330 to latest
+이미 매크로 감시중인 유저입니다.
+The player is being monitored.
+*/
+ MSG_ID_B3F = 0xb3f,
+/*20160330 to latest
+매크로가 등록되었습니다..
+Already signed in investigation system.
+*/
+ MSG_ID_B40 = 0xb40,
+/*20160330 to latest
+이미지 등록에 실패하였습니다.
+Failed to store icon.
+*/
+ MSG_ID_B41 = 0xb41,
+/*20160330 to latest
+정답 등록에 실패하였습니다.
+Failed to store replied answer.
+*/
+ MSG_ID_B42 = 0xb42,
+/*20160330 to latest
+안녕하세요. 불법프로그램 단속중입니다.
+Hello, illegal software is being monitored.
+*/
+ MSG_ID_B43 = 0xb43,
+/*20160330 to latest
+지정된 시간내에 아래의 문자를 입력해주세요.
+Please enter the text below within the specified time.
+*/
+ MSG_ID_B44 = 0xb44,
+/*20160330 to latest
+3회 오류시 운영정책에 의거하여 영구블록됩니다.
+According to game regulation, when you enter the wrong text three times, you will get banned.
+*/
+ MSG_ID_B45 = 0xb45,
+/*20160330 to latest
+남은 횟수 : %d
+Remaining chance : %d
+*/
+ MSG_ID_B46 = 0xb46,
+/*20160330 to latest
+캐릭터
+Role
+*/
+ MSG_ID_B47 = 0xb47,
+/*20160330 to latest
+범위
+Range
+*/
+ MSG_ID_B48 = 0xb48,
+/*20160330 to latest
+캐릭터 선택은 좌클릭으로 합니다.
+You use the left mouse button to specify the role
+*/
+ MSG_ID_B49 = 0xb49,
+/*20160330 to latest
+범위 선택은 우클릭으로 합니다.
+You use the left mouse button to specify the range
+*/
+ MSG_ID_B4A = 0xb4a,
+/*20160330 to latest
+범위 크기를 지정하기 위해서는 엔터를 입력해주세요
+Not a valid range, please press Enter
+*/
+ MSG_ID_B4B = 0xb4b,
+/*20160330 to latest
+E X P : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4C = 0xb4c,
+/*20160330 to latest
+DROP : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4D = 0xb4d,
+/*20160330 to latest
+DEATH : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4E = 0xb4e,
+/*20160330 to 20160330
+변경된 캐릭명 %s 로 전송했습니다. 확인 바랍니다
+20160406 to latest
+변경된 캐릭명으로 발송했습니다. 변경된 캐릭명 : %s
+The role name will be sent: %s
+*/
+ MSG_ID_B4F = 0xb4f,
+#endif
+#if PACKETVER >= 20160427
+/*20160427 to latest
+합성에 필요한 재료
+Synthesis of the required materials
+*/
+ MSG_ID_B50 = 0xb50,
+/*20160427 to latest
+조합 재료가 부족해서 조합할 수 없습니다.
+Insufficient synthesis materials
+*/
+ MSG_ID_B51 = 0xb51,
+#endif
+#if PACKETVER >= 20160504
+/*20160504 to latest
+해당 재료는 %d개가 필요합니다.
+Required material %d ea.
+*/
+ MSG_ID_B52 = 0xb52,
+/*20160504 to latest
+제련도가 낮아서 조합할 수 없습니다.
+Refine value is to low for synthesis
+*/
+ MSG_ID_B53 = 0xb53,
+/*20160504 to latest
+모험가중개소에 등록 하시겠습니까?
+Do you want to sign in to the adventurers?
+*/
+ MSG_ID_B54 = 0xb54,
+#endif
+#if PACKETVER >= 20160511
+/*20160511 to latest
+자유롭게 코멘트를 남겨보세요.
+Please leave a message
+*/
+ MSG_ID_B55 = 0xb55,
+#endif
+#if PACKETVER >= 20160518
+/*20160518 to latest
+그림에 보이는 문자를 입력해주세요.
+Please enter the text on the graph
+*/
+ MSG_ID_B56 = 0xb56,
+/*20160518 to latest
+%d초 남았습니다
+%d second left
+*/
+ MSG_ID_B57 = 0xb57,
+/*20160518 to latest
+OTP 인증번호 6자리를 입력해 주세요
+Please enter your 6 identification number.
+*/
+ MSG_ID_B58 = 0xb58,
+/*20160518 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_B59 = 0xb59,
+/*20160518 to latest
+6자리의 숫자가 아닙니다. 다시 확인해 주세요
+It's not a 6 identification number. Please try again
+*/
+ MSG_ID_B5A = 0xb5a,
+#endif
+#if PACKETVER >= 20160608
+/*20160608 to latest
+이미 삭제된 메일입니다.
+The message has been deleted
+*/
+ MSG_ID_B5B = 0xb5b,
+#endif
+#if PACKETVER >= 20160615
+/*20160615 to latest
+개인 비공정으로 이동할 지역을 선택해주세요.
+Please select the area where the private airship will move
+*/
+ MSG_ID_B5C = 0xb5c,
+/*20160615 to latest
+E X P : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5D = 0xb5d,
+/*20160615 to latest
+DROP : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5E = 0xb5e,
+/*20160615 to latest
+DEATH : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5F = 0xb5f,
+/*20160615 to latest
+목적지로 이동중입니다.
+Move to the destination
+*/
+ MSG_ID_B60 = 0xb60,
+#endif
+#if PACKETVER >= 20160629
+/*20160629 to latest
+[%s] 파일이 존재하지 않아 default AI 로 동작합니다
+The [%s] is not present, the default AI will be used instead.
+*/
+ MSG_ID_B61 = 0xb61,
+/*20160629 to 20160630
+ %.1f%% ( Premium %.1f%% + %s %.1f%%)
+20160706 to latest
+ %.1f%% ( Basic 100.0%% + Premium %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_B62 = 0xb62,
+#endif
+#if PACKETVER >= 20160706
+/*20160706 to latest
+이 자리에 노점을 세우시겠습니까?
+Would you like to open a shop at this location?
+*/
+ MSG_ID_B63 = 0xb63,
+#endif
+#if PACKETVER >= 20160713
+/*20160713 to latest
+도람족은 해당 의상을 입을 수 없습니다.
+Doram race can't wear this clothes
+*/
+ MSG_ID_B64 = 0xb64,
+/*20160713 to 20160727
+구입한 물건이 로덱스로 배송되었습니다.
+20160803 to latest
+판매 노점에서 거래한 아이템이 로덱스로 배송되었습니다.
+Props open-air store sales will be traded in RODEX
+*/
+ MSG_ID_B65 = 0xb65,
+/*20160713 to latest
+30,000 z
+*/
+ MSG_ID_B66 = 0xb66,
+/*20160713 to latest
+말랑도 특산 통조림 100개
+Malangdo Special Can 100 pc
+*/
+ MSG_ID_B67 = 0xb67,
+#endif
+#if PACKETVER >= 20160720
+/*20160720 to latest
+무게가 80%를 초과하여 진행할 수 없습니다.
+Cannot carry anymore because weight limit over 80%
+*/
+ MSG_ID_B68 = 0xb68,
+/*20160720 to latest
+판매되지 못한 상품이 로덱스로 배송되었습니다.
+Unsold items are sent to RODEX
+*/
+ MSG_ID_B69 = 0xb69,
+#endif
+#if PACKETVER >= 20160727
+/*20160727 to latest
+장착 모습
+Preview
+*/
+ MSG_ID_B6A = 0xb6a,
+/*20160727 to latest
+길드마스터 위임
+Assign Guild Leader
+*/
+ MSG_ID_B6B = 0xb6b,
+/*20160727 to latest
+정말로 %s님께 길드마스터를 위임하시겠습니까? 위임 후 당신의 지위는 %s님과 지위가 바뀌게 됩니다.
+Are sure want to assign %s as guild leader? After assigned your position will become %s
+*/
+ MSG_ID_B6C = 0xb6c,
+/*20160727 to latest
+철회
+Cancel
+*/
+ MSG_ID_B6D = 0xb6d,
+/*20160727 to latest
+노점을 철수하시겠습니까?
+Do you want to close the shop?
+*/
+ MSG_ID_B6E = 0xb6e,
+/*20160727 to latest
+%02d일 %02d시간 %02d분 %02d초
+%02d day %02d hour %02d minute %02d second
+*/
+ MSG_ID_B6F = 0xb6f,
+/*20160727 to latest
+접속불가
+Unable to sign in
+*/
+ MSG_ID_B70 = 0xb70,
+/*20160727 to latest
+접속가능인원을 초과하여 접속이 불가능 합니다.
+Unable to sign in because the maximum number of sign-in is exceeded
+*/
+ MSG_ID_B71 = 0xb71,
+/*20160727 to latest
+노점을 설치할 위치를 선택해주세요.
+Please select a location for your shop
+*/
+ MSG_ID_B72 = 0xb72,
+/*20160727 to latest
+펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+Pet name will be changed to ^0000ff^0000ff %s^000000^000000, do you want to continue?
+*/
+ MSG_ID_B73 = 0xb73,
+#endif
+#if PACKETVER >= 20160803
+/*20160803 to 20160803
+판매 일시 :
+20160810 to latest
+거래 일시 :
+Trade date :
+*/
+ MSG_ID_B74 = 0xb74,
+/*20160803 to 20160803
+판매 아이템 :
+20160810 to latest
+거래 아이템 :
+Trade item :
+*/
+ MSG_ID_B75 = 0xb75,
+/*20160803 to 20160803
+판매 수량 :
+20160810 to latest
+거래 수량 :
+Trade quantity :
+*/
+ MSG_ID_B76 = 0xb76,
+/*20160803 to 20160803
+판매 단가 :
+20160810 to latest
+거래 단가 :
+Trade price :
+*/
+ MSG_ID_B77 = 0xb77,
+/*20160803 to 20160803
+판매 금액 :
+20160810 to latest
+거래 금액 :
+Total trade :
+*/
+ MSG_ID_B78 = 0xb78,
+/*20160803 to latest
+노점 판매 아이템
+Open vending sales agent
+*/
+ MSG_ID_B79 = 0xb79,
+/*20160803 to latest
+노점 구매 아이템
+Open vending purchase agent
+*/
+ MSG_ID_B7A = 0xb7a,
+/*20160803 to latest
+판매 노점 아르바이트 종료
+Close vending sales agent
+*/
+ MSG_ID_B7B = 0xb7b,
+/*20160803 to latest
+구매 노점 아르바이트 종료
+Close vending purchase agent
+*/
+ MSG_ID_B7C = 0xb7c,
+/*20160803 to latest
+남은 금액:
+Balance:
+*/
+ MSG_ID_B7D = 0xb7d,
+/*20160803 to latest
+아이템 리스트:
+Item list:
+*/
+ MSG_ID_B7E = 0xb7e,
+/*20160803 to latest
+노점 아르바이트생
+Vending agent
+*/
+ MSG_ID_B7F = 0xb7f,
+/*20160803 to latest
+반환 아이템:
+Returned item:
+*/
+ MSG_ID_B80 = 0xb80,
+/*20160803 to latest
+반환 수량:
+Returned quantity:
+*/
+ MSG_ID_B81 = 0xb81,
+/*20160803 to latest
+반환 일시:
+Returned date:
+*/
+ MSG_ID_B82 = 0xb82,
+/*20160803 to latest
+구매 노점에서 거래한 금액이 로덱스로 배송되었습니다
+Total trade will be sent to RODEX
+*/
+ MSG_ID_B83 = 0xb83,
+/*20160803 to latest
+사용할 수 없는 이름입니다.
+Name isn't available
+*/
+ MSG_ID_B84 = 0xb84,
+#endif
+#if PACKETVER >= 20160817
+/*20160817 to latest
+상품이 도착했습니다.
+Item has been delivered
+*/
+ MSG_ID_B85 = 0xb85,
+/*20160817 to latest
+구입해주셔서 감사합니다.
+Thank you for purchasing
+*/
+ MSG_ID_B86 = 0xb86,
+#endif
+#if PACKETVER >= 20160824
+/*20160824 to latest
+NPC에게 아이템을 판매하지 않습니다.
+Press again to unlock
+*/
+ MSG_ID_B87 = 0xb87,
+/*20160824 to latest
+아이템 판매 잠금
+Lock from NPC selling
+*/
+ MSG_ID_B88 = 0xb88,
+/*20160824 to latest
+근처에서 소환가능 위치를 찾을수 없습니다.
+There is no callable location nearby
+*/
+ MSG_ID_B89 = 0xb89,
+/*20160824 to latest
+전체 화면 캡쳐
+Capture full screens
+*/
+ MSG_ID_B8A = 0xb8a,
+/*20160824 to latest
+부분 화면 캡쳐
+Capture part of screen
+*/
+ MSG_ID_B8B = 0xb8b,
+/*20160824 to latest
+보내기
+Send
+*/
+ MSG_ID_B8C = 0xb8c,
+/*20160824 to latest
+가족 분과 담당자
+Family Affairs agent
+*/
+ MSG_ID_B8D = 0xb8d,
+/*20160824 to latest
+가족 사항 변동 안내
+Acknowledgement of family member registrations.
+*/
+ MSG_ID_B8E = 0xb8e,
+/*20160824 to latest
+안녕하십니까.
+
+금일 "%s"님과 "%s"님의 자녀인 "%s"님이 독립하여 단독 세대를 구성하였습니다.
+
+이에 서면으로 안내를 드립니다.
+
+가족 관계 확인을 원하시는 분은 프론테라 동사무소의 담당 직원에게 문의하시기 바랍니다.
+
+감사합니다.
+Dear whom it may concern.
+
+ Today, \"%s\" and \"%s\" 's son/daughter \"%s\" has fully separated and independent from your member of family.
+
+Hereat, we inform you in writing.
+
+Please contact to Prontera Family Affairs if you have any enquiries.
+
+Thank you.
+*/
+ MSG_ID_B8F = 0xb8f,
+#endif
+#if PACKETVER >= 20160831
+/*20160831 to latest
+장착
+Equip
+*/
+ MSG_ID_B90 = 0xb90,
+/*20160831 to latest
+이미지 없음
+No image
+*/
+ MSG_ID_B91 = 0xb91,
+#endif
+#if PACKETVER >= 20160907
+/*20160907 to 20160921
+%s은(는) 현재 호출을 차단한 상태입니다.
+20160928 to latest
+[%s]은(는) 현재 호출을 차단한 상태입니다.
+[%s] is blocking Call Massage.
+*/
+ MSG_ID_B92 = 0xb92,
+#endif
+#if PACKETVER >= 20160913
+/*20160913 to latest
+현재 공성전이 진행중이므로, 길드마스터를 위임 할 수 없습니다.
+Currently in WoE hours, unable to delegate Guild leader
+*/
+ MSG_ID_B93 = 0xb93,
+/*20160913 to latest
+현재 길드장 위임을 받은지 만 하루가 지나지 않아, 길드장을 위임할 수 없습니다.
+You have to wait for one day before delegating a new Guild leader
+*/
+ MSG_ID_B94 = 0xb94,
+/*20160913 to latest
+아이가 되면 전승을 할 수 없고 스텟의 제한이 있으며 HP와 SP가 줄어듭니다.
+그래도 괜찮습니까?
+When adopted, character will not able to transcend, maximum stats will be limited, MaxHP and MaxSP will be reduced.
+Are you sure you want to continue?
+*/
+ MSG_ID_B95 = 0xb95,
+/*20160913 to latest
+제련
+Refining
+*/
+ MSG_ID_B96 = 0xb96,
+/*20160913 to latest
+대장장이의 축복을 사용중입니다.
+Use Blacksmith's Blessing
+*/
+ MSG_ID_B97 = 0xb97,
+/*20160913 to latest
+제니가 부족합니다.
+Insufficient zeny
+*/
+ MSG_ID_B98 = 0xb98,
+/*20160913 to latest
+대장장이의 축복 개수가 부족합니다.
+Not enough Blacksmith's Blessing
+*/
+ MSG_ID_B99 = 0xb99,
+/*20160913 to latest
+해당 장비는 제련이 불가능합니다.
+This equipment can not be refined
+*/
+ MSG_ID_B9A = 0xb9a,
+/*20160913 to 20170621
+제련 성공!
+20170628 to latest
+제련 성공
+Upgrade success!
+*/
+ MSG_ID_B9B = 0xb9b,
+/*20160913 to 20170621
+제련 실패!
+20170628 to latest
+제련 실패
+Upgrade failed!
+*/
+ MSG_ID_B9C = 0xb9c,
+/*20160913 to latest
+돌아가기
+Back
+*/
+ MSG_ID_B9D = 0xb9d,
+/*20160913 to latest
+성공
+Success
+*/
+ MSG_ID_B9E = 0xb9e,
+/*20160913 to latest
+원래대로
+Return
+*/
+ MSG_ID_B9F = 0xb9f,
+#endif
+#if PACKETVER >= 20160921
+/*20160921 to latest
+씨와의
+With Mr/Miss
+*/
+ MSG_ID_BA0 = 0xba0,
+/*20160921 to latest
+호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+The Homunculus's name will be changed to^0000ff^0000ff %s^000000^000000, Are you sure?
+*/
+ MSG_ID_BA1 = 0xba1,
+#endif
+#if PACKETVER >= 20160928
+/*20160928 to latest
+호출이 허용된 상태입니다. (호출 기능 ON)
+Call function is ON
+*/
+ MSG_ID_BA2 = 0xba2,
+/*20160928 to latest
+호출이 차단된 상태입니다. (호출 기능 OFF)
+Call function is OFF
+*/
+ MSG_ID_BA3 = 0xba3,
+/*20160928 to latest
+호출 메시지 표시
+Display Call messages
+*/
+ MSG_ID_BA4 = 0xba4,
+/*20160928 to latest
+해당 캐릭터가 현재 노점 아이템을 사용 중이므로 삭제할 수 없습니다.
+This character is currently opening a shop and can't be deleted
+*/
+ MSG_ID_BA5 = 0xba5,
+/*20160928 to latest
+이미 동일한 노점 NPC가 설치 중입니다.
+The same vend shop NPC has been set up
+*/
+ MSG_ID_BA6 = 0xba6,
+/*20160928 to latest
+노점을 설치할 수 없는 위치입니다.
+Opening shop is not allowed on this location
+*/
+ MSG_ID_BA7 = 0xba7,
+/*20160928 to latest
+다른 캐릭터가 있는 위치에는 노점을 설치할 수 없습니다.
+Opening shop is not allowed when there is other character
+*/
+ MSG_ID_BA8 = 0xba8,
+#endif
+#if PACKETVER >= 20161005
+/*20161005 to latest
+펫 먹이주기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+Failed to feed pet, please close RODEX window
+*/
+ MSG_ID_BA9 = 0xba9,
+/*20161005 to latest
+장비 세트 설정
+Set item setting
+*/
+ MSG_ID_BAA = 0xbaa,
+/*20161005 to latest
+장착 하기
+Equip
+*/
+ MSG_ID_BAB = 0xbab,
+#endif
+#if PACKETVER >= 20161019
+/*20161019 to latest
+제련 실패시 장비가 사라집니다.
+Equipment will dissapear when refine fails
+*/
+ MSG_ID_BAC = 0xbac,
+/*20161019 to latest
+제련 실패시 장비의 제련도가 내려갑니다.
+Equipment's refine level will decreased when refine fails
+*/
+ MSG_ID_BAD = 0xbad,
+/*20161019 to latest
+제련 실패시 장비의 제련도가 내려가거나 사라질 수 있습니다.
+Equipment will dissapear or refine level will decreased when refine fails
+*/
+ MSG_ID_BAE = 0xbae,
+#endif
+#if PACKETVER >= 20161026
+/*20161026 to latest
+제련 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+You cannot use RODEX while refining. RODEX has closed.
+*/
+ MSG_ID_BAF = 0xbaf,
+/*20161026 to latest
+제련 중에는 로덱스를 사용할 수 없습니다.
+You cannot use RODEX while refining.
+*/
+ MSG_ID_BB0 = 0xbb0,
+/*20161026 to latest
+제련을 진행하려면 다른 창을 닫아주세요.
+Please close other windows to continue.
+*/
+ MSG_ID_BB1 = 0xbb1,
+/*20161026 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_ID_BB2 = 0xbb2,
+/*20161026 to latest
+오오라가 표시되지 않습니다 [오오라 OFF]
+Turn Off Aura [Auta OFF]
+*/
+ MSG_ID_BB3 = 0xbb3,
+/*20161026 to latest
+오오라가 Off 상태입니다. Off 를 해제하고 시도해 주세요
+Aura is turned off. Please turn it on and try again
+*/
+ MSG_ID_BB4 = 0xbb4,
+/*20161026 to latest
+스킬 발동시 최소 %d개의 탄알이 필요합니다.
+You need %d bullet(s) to activate the skill.
+*/
+ MSG_ID_BB5 = 0xbb5,
+/*20161026 to latest
+장비 세트를 변경하시겠습니까?
+Do you want to change the equipment set?
+*/
+ MSG_ID_BB6 = 0xbb6,
+/*20161026 to latest
+죽은 상태에서는 할 수 없습니다
+You can not do it while you are dead.
+*/
+ MSG_ID_BB7 = 0xbb7,
+/*20161026 to latest
+캐스팅 도중에는 할 수 없습니다
+You can not do it while casting
+*/
+ MSG_ID_BB8 = 0xbb8,
+/*20161026 to latest
+거래 도중에는 할 수 없습니다
+You can not do it while trading
+*/
+ MSG_ID_BB9 = 0xbb9,
+/*20161026 to latest
+노점 개설 도중에는 할 수 없습니다
+You can not do it while opening vendor
+*/
+ MSG_ID_BBA = 0xbba,
+/*20161026 to latest
+NPC 이용중에는 할 수 없습니다
+You can not do it while using NPC
+*/
+ MSG_ID_BBB = 0xbbb,
+/*20161026 to latest
+채팅방 이용중에는 할 수 없습니다
+You can not do it while using chatting room
+*/
+ MSG_ID_BBC = 0xbbc,
+/*20161026 to latest
+파티원 전원이 접속 상태가 아닙니다.
+Party members are not connected.
+*/
+ MSG_ID_BBD = 0xbbd,
+/*20161026 to latest
+스킬 발동시 최소 %d개의 화살이 필요합니다.
+You need %d arrow(s) to activate the skill.
+*/
+ MSG_ID_BBE = 0xbbe,
+#endif
+#if PACKETVER >= 20161102
+/*20161102 to latest
+아이템 정렬
+Align items
+*/
+ MSG_ID_BBF = 0xbbf,
+/*20161102 to latest
+아이템을 버리려면 장비 설정 창을 닫아주세요.
+Please close item setting window to dump item.
+*/
+ MSG_ID_BC0 = 0xbc0,
+#endif
+#if PACKETVER >= 20161109
+/*20161109 to latest
+교체 할 수 있는 아이템이 없습니다.
+There is no item to replace.
+*/
+ MSG_ID_BC1 = 0xbc1,
+/*20161109 to latest
+삭제된 캐릭터
+Deleted character
+*/
+ MSG_ID_BC2 = 0xbc2,
+#endif
+#if PACKETVER >= 20161116
+/*20161116 to latest
+%Y.%m.%d
+*/
+ MSG_ID_BC3 = 0xbc3,
+/*20161116 to latest
+접속일: %s
+Access date: %s
+*/
+ MSG_ID_BC4 = 0xbc4,
+/*20161116 to latest
+제련 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+You can not use bank while refining. Bank has closed.
+*/
+ MSG_ID_BC5 = 0xbc5,
+/*20161116 to latest
+제련 중에는 은행을 사용할 수 없습니다.
+You can not use bank while refining.
+*/
+ MSG_ID_BC6 = 0xbc6,
+/*20161116 to latest
+장비 세트 설정 중인 아이템입니다.
+The item has bind to set equipment.
+*/
+ MSG_ID_BC7 = 0xbc7,
+#endif
+#if PACKETVER >= 20161123
+/*20161123 to latest
+인간
+Human
+*/
+ MSG_ID_BC8 = 0xbc8,
+/*20161123 to latest
+검사, 법사, 상인, 복사, 도둑, 궁수
+Swordman, Mage, Merchant, Acolyte, Thief, Archer
+*/
+ MSG_ID_BC9 = 0xbc9,
+/*20161123 to latest
+도람
+Doram
+*/
+ MSG_ID_BCA = 0xbca,
+/*20161123 to latest
+소환사
+Summoner
+*/
+ MSG_ID_BCB = 0xbcb,
+/*20161123 to latest
+미드가르드 대륙의 대표 종족. 무한한 잠재력과 뛰어난 적응력으로 문제 해결에 탁월한 것이 특징이다.
+Delegate race of Midgard. Very talented race to solve a problem with inifite potential and great adaptability.
+*/
+ MSG_ID_BCC = 0xbcc,
+/*20161123 to latest
+파-스타 대륙의 대표적인 종족 중 하나로, 선천적으로 호기심이 강하고 발랄한 성격을 지녔다.
+One of delegate race of Far-star continent with natural born curiosity and sparky character.
+*/
+ MSG_ID_BCD = 0xbcd,
+/*20161123 to latest
+소지 한계량이 70%를 초과하거나, 인벤토리에 10칸 이상의 여유 공간이 부족한 상태입니다.
+Weight limit has reached toover 70%. Or less then 10 invenrory space.
+*/
+ MSG_ID_BCE = 0xbce,
+/*20161123 to latest
+C
+EUR
+*/
+ MSG_ID_BCF = 0xbcf,
+/*20161123 to latest
+C
+EUR
+*/
+ MSG_ID_BD0 = 0xbd0,
+/*20161123 to latest
+다른 일을 하는 중입니다.
+Doing in other activity.
+*/
+ MSG_ID_BD1 = 0xbd1,
+/*20161123 to latest
+오버히트 리미트 : %d
+Overheat limit : %d
+*/
+ MSG_ID_BD2 = 0xbd2,
+#endif
+#if PACKETVER >= 20161130
+/*20161130 to latest
+메모리얼 던전 이용 중엔 초대 및 탈퇴가 되지 않습니다.
+You cannot invite or withdraw while in memorial dungeon.
+*/
+ MSG_ID_BD3 = 0xbd3,
+/*20161130 to latest
+비속어가 포함되어있습니다.
+다시 한번 확인해주세요.
+Expletive has detected.
+Please check again.
+*/
+ MSG_ID_BD4 = 0xbd4,
+#endif
+#if PACKETVER >= 20161207
+/*20161207 to latest
+아이디는 %d자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Please enter over %d characters. If you don't have user account, please click [Register] button on the bottom left.
+*/
+ MSG_ID_BD5 = 0xbd5,
+/*20161207 to latest
+비밀번호는 %d자 이상 입력해주세요.
+Please enter the password over %d characters.
+*/
+ MSG_ID_BD6 = 0xbd6,
+/*20161207 to latest
+진행중이던 작업을 종료후 다시 시도하세요.
+Please finish your current work and try it again.
+*/
+ MSG_ID_BD7 = 0xbd7,
+/*20161207 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + %s서버 %.1f%%)
+%.1f%% (Internet-Cafe %.1f%% + TPLUS %.1f%% + %sServer %.1f%%)
+*/
+ MSG_ID_BD8 = 0xbd8,
+/*20161207 to latest
+아이템을 등록할 수 없습니다
+The item cannot be registered.
+*/
+ MSG_ID_BD9 = 0xbd9,
+#endif
+#if PACKETVER >= 20161214
+/*20161214 to latest
+/100
+/300
+*/
+ MSG_ID_BDA = 0xbda,
+/*20161214 to latest
+/2000
+/4000
+*/
+ MSG_ID_BDB = 0xbdb,
+/*20161214 to latest
+https://member.gnjoy.com.tw/mRO_SecPwd.aspx
+*/
+ MSG_ID_BDC = 0xbdc,
+/*20161214 to latest
+등록할 emblem이 존재하지 않습니다. emblem 폴더에 파일을 넣고 시도해 주세요
+The emblem you want to register does not exist. Insert it in the emblem file and try again
+*/
+ MSG_ID_BDD = 0xbdd,
+/*20161214 to 20170315
+#라그나로크 #Ragnarok
+20170322 to latest
+라그나로크
+Ragnarok Ragnarok
+*/
+ MSG_ID_BDE = 0xbde,
+/*20161214 to 20161214
+스크린샷에 자신 이외의 캐리터명이 표시되는 경우나 채팅창에 자신 이외의 캐릭터 대화가 표시되는 경우, 해당 사용자에게 반드시 양해를 구한 후 사용 해 주시기 바랍니다.
+20161221 to latest
+스크린샷에 자신 이외의 캐릭터명이 표시되는 경우나 채팅창에 자신 이외의 캐릭터 대화가 표시되는 경우, 해당 사용자에게 반드시 양해를 구한 후 사용 해 주시기 바랍니다.
+If your screenshot or chat box includes other users besides yourself, first ask permission from the other users before using it.
+*/
+ MSG_ID_BDF = 0xbdf,
+#endif
+#if PACKETVER >= 20161221
+/*20161221 to latest
+현재 상태에선 장비를 교체할 수 없습니다
+You cannot change equipment in current condition
+*/
+ MSG_ID_BE0 = 0xbe0,
+/*20161221 to latest
+해당 유저의 이름을 가져오고 있습니다
+Getting the user's name
+*/
+ MSG_ID_BE1 = 0xbe1,
+/*20161221 to latest
+해당 메시지는 사용 할 수 없는 내용을 포함하고 있습니다.
+This message includes contents you are not able to use.
+*/
+ MSG_ID_BE2 = 0xbe2,
+/*20161221 to latest
+아이템 구입에 실패하였습니다.
+Failed to purchase item.
+*/
+ MSG_ID_BE3 = 0xbe3,
+/*20161221 to latest
+신분증번호 하위 7자리가 일치하지 않습니다.
+The lower numbers of the identification number does not match.
+*/
+ MSG_ID_BE4 = 0xbe4,
+#endif
+#if PACKETVER >= 20161228
+/*20161228 to latest
+닫기
+Close
+*/
+ MSG_ID_BE5 = 0xbe5,
+/*20161228 to latest
+규칙
+Rule
+*/
+ MSG_ID_BE6 = 0xbe6,
+/*20161228 to latest
+1회 구매
+Purchase 1x
+*/
+ MSG_ID_BE7 = 0xbe7,
+/*20161228 to latest
+10회 구매
+Purchase 10x
+*/
+ MSG_ID_BE8 = 0xbe8,
+/*20161228 to latest
+100회 구매
+Purchase 100x
+*/
+ MSG_ID_BE9 = 0xbe9,
+/*20161228 to latest
+1등 당첨
+Win 1st prize
+*/
+ MSG_ID_BEA = 0xbea,
+/*20161228 to latest
+2등 당첨
+Win 2nd prize
+*/
+ MSG_ID_BEB = 0xbeb,
+/*20161228 to latest
+3등 당첨
+Win 3rd prize
+*/
+ MSG_ID_BEC = 0xbec,
+/*20161228 to 20170111
+복권 구매 금액
+Lottery purchase amount
+20170118 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BED = 0xbed,
+/*20161228 to 20170111
+참여 캐릭터
+Participating character
+20170118 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BEE = 0xbee,
+/*20161228 to latest
+제니 로또 당첨자
+Zeny Lottery winner
+*/
+ MSG_ID_BEF = 0xbef,
+/*20161228 to 20170111
+복권 진행일
+20170118 to latest
+복권 구매 금액
+Lottery purchase amount
+*/
+ MSG_ID_BF0 = 0xbf0,
+/*20161228 to latest
+참여 캐릭터
+Participating character
+*/
+ MSG_ID_BF1 = 0xbf1,
+/*20161228 to latest
+1등
+1st Price
+*/
+ MSG_ID_BF2 = 0xbf2,
+/*20161228 to latest
+2등
+2nd Price
+*/
+ MSG_ID_BF3 = 0xbf3,
+/*20161228 to latest
+3등
+3rd Price
+*/
+ MSG_ID_BF4 = 0xbf4,
+/*20161228 to latest
+구매 보상 아이템
+Purchase Reward Item
+*/
+ MSG_ID_BF5 = 0xbf5,
+/*20161228 to latest
+^1a1a1a복권 ^b%d개^/b를
+^4435b2%dZeny^1a1a1a로
+구매하시겠습니까?
+^1a1a1a Do you want to purchase ^b%d lottery tickets for
+^4435b2%dZeny^1a1a1a?
+*/
+ MSG_ID_BF6 = 0xbf6,
+/*20161228 to latest
+복권을 성공적으로 구매하였습니다.
+You have successfully purchased the lottery ticket.
+*/
+ MSG_ID_BF7 = 0xbf7,
+/*20161228 to latest
+소지 제니가 부족하여 복권을 구매 할 수 없습니다.
+Not enough Zeny to purchase lottey ticket.
+*/
+ MSG_ID_BF8 = 0xbf8,
+/*20161228 to latest
+최대 복권 구매 횟수는 1000회를 초과 할 수 없습니다.
+You are only able to purchase the tickets upto 1000 times.
+*/
+ MSG_ID_BF9 = 0xbf9,
+/*20161228 to latest
+예
+Yes
+*/
+ MSG_ID_BFA = 0xbfa,
+/*20161228 to latest
+아니요
+No
+*/
+ MSG_ID_BFB = 0xbfb,
+/*20161228 to latest
+HP
+*/
+ MSG_ID_BFC = 0xbfc,
+/*20161228 to latest
+SP
+*/
+ MSG_ID_BFD = 0xbfd,
+/*20161228 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFE = 0xbfe,
+/*20161228 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFF = 0xbff,
+/*20161228 to latest
+Exp
+*/
+ MSG_ID_C00 = 0xc00,
+/*20161228 to latest
+ all on
+*/
+ MSG_ID_C01 = 0xc01,
+/*20161228 to latest
+Play Replay Flie
+Start replay
+*/
+ MSG_ID_C02 = 0xc02,
+/*20161228 to latest
+P
+*/
+ MSG_ID_C03 = 0xc03,
+/*20161228 to latest
+Total
+*/
+ MSG_ID_C04 = 0xc04,
+/*20161228 to latest
+Basicinfo
+*/
+ MSG_ID_C05 = 0xc05,
+/*20161228 to latest
+Equip
+Equipment
+*/
+ MSG_ID_C06 = 0xc06,
+/*20161228 to latest
+Item
+Items
+*/
+ MSG_ID_C07 = 0xc07,
+/*20161228 to latest
+Skill
+Skills
+*/
+ MSG_ID_C08 = 0xc08,
+/*20161228 to latest
+Guild
+*/
+ MSG_ID_C09 = 0xc09,
+/*20161228 to latest
+Party
+*/
+ MSG_ID_C0A = 0xc0a,
+/*20161228 to latest
+Chatting
+Chat
+*/
+ MSG_ID_C0B = 0xc0b,
+/*20161228 to latest
+Shortcut
+Hotkeys
+*/
+ MSG_ID_C0C = 0xc0c,
+/*20161228 to latest
+Status
+*/
+ MSG_ID_C0D = 0xc0d,
+/*20161228 to latest
+ALL
+*/
+ MSG_ID_C0E = 0xc0e,
+/*20161228 to latest
+User Defined File Name
+Custom file name
+*/
+ MSG_ID_C0F = 0xc0f,
+/*20161228 to latest
+Repeated File Check
+Check file
+*/
+ MSG_ID_C10 = 0xc10,
+/*20161228 to latest
+on
+*/
+ MSG_ID_C11 = 0xc11,
+/*20161228 to latest
+<Basic Skin>
+<Basic>
+*/
+ MSG_ID_C12 = 0xc12,
+/*20161228 to latest
+Select Skin
+Choose skin
+*/
+ MSG_ID_C13 = 0xc13,
+#endif
+#if PACKETVER >= 20170111
+/*20170111 to latest
+현재 복권에 참여 중이라 삭제할 수 없습니다
+You cannot delete it because you are currently participating in the lottery
+*/
+ MSG_ID_C14 = 0xc14,
+/*20170111 to latest
+/achievement
+*/
+ MSG_ID_C15 = 0xc15,
+/*20170111 to latest
+제니 복권
+Zeny Lottery ticket
+*/
+ MSG_ID_C16 = 0xc16,
+/*20170111 to latest
+제니 복권 %d등 당첨 보상
+Zenyy Lottery %dprize reward
+*/
+ MSG_ID_C17 = 0xc17,
+/*20170111 to latest
+%d등 당첨 보상: %s
+%dprize reward: %s
+*/
+ MSG_ID_C18 = 0xc18,
+/*20170111 to latest
+제니 복권 누적 구매 보상
+Zeny Lottery Cumulative purchase reward
+*/
+ MSG_ID_C19 = 0xc19,
+/*20170111 to latest
+누적 %d회 보상: %s
+Cumulative %d times reward: %s
+*/
+ MSG_ID_C1A = 0xc1a,
+/*20170111 to latest
+제니 복권 구매 환불
+Zeny Lottery Refund
+*/
+ MSG_ID_C1B = 0xc1b,
+/*20170111 to 20170111
+환불 금액: %d Zeny
+환불 사유: 서버 내 복권 추첨 달성 실패
+20170118 to latest
+환불 금액: %d Zeny
+환불 사유: 서버 내 복권 추첨 달성 실패
+Refund amount: %d Zeny
+Reason for Refund: Failed to draw lottery in the server
+*/
+ MSG_ID_C1C = 0xc1c,
+/*20170111 to latest
+미니 파티창 추가
+Add Mini Party Chat
+*/
+ MSG_ID_C1D = 0xc1d,
+/*20170111 to latest
+미니 파티창 삭제
+Delete Mini Party Chat
+*/
+ MSG_ID_C1E = 0xc1e,
+#endif
+#if PACKETVER >= 20170118
+/*20170118 to latest
+복권 추첨이 모두 종료 되었습니다! 당첨자를 확인해주세요
+The lottery draw had ended! Check the winner!
+*/
+ MSG_ID_C1F = 0xc1f,
+/*20170118 to latest
+%d월 %d일
+%dMonth %dDay
+*/
+ MSG_ID_C20 = 0xc20,
+/*20170118 to latest
+다음 등급까지
+Till the next grade
+*/
+ MSG_ID_C21 = 0xc21,
+/*20170118 to latest
+전체
+All
+*/
+ MSG_ID_C22 = 0xc22,
+/*20170118 to latest
+미완료
+Incomplete
+*/
+ MSG_ID_C23 = 0xc23,
+/*20170118 to latest
+(달성!)
+(Accomplished!)
+*/
+ MSG_ID_C24 = 0xc24,
+/*20170118 to latest
+(미달성)
+(Not Accomplished)
+*/
+ MSG_ID_C25 = 0xc25,
+#endif
+#if PACKETVER >= 20170208
+/*20170208 to latest
+장비 교체
+Change equipment
+*/
+ MSG_ID_C26 = 0xc26,
+/*20170208 to latest
+CHANGE
+*/
+ MSG_ID_C27 = 0xc27,
+/*20170208 to latest
+힘 파라메터
+ ^cc0000근접 물리 공격력^ffffff, 소지무게
+Power Parameter
+ ^cc0000Melee PhysicalAttack^ffffff, Carrying Weight
+*/
+ MSG_ID_C28 = 0xc28,
+/*20170208 to latest
+민첩성 파라메터
+^cc0000공격 속도^ffffff, 회피율, 물리 방어력
+Agility Parameter
+^cc0000Attack Speed^ffffff, Dodge, Physical Defense
+*/
+ MSG_ID_C29 = 0xc29,
+/*20170208 to latest
+체력 파라메터
+^cc0000최대 체력^ffffff, 물리 방어력, 마법 방어력
+HP Parameter
+^cc0000Max HP^ffffff, Physical Defense, Magic Defense
+*/
+ MSG_ID_C2A = 0xc2a,
+/*20170208 to latest
+지력 파라메터
+^cc0000마법 공격력^ffffff, 캐스팅 시간, 마법 방어력
+Intellect Parameter
+^cc0000Magic Attack^ffffff, Casting Time, Magic Defense
+*/
+ MSG_ID_C2B = 0xc2b,
+/*20170208 to latest
+손재주 파라메터
+^cc0000원거리 물리 공격력^ffffff, 명중률, 캐스팅 시간, 마법 공격력
+Handcraft Parameter
+^cc0000Long Range Physical Attack^ffffff, Accuracy, Casting Time, Magic Attack
+*/
+ MSG_ID_C2C = 0xc2c,
+/*20170208 to latest
+운 파라메터
+^cc0000치명타율^ffffff, 명중률, 물리공격력, 마법공격력, 회피율
+Moon Parameter
+^cc0000Critical Rate^ffffff, Accuracy, Physical Attack, Magic Attack, Dodge
+*/
+ MSG_ID_C2D = 0xc2d,
+/*20170208 to latest
+물리 공격력
+Physical Attack
+*/
+ MSG_ID_C2E = 0xc2e,
+/*20170208 to latest
+물리 방어력
+Physical Defense
+*/
+ MSG_ID_C2F = 0xc2f,
+/*20170208 to latest
+명중률
+Accuracy
+*/
+ MSG_ID_C30 = 0xc30,
+/*20170208 to latest
+치명타율
+Critical Rate
+*/
+ MSG_ID_C31 = 0xc31,
+/*20170208 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_ID_C32 = 0xc32,
+/*20170208 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_ID_C33 = 0xc33,
+/*20170208 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_ID_C34 = 0xc34,
+/*20170208 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_ID_C35 = 0xc35,
+/*20170208 to latest
+회피율
+Dodge
+*/
+ MSG_ID_C36 = 0xc36,
+/*20170208 to latest
+공격 속도
+Attack Speed
+*/
+ MSG_ID_C37 = 0xc37,
+#endif
+#if PACKETVER >= 20170215
+/*20170215 to latest
+단축키 안내
+Shortcut
+*/
+ MSG_ID_C38 = 0xc38,
+/*20170215 to latest
+옵션
+Option
+*/
+ MSG_ID_C39 = 0xc39,
+/*20170215 to latest
+스킬 단축키 (F1 ~ F9)
+Skill Shortcut Key (F1 ~ F9)
+*/
+ MSG_ID_C3A = 0xc3a,
+/*20170215 to latest
+이미지 캡쳐
+Capture Image
+*/
+ MSG_ID_C3B = 0xc3b,
+/*20170215 to latest
+확대
+Zoom In
+*/
+ MSG_ID_C3C = 0xc3c,
+/*20170215 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_C3D = 0xc3d,
+/*20170215 to latest
+길드
+Guild
+*/
+ MSG_ID_C3E = 0xc3e,
+/*20170215 to latest
+은행
+Bank
+*/
+ MSG_ID_C3F = 0xc3f,
+/*20170215 to latest
+우편
+Mail
+*/
+ MSG_ID_C40 = 0xc40,
+/*20170215 to latest
+캐시 상점
+Cash Shop
+*/
+ MSG_ID_C41 = 0xc41,
+/*20170215 to latest
+앉기
+Sit
+*/
+ MSG_ID_C42 = 0xc42,
+/*20170215 to latest
+이동
+Move
+*/
+ MSG_ID_C43 = 0xc43,
+/*20170215 to latest
+회전
+Rotate
+*/
+ MSG_ID_C44 = 0xc44,
+/*20170215 to latest
+파티장은 파티장을 다른 파티원에게 위임 후 탈퇴 가능합니다.
+The Party Leader can be dropped out only after another party member becomes a Party Leader.
+*/
+ MSG_ID_C45 = 0xc45,
+/*20170215 to latest
+이 동영상을 그만 보시겠습니까?
+Do you want to stop viewing this video?
+*/
+ MSG_ID_C46 = 0xc46,
+/*20170215 to latest
+ 장비가 장비 교체 창에 장착 되었습니다.
+ gear has been equipped in the gear equipment pop-up.
+*/
+ MSG_ID_C47 = 0xc47,
+/*20170215 to latest
+ 장비가 장비 교체 창에서 해제 되었습니다.
+ gear has been removed in the gear equipment pop-up.
+*/
+ MSG_ID_C48 = 0xc48,
+#endif
+#if PACKETVER >= 20170222
+/*20170222 to latest
+현재가 마지막 라인입니다.
+This is the last line.
+*/
+ MSG_ID_C49 = 0xc49,
+/*20170222 to latest
+%.1f%% ( 기본 100%% + 프리미엄 %.1f%%+ %s서버 %.1f%% )
+%.1f%% ( Base 100%% + Premium %.1f%%+ %sServer %.1f%% )
+*/
+ MSG_ID_C4A = 0xc4a,
+#endif
+#if PACKETVER >= 20170228
+/*20170228 to latest
+한자
+Chinese character
+*/
+ MSG_ID_C4B = 0xc4b,
+/*20170228 to latest
+단축키 설정
+Shortcut Settings
+*/
+ MSG_ID_C4C = 0xc4c,
+#endif
+#if PACKETVER >= 20170308
+/*20170308 to latest
+당신의 정액제 기간은 %s에 종료됩니다.
+Your subscription will be ended on%s.
+*/
+ MSG_ID_C4D = 0xc4d,
+/*20170308 to latest
+리플레이 파일을 찾지 못하였습니다.
+Cannot find the replay file.
+*/
+ MSG_ID_C4E = 0xc4e,
+/*20170308 to 20170801
+신발
+Head
+20170809 to latest
+의상
+Shoes
+*/
+ MSG_ID_C4F = 0xc4f,
+/*20170308 to 20170801
+머리
+Costume
+20170809 to latest
+신발
+Head
+*/
+ MSG_ID_C50 = 0xc50,
+/*20170308 to latest
+갑옷
+Armor
+*/
+ MSG_ID_C51 = 0xc51,
+/*20170308 to latest
+어깨
+Shoulders
+*/
+ MSG_ID_C52 = 0xc52,
+/*20170308 to latest
+악세
+Accessory
+*/
+ MSG_ID_C53 = 0xc53,
+/*20170308 to 20170801
+의상
+Shoes
+20170809 to latest
+머리
+Costume
+*/
+ MSG_ID_C54 = 0xc54,
+/*20170308 to latest
+차순정렬
+Sort Order
+*/
+ MSG_ID_C55 = 0xc55,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+일반 장비
+Normal Gear
+*/
+ MSG_ID_C56 = 0xc56,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+특수 장비
+Special Gear
+*/
+ MSG_ID_C57 = 0xc57,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+칭호
+Style
+*/
+ MSG_ID_C58 = 0xc58,
+#endif
+#if PACKETVER >= 20170315
+/*20170315 to latest
+/quake : 화면 흔들림 효과 On/Off
+/quake : Screen Shaking Effect On/Off
+*/
+ MSG_ID_C59 = 0xc59,
+/*20170315 to latest
+/aura2 : 오오라를 완전히 Off 시킬 수 있습니다 On Off
+/aura2 : You can completely turn off the aurora On/Off
+*/
+ MSG_ID_C5A = 0xc5a,
+/*20170315 to latest
+기본 설정
+Default Settings
+*/
+ MSG_ID_C5B = 0xc5b,
+/*20170315 to latest
+고급 설정
+Advanced Settings
+*/
+ MSG_ID_C5C = 0xc5c,
+/*20170315 to latest
+기본설정값이 적용됩니다.
+The Default Settings will be applied.
+*/
+ MSG_ID_C5D = 0xc5d,
+/*20170315 to latest
+기본 설정값이 적용됩니다. 동의하십니까?
+The Default Settings will be applied. Do you agree?
+*/
+ MSG_ID_C5E = 0xc5e,
+/*20170315 to latest
+설정값이 적용됩니다. 동의하십니까?
+The settings will be applied. Do you agree?
+*/
+ MSG_ID_C5F = 0xc5f,
+/*20170315 to latest
+설정값을 적용하려면 재시작이 필요합니다. 동의하십니까?
+Need to restart to apply the settings. Do you agree?
+*/
+ MSG_ID_C60 = 0xc60,
+/*20170315 to latest
+안개
+Fog
+*/
+ MSG_ID_C61 = 0xc61,
+/*20170315 to latest
+오오라 간략화
+Simplified aurora
+*/
+ MSG_ID_C62 = 0xc62,
+/*20170315 to latest
+오오라켜기
+Turn on aurora
+*/
+ MSG_ID_C63 = 0xc63,
+/*20170315 to latest
+이펙트 표시
+Show Effect
+*/
+ MSG_ID_C64 = 0xc64,
+/*20170315 to latest
+음영 표시
+Show Shadows
+*/
+ MSG_ID_C65 = 0xc65,
+/*20170315 to latest
+No Shift
+*/
+ MSG_ID_C66 = 0xc66,
+/*20170315 to latest
+하드웨어 T&L 가속기능을 선택합니다
+Select Hardware T&L Acceleration Function
+*/
+ MSG_ID_C67 = 0xc67,
+/*20170315 to latest
+게임의 해상도를 선택합니다
+Select Game Resolution
+*/
+ MSG_ID_C68 = 0xc68,
+/*20170315 to latest
+전체화면 사용
+Use full screen
+*/
+ MSG_ID_C69 = 0xc69,
+/*20170315 to latest
+마우스 고정
+Fix mouse
+*/
+ MSG_ID_C6A = 0xc6a,
+/*20170315 to latest
+이펙트 설정
+Effect Settings
+*/
+ MSG_ID_C6B = 0xc6b,
+/*20170315 to latest
+Control 설정
+Control Settings
+*/
+ MSG_ID_C6C = 0xc6c,
+/*20170315 to latest
+그래픽 장치 설정
+Graphic Device Settings
+*/
+ MSG_ID_C6D = 0xc6d,
+/*20170315 to latest
+그래픽 해상도 설정
+Graphic Resolution Settings
+*/
+ MSG_ID_C6E = 0xc6e,
+/*20170315 to latest
+전체 화면 유무 설정
+Full Screen Settings
+*/
+ MSG_ID_C6F = 0xc6f,
+/*20170315 to latest
+마우스 고정 여부 설정
+Fix mouse Settings
+*/
+ MSG_ID_C70 = 0xc70,
+/*20170315 to latest
+수수료 :
+Commission :
+*/
+ MSG_ID_C71 = 0xc71,
+/*20170315 to latest
+수수료 총액 :
+Total commission amount :
+*/
+ MSG_ID_C72 = 0xc72,
+/*20170315 to latest
+수신인 설정
+Select receiver
+*/
+ MSG_ID_C73 = 0xc73,
+/*20170315 to latest
+수신그룹 설정
+Select receiving group
+*/
+ MSG_ID_C74 = 0xc74,
+/*20170315 to latest
+크기 변경(F10)
+Change size(F10)
+*/
+ MSG_ID_C75 = 0xc75,
+/*20170315 to latest
+메일함을 불러오는 중 입니다.
+불필요한 메일은 ^c92114삭제^000000해 주세요~!!
+Loading the mailbox.
+^c92114Delete^000000unnecessary emails!!
+*/
+ MSG_ID_C76 = 0xc76,
+/*20170315 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_C77 = 0xc77,
+/*20170315 to latest
+제목
+Title
+*/
+ MSG_ID_C78 = 0xc78,
+/*20170315 to latest
+보낸이
+Sender
+*/
+ MSG_ID_C79 = 0xc79,
+#endif
+#if PACKETVER >= 20170322
+/*20170322 to latest
+라그나로크 클라이언트와 동시에 실행이 불가능 합니다. setup을 종료합니다
+*/
+ MSG_ID_C7A = 0xc7a,
+/*20170322 to latest
+추가 기능 설정
+*/
+ MSG_ID_C7B = 0xc7b,
+/*20170322 to latest
+This account does not exist.
+*/
+ MSG_ID_C7C = 0xc7c,
+/*20170322 to latest
+Passwords do not match.
+*/
+ MSG_ID_C7D = 0xc7d,
+/*20170322 to latest
+Failed to pass IP authentication
+*/
+ MSG_ID_C7E = 0xc7e,
+/*20170322 to latest
+No identification number, supplement your registration information
+*/
+ MSG_ID_C7F = 0xc7f,
+/*20170322 to latest
+Account block
+*/
+ MSG_ID_C80 = 0xc80,
+/*20170322 to latest
+System error
+*/
+ MSG_ID_C81 = 0xc81,
+/*20170322 to latest
+unknown error found.
+*/
+ MSG_ID_C82 = 0xc82,
+#endif
+#if PACKETVER >= 20170329
+/*20170329 to latest
+길안내 아이콘 설정
+*/
+ MSG_ID_C83 = 0xc83,
+/*20170329 to latest
+길 안내 정보 UI
+*/
+ MSG_ID_C84 = 0xc84,
+/*20170329 to latest
+길 안내 정보 열기
+*/
+ MSG_ID_C85 = 0xc85,
+/*20170329 to latest
+현재 위치 공유
+*/
+ MSG_ID_C86 = 0xc86,
+/*20170329 to latest
+검색결과[0]
+*/
+ MSG_ID_C87 = 0xc87,
+/*20170329 to latest
+검색&안내
+*/
+ MSG_ID_C88 = 0xc88,
+/*20170329 to 20170329
+위치 값은 음수 값이 들어 올 수 없습니다.
+20170405 to latest
+위치가 올바르지 않습니다.
+*/
+ MSG_ID_C89 = 0xc89,
+/*20170329 to latest
+검색결과[%d]
+*/
+ MSG_ID_C8A = 0xc8a,
+/*20170329 to latest
+길안내 표시를 위한 아이콘 설정
+*/
+ MSG_ID_C8B = 0xc8b,
+/*20170329 to latest
+길 찾기에 zeny 허용
+*/
+ MSG_ID_C8C = 0xc8c,
+/*20170329 to latest
+내비게이션 도킹 해제
+*/
+ MSG_ID_C8D = 0xc8d,
+/*20170329 to latest
+활성화 하지 않은 계정입니다.
+*/
+ MSG_ID_C8E = 0xc8e,
+#endif
+#if PACKETVER >= 20170405
+/*20170405 to latest
+클릭한 위치가 채팅창에 공유 됩니다.
+*/
+ MSG_ID_C8F = 0xc8f,
+/*20170405 to latest
+4. Service 항목을 선택하면 Zeny&비공정 이용을 고려하여 안내 한다.
+*/
+ MSG_ID_C90 = 0xc90,
+/*20170405 to latest
+5. [<-] 버튼 : 길안내 모드 <-> 검색 모드를 바꾸거나
+*/
+ MSG_ID_C91 = 0xc91,
+/*20170405 to latest
+공유하기 모드 -> 서치 모드로 돌아갈때 사용 된다.
+*/
+ MSG_ID_C92 = 0xc92,
+/*20170405 to latest
+경험치 %lld 얻음
+*/
+ MSG_ID_C93 = 0xc93,
+/*20170405 to latest
+'%lld'의 경험치를
+*/
+ MSG_ID_C94 = 0xc94,
+/*20170405 to 20170517
+^b- 노점 수수료 안내^/b
+노점 설정 가격에 따라 일정 비율의 수수료가 부가됩니다.
+
+ ^b> 수수료 비율^/b
+각 금액에 따른 수수료의 비율은 아래와 같습니다.
+
+0 z ~ 10,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,001 z ~ 100,000 z
+ = 수수료율 : ^1567fe2%^000000
+100,001 z ~ 1,000,000 z
+ = 수수료율 : ^1567fe4%^000000
+1,000,001 z ~ 10,000,000 z
+ = 수수료율 : ^1567fe6%^000000
+10,000,001 z ~ 100,000,000 z
+ = 수수료율 : ^1567fe8%^000000
+100,000,001 z 이상
+ = 수수료율 : ^1567fe10%^000000
+20170524 to latest
+^b- 노점 수수료 안내^/b
+노점 설정 가격에 따라 일정 비율의 수수료가 부가됩니다.
+
+ ^b> 수수료 비율^/b
+각 금액에 따른 수수료의 비율은 아래와 같습니다.
+
+0 z ~ 10,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,001 z ~ 100,000 z
+ = 수수료율 : ^1567fe0%^000000
+100,001 z ~ 1,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+1,000,001 z ~ 10,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,000,001 z ~ 100,000,000 z
+ = 수수료율 : ^1567fe5%^000000
+100,000,001 z 이상
+ = 수수료율 : ^1567fe5%^000000
+*/
+ MSG_ID_C95 = 0xc95,
+/*20170405 to latest
+실거래가 :
+*/
+ MSG_ID_C96 = 0xc96,
+/*20170405 to latest
+※ 아이템 판매시, 실거래가만큼 제니를 획득합니다.
+*/
+ MSG_ID_C97 = 0xc97,
+/*20170405 to latest
+※ 아이템 구매시, 실거래가만큼 제니가 차감됩니다.
+*/
+ MSG_ID_C98 = 0xc98,
+/*20170405 to latest
+채팅방 개설
+*/
+ MSG_ID_C99 = 0xc99,
+#endif
+#if PACKETVER >= 20170412
+/*20170412 to latest
+해당 캐릭터는 파티가입이 가능하지 않은 레벨입니다.
+*/
+ MSG_ID_C9A = 0xc9a,
+/*20170412 to latest
+'%lld'의 잡경험치를
+*/
+ MSG_ID_C9B = 0xc9b,
+/*20170412 to latest
+잡경험치 %lld 얻음
+*/
+ MSG_ID_C9C = 0xc9c,
+#endif
+#if PACKETVER >= 20170419
+/*20170419 to latest
+현재위치(대로)에는 노점을 개설할 수 없습니다.
+*/
+ MSG_ID_C9D = 0xc9d,
+#endif
+#if PACKETVER >= 20170426
+/*20170426 to latest
+초 후 가능합니다.
+*/
+ MSG_ID_C9E = 0xc9e,
+#endif
+#if PACKETVER >= 20170517
+/*20170517 to latest
+파티원
+*/
+ MSG_ID_C9F = 0xc9f,
+/*20170517 to latest
+SNS 전송실패(%d)
+*/
+ MSG_ID_CA0 = 0xca0,
+/*20170517 to latest
+SNS 서버 연결실패
+*/
+ MSG_ID_CA1 = 0xca1,
+/*20170517 to latest
+SNS 로그인 후 사용 가능합니다.
+*/
+ MSG_ID_CA2 = 0xca2,
+/*20170517 to latest
+접속 할 수 있는 주소가 존재하지 않습니다.
+*/
+ MSG_ID_CA3 = 0xca3,
+#endif
+#if PACKETVER >= 20170524
+/*20170524 to latest
+미니파티창이 겹쳐져 있어 사용하실 수 없습니다.
+*/
+ MSG_ID_CA4 = 0xca4,
+#endif
+#if PACKETVER >= 20170531
+/*20170531 to latest
+나의 판매노점
+*/
+ MSG_ID_CA5 = 0xca5,
+#endif
+#if PACKETVER >= 20170614
+/*20170614 to latest
+BOX
+*/
+ MSG_ID_CA6 = 0xca6,
+/*20170614 to latest
+팁박스
+*/
+ MSG_ID_CA7 = 0xca7,
+#endif
+#if PACKETVER >= 20170621
+/*20170621 to latest
+트윗을 성공했습니다.
+*/
+ MSG_ID_CA8 = 0xca8,
+#endif
+#if PACKETVER >= 20170628
+/*20170628 to latest
+다시하기
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CA9 = 0xca9,
+/*20170628 to 20170809
+제련재료가 변경되어 다시하기가 비활성화 되었습니다.
+20170816 to latest
+다시하기가 비활성화되었습니다. 제련 재료를 다시 선택해주세요.
+*/
+ MSG_ID_CAA = 0xcaa,
+/*20170628 to latest
+제련석이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAB = 0xcab,
+/*20170628 to latest
+제니가 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAC = 0xcac,
+/*20170628 to latest
+대장장이의 축복이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAD = 0xcad,
+/*20170628 to latest
+아이템이 파괴되었습니다.
+*/
+ MSG_ID_CAE = 0xcae,
+/*20170628 to latest
+모든 스테이터스가 감소되었습니다.
+*/
+ MSG_ID_CAF = 0xcaf,
+/*20170628 to latest
+모든 스테이터스 감소 효과가 해제되었습니다.
+*/
+ MSG_ID_CB0 = 0xcb0,
+/*20170628 to latest
+OTP 비밀번호는 8자리 입니다.
+*/
+ MSG_ID_CB1 = 0xcb1,
+#endif
+#if PACKETVER >= 20170705
+/*20170705 to latest
+통합계정
+*/
+ MSG_ID_CB2 = 0xcb2,
+/*20170705 to latest
+라그나로크
+*/
+ MSG_ID_CB3 = 0xcb3,
+/*20170705 to latest
+서비스 점검 중입니다.
+*/
+ MSG_ID_CB4 = 0xcb4,
+/*20170705 to latest
+검색어를 입력해주세요
+*/
+ MSG_ID_CB5 = 0xcb5,
+/*20170705 to latest
+MOTP
+*/
+ MSG_ID_CB6 = 0xcb6,
+/*20170705 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_CB7 = 0xcb7,
+/*20170705 to latest
+휴대폰에 다운받은 GNJOY MOTP를 실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_CB8 = 0xcb8,
+#endif
+#if PACKETVER >= 20170712
+/*20170712 to latest
+파티장을 위임할 파티원이 존재하지 않습니다. 파티를 해산하시겠습니까?
+*/
+ MSG_ID_CB9 = 0xcb9,
+#endif
+#if PACKETVER >= 20170719
+/*20170719 to latest
+ - 만18세이상
+*/
+ MSG_ID_CBA = 0xcba,
+/*20170719 to latest
+ - 유료서버
+*/
+ MSG_ID_CBB = 0xcbb,
+/*20170719 to latest
+ - 무료서버
+*/
+ MSG_ID_CBC = 0xcbc,
+/*20170719 to latest
+쾌적
+*/
+ MSG_ID_CBD = 0xcbd,
+/*20170719 to latest
+보통
+Normal
+*/
+ MSG_ID_CBE = 0xcbe,
+/*20170719 to latest
+혼잡
+*/
+ MSG_ID_CBF = 0xcbf,
+/*20170719 to latest
+포화
+*/
+ MSG_ID_CC0 = 0xcc0,
+/*20170719 to latest
+map
+*/
+ MSG_ID_CC1 = 0xcc1,
+/*20170719 to latest
+월드창고는 인벤토리 아이템만 입출고 할 수 있습니다.
+*/
+ MSG_ID_CC2 = 0xcc2,
+/*20170719 to latest
+월드창고에는 펫알을 입고할 수 없습니다.
+*/
+ MSG_ID_CC3 = 0xcc3,
+/*20170719 to latest
+월드창고에는 제작아이템을 입고할 수 없습니다.
+*/
+ MSG_ID_CC4 = 0xcc4,
+/*20170719 to latest
+%s 에서는 출고 할 수 없는 아이템입니다.
+*/
+ MSG_ID_CC5 = 0xcc5,
+#endif
+#if PACKETVER >= 20170726
+/*20170726 to latest
+던전 파괴
+*/
+ MSG_ID_CC6 = 0xcc6,
+/*20170726 to latest
+[%s] 님이 제련을 성공하여, [+%d %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_CC7 = 0xcc7,
+/*20170726 to latest
+[%s] 님이 [+%d %s] 아이템의 제련에 실패하였습니다.
+*/
+ MSG_ID_CC8 = 0xcc8,
+/*20170726 to latest
+파티장을 위임한 이후에 탈퇴할 수 있습니다.
+*/
+ MSG_ID_CC9 = 0xcc9,
+#endif
+#if PACKETVER >= 20170809
+/*20170809 to latest
+오름
+*/
+ MSG_ID_CCA = 0xcca,
+/*20170809 to latest
+내림
+*/
+ MSG_ID_CCB = 0xccb,
+/*20170809 to latest
+기본
+*/
+ MSG_ID_CCC = 0xccc,
+/*20170809 to latest
+변조된 파일이 발견되었습니다. 게임을 다시 실행시켜주세요.
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CCD = 0xccd,
+#endif
+#if PACKETVER >= 20170823
+/*20170823 to latest
+%s 은(는) 이맵에서 이동이 제한된 아이템입니다.
+*/
+ MSG_ID_CCE = 0xcce,
+#endif
+#if PACKETVER >= 20170906
+/*20170906 to latest
+스스로
+먹이먹기
+*/
+ MSG_ID_CCF = 0xccf,
+/*20170906 to latest
+로덱스 작성창이 열려있는 동안 호문클루스가 먹이를 먹지 못합니다.
+*/
+ MSG_ID_CD0 = 0xcd0,
+/*20170906 to latest
+호문클루스가 먹이를 먹었습니다. '%s' 잔여량 %d개
+*/
+ MSG_ID_CD1 = 0xcd1,
+/*20170906 to latest
+호문클루스 스스로 먹이 먹기 활성화 On
+*/
+ MSG_ID_CD2 = 0xcd2,
+/*20170906 to latest
+호문클루스 스스로 먹이 먹기 활성화 Off
+*/
+ MSG_ID_CD3 = 0xcd3,
+/*20170906 to latest
+호문클루스는 주인이 획득하는 경험치의
+10%만큼을 자신의 경험치로 분배 받습니다.
+*/
+ MSG_ID_CD4 = 0xcd4,
+/*20170906 to latest
+확률 : %d%%
+*/
+ MSG_ID_CD5 = 0xcd5,
+/*20170906 to latest
+해당 대상은 호문의 공격대상이 아닙니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD6 = 0xcd6,
+/*20170906 to latest
+호문의 공격대상이 존재하지 않습니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD7 = 0xcd7,
+#endif
+#if PACKETVER >= 20170913
+/*20170913 to latest
+판매 리스트
+*/
+ MSG_ID_CD8 = 0xcd8,
+/*20170913 to latest
+구입 리스트
+*/
+ MSG_ID_CD9 = 0xcd9,
+/*20170913 to latest
+신규
+New
+*/
+ MSG_ID_CDA = 0xcda,
+/*20170913 to latest
+인기
+Headgears
+*/
+ MSG_ID_CDB = 0xcdb,
+/*20170913 to latest
+한정
+Limited
+*/
+ MSG_ID_CDC = 0xcdc,
+/*20170913 to latest
+임대장비
+Rental Items
+*/
+ MSG_ID_CDD = 0xcdd,
+/*20170913 to latest
+영구장비
+Equipments
+*/
+ MSG_ID_CDE = 0xcde,
+/*20170913 to latest
+버프
+Scrolls
+*/
+ MSG_ID_CDF = 0xcdf,
+/*20170913 to latest
+회복
+Consumables
+*/
+ MSG_ID_CE0 = 0xce0,
+/*20170913 to latest
+기타
+Other
+*/
+ MSG_ID_CE1 = 0xce1,
+/*20170913 to latest
+특가
+Special
+*/
+ MSG_ID_CE2 = 0xce2,
+/*20170913 to latest
+충전하기
+*/
+ MSG_ID_CE3 = 0xce3,
+/*20170913 to latest
+구입하기
+*/
+ MSG_ID_CE4 = 0xce4,
+/*20170913 to 20171206
+https://payment.gnjoy.com/bill/login.grv
+20171213 to latest
+http://member.gnjoy.com/user/pay/chargelist.asp
+*/
+ MSG_ID_CE5 = 0xce5,
+/*20170913 to latest
+아이템 검색
+*/
+ MSG_ID_CE6 = 0xce6,
+/*20170913 to latest
+무료캐시
+*/
+ MSG_ID_CE7 = 0xce7,
+/*20170913 to latest
+무료캐시 사용
+*/
+ MSG_ID_CE8 = 0xce8,
+/*20170913 to latest
+소지캐시
+*/
+ MSG_ID_CE9 = 0xce9,
+/*20170913 to latest
+수량갱신
+*/
+ MSG_ID_CEA = 0xcea,
+/*20170913 to latest
+성제(여)
+*/
+ MSG_ID_CEB = 0xceb,
+/*20170913 to latest
+소울리퍼(여)
+*/
+ MSG_ID_CEC = 0xcec,
+/*20170913 to latest
+성제(남)
+*/
+ MSG_ID_CED = 0xced,
+/*20170913 to latest
+소울리퍼(남)
+*/
+ MSG_ID_CEE = 0xcee,
+#endif
+#if PACKETVER >= 20170920
+/*20170920 to latest
+무게가 %d 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+*/
+ MSG_ID_CEF = 0xcef,
+/*20170920 to latest
+한 번에 구입 가능한 아이템의 가짓수는 8개입니다.
+*/
+ MSG_ID_CF0 = 0xcf0,
+/*20170920 to 20190228
+http://gift.zhaouc.com/#/index
+http://gift.zhaouc.com/
+20190306 to latest
+http://gift.zhaouc.com/
+*/
+ MSG_ID_CF1 = 0xcf1,
+#endif
+#if PACKETVER >= 20170927
+/*20170927 to latest
+UNKNOWN ERROR:%d
+*/
+ MSG_ID_CF2 = 0xcf2,
+/*20170927 to latest
+NOT USER
+*/
+ MSG_ID_CF3 = 0xcf3,
+/*20170927 to latest
+THIS ACCOUNT ID IS BLOCKED
+*/
+ MSG_ID_CF4 = 0xcf4,
+/*20170927 to latest
+COUNTRY REJECT (OR NOT AVALIABLE USER )
+*/
+ MSG_ID_CF5 = 0xcf5,
+/*20170927 to latest
+NOT MATCH PASSWORD
+*/
+ MSG_ID_CF6 = 0xcf6,
+/*20170927 to latest
+NOT EMAIL CERT
+*/
+ MSG_ID_CF7 = 0xcf7,
+/*20170927 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CF8 = 0xcf8,
+/*20170927 to latest
+COUNTRY REJECT
+*/
+ MSG_ID_CF9 = 0xcf9,
+/*20170927 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CFA = 0xcfa,
+/*20170927 to latest
+WEB BLOCK
+*/
+ MSG_ID_CFB = 0xcfb,
+/*20170927 to latest
+AGE LIMIT USER
+*/
+ MSG_ID_CFC = 0xcfc,
+/*20170927 to latest
+PASSWORD HAS NOT BEEN CHANGED FOR MORE THAN 90DAYS
+*/
+ MSG_ID_CFD = 0xcfd,
+/*20170927 to latest
+INPUT DATA ERROR
+*/
+ MSG_ID_CFE = 0xcfe,
+/*20170927 to latest
+ERROR DATABASE
+*/
+ MSG_ID_CFF = 0xcff,
+/*20170927 to latest
+ERROR SYSTEM
+*/
+ MSG_ID_D00 = 0xd00,
+/*20170927 to 20171025
+%s 지불
+20171101 to latest
+%s 소모
+*/
+ MSG_ID_D01 = 0xd01,
+/*20170927 to latest
+비용지불
+*/
+ MSG_ID_D02 = 0xd02,
+/*20170927 to latest
+출발 가능한 맵이 아닙니다.
+*/
+ MSG_ID_D03 = 0xd03,
+/*20170927 to latest
+이동 불가능한 맵입니다
+*/
+ MSG_ID_D04 = 0xd04,
+/*20170927 to latest
+아이템이 부족합니다.
+*/
+ MSG_ID_D05 = 0xd05,
+/*20170927 to latest
+줄 바꿈 없이 한 줄로 입력해주세요.
+*/
+ MSG_ID_D06 = 0xd06,
+#endif
+#if PACKETVER >= 20171011
+/*20171011 to latest
+불량 단어가 포함된 이름은 등록할 수 없습니다.
+*/
+ MSG_ID_D07 = 0xd07,
+#endif
+#if PACKETVER >= 20171018
+/*20171018 to latest
+회원 가입을 위해 공식 홈페이지로 이동됩니다.
+*/
+ MSG_ID_D08 = 0xd08,
+#endif
+#if PACKETVER >= 20171025
+/*20171025 to latest
+TokenAgency 서버 연결 실패
+*/
+ MSG_ID_D09 = 0xd09,
+/*20171025 to latest
+과금정보
+*/
+ MSG_ID_D0A = 0xd0a,
+/*20171025 to latest
+삭제예약
+*/
+ MSG_ID_D0B = 0xd0b,
+/*20171025 to latest
+예약취소
+*/
+ MSG_ID_D0C = 0xd0c,
+/*20171025 to latest
+게임시작
+*/
+ MSG_ID_D0D = 0xd0d,
+/*20171025 to latest
+삭제
+Delete
+*/
+ MSG_ID_D0E = 0xd0e,
+/*20171025 to latest
+Character List
+*/
+ MSG_ID_D0F = 0xd0f,
+/*20171025 to latest
+공지
+Notice
+*/
+ MSG_ID_D10 = 0xd10,
+/*20171025 to latest
+생성
+*/
+ MSG_ID_D11 = 0xd11,
+/*20171025 to latest
+Hair Style
+*/
+ MSG_ID_D12 = 0xd12,
+/*20171025 to latest
+Hair Color
+*/
+ MSG_ID_D13 = 0xd13,
+/*20171025 to latest
+중복확인
+*/
+ MSG_ID_D14 = 0xd14,
+/*20171025 to latest
+%d시 %d분 %d초
+*/
+ MSG_ID_D15 = 0xd15,
+/*20171025 to latest
+MOTP 입력 시간이 초과되었습니다. 처음부터 다시 로그인해주십시오.
+*/
+ MSG_ID_D16 = 0xd16,
+/*20171025 to latest
+뒤로가기
+*/
+ MSG_ID_D17 = 0xd17,
+#endif
+#if PACKETVER >= 20171101
+/*20171101 to latest
+아이템을 사용할 수 없습니다.
+*/
+ MSG_ID_D18 = 0xd18,
+/*20171101 to latest
+동일한 맵으로 이동할 수 없습니다.
+*/
+ MSG_ID_D19 = 0xd19,
+/*20171101 to latest
+사망시 이동이 불가능합니다.
+*/
+ MSG_ID_D1A = 0xd1a,
+/*20171101 to latest
+캐릭터 생성
+*/
+ MSG_ID_D1B = 0xd1b,
+#endif
+#if PACKETVER >= 20171108
+/*20171108 to latest
+모험가 중개소 등록
+*/
+ MSG_ID_D1C = 0xd1c,
+/*20171108 to 20191120
+모집 중단
+20191127 to latest
+모험가 중개소 등록하기
+*/
+ MSG_ID_D1D = 0xd1d,
+/*20171108 to 20191120
+모험가 중개소 설정
+20191127 to latest
+모집 중단
+*/
+ MSG_ID_D1E = 0xd1e,
+/*20171108 to 20191120
+전 지역
+20191127 to latest
+메모
+Note
+*/
+ MSG_ID_D1F = 0xd1f,
+/*20171108 to 20191120
+직접기재
+20191127 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_D20 = 0xd20,
+/*20171108 to 20191120
+검사계열
+20191127 to latest
+필드
+*/
+ MSG_ID_D21 = 0xd21,
+/*20171108 to 20191120
+법사계열
+20191127 to latest
+던전
+Dungeon
+*/
+ MSG_ID_D22 = 0xd22,
+/*20171108 to 20191120
+궁수계열
+20191127 to latest
+MD
+*/
+ MSG_ID_D23 = 0xd23,
+/*20171108 to 20191120
+복사계열
+20191127 to latest
+낙원단
+*/
+ MSG_ID_D24 = 0xd24,
+/*20171108 to 20191120
+상인계열
+20191127 to latest
+기타
+Other
+*/
+ MSG_ID_D25 = 0xd25,
+/*20171108 to 20191120
+도둑계열
+20191127 to latest
+검색
+Search
+*/
+ MSG_ID_D26 = 0xd26,
+/*20171108 to 20191120
+태권계열
+20191127 to latest
+초기화
+*/
+ MSG_ID_D27 = 0xd27,
+/*20171108 to 20191120
+닌자계열
+20191127 to latest
+파티가입신청
+*/
+ MSG_ID_D28 = 0xd28,
+/*20171108 to 20191120
+건슬링거계열
+20191127 to latest
+목적
+*/
+ MSG_ID_D29 = 0xd29,
+/*20171108 to 20191120
+도람족계열
+20191127 to latest
+※욕설, 현거래등 운영 규칙에 위배되는 목적으로 사용 시 처벌 받을 수 있습니다.
+*/
+ MSG_ID_D2A = 0xd2a,
+/*20171108 to 20191120
+지역명
+20191127 to latest
+등록하기
+Register
+*/
+ MSG_ID_D2B = 0xd2b,
+/*20171108 to 20191120
+지역명 검색
+20191127 to latest
+사용할 수 없는 단어가 포함되어 있습니다.
+*/
+ MSG_ID_D2C = 0xd2c,
+/*20171108 to 20191120
+가입 요청하기
+20191127 to latest
+파티가입
+*/
+ MSG_ID_D2D = 0xd2d,
+/*20171108 to 20191120
+신고하기
+20191127 to latest
+1:1대화
+*/
+ MSG_ID_D2E = 0xd2e,
+/*20171108 to 20191120
+파티 모집 중단
+20191127 to latest
+모집 중지
+*/
+ MSG_ID_D2F = 0xd2f,
+/*20171108 to 20191120
+지역명을 입력해주세요.
+20191127 to latest
+수정하기
+*/
+ MSG_ID_D30 = 0xd30,
+/*20171108 to 20191120
+지역
+20191127 to latest
+전체
+All
+*/
+ MSG_ID_D31 = 0xd31,
+/*20171108 to 20191120
+전 직업
+20191127 to latest
+[%s] 님이 파티가입을 신청했습니다.
+*/
+ MSG_ID_D32 = 0xd32,
+/*20171108 to latest
+로그인
+*/
+ MSG_ID_D33 = 0xd33,
+/*20171108 to latest
+계정
+*/
+ MSG_ID_D34 = 0xd34,
+/*20171108 to latest
+종료
+Exit
+*/
+ MSG_ID_D35 = 0xd35,
+/*20171108 to latest
+신청
+*/
+ MSG_ID_D36 = 0xd36,
+/*20171108 to latest
+접속
+*/
+ MSG_ID_D37 = 0xd37,
+/*20171108 to latest
+확인
+*/
+ MSG_ID_D38 = 0xd38,
+/*20171108 to latest
+휴대폰에 다운받은 GNJOY MOTP를
+*/
+ MSG_ID_D39 = 0xd39,
+/*20171108 to latest
+실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_D3A = 0xd3a,
+/*20171108 to latest
+NPC가 있는 맵의 랜덤 좌표로 이동 됩니다.
+*/
+ MSG_ID_D3B = 0xd3b,
+/*20171108 to latest
+태권
+Taekwon
+*/
+ MSG_ID_D3C = 0xd3c,
+#endif
+#if PACKETVER >= 20171115
+/*20171115 to 20171115
+ 님이 차단 상태로 설정되었습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D3D = 0xd3d,
+/*20171115 to 20171115
+ 님을 차단 상태로 설정하는데 실패하였습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부 요청 실패
+*/
+ MSG_ID_D3E = 0xd3e,
+/*20171115 to 20171115
+ 님을 차단 상태로 설정하는데 실패하였습니다.(인원 초과)
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부 요청실패 (인원초과)
+*/
+ MSG_ID_D3F = 0xd3f,
+/*20171115 to 20171115
+ 님이 차단 해제 되었습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D40 = 0xd40,
+/*20171115 to 20171115
+ 님을 차단 해제하는데 실패하였습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패
+*/
+ MSG_ID_D41 = 0xd41,
+/*20171115 to 20171115
+ 님을 차단 해제하는데 실패하였습니다.(인원 초과)
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패 (인원초과)
+*/
+ MSG_ID_D42 = 0xd42,
+/*20171115 to latest
+차단 리스트가 없습니다
+Ignore-list is empty
+*/
+ MSG_ID_D43 = 0xd43,
+/*20171115 to latest
+-차단 리스트-
+Characters in ignore-list:
+*/
+ MSG_ID_D44 = 0xd44,
+/*20171115 to latest
+진행중
+Act
+*/
+ MSG_ID_D45 = 0xd45,
+/*20171115 to latest
+추천
+Rec
+*/
+ MSG_ID_D46 = 0xd46,
+/*20171115 to latest
+보류중
+Pen
+*/
+ MSG_ID_D47 = 0xd47,
+/*20171115 to latest
+QUEST
+*/
+ MSG_ID_D48 = 0xd48,
+/*20171115 to latest
+내용
+For
+*/
+ MSG_ID_D49 = 0xd49,
+/*20171115 to latest
+몬스터
+*/
+ MSG_ID_D4A = 0xd4a,
+/*20171115 to latest
+보상
+*/
+ MSG_ID_D4B = 0xd4b,
+/*20171115 to latest
+EXP
+*/
+ MSG_ID_D4C = 0xd4c,
+/*20171115 to latest
+JEXP
+*/
+ MSG_ID_D4D = 0xd4d,
+/*20171115 to latest
+아이템
+Item
+*/
+ MSG_ID_D4E = 0xd4e,
+/*20171115 to latest
+진행/보류
+*/
+ MSG_ID_D4F = 0xd4f,
+/*20171115 to latest
+하단으로 이동
+*/
+ MSG_ID_D50 = 0xd50,
+/*20171115 to latest
+간편 퀘스트창에 표시
+*/
+ MSG_ID_D51 = 0xd51,
+/*20171115 to latest
+입력시간
+*/
+ MSG_ID_D52 = 0xd52,
+#endif
+#if PACKETVER >= 20171122
+/*20171122 to latest
+아이디 저장
+*/
+ MSG_ID_D53 = 0xd53,
+/*20171122 to latest
+비밀번호
+Password
+*/
+ MSG_ID_D54 = 0xd54,
+/*20171122 to latest
+아이디
+*/
+ MSG_ID_D55 = 0xd55,
+/*20171122 to latest
+회원가입
+*/
+ MSG_ID_D56 = 0xd56,
+/*20171122 to 20191120
+노비스계열
+20191127 to latest
+파티장
+Leader
+*/
+ MSG_ID_D57 = 0xd57,
+/*20171122 to 20191120
+슈퍼노비스계열
+20191127 to latest
+파티에 가입할 수 있는 레벨이 아닙니다.
+*/
+ MSG_ID_D58 = 0xd58,
+/*20171122 to latest
+모험가 중개소 등록에 실패했습니다.
+*/
+ MSG_ID_D59 = 0xd59,
+/*20171122 to latest
+모험가 중개소에 등록되었습니다.
+*/
+ MSG_ID_D5A = 0xd5a,
+/*20171122 to 20180328
+직업을 한 개 이상 선택해주세요.
+20180404 to 20191120
+모집을 희망하는 파티원의 직업을 한 개 이상 선택해 주세요.
+20191127 to latest
+검색내용입력
+*/
+ MSG_ID_D5B = 0xd5b,
+/*20171122 to 20191127
+지역명을 두 글자 이상 입력해주세요.
+20191204 to latest
+탱커
+*/
+ MSG_ID_D5C = 0xd5c,
+/*20171122 to latest
+%.1f%% (+ %s서버 %.1f%%)
+*/
+ MSG_ID_D5D = 0xd5d,
+/*20171122 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D5E = 0xd5e,
+/*20171122 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D5F = 0xd5f,
+/*20171122 to latest
+/ex or /차단 : 전체채팅 및 귓말 차단 캐릭터 리스트
+*/
+ MSG_ID_D60 = 0xd60,
+/*20171122 to latest
+/exall or /차단전부 : 모두에게 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D61 = 0xd61,
+/*20171122 to latest
+/inall or /해제전부 : 모두에게 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D62 = 0xd62,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D63 = 0xd63,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 거부요청 실패
+*/
+ MSG_ID_D64 = 0xd64,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D65 = 0xd65,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 가능요청 실패
+*/
+ MSG_ID_D66 = 0xd66,
+/*20171122 to latest
+오프닝
+*/
+ MSG_ID_D67 = 0xd67,
+#endif
+#if PACKETVER >= 20171206
+/*20171206 to latest
+로그인 화면으로 돌아가시겠습니까?
+*/
+ MSG_ID_D68 = 0xd68,
+/*20171206 to latest
+힘과 공격력이 강해졌습니다.
+*/
+ MSG_ID_D69 = 0xd69,
+/*20171206 to latest
+힘, 지능, 손재주 및 명중률이 증가하였습니다.
+*/
+ MSG_ID_D6A = 0xd6a,
+/*20171206 to latest
+방어력 및 HP가 증가되었습니다.
+*/
+ MSG_ID_D6B = 0xd6b,
+/*20171206 to latest
+젤스타
+*/
+ MSG_ID_D6C = 0xd6c,
+/*20171206 to latest
+계정버프
+*/
+ MSG_ID_D6D = 0xd6d,
+/*20171206 to latest
+정액서비스
+*/
+ MSG_ID_D6E = 0xd6e,
+#endif
+#if PACKETVER >= 20171213
+/*20171213 to latest
+현재 접속이 지연되고 있습니다. 순차적으로 접속이 가능하니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D6F = 0xd6f,
+/*20171213 to latest
+현재 접속이 지연되고 있으니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D70 = 0xd70,
+/*20171213 to latest
+불량 단어가 포함된 이름은 검색할 수 없습니다.
+*/
+ MSG_ID_D71 = 0xd71,
+/*20171213 to 20191127
+파티 마스터가 요청을 받을 수 없는 맵에 있습니다.
+20191204 to latest
+파티 마스터가 요청을 받을 수 없는 상태입니다.
+*/
+ MSG_ID_D72 = 0xd72,
+/*20171213 to latest
+파티를 찾을 수 없습니다.
+*/
+ MSG_ID_D73 = 0xd73,
+/*20171213 to 20180328
+님의 파티요청입니다.
+20180404 to 20191127
+님의 파티 가입 요청입니다.
+20191204 to latest
+딜러
+*/
+ MSG_ID_D74 = 0xd74,
+#endif
+#if PACKETVER >= 20171220
+/*20171220 to latest
+http://ro.gnjoy.com
+*/
+ MSG_ID_D75 = 0xd75,
+/*20171220 to latest
+▲
+*/
+ MSG_ID_D76 = 0xd76,
+/*20171220 to latest
+▼
+*/
+ MSG_ID_D77 = 0xd77,
+#endif
+#if PACKETVER >= 20171227
+/*20171227 to latest
+이미 친구입니다
+*/
+ MSG_ID_D78 = 0xd78,
+/*20171227 to latest
+상대방을 찾을 수 없습니다
+*/
+ MSG_ID_D79 = 0xd79,
+/*20171227 to latest
+이미 다른 캐릭터가 친구 신청 중입니다.
+*/
+ MSG_ID_D7A = 0xd7a,
+/*20171227 to latest
+혼구슬 표시 ON
+*/
+ MSG_ID_D7B = 0xd7b,
+/*20171227 to latest
+혼구슬 표시 OFF
+*/
+ MSG_ID_D7C = 0xd7c,
+#endif
+#if PACKETVER >= 20180117
+/*20180117 to latest
+해당 계정은 2차 비밀번호 오입력으로 인해 게임내 접속이 제한된 상태입니다.
+ %02d시간 %02d분 후에 접속제한이 해제되며, 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7D = 0xd7d,
+/*20180117 to latest
+보안패스워드를 3회이상 틀리셨습니다. 계정 보안을 위해 24시간동안 게임내 접속이 제한됩니다.
+ 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7E = 0xd7e,
+/*20180117 to latest
+운영진
+*/
+ MSG_ID_D7F = 0xd7f,
+/*20180117 to latest
+%d일차 출석 보상이 지급되었습니다.
+*/
+ MSG_ID_D80 = 0xd80,
+/*20180117 to 20180117
+계정설정정보 받아오는데 실패 했습니다.( 재시도를 위해서는 재시작 해야 합니다. )
+20180124 to latest
+계정 설정 데이터를 불러오는 중에 오류가 발생했습니다. ( 재시도를 위해서는 재시작 해야 합니다. )
+*/
+ MSG_ID_D81 = 0xd81,
+/*20180117 to latest
+해당 스킬은 파티 상태에서 사용 가능합니다.
+*/
+ MSG_ID_D82 = 0xd82,
+#endif
+#if PACKETVER >= 20180124
+/*20180124 to latest
+파티 모집을 중단하였습니다.
+*/
+ MSG_ID_D83 = 0xd83,
+/*20180124 to latest
+길드 상납 경험치는 최대 %d%%까지 가능합니다.
+*/
+ MSG_ID_D84 = 0xd84,
+/*20180124 to latest
+길드 레벨이 최대여서 더 이상 경험치를 상납할 수 없습니다.
+*/
+ MSG_ID_D85 = 0xd85,
+#endif
+#if PACKETVER >= 20180207
+/*20180207 to latest
+계정보안을 위하여 MOTP미사용자는 홈페이지 로그인만 가능합니다.
+홈페이지로 로그인을 시도해주시기 바랍니다.
+*/
+ MSG_ID_D86 = 0xd86,
+/*20180207 to latest
+물리 공격력과 마법 공격력이 향상되었습니다.
+*/
+ MSG_ID_D87 = 0xd87,
+/*20180207 to latest
+물리 공격력과 마법 공격력이 감소되었습니다.
+*/
+ MSG_ID_D88 = 0xd88,
+/*20180207 to latest
+%s 출석체크 보상
+%s Attendance Check Reward
+*/
+ MSG_ID_D89 = 0xd89,
+/*20180207 to 20180509
+이벤트 기간 : %02d월 %02d일 ~ %2d월 %2d일 24:00까지
+Event period : From %02d/%02d ~ Until %2d/%2d (Month/Day) 24:00
+20180516 to latest
+이벤트 기간 : %02d월 %02d일 ~ %02d월 %02d일 24:00까지
+*/
+ MSG_ID_D8A = 0xd8a,
+/*20180207 to latest
+%d일차
+%d Day
+*/
+ MSG_ID_D8B = 0xd8b,
+/*20180207 to latest
+%d일차 출석체크
+클릭해주세요~!
+%d Day attendance check
+Please click~!
+*/
+ MSG_ID_D8C = 0xd8c,
+/*20180207 to latest
+%d일차 출석 성공!
+%d Day attendance success!
+*/
+ MSG_ID_D8D = 0xd8d,
+/*20180207 to latest
+D-day
+*/
+ MSG_ID_D8E = 0xd8e,
+/*20180207 to latest
+일
+Day
+*/
+ MSG_ID_D8F = 0xd8f,
+/*20180207 to latest
+출석체크에 실패하였습니다. 다시 실행해주세요.
+Attendance Check failed. Please run again.
+*/
+ MSG_ID_D90 = 0xd90,
+/*20180207 to latest
+출석체크
+Attendance Check
+*/
+ MSG_ID_D91 = 0xd91,
+/*20180207 to latest
+현재 출석체크 이벤트 기간이 아닙니다
+This is not the current attendance check event
+*/
+ MSG_ATTENDANCE_UNAVAILABLE = 0xd92,
+/*20180207 to 20180328
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다
+20180404 to latest
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+*/
+ MSG_ID_D93 = 0xd93,
+/*20180207 to latest
+개인 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+
+*/
+ MSG_ID_D94 = 0xd94,
+#endif
+#if PACKETVER >= 20180213
+/*20180213 to latest
+메시지
+*/
+ MSG_ID_D95 = 0xd95,
+/*20180213 to latest
+트위터에 메세지 전송을 실패 했습니다.
+*/
+ MSG_ID_D96 = 0xd96,
+/*20180213 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_D97 = 0xd97,
+#endif
+#if PACKETVER >= 20180307
+/*20180307 to latest
+몬스터의 테이밍이 불가능한 지역입니다.
+*/
+ MSG_ID_D98 = 0xd98,
+#endif
+#if PACKETVER >= 20180321
+/*20180321 to latest
+순위를 가져오고 있습니다...
+*/
+ MSG_ID_D99 = 0xd99,
+/*20180321 to latest
+해당 스킬은 파티장일때만 사용 가능합니다.
+*/
+ MSG_ID_D9A = 0xd9a,
+#endif
+#if PACKETVER >= 20180404
+/*20180404 to latest
+파트너의 SP가 부족하거나, 스킬 사용 불가 상태입니다.
+*/
+ MSG_ID_D9B = 0xd9b,
+/*20180404 to latest
+아르바이트 노점 강제 종료 알림메일
+*/
+ MSG_ID_D9C = 0xd9c,
+/*20180404 to latest
+안녕하세요. 운영팀입니다.
+해당 아르바이트 노점은 운영정책 위배되는 사항이 확인되어 강제 종료되었습니다.
+자세한 확인을 원하시는 경우에는 1:1 문의를 접수해 주시기 바랍니다.
+감사합니다
+*/
+ MSG_ID_D9D = 0xd9d,
+/*20180404 to latest
+50% 이상의 값을 입력할 수 없습니다.
+The guild tax rate can't be set to more than 50%.
+*/
+ MSG_ID_D9E = 0xd9e,
+/*20180404 to 20191204
+파티 가입 요청을 보냈습니다.
+20191211 to latest
+파티가 모험가 중개소에 등록되어, 파티장을 변경 할 수 없습니다.
+*/
+ MSG_ID_D9F = 0xd9f,
+/*20180404 to latest
+모험가 중개소에 파티를 등록할 수 없습니다
+*/
+ MSG_ID_DA0 = 0xda0,
+/*20180404 to latest
+수락
+*/
+ MSG_ID_DA1 = 0xda1,
+/*20180404 to latest
+거절
+*/
+ MSG_ID_DA2 = 0xda2,
+/*20180404 to 20191127
+설정 권한은 파티장에게 있습니다.
+20191204 to latest
+힐러
+*/
+ MSG_ID_DA3 = 0xda3,
+/*20180404 to latest
+해당 캐릭터를 찾을 수 없습니다.
+*/
+ MSG_ID_DA4 = 0xda4,
+/*20180404 to latest
+노점 강제 철거
+*/
+ MSG_ID_DA5 = 0xda5,
+/*20180404 to latest
+해당 파티의 파티장을 찾을 수 없습니다.
+*/
+ MSG_ID_DA6 = 0xda6,
+/*20180404 to latest
+잡레벨이 낮아 파티에 가입 할 수 없습니다.
+*/
+ MSG_ID_DA7 = 0xda7,
+/*20180404 to latest
+현재 요청자가 파티가입이 불가능한 지역에 있습니다.
+*/
+ MSG_ID_DA8 = 0xda8,
+/*20180404 to latest
+파티 인원수가 초과되었습니다.
+*/
+ MSG_ID_DA9 = 0xda9,
+/*20180404 to latest
+%s 파티의 파티장이 파티 가입을 승인했습니다.
+*/
+ MSG_ID_DAA = 0xdaa,
+/*20180404 to latest
+%s 파티의 파티장이 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAB = 0xdab,
+/*20180404 to latest
+%s 님이 이미 파티에 가입 중입니다.
+*/
+ MSG_ID_DAC = 0xdac,
+/*20180404 to latest
+%s 님의 파티 가입을 수락했습니다.
+*/
+ MSG_ID_DAD = 0xdad,
+/*20180404 to latest
+%s 님의 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAE = 0xdae,
+/*20180404 to latest
+파티 요청을 받을 수 없는 상태여서 %s님의 신청이 거절되었습니다.
+*/
+ MSG_ID_DAF = 0xdaf,
+/*20180404 to latest
+모험가 중개소 리스트
+*/
+ MSG_ID_DB0 = 0xdb0,
+/*20180404 to latest
+파티 가입 요청
+*/
+ MSG_ID_DB1 = 0xdb1,
+/*20180404 to 20191120
+파티장이 아닌 경우, 모험가 중개소에 파티를 등록할 수 없습니다.
+20191127 to latest
+파티장이 아닌 경우 모험가 중개소에 파티를 등록할 수 없습니다.
+*/
+ MSG_ID_DB2 = 0xdb2,
+/*20180404 to 20180404
+파티 모집 중단에 실패했습니다.
+20180418 to latest
+파티 모집을 중단할 수 없습니다.
+*/
+ MSG_ID_DB3 = 0xdb3,
+#endif
+#if PACKETVER >= 20180418
+/*20180418 to 20191127
+존재하지 않는 파티 글입니다.
+20191204 to latest
+보조
+Support
+*/
+ MSG_ID_DB4 = 0xdb4,
+/*20180418 to 20180418
+시야 확장
+20180425 to latest
+Zoom Out
+*/
+ MSG_ID_DB5 = 0xdb5,
+/*20180418 to 20180418
+%s : 시야확장을 켜거나 끌수 있습니다 On Off
+20180425 to latest
+%s : Zoom Out을 켜거나 끌수 있습니다 On Off
+*/
+ MSG_ID_DB6 = 0xdb6,
+/*20180418 to 20180418
+시야를 확장합니다(On)
+20180425 to latest
+Zoom Out 기능을 켭니다 (On)
+*/
+ MSG_ID_DB7 = 0xdb7,
+/*20180418 to 20180418
+시야확장을 해제합니다(Off)
+20180425 to latest
+Zoom Out 기능을 해제합니다 (Off)
+*/
+ MSG_ID_DB8 = 0xdb8,
+/*20180418 to 20180418
+/expandsight
+20180425 to latest
+/zoom
+*/
+ MSG_ID_DB9 = 0xdb9,
+/*20180418 to latest
+모험가 중개소
+*/
+ MSG_ID_DBA = 0xdba,
+/*20180418 to latest
+파티장인 경우, 가입 요청을 할 수 없습니다.
+*/
+ MSG_ID_DBB = 0xdbb,
+/*20180418 to 20191211
+모험가 중개소에 등록 중입니다. 잠시만 기다려 주세요.
+20191218 to latest
+파티 가입 최대 레벨은 최소 레벨 설정보다 높아야 합니다.
+*/
+ MSG_ID_DBC = 0xdbc,
+/*20180418 to latest
+더 이상 직업을 선택할 수 없습니다.
+*/
+ MSG_ID_DBD = 0xdbd,
+/*20180418 to 20191120
+게임 중 해당 유저의 가입 요청을 받지 않습니다.
+20191127 to latest
+게임 중 해당 유저의 가입 요청을 받지 않습니다.(클라이언트 종료 전까지 유효)
+*/
+ MSG_ID_DBE = 0xdbe,
+#endif
+#if PACKETVER >= 20180502
+/*20180502 to latest
+잠시 후 다시 열어주시기 바랍니다.
+*/
+ MSG_ID_DBF = 0xdbf,
+/*20180502 to latest
+공성시작 전 %d분 동안은 해당 기능을 이용하실 수 없습니다.
+*/
+ MSG_ID_DC0 = 0xdc0,
+#endif
+#if PACKETVER >= 20180516
+/*20180516 to latest
+/viewclear
+*/
+ MSG_ID_DC1 = 0xdc1,
+/*20180516 to latest
+건물 반 투명화 ON
+*/
+ MSG_ID_DC2 = 0xdc2,
+/*20180516 to latest
+건물 반 투명화 OFF
+*/
+ MSG_ID_DC3 = 0xdc3,
+/*20180516 to latest
+건물 투명화
+*/
+ MSG_ID_DC4 = 0xdc4,
+/*20180516 to latest
+알로 되돌리기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+*/
+ MSG_ID_DC5 = 0xdc5,
+/*20180516 to latest
+Emblem Frame
+*/
+ MSG_ID_DC6 = 0xdc6,
+/*20180516 to latest
+Emblem 테두리를 그려줍니다
+*/
+ MSG_ID_DC7 = 0xdc7,
+/*20180516 to latest
+Emblem 테두리를 그려주지 않습니다
+*/
+ MSG_ID_DC8 = 0xdc8,
+#endif
+#if PACKETVER >= 20180605
+/*20180605 to latest
+장착된 무기가 없습니다.
+*/
+ MSG_ID_DC9 = 0xdc9,
+/*20180605 to latest
+에너지 구체가 부족합니다.
+*/
+ MSG_ID_DCA = 0xdca,
+/*20180605 to latest
+배울 수 없는 스킬(%s)이 포함되어있습니다.
+*/
+ MSG_ID_DCB = 0xdcb,
+/*20180605 to latest
+/frame
+*/
+ MSG_ID_DCC = 0xdcc,
+#endif
+#if PACKETVER >= 20180620
+/*20180620 to latest
+웨폰 블로킹 발동후 제한시간 내에 사용가능한 스킬입니다.
+*/
+ MSG_ID_DCD = 0xdcd,
+#endif
+#if PACKETVER >= 20180704
+/*20180704 to latest
+아이디혹은 패스워드가 잘못되었읍니다.
+*/
+ MSG_ID_DCE = 0xdce,
+#endif
+#if PACKETVER >= 20180718
+/*20180718 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DCF = 0xdcf,
+/*20180718 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD0 = 0xdd0,
+/*20180718 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD1 = 0xdd1,
+#endif
+#if PACKETVER >= 20180829
+/*20180829 to latest
+영문이나 러시아어 단독으로만 사용이 가능합니다.
+Forbidden symbols in character name.
+*/
+ MSG_ID_DD2 = 0xdd2,
+/*20180829 to latest
+you must have an AccessTicket to login
+*/
+ MSG_ID_DD3 = 0xdd3,
+/*20180829 to latest
+창고를 불러오는 중입니다.
+Loading....
+*/
+ MSG_ID_DD4 = 0xdd4,
+/*20180829 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_DD5 = 0xdd5,
+#endif
+#if PACKETVER >= 20181002
+/*20181002 to latest
+삭제
+Delete
+*/
+ MSG_ID_DD6 = 0xdd6,
+/*20181002 to latest
+답장
+Reply
+*/
+ MSG_ID_DD7 = 0xdd7,
+/*20181002 to latest
+전송
+Send
+*/
+ MSG_ID_DD8 = 0xdd8,
+/*20181002 to latest
+이름확인
+Name Check
+*/
+ MSG_ID_DD9 = 0xdd9,
+/*20181002 to latest
+공지
+Notice
+*/
+ MSG_ID_DDA = 0xdda,
+/*20181002 to latest
+일반
+General
+*/
+ MSG_ID_DDB = 0xddb,
+/*20181002 to latest
+반송
+Clear
+*/
+ MSG_ID_DDC = 0xddc,
+/*20181002 to latest
+검색
+Search
+*/
+ MSG_ID_DDD = 0xddd,
+#endif
+#if PACKETVER >= 20181031
+/*20181031 to latest
+펫 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDE = 0xdde,
+/*20181031 to latest
+호문 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDF = 0xddf,
+/*20181031 to latest
+화폐
+*/
+ MSG_ID_DE0 = 0xde0,
+/*20181031 to latest
+%s %d개
+*/
+ MSG_ID_DE1 = 0xde1,
+/*20181031 to latest
+교환에 실패하였습니다.
+*/
+ MSG_ID_DE2 = 0xde2,
+/*20181031 to latest
+교환이 잘 이루어졌습니다.
+*/
+ MSG_ID_DE3 = 0xde3,
+/*20181031 to latest
+교환에 필요한 재화가 부족합니다.
+*/
+ MSG_ID_DE4 = 0xde4,
+/*20181031 to latest
+해당 아이템은 이미 판매되어 재고가 부족합니다.
+*/
+ MSG_ID_DE5 = 0xde5,
+/*20181031 to latest
+사망
+*/
+ MSG_ID_DE6 = 0xde6,
+/*20181031 to latest
+PvP
+*/
+ MSG_ID_DE7 = 0xde7,
+/*20181031 to latest
+아이템 소지 확장
+*/
+ MSG_ID_DE8 = 0xde8,
+/*20181031 to 20181031
+(^0000ff%s^000000)을 소모하여, 아이템 최대 소지 종류수를 확장하시겠습니까?
+(^0000ff%d^000000)에서 (^0000ff%d^000000)로 확장됩니다.
+^ff0000※ 소모된 아이템 및 확장된 최대 소지 종류수는 되돌릴 수 없습니다.^000000
+20181107 to latest
+^0000ff%s^000000을 소모하여, 아이템 최대 소지 종류수를 확장하시겠습니까?
+(^0000ff%d^000000)에서 (^0000ff%d^000000)로 확장됩니다.
+^ff0000※ 소모된 아이템 및 확장된 최대 소지 종류수는 되돌릴 수 없습니다.^000000
+*/
+ MSG_ID_DE9 = 0xde9,
+/*20181031 to 20181031
+아이템 소지 종류 수 확장에 실패하였습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 실패하였습니다.
+*/
+ MSG_ID_DEA = 0xdea,
+/*20181031 to 20181031
+아이템 소지 종류 수 확장을 위해, 다른 작업을 종료하여 주시기 바랍니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장을 위해, 다른 작업을 종료하여 주시기 바랍니다.
+*/
+ MSG_ID_DEB = 0xdeb,
+/*20181031 to 20181031
+아이템 소지 확장에 필요한 아이템을 소지하고 있지 않습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 필요한 아이템을 소지하고 있지 않습니다.
+*/
+ MSG_ID_DEC = 0xdec,
+/*20181031 to 20181031
+이미 아이템 소지 종류 수 확장이 최대로 적용 중입니다.
+20181107 to latest
+더 이상 아이템 최대 소지 종류수를 확장 할 수 없습니다.
+*/
+ MSG_ID_DED = 0xded,
+/*20181031 to 20181031
+아이템 소지 확장에 성공하였습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 성공하였습니다.
+*/
+ MSG_ID_DEE = 0xdee,
+#endif
+#if PACKETVER >= 20181121
+/*20181121 to latest
+같은 아이템을 %d개 이상 가질 수 없습니다.
+*/
+ MSG_ID_DEF = 0xdef,
+/*20181121 to latest
+소지 한계량 초과로 구입이 불가능합니다.
+*/
+ MSG_ID_DF0 = 0xdf0,
+/*20181121 to latest
+해당 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_ID_DF1 = 0xdf1,
+#endif
+#if PACKETVER >= 20181205
+/*20181205 to latest
+성제
+*/
+ MSG_ID_DF2 = 0xdf2,
+/*20181205 to latest
+소울리퍼
+*/
+ MSG_ID_DF3 = 0xdf3,
+#endif
+#if PACKETVER >= 20181212
+/*20181212 to latest
+설정한 내용은 정상 종료 시 서버에 저장됩니다.
+*/
+ MSG_ID_DF4 = 0xdf4,
+#endif
+#if PACKETVER >= 20190109
+/*20190109 to latest
+Capture Monster
+Taming monster
+*/
+ MSG_ID_DF5 = 0xdf5,
+/*20190109 to latest
+message
+*/
+ MSG_ID_DF6 = 0xdf6,
+/*20190109 to latest
+TITLE
+Header
+*/
+ MSG_ID_DF7 = 0xdf7,
+/*20190109 to latest
+데미지 표기 확장
+*/
+ MSG_ID_DF8 = 0xdf8,
+#endif
+#if PACKETVER >= 20190213
+/*20190213 to latest
+맵 이름 표기
+*/
+ MSG_ID_DF9 = 0xdf9,
+/*20190213 to latest
+시스템 메세지 : 현재 노점보기 기능이 %s 상태입니다. (/노점보기)
+*/
+ MSG_ID_DFA = 0xdfa,
+/*20190213 to latest
+수직 동기
+*/
+ MSG_ID_DFB = 0xdfb,
+/*20190213 to latest
+자료
+*/
+ MSG_ID_DFC = 0xdfc,
+/*20190213 to 20190228
+http://rodata.zhaouc.com/renwu.html#container
+20190306 to latest
+http://rodata.zhaouc.com/renwu.html
+*/
+ MSG_ID_DFD = 0xdfd,
+/*20190213 to latest
+작위
+*/
+ MSG_ID_DFE = 0xdfe,
+/*20190213 to latest
+프레임 제한
+*/
+ MSG_ID_DFF = 0xdff,
+#endif
+#if PACKETVER >= 20190227
+/*20190227 to latest
+%d개를 초과할 경우 더 이상 설치 할 수 없습니다.
+*/
+ MSG_ID_E00 = 0xe00,
+/*20190227 to latest
+목적지
+*/
+ MSG_ID_E01 = 0xe01,
+#endif
+#if PACKETVER >= 20190306
+/*20190306 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_E02 = 0xe02,
+/*20190306 to latest
+등록할 수 없는 파일입니다.
+*/
+ MSG_ID_E03 = 0xe03,
+#endif
+#if PACKETVER >= 20190320
+/*20190320 to latest
+선택 삭제
+*/
+ MSG_ID_E04 = 0xe04,
+/*20190320 to latest
+모두 삭제
+*/
+ MSG_ID_E05 = 0xe05,
+/*20190320 to latest
+[%s]편지함의 모든 메일을 삭제하시겠습니까?
+*/
+ MSG_ID_E06 = 0xe06,
+/*20190320 to latest
+선택 받기
+*/
+ MSG_ID_E07 = 0xe07,
+/*20190320 to latest
+모두 받기
+*/
+ MSG_ID_E08 = 0xe08,
+/*20190320 to latest
+선택한 메일의 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E09 = 0xe09,
+/*20190320 to latest
+[%s]편지함의 모든 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E0A = 0xe0a,
+#endif
+#if PACKETVER >= 20190403
+/*20190403 to latest
+스킬바2
+*/
+ MSG_ID_E0B = 0xe0b,
+/*20190403 to latest
+스킬바 교체
+*/
+ MSG_ID_E0C = 0xe0c,
+/*20190403 to latest
+←
+*/
+ MSG_ID_E0D = 0xe0d,
+/*20190403 to latest
+↑
+*/
+ MSG_ID_E0E = 0xe0e,
+/*20190403 to latest
+→
+*/
+ MSG_ID_E0F = 0xe0f,
+/*20190403 to latest
+↓
+*/
+ MSG_ID_E10 = 0xe10,
+/*20190403 to latest
+▤
+*/
+ MSG_ID_E11 = 0xe11,
+/*20190403 to latest
+←
+*/
+ MSG_ID_E12 = 0xe12,
+/*20190403 to latest
+로딩중에는 창을 닫을 수 없습니다.
+*/
+ MSG_ID_E13 = 0xe13,
+#endif
+#if PACKETVER >= 20190417
+/*20190417 to latest
+리딩 스펠북으로 저장된 마법이 없습니다.
+*/
+ MSG_ID_E14 = 0xe14,
+/*20190417 to latest
+이동 시 사용한 아이템은 재교환이 불가능합니다.
+*/
+ MSG_ID_E15 = 0xe15,
+/*20190417 to latest
+자유이동권을 구매 하였습니다
+*/
+ MSG_ID_E16 = 0xe16,
+/*20190417 to latest
+자유이동권 사용 중, 관련 아이템을 소모하지 않습니다.
+*/
+ MSG_ID_E17 = 0xe17,
+/*20190417 to latest
+적용
+*/
+ MSG_ID_E18 = 0xe18,
+/*20190417 to latest
+중지
+*/
+ MSG_ID_E19 = 0xe19,
+#endif
+#if PACKETVER >= 20190508
+/*20190508 to latest
+자유이동권
+*/
+ MSG_ID_E1A = 0xe1a,
+/*20190508 to latest
+%d시간 이용, %s %d개
+*/
+ MSG_ID_E1B = 0xe1b,
+/*20190508 to latest
+자유이용권 사용중
+*/
+ MSG_ID_E1C = 0xe1c,
+/*20190508 to latest
+특성 스테이터스
+*/
+ MSG_ID_E1D = 0xe1d,
+/*20190508 to latest
+파워 파라메터
+^cc0000물리 공격력, 특성 공격력^ffffff 증가
+*/
+ MSG_ID_E1E = 0xe1e,
+/*20190508 to latest
+스테미나 파라메터
+^cc0000물리 저항력^ffffff 증가
+*/
+ MSG_ID_E1F = 0xe1f,
+/*20190508 to latest
+위즈덤 파라메터
+^cc0000마법 저항력^ffffff 증가
+*/
+ MSG_ID_E20 = 0xe20,
+/*20190508 to latest
+스펠 파라메터
+^cc0000마법 공격력, 마법 공격력^ffffff 증가
+*/
+ MSG_ID_E21 = 0xe21,
+/*20190508 to latest
+컨센트레이션 파라메터
+^cc0000명중률, 회피율, 특성 물리/마법 공격력^ffffff 증가
+*/
+ MSG_ID_E22 = 0xe22,
+/*20190508 to latest
+크리에이티브 파라메터
+^cc0000특성 힐 회복량, 크리티컬 데미지 비율^ffffff 증가
+*/
+ MSG_ID_E23 = 0xe23,
+/*20190508 to latest
+특성 물리 공격력
+*/
+ MSG_ID_E24 = 0xe24,
+/*20190508 to latest
+특성 마법 공격력
+*/
+ MSG_ID_E25 = 0xe25,
+/*20190508 to latest
+물리 저항력
+*/
+ MSG_ID_E26 = 0xe26,
+/*20190508 to latest
+마법 저항력
+*/
+ MSG_ID_E27 = 0xe27,
+/*20190508 to latest
+특성 힐 회복량
+*/
+ MSG_ID_E28 = 0xe28,
+/*20190508 to latest
+크리티컬 데미지 비율
+*/
+ MSG_ID_E29 = 0xe29,
+/*20190508 to latest
+특성 파라메터 레벨업에 사용되는 포인트
+*/
+ MSG_ID_E2A = 0xe2a,
+/*20190508 to latest
+J.Lv
+*/
+ MSG_ID_E2B = 0xe2b,
+/*20190508 to latest
+AP
+*/
+ MSG_ID_E2C = 0xe2c,
+#endif
+#if PACKETVER >= 20190522
+/*20190522 to latest
+영지로 이동
+*/
+ MSG_ID_E2D = 0xe2d,
+/*20190522 to latest
+상업도/방어도 확인
+*/
+ MSG_ID_E2E = 0xe2e,
+/*20190522 to 20190605
+관리영지 "%s"(으)로 이동하시겠습니까?
+(1회 이동 시 마다 1,000제니가 소모됩니다.
+공성전 시간에는 제니의 소모가 100배로 증가합니다.)
+20190619 to 20190619
+관리영지 "%s"(으)로 이동하시겠습니까?
+이동 시 마다 %d제니가 소모됩니다.
+20190703 to latest
+관리영지 "%s"(으)로 이동하시겠습니까?
+이동 시 마다 %d제니가 소모됩니다.
+(공성전 시간에는 %d제니가 소모됩니다.)
+*/
+ MSG_ID_E2F = 0xe2f,
+/*20190522 to latest
+
+관리영지 "%s"
+
+방어도: %d / %d
+상업도: %d / %d
+*/
+ MSG_ID_E30 = 0xe30,
+/*20190522 to 20190717
+공성 영지 내에서는 다른 공성 영지로 이동 할 수 없습니다.
+20190717 to latest
+공성 영지에서는 사용할 수 없는 기능입니다.
+*/
+ MSG_ID_E31 = 0xe31,
+#endif
+#if PACKETVER >= 20190619
+/*20190619 to latest
+기본 기능 스킬을 습득하지 않은 캐릭터입니다.
+*/
+ MSG_ID_E32 = 0xe32,
+#endif
+#if PACKETVER >= 20190703
+/*20190703 to latest
+접속하신 IP는 라그나로크 제로 이용이 불가능합니다.
+고객센터 또는 홈페이지로 문의해 주십시오.
+*/
+ MSG_ID_E33 = 0xe33,
+#endif
+#if PACKETVER >= 20190717
+/*20190717 to latest
+탑승/장착 해제
+*/
+ MSG_ID_E34 = 0xe34,
+/*20190717 to latest
+가져오기
+*/
+ MSG_ID_E35 = 0xe35,
+/*20190717 to latest
+직전 노점에 등록된 아이템 정보를 가져옵니다.
+*/
+ MSG_ID_E36 = 0xe36,
+/*20190717 to latest
+서버 이슈로 인해 로그인이 제한되고 있습니다.
+*/
+ MSG_ID_E37 = 0xe37,
+/*20190717 to latest
+메시지
+*/
+ MSG_ID_E38 = 0xe38,
+/*20190717 to latest
++18 이상만 플레이가 가능합니다.
+*/
+ MSG_ID_E39 = 0xe39,
+/*20190717 to latest
+3시간 이상의 게임 플레이를 권장하지 않습니다.
+*/
+ MSG_ID_E3A = 0xe3a,
+/*20190717 to latest
+AP가 부족합니다.
+*/
+ MSG_ID_E3B = 0xe3b,
+#endif
+#if PACKETVER >= 20190731
+/*20190731 to latest
+제련도가 높아서 조합할 수 없습니다.
+*/
+ MSG_ID_E3C = 0xe3c,
+/*20190731 to latest
+제련도가 조합에 필요한 요구치보다 높습니다.
+*/
+ MSG_ID_E3D = 0xe3d,
+/*20190731 to 20191107
+'카드가 끼워져있거나 인챈트 되어 있습니다.
+20191113 to latest
+카드가 끼워져있거나 인챈트 되어 있습니다.
+*/
+ MSG_ID_E3E = 0xe3e,
+/*20190731 to latest
+∞
+?
+*/
+ MSG_ID_E3F = 0xe3f,
+/*20190731 to latest
+Z
+*/
+ MSG_ID_E40 = 0xe40,
+/*20190731 to latest
+Total : %s Zeny
+*/
+ MSG_ID_E41 = 0xe41,
+#endif
+#if PACKETVER >= 20190821
+/*20190821 to latest
+계정한정판매 등록창
+Limited Account Registration Window
+*/
+ MSG_ID_E42 = 0xe42,
+/*20190821 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_ID_E43 = 0xe43,
+/*20190821 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_ID_E44 = 0xe44,
+/*20190821 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_ID_E45 = 0xe45,
+/*20190821 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_ID_E46 = 0xe46,
+/*20190821 to latest
+판매 종료시간
+Sale end time
+*/
+ MSG_ID_E47 = 0xe47,
+/*20190821 to latest
+계정 한정
+Account only
+*/
+ MSG_ID_E48 = 0xe48,
+/*20190821 to latest
+판매기간 : %d월 %d일 %d시 %d분
+Sale period:% d month% d day% d hours% d
+*/
+ MSG_ID_E49 = 0xe49,
+/*20190821 to 20191002
+구입가능 %d개
+% D available
+20191016 to latest
+계정당 구매가능
+*/
+ MSG_ID_E4A = 0xe4a,
+/*20190821 to latest
+%d개 한정
+limited to% d
+*/
+ MSG_ID_E4B = 0xe4b,
+/*20190821 to latest
+>> ItemName : %s / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName:% s / Quantity:% d / Sales Period:% d Month:% d Day:% d Hour:% d Minute ~% d Month:% d Day:% d Hour:% d Minute
+*/
+ MSG_ID_E4C = 0xe4c,
+/*20190821 to latest
+Sold Out
+*/
+ MSG_ID_E4D = 0xe4d,
+/*20190821 to latest
+[%s]은(는) 현재 소환할 수 없는 지역에 있습니다.
+% s] is currently in a region that cannot be summoned.
+*/
+ MSG_ID_E4E = 0xe4e,
+/*20190821 to latest
+~ %d월 %d일 %d시 %d분
+% d min% d days% d days
+*/
+ MSG_ID_E4F = 0xe4f,
+/*20190821 to latest
+상품을 더이상 추가할 수 없습니다
+Can't add any more items
+*/
+ MSG_ID_E50 = 0xe50,
+#endif
+#if PACKETVER >= 20190828
+/*20190828 to latest
+장착 중인 아이템은 교환할 수 없습니다. 장착을 해제한 뒤 시도해 주시길 바랍니다.
+The item being mounted cannot be exchanged. Please unmount it and try again.
+*/
+ MSG_ID_E51 = 0xe51,
+#endif
+#if PACKETVER >= 20190904
+/*20190904 to latest
+길드 창고 이용 중엔 캐릭터 선택창으로 이동 할 수 없습니다.
+You can not move to the character selection window while using the Guild Warehouse.
+*/
+ MSG_ID_E52 = 0xe52,
+/*20190904 to latest
+아이템 태그가 포함되어 있어 사용할 수 없습니다.
+Item tag is included and cannot be used.
+*/
+ MSG_ID_E53 = 0xe53,
+/*20190904 to latest
+Monster
+*/
+ MSG_ID_E54 = 0xe54,
+/*20190904 to latest
+Unknown
+*/
+ MSG_ID_E55 = 0xe55,
+/*20190904 to latest
+Undead
+*/
+ MSG_ID_E56 = 0xe56,
+/*20190904 to latest
+Animal
+*/
+ MSG_ID_E57 = 0xe57,
+/*20190904 to latest
+Plant
+*/
+ MSG_ID_E58 = 0xe58,
+/*20190904 to latest
+Insect
+*/
+ MSG_ID_E59 = 0xe59,
+/*20190904 to latest
+Marine
+*/
+ MSG_ID_E5A = 0xe5a,
+/*20190904 to latest
+Devil
+*/
+ MSG_ID_E5B = 0xe5b,
+/*20190904 to latest
+Human
+*/
+ MSG_ID_E5C = 0xe5c,
+/*20190904 to latest
+Angel
+*/
+ MSG_ID_E5D = 0xe5d,
+/*20190904 to latest
+Dragon
+*/
+ MSG_ID_E5E = 0xe5e,
+#endif
+#if PACKETVER >= 20190918
+/*20190918 to latest
+Balance: %s %c
+*/
+ MSG_ID_E5F = 0xe5f,
+/*20190918 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money will be deducted from your total balance.
+*/
+ MSG_ID_E60 = 0xe60,
+/*20190918 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %s캐시, 무료 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money and %s Free Points will be deducted from your total balance.
+*/
+ MSG_ID_E61 = 0xe61,
+/*20190918 to 20190918
+[%s]의 호출이 거부되었습니다.
+20190925 to latest
+호출이 거부되었습니다.
+*/
+ MSG_ID_E62 = 0xe62,
+/*20190918 to latest
+구매 한도액은 소지액을 초과할 수 없습니다.
+*/
+ MSG_ID_E63 = 0xe63,
+/*20190918 to latest
+노점을 여는데 실패하였습니다. 구매노점 개설을 닫아주시기 바랍니다.
+*/
+ MSG_ID_E64 = 0xe64,
+#endif
+#if PACKETVER >= 20191002
+/*20191002 to latest
+판매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E65 = 0xe65,
+/*20191002 to latest
+구매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E66 = 0xe66,
+/*20191002 to latest
+VTC 인증에 실패하였습니다.
+*/
+ MSG_ID_E67 = 0xe67,
+#endif
+#if PACKETVER >= 20191016
+/*20191016 to latest
+물물교환 중에는 장비를 착용할 수 없습니다.
+*/
+ MSG_ID_E68 = 0xe68,
+/*20191016 to latest
+교환하려는 품목
+*/
+ MSG_ID_E69 = 0xe69,
+/*20191016 to latest
+ 1차, 2차, 3차 직업 스킬 %d개를 더 올려 주십시오.
+*/
+ MSG_ID_E6A = 0xe6a,
+#endif
+#if PACKETVER >= 20191030
+/*20191030 to latest
+같은 아이템은 %d개까지 소유할 수 있습니다.
+*/
+ MSG_ID_E6B = 0xe6b,
+/*20191030 to latest
+같은 아이템은 한 번에 %d개까지 교환할 수 있습니다.
+*/
+ MSG_ID_E6C = 0xe6c,
+/*20191030 to latest
+해당 로덱스는 "%s"서버에서 열 수 있습니다.
+*/
+ MSG_ID_E6D = 0xe6d,
+/*20191030 to latest
+[공지]편지함의 모든 메일을 삭제하시겠습니까 ?
+(해당 "%s"서버의 메일만 삭제됩니다.)
+*/
+ MSG_ID_E6E = 0xe6e,
+/*20191030 to latest
+[공지]편지함의 모든 첨부 물품을 받으시겠습니까?
+(해당 "%s"서버의 메일의 물품만 받으실 수 있습니다.)
+*/
+ MSG_ID_E6F = 0xe6f,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 삭제 가능합니다.
+*/
+ MSG_ID_E70 = 0xe70,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 물품 받기가 가능합니다.
+*/
+ MSG_ID_E71 = 0xe71,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 내용읽기가 가능합니다.
+*/
+ MSG_ID_E72 = 0xe72,
+/*20191030 to latest
+합계 : %d z
+*/
+ MSG_ID_E73 = 0xe73,
+/*20191030 to latest
+메세지
+*/
+ MSG_ID_E74 = 0xe74,
+#endif
+#if PACKETVER >= 20191106
+/*20191106 to latest
+구매상점 개설 중에는 개인상점의 물건을 구입할 수 없습니다.
+*/
+ MSG_ID_E75 = 0xe75,
+#endif
+#if PACKETVER >= 20191113
+/*20191113 to latest
+등급강화가 성공적으로 되었습니다.
+*/
+ MSG_ID_E76 = 0xe76,
+/*20191113 to latest
+등급강화가 실패하였습니다.
+*/
+ MSG_ID_E77 = 0xe77,
+/*20191113 to latest
+등급 수치가 하향 조정 되었습니다.
+*/
+ MSG_ID_E78 = 0xe78,
+/*20191113 to latest
+장비가 파괴되었습니다.
+*/
+ MSG_ID_E79 = 0xe79,
+/*20191113 to latest
+장비가 보호되었습니다.
+*/
+ MSG_ID_E7A = 0xe7a,
+/*20191113 to latest
+재료가 선택되지 않았습니다.
+*/
+ MSG_ID_E7B = 0xe7b,
+/*20191113 to latest
+재료가 부족합니다.
+*/
+ MSG_ID_E7C = 0xe7c,
+/*20191113 to latest
+소지 금액이 부족합니다.
+*/
+ MSG_ID_E7D = 0xe7d,
+/*20191113 to latest
+아이템 공간이 부족합니다.
+*/
+ MSG_ID_E7E = 0xe7e,
+/*20191113 to latest
+장비가 보호되고 있습니다.
+*/
+ MSG_ID_E7F = 0xe7f,
+/*20191113 to latest
+장비가 파괴될 수 있습니다.
+*/
+ MSG_ID_E80 = 0xe80,
+/*20191113 to latest
+등급강화 실패 시 등급이 내려갑니다.
+*/
+ MSG_ID_E81 = 0xe81,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+*/
+ MSG_ID_E82 = 0xe82,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다.
+*/
+ MSG_ID_E83 = 0xe83,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+*/
+ MSG_ID_E84 = 0xe84,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다.
+*/
+ MSG_ID_E85 = 0xe85,
+/*20191113 to latest
+[%s] 님이 등급강화를 성공하여, [%s등급 %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_E86 = 0xe86,
+/*20191113 to latest
+[%s] 님이 [%s등급 %s] 아이템의 등급강화에 실패하였습니다.
+*/
+ MSG_ID_E87 = 0xe87,
+/*20191113 to latest
+등급 강화가 불가능한 장비입니다.
+*/
+ MSG_ID_E88 = 0xe88,
+/*20191113 to latest
+체인지 메테리얼
+*/
+ MSG_ID_E89 = 0xe89,
+/*20191113 to latest
+가나다 정렬
+*/
+ MSG_ID_E8A = 0xe8a,
+/*20191113 to 20191224
+기본 결과물은 %s %d개 이나, 낮은 확률로 최대 %d개까지 생성될 수 있습니다.
+20200108 to latest
+※[%s] %d~%d개 제작
+*/
+ MSG_ID_E8B = 0xe8b,
+/*20191113 to latest
+성공 %d%%
+*/
+ MSG_ID_E8C = 0xe8c,
+/*20191113 to latest
+아이템 태그는 소지한 아이템만 태그할 수 있습니다.
+*/
+ MSG_ID_E8D = 0xe8d,
+#endif
+#if PACKETVER >= 20191127
+/*20191127 to latest
+공격력 및 특성 공격력이 증가되었습니다.
+*/
+ MSG_ID_E8E = 0xe8e,
+/*20191127 to latest
+강인한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E8F = 0xe8f,
+/*20191127 to latest
+HP 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_E90 = 0xe90,
+/*20191127 to latest
+굳건한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E91 = 0xe91,
+/*20191127 to latest
+공격 속도 및 유도 공격 확률이 증가되었습니다.
+*/
+ MSG_ID_E92 = 0xe92,
+/*20191127 to latest
+신실한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E93 = 0xe93,
+/*20191127 to latest
+POW, CRT 및 CON 이 증가되었습니다.
+*/
+ MSG_ID_E94 = 0xe94,
+/*20191127 to latest
+베네딕툼 효과가 해제되었습니다.
+*/
+ MSG_ID_E95 = 0xe95,
+/*20191127 to latest
+SPL, WIS 및 CRT 가 증가되었습니다.
+*/
+ MSG_ID_E96 = 0xe96,
+/*20191127 to latest
+렐리지오 효과가 해제되었습니다.
+*/
+ MSG_ID_E97 = 0xe97,
+/*20191127 to latest
+특성 공격력 및 특성 마법 공격력이 증가되었습니다.
+*/
+ MSG_ID_E98 = 0xe98,
+/*20191127 to latest
+콤페텐티아 효과가 해제되었습니다.
+*/
+ MSG_ID_E99 = 0xe99,
+/*20191127 to latest
+크리티컬 데미지 비율이 증가되었습니다.
+*/
+ MSG_ID_E9A = 0xe9a,
+/*20191127 to latest
+프레센스 아치에스 효과가 해제되었습니다.
+*/
+ MSG_ID_E9B = 0xe9b,
+/*20191127 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9C = 0xe9c,
+/*20191127 to latest
+아르구투스 텔룸 효과가 해제되었습니다.
+*/
+ MSG_ID_E9D = 0xe9d,
+/*20191127 to latest
+마법 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9E = 0xe9e,
+/*20191127 to latest
+아르구투스 비타 효과가 해제되었습니다.
+*/
+ MSG_ID_E9F = 0xe9f,
+/*20191127 to latest
+Num: %d/%d Weight: %d/%d
+*/
+ MSG_ID_EA0 = 0xea0,
+#endif
+#if PACKETVER >= 20191204
+/*20191204 to latest
+서번트 웨폰 효과가 해제되었습니다.
+*/
+ MSG_ID_EA1 = 0xea1,
+/*20191204 to latest
+챠징 피어스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA2 = 0xea2,
+/*20191204 to latest
+비고르 효과가 해제되었습니다.
+*/
+ MSG_ID_EA3 = 0xea3,
+/*20191204 to latest
+공격력이 증가하고, 방어력이 감소되었습니다.
+*/
+ MSG_ID_EA4 = 0xea4,
+/*20191204 to latest
+어택 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA5 = 0xea5,
+/*20191204 to latest
+방어력이 증가하고, 공격력이 감소되었습니다.
+*/
+ MSG_ID_EA6 = 0xea6,
+/*20191204 to latest
+가드 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA7 = 0xea7,
+/*20191204 to latest
+배리어가 부여되었습니다.
+*/
+ MSG_ID_EA8 = 0xea8,
+/*20191204 to latest
+가디언 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EA9 = 0xea9,
+/*20191204 to latest
+헌신 효과로 받는 데미지가 감소되었습니다.
+*/
+ MSG_ID_EAA = 0xeaa,
+/*20191204 to latest
+리바운드 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAB = 0xeab,
+/*20191204 to latest
+성속성 마법 데미지와 암/불사속성 내성이 증가되었습니다.
+*/
+ MSG_ID_EAC = 0xeac,
+/*20191204 to latest
+홀리 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAD = 0xead,
+/*20191204 to latest
+즉시 부활 효과가 부여되었습니다.
+*/
+ MSG_ID_EAE = 0xeae,
+/*20191204 to latest
+얼티메이트 세크리파이스 효과가 해제되었습니다.
+*/
+ MSG_ID_EAF = 0xeaf,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB0 = 0xeb0,
+/*20191204 to latest
+클라이막스 효과가 해제되었습니다.
+*/
+ MSG_ID_EB1 = 0xeb1,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB2 = 0xeb2,
+/*20191204 to latest
+쉐도우 익시드 효과가 해제되었습니다.
+*/
+ MSG_ID_EB3 = 0xeb3,
+/*20191204 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_EB4 = 0xeb4,
+/*20191204 to latest
+포텐트 베넘 효과가 해제되었습니다.
+*/
+ MSG_ID_EB5 = 0xeb5,
+/*20191204 to latest
+매 공격 시, 일정 확률로 대상이 받는 데미지를 증가시킵니다.
+*/
+ MSG_ID_EB6 = 0xeb6,
+/*20191204 to latest
+인챈팅 쉐도우 효과가 해제되었습니다.
+*/
+ MSG_ID_EB7 = 0xeb7,
+#endif
+#if PACKETVER >= 20191211
+/*20191211 to latest
+토벌 카운트 On
+*/
+ MSG_ID_EB8 = 0xeb8,
+/*20191211 to latest
+토벌 카운트 Off
+*/
+ MSG_ID_EB9 = 0xeb9,
+/*20191211 to latest
+대상의 AP가 최대치입니다
+*/
+ MSG_ID_EBA = 0xeba,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBB = 0xebb,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBC = 0xebc,
+#endif
+#if PACKETVER >= 20191218
+/*20191218 to latest
+서번트 웨폰 %d개가 필요합니다.
+*/
+ MSG_ID_EBD = 0xebd,
+/*20191218 to latest
+https://member.gnjoy.com.tw/billing.aspx
+*/
+ MSG_ID_EBE = 0xebe,
+#endif
+#if PACKETVER >= 20200108
+/*20200108 to latest
+역순 정렬
+*/
+ MSG_ID_EBF = 0xebf,
+/*20200108 to latest
+검색 내용 입력
+*/
+ MSG_ID_EC0 = 0xec0,
+/*20200108 to latest
+검색
+Search
+*/
+ MSG_ID_EC1 = 0xec1,
+#endif
+#if PACKETVER >= 20200122
+/*20200122 to latest
+리서치 리포트 상태가 됩니다.
+*/
+ MSG_ID_EC2 = 0xec2,
+/*20200122 to latest
+리서치 리포트 상태가 해제됩니다.
+*/
+ MSG_ID_EC3 = 0xec3,
+/*20200122 to latest
+제조에 성공 했습니다.
+*/
+ MSG_ID_EC4 = 0xec4,
+/*20200122 to latest
+제조에 실패 했습니다.
+*/
+ MSG_ID_EC5 = 0xec5,
+/*20200122 to latest
+쉐도우 장비가 파괴 및 해제에서 보호됩니다.
+*/
+ MSG_ID_EC6 = 0xec6,
+/*20200122 to latest
+풀 쉐도우 프로텍션이 해제됩니다.
+*/
+ MSG_ID_EC7 = 0xec7,
+/*20200122 to latest
+식물형, 무형 몬스터에게 주는 데미지가 증가합니다.
+*/
+ MSG_ID_EC8 = 0xec8,
+/*20200122 to latest
+지옥 나무의 가루효과가 사라집니다.
+*/
+ MSG_ID_EC9 = 0xec9,
+#endif
+#if PACKETVER >= 20200129
+/*20200129 to latest
+공격 장치가 활성화되었습니다.
+*/
+ MSG_ID_ECA = 0xeca,
+/*20200129 to latest
+공격 장치가 해제되었습니다.
+*/
+ MSG_ID_ECB = 0xecb,
+/*20200129 to latest
+물리 방어력 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_ECC = 0xecc,
+/*20200129 to latest
+방어 장치가 해제되었습니다.
+*/
+ MSG_ID_ECD = 0xecd,
+/*20200129 to latest
+검색
+Search
+*/
+ MSG_ID_ECE = 0xece,
+#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
+
+};
+#endif /* MAP_MESSAGES_MAIN_H */
diff --git a/src/map/messages_re.h b/src/map/messages_re.h
new file mode 100644
index 000000000..e32f6b275
--- /dev/null
+++ b/src/map/messages_re.h
@@ -0,0 +1,22094 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_MESSAGES_RE_H
+#define MAP_MESSAGES_RE_H
+
+/* This file is autogenerated, please do not commit manual changes
+
+Latest version: 20200304
+*/
+
+enum clif_messages {
+/*20080827 to latest
+동의 하십니까?
+Do you agree?
+*/
+ MSG_DO_YOU_AGREE = 0x0,
+/*20080827 to latest
+서버 연결 실패
+Failed to Connect to Server.
+*/
+ MSG_SERVER_CONNECTION_FAILED = 0x1,
+/*20080827 to latest
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+*/
+ MSG_UNABLE_TO_CONNECT_SERVER = 0x2,
+/*20080827 to latest
+서버와 연결이 끊어졌습니다!
+Disconnected from Server!
+*/
+ MSG_BANNED = 0x3,
+/*20080827 to latest
+서버 종료됨
+Server Closed.
+*/
+ MSG_SERVER_OFF = 0x4,
+/*20080827 to latest
+같은 계정으로 다른 사용자가 로그인 하였습니다.
+Someone has Logged in with this ID.
+*/
+ MSG_DOUBLE_LOGIN_PROHIBITED = 0x5,
+/*20080827 to latest
+등록되지 않은 계정입니다. 다시 확인 바랍니다.
+Unregistered ID. Please make sure you have a registered account and you have correctly typed in the user ID.
+*/
+ MSG_INCORRECT_USERID = 0x6,
+/*20080827 to latest
+입력하신 비밀번호가 올바르지 않습니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_PASSWORD = 0x7,
+/*20080827 to latest
+본 ID 는 사용기간이 만료 되었습니다
+This ID is expired.
+*/
+ MSG_ID_EXPIRED = 0x8,
+/*20080827 to latest
+서버 접근 거부
+Rejected from Server.
+*/
+ MSG_ACCESS_DENIED = 0x9,
+/*20080827 to latest
+같은 캐릭터 이름이 있습니다.
+Character Name already exists.
+*/
+ MSG_CHARACTER_NAME_ALREADY_EXISTS = 0xa,
+/*20080827 to latest
+캐릭터 생성 거부됨
+Character Creation is denied.
+*/
+ MSG_CHARACTER_CREATION_DENIED = 0xb,
+/*20080827 to latest
+캐릭터 삭제 거부
+Character Deletion is denied.
+*/
+ MSG_CANNOT_DELETE_CHARACTER = 0xc,
+/*20080827 to latest
+방제목를 입력하세요.
+Please Enter Room Title.
+*/
+ MSG_ENTER_ROOM_TITLE = 0xd,
+/*20080827 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_SENTANGE = 0xe,
+/*20080827 to latest
+암호를 입력하세요.
+Please enter Password.
+*/
+ MSG_ENTER_PASSWORD = 0xf,
+/*20080827 to latest
+암호를 영문 4자 이상 입력하세요.
+Please enter Password. Passwords must be at least 4 characters long.
+*/
+ MSG_Enter_Password_more_than_4_char = 0x10,
+/*20080827 to latest
+종료 하시겠습니까?
+Are you sure that you want to quit?
+*/
+ MSG_DO_YOU_REALLY_WANT_TO_QUIT = 0x11,
+/*20080827 to latest
+4자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Passwords are at least 4 characters long. Please try again.
+*/
+ MSG_NAME_MUST_EXCEED_4_CHAR = 0x12,
+/*20080827 to latest
+한 번 삭제된 캐릭터 및 관련 정보는 다시 복구되지 않습니다. 캐릭터를 삭제하시겠습니까?
+Are you sure that you want to delete this character?
+*/
+ MSG_DELETE_CHARACTER = 0x13,
+/*20080827 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_NAME = 0x14,
+/*20080827 to latest
+이름을 입력해 주세요.(한글 2자 영문 4자 이상)
+Character Name must be at least 4 characters long.
+*/
+ MSG_ENTER_NAME_MORE_THAN_4_CHAR = 0x15,
+/*20080827 to latest
+명령어 일람: /h
+Command List: /h | /help
+*/
+ MSG_LIST_COMMAND = 0x16,
+/*20080827 to latest
+이펙트 On
+Effects On
+*/
+ MSG_EFFECT_ON = 0x17,
+/*20080827 to latest
+이펙트 Off
+Effects Off
+*/
+ MSG_EFFECT_OFF = 0x18,
+/*20080827 to latest
+사운드 볼륨
+Sound Volume
+*/
+ MSG_VOLUME_OF_SOUND = 0x19,
+/*20080827 to latest
+배경음악 볼륨
+BGM Volume
+*/
+ MSG_VOLUME_OF_BGM = 0x1a,
+/*20080827 to latest
+효과음 On
+Sound Effects On
+*/
+ MSG_SOUND_ON = 0x1b,
+/*20080827 to latest
+효과음 Off
+Sound Effects Off
+*/
+ MSG_SOUND_OFF = 0x1c,
+/*20080827 to latest
+프레임스킵 On
+Frame Skip On
+*/
+ MSG_FRAME_SKIP_ON = 0x1d,
+/*20080827 to latest
+프레임스킵 Off
+Frame Skip Off
+*/
+ MSG_FRAME_SKIP_OFF = 0x1e,
+/*20080827 to latest
+배경음악 On
+BGM On
+*/
+ MSG_BGM_ON = 0x1f,
+/*20080827 to latest
+배경음악 Off
+BGM Off
+*/
+ MSG_BGM_OFF = 0x20,
+/*20080827 to latest
+/h or /help: 명령어 일람
+/h or /help: Shows this Command Help List
+*/
+ MSG_EXPLAIN_HELP = 0x21,
+/*20080827 to latest
+/w or /who or /접속자 or /누구: 현재 접속자수 보기
+/w or /who or /player or /who: wiew current the number of player
+*/
+ MSG_EXPLAIN_WHO = 0x22,
+/*20080827 to latest
+/음악 : 배경음악 On Off
+/music: Turns BGM On or Off
+*/
+ MSG_EXPLAIN_MUSIC = 0x23,
+/*20080827 to latest
+/효과음 : 효과음 On Off
+/sound: Turns Sound Effects On or Off
+*/
+ MSG_EXPLAIN_SOUND = 0x24,
+/*20080827 to latest
+/이펙트 : 이펙트 On Off
+/effect: Effects On or Off
+*/
+ MSG_EXPLAIN_EFFECT = 0x25,
+/*20080827 to latest
+/좌표 or /장소: 현재 위치 표시
+/where: Shows your present location
+*/
+ MSG_EXPLAIN_POS = 0x26,
+/*20080827 to latest
+/skip : 프래임스킵 On Off
+/skip: Turns Frame Skip On or Off
+*/
+ MSG_EXPLAIN_FRAMESKIP = 0x27,
+/*20080827 to latest
+/v (0~127): 효과음 볼륨조정
+/v (0~127): Controls the volume of the Sound Effects
+*/
+ MSG_EXPLAIN_SOUNDVOLUME = 0x28,
+/*20080827 to latest
+/bv (0~127): 배경음악 볼륨조정
+/bv (0~127): Controls the volume of the BGM
+*/
+ MSG_EXPLAIN_BGMVOLUME = 0x29,
+/*20080827 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당캐릭터에 대해 귓말차단
+/ex (Character Name): Blocks whispering from the Character
+*/
+ MSG_EXPLAIN_SAYISOLATION = 0x2a,
+/*20080827 to latest
+/ex or /차단 : 귓말차단 캐릭터 리스트
+/ex: View a list of Characters you have Blocked
+*/
+ MSG_EXPLAIN_LIST_SAYISOLATION_CHAR = 0x2b,
+/*20080827 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당캐릭터에 대해 귓말허용
+/in (Character Name): Allows whispering from the Character
+*/
+ MSG_EXPLAIN_SAY_PERMIT = 0x2c,
+/*20080827 to latest
+/inall or /해제전부 : 모두에게 귓말허용
+/inall: Allows whispers from anyone
+*/
+ MSG_EXPLAIN_SAY_PERMITALL = 0x2d,
+/*20080827 to latest
+/exall or /차단전부 : 모두에게 귓말차단
+/exall: Blocks whispers from everyone
+*/
+ MSG_EXPLAIN_SAY_ISOLATEALL = 0x2e,
+/*20080827 to latest
+다른유저 캐릭터를 마우스 오른버튼을 누르고 있는 상태에서 왼버튼으로 클릭하면 그캐릭터이름이 귓말콤보박스에 저장됩니다.
+Right click on a character and select [Register as a Friend] to add a person to your Friend List.
+*/
+ MSG_EXPLAIN_TIP1 = 0x2f,
+/*20080827 to latest
+단축아이탬창(F12) 소비장비 아이템을 드래그한후 사용하세요. 사용키(F1F2F3F4F5F6F7F8F9)
+F12 Brings up a Hotkey Window which allows you to drag and drop Recovery Items, Equipment and Skills into it for faster access.
+*/
+ MSG_EXPLAIN_TIP2 = 0x30,
+/*20080827 to latest
+같은말을 3번이상 연속해서 전송할 수 없습니다.
+You can't type the same word/phrase more than 3 times.
+*/
+ MSG_NO_SAME_SENTANCE = 0x31,
+/*20080827 to latest
+불량단어 검출로 전송이 중단 되었습니다.
+Chat Filter: Yeah, uh, I don't think so buddy...
+*/
+ MSG_NO_SEND_BECAUSE_INSULT = 0x32,
+/*20080827 to latest
+같은아이템은 한번만 올릴수 있습니다.
+You cannot overlap items on a window.
+*/
+ MSG_CAN_DRAG_ITEM_OLNY_ONETIME = 0x33,
+/*20080827 to latest
+무게가 초과하여 아이템을 가질 수 없습니다.
+You cannot carry more items because you are overweight.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_WEIGHT = 0x34,
+/*20080827 to latest
+아이템을 가질 수 없습니다.
+You cannot get the item.
+*/
+ MSG_CANT_GET_ITEM = 0x35,
+/*20080827 to latest
+거래가 잘 이루어졌습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SECCESS = 0x36,
+/*20080827 to latest
+돈이 부족합니다.
+You do not have enough zeny.
+*/
+ MSG_INSUFFICIENT_MONEY = 0x37,
+/*20080827 to latest
+무게가 초과 되었습니다.
+You are over your Weight Limit.
+*/
+ MSG_OVER_WEIGHT = 0x38,
+/*20080827 to latest
+거래가 실패 했습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAIL = 0x39,
+/*20080827 to latest
+모두에게 귓말거부상태로됨
+You've blocked whispers from everyone.
+*/
+ MSG_REFUSE_HEAR_ALL = 0x3a,
+/*20080827 to latest
+모두에게 귓말거부요청 실패함
+You've failed to block all whispers.
+*/
+ MSG_REQ_REFUSE_HEAR_ALL_FAIL = 0x3b,
+/*20080827 to latest
+모두에게 귓말가능상태가됨
+You've allowed whispers from everyone.
+*/
+ MSG_HEAR_ALL = 0x3c,
+/*20080827 to latest
+모두에게 귓말가능요청 실패함
+You've failed to allow all whispers.
+*/
+ MSG_REQ_HEAR_ALL_FAIL = 0x3d,
+/*20080827 to latest
+귓말 거부 리스트가 없습니다
+You have no Block List.
+*/
+ MSG_NO_REFUSE_HEAR_LIST = 0x3e,
+/*20080827 to latest
+-귓말 거부 리스트-
+[ Character Block List ]
+*/
+ MSG_REFUSE_HEAR_LIST = 0x3f,
+/*20080827 to latest
+방이 잘 만들어 졌습니다.
+Room has been successfully created.
+*/
+ MSG_ROOM_IS_MADE = 0x40,
+/*20080827 to latest
+방갯수가 허용갯수를 초과 하였습니다.
+Room Limit Exceeded.
+*/
+ MSG_TOO_MANY_ROOM = 0x41,
+/*20080827 to latest
+같은 방제목이 있습니다.
+Same Room exists.
+*/
+ MSG_SAME_ROOM_TITLE = 0x42,
+/*20080827 to latest
+인원초과로 방에 들어갈 수 없습니다.
+The Room is full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_ROOM = 0x43,
+/*20080827 to latest
+강제로 퇴장된 방입니다.
+You have been kicked out of this room.
+*/
+ MSG_YOU_HAVE_BANNED_FROM_THE_ROOM = 0x44,
+/*20080827 to latest
+교환요청을 거절 했습니다.
+The deal has been rejected.
+*/
+ MSG_REJECT_DEAL = 0x45,
+/*20080827 to latest
+교환가능거리를 벗어났습니다.
+You are too far away from the person to trade.
+*/
+ MSG_TOO_FAR_TO_DEAL = 0x46,
+/*20080827 to latest
+해당 캐릭터가 없습니다.
+The Character is not currently online or does not exist.
+*/
+ MSG_CHARACTER_IS_NOT_EXIST = 0x47,
+/*20080827 to latest
+다른캐릭터와 교환중입니다.
+The person is in another deal.
+*/
+ MSG_CHARACTER_IS_DEALING = 0x48,
+/*20080827 to 20110628
+상태캐릭터 중량초과로 올려놓을수가 없습니다.
+20110706 to latest
+상대 캐릭터 중량초과로 올려놓을 수 없습니다.
+You cannot trade because this character will exceed his weight limit.
+*/
+ MSG_CHARACTER_IS_OVER_WEIGHT = 0x49,
+/*20080827 to latest
+거래가 취소 되었습니다.
+The deal has been canceled.
+*/
+ MSG_DEAL_IS_CANCELED = 0x4a,
+/*20080827 to latest
+아이템 교환이 잘 되었습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SUCCESS = 0x4b,
+/*20080827 to latest
+아이템 교환이 실패 하였습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAILED = 0x4c,
+/*20080827 to latest
+파티가 만들어졌습니다.
+Party has successfully been organized.
+*/
+ MSG_PARTY_MAKE_SUCCEED = 0x4d,
+/*20080827 to latest
+같은 파티이름이 있습니다.
+That Party Name already exists.
+*/
+ MSG_SAME_PARTY_NAME = 0x4e,
+/*20080827 to latest
+이미 파티에 속해있습니다.
+The Character is already in a party.
+*/
+ MSG_YOU_ARE_ALREADY_IN_PARTY = 0x4f,
+/*20080827 to latest
+다른파티에 가입되어 있습니다.
+The Character already joined another party.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_PARTY = 0x50,
+/*20080827 to latest
+파티가입을 거부했습니다.
+Request for party rejected.
+*/
+ MSG_CHARACTER_REJECT_JOIN = 0x51,
+/*20080827 to latest
+파티가입을 수락했습니다.
+Request for party accepted.
+*/
+ MSG_CHARACTER_ACCEPT_JOIN = 0x52,
+/*20080827 to latest
+파티정원을 초과했습니다.
+Party Capacity exceeded.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_PARTY = 0x53,
+/*20080827 to latest
+파티에서 탈퇴하였습니다.
+You left the party.
+*/
+ MSG_YOU_LEAVE_FROM_PARTY = 0x54,
+/*20080827 to latest
+전체에게 보냄
+Send to All
+*/
+ MSG_SEND_TO_ALL = 0x55,
+/*20080827 to latest
+파티에게 보냄
+Send to Party
+*/
+ MSG_SEND_TO_PARTY = 0x56,
+/*20080827 to latest
+님과의 거래요청
+Request a deal with %s
+*/
+ MSG_REQ_DEAL_WITH = 0x57,
+/*20080827 to latest
+님 파티에 가입요청
+Ask %s to join your party
+*/
+ MSG_REQ_JOIN_PARTY = 0x58,
+/*20080827 to latest
+비공개 :
+Pri:
+*/
+ MSG_ROOM_PRIVATE = 0x59,
+/*20080827 to latest
+공개 :
+Pub:
+*/
+ MSG_ROOM_PUBLIC = 0x5a,
+/*20080827 to latest
+마지막 체크지점부터 시작하려면 '재시작'을 캐릭터 선택으로 돌아가려면 '종료'를 눌러주세요.
+Click ''Restart'' to go back to your save point or click ''Exit'' to select another character.
+*/
+ MSG_RESTART_MSG = 0x5b,
+/*20080827 to latest
+원하는 거래를 선택하세요.
+Please select a Deal Type.
+*/
+ MSG_SELECT_DEAL_TYPE = 0x5c,
+/*20080827 to latest
+님이 거래를 요청했습니다.
+ requests a deal.
+*/
+ MSG_SUGGEST_DEAL = 0x5d,
+/*20080827 to latest
+ 파티에서 초청 메시지가 왔습니다. 합류하겠습니까?
+ Party has sent you an invitation. Would you like to join?
+*/
+ MSG_SUGGEST_JOIN_PARTY = 0x5e,
+/*20080827 to latest
+명령이 틀렸습니다.
+Invalid Command
+*/
+ MSG_INVALID_COMMAND = 0x5f,
+/*20080827 to latest
+탈퇴하기
+Leave party
+*/
+ MSG_LEAVE_PARTY = 0x60,
+/*20080827 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL = 0x61,
+/*20080827 to latest
+쪽지보내기
+Send Message
+*/
+ MSG_MSG = 0x62,
+/*20080827 to latest
+1:1 대화
+1:1 Chat
+*/
+ MSG_1ON1 = 0x63,
+/*20080827 to latest
+정보
+Information
+*/
+ MSG_CHARACTER_INFO = 0x64,
+/*20080827 to latest
+파티설정
+Party Setup
+*/
+ MSG_PARTY_SETTING = 0x65,
+/*20080827 to latest
+친구
+Friend
+*/
+ MSG_FRIEND = 0x66,
+/*20080827 to latest
+파티
+Party
+*/
+ MSG_PARTY = 0x67,
+/*20080827 to latest
+장착아이템
+Equipment
+*/
+ MSG_EQUIPED_ITEM = 0x68,
+/*20080827 to latest
+스테이터스
+Status
+*/
+ MSG_STATUS_ = 0x69,
+/*20080827 to latest
+소지아이템
+Inventory
+*/
+ MSG_ITEM = 0x6a,
+/*20080827 to latest
+/결성 [파티이름] : 파티결성 /탈퇴 : 파티탈퇴
+/organize ''Party Name'' To organize a party. Type /leave To leave a Party.
+*/
+ MSG_EXPLAIN_PARTY = 0x6b,
+/*20080827 to latest
+자신이 파티리더일때 캐릭터를 오른버튼으로 클릭하면 파티에 가입요청하기 메뉴가 뜹니다.
+If you are the party master, you can invite someone into your party by right-clicking on a Character.
+*/
+ MSG_EXPLAIN_TIP3 = 0x6c,
+/*20080827 to latest
+회복
+Consumables
+*/
+ MSG_RESTORE = 0x6d,
+/*20080827 to latest
+공격
+Attack
+*/
+ MSG_ATTACK = 0x6e,
+/*20080827 to latest
+보조
+Support
+*/
+ MSG_SUPPORT = 0x6f,
+/*20080827 to latest
+전체
+All
+*/
+ MSG_ALL = 0x70,
+/*20080827 to latest
+무기
+Weapons
+*/
+ MSG_WEAPON = 0x71,
+/*20080827 to latest
+방어
+Defense
+*/
+ MSG_DEFENCE = 0x72,
+/*20080827 to latest
+수
+Water
+*/
+ MSG_WATER = 0x73,
+/*20080827 to latest
+지
+Earth
+*/
+ MSG_EARTH = 0x74,
+/*20080827 to latest
+화
+Fire
+*/
+ MSG_FIRE = 0x75,
+/*20080827 to latest
+풍
+Wind
+*/
+ MSG_WIND = 0x76,
+/*20080827 to 20191023
+같은종류의 장비아이템은 한번에 한개만 살 수 있습니다.
+Please avoid buying 2 of the same items at one time.
+20191030 to latest
+같은 종류의 장비 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_EQUIPITEM_OLNY_ONE = 0x77,
+/*20080827 to latest
+창모드에서 실행 할때는 16비트 컬러로 맞춰주세요.
+Please change your desktop Color Depth to 16-bit when running Ragnarok in windowed mode.
+*/
+ MSG_ONLY_16BIT_WHEN_WINDOWMODE = 0x78,
+/*20080827 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_PLEASE_BE_PATIENT = 0x79,
+/*20080827 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_WAITING_RESPONSE_FROM_SERVER = 0x7a,
+/*20080827 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_MAKING_CHARACTER = 0x7b,
+/*20080827 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_DELETING_CHARACTER = 0x7c,
+/*20080827 to latest
+방 만들기
+Make a Room
+*/
+ MSG_MAKING_ROOM = 0x7d,
+/*20080827 to latest
+방셋팅 바꾸기
+Room Setup
+*/
+ MSG_CHANGE_ROOM_SETTING = 0x7e,
+/*20080827 to latest
+강퇴시키기
+Kick Character Out
+*/
+ MSG_BAN = 0x7f,
+/*20080827 to latest
+방장권한 주기
+Give Master Authority
+*/
+ MSG_GIVE_GIVE_ROOM_POWER = 0x80,
+/*20080827 to latest
+정보보기
+View Information
+*/
+ MSG_SEE_INFORMATION_OF_CHARACTER = 0x81,
+/*20080827 to latest
+대화방
+Chat Room
+*/
+ MSG_CHAT_ROOM = 0x82,
+/*20080827 to latest
+명
+Ppl
+*/
+ MSG_COUNT_UNIT_OF_PEOPLE = 0x83,
+/*20080827 to latest
+/앉기 or /sit : 앉기. 앉아있을때 서기
+/sit: Sit command. If you are sitting, you will stand instead.
+*/
+ MSG_EXPLAIN_SIT = 0x84,
+/*20080827 to latest
+/서기 or /stand : 서기. 서있을때 앉기
+/stand: Stand command. If you are standing, you will sit instead.
+*/
+ MSG_EXPLAIN_STAND = 0x85,
+/*20080827 to latest
+/채팅방 or /chat : 채팅방 만들기창 띄우기
+/chat: Creates a Chat Room
+*/
+ MSG_EXPLAIN_MAKE_CHAT = 0x86,
+/*20080827 to latest
+/q : 채팅방 나가기.
+/q: Leaves a Chat Room
+*/
+ MSG_EXPLAIN_EXIT_CHAT_ROOM = 0x87,
+/*20080827 to latest
+/거래 [캐릭터이름] or /교환 [캐릭터이름] or /deal [캐릭터이름] : 해당 캐릭터와 거래요청
+/deal ''Character Name'' Requests a deal with a character
+*/
+ MSG_EXPLAIN_DEAL = 0x88,
+/*20080827 to latest
+/결성 [파티이름] or /organize [파티이름] : 파티결성
+/organize ''Party Name'' Organizes a party
+*/
+ MSG_EXPLAIN_ORGANIZE_PARTY = 0x89,
+/*20080827 to latest
+/탈퇴 or /leave : 파티 탈퇴
+/leave: Leaves a party
+*/
+ MSG_EXPLAIN_LEAVE_PARTY = 0x8a,
+/*20080827 to latest
+/제명 [캐릭터이름] or /expel [캐릭터이름] : 해당캐릭터를 파티에서 제명시킴
+/expel ''Character Name'' kicks a Character out of your party
+*/
+ MSG_EXPLAIN_EXPEL_PARTY_MEMBER = 0x8b,
+/*20080827 to latest
+[Alt] + [End] : 플레이어 hp/sp 게이지 On Off
+[Alt] + [End]: Turns HP/SP Bar On or Off
+*/
+ MSG_EXPLAIN_TIP4 = 0x8c,
+/*20080827 to latest
+[Alt] + [Home] : 지면 커서 표시 On Off
+[Alt] + [Home]: Turns Ground Cursor On or Off
+*/
+ MSG_EXPLAIN_TIP5 = 0x8d,
+/*20080827 to latest
+[Insert] : 앉기 서기
+[Insert]: Makes you sit or stand. (Hotkey to toggle between /sit and /stand)
+*/
+ MSG_EXPLAIN_TIP6 = 0x8e,
+/*20080827 to latest
+MVP가 되셨습니다!! MVP 아이템은
+Congratulations! You are the MVP! Your reward item is
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM = 0x8f,
+/*20080827 to latest
+ !!
+!
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM2 = 0x90,
+/*20080827 to latest
+MVP가 되셨습니다!! 특별경험치
+Congratulations! You are the MVP! Your reward EXP Points are
+*/
+ MSG_YOU_RECEIVE_MVP_EXP = 0x91,
+/*20080827 to latest
+ 획득!!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_EXP2 = 0x92,
+/*20080827 to latest
+MVP가 되셨습니다만 무게초과로 MVP 아이템을 가질 수 없었습니다!!
+You are the MVP, but you can't take the reward because you are over your weight limit.
+*/
+ MSG_YOU_THROW_MVPITEM = 0x93,
+/*20080827 to latest
+ 없는 캐릭터 이름 입니다.
+There is no such character name or the user is offline.
+*/
+ MSG_NOT_EXIST_CHARACTER = 0x94,
+/*20080827 to latest
+ 수신 거부 상태입니다.
+ doesn't want to receive your messages.
+*/
+ MSG_NO_RECEIVE_MODE = 0x95,
+/*20080827 to latest
+ 모든 캐릭터에 대해 수신 거부 상태 입니다.
+ is not in the mood to talk with anyone.
+*/
+ MSG_NO_RECEIVE_MODE_FOR_ALL = 0x96,
+/*20080827 to latest
+캐릭터 접속끊기 성공.
+Killed/Disconnected User.
+*/
+ MSG_SUCCESS_DISCONNECT_CHARACTER = 0x97,
+/*20080827 to latest
+캐릭터 접속끊기 실패.
+Kill has failed.
+*/
+ MSG_FAIL_DISCONNECT_CHARACTER = 0x98,
+/*20080827 to latest
+%s %d 개 획득
+You got %s (%d).
+*/
+ MSG_GET_ITEM = 0x99,
+/*20080827 to latest
+[Alt] + [=] : 알파벳 간격이 넓어졌을때 되돌리기.
+[Alt] + [=]: Fix the interval error between letters.
+*/
+ MSG_EXPLAIN_TIP7 = 0x9a,
+/*20080827 to latest
+[F10] : 채팅창 크기조정 [Alt] + [F10] : 채팅창 On Off
+[F10]: To toggle Chat Window size; [Alt] + [F10]: Toggle Chat Window On or Off
+*/
+ MSG_EXPLAIN_TIP8 = 0x9b,
+/*20080827 to latest
+귓속말 하는법 : 채팅창 왼쪽 입력란에 캐릭터이름을 입력하고 오른쪽 입력란에 말을 입력하면 됩니다. TAB키로 두입력란 사이로 커서를 이동할 수 있습니다.
+How to Whisper: Enter a Character's Name on the left side of chat window and type your message on the right side. The Tab key helps you move between these boxes.
+*/
+ MSG_EXPLAIN_TIP9 = 0x9c,
+/*20080827 to latest
+/! /? /기쁨 /하트 /땀 /아하 /짜증 /화 /돈 /... /가위 /바위 /보 : Alt + (1~9) Ctrl + (-=\) 에 대응되는 명령어 입니다.
+/!,/?,/ho,/lv,/lv2,/swt,/ic,/an,/ag,/$,/….,/thx,/wah,/sry,/heh,/swt2,/hmm,/no1,/??,/omg,/oh,/X,/hp,/go,/sob,/gg,/kis,/kis2,/pif,/ok: Emotion icons corresponding to Alt + (1~9) Ctrl + (-=\\)
+*/
+ MSG_EXPLAIN_TIP10 = 0x9d,
+/*20080827 to latest
+파티원에게 말하는법 : 말의 제일앞에 '%'를 붙이면 파티원에게 말이 갑니다. (예: "%안녕")
+How to Speak to Party: Add % in front of every message.(Example: \%Hello\)
+*/
+ MSG_EXPLAIN_TIP11 = 0x9e,
+/*20080827 to latest
+스킬레벨이 부족합니다. 교환 불능.
+You haven't learned enough Basic Skills to Trade.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE1 = 0x9f,
+/*20080827 to latest
+스킬레벨이 부족합니다. 이모션 불능.
+You haven't learned enough Basic Skills to use Emotion icons.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE2 = 0xa0,
+/*20080827 to latest
+스킬레벨이 부족합니다. 앉기 불능.
+You haven't learned enough Basic Skills to Sit.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE3 = 0xa1,
+/*20080827 to latest
+스킬레벨이 부족합니다. 채팅방만들기 불능.
+You haven't learned enough Basic Skills to create a chat room.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE4 = 0xa2,
+/*20080827 to latest
+스킬레벨이 부족합니다. 파티만들기 불능
+You haven't learned enough Basic Skills to Party.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5 = 0xa3,
+/*20080827 to latest
+스킬레벨이 부족합니다. 외치기 불능
+You haven't learned enough skills to Shout.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE6 = 0xa4,
+/*20080827 to latest
+스킬레벨이 부족합니다. pk 불능
+You haven't learned enough skills for Pking.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE7 = 0xa5,
+/*20080827 to latest
+사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY = 0xa6,
+/*20080827 to latest
+아이템 상점
+Item Shop
+*/
+ MSG_ITEM_STORE = 0xa7,
+/*20080827 to latest
+팔고자하는 품목
+Selling Items
+*/
+ MSG_ITEMS_FOR_SELL = 0xa8,
+/*20080827 to latest
+보관아이템
+Storage
+*/
+ MSG_ITEMS_THAT_IS_STORED = 0xa9,
+/*20080827 to latest
+ 장비가 장착 되었습니다.
+ is put on.
+*/
+ MSG_ITEM_IS_EQUIPED = 0xaa,
+/*20080827 to latest
+ 장비가 해제 되었습니다.
+ is taken off.
+*/
+ MSG_ITEM_IS_REMOVED = 0xab,
+/*20080827 to latest
+귓말리스트에 이름넣기
+To add names on the Whispering List
+*/
+ MSG_ADD_TO_WHISPER_CHAR_LIST = 0xac,
+/*20080827 to latest
+스크린샷 찍는법 : [Print Screen]키나 [Scroll Lock]키를 누르면 됩니다.
+How to Take Screen Shots: Press [Print Screen] or [Scroll Lock]
+*/
+ MSG_EXPLAIN_TIP12 = 0xad,
+/*20080827 to latest
+오늘의 팁
+Tip of the Day
+*/
+ MSG_TIPOFTHEDAY = 0xae,
+/*20080827 to latest
+^3850a0알고 계셨습니까... ^000000 //^709fed
+^3850a0Did you know...?^709fed
+*/
+ MSG_DIDYOUKNOW = 0xaf,
+/*20080827 to latest
+시작할때 열기
+Display at startup
+*/
+ MSG_SHOWTIPSATSTARTUP = 0xb0,
+/*20080827 to latest
+/tip : 오늘의팁 열기
+/tip: Opens ''Tip of the Day''
+*/
+ MSG_EXPLAIN_OPENTIP = 0xb1,
+/*20080827 to latest
+현재 접속자 %d명
+There are %d Players Currently Connected.
+*/
+ MSG_NUMPEOPLE = 0xb2,
+/*20080827 to latest
+(%s)님이 입장 하였습니다.
+(%s) has entered.
+*/
+ MSG_USERGETINTHEROOM = 0xb3,
+/*20080827 to latest
+(%s)님이 퇴장 하였습니다.
+(%s) has left.
+*/
+ MSG_USERGETOUTOFTHEROOM = 0xb4,
+/*20080827 to latest
+(%s)님이 강제 퇴장 되었습니다.
+(%s) was kicked out.
+*/
+ MSG_USERGETOUTOFTHEROOMBYFORCE = 0xb5,
+/*20080827 to latest
+ %d 개
+%d ea.
+*/
+ MSG_EA = 0xb6,
+/*20080827 to latest
+%s : %d 개
+%s: %d ea.
+*/
+ MSG_EA2 = 0xb7,
+/*20080827 to latest
+%s %s : %d 개
+%s %s: %d
+*/
+ MSG_EA3 = 0xb8,
+/*20080827 to latest
+팔 수 있는 품목
+Available Items to sell
+*/
+ MSG_ITEMSYOUCANSELL = 0xb9,
+/*20080827 to latest
+상점에서 파는 품목
+Shop Items
+*/
+ MSG_SHOPITEMS = 0xba,
+/*20080827 to latest
+알 수 없는곳
+Unknown Area
+*/
+ MSG_NOWHERE = 0xbb,
+/*20080827 to latest
+서버와 언어가 맞지 않습니다.
+Your Client language doesn't match the Server language.
+*/
+ MSG_CLIENTTYPEMISMATCH = 0xbc,
+/*20080827 to latest
+아이템을 버릴려면 장비창을 닫으세요.
+Please move your equipment to the inventory. And close the equipment window.
+*/
+ MSG_CLOSEEQUIPWND = 0xbd,
+/*20080827 to latest
+영어만 됩니다.
+This server provides English Text Characters Only.
+*/
+ MSG_ENGLISHONLY = 0xbe,
+/*20080827 to latest
+지금은 지원되지 않습니다.
+This is not implemented yet.
+*/
+ MSG_NOTSUPPORTEDYET = 0xbf,
+/*20080827 to latest
+귓말 리스트가 없습니다.
+No Whisper List.
+*/
+ MSG_NOWHISPERLIST = 0xc0,
+/*20080827 to latest
+ 에게 귓말거부상태로됨
+: Whispering Blocked.
+*/
+ MSG_WHISPERIGNORESUCCESS = 0xc1,
+/*20080827 to latest
+ 에게 귓말거부 요청실패함
+: Whispering Block has failed.
+*/
+ MSG_WHISPERIGNOREFAILED1 = 0xc2,
+/*20080827 to latest
+ 에게 귓말거부 요청실패함 (인원초과)
+: Whispering Block has failed. Block List is full.
+*/
+ MSG_WHISPERIGNOREFAILED2 = 0xc3,
+/*20080827 to latest
+ 에게 귓말가능상태로됨
+: Whispering accepted.
+*/
+ MSG_WHISPERNOIGNORESUCCESS = 0xc4,
+/*20080827 to latest
+ 에게 귓말가능 요청실패함
+: Command has failed.
+*/
+ MSG_WHISPERNOIGNOREFAILED1 = 0xc5,
+/*20080827 to latest
+ 에게 귓말가능 요청실패함 (인원초과)
+: Command has failed. Block List is full.
+*/
+ MSG_WHISPERNOIGNOREFAILED2 = 0xc6,
+/*20080827 to latest
+이름의 처음과 마지막에는 공백문자를 사용할 수 없습니다.
+You cannot put a space at the beginning or end of a name.
+*/
+ MSG_NO_SPACE_IN_NAME = 0xc7,
+/*20080827 to latest
+비공개
+Private
+*/
+ MSG_ROOM_PRIVATE2 = 0xc8,
+/*20080827 to latest
+공개
+Public
+*/
+ MSG_ROOM_PUBLIC2 = 0xc9,
+/*20080827 to latest
+SP가 부족합니다.
+Not Enough SP
+*/
+ MSG_USESKILL_FAIL_SP_INSUFFICIENT = 0xca,
+/*20080827 to latest
+HP가 부족합니다.
+Not Enough HP
+*/
+ MSG_USESKILL_FAIL_HP_INSUFFICIENT = 0xcb,
+/*20080827 to latest
+스킬사용 실패.
+Skill has failed.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE8 = 0xcc,
+/*20080827 to latest
+훔치기 실패.
+Steal has failed.
+*/
+ MSG_FAIL_STEAL = 0xcd,
+/*20080827 to latest
+교환창
+Trade
+*/
+ MSG_EXCHANGE = 0xce,
+/*20080827 to latest
+독걸기 실패.
+Envenom skill has failed.
+*/
+ MSG_FAIL_POISON = 0xcf,
+/*20080827 to latest
+이 아이디로는 이 서버에 접속할 수 없습니다.
+You cannot use this ID on this server.
+*/
+ MSG_ID_MISMATCH = 0xd0,
+/*20080827 to latest
+스피드가 향상되었습니다.
+Your Speed has increased.
+*/
+ MSG_SPEEDUP = 0xd1,
+/*20080827 to latest
+스피드가 감소되었습니다.
+Your Speed has decreased.
+*/
+ MSG_SPEEDDOWN = 0xd2,
+/*20080827 to latest
+/기억 : 워프할 장소 기억(워프 스킬이 있는경우)
+/memo: To memorize a place as Warp Point (If you are an Acolyte Class character)
+*/
+ MSG_EXPLAIN_TIP13 = 0xd3,
+/*20080827 to latest
+임의의 위치
+Random Area
+*/
+ MSG_RANDOM_POS = 0xd4,
+/*20080827 to latest
+워프 할 위치를 선택하세요.
+Select an Area to Warp
+*/
+ MSG_SELECTWHERETOWARP = 0xd5,
+/*20080827 to latest
+스킬레벨이 부족합니다.
+Skill Level is not high enough
+*/
+ MSG_NOTENOUGHSKILLLEVEL = 0xd6,
+/*20080827 to latest
+저장된 워프할 장소가 없습니다.
+There are no memorized locations (Memo Points).
+*/
+ MSG_NO_STORED_PLACE_TO_WARP = 0xd7,
+/*20080827 to latest
+워프 관련 스킬이 없습니다.
+You haven't learned Warp.
+*/
+ MSG_NOWARPSKILL = 0xd8,
+/*20080827 to latest
+워프 장소로 저장됨.
+Saved location as a Memo Point for Warp Skill.
+*/
+ MSG_WARPPOINTSTORED = 0xd9,
+/*20080827 to latest
+취소
+Cancel
+*/
+ MSG_CANCEL = 0xda,
+/*20080827 to latest
+스킬 사용후 시간이 충분히 지나지 않았습니다.
+There is a Delay after using a Skill.
+*/
+ MSG_SKILLINTERVAL = 0xdb,
+/*20080827 to latest
+한번에 가질 수 있는 아이템 종류수를 초과하여 아이템을 가질 수 없습니다.
+You can't have this item because you will exceed the weight limit.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_COUNT = 0xdc,
+/*20080827 to latest
+아이템 최대 종류수를 초과 하였습니다.
+Out of the maximum capacity
+*/
+ MSG_INSUFFICIENT_OVER_COUNT = 0xdd,
+/*20080827 to latest
+수레아이템
+Cart Items
+*/
+ MSG_MERCHANTITEM = 0xde,
+/*20080827 to latest
+수레 벗기
+Take off Cart
+*/
+ MSG_CARTOFF = 0xdf,
+/*20080827 to latest
+노점 개설
+Opening a stall
+*/
+ MSG_MERCHANTSHOPMAKER = 0xe0,
+/*20080827 to latest
+노점이름을 입력하세요.
+Please Name your Shop.
+*/
+ MSG_ENTER_SHOP_TITLE = 0xe1,
+/*20080827 to latest
+나의 노점
+My Shop
+*/
+ MSG_ITEM_MY_STORE = 0xe2,
+/*20080827 to latest
+상인 아이템 상점
+Merchant Shop
+*/
+ MSG_ITEM_MERCHANT_STORE = 0xe3,
+/*20080827 to latest
+상인에게 사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY_FROM_MERCHANT = 0xe4,
+/*20080827 to 20130508
+%s 사기 실패 %s
+20130515 to latest
+%s 구입 실패 %s
+%s Purchase Failed %s
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT = 0xe5,
+/*20080827 to latest
+재고 부족.
+Out of Stock
+*/
+ MSG_INSUFFICIENT_STOCK = 0xe6,
+/*20080827 to latest
+%s %d 개 팔림.
+%s %d sold.
+*/
+ MSG_ITEM_IS_SOLD = 0xe7,
+/*20080827 to latest
+노점에서 팔 수 있는 아이템
+Available Items for Vending
+*/
+ MSG_MERCHANTMIRRORITEM = 0xe8,
+/*20080827 to 20111012
+돈이 부족해서 스킬을 쓸 수 없습니다.
+20111017 to latest
+제니가 부족해서 스킬을 사용 할 수 없습니다.
+Skill has failed because you do not have enough zeny.
+*/
+ MSG_SKILL_FAIL_MONEY = 0xe9,
+/*20080827 to latest
+사용할 대상을 선택하세요
+Select a Target.
+*/
+ MSG_SELECTTARGET = 0xea,
+/*20080827 to latest
+/pk on : pk On /pk off : pk Off
+/pk on: Turns PK On. /pk off: Turns PK Off.
+*/
+ MSG_EXPLAIN_TIP14 = 0xeb,
+/*20080827 to latest
+노점
+Shop
+*/
+ MSG_STREETSHOP = 0xec,
+/*20080827 to latest
+수레 아이템 [Alt+W]
+Cart Items [Alt+W]
+*/
+ MSG_OPENCARTWINDOW = 0xed,
+/*20080827 to latest
+기본정보
+Basic Information
+*/
+ MSG_BASICINFOWND = 0xee,
+/*20080827 to 20191204
+이무기로는 이스킬을 사용할수 없습니다.
+The skill cannot be used with this weapon.
+20191211 to latest
+현재 무기로는 스킬을 사용할 수 없습니다.
+*/
+ MSG_USESKILL_FAIL_NOT_SUITABLE_WEAPON = 0xef,
+/*20080827 to latest
+%s 사기 실패 재고 부족 현재 재고 %d 개.
+Buying %s has been failed. Out of Stock. Current Stock %d.
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT_NO_STOCK = 0xf0,
+/*20080827 to latest
+서버와 동기화가 틀려 연결이 끊어졌습니다.
+You've been disconnected due to a time gap between you and the server.
+*/
+ MSG_SPEEDHACK = 0xf1,
+/*20080827 to latest
+화살을 장착하세요
+Please equip the proper ammunition first.
+*/
+ MSG_ERR_ATTACK_ARROW = 0xf2,
+/*20080827 to latest
+중량과다로 공격이나 스킬을 사용할 수 없습니다.
+You can't attack or use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_ATTACK_WEIGHT = 0xf3,
+/*20080827 to latest
+중량과다로 스킬을 사용할 수 없습니다.
+You can't use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_SKILL_WEIGHT = 0xf4,
+/*20080827 to latest
+화살이 장착되었습니다.
+Ammunition has been equipped.
+*/
+ MSG_MSG_ARROW_EQUIPMENT_SUCCESS = 0xf5,
+/*20080827 to latest
+레드젬스톤이 필요합니다.
+Red Gemstone required.
+*/
+ MSG_NEED_REDJAMSTONE = 0xf6,
+/*20080827 to latest
+블루젬스톤이 필요합니다.
+Blue Gemstone required.
+*/
+ MSG_NEED_BLUEJAMSTONE = 0xf7,
+/*20080827 to latest
+힘 파라메터
+Strength
+*/
+ MSG_DESC_STR = 0xf8,
+/*20080827 to latest
+민첩성 파라메터
+Agility
+*/
+ MSG_DESC_AGI = 0xf9,
+/*20080827 to latest
+체력 파라메터
+Vitality
+*/
+ MSG_DESC_VIT = 0xfa,
+/*20080827 to latest
+지력 파라메터
+Intelligence
+*/
+ MSG_DESC_INT = 0xfb,
+/*20080827 to latest
+손재주 파라메터
+Dexterity
+*/
+ MSG_DESC_DEX = 0xfc,
+/*20080827 to latest
+운 파라메터
+Luck
+*/
+ MSG_DESC_LUK = 0xfd,
+/*20080827 to latest
+공격력
+Hit Point
+*/
+ MSG_DESC_ATK = 0xfe,
+/*20080827 to latest
+방어력
+Defence Rate
+*/
+ MSG_DESC_DEF = 0xff,
+/*20080827 to latest
+명중률
+Accuracy
+*/
+ MSG_DESC_HIT = 0x100,
+/*20080827 to latest
+필살공격률
+Critical Attack
+*/
+ MSG_DESC_CRI = 0x101,
+/*20080827 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_DESC_GUILD = 0x102,
+/*20080827 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_DESC_POINT = 0x103,
+/*20080827 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_DESC_MATK = 0x104,
+/*20080827 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_DESC_MDEF = 0x105,
+/*20080827 to latest
+회피율
+Dodge
+*/
+ MSG_DESC_FLEE = 0x106,
+/*20080827 to latest
+공격스피드
+Attack Speed
+*/
+ MSG_DESC_ASPD = 0x107,
+/*20080827 to latest
+지역당 수용인원 초과로 접속할 수 없습니다.
+Server is jammed due to over population. Please try again shortly.
+*/
+ MSG_PC_OVERFLOW = 0x108,
+/*20080827 to latest
+옵션
+Option
+*/
+ MSG_OPTIONWND = 0x109,
+/*20080827 to latest
+E-MAIL 인증이 되지않았거나 블럭된 계정입니다.
+Account ID blocked by the Game Master Team.
+*/
+ MSG_ID_EMAIL_CONFIRM_NEEDED = 0x10a,
+/*20080827 to latest
+비밀번호가 틀립니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_LOGIN_PASSWORD = 0x10b,
+/*20080827 to latest
+머리모양 선택
+Choose Hairstyle
+*/
+ MSG_SELECT_HAIR_STYLE = 0x10c,
+/*20080827 to latest
+공격력
+Hit Point
+*/
+ MSG_ATK = 0x10d,
+/*20080827 to latest
+방어력
+Defence Rate
+*/
+ MSG_DEF = 0x10e,
+/*20080827 to latest
+공격스냅 On
+Attack Snap On
+*/
+ MSG_ATTACK_SNAP_ON = 0x10f,
+/*20080827 to latest
+공격스냅 Off
+Attack Snap Off
+*/
+ MSG_ATTACK_SNAP_OFF = 0x110,
+/*20080827 to latest
+스킬스냅 On
+Skill Snap On
+*/
+ MSG_SKILL_SNAP_ON = 0x111,
+/*20080827 to latest
+스킬스냅 Off
+Skill Snap Off
+*/
+ MSG_SKILL_SNAP_OFF = 0x112,
+/*20080827 to latest
+/스냅 or /snap: 몬스터 공격시 스냅 On Off /스킬스냅 or /skillsnap: 스킬로 몬스터 공격시 스냅 On Off /아이템스냅 or /itemsnap: 아이템 주울때 스냅 On Off
+/snap: Turns snap On | Off for fights, /skillsnap: Turns snap On | Off for skills. /itemsnap: Turns snap On | Off for items on the grounds.
+*/
+ MSG_EXPLAIN_SNAP = 0x113,
+/*20080827 to latest
+아이템스냅 On
+Item Snap On
+*/
+ MSG_ITEM_SNAP_ON = 0x114,
+/*20080827 to latest
+아이템스냅 Off
+Item Snap Off
+*/
+ MSG_ITEM_SNAP_OFF = 0x115,
+/*20080827 to latest
+스냅
+Snap
+*/
+ MSG_SNAP = 0x116,
+/*20080827 to latest
+한가지 아이템을 3만개 이상 가질수 없습니다.
+You cannot carry more than 30,000 of one kind of item.
+*/
+ MSG_CANT_GET_ITEM_OVERCOUNT_ONEITEM = 0x117,
+/*20080827 to latest
+레벨 30이상의 캐릭터는 삭제할 수 없습니다. 삭제를 원하시면 관계자에게 문의 하세요.
+You cannot delete a Character with a level greater than 30. If you want to delete the character please contact a Game Master.
+*/
+ MSG_CANT_DELETE_CHARACTER_OVER_30_LEVEL = 0x118,
+/*20080827 to 20091208
+이이템 교환중에는 아이템을 사고 팔 수 없습니다.
+20091215 to latest
+아이템 교환중에는 아이템을 사고 팔 수 없습니다.
+You cannot use an NPC shop while in a trade.
+*/
+ MSG_FAIL_BUY_ITEM_ITEM_EXCHANGING = 0x119,
+/*20080827 to latest
+상점명
+Shop Name
+*/
+ MSG_STALL_NAME = 0x11a,
+/*20080827 to latest
+스킬목록
+Skill Tree
+*/
+ MSG_SKILLLIST = 0x11b,
+/*20080827 to latest
+스킬포인트 : %d
+Skill Point: %d
+*/
+ MSG_SKILLPOINT = 0x11c,
+/*20080827 to latest
+스킬사용 실패
+Skill has failed.
+*/
+ MSG_USESKILL_FAIL = 0x11d,
+/*20080827 to latest
+패시브
+Passive
+*/
+ MSG_PASSIVE = 0x11e,
+/*20080827 to latest
+각자 취득
+Individual
+*/
+ MSG_EXPDIV1 = 0x11f,
+/*20080827 to latest
+균등하게 분배
+Shared
+*/
+ MSG_EXPDIV2 = 0x120,
+/*20080827 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMCOLLECT1 = 0x121,
+/*20080827 to latest
+파티 전체 공유
+Party Share
+*/
+ MSG_ITEMCOLLECT2 = 0x122,
+/*20080827 to latest
+파티 설정
+Party Setup
+*/
+ MSG_PARTYSETTING = 0x123,
+/*20080827 to latest
+경험치 분배방식
+How to share EXP
+*/
+ MSG_HOWEXPDIV = 0x124,
+/*20080827 to latest
+아이템 수집방식
+How to share Items
+*/
+ MSG_HOWITEMCOLLECT = 0x125,
+/*20080827 to latest
+파티 리더만 설정할 수 있습니다.
+Only the Party Leader can change this setting.
+*/
+ MSG_ONLY_PARTYMASTER = 0x126,
+/*20080827 to latest
+아이템 갯수 안물어보기
+Toggle Item Amount.
+*/
+ MSG_NOQUESTION_ITEMCOUNT = 0x127,
+/*20080827 to latest
+^ff0000%d^000000 초 후에 캐릭터가 지워집니다. 취소 하려면 취소 버튼을 누르세요.
+Character will be deleted after ^ff0000%d^000000 seconds. Press Cancel to quit.
+*/
+ MSG_CHARARATER_DELETE_COUNT = 0x128,
+/*20080827 to latest
+교환할 수 있는 최대 아이템 갯수는 10가지 입니다.
+You cannot trade more than 10 types of items per trade.
+*/
+ MSG_MAXEXCHANGE_IS_10_KIND = 0x129,
+/*20080827 to latest
+이서버를 이용할 수 없는 나이입니다.
+You are underaged.
+*/
+ MSG_LIMIT_AGE = 0x12a,
+/*20080827 to latest
+이메일 주소를 입력하세요.
+Please enter the deletion password.
+*/
+ MSG_ENTER_EMAIL = 0x12b,
+/*20080827 to latest
+이메일 주소 입력하기
+E-mail Address (Case Sensitive).
+*/
+ MSG_ENTER_EMAIL_TOOLTIP = 0x12c,
+/*20080827 to latest
+이메일 주소가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect e-mail address.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_EMAIL = 0x12d,
+/*20080827 to latest
+계정 비밀번호를 입력하세요.
+Enter Second Serial Cord of your Social Security number.
+*/
+ MSG_ENTER_PEOPLE_REG_NUMBER = 0x12e,
+/*20080827 to latest
+비밀번호가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect SSN.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_PEOPLE_REG_NUMBER = 0x12f,
+/*20080827 to latest
+한번에 15가지 이상의 아이템을 팔 수 없습니다.
+You can't sell more than 15 types of Items at one time.
+*/
+ MSG_CANT_SELL_OVER_15 = 0x130,
+/*20080827 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_UNDER_AGE = 0x131,
+/*20080827 to latest
+무게가 50 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+HP/SP will not be restored when your carried weight is over 50% of the Weight Limit.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT = 0x132,
+/*20080827 to latest
+무게가 90 퍼센트 이상일때는 공격과 스킬을 사용할 수 없습니다.
+You can't use Skills or Attack while your carried weight is over 90% of your Weight Limit.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT = 0x133,
+/*20080827 to latest
+HP SP가 자연적으로 회복이 가능한 상태가 되었습니다.
+Your HP/SP are now being restored naturally.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT_RELEASED = 0x134,
+/*20080827 to latest
+공격과 스킬이 가능한 상태가 되었습니다.
+Attack and Skills are now available.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT_RELEASED = 0x135,
+/*20080827 to latest
+서버 점검중입니다.
+Your Game's Exe File is not the latest version.
+*/
+ MSG_INVALID_VERSION = 0x136,
+/*20080827 to latest
+아이템이 모두 팔렸습니다.
+Items are sold out.
+*/
+ MSG_ITEM_IS_SOLD_OUT = 0x137,
+/*20080827 to latest
+채팅내용 파일로 저장하기
+Save Chat as Text File
+*/
+ MSG_WRITE_CHAT_TO_FILE = 0x138,
+/*20080827 to latest
+/갈무리 or /savechat : 채팅 내용 파일로 저장하기.
+/savechat: Save a Chat Log
+*/
+ MSG_EXPLAIN_SAVE_CHAT = 0x139,
+/*20080827 to latest
+계정 만들기
+Register
+*/
+ MSG_MAKEACCOUNT = 0x13a,
+/*20080827 to latest
+수신거부하기
+Reject Whispering
+*/
+ MSG_REQ_EX_LIST = 0x13b,
+/*20080827 to latest
+수신거부해제하기
+Allow Whispering
+*/
+ MSG_REQ_IN = 0x13c,
+/*20080827 to latest
+미스표시 On
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_ON = 0x13d,
+/*20080827 to latest
+미스표시 Off
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_OFF = 0x13e,
+/*20080827 to latest
+카메라고정 On
+Camera Zooming On
+*/
+ MSG_FIXED_CAMERA_ON = 0x13f,
+/*20080827 to latest
+카메라고정 Off
+Camera Zooming Off
+*/
+ MSG_FIXED_CAMERA_OFF = 0x140,
+/*20080827 to latest
+/camera : 플레이어에게 카메라고정 On Off /miss : 미스이펙트 On Off
+/camera: Camera Zooming On or Off. /miss: Toggle ''Miss'' display
+*/
+ MSG_EXPLAIN_CAMERA_MISS = 0x141,
+/*20080827 to latest
+스킬정보보기
+View Skill Info
+*/
+ MSG_SEE_INFORMATION_OF_SKILL = 0x142,
+/*20080827 to latest
+스킬이름바꾸기
+Change Skill
+*/
+ MSG_CHANGE_SKILL_NAME = 0x143,
+/*20080827 to latest
+스프라이트 해상도
+Sprite Resolution
+*/
+ MSG_SPRITE_RESOLUTION = 0x144,
+/*20080827 to latest
+텍스쳐 해상도
+Texture Resolution
+*/
+ MSG_TEXTURE_RESOLUTION = 0x145,
+/*20080827 to latest
+디테일 조정
+Arrange Detail
+*/
+ MSG_DETAILLEVELWND = 0x146,
+/*20080827 to latest
+%s Zeny 획득
+You got %s Zeny
+*/
+ MSG_GET_ZENY = 0x147,
+/*20080827 to latest
+길드명
+Guild Name
+*/
+ MSG_GUILDNAME = 0x148,
+/*20080827 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILDLEVEL = 0x149,
+/*20080827 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_GUILD_MASTER_NAME = 0x14a,
+/*20080827 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_NUM_MEMBER = 0x14b,
+/*20080827 to latest
+조합원 평균레벨
+Avg.lvl of Guildsmen
+*/
+ MSG_GUILD_AVG_MEMBER_LEVEL = 0x14c,
+/*20080827 to latest
+관리영지
+Castles Owned
+*/
+ MSG_GUILD_MANAGE_LAND = 0x14d,
+/*20080827 to latest
+성향
+Tendency
+*/
+ MSG_GUILD_FAIR = 0x14e,
+/*20080827 to latest
+경험치
+EXP
+*/
+ MSG_GUILD_EXP = 0x14f,
+/*20080827 to latest
+길드엠블렘
+Emblem
+*/
+ MSG_GUILD_EMBLEM = 0x150,
+/*20080827 to latest
+길드상납포인트
+Tax Point
+*/
+ MSG_GUILD_POINT = 0x151,
+/*20080827 to latest
+동맹길드
+Alliances
+*/
+ MSG_ALLY_GUILD = 0x152,
+/*20080827 to latest
+적대길드
+Antagonists
+*/
+ MSG_HOSTILITY_GUILD = 0x153,
+/*20080827 to latest
+길드정보
+Guild Info
+*/
+ MSG_GUILDINFOMANAGE = 0x154,
+/*20080827 to latest
+조합원정보
+Guildsmen Info
+*/
+ MSG_GUILDMEMBERMANAGE = 0x155,
+/*20080827 to latest
+직위설정
+Position
+*/
+ MSG_GUILDPOSITIONMANAGE = 0x156,
+/*20080827 to latest
+길드스킬
+Guild Skill
+*/
+ MSG_GUILDSKILL = 0x157,
+/*20080827 to latest
+추방자 리스트
+Expel History
+*/
+ MSG_GUILDBANISHEDMEMBER = 0x158,
+/*20080827 to latest
+공지사항
+Guild Notice
+*/
+ MSG_GUILDNOTICE = 0x159,
+/*20080827 to latest
+전체길드 리스트
+Entire Guild List
+*/
+ MSG_GUILDTOTALINFO = 0x15a,
+/*20080827 to latest
+귓말 리스트
+Whispering List
+*/
+ MSG_WHISPERLISTWND = 0x15b,
+/*20080827 to latest
+귓말창 열기
+Open Whispering Window
+*/
+ MSG_OPENWHISPERLISTWND = 0x15c,
+/*20080827 to latest
+귓말 리스트 창 여는법 : [Alt] + [H] 를 누르면 귓말 리스트 창이 열립니다.
+How to Open Whispering List: Press [Alt] + [H]
+*/
+ MSG_EXPLAIN_WHISPER_LIST_WND = 0x15d,
+/*20080827 to latest
+자동으로 귓말창 열기
+Open Whispering List Automatically
+*/
+ MSG_AUTOOPENWHISPERLISTWND = 0x15e,
+/*20080827 to latest
+지우기
+Delete
+*/
+ MSG_DELETE = 0x15f,
+/*20080827 to latest
+다음부터 열리지 않음
+Close since next
+*/
+ MSG_DONTOPEN = 0x160,
+/*20080827 to latest
+마지막으로 접속한 시간
+Last Log-in Time
+*/
+ MSG_LAST_LOGIN_TIME = 0x161,
+/*20080827 to latest
+마지막으로 접속한 IP
+Last Log-in IP
+*/
+ MSG_LAST_LOGIN_IP = 0x162,
+/*20080827 to latest
+친구 설정
+Friend Setup
+*/
+ MSG_FRIEND_SETTING = 0x163,
+/*20080827 to latest
+정말 지우시겠습니까?
+Are you sure that you want to delete?
+*/
+ MSG_DO_YOU_REALLY_WANT_DELETE = 0x164,
+/*20080827 to latest
+정말 탈퇴하시겠습니까?
+Are you sure that you want to leave?
+*/
+ MSG_DO_YOU_REALLY_WANT_LEAVE = 0x165,
+/*20080827 to latest
+친구로 등록하기
+Register as a Friend
+*/
+ MSG_ADD_TO_FRIEND_CHAR_LIST = 0x166,
+/*20080827 to latest
+친구일때 자동으로 1:1창 열기
+Open 1:1 Chat between Friends
+*/
+ MSG_AUTOOPENWHISPERLISTWND_FRIEND = 0x167,
+/*20080827 to latest
+1:1창 열기
+Open 1:1 Chat
+*/
+ MSG_OPEN_1ON1_WINDOW = 0x168,
+/*20080827 to latest
+친구가 아닐때 자동으로 1:1창 열기
+Open 1:1 Chat between Strangers
+*/
+ MSG_AUTOOPEN_1ON1_WINDOW = 0x169,
+/*20080827 to latest
+1:1창 열릴때 소리로 알림
+Alarm when you recieve a 1:1 Chat
+*/
+ MSG_WHISPER_OPEN_SOUND = 0x16a,
+/*20080827 to latest
+정말 제명시키시겠습니까?
+Are you sure that you want to expel?
+*/
+ MSG_DO_YOU_REALLY_WANT_EXPEL = 0x16b,
+/*20080827 to latest
+%s 님이 길드를 탈퇴했습니다.
+%s has withdrawn from the guild.
+*/
+ MSG_USER_LEFT_GUILD = 0x16c,
+/*20080827 to latest
+탈퇴사유 : %s
+Secession Reason: %s
+*/
+ MSG_REASON_LEAVE_GUILD = 0x16d,
+/*20080827 to 20120202
+길드 해체 실패
+20120207 to latest
+길드명이 일치하지 않습니다
+You have failed to disband the guild.
+*/
+ MSG_DISORGANIZE_GUILD_FAILURE = 0x16e,
+/*20080827 to latest
+길드해체사유 : %s
+Disband Reason: %s
+*/
+ MSG_DISORGANIZATION_REASON = 0x16f,
+/*20080827 to latest
+해당 계정은 삭제된 아이디 입니다.
+This ID has been removed.
+*/
+ MSG_DELETED_ACCOUNT = 0x170,
+/*20080827 to latest
+판매가 :
+Price:
+*/
+ MSG_SELLPRICE = 0x171,
+/*20080827 to latest
+%s 님이 길드에서 추방되었습니다.
+%s has been expelled from our guild.
+*/
+ MSG_BAN_GUILD = 0x172,
+/*20080827 to latest
+추방사유 : %s
+Expulsion Reason: %s
+*/
+ MSG_REASON_BAN_GUILD = 0x173,
+/*20080827 to latest
+아이템을 착용할 수 없습니다.
+You can't put this item on.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM = 0x174,
+/*20080827 to latest
+파티설정을 변경할 수 없습니다.
+You can't modify Party Setup.
+*/
+ MSG_PARTYSETTING_CHANGE_IMPOSSIBLE = 0x175,
+/*20080827 to latest
+길드가 만들어 졌습니다.
+Guild has been Created.
+*/
+ MSG_GUILD_MAKE_SUCCESS = 0x176,
+/*20080827 to latest
+이미 길드에 속해있습니다.
+You are already in a Guild.
+*/
+ MSG_GUILD_MAKE_ALREADY_MEMBER = 0x177,
+/*20080827 to latest
+같은이름의 길드가 존재합니다.
+That Guild Name already exists.
+*/
+ MSG_GUILD_MAKE_GUILD_EXIST = 0x178,
+/*20080827 to latest
+ 길드에서 초청 메시지가 왔습니다. 가입하겠습니까?
+ Guild has sent you an invitation. Would you like to join this Guild?
+*/
+ MSG_SUGGEST_JOIN_GUILD = 0x179,
+/*20080827 to latest
+다른길드에 가입되어 있습니다.
+He/She is already in a Guild.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_GUILD = 0x17a,
+/*20080827 to latest
+길드가입을 거절 했습니다.
+Offer Rejected
+*/
+ MSG_CHARACTER_REJECT_JOIN_GUILD = 0x17b,
+/*20080827 to latest
+길드가입을 수락했습니다.
+Offer Accepted
+*/
+ MSG_CHARACTER_ACCEPT_JOIN_GUILD = 0x17c,
+/*20080827 to latest
+길드정원을 초과했습니다.
+Your Guild is Full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_GUILD = 0x17d,
+/*20080827 to latest
+(%s)님 길드에 가입요청
+Send (%s) a Guild invitation
+*/
+ MSG_REQ_JOIN_GUILD = 0x17e,
+/*20080827 to latest
+스킬 레벨이 모자라서 매너포인트를 줄 수 없습니다.
+You haven't learned enough skills for aligning.
+*/
+ MSG_NOT_ENOUGH_FOR_MANNER_POINT = 0x17f,
+/*20080827 to latest
+매너 포인트 주기 성공
+Aligning completed.
+*/
+ MSG_GIVING_MANNER_POINT_SUCCESS = 0x180,
+/*20080827 to latest
+오늘 이미 사용했습니다.
+You already spent your point for today.
+*/
+ MSG_YOU_USE_TODAY_ALREADY = 0x181,
+/*20080827 to latest
+이캐릭터에게 지급한지 한달이 지나지 않았습니다.
+Hasn't been a month yet since you aligned this person.
+*/
+ MSG_ONE_MONTH_NOT_PASSED = 0x182,
+/*20080827 to latest
+%s 님으로부터 플러스 매너 포인트를 받았습니다.
+Remember, Spamming isn't nice.
+*/
+ MSG_RECEIVE_PLUS_MANNER_POINT = 0x183,
+/*20080827 to latest
+%s 님으로부터 마이너스 매너 포인트를 받았습니다.
+Please refrain from ill-mannered conduct, thank you.
+*/
+ MSG_RECEIVE_MINUS_MANNER_POINT = 0x184,
+/*20080827 to latest
+채팅 금지 시간 줄이기(풀기)
+Align with a Good Point
+*/
+ MSG_GIVE_PLUS_MANNER_POINT = 0x185,
+/*20080827 to latest
+채팅 금지 시간 늘이기(걸기)
+Align with a Bad Point
+*/
+ MSG_GIVE_MINUS_MANNER_POINT = 0x186,
+/*20080827 to latest
+(%s)님과의 거래요청
+Request a deal with (%s)
+*/
+ MSG_REQ_DEAL_WITH2 = 0x187,
+/*20080827 to latest
+(%s)님 파티에 가입요청
+Ask (%s) to join your party
+*/
+ MSG_REQ_JOIN_PARTY2 = 0x188,
+/*20080827 to latest
+ 길드에서 동맹요청 메시지가 왔습니다. 동맹하겠습니까?
+ Guild is asking you to agree to an Alliance with them. Do you accept?
+*/
+ MSG_SUGGEST_ALLY_GUILD = 0x189,
+/*20080827 to latest
+이미 동맹되어 있습니다.
+This Guild is already your Ally.
+*/
+ MSG_REQALLYGUILD_ALREADY_ALLIED = 0x18a,
+/*20080827 to latest
+동맹을 거절 했습니다.
+You reject the offer
+*/
+ MSG_REQALLYGUILD_REJECT = 0x18b,
+/*20080827 to latest
+동맹을 수락 했습니다.
+You accept the offer
+*/
+ MSG_REQALLYGUILD_ACCEPT = 0x18c,
+/*20080827 to latest
+상대길드의 동맹길드의 수가 초과 되었습니다.
+They have too many Alliances.
+*/
+ MSG_REQALLYGUILD_OVERSIZE = 0x18d,
+/*20080827 to latest
+길드의 동맹길드의 수가 초과 되었습니다.
+You have too many Alliances.
+*/
+ MSG_REQALLYMYGUILD_OVERSIZE = 0x18e,
+/*20080827 to latest
+길드 동맹 요청
+Set this guild as an Alliance
+*/
+ MSG_REQ_ALLY_GUILD = 0x18f,
+/*20080827 to latest
+길드가 성공적으로 해체 되었습니다.
+Guild was successfully disbanded.
+*/
+ MSG_DISORGANIZE_GUILD_SUCCESS = 0x190,
+/*20080827 to latest
+주민등록번호가 틀려서 길드가 해체되지 않았습니다.
+You have failed to disband the guild due to your incorrect SSN.
+*/
+ MSG_DISORGANIZE_GUILD_INVALIDKEY = 0x191,
+/*20080827 to latest
+길드맴버가 존재해서 길드가 해체되지 않았습니다.
+You have failed to disband the guild because there are guildsmen still present.
+*/
+ MSG_DISORGANIZE_GUILD_MEMBEREXIST = 0x192,
+/*20080827 to latest
+길드 적대 요청
+Set this guild as an Antagonist
+*/
+ MSG_REQ_HOSTILE_GUILD = 0x193,
+/*20080827 to latest
+머리색깔 선택
+Choose Hair Color
+*/
+ MSG_SELECT_HAIR_COLOR = 0x194,
+/*20080827 to latest
+길드결성시 필요한 아이템이 없습니다.
+You don't have necessary item to create a Guild.
+*/
+ MSG_GUILD_MAKE_GUILD_NONE_ITEM = 0x195,
+/*20080827 to latest
+몬스터 정보
+Monster Info
+*/
+ MSG_MONSTER_INFO_WINDOW = 0x196,
+/*20080827 to latest
+이름
+Name
+*/
+ MSG_NAME = 0x197,
+/*20080827 to latest
+레벨
+Level
+*/
+ MSG_LEVEL = 0x198,
+/*20080827 to latest
+HP
+*/
+ MSG_HP = 0x199,
+/*20080827 to latest
+크기
+Size
+*/
+ MSG_SIZE = 0x19a,
+/*20080827 to latest
+종족
+Type
+*/
+ MSG_RACETYPE = 0x19b,
+/*20080827 to latest
+MDEF
+*/
+ MSG_MDEFPOWER = 0x19c,
+/*20080827 to latest
+속성
+Attribute
+*/
+ MSG_PROPERTY = 0x19d,
+/*20080827 to latest
+無
+Neutral
+*/
+ MSG_PROPERTY_NEUTURAL = 0x19e,
+/*20080827 to latest
+水
+Water
+*/
+ MSG_PROPERTY_WATER = 0x19f,
+/*20080827 to latest
+地
+Earth
+*/
+ MSG_PROPERTY_EARTH = 0x1a0,
+/*20080827 to latest
+火
+Fire
+*/
+ MSG_PROPERTY_FIRE = 0x1a1,
+/*20080827 to latest
+風
+Wind
+*/
+ MSG_PROPERTY_WIND = 0x1a2,
+/*20080827 to latest
+毒
+Poison
+*/
+ MSG_PROPERTY_POISON = 0x1a3,
+/*20080827 to latest
+聖
+Holy
+*/
+ MSG_PROPERTY_SAINT = 0x1a4,
+/*20080827 to latest
+暗
+Shadow
+*/
+ MSG_PROPERTY_DARK = 0x1a5,
+/*20080827 to latest
+念
+Ghost
+*/
+ MSG_PROPERTY_MENTAL = 0x1a6,
+/*20080827 to latest
+死
+Undead
+*/
+ MSG_PROPERTY_UNDEAD = 0x1a7,
+/*20080827 to latest
+현재는 아이템을 만들 수 없습니다.
+You can't create items yet.
+*/
+ MSG_CANT_MAKE_ITEM = 0x1a8,
+/*20080827 to latest
+제조 목록
+Item List you can craft
+*/
+ MSG_MAKE_LIST = 0x1a9,
+/*20080827 to latest
+ 만들기
+ Create
+*/
+ MSG_MAKE_TARGET = 0x1aa,
+/*20080827 to latest
+ 에 필요한 재료:
+'s materials
+*/
+ MSG_REQUIRE_FOR_MAKE_TARGET = 0x1ab,
+/*20080827 to latest
+ 만들기 실패
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL = 0x1ac,
+/*20080827 to latest
+ 만들기 성공
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS = 0x1ad,
+/*20080827 to latest
+%s 만들기를 실패하였습니다.
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL_MSG = 0x1ae,
+/*20080827 to latest
+%s 만들기를 성공했습니다.
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS_MSG = 0x1af,
+/*20080827 to latest
+레벨이 부족합니다.
+You are not the required lvl.
+*/
+ MSG_NOT_ENOUGH_LEVEL = 0x1b0,
+/*20080827 to latest
+레벨이 너무 높습니다.
+Too high lvl for this job.
+*/
+ MSG_TOO_HIGH_LEVEL = 0x1b1,
+/*20080827 to latest
+직업이 적합하지 않습니다.
+Not the suitable job for this type of work.
+*/
+ MSG_NOT_ACCEPTABLE_JOB = 0x1b2,
+/*20080827 to latest
+토키 박스 트랩 메세지
+Record a message in the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW = 0x1b3,
+/*20080827 to latest
+기록할 메세지를 입력하시기 바랍니다.
+Please type a message for the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW_MSG = 0x1b4,
+/*20080827 to latest
+길드에게 보냄
+Send to Guild
+*/
+ MSG_SEND_TO_GUILD = 0x1b5,
+/*20080827 to latest
+결제된 계정이 아닙니다. 결제 페이지로 이동하시겠습니까?
+You didn't pay for this ID. Would you like to pay for it now?
+*/
+ MSG_NOT_SETTLED = 0x1b6,
+/*20080827 to latest
+서버가 혼잡한 관계로 잠시후 다시 시도해 주시기 바랍니다.
+Server is jammed due to overpopulation. Please try again after few minutes.
+*/
+ MSG_ACCOUNT_BUSY = 0x1b7,
+/*20080827 to latest
+지난 접속 정보가 남아 있습니다. 30초정도 지난뒤에 다시 시도해 주시기 바랍니다.
+Server still recognizes your last log-in. Please try again after a few minutes.
+*/
+ MSG_INFORMATION_REMAINED = 0x1b8,
+/*20080827 to latest
+매 풀어주기
+Release Falcon
+*/
+ MSG_BIRDOFF = 0x1b9,
+/*20080827 to latest
+페코페코 내리기
+Dismount
+*/
+ MSG_CHIKENOFF = 0x1ba,
+/*20080827 to latest
+小
+Small
+*/
+ MSG_SIZE_SMALL = 0x1bb,
+/*20080827 to latest
+中
+Med
+*/
+ MSG_SIZE_MIDDLE = 0x1bc,
+/*20080827 to latest
+大
+Big
+*/
+ MSG_SIZE_BIG = 0x1bd,
+/*20080827 to latest
+더블
+Double
+*/
+ MSG_DOUBLE = 0x1be,
+/*20080827 to latest
+트리플
+Triple
+*/
+ MSG_TRIPLE = 0x1bf,
+/*20080827 to latest
+쿼드로플
+Quadruple
+*/
+ MSG_QUADROPLE = 0x1c0,
+/*20080827 to latest
+%s 까지 로그인을 금지하고 있습니다.
+You are prohibited to log in until %s.
+*/
+ MSG_LOGIN_REFUSE_BLOCKED_UNTIL = 0x1c1,
+/*20080827 to latest
+의
+'s
+*/
+ MSG_MANUFACTURED_NORMAL_ITEM = 0x1c2,
+/*20080827 to latest
+의 파이어
+'s Fire
+*/
+ MSG_MANUFACTURED_FIRE_ITEM = 0x1c3,
+/*20080827 to latest
+의 아이스
+'s Ice
+*/
+ MSG_MANUFACTURED_ICE_ITEM = 0x1c4,
+/*20080827 to latest
+의 윈드
+'s Wind
+*/
+ MSG_MANUFACTURED_WIND_ITEM = 0x1c5,
+/*20080827 to latest
+의 어스
+'s Earth
+*/
+ MSG_MANUFACTURED_EARTH_ITEM = 0x1c6,
+/*20080827 to latest
+211.239.161.246
+38.144.194.2
+*/
+ MSG_ACCOUNT_ADDRESS = 0x1c7,
+/*20080827 to latest
+6900
+*/
+ MSG_ACCOUNT_PORT = 0x1c8,
+/*20080827 to 20171206
+http://www.ragnarok.co.kr
+20171213 to latest
+http://roz.gnjoy.com/
+http://www.ragnarok.co.kr
+*/
+ MSG_REGISTRATION_WEB_URL = 0x1c9,
+/*20080827 to latest
+%s 사용자 강제 종료
+Kill %s
+*/
+ MSG_BAN_USER = 0x1ca,
+/*20080827 to latest
+무지쎈
+Very Strong
+*/
+ MSG_ONE_STARPIECE = 0x1cb,
+/*20080827 to latest
+무지무지쎈
+Very Very Strong
+*/
+ MSG_TWO_STARPIECE = 0x1cc,
+/*20080827 to latest
+무무무쎈
+Very Very Very Strong
+*/
+ MSG_THREE_STARPIECE = 0x1cd,
+/*20080827 to latest
+길드 추방 사유
+The Reason of Expulsion
+*/
+ MSG_GUILD_KICK_REASON = 0x1ce,
+/*20080827 to latest
+ 공격 속도가 증가했습니다.
+Attack Speed is up.
+*/
+ MSG_INCATTACKSPEED = 0x1cf,
+/*20080827 to latest
+ 공격 속도가 감소했습니다.
+Attack Speed is down.
+*/
+ MSG_DECATTACKSPEED = 0x1d0,
+/*20080827 to latest
+ 무기의 공격력이 향상되었습니다.
+Weapon Damage is improved.
+*/
+ MSG_INCWEAPONATTACK = 0x1d1,
+/*20080827 to latest
+ 무기의 공격력이 감소되었습니다.
+Weapon Damage is reduced.
+*/
+ MSG_DECWEAPONATTACK = 0x1d2,
+/*20080827 to latest
+ 시전 딜레이가 줄었습니다.
+Cast Delay is reduced.
+*/
+ MSG_FASTPREDELAY = 0x1d3,
+/*20080827 to latest
+ 시전 딜레이가 정상으로 되었습니다.
+Cast Delay has returned to normal.
+*/
+ MSG_NORMALPREDELAY = 0x1d4,
+/*20080827 to latest
+ 무기에 독속성이 부여되었습니다.
+Weapon is temporarily enchanted with Poison.
+*/
+ MSG_WEAPONPROPERTYPOISON = 0x1d5,
+/*20080827 to latest
+ 무기에 성속성이 부여되었습니다.
+Weapon is temporarily enchanted with an elemental property.
+*/
+ MSG_WEAPONPROPERTYSAINT = 0x1d6,
+/*20080827 to latest
+ 무기의 원래속성이 적용되었습니다.
+Weapon has changed back to normal.
+*/
+ MSG_WEAPONPROPERTYORIGINAL = 0x1d7,
+/*20080827 to latest
+ 방어구에 성속성이 부여되었습니다.
+Armor has been enchanted with the Holy Ghost.
+*/
+ MSG_ARMORPROPERTYSAINT = 0x1d8,
+/*20080827 to latest
+ 방어구의 원래속성이 적용되었습니다.
+Armor has changed back to normal.
+*/
+ MSG_ARMORPROPERTYORIGINAL = 0x1d9,
+/*20080827 to latest
+ 배리어 상태가 되었습니다.
+Barrier Formed.
+*/
+ MSG_BARRIOR = 0x1da,
+/*20080827 to latest
+ 배리어 상태가 해제 되었습니다.
+Barrier Canceled.
+*/
+ MSG_DISAPPEARBARRIOR = 0x1db,
+/*20080827 to latest
+ 소형, 중형, 대형 몬스터에게 100% 공격력을 줍니다.
+Weapon Perfection Initiated.
+*/
+ MSG_PERFECTDAMAGE = 0x1dc,
+/*20080827 to latest
+ 웨폰퍼펙션 모드가 해제 되었습니다.
+Weapon perfection Canceled.
+*/
+ MSG_DISAPPEARPERFECTDAMAGE = 0x1dd,
+/*20080827 to latest
+ 무기가 파괴될 가능성이 높아진 대신 무기의 공격력이 증가하였습니다.
+Power-Thrust Initiated.
+*/
+ MSG_OVERTHRUSTING = 0x1de,
+/*20080827 to latest
+ 오버트러스트 상태가 해제 되었습니다.
+Power-Thrust Canceled.
+*/
+ MSG_DISAPPEAROVERTHRUSTING = 0x1df,
+/*20080827 to latest
+ 무기의 최대 성능을 끌어냅니다.
+Maximize-Power Initiated.
+*/
+ MSG_MAXIMIZE = 0x1e0,
+/*20080827 to latest
+ 맥시마이즈 상태가 해제 되었습니다.
+Maximize-Power Canceled.
+*/
+ MSG_DISAPPEARMAXIMIZE = 0x1e1,
+/*20080827 to latest
+[신서버]
+[New Server]
+*/
+ MSG_SERVER_PROPERTY_NEW = 0x1e2,
+/*20080827 to latest
+(%d 명)
+(%d players)
+*/
+ MSG_SERVER_USER_COUNT = 0x1e3,
+/*20080827 to latest
+(점검중)
+(On the maintenance)
+*/
+ MSG_SERVER_INSPECTING = 0x1e4,
+/*20080827 to latest
+길드멤버 %s님이 접속하셨습니다.
+Guild member %s has connected.
+*/
+ MSG_GUILD_MEMBER_STATUS_ONLINE = 0x1e5,
+/*20080827 to latest
+길드멤버 %s님이 종료하셨습니다.
+Guild member %s has disconnected.
+*/
+ MSG_GUILD_MEMBER_STATUS_OFFLINE = 0x1e6,
+/*20080827 to latest
+경험치 %d 얻음
+You got %d Base EXP.
+*/
+ MSG_GOT_EXPERIENCE_POINT = 0x1e7,
+/*20080827 to latest
+잡경험치 %d 얻음
+You got %d Job EXP.
+*/
+ MSG_GOT_JOB_EXPERIENCE_POINT = 0x1e8,
+/*20080827 to latest
+길드에서 탈퇴 했습니다.
+You left the guild.
+*/
+ MSG_LEFT_GUILD = 0x1e9,
+/*20080827 to latest
+길드에서 추방 당했습니다.
+You have been expelled from the Guild.
+*/
+ MSG_BAN_FROM_GUILD = 0x1ea,
+/*20080827 to latest
+아이템 감정 성공
+Item Appraisal has completed successfully.
+*/
+ MSG_ITEM_IDENTIFY_SUCCEESS = 0x1eb,
+/*20080827 to latest
+아이템 감정 실패
+Item appraisal has failed.
+*/
+ MSG_ITEM_IDENTIFY_FAIL = 0x1ec,
+/*20080827 to latest
+아이템 조합 성공
+Compounding has completed successfully.
+*/
+ MSG_ITEM_COMPOUNDING_SUCCEESS = 0x1ed,
+/*20080827 to latest
+아이템 조합 실패
+Compounding has failed.
+*/
+ MSG_ITEM_COMPOUNDING_FAIL = 0x1ee,
+/*20080827 to latest
+길드 적대 성공
+Antagonist has been set.
+*/
+ MSG_HOSTILE_GUILD_SUCCEESS = 0x1ef,
+/*20080827 to latest
+적대 길드수 초과로 길드 적대 실패
+Guild has too many Antagonists.
+*/
+ MSG_TOO_MANY_HOSTILE_GUILD = 0x1f0,
+/*20080827 to latest
+이미 적대 길드 입니다
+Already set as an Antagonist
+*/
+ MSG_ALREADY_REGISTERED_HOSTILE_GUILD = 0x1f1,
+/*20080827 to latest
+제련이 성공적으로 되었습니다.
+Upgrade has been completed successfully.
+*/
+ MSG_ITEM_REFINING_SUCCEESS = 0x1f2,
+/*20080827 to latest
+제련이 실패하였습니다.
+Upgrade has failed.
+*/
+ MSG_ITEM_REFINING_FAIL = 0x1f3,
+/*20080827 to latest
+이곳에서는 순간이동이 불가능합니다.
+Unavailable Area to Teleport
+*/
+ MSG_IMPOSSIBLE_TELEPORT_AREA = 0x1f4,
+/*20080827 to latest
+이 장소는 기억할 수 없습니다.
+Unable to memorize this place as Warp Point
+*/
+ MSG_POSSIBLE_TELEPORT_AREA = 0x1f5,
+/*20080827 to latest
+지금은 종료할 수 없습니다.
+Please wait 10 seconds before trying to log out.
+*/
+ MSG_CANT_EXIT_NOW = 0x1f6,
+/*20080827 to latest
+직위
+Position
+*/
+ MSG_POSITION = 0x1f7,
+/*20080827 to latest
+직업
+Job
+*/
+ MSG_JOB = 0x1f8,
+/*20080827 to latest
+메모
+Note
+*/
+ MSG_MEMO = 0x1f9,
+/*20080827 to latest
+기여
+Devotion
+*/
+ MSG_CONTRIBUTION = 0x1fa,
+/*20080827 to latest
+상납경험치
+Tax Point
+*/
+ MSG_EXP_CONTIRIBUTION = 0x1fb,
+/*20080827 to latest
+길드탈퇴
+Leave Guild
+*/
+ MSG_LEAVE_GUILD = 0x1fc,
+/*20080827 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL_GUILD = 0x1fd,
+/*20080827 to latest
+서열
+Rank
+*/
+ MSG_GRADE = 0x1fe,
+/*20080827 to latest
+직위명
+Position Title
+*/
+ MSG_POSITION_NAME = 0x1ff,
+/*20080827 to latest
+가입권한
+Invitation
+*/
+ MSG_JOIN_AUTHORITY = 0x200,
+/*20080827 to latest
+처벌권한
+Punish
+*/
+ MSG_PENALTY_AUTORITY = 0x201,
+/*20080827 to latest
+상납%
+Tax %
+*/
+ MSG_CONTRIBUTION_PERCENT = 0x202,
+/*20080827 to latest
+제목
+Title
+*/
+ MSG_TITLE = 0x203,
+/*20080827 to latest
+내용
+For
+*/
+ MSG_CONTENTS = 0x204,
+/*20080827 to latest
+길드이름
+Guild Name
+*/
+ MSG_GUILD_NAME = 0x205,
+/*20080827 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILD_LEVEL = 0x206,
+/*20080827 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_PEOPLE_COUNT = 0x207,
+/*20080827 to latest
+랭킹
+Ranking
+*/
+ MSG_RANKING = 0x208,
+/*20080827 to latest
+아이템 감정
+Item Appraisal
+*/
+ MSG_ITEM_IDENTIFY = 0x209,
+/*20080827 to latest
+아이템 조합
+Insert Card
+*/
+ MSG_ITEM_COMPOUNDING = 0x20a,
+/*20080827 to latest
+탈퇴 사유를 입력해주세요.
+Please enter the reason of Secession.
+*/
+ MSG_PLEASE_INPUT_WHY_LEAVING = 0x20b,
+/*20080827 to latest
+추방 사유를 입력해주세요.
+Please enter the reason of Expulsion.
+*/
+ MSG_PELASE_INPUT_WHY_EXPEL = 0x20c,
+/*20080827 to latest
+상점을 닫으세요.
+Please close Shop.
+*/
+ MSG_PLEASE_CLOSE_STORE = 0x20d,
+/*20080827 to latest
+스킬 이름
+Skill
+*/
+ MSG_SKILL_NAME = 0x20e,
+/*20080827 to latest
+아이템 이름
+Item Name
+*/
+ MSG_ITEM_NAME = 0x20f,
+/*20080827 to latest
+https://payment.ragnarok.co.kr
+https://pay.ragnarok.co.kr (Billing Web)
+*/
+ MSG_SETTLE_WEB_URL = 0x210,
+/*20080827 to latest
+게임방에서 사용가능한 IP개수가 모두 사용중입니다. 개인 계정으로 결제 하시겠습니까?
+IP capacity of this Internet Cafe is full. Would you like to pay the personal base?
+*/
+ MSG_BAN_IP_OVERFLOW = 0x211,
+/*20080827 to latest
+결제시간이 다되어 게임을 종료합니다.
+You are out of available paid playing time. Game will be shut down automatically.
+*/
+ MSG_BAN_PAY_OUT = 0x212,
+/*20080827 to latest
+이름이 너무 깁니다. 한글 11자 영문 23자 이내로 써주십시오.
+Name is too long. Please enter a name no greater than 23 english characters.
+*/
+ MSG_NAMELENGTH_TOO_LONG = 0x213,
+/*20080827 to latest
+deleted
+Character will be deleted in %d seconds.
+*/
+ MSG_DELETE_AFTER_10_SECOND = 0x214,
+/*20080827 to latest
+귀하는 개인 정액제 사용자입니다.
+You paid with the personal regular base.
+*/
+ MSG_BILLING_100 = 0x215,
+/*20080827 to latest
+귀하는 개인정량제 사용자입니다.
+You paid with the personal regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_200 = 0x216,
+/*20080827 to latest
+귀하는 개인 무료 사용자입니다.
+You are free!
+*/
+ MSG_BILLING_300 = 0x217,
+/*20080827 to latest
+귀하는 개인 무료 허용기간 사용자입니다.
+You are free for the test, your available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_400 = 0x218,
+/*20080827 to latest
+귀하는 게임방 정액제 사용자입니다.
+You paid with the Internet Cafe regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_500 = 0x219,
+/*20080827 to latest
+귀하는 게임방 정량제 사용자입니다.
+You paid with the Time Limit for Internet Cafe. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_501 = 0x21a,
+/*20080827 to latest
+귀하는 게임방 무료 허용기간 사용자입니다.
+You are free for the test of Internet Cafe version .
+*/
+ MSG_BILLING_600 = 0x21b,
+/*20080827 to latest
+귀하는 게임방 무료 사용자입니다.
+You are free for the Internet Cafe version.
+*/
+ MSG_BILLING_700 = 0x21c,
+/*20080827 to latest
+귀하는 종량제 사이트 이용자입니다.
+You paid on the Time Limit Website.
+*/
+ MSG_BILLING_800 = 0x21d,
+/*20080827 to latest
+이모션 목록
+Emotion icon List
+*/
+ MSG_EMOTION_LIST = 0x21e,
+/*20080827 to latest
+/이모션
+/emo
+*/
+ MSG_VIEW_EMOTION = 0x21f,
+/*20080827 to latest
+/!
+*/
+ MSG_EMOTION_SURPRISE = 0x220,
+/*20080827 to latest
+/?
+*/
+ MSG_EMOTION_QUESTION = 0x221,
+/*20080827 to latest
+/기쁨
+/ho
+*/
+ MSG_EMOTION_DELIGHT = 0x222,
+/*20080827 to latest
+/하트
+/lv
+*/
+ MSG_EMOTION_THROB = 0x223,
+/*20080827 to latest
+/왕하트
+/lv2
+*/
+ MSG_EMOTION_BIGTHROB = 0x224,
+/*20080827 to latest
+/땀
+/swt
+*/
+ MSG_EMOTION_SWEAT = 0x225,
+/*20080827 to latest
+/아하
+/ic
+*/
+ MSG_EMOTION_AHA = 0x226,
+/*20080827 to latest
+/짜증
+/an
+*/
+ MSG_EMOTION_FRET = 0x227,
+/*20080827 to latest
+/화
+/ag
+*/
+ MSG_EMOTION_ANGER = 0x228,
+/*20080827 to latest
+/돈
+/$
+*/
+ MSG_EMOTION_MONEY = 0x229,
+/*20080827 to latest
+/...
+*/
+ MSG_EMOTION_THINK = 0x22a,
+/*20080827 to latest
+/감사
+/thx
+*/
+ MSG_EMOTION_THANKS = 0x22b,
+/*20080827 to latest
+/꽥
+/wah
+*/
+ MSG_EMOTION_KEK = 0x22c,
+/*20080827 to latest
+/죄송
+/sry
+*/
+ MSG_EMOTION_SORRY = 0x22d,
+/*20080827 to latest
+/웃음
+/heh
+*/
+ MSG_EMOTION_SMILE = 0x22e,
+/*20080827 to latest
+/뻘뻘
+/swt2
+*/
+ MSG_EMOTION_PROFUSELY_SWEAT = 0x22f,
+/*20080827 to latest
+/긁적
+/hmm
+*/
+ MSG_EMOTION_SCRATCH = 0x230,
+/*20080827 to latest
+/최고
+/no1
+*/
+ MSG_EMOTION_BEST = 0x231,
+/*20080827 to latest
+/두리번
+/??
+*/
+ MSG_EMOTION_STARE_ABOUT = 0x232,
+/*20080827 to latest
+/헉
+/omg
+*/
+ MSG_EMOTION_HUK = 0x233,
+/*20080827 to latest
+/오
+/oh
+*/
+ MSG_EMOTION_O = 0x234,
+/*20080827 to latest
+/엑스
+/X
+*/
+ MSG_EMOTION_X = 0x235,
+/*20080827 to latest
+/헬프
+/hlp
+*/
+ MSG_EMOTION_HELP = 0x236,
+/*20080827 to latest
+/가
+/go
+*/
+ MSG_EMOTION_GO = 0x237,
+/*20080827 to latest
+/엉엉
+/sob
+*/
+ MSG_EMOTION_CRY = 0x238,
+/*20080827 to latest
+/킥킥
+/gg
+*/
+ MSG_EMOTION_KIK = 0x239,
+/*20080827 to latest
+/쪽
+/kis
+*/
+ MSG_EMOTION_CHUP = 0x23a,
+/*20080827 to latest
+/쪽쪽
+/kis2
+*/
+ MSG_EMOTION_CHUPCHUP = 0x23b,
+/*20080827 to latest
+/흥
+/pif
+*/
+ MSG_EMOTION_HNG = 0x23c,
+/*20080827 to latest
+/응
+/ok
+*/
+ MSG_EMOTION_OK = 0x23d,
+/*20080827 to latest
+단축키 목록
+Shortcut List
+*/
+ MSG_SHORTCUT_LIST = 0x23e,
+/*20080827 to latest
+귀하의 계정은 보류되었습니다.
+Your account is suspended.
+*/
+ MSG_BAN_PAY_SUSPEND = 0x23f,
+/*20080827 to latest
+과금 정책 변경으로 인해 일시 종료됩니다. 다시 접속하여 주시기 바랍니다.
+Your connection is terminated due to change in the billing policy. Please connect again.
+*/
+ MSG_BAN_PAY_CHANGE = 0x240,
+/*20080827 to latest
+어카운트 서버에 인증된 IP와 귀하의 IP가 달라 연결을 종료합니다.
+Your connection is terminated because your IP doesn't match the authorized IP from the account server.
+*/
+ MSG_BAN_PAY_WRONGIP = 0x241,
+/*20080827 to latest
+게임방 IP에서 개인 종량제 과금을 막기 위해 연결을 종료합니다. 개인 종량제 과금을 사용하기 위해서는 게임방IP로 등록이 되지 않은 IP를 사용해 주세요.
+Your connection is terminated to prevent charging from your account's play time.
+*/
+ MSG_BAN_PAY_PNGAMEROOM = 0x242,
+/*20080827 to latest
+귀하는 운영자에 의해 강제 종료 되었습니다.
+You have been forced to disconnect by the Game Master Team.
+*/
+ MSG_BAN_OP_FORCE = 0x243,
+/*20080827 to latest
+무게가 90%를 초과하여 스킬을 사용할 수 없습니다.
+You can't use this Skill because you are over your Weight Limit.
+*/
+ MSG_USESKILL_FAIL_WEIGHTOVER = 0x244,
+/*20080827 to latest
+무명
+Nameless
+*/
+ MSG_NAMELESS_USER = 0x245,
+/*20080827 to latest
+축하합니다. %s님의 현재 랭킹이 %d위로 상승하였습니다.
+Congratulations! %s ranking has gone up to %d.
+*/
+ MSG_RANK_IN_TEN = 0x246,
+/*20080827 to latest
+안타깝게도 %s님의 현재 랭킹이 %d위로 하락하였습니다.
+What a pity! %s ranking has gone down to %d.
+*/
+ MSG_RANK_OUT_TEN = 0x247,
+/*20080827 to latest
+Pet Info
+*/
+ MSG_PET_INFO = 0x248,
+/*20080827 to latest
+만복도
+Hunger
+*/
+ MSG_PET_HUNGRY = 0x249,
+/*20080827 to latest
+친밀도
+Intimacy
+*/
+ MSG_PET_FRIENDLY = 0x24a,
+/*20080827 to latest
+상점과 채팅방을 동시에 열수 없습니다.
+Please avoid opening a chatroom while vending.
+*/
+ MSG_CANT_OPEN_STORE_WHILE_CHAT = 0x24b,
+/*20080827 to latest
+개
+Total
+*/
+ MSG_EA4 = 0x24c,
+/*20080827 to latest
+%s 를 전투불능으로 만들었습니다.
+You have knocked down %s.
+*/
+ MSG_SLAIN = 0x24d,
+/*20080827 to latest
+%s 님에 의해 전투불능 상태가 되었습니다.
+You have been knocked down by %s.
+*/
+ MSG_SLAINBY = 0x24e,
+/*20080827 to latest
+먹이 - '%s' 아이템이 존재하지 않습니다..
+Feed - "%s" is not available.
+*/
+ MSG_NOT_EXIST_PET_FOOD = 0x24f,
+/*20080827 to latest
+먹이 주기
+Feed Pet
+*/
+ MSG_PET_FEEDING = 0x250,
+/*20080827 to latest
+퍼포먼스
+Performance
+*/
+ MSG_PET_PERFORMANCE = 0x251,
+/*20080827 to latest
+알로 되돌리기
+Return to Egg Shell
+*/
+ MSG_PET_RETURN_EGG = 0x252,
+/*20080827 to latest
+악세사리 해제
+Unequip Accessory
+*/
+ MSG_PET_ACC_OFF = 0x253,
+/*20080827 to latest
+Pet 상태 보기
+Check Pet Status
+*/
+ MSG_PET_SHOWINFO = 0x254,
+/*20080827 to latest
+악세사리
+Accessory
+*/
+ MSG_PET_ACCESSARY = 0x255,
+/*20080827 to latest
+장착됨
+Equipped
+*/
+ MSG_ITEM_EQUIPED = 0x256,
+/*20080827 to latest
+펫 리스트
+Pet List
+*/
+ MSG_PET_EGG_LIST = 0x257,
+/*20080827 to latest
+장착 안됨
+Unequipped
+*/
+ MSG_ITEM_UNEQUIPED = 0x258,
+/*20080827 to latest
+정말로 먹이를 주시겠습니까?
+Are you sure that you want to feed your pet?
+*/
+ MSG_SURE_TO_FEED_PET = 0x259,
+/*20080827 to latest
+가격을 쓰실땐 숫자(0~9)만 써주십시오.
+Only the numbers (0~9) are available.
+*/
+ MSG_CAN_INPUT_NUMBER_ONLY = 0x25a,
+/*20080827 to latest
+감정되지 않은 아이템은 판매할 수 없습니다.
+You cannot sell unidentified items.
+*/
+ MSG_CANT_SELL_UNIDENTIFIED_ITEM = 0x25b,
+/*20080827 to latest
+가격이 0 Zeny인 아이템이 존재합니다. 계속 하시겠습니까?
+Item at 0 Zeny exists. Do you wish to continue?
+*/
+ MSG_YOU_HAVE_FREE_ITEM_ON_SHOP = 0x25c,
+/*20080827 to latest
+[새로 추가된 이모션 리스트]
+[New Emotion List]
+*/
+ MSG_NEW_EMOTION_LIST = 0x25d,
+/*20080827 to latest
+일본쪽 베타 사용자들에게 전하는 메세지. -> 겅호에서 재가입 하세요.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE1 = 0x25e,
+/*20080827 to latest
+일본쪽 과금이 종료된 사용자들에게 전하는 메세지. -> 돈내라. 두 번내라.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE2 = 0x25f,
+/*20080827 to latest
+같은 계정의 캐릭터가 이미 가입되어있습니다.
+Character in the same account already joined.
+*/
+ MSG_ALREADY_SAME_AID_JOINED = 0x260,
+/*20080827 to latest
+(%d 명) - 만18세이상
+(%d ppl) - over the age 18
+*/
+ MSG_SERVER_PROPERTY_ADULT = 0x261,
+/*20080827 to latest
+ 프로보크 상태가 되었습니다.
+Provoke initiated.
+*/
+ MSG_ENST_PROVOKE = 0x262,
+/*20080827 to latest
+ 프로보크 상태가 해제되었습니다.
+Provoke canceled.
+*/
+ MSG_DSST_PROVOKE = 0x263,
+/*20080827 to latest
+ 인듀어 상태가 되었습니다.
+Endure initiated.
+*/
+ MSG_ENST_ENDURE = 0x264,
+/*20080827 to latest
+ 인듀어 상태가 해제되었습니다.
+Endure canceled.
+*/
+ MSG_DSST_ENDURE = 0x265,
+/*20080827 to latest
+ 집중력 향상 상태가 되었습니다.
+Improve Concentration initiated.
+*/
+ MSG_ENST_CONCENTRATION = 0x266,
+/*20080827 to latest
+ 집중력 향상 상태가 해제되었습니다.
+Improve Concentration canceled.
+*/
+ MSG_DSST_CONCENTRATION = 0x267,
+/*20080827 to latest
+ 하이딩 상태가 되었습니다.
+Hiding Initiated.
+*/
+ MSG_ENST_HIDING = 0x268,
+/*20080827 to latest
+ 하이딩 상태가 해제되었습니다.
+Hiding Canceled.
+*/
+ MSG_DSST_HIDING = 0x269,
+/*20080827 to latest
+ 클로킹 상태가 되었습니다.
+Cloaking initiated.
+*/
+ MSG_ENST_CLOAKING = 0x26a,
+/*20080827 to latest
+ 클로킹 상태가 해제되었습니다.
+Cloaking canceled.
+*/
+ MSG_DSST_CLOAKING = 0x26b,
+/*20080827 to latest
+ 독을 반사 할 수 있는 상태가 되었습니다.
+Poison React initiated.
+*/
+ MSG_ENST_POISONREACT = 0x26c,
+/*20080827 to latest
+ 포이즌 리액트 상태가 해제되었습니다.
+Poison React canceled.
+*/
+ MSG_DSST_POISONREACT = 0x26d,
+/*20080827 to latest
+ 이동속도가 감소하였습니다.
+Speed reduced.
+*/
+ MSG_ENST_QUAGMIRE = 0x26e,
+/*20080827 to latest
+ 콰그마이어 상태가 해제되었습니다.
+Quagmire canceled.
+*/
+ MSG_DSST_QUAGMIRE = 0x26f,
+/*20080827 to latest
+ 방어력이 증가되었습니다.
+Defense increased.
+*/
+ MSG_ENST_ANGELUS = 0x270,
+/*20080827 to latest
+ 안젤루스 상태가 해제되었습니다.
+Angelus canceled.
+*/
+ MSG_DSST_ANGELUS = 0x271,
+/*20080827 to latest
+ 힘과 지능, 덱스가 증가하였습니다.
+Blessing aligned.
+*/
+ MSG_ENST_BLESSING = 0x272,
+/*20080827 to latest
+ 블레싱 상태가 해제되었습니다.
+Blessing canceled.
+*/
+ MSG_DSST_BLESSING = 0x273,
+/*20080827 to latest
+ 시그넘 크루시스를 사용하였습니다.
+Signum Crusis initiated.
+*/
+ MSG_ENST_CRUCIS = 0x274,
+/*20080827 to latest
+ 시그넘 크루시스 상태가 해제되었습니다.
+Signum Crusis canceled.
+*/
+ MSG_DSST_CRUCIS = 0x275,
+/*20080827 to latest
+ 독이 퍼지는 속도가 느려졌습니다.
+Slow Poison initiated.
+*/
+ MSG_ENST_SLOWPOISON = 0x276,
+/*20080827 to latest
+ 슬로우 포이즌 상태가 해제되었습니다.
+Slow Poison Canceled.
+*/
+ MSG_DSST_SLOWPOISON = 0x277,
+/*20080827 to latest
+ SP의 회복 속도가 향상 되었습니다.
+HP/SP recovery increased.
+*/
+ MSG_ENST_MAGNIFICAT = 0x278,
+/*20080827 to latest
+ 마니피캇 상태가 해제되었습니다.
+Magnificat canceled.
+*/
+ MSG_DSST_MAGNIFICAT = 0x279,
+/*20080827 to latest
+ 행운이 향상되었습니다.
+Luck increased.
+*/
+ MSG_ENST_GLORIA = 0x27a,
+/*20080827 to latest
+ 글로리아 상태가 해제되었습니다.
+Gloria canceled.
+*/
+ MSG_DSST_GLORIA = 0x27b,
+/*20080827 to latest
+ 1회 공격에 두 배 데미지를 받는 상태가 되었습니다.
+You will received double damage from all attacking opponents.
+*/
+ MSG_ENST_LEXAETERNA = 0x27c,
+/*20080827 to latest
+ 렉스에테르나 상태가 해제되었습니다.
+Lex Eterna canceled.
+*/
+ MSG_DSST_LEXAETERNA = 0x27d,
+/*20080827 to latest
+ 공격속도가 증가하였습니다.
+Attack Speed increased.
+*/
+ MSG_ENST_ADRENALINE = 0x27e,
+/*20080827 to latest
+ 공격속도가 감소하였습니다.
+Attack Speed reduced.
+*/
+ MSG_DSST_ADRENALINE = 0x27f,
+/*20080827 to latest
+ 페코에 올라 탔습니다.
+You've just been on a Peco Peco.
+*/
+ MSG_ENST_RIDING = 0x280,
+/*20080827 to latest
+ 페코에서 내렸습니다.
+You've just got off of a Peco Peco.
+*/
+ MSG_DSST_RIDING = 0x281,
+/*20080827 to latest
+ 팔콘을 장착하였습니다.
+You've just carried a Falcon with.
+*/
+ MSG_ENST_FALCON = 0x282,
+/*20080827 to latest
+ 팔콘을 풀어주었습니다.
+You've just released a Falcon.
+*/
+ MSG_DSST_FALCON = 0x283,
+/*20080827 to latest
+ 죽은척하기 상태가 되었습니다.
+Play Dead initiated.
+*/
+ MSG_ENST_TRICKDEAD = 0x284,
+/*20080827 to latest
+ 죽은척하기 상태가 해제되었습니다.
+Play Dead canceled.
+*/
+ MSG_DSST_TRICKDEAD = 0x285,
+/*20080827 to latest
+ 힘이 강해졌습니다.
+STR improved.
+*/
+ MSG_ENST_SHOUT = 0x286,
+/*20080827 to latest
+ 힘이 원래대로 돌아왔습니다.
+STR turned back to normal.
+*/
+ MSG_DSST_SHOUT = 0x287,
+/*20080827 to latest
+ 에너지코트 상태가 되었습니다.
+Energy Coat initiated.
+*/
+ MSG_ENST_ENERGYCOAT = 0x288,
+/*20080827 to latest
+ 에너지코트 상태가 해제되었습니다.
+Energy Coat canceled.
+*/
+ MSG_DSST_ENERGYCOAT = 0x289,
+/*20080827 to latest
+ 방어구가 파괴되었습니다.
+Armor destroyed.
+*/
+ MSG_ENST_BROKENAMOR = 0x28a,
+/*20080827 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENAMOR = 0x28b,
+/*20080827 to latest
+ 무기가 파괴되었니다.
+Weapon destroyed.
+*/
+ MSG_ENST_BROKENWEAPON = 0x28c,
+/*20080827 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENWEAPON = 0x28d,
+/*20080827 to latest
+ 환영상태가 되었습니다.
+Invisibility initiated.
+*/
+ MSG_ENST_ILLUSION = 0x28e,
+/*20080827 to latest
+ 환영상태가 해제되었습니다.
+Invisibility canceled.
+*/
+ MSG_DSST_ILLUSION = 0x28f,
+/*20080827 to latest
+과금 정보 처리가 늦어지고 있어 접속이 지연되고 있습니다. 잠시 후에 다시 시도해 주시기 바랍니다.
+Sorry. It is delayed due to the process of payment. Please re-connect in a minute.
+*/
+ MSG_REFUSE_BLOCK_TEMPORARY = 0x290,
+/*20080827 to latest
+장착된 화살/탄환/수리검 을 해제해야합니다.
+You must unequip ammunition first.
+*/
+ MSG_UNEQUIP_ARROW = 0x291,
+/*20080827 to latest
+화살 목록
+Arrow List
+*/
+ MSG_ARROW_LIST = 0x292,
+/*20080827 to latest
+카트 목록
+Cart List
+*/
+ MSG_CART_LIST = 0x293,
+/*20080827 to latest
+카트를 장착한 상태여야 합니다.
+You must have a Pushcart.
+*/
+ MSG_MUST_EQUIP_CART = 0x294,
+/*20080827 to latest
+채팅방을 개설 할 수 없습니다.
+You cannot open a Chat Window.
+*/
+ MSG_CANT_MAKE_CHAT_ROOM = 0x295,
+/*20080827 to latest
+라그나로크 홈페이지로 접속하여 계정을 만듭니다. 처음 계정을 만드시면 3일 동안은 무료로 이용하실 수 있습니다.
+Registering an account is the first step to accessing the game. Do you want to visit the registration page now?
+*/
+ MSG_3DAY_FREE = 0x296,
+/*20080827 to latest
+앉은 상태에서는 이 아이템을 사용할 수 없습니다.
+You cannot use this item while sitting.
+*/
+ MSG_CANT_USE_WHEN_SITDOWN = 0x297,
+/*20080827 to latest
+채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+Your use of skills and chat will be blocked for the next %d minutes.
+*/
+ MSG_BAD_MANNER_REMAIN = 0x298,
+/*20080827 to latest
+채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+Your use of skills and chat have been reinstated.
+*/
+ MSG_BAD_MANNER_END = 0x299,
+/*20080827 to latest
+-[장착안됨]
+- [Not equipped]
+*/
+ MSG_REF_UNEQUIP = 0x29a,
+/*20080827 to latest
+배고픔
+Very Hungry
+*/
+ MSG_VERY_HUNGRY = 0x29b,
+/*20080827 to latest
+출출함
+Hungry
+*/
+ MSG_HUNGRY = 0x29c,
+/*20080827 to latest
+보통
+Normal
+*/
+ MSG_NORMAL = 0x29d,
+/*20080827 to latest
+배부름
+Satisfied
+*/
+ MSG_REPLETE = 0x29e,
+/*20080827 to latest
+아주 배부름
+Stuffed
+*/
+ MSG_VERY_REPLETE = 0x29f,
+/*20080827 to latest
+서먹서먹함
+Awkward
+*/
+ MSG_VERY_AWKWARD = 0x2a0,
+/*20080827 to latest
+어색함
+Shy
+*/
+ MSG_AWKWARD = 0x2a1,
+/*20080827 to latest
+친함
+Cordial
+*/
+ MSG_FRIENDLY = 0x2a2,
+/*20080827 to latest
+절친함
+Loyal
+*/
+ MSG_VERY_FRIENDLY = 0x2a3,
+/*20080827 to latest
+알수 없음
+Unknown
+*/
+ MSG_UNKNOWN = 0x2a4,
+/*20080827 to latest
+귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d day %d hour %d minute.
+*/
+ MSG_BILLING_DAY_HOUR_MINUTES = 0x2a5,
+/*20080827 to latest
+이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+Your account is already connected to account server.
+*/
+ MSG_BAN_INFORMATION_REMAINED_ANOTHER_ACCOUNT = 0x2a6,
+/*20080827 to latest
+귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d hour %d minute.
+*/
+ MSG_BILLING_HOUR_MINUTES = 0x2a7,
+/*20080827 to latest
+귀하는 무료 사용자 입니다.
+Your account is a free account.
+*/
+ MSG_BILLING_FREE_USER = 0x2a8,
+/*20080827 to latest
+이 계정으로 사크라이에 접속할수 없습니다.
+This account can't connect the Sakray server.
+*/
+ MSG_REFUSE_NONSAKRAY_ID_BLOCKED = 0x2a9,
+/*20080827 to latest
+펫의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Your pet name must be 23 characters or less.
+*/
+ MSG_PETNAME_IN23 = 0x2aa,
+/*20080827 to latest
+이름은 단 한번만 바꿀수 있습니다. 펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You may change your pet's name only once. Your pet's name will be changed to ^0000ff^0000ff %s^000000^000000. Do you wish to continue?
+*/
+ MSG_PETNAME_CHANGE_ONLYONCE = 0x2ab,
+/*20080827 to latest
+/폰트
+/font
+*/
+ MSG_NAMEBALLOON_TYPE = 0x2ac,
+/*20080827 to latest
+길드에 남은 제니가 부족하여 작업이 실패하였습니다.
+Your guild lacks the funds to pay for this venture.
+*/
+ MSG_GUILDZENY_NOT_ENOUGH = 0x2ad,
+/*20080827 to latest
+길드가 소유할 수 있는 최대 금액을 초과하여 작업이 실패하였습니다.
+Your guild zeny limit prevents you from performing this action.
+*/
+ MSG_GUILDZENY_OVER = 0x2ae,
+/*20080827 to latest
+이펙트 간략화 On
+Simplified effects have been activated.
+*/
+ MSG_MINEFFECT_ON = 0x2af,
+/*20080827 to latest
+이펙트 간략화 Off
+Simplified effects have been deactivated.
+*/
+ MSG_MINEFFECT_OFF = 0x2b0,
+/*20080827 to latest
+자본금
+Required Fee
+*/
+ MSG_CAPITAL = 0x2b1,
+/*20080827 to latest
+아이템을 바닥에 버리려면, 아이템 창을 열어 주십시오.
+If you wish to drop an item, you must first open your Item Window (alt+e).
+*/
+ MSG_OPEN_ITEMWND_TO_THROW = 0x2b2,
+/*20080827 to latest
+PC방 요금이 종료하여 개인 요금제로 전환합니다. 개인 요금으로 게임을 계속 하시겠습니까?
+Internet Cafe Time Plan has been ended. Would you like to continue the game with your personal play time?
+*/
+ MSG_ASK_PNGAMEROOM = 0x2b3,
+/*20080827 to 20100810
+
+20081111 to latest
+
+Current admission application state.
+*/
+ MSG_REPLY_REMAINTIME = 0x2b4,
+/*20080827 to 20100810
+
+20081111 to latest
+
+Current admission application state.
+*/
+ MSG_INFO_REMAINTIME = 0x2b5,
+/*20080827 to latest
+돈이 모자라거나, 가질 수 있는 최대 금액을 초과하였습니다.
+Your lack of zeny or your zeny limit have prevented you from performing this action.
+*/
+ MSG_OVER_OR_LOW_MONEY = 0x2b6,
+/*20080827 to latest
+전투불능 상태가 되었습니다. esc키를 누르시면 선택창이 뜹니다.
+Your character has fainted. Push the ESC key to restart.
+*/
+ MSG_PRESS_ESC_TO_RESTART = 0x2b7,
+/*20080827 to latest
+ %d 개 획득
+- %d obtained.
+*/
+ MSG_EA_OBTAIN = 0x2b8,
+/*20080827 to latest
+스펠 리스트
+Spell List
+*/
+ MSG_SPELL_LIST = 0x2b9,
+/*20080827 to latest
+/최소화
+/minimize
+*/
+ MSG_MINEFFECT = 0x2ba,
+/*20080827 to latest
+이 아이템은 손상되어 있습니다..
+This item has been damaged.
+*/
+ MSG_DAMAGED_ITEM = 0x2bb,
+/*20080827 to latest
+/noshift : 쉬프트를 누르지않고 힐로 적을 공격할수있게됩니다 On Off
+/noshift: You may use your ''force heal'' ability without the Shift key. On | Off
+*/
+ MSG_EXPLAIN_NOSHIFT = 0x2bc,
+/*20080827 to latest
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns ON]
+[no shift] option activated. [ON]
+*/
+ MSG_NOSHIFT_ON = 0x2bd,
+/*20080827 to latest
+시프트를 눌러야 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+[no shift] option deactivated. [OFF]
+*/
+ MSG_NOSHIFT_OFF = 0x2be,
+/*20080827 to latest
+MSI_REFUSE_BAN_BY_DBA
+*/
+ MSG_REFUSE_BAN_BY_DBA = 0x2bf,
+/*20080827 to latest
+MSI_REFUSE_EMAIL_NOT_CONFIRMED
+*/
+ MSG_REFUSE_EMAIL_NOT_CONFIRMED = 0x2c0,
+/*20080827 to latest
+MSI_REFUSE_BAN_BY_GM
+*/
+ MSG_REFUSE_BAN_BY_GM = 0x2c1,
+/*20080827 to latest
+MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+*/
+ MSG_REFUSE_TEMP_BAN_FOR_DBWORK = 0x2c2,
+/*20080827 to latest
+MSI_REFUSE_SELF_LOCK
+*/
+ MSG_REFUSE_SELF_LOCK = 0x2c3,
+/*20080827 to latest
+MSI_REFUSE_NOT_PERMITTED_GROUP
+*/
+ MSG_REFUSE_NOT_PERMITTED_GROUP = 0x2c4,
+/*20080827 to latest
+MSI_REFUSE_WAIT_FOR_SAKRAY_ACTIVE
+*/
+ MSG_REFUSE_WAIT_FOR_SAKRAY_ACTIVE = 0x2c5,
+/*20080827 to latest
+/aura : 오오라를 간략화 시킬수있습니다 On Off
+/aura: Simplify Aura effect On | Off
+*/
+ MSG_EXPLAIN_AURA = 0x2c6,
+/*20080827 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_AURA_ON = 0x2c7,
+/*20080827 to latest
+오오라가 간략화되서 표시됩니다 [오오라 OFF]
+Simplify Aura enabled. [ON]
+*/
+ MSG_AURA_OFF = 0x2c8,
+/*20080827 to latest
+채팅금지 기록 %d 회
+Chat block record %d times
+*/
+ MSG_PROHIBIT_LOG = 0x2c9,
+/*20080827 to latest
+채팅 금지 리스트
+Chat block list
+*/
+ MSG_PROHIBIT_LIST = 0x2ca,
+/*20080827 to latest
+/이름표시 or /showname : 캐릭터의 이름 표시 방식을 변경합니다.
+/showname: Change the name font type.
+*/
+ MSG_EXPLAIN_SHOWNAMETYPE = 0x2cb,
+/*20080827 to latest
+/noctrl : 콘트롤을 누르지않아도 자동공격이 됩니다. On Off
+/noctrl | /nc: Auto attack without pressing ctrl key. On | Off
+*/
+ MSG_EXPLAIN_NOCTRL = 0x2cc,
+/*20080827 to latest
+콘트롤을 누르지 않아도 자동공격을 합니다 [/nc ON]
+Use auto attack without Ctrl. [Auto attack ON]
+*/
+ MSG_NOCTRL_ON = 0x2cd,
+/*20080827 to latest
+콘트롤을 눌러야 자동공격을 합니다 [/nc OFF]
+Use auto attack with Ctrl. [Auto attack OFF]
+*/
+ MSG_NOCTRL_OFF = 0x2ce,
+/*20080827 to latest
+채팅 금지 주기
+Mute this player.
+*/
+ MSG_APPEND_PROHIBIT = 0x2cf,
+/*20080827 to latest
+채팅 금지 완전 풀기 & 로그 삭제
+Unmute player & Erase mute time.
+*/
+ MSG_ERASE_PROHIBIT = 0x2d0,
+/*20080827 to latest
+채팅 금지 시간 줄이기(로그 삭제 안됨)
+Decrease Player Mute time.
+*/
+ MSG_REDUCE_PROHIBIT = 0x2d1,
+/*20080827 to latest
+폰트가 정상적으로 바뀌었습니다 [이름표시방식 1]
+Normal Font Displayed. [showname type 1]
+*/
+ MSG_SHOWNAME_ON = 0x2d2,
+/*20080827 to latest
+폰트가 가늘게 바뀌면서 파티명도 표시됩니다 [이름표시방식 2]
+Font will be thin and party name will be shown [showname type 2]
+*/
+ MSG_SHOWNAME_OFF = 0x2d3,
+/*20080827 to latest
+/doridori : 연속해서 이 명령어를 쳐주면 캐릭터가 도리도리 ^^;;
+/doridori: Shake head
+*/
+ MSG_EXPLAIN_DORIDORI = 0x2d4,
+/*20080827 to latest
+인터넷 카페에서 과금을 하고 있습니다.
+Internet room is paying now.
+*/
+ MSG_BILLING_INTERNET_CAFE = 0x2d5,
+/*20080827 to latest
+정액제 과금은 %d일 %d시간 %d분이 남았습니다.
+종량제 과금은 %d시간 %d분이 남았습니다.
+Prepaid voucher validate until %d days %d hours %d minutes later.
+Time limit voucher validate untill %d hours %d minutes later.
+*/
+ MSG_BILLING_BOTH = 0x2d6,
+/*20080827 to latest
+/bingbing : 연속해서 이 명령어를 쳐주면 캐릭터가 빙글빙글 ^^;;
+/bingbing: Rotates player counter clockwise.
+*/
+ MSG_EXPLAIN_BINGBING = 0x2d7,
+/*20080827 to latest
+/bangbang : 연속해서 이 명령어를 쳐주면 캐릭터가 뱅글뱅글 ^^;;
+/bangbang: Rotates player clockwise.
+*/
+ MSG_EXPLAIN_BANGBANG = 0x2d8,
+/*20080827 to latest
+/skillfail : 빨간색의 스킬사용 실패 메세지를 표시하지 않습니다 On Off
+/skillfail: Display red font message when skill fails. On | Off
+*/
+ MSG_EXPLAIN_SKILLFAIL = 0x2d9,
+/*20080827 to latest
+스킬사용 실패 메세지를 표시합니다 [/sf ON]
+Skill fail messages will be displayed. [Display On]
+*/
+ MSG_SKILLFAIL_ON = 0x2da,
+/*20080827 to latest
+스킬사용 실패 메세지를 표시하지 않습니다 [/sf OFF]
+Skill fail messages will not be displayed. [Display OFF]
+*/
+ MSG_SKILLFAIL_OFF = 0x2db,
+/*20080827 to latest
+/notalkmsg : 채팅내용을 채팅창에 표시하지 않습니다 On Off
+/notalkmsg: Chat will not be displayed in chat window. On | Off
+*/
+ MSG_EXPLAIN_NOTALKMSG = 0x2dc,
+/*20080827 to latest
+채팅내용을 채팅창에 표시합니다 [/nm ON]
+Chat content will be displayed in the chat window. [Display ON]
+*/
+ MSG_NOTALKMSG_ON = 0x2dd,
+/*20080827 to latest
+채팅내용을 채팅창에 표시하지않습니다 [/nm OFF]
+Chat content will not be displayed in the chat window. [Display OFF]
+*/
+ MSG_NOTALKMSG_OFF = 0x2de,
+/*20080827 to latest
+/set1 : /nc + /showname + /sf + /wi, /set2 : + /q3
+/set1: /noctrl + /showname + /skillfail
+*/
+ MSG_EXPLAIN_SET1 = 0x2df,
+/*20080827 to latest
+/fog : FOG이펙트를 키거나 끌수있습니다 On Off
+/fog: Fog effect. On | Off
+*/
+ MSG_EXPLAIN_FOG = 0x2e0,
+/*20080827 to latest
+ 청혼을 해왔습니다. 승낙하시겠습니까?
+You have received a marriage proposal. Do you accept?
+*/
+ MSG_SUGGEST_COUPLE = 0x2e1,
+/*20080827 to latest
+아이템 분배 방식
+Item sharing type
+*/
+ MSG_HOWITEMDIV = 0x2e2,
+/*20080827 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMDIV1 = 0x2e3,
+/*20080827 to latest
+균등하게 분배
+Shared
+*/
+ MSG_ITEMDIV2 = 0x2e4,
+/*20080827 to latest
+nProtect KeyCrypt
+*/
+ MSG_KEYCRYPT = 0x2e5,
+/*20080827 to latest
+Keyboard Driver가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+Keyboard Driver has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_INSTALL_KEYDRIVER = 0x2e6,
+/*20080827 to latest
+설치가 완료 되었습니다.
+
+시스템을 Reboot 합니다.
+Installation has been completed.
+
+System will be rebooted.
+*/
+ MSG_KEYCRYPT_REBOOT = 0x2e7,
+/*20080827 to latest
+설치 실패.
+Installation has been failed.
+*/
+ MSG_KEYCRYPT_INSTALLFAIL = 0x2e8,
+/*20080827 to latest
+키보드 보안을 적용하지 않고 계속합니다.
+Keyboard Security will be skipped.
+*/
+ MSG_KEYCRYPT_SKIPKEYCRYPT = 0x2e9,
+/*20080827 to latest
+키보드 보안에 필요한 파일이 존재하지 않습니다.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+Required file for Keyboard Security is not existing.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+*/
+ MSG_KEYCRYPT_NOKEYCRYPTFILE = 0x2ea,
+/*20080827 to latest
+USB Keyboard가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+USB Keyboard has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_USBKEYBOARD = 0x2eb,
+/*20080827 to latest
+ftp://ragnarok.nefficient.co.kr/pub/ragnarok/ragnarok0526.exe
+*/
+ MSG_FINDHACK_PATH = 0x2ec,
+/*20080827 to latest
+FindHack이 정상적으로 설치가 되어있지 않습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.(%d).
+FindHack is not installed correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.(%d).
+*/
+ MSG_FINDHACK_NOTINSTALLED = 0x2ed,
+/*20080827 to latest
+해킹툴이 존재하지만 치료가 정상적으로 되지 않았습니다. 라그나로크가 실행되지 않습니다.
+Hacking tool is existing but it hasn't been cleaned. Rangarok Online will not be executed.
+*/
+ MSG_FINDHACK_HACKTOOLEXIST = 0x2ee,
+/*20080827 to latest
+해킹툴 진단 프로그램이 정상적으로 다운로드 되지 않았습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+Hacking tool scan program has not been downloaded correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_CANTDOWNLOAD = 0x2ef,
+/*20080827 to latest
+NPX.DLL 등록에러 이거나 FindHack 구동에 필요한 파일이 없습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+NPX.DLL register error or there is no necessary file to run FindHack. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_NOFILE = 0x2f0,
+/*20080827 to latest
+예외사항이 발생했습니다. (02-3281-0361)로 문의해주세요. 리턴값(%d)
+Exceptional Error. Please contact the customer support. Return Value: (%d)
+*/
+ MSG_FINDHACK_EXCEPTION = 0x2f1,
+/*20080827 to latest
+종료버튼을 클릭 하셨습니다.
+Exit button has been clicked.
+*/
+ MSG_FINDHACK_EXITPRESSED = 0x2f2,
+/*20080827 to latest
+Findhack 업데이트 서버접근 실패하였습니다. 잠시 후에 다시 시도해 주시거나 그라비티 운영팀으로 연락해주시기 바랍니다.
+Unable to connect Findhack Update Server. Please try again or contact the customer support.
+*/
+ MSG_FINDHACK_UPDATEFAILED = 0x2f3,
+/*20080827 to latest
+사랑받고있는
+Beloved
+*/
+ MSG_NAMED_PET = 0x2f4,
+/*20080827 to latest
+/report or /신고 : 신고용 갈무리 파일을 저장합니다.
+/report: Save a chat log file.
+*/
+ MSG_REPORTCOMMAND_EXPLANATION = 0x2f5,
+/*20080827 to latest
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로 사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+Chat logs are not accepted as evidence for any ill-mannered violation on account of possible file modifications. However this feature is provided for players' personal reference.
+*/
+ MSG_REPORTTEXT_HEADER = 0x2f6,
+/*20080827 to latest
+당신을 사랑해요 ♡
+I love you.
+*/
+ MSG_LOVE_SKILL = 0x2f7,
+/*20080827 to latest
+화면 또는 이펙트가 밝아서 눈에 부담이 되시는분들은 모니터의 밝기를 조정해주시기바랍니다.
+Please adjust your monitor/video brightness if effects appear too bright.
+*/
+ MSG_EXPLAIN_BRIGHT = 0x2f8,
+/*20080827 to latest
+전체화면모드가 잘안되는 경우에 게임실행후 ALT+TAB으로 화면을 전환하면 잘되는 기종도 있습니다
+If full screen mode fails to work, it is suggested you alt+tab [or ctrl+esc] to inactivate and reactivate the Ragnarok Client.
+*/
+ MSG_EXPLAIN_ALTTAB = 0x2f9,
+/*20080827 to latest
+(%d 명) - 유료서버
+(%d players) - Pay to Play Server
+*/
+ MSG_SERVER_PROPERTY_PAY = 0x2fa,
+/*20080827 to latest
+(%d 명) - 무료서버
+(%d players) - Free Server
+*/
+ MSG_SERVER_PROPERTY_FREE = 0x2fb,
+/*20080827 to latest
+무료 회원은 유료 서버로 접속할 수 없습니다.
+Trial players can't connect Pay to Play Server.
+*/
+ MSG_CANT_CONNECT_TO_PAY_SERVER = 0x2fc,
+/*20080827 to latest
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [/q1 ON]
+Right click menu skills for F9 are Enabled.[/q1 ON]
+*/
+ MSG_QUICKSPELL_ON = 0x2fd,
+/*20080827 to latest
+마우스 우클릭으로 스킬을 사용하지 못합니다 [/q1 OFF]
+Right click menu skills for F9 are Disabled.[/q1 OFF]
+*/
+ MSG_QUICKSPELL_OFF = 0x2fe,
+/*20080827 to latest
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+/quickspell: Right-click menu enables you to use skills assigned to the F9 hotkey. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL = 0x2ff,
+/*20080827 to latest
+마우스의 WHEEL을 사용해서 F7 과 F8에 저장한 스킬을 사용합니다 [/q2 ON]
+Mouse wheel skills for F7 and F8 are Enabled.[/q2 ON]
+*/
+ MSG_QUICKSPELL2_ON = 0x300,
+/*20080827 to latest
+마우스 WHEEL로 스킬을 사용하지 못합니다 [/q2 OFF]
+Mouse wheel skills for F7 and F8 are Disabled.[/q2 OFF]
+*/
+ MSG_QUICKSPELL2_OFF = 0x301,
+/*20080827 to latest
+/quickspell2 : 마우스 WHEEL을 위,아래로 굴려서 F7과F8에 저장한 스킬을 사용합니다 On Off
+/quickspell2: By rolling the mouse wheel up and down, you are able to use skills registered on F7 and F8 hotkeys. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL2 = 0x302,
+/*20080827 to latest
+/q3 : /quickspell (/q1) + /quickspell2 (/q2)
+*/
+ MSG_EXPLAIN_QUICKSPELL3 = 0x303,
+/*20080827 to latest
+/찌릿
+/bzz
+*/
+ MSG_EMOTION_STARE = 0x304,
+/*20080827 to latest
+/밥
+/rice
+*/
+ MSG_EMOTION_HUNGRY = 0x305,
+/*20080827 to latest
+/멋져
+/awsm
+*/
+ MSG_EMOTION_COOL = 0x306,
+/*20080827 to latest
+/메롱
+/meh
+*/
+ MSG_EMOTION_MERONG = 0x307,
+/*20080827 to latest
+/부끄
+/shy
+*/
+ MSG_EMOTION_SHY = 0x308,
+/*20080827 to latest
+/쓱쓱
+/pat
+*/
+ MSG_EMOTION_GOODBOY = 0x309,
+/*20080827 to latest
+/엠탐
+/mp
+*/
+ MSG_EMOTION_SPTIME = 0x30a,
+/*20080827 to latest
+/질질
+/slur
+*/
+ MSG_EMOTION_SEXY = 0x30b,
+/*20080827 to latest
+/컴온
+/com
+*/
+ MSG_EMOTION_COMEON = 0x30c,
+/*20080827 to latest
+/하품
+/yawn
+*/
+ MSG_EMOTION_SLEEPY = 0x30d,
+/*20080827 to latest
+/축하
+/grat
+*/
+ MSG_EMOTION_CONGRATULATION = 0x30e,
+/*20080827 to latest
+/피탐
+/hp
+*/
+ MSG_EMOTION_HPTIME = 0x30f,
+/*20080827 to latest
+/이모션 : 현재 사용가능한 이모션의 리스트를 보여줍니다.
+/emotion: views the emoticon list.
+*/
+ MSG_EXPLAIN_EMOTION = 0x310,
+/*20080827 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용합니다. [/bm ON]
+Skills assigned to shortcut windows 1, 2, 3 are Enabled. [/bm ON]
+*/
+ MSG_BATTLE_ON = 0x311,
+/*20080827 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용하지못합니다. [/bm OFF]
+Skills assigned to shortcut windows 1, 2, 3 are Disabled. [/bm OFF]
+*/
+ MSG_BATTLE_OFF = 0x312,
+/*20080827 to latest
+/battlemode : Q ~ O 를 누르면 스킬단축창2의 스킬들이 사용됩니다.
+/battlemode: allows you to use skills assigned to Shortcut Window 2 by pressing Q ~ O keys.
+*/
+ MSG_EXPLAIN_BATTLE = 0x313,
+/*20080827 to latest
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다.
+A ~ L keys allow you to use skills assigned to Shortcut Window 3.
+*/
+ MSG_EXPLAIN_BATTLE2 = 0x314,
+/*20080827 to latest
+라그나로크를 실행하실때 다른 프로그램을 띄우시면 게임이 느려질수도있습니다.
+Please remember, programs running in the background while playing may affect the game's performance.
+*/
+ MSG_EXPLAIN_LAG = 0x315,
+/*20080827 to latest
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+*/
+ MSG_SUPERNOVICE1 = 0x316,
+/*20080827 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_SUPERNOVICE2 = 0x317,
+/*20080827 to latest
+예요~
+Super Novice~
+*/
+ MSG_SUPERNOVICE3 = 0x318,
+/*20080827 to latest
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE4 = 0x319,
+/*20080827 to latest
+님께서 당신을 입양시키고 싶어하십니다. 승낙하시겠습니까?
+ wishes to adopt you. Do you accept?
+*/
+ MSG_SUGGEST_BABY = 0x31a,
+/*20080827 to latest
+ Z ~ > 을 누르면 스킬단축창1의 스킬들이 사용됩니다. On Off
+Z ~ > keys allow you to use skills assigned on shortcut window 1. On | Off
+*/
+ MSG_EXPLAIN_BATTLE3 = 0x31b,
+/*20080827 to latest
+ Space를 한번 누른뒤에 글자를 입력하면 채팅을 할수있습니다.
+Press the space bar to Chat when in Battle mode [/battlemode | /bm].
+*/
+ MSG_EXPLAIN_BATTLE4 = 0x31c,
+/*20080827 to latest
+게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다.
+"Either there's no Game Guard installed on the program or Game Guard is cracked. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_AUTH_GAMEGUARD = 0x31d,
+/*20080827 to latest
+윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다.
+Some of Windows system files have been damaged. Please re-install your Internet Explorer.
+*/
+ MSG_NPGAMEMON_ERROR_CRYPTOAPI = 0x31e,
+/*20080827 to latest
+게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다.
+"Failed to run Game Guard. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_EXECUTE = 0x31f,
+/*20080827 to latest
+불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다.
+"At least one hazardous program has been detected. Please, terminate all the unnecessary programs before executing Game Guard."
+*/
+ MSG_NPGAMEMON_ERROR_ILLEGAL_PRG = 0x320,
+/*20080827 to latest
+게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 방화벽 상태를 점검해보시기 바랍니다.
+"Game Guard update is canceled. If the disconnection continues, please, check your internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_ABORT = 0x321,
+/*20080827 to latest
+게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 인터넷 및 방화벽 상태를 점검해 보시기 바랍니다.
+"Failed to connect to Game Guard update server. Try to connect again later, or try to check the internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_CONNECT = 0x322,
+/*20080827 to latest
+게임가드 업데이트를 완료하지 못 했습니다. 바이러스 검사를 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정한 후 게임을 실행해 보시기 바랍니다.
+"Can't complete Game Guard update process. Please, try to execute a vaccine program to remove viruses. Or, please try to modify the settings of your PC managing tool if you are using any."
+*/
+ MSG_NPGMUP_ERROR_AUTH = 0x323,
+/*20080827 to latest
+/notrade : 거래신청을 자동으로 거절합니다 On Off
+/notrade: Declines trade offers automatically. On | Off
+*/
+ MSG_EXPLAIN_NOTRADE = 0x324,
+/*20080827 to latest
+거래신청과 친구등록요청을 자동으로 거절합니다 [/nt ON]
+Auto decline trade offers has been Enabled. [/nt ON]
+*/
+ MSG_NOTRADE_ON = 0x325,
+/*20080827 to latest
+거래신청과 친구등록요청을 정상적으로 받습니다 [/nt OFF]
+Auto decline trade offers has been Disabled. [/nt OFF]
+*/
+ MSG_NOTRADE_OFF = 0x326,
+/*20080827 to latest
+같은 아이템은 한번에 30000개 이상은 살수 없습니다.
+You cannot buy more than 30,000ea items at once.
+*/
+ MSG_LIMIT_BUY_ITEM = 0x327,
+/*20080827 to latest
+재료가 충분하지 않습니다.
+You do not have enough ingredients.
+*/
+ MSG_NOT_ENOUGH_SOURCE = 0x328,
+/*20080827 to latest
+%s에 계정정보가 남아있습니다.
+Login information remains at %s.
+*/
+ MSG_ALREADY_CONNECT = 0x329,
+/*20080827 to latest
+계정도용 조사를 위해 로그인이 금지되었습니다. 자세한 문의는 계정도용 관련 문의 메일로 해주시기 바랍니다.
+Account has been locked for a hacking investigation. Please contact the GM Team for more information.
+*/
+ MSG_HACKING_INVESTIGATION = 0x32a,
+/*20080827 to latest
+귀하는 버그관련 조사중이므로 일시적으로 접속을 금합니다
+This account has been temporarily prohibited from login due to a bug-related investigation.
+*/
+ MSG_BUG_INVESTIGATION = 0x32b,
+/*20080827 to latest
+수리가능한 아이템
+Repairable items
+*/
+ MSG_REPAIRITEMLIST = 0x32c,
+/*20080827 to latest
+아이템 수리 성공
+Item has been successfully repaired.
+*/
+ MSG_ITEM_REPAIR_SUCCEESS = 0x32d,
+/*20080827 to latest
+아이템 수리 실패 (재료 또는 상대와의 거리등을 확인해주십시요)
+You have failed to repair this item. Please check the distance between you and opponent.
+*/
+ MSG_ITEM_REPAIR_FAIL = 0x32e,
+/*20080827 to latest
+시스템 상황을 지속적으로 체크 합니다.[운영자모드] [/sc ON]
+System process enabled [GM mode] [/sc ON]
+*/
+ MSG_SYSTEM_CHECK_ON = 0x32f,
+/*20080827 to latest
+시스템 상황을 지속적으로 체크 하지 않습니다.[운영자모드] [/sc OFF]
+System process disabled [GM mode] [/sc OFF]
+*/
+ MSG_SYSTEM_CHECK_OFF = 0x330,
+/*20080827 to latest
+/systemcheck : 시스템 상황을 지속적으로 체크 합니다.[운영자모드]
+/systemcheck: Check the system process [GM mode] On | Off
+*/
+ MSG_EXPLAIN_SYSTEM_CHECK = 0x331,
+/*20080827 to latest
+(%s)님이 친구 신청을 하셨습니다. 친구가 되시겠습니까?
+(%s) wishes to be friends with you. Would you like to accept?
+*/
+ MSG_SUGGEST_JOIN_FRIEND = 0x332,
+/*20080827 to latest
+더 이상 친구 등록을 하실수 없습니다.
+Your Friend List is full.
+*/
+ MSG_FRIEND_ADD_ME_OVERSIZE = 0x333,
+/*20080827 to latest
+(%s)님이 더 이상 친구 등록을 하실수 없습니다.
+(%s)'s Friend List is full.
+*/
+ MSG_FRIEND_ADD_OTHER_OVERSIZE = 0x334,
+/*20080827 to latest
+(%s)님과 친구가 되셨습니다.
+You have become friends with (%s).
+*/
+ MSG_FRIEND_ADD_SUCCEED = 0x335,
+/*20080827 to latest
+(%s)님이 친구 되기를 원하지 않습니다.
+(%s) does not want to be friends with you.
+*/
+ MSG_FRIEND_ADD_FALSE = 0x336,
+/*20080827 to latest
+이 캐릭터는 %s 까지 블럭되어있습니다.
+This character will be blocked to use until %s.
+*/
+ MSG_BLOCKED = 0x337,
+/*20080827 to latest
+천만제니 이상 입력하셔도 가격은 천만제니로 판매됩니다.
+Price will be fixed at 10,000,000 zeny, even if you enter higher price.
+*/
+ MSG_OVERPRICE = 0x338,
+/*20080827 to latest
+(적음)
+(Very low)
+*/
+ MSG_LITTLEUSER = 0x339,
+/*20080827 to latest
+(약간 적음)
+(Low)
+*/
+ MSG_ALITTLEUSER = 0x33a,
+/*20080827 to latest
+(보통)
+(Normal)
+*/
+ MSG_NORMLEUSER = 0x33b,
+/*20080827 to latest
+(많음)
+(High)
+*/
+ MSG_MANYUSER = 0x33c,
+/*20080827 to latest
+(매우 많음)
+(Very high)
+*/
+ MSG_VERYMANYUSER = 0x33d,
+/*20080827 to latest
+비매너에 의해 운영자로부터 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d minutes by the GM Team.
+*/
+ MSG_GM_BAD_MANNER_START = 0x33e,
+/*20080827 to latest
+GM에 의한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_REMAIN = 0x33f,
+/*20080827 to latest
+GM에 의한 채팅금지가 해지 되었습니다.
+You have been released from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_END = 0x340,
+/*20080827 to latest
+도배 방지 시스템으로 인한 자동 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d as an automatic penalty.
+*/
+ MSG_AUTO_BAD_MANNER_START = 0x341,
+/*20080827 to latest
+도배 방지 시스템으로 인한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from auto penalty.
+*/
+ MSG_AUTO_BAD_MANNER_REMAIN = 0x342,
+/*20080827 to latest
+도배 방지 시스템으로 인한 채팅금지가 해지되었습니다. 게임진행 시에는 도배에 대해서 주의하여 주시기 바랍니다.
+You have been released from the auto penalty. Please refrain from spamming in-game.
+*/
+ MSG_AUTO_BAD_MANNER_END = 0x343,
+/*20080827 to latest
+%s님과 %s님이 이혼하셨습니다.
+%s and %s have divorced from each other.
+*/
+ MSG_DIVORCE = 0x344,
+/*20080827 to latest
+拳聖 %s의 태양의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Space.
+*/
+ MSG_STARPLACE1 = 0x345,
+/*20080827 to latest
+拳聖 %s의 달의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Space.
+*/
+ MSG_STARPLACE2 = 0x346,
+/*20080827 to latest
+拳聖 %s의 별의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Space.
+*/
+ MSG_STARPLACE3 = 0x347,
+/*20080827 to latest
+拳聖 %s의 태양의 장소는 %s 입니다
+Gravity %s's Solar Space: %s
+*/
+ MSG_STARPLACE4 = 0x348,
+/*20080827 to latest
+拳聖 %s의 달의 장소는 %s 입니다
+Gravity %s's Luna Space: %s
+*/
+ MSG_STARPLACE5 = 0x349,
+/*20080827 to latest
+拳聖 %s의 별의 장소는 %s 입니다
+Gravity %s's Stellar Space: %s
+*/
+ MSG_STARPLACE6 = 0x34a,
+/*20080827 to latest
+拳聖 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Monster.
+*/
+ MSG_STARMONSTER1 = 0x34b,
+/*20080827 to latest
+拳聖 %s의 달의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Monster.
+*/
+ MSG_STARMONSTER2 = 0x34c,
+/*20080827 to latest
+拳聖 %s의 별의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Monster.
+*/
+ MSG_STARMONSTER3 = 0x34d,
+/*20080827 to latest
+拳聖 %s의 태양의 몬스터는 %s 입니다
+Gravity %s's Solar Monster: %s
+*/
+ MSG_STARMONSTER4 = 0x34e,
+/*20080827 to latest
+拳聖 %s의 달의 몬스터는 %s 입니다
+Gravity %s's Luna Monster: %s
+*/
+ MSG_STARMONSTER5 = 0x34f,
+/*20080827 to latest
+拳聖 %s의 별의 몬스터는 %s 입니다
+Gravity %s's Stellar Monster: %s
+*/
+ MSG_STARMONSTER6 = 0x350,
+/*20080827 to latest
+/window : 창 위치 이동시 다른 창과 달라붙는 속성이 들어갑니다 On Off
+/window: Display windows will snap/dock together. On | Off
+*/
+ MSG_EXPLAIN_WINDOW = 0x351,
+/*20080827 to latest
+창 위치 이동시 다른 창과 잘 붙습니다 [/wi ON]
+Display window docking enabled. [/wi ON]
+*/
+ MSG_WINDOW_ON = 0x352,
+/*20080827 to latest
+창 위치 이동시 다른 창과 붙으려는 속성을 가지지 않습니다 [/wi OFF]
+Display window docking disabled. [/wi OFF]
+*/
+ MSG_WINDOW_OFF = 0x353,
+/*20080827 to latest
+/pvpinfo : 자신의 PVP 승패와 PVP 포인트를 알 수 있습니다.
+/pvpinfo: shows your PVP result and PVP points.
+*/
+ MSG_EXPLAIN_PVP_INFO = 0x354,
+/*20080827 to latest
+현재 %d승, %d패, PVP포인트는 %d입니다.
+You have won %d times and have lost %d times in PVP. Current points %d.
+*/
+ MSG_PVP_INFO = 0x355,
+/*20080827 to latest
+매너 포인트를 성공적으로 보냈습니다.
+A manner point has been successfully aligned.
+*/
+ MSG_SEND_MANNER_POINT = 0x356,
+/*20080827 to latest
+현재 이곳은 PK 가능 지역입니다. 불의의 공격에 유의 하시기 바랍니다.
+You are in a PK area. Please beware of sudden attack.
+*/
+ MSG_PKZONE = 0x357,
+/*20080827 to latest
+게임가드 업데이트가 바이러스나 스파이웨어와의 충돌로 실패했습니다. 백신 프로그램/스파이웨어 제거 프로그램을 사용한 후 접속해 주십시기 바랍니다
+Game Guard update has been failed when either Virus or Spyware conflicted with. Please, Uninstall Spyware and Virus protection program before you log in.
+*/
+ MSG_NPGAMEMON_ERROR_100ERROR = 0x358,
+/*20080827 to latest
+윈도우 호환성 문제로 프로그램을 종료합니다. 게임을 다시 실행해 주시기 바랍니다
+Program has encountered an error related to Windows compatibility. Please start the game again.
+*/
+ MSG_NPGAMEMON_XP_COMPATIBILITY = 0x359,
+/*20080827 to latest
+채팅, 스킬, 아이템을 사용할수없게 되었습니다.
+You have been blocked from chatting, using skills and items.
+*/
+ MSG_PK_HONOR = 0x35a,
+/*20080827 to latest
+캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while this character is being deleted.
+*/
+ MSG_DELETING_CHAR = 0x35b,
+/*20080827 to latest
+결혼 상대자의 캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while your spouse character is being deleted.
+*/
+ MSG_DELETING_SPOUSE_CHAR = 0x35c,
+/*20080827 to latest
+Novice
+*/
+ MSG_NOVICE = 0x35d,
+/*20080827 to latest
+Swordman
+*/
+ MSG_SWORDMAN = 0x35e,
+/*20080827 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN = 0x35f,
+/*20080827 to latest
+Archer
+*/
+ MSG_ARCHER = 0x360,
+/*20080827 to latest
+Acolyte
+*/
+ MSG_ACOLYTE = 0x361,
+/*20080827 to latest
+Merchant
+*/
+ MSG_MERCHANT = 0x362,
+/*20080827 to latest
+Thief
+*/
+ MSG_THIEF = 0x363,
+/*20080827 to latest
+Knight
+*/
+ MSG_KNIGHT = 0x364,
+/*20080827 to 20181128
+Prieset
+Priest
+20181205 to latest
+Priest
+*/
+ MSG_PRIEST = 0x365,
+/*20080827 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD = 0x366,
+/*20080827 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH = 0x367,
+/*20080827 to latest
+Hunter
+*/
+ MSG_HUNTER = 0x368,
+/*20080827 to latest
+Assassin
+*/
+ MSG_ASSASSIN = 0x369,
+/*20080827 to latest
+Novice
+*/
+ MSG_NOVICE_W = 0x36a,
+/*20080827 to latest
+Swordman
+*/
+ MSG_SWORDMAN_W = 0x36b,
+/*20080827 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN_W = 0x36c,
+/*20080827 to latest
+Archer
+*/
+ MSG_ARCHER_W = 0x36d,
+/*20080827 to latest
+Acolyte
+*/
+ MSG_ACOLYTE_W = 0x36e,
+/*20080827 to latest
+Merchant
+*/
+ MSG_MERCHANT_W = 0x36f,
+/*20080827 to latest
+Thief
+*/
+ MSG_THIEF_W = 0x370,
+/*20080827 to latest
+Knight
+*/
+ MSG_KNIGHT_W = 0x371,
+/*20080827 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST_W = 0x372,
+/*20080827 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD_W = 0x373,
+/*20080827 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH_W = 0x374,
+/*20080827 to latest
+Hunter
+*/
+ MSG_HUNTER_W = 0x375,
+/*20080827 to latest
+Assassin
+*/
+ MSG_ASSASSIN_W = 0x376,
+/*20080827 to latest
+(%s)님을 아이로 입양신청
+Send an adoption request to %s
+*/
+ MSG_REQ_JOIN_BABY = 0x377,
+/*20080827 to latest
+아이가 되면 전승을 할수없고 스텟은 80이상 올릴수없게되며 HP와 SP가 줄어듭니다. 그래도 괜찮습니까?
+When you become a child, you will be unable to become a Transcendent Class character, all stats will be limited to a maximum of 80, and Max HP/SP will be reduced. Are you sure that you want to be adopted?
+*/
+ MSG_SUGGEST_BABY2 = 0x378,
+/*20080827 to latest
+모든 나쁜 상태이상이 제거 되었습니다.
+All abnormal status effects have been removed.
+*/
+ MSG_GOSPEL1 = 0x379,
+/*20080827 to latest
+1분간 모든 상태이상에 대해 면역이 됩니다.
+You will be immune to abnormal status effects for the next minute.
+*/
+ MSG_GOSPEL2 = 0x37a,
+/*20080827 to latest
+1분간 최대 생명력이 크게 늘어납니다.
+Your Max HP will stay increased for the next minute.
+*/
+ MSG_GOSPEL3 = 0x37b,
+/*20080827 to latest
+1분간 최대 마법력이 크게 늘어납니다.
+Your Max SP will stay increased for the next minute.
+*/
+ MSG_GOSPEL4 = 0x37c,
+/*20080827 to latest
+1분간 모든 능력이 크게 상승합니다.
+All of your Stats will stay increased for the next minute.
+*/
+ MSG_GOSPEL5 = 0x37d,
+/*20080827 to latest
+1분간 사용하는 무기에 성스러운 속성이 부여됩니다.
+Your weapon will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL6 = 0x37e,
+/*20080827 to latest
+1분간 사용하는 갑옷에 성스러운 속성이 부여됩니다.
+Your armor will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL7 = 0x37f,
+/*20080827 to latest
+10초간 방어력이 크게 상승합니다.
+Your Defense will stay increased for the next 10 seconds.
+*/
+ MSG_GOSPEL8 = 0x380,
+/*20080827 to latest
+1분간 공격력이 크게 증가합니다.
+Your Attack strength will be increased for the next minute.
+*/
+ MSG_GOSPEL9 = 0x381,
+/*20080827 to latest
+1분간 명중률과 회피율이 크게 상승합니다.
+Your Accuracy and Flee Rate will be increased for the next minute.
+*/
+ MSG_GOSPEL10 = 0x382,
+/*20080827 to latest
+아이를 한번 입양했던 부부는 추가 입양이 불가능합니다.
+You cannot adopt more than 1 child.
+*/
+ MSG_BABY1 = 0x383,
+/*20080827 to latest
+부부가 둘다 레벨70이 넘어야 아이를 입양할수있습니다.
+You must be at least character level 70 in order to adopt someone.
+*/
+ MSG_BABY2 = 0x384,
+/*20080827 to latest
+[POINT] 블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Blacksmith rank points. Your point total is %d.
+*/
+ MSG_BLACKSMITH_POINT = 0x385,
+/*20080827 to latest
+[POINT] 알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Alchemist rank points. Your point total is %d.
+*/
+ MSG_ALCHEMIST_POINT = 0x386,
+/*20080827 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE11 = 0x387,
+/*20080827 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE12 = 0x388,
+/*20080827 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE13 = 0x389,
+/*20080827 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE14 = 0x38a,
+/*20080827 to latest
+/notalkmsg2 : 채팅내용을 채팅창에 표시하지 않습니다 (길드말 포함) On Off
+/notalkmsg2: Hides chat messages(including guild chat). On Off
+*/
+ MSG_EXPLAIN_NOTALKMSG2 = 0x38b,
+/*20080827 to latest
+채팅내용을 채팅창에 표시합니다 [/nm2 ON]
+Show chat messages. [/nm2 ON]
+*/
+ MSG_NOTALKMSG2_ON = 0x38c,
+/*20080827 to latest
+채팅내용을 채팅창에 표시하지않습니다 (길드말 포함) [/nm2 OFF]
+Hide chat messages(including guild chat) [/nm2 OFF]
+*/
+ MSG_NOTALKMSG2_OFF = 0x38d,
+/*20080827 to latest
+제련가능한 아이템
+Upgradable Weapons
+*/
+ MSG_REFINEITEMLIST = 0x38e,
+/*20080827 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_SUCCEESS = 0x38f,
+/*20080827 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_FAIL = 0x390,
+/*20080827 to latest
+무기제련스킬의 레벨이 부족해서 %s 제련을 할수없습니다.
+You cannot upgrade %s until you level up your Upgrade Weapon skill.
+*/
+ MSG_ITEM_REFINE_FAIL_LEVEL = 0x391,
+/*20080827 to latest
+제련에 필요한 아이템 (%s) 이 없으므로 제련할수없습니다.
+You lack a necessary item %s to upgrade this weapon.
+*/
+ MSG_ITEM_REFINE_FAIL_MATERIAL = 0x392,
+/*20080827 to latest
+완벽하게 코팅되어있어서 풀스트립이 통하지 않습니다.
+Full Divestment cannot pierce the target. The target is fully shielded.
+*/
+ MSG_FULLSTRIP = 0x393,
+/*20080827 to latest
+결혼한 캐릭터는 입양시킬수 없습니다.
+You cannot adopt a married person.
+*/
+ MSG_BABY3 = 0x394,
+/*20080827 to latest
+친구로 등록된 이름과 비슷하지만 등록된 이름이 아닙니다. 아는사람인지 확인하십시요.
+This name is not registered in your Friend List. Please check the name again.
+*/
+ MSG_ID_WARNING = 0x395,
+/*20080827 to latest
+/hi 또는 /hi 문장 : 친구로 등록된 캐릭터들에게 인사를 합니다.
+/hi or /hi message: Send greetings to people who are online and registered on your Friend List.
+*/
+ MSG_EXPLAIN_HI = 0x396,
+/*20080827 to latest
+길드원의 이름과 비슷하지만 길드원이 아닙니다. 길드원인지 확인하십시요.
+This character is not your guildsman. Please check the name again.
+*/
+ MSG_ID_WARNING_GUILD = 0x397,
+/*20080827 to latest
+9999만제니 이상 입력하셔도 가격은 9999만제니로 판매됩니다.
+Please be aware that the maximum selling price is fixed as 2 Billion. You cannot sell an item higher than that.
+*/
+ MSG_OVERPRICE9999 = 0x398,
+/*20080827 to latest
+친구의 귓속말은 [ Friend ] , 길드원은 [ Member ] 로 표시됩니다.
+Whispers from friends are displayed as [ Friend ], and ones from guildsmen are displayed as [ Member ].
+*/
+ MSG_EXPLAIN_SACHING1 = 0x399,
+/*20080827 to latest
+( From 캐릭터이름 : ) 이라고 표시 되는 귓속말은 친구나 길드원이 아닙니다.
+( From character name: ) is from an anonymous character who is neither your friend nor guildsman.
+*/
+ MSG_EXPLAIN_SACHING2 = 0x39a,
+/*20080827 to latest
+/blacksmith : 블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+/blacksmith: Shows top 10 Blacksmiths in the server.
+*/
+ MSG_EXPLAIN_BLACKSMITH = 0x39b,
+/*20080827 to latest
+/alchemist : 알케미스트의 상위 10위권 랭킹을 보여줍니다.
+/alchemist: Shows top 10 Alchemists in the server.
+*/
+ MSG_EXPLAIN_ALCHEMIST = 0x39c,
+/*20080827 to latest
+ALT+Y : 여러가지 명령어를 쉽게 쓸수있는 윈도우가 열립니다.
+ALT+Y: Opens a window which allows you to use various commands with ease.
+*/
+ MSG_EXPLAIN_ALTY = 0x39d,
+/*20080827 to latest
+[POINT] 태권미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Tae-Kwon Mission rank points. Your point total is %d.
+*/
+ MSG_TAEKWON_POINT = 0x39e,
+/*20080827 to latest
+[태권미션] Target Monster : %s (%d%%)
+[Taekwon Mission] Target Monster: %s (%d%%)
+*/
+ MSG_TAEKWON_MISSION = 0x39f,
+/*20080827 to latest
+게임가드 초기화 에러 : %lu
+Error - Failed to initialize GameGuard: %lu
+*/
+ MSG_INIT_ERROR = 0x3a0,
+/*20080827 to latest
+스피드핵이 감지되었습니다.
+Speed Hack has been detected.
+*/
+ MSG_SPEEDHACK_DETECT = 0x3a1,
+/*20080827 to latest
+불법 프로그램 (%s) 가 발견되었습니다
+The illegal program, (%s) has been detected.
+*/
+ MSG_GAMEHACK_DETECT = 0x3a2,
+/*20080827 to latest
+게임이나 게임가드가 변조되었습니다.
+The Game or Gameguard has been cracked.
+*/
+ MSG_GAMEHACK_DOUBT = 0x3a3,
+/*20080827 to latest
+게임가드가 실행 중 입니다. 잠시 후에 다시 실행해보시기 바랍니다.
+GameGuard is currently running. Please wait for sometime and restart the game.
+*/
+ MSG_ERROR_EXIST = 0x3a4,
+/*20080827 to latest
+게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다.
+The Game or GameGuard is already running. Please close the game and restart the game.
+*/
+ MSG_GAME_EXIST = 0x3a5,
+/*20080827 to latest
+게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다.
+Failed to intialize GameGuard. Please try again after rebooting the system or closing other programs.
+*/
+ MSG_ERROR_INIT = 0x3a6,
+/*20080827 to latest
+바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다.
+Failed to load the scan module of virus and hacking tool. It's caused by lack of memory or PC virus infection.
+*/
+ MSG_ERROR_NPSCAN = 0x3a7,
+/*20080827 to latest
+호문클루스 정보
+Homunculus Info
+*/
+ MSG_HOMUN_INFO = 0x3a8,
+/*20080827 to latest
+호문클루스 스킬목록
+Homunculus Skill List
+*/
+ MSG_HOMUN_SKILLLIST = 0x3a9,
+/*20080827 to latest
+호문클루스의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Please give your Homunculus a name no longer than 23 letters.
+*/
+ MSG_HOMUN_NAME_IN23 = 0x3aa,
+/*20080827 to latest
+이름은 단 한번만 바꿀수 있습니다. 호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You can name a Homunculus only once. You have entered the name, ^0000ff%s^000000. Would you like to continue?
+*/
+ MSG_HOMUN_NAME_CHANGE_ONLYONCE = 0x3ab,
+/*20080827 to latest
+지금은 부재중~
+(Away)
+*/
+ MSG_AUTO_MSG = 0x3ac,
+/*20080827 to latest
+[자동응답]
+[Automated Message]
+*/
+ MSG_AUTO_MSG2 = 0x3ad,
+/*20080827 to latest
+부재시 타인의 귓말에 자동응답합니다.
+Send an automated message while you are away.
+*/
+ MSG_AUTO_MSG_ON = 0x3ae,
+/*20080827 to latest
+부재시 타인의 귓말에 자동응답하지 않습니다.
+Cancel automated away message.
+*/
+ MSG_AUTO_MSG_OFF = 0x3af,
+/*20080827 to latest
+자동 응답 메시지를 입력하세요.
+Please enter Away Message.
+*/
+ MSG_ENTER_AUTO_MSG = 0x3b0,
+/*20080827 to latest
+/번쩍
+/fsh
+*/
+ MSG_EMOTION_SPARK = 0x3b1,
+/*20080827 to latest
+/빙빙
+/spin
+*/
+ MSG_EMOTION_CONFUSE = 0x3b2,
+/*20080827 to latest
+/하아
+/sigh
+*/
+ MSG_EMOTION_OHNO = 0x3b3,
+/*20080827 to latest
+/덤덤
+/dum
+*/
+ MSG_EMOTION_HUM = 0x3b4,
+/*20080827 to latest
+/시끌
+/crwd
+*/
+ MSG_EMOTION_BLABLA = 0x3b5,
+/*20080827 to latest
+/좌절
+/desp
+*/
+ MSG_EMOTION_OTL = 0x3b6,
+/*20080827 to latest
+/주사위
+/dice
+*/
+ MSG_EMOTION_DICE = 0x3b7,
+/*20080827 to latest
+/pk : 학살자의 상위 10위권 랭킹을 보여줍니다.
+/pk: Shows top 10 Slayers in the server.
+*/
+ MSG_EXPLAIN_KILLER_RANK = 0x3b8,
+/*20080827 to latest
+[POINT] 학살자 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Slayer rank points. Your point total is %d.
+*/
+ MSG_KILLER_POINT = 0x3b9,
+/*20080827 to latest
+진화 가능
+Evolution Available
+*/
+ MSG_HOMUN_EVOLVE = 0x3ba,
+/*20080827 to latest
+^ff0000^ff0000호문클루스를 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+You have decided to delete this Homunculus ^ff0000^ff0000. When deleted, the homunculus and its history will be deleted and they cannot be restored in the future. Would you like to continue?
+*/
+ MSG_DELETE_HOMUN = 0x3bb,
+/*20080827 to latest
+호문의 상태를 파일에 저장합니다.
+Save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_ON = 0x3bc,
+/*20080827 to latest
+호문의 상태를 파일에 저장하지 않습니다.
+Do not save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_OFF = 0x3bd,
+/*20080827 to latest
+Crusader
+*/
+ MSG_CRUSADER = 0x3be,
+/*20080827 to latest
+Monk
+*/
+ MSG_MONK = 0x3bf,
+/*20080827 to latest
+Sage
+*/
+ MSG_SAGE = 0x3c0,
+/*20080827 to latest
+Rouge
+Rogue
+*/
+ MSG_ROGUE = 0x3c1,
+/*20080827 to latest
+Alchemist
+*/
+ MSG_ALCHEMIST = 0x3c2,
+/*20080827 to latest
+Bard
+*/
+ MSG_BARD = 0x3c3,
+/*20080827 to latest
+Crusader_W
+Crusader
+*/
+ MSG_CRUSADER_W = 0x3c4,
+/*20080827 to latest
+Monk_W
+Monk
+*/
+ MSG_MONK_W = 0x3c5,
+/*20080827 to latest
+Sage_W
+Sage
+*/
+ MSG_SAGE_W = 0x3c6,
+/*20080827 to latest
+Rouge_W
+Rogue
+*/
+ MSG_ROGUE_W = 0x3c7,
+/*20080827 to latest
+Alchemist_W
+Alchemist
+*/
+ MSG_ALCHEMIST_W = 0x3c8,
+/*20080827 to latest
+Dancer
+*/
+ MSG_DANCER = 0x3c9,
+/*20080827 to latest
+Novice High
+High Novice
+*/
+ MSG_NOVICE_H = 0x3ca,
+/*20080827 to latest
+Swordman High
+High Swordman
+*/
+ MSG_SWORDMAN_H = 0x3cb,
+/*20080827 to latest
+Magician High
+High Mage
+*/
+ MSG_MAGICIAN_H = 0x3cc,
+/*20080827 to latest
+Archer High
+High Archer
+*/
+ MSG_ARCHER_H = 0x3cd,
+/*20080827 to latest
+Acolyte High
+High Acolyte
+*/
+ MSG_ACOLYTE_H = 0x3ce,
+/*20080827 to latest
+Merchant High
+High Merchant
+*/
+ MSG_MERCHANT_H = 0x3cf,
+/*20080827 to latest
+Thief High
+High Thief
+*/
+ MSG_THIEF_H = 0x3d0,
+/*20080827 to latest
+Novice High_W
+High Novice
+*/
+ MSG_NOVICE_H_W = 0x3d1,
+/*20080827 to latest
+Swordman High_W
+High Swordman
+*/
+ MSG_SWORDMAN_H_W = 0x3d2,
+/*20080827 to latest
+Magician High_W
+High Mage
+*/
+ MSG_MAGICIAN_H_W = 0x3d3,
+/*20080827 to latest
+Archer High_W
+High Archer
+*/
+ MSG_ARCHER_H_W = 0x3d4,
+/*20080827 to latest
+Acolyte High_W
+High Acolyte
+*/
+ MSG_ACOLYTE_H_W = 0x3d5,
+/*20080827 to latest
+Merchant High_W
+High Merchant
+*/
+ MSG_MERCHANT_H_W = 0x3d6,
+/*20080827 to latest
+Thief High_W
+High Thief
+*/
+ MSG_THIEF_H_W = 0x3d7,
+/*20080827 to latest
+Lord Knight
+*/
+ MSG_KNIGHT_H = 0x3d8,
+/*20080827 to latest
+High Priest
+*/
+ MSG_PRIEST_H = 0x3d9,
+/*20080827 to latest
+High Wizard
+*/
+ MSG_WIZARD_H = 0x3da,
+/*20080827 to latest
+White Smith
+MasterSmith
+*/
+ MSG_BLACKSMITH_H = 0x3db,
+/*20080827 to latest
+Sniper
+*/
+ MSG_HUNTER_H = 0x3dc,
+/*20080827 to 20181128
+Saaassin Cross
+Assassin Cross
+20181205 to latest
+Assassin Cross
+*/
+ MSG_ASSASSIN_H = 0x3dd,
+/*20080827 to latest
+Lord Knight_W
+Lord Knight
+*/
+ MSG_KNIGHT_H_W = 0x3de,
+/*20080827 to latest
+High Priest_W
+High Priest
+*/
+ MSG_PRIEST_H_W = 0x3df,
+/*20080827 to latest
+High Wizard_W
+High Wizard
+*/
+ MSG_WIZARD_H_W = 0x3e0,
+/*20080827 to latest
+White Smith_W
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H_W = 0x3e1,
+/*20080827 to latest
+Sniper_W
+Sniper
+*/
+ MSG_HUNTER_H_W = 0x3e2,
+/*20080827 to 20181128
+Saaassin Cross_W
+Assassin Cross
+20181205 to latest
+Assassin Cross_W
+*/
+ MSG_ASSASSIN_H_W = 0x3e3,
+/*20080827 to latest
+Paladin
+*/
+ MSG_CRUSADER_H = 0x3e4,
+/*20080827 to latest
+Champion
+*/
+ MSG_MONK_H = 0x3e5,
+/*20080827 to latest
+Professor
+Scholar
+*/
+ MSG_SAGE_H = 0x3e6,
+/*20080827 to latest
+Stalker
+*/
+ MSG_ROGUE_H = 0x3e7,
+/*20080827 to latest
+Creator
+Biochemist
+*/
+ MSG_ALCHEMIST_H = 0x3e8,
+/*20080827 to latest
+Clown
+Minstrel
+*/
+ MSG_BARD_H = 0x3e9,
+/*20080827 to latest
+Paladin_W
+Paladin
+*/
+ MSG_CRUSADER_H_W = 0x3ea,
+/*20080827 to latest
+Champion_W
+Champion
+*/
+ MSG_MONK_H_W = 0x3eb,
+/*20080827 to latest
+Professor_W
+Professor
+*/
+ MSG_SAGE_H_W = 0x3ec,
+/*20080827 to latest
+Stalker_W
+Stalker
+*/
+ MSG_ROGUE_H_W = 0x3ed,
+/*20080827 to latest
+Creator_W
+Creator
+*/
+ MSG_ALCHEMIST_H_W = 0x3ee,
+/*20080827 to latest
+Gypsy
+*/
+ MSG_DANCER_H = 0x3ef,
+/*20080827 to latest
+비밀번호가 지정되어 있지 않습니다. 새로운 비밀번호를 지정하시겠습니까?
+You have not set a password yet. Would you like to create one now?
+*/
+ MSG_STORE_PASSWORD_REQ = 0x3f0,
+/*20080827 to latest
+비밀번호를 3회 틀려셨습니다. 나중에 다시 시도해 주세요.
+You have incorrectly entered the password 3 times. Please try again later.
+*/
+ MSG_STORE_PASSWORD_PENALTY = 0x3f1,
+/*20080827 to latest
+비밀번호 변경이 실패하였습니다.
+Password creation has failed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_NG = 0x3f2,
+/*20080827 to latest
+비밀번호는 4자리 이상 8자리이하여야만 합니다.
+Password must be 4~8 letters long.
+*/
+ MSG_STORE_PASSWORD_4_8 = 0x3f3,
+/*20080827 to latest
+비밀번호
+Password
+*/
+ MSG_STORE_PASSWORD = 0x3f4,
+/*20080827 to latest
+신규 비밀번호
+New Password
+*/
+ MSG_STORE_NEW_PASSWORD = 0x3f5,
+/*20080827 to latest
+확인 비밀번호
+Confirm Password
+*/
+ MSG_STORE_RENEW_PASSWORD = 0x3f6,
+/*20080827 to latest
+비밀번호 변경이 완료되었습니다.
+Password has been changed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_OK = 0x3f7,
+/*20080827 to latest
+비밀번호가 서로 다릅니다.
+Password does not match.
+*/
+ MSG_STORE_PASSWORD_MISMATCH = 0x3f8,
+/*20080827 to latest
+비밀번호 입력
+Enter Password
+*/
+ MSG_STORE_PASSWORD_INPUT = 0x3f9,
+/*20080827 to latest
+호문이 아사 직전입니다! 먹이를 주지 않으면 가출하게됩니다.
+Your Homunculus is starving. Please feed it, otherwise it will leave you.
+*/
+ MSG_HOMUN_HUNGRY = 0x3fa,
+/*20080827 to latest
+경험치
+EXP
+*/
+ MSG_HOMUN_EXP = 0x3fb,
+/*20080827 to 20110526
+[EVENT] 이벤트에 당첨되셨습니다. 게임내에서 아이템을 지급받으십시요.
+20110531 to latest
+수령하지 않은 아이템이 존재합니다. 알베르타의 존다 기획사 직원을 찾아주세요. ^ff0000※ 아이템 수령 기간이 지나면 아이템이 소실 됩니다!^000000
+[EVENT] You have won an event prize. Please claim your prize in game.
+*/
+ MSG_EVENT_RESULT = 0x3fc,
+/*20080827 to latest
+싫어함
+Hate
+*/
+ MSG_HATE = 0x3fd,
+/*20080827 to latest
+매우싫어함
+Hate with a Passion
+*/
+ MSG_VERYHATE = 0x3fe,
+/*20080827 to latest
+호문클루스가 사용자 인공지능으로 동작합니다.
+Homunculus has been customized.
+*/
+ MSG_HOMUN_USERAI_ON = 0x3ff,
+/*20080827 to latest
+호문클루스가 기본 인공지능으로 동작합니다.
+Homunculus has been activated with the basic AI.
+*/
+ MSG_HOMUN_USERAI_OFF = 0x400,
+/*20080827 to latest
+편지목록
+Mail List
+*/
+ MSG_MAIL_LIST = 0x401,
+/*20080827 to latest
+편지쓰기
+Write Mail
+*/
+ MSG_MAIL_WRITE = 0x402,
+/*20080827 to latest
+편지읽기
+Read Mail
+*/
+ MSG_MAIL_READ = 0x403,
+/*20080827 to latest
+한번 지정하시면 변경이 불가능합니다! 이 맵으로 지정하시겠습니까?
+You cannot change a map's designation once it is designated. Are you sure that you want to designate this map?
+*/
+ MSG_STARPLACE_ACCEPT = 0x404,
+/*20080827 to latest
+메일 아이템을 수령했습니다.
+Item has been added in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_SUCCESS = 0x405,
+/*20080827 to latest
+메일 아이템을 수령하지 못했습니다.
+You have failed to add the item in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_FAILURE = 0x406,
+/*20080827 to latest
+메일 보내기가 성공하였습니다.
+You have successfully mailed a message.
+*/
+ MSG_MAIL_SEND_SUCCESS = 0x407,
+/*20080827 to latest
+메일 보내기가 실패하였습니다. 받는 사람이 존재하지 않습니다.
+You have failed to mail a message. Recipient does not exist.
+*/
+ MSG_MAIL_USER_NOT_FOUND = 0x408,
+/*20080827 to latest
+[태양과 달과 별의 천사] 지정했던 장소들과 몬스터들이 초기화됐습니다!
+[Solar, Lunar and Stellar Angel] Designated places and monsters have been reset.
+*/
+ MSG_STAR_ANGEL = 0x409,
+/*20080827 to latest
+경매 등록이 실패했습니다.
+The minimum starting bid for auctions is 10,000,000 zeny.
+*/
+ MSG_AUCTION_ADD_FALSE = 0x40a,
+/*20080827 to latest
+경매 등록이 성공했습니다.
+You have successfully started a new auction.
+*/
+ MSG_AUCTION_ADD_TRUE = 0x40b,
+/*20080827 to latest
+해당 경매가 취소되었습니다.
+The auction has been canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL = 0x40c,
+/*20080827 to latest
+입찰자가 있는 경매는 취소할 수 없습니다.
+An auction with at least one bidder cannot be canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL_FALSE = 0x40d,
+/*20080827 to latest
+메일 삭제가 성공하였습니다.
+Mail has been successfully deleted.
+*/
+ MSG_MAIL_DELETE_SUCCESS = 0x40e,
+/*20080827 to latest
+메일 삭제가 실패하였습니다.
+You have failed to delete the mail.
+*/
+ MSG_MAIL_DELETE_FAILURE = 0x40f,
+/*20080827 to latest
+던지는 단검이 장착되었습니다.
+You have equipped throwing daggers.
+*/
+ MSG_MSG_KNIFE_EQUIPMENT_SUCCESS = 0x410,
+/*20080827 to latest
+%s 님이 로그인했습니다.
+%s has logged in.
+*/
+ MSG_LOGIN_FRIEND = 0x411,
+/*20080827 to latest
+%s 님이 로그아웃했습니다.
+%s has logged out.
+*/
+ MSG_LOGOUT_FRIEND = 0x412,
+/*20080827 to latest
+/loginout : 길드원과 친구들의 접속관련 메세지를 보여줍니다. On Off
+/loginout: Shows guildsmen and friends online status. On Off
+*/
+ MSG_EXPLAIN_LOGINOUT = 0x413,
+/*20080827 to latest
+친구들의 접속관련 메세지를 대화창에 표시합니다. [/li ON]
+Display online status of friends in Chat Window. [/li ON]
+*/
+ MSG_LOGINOUT_ON = 0x414,
+/*20080827 to latest
+친구들의 접속관련 메세지를 대화창에 표시하지않습니다. [/li OFF]
+Do not display online status of friends in Chat Window. [/li OFF]
+*/
+ MSG_LOGINOUT_OFF = 0x415,
+/*20080827 to latest
+이미 실행중입니다.
+It is already running.
+*/
+ MSG_SGP_CODE_ALREADY_RUNNING = 0x416,
+/*20080827 to latest
+매크로 사용이 감지되었습니다.
+Use of Macro program has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MACRO = 0x417,
+/*20080827 to latest
+스피드해킹이 감지되었습니다.
+Use of Speed hack has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_SPEEDHACK = 0x418,
+/*20080827 to latest
+API 후킹이 감지되었습니다.
+API Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_APIHOOK = 0x419,
+/*20080827 to latest
+메시지 후킹이 감지되었습니다.
+Message Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MSGHOOK = 0x41a,
+/*20080827 to latest
+모듈이 변조 또는 손상되었거나 버전이 일치하지 않습니다.
+Module has been modified or damaged or its version does not match.
+*/
+ MSG_SGP_CODE_NOT_EQUALENCRYPTEDDATA = 0x41b,
+/*20080827 to latest
+(태국)귀하는 게임방 과금으로 로그인 하셨습니다.
+(Thailand) You have logged in game with PC cafe payment.
+*/
+ MSG_BILLING_PCB = 0x41c,
+/*20080827 to latest
+이전
+Prev
+*/
+ MSG_PREV_PAGE = 0x41d,
+/*20080827 to latest
+다음
+Next
+*/
+ MSG_NEXT_PAGE = 0x41e,
+/*20080827 to latest
+경매
+Auction
+*/
+ MSG_AUCTION = 0x41f,
+/*20080827 to latest
+물품보기
+Product List
+*/
+ MSG_AUCTION_VIEW = 0x420,
+/*20080827 to latest
+등록하기
+Register
+*/
+ MSG_AUCTION_ADD = 0x421,
+/*20080827 to latest
+판매 진행상태
+Sale Status
+*/
+ MSG_AUCTION_SELL = 0x422,
+/*20080827 to latest
+구매 진행상태
+Purchase Status
+*/
+ MSG_AUCTION_BUY = 0x423,
+/*20080827 to latest
+아이템
+Item
+*/
+ MSG_ITEM2 = 0x424,
+/*20080827 to latest
+아이템명
+Name
+*/
+ MSG_ITEM_NAME2 = 0x425,
+/*20080827 to latest
+가격 / 즉시구입가격
+Current Bid / Max Bid
+*/
+ MSG_ITEM_PRICE = 0x426,
+/*20080827 to latest
+판매자
+Seller
+*/
+ MSG_SELLER = 0x427,
+/*20080827 to latest
+구매자
+Buyer
+*/
+ MSG_BUYER = 0x428,
+/*20080827 to latest
+종료시간
+End Time
+*/
+ MSG_FINISH_TIME = 0x429,
+/*20080827 to latest
+%m월 %d일 %H시
+%m %d %H
+*/
+ MSG_TIME_TYPE = 0x42a,
+/*20080827 to latest
+시간설정
+Time (Hr)
+*/
+ MSG_SET_TIME = 0x42b,
+/*20080827 to latest
+수수료
+Fee
+*/
+ MSG_CHARGE = 0x42c,
+/*20080827 to 20170906
+검색 된 아이템이 없습니다.
+20170913 to latest
+검색된 아이템이 없습니다.
+No items found in search.
+*/
+ MSG_NOTHING_SEARCH_ITEM = 0x42d,
+/*20080827 to latest
+현재 판매중인 아이템이 없습니다.
+Your Sale List is empty.
+*/
+ MSG_NOTHING_SEARCH_SELL_ITEM = 0x42e,
+/*20080827 to latest
+현재 구매중인 아이템이 없습니다.
+Your Purchase List is empty.
+*/
+ MSG_NOTHING_SEARCH_BUY_ITEM = 0x42f,
+/*20080827 to latest
+경매정보가 정확하지 않습니다.
+Auction Information is incorrect or incomplete.
+*/
+ MSG_ERROR_AUCTION_ITEM_INFO = 0x430,
+/*20080827 to latest
+경매에 등록할 아이템 정보가 없습니다.
+You must drag and drop an item from your Inventory into the Register Window to begin a new auction.
+*/
+ MSG_NOTHING_AUCTION_ITEM_INFO = 0x431,
+/*20080827 to latest
+이미 등록된 경매입니다.
+The auction has already been registered.
+*/
+ MSG_ERROR_ADD_AUCTION = 0x432,
+/*20080827 to latest
+제시가격
+Starting Bid
+*/
+ MSG_PRICE = 0x433,
+/*20080827 to latest
+구입희망가격
+Current Bid
+*/
+ MSG_PRICE2 = 0x434,
+/*20080827 to latest
+즉시구입가격
+Buy Now Price
+*/
+ MSG_PRICE3 = 0x435,
+/*20080827 to latest
+현재소지제니
+Your Current Zeny
+*/
+ MSG_PRICE4 = 0x436,
+/*20080827 to latest
+현재최고가격
+Highest Bid
+*/
+ MSG_PRICE5 = 0x437,
+/*20080827 to latest
+이전입찰가격
+Previous Bid
+*/
+ MSG_PRICE6 = 0x438,
+/*20080827 to latest
+추가입찰가격
+Next Bid
+*/
+ MSG_PRICE7 = 0x439,
+/*20080827 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BUY_ACTION_ITEM = 0x43a,
+/*20080827 to latest
+이 가격에 판매하시겠습니까?
+Would you like to sell this item?
+*/
+ MSG_SELL_ACTION_ITEM = 0x43b,
+/*20080827 to latest
+입찰하기
+Place Bid
+*/
+ MSG_BUY_AUCTION = 0x43c,
+/*20080827 to latest
+즉시구매하기
+Buy Now
+*/
+ MSG_BUY_AUCTION2 = 0x43d,
+/*20080827 to latest
+경매종료하기
+End the Auction
+*/
+ MSG_BUY_AUCTION3 = 0x43e,
+/*20080827 to latest
+재입찰하기
+Place another Bid
+*/
+ MSG_FINISH_AUCTION = 0x43f,
+/*20080827 to latest
+해당 경매에 대한 입찰이 성공했습니다.
+You have placed a bid.
+*/
+ MSG_RESULT_BUY_TRUE = 0x440,
+/*20080827 to latest
+해당 경매에 대한 입찰이 실패했습니다.
+You have failed to place a bid.
+*/
+ MSG_RESULT_BUY_FALSE = 0x441,
+/*20080827 to latest
+제니가 충분하지 않습니다.
+You do not have enough zeny.
+*/
+ MSG_RESULT_BUY_FALSE_MONEY = 0x442,
+/*20080827 to latest
+방어구
+Armors
+*/
+ MSG_EQUIP = 0x443,
+/*20080827 to latest
+카드
+Card
+*/
+ MSG_CARD = 0x444,
+/*20080827 to latest
+기타
+Other
+*/
+ MSG_ETC = 0x445,
+/*20080827 to latest
+경매번호
+Bid
+*/
+ MSG_AUCTION_NUM = 0x446,
+/*20080827 to latest
+검색
+Search
+*/
+ MSG_AUCTION_SEARCH = 0x447,
+/*20080827 to latest
+해당 경매를 종료했습니다.
+You have ended the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_TRUE = 0x448,
+/*20080827 to latest
+해당 경매를 종료 할 수 없습니다.
+You cannot end the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_FALSE = 0x449,
+/*20080827 to latest
+경매 번호가 정확하지 않습니다.
+Bid Number is incorrect.
+*/
+ MSG_RESULT_AUCTION_ID_FALSE = 0x44a,
+/*20080827 to latest
+받는이
+To
+*/
+ MSG_SENDER = 0x44b,
+/*20080827 to latest
+제 목
+Title
+*/
+ MSG_TITLE2 = 0x44c,
+/*20080827 to latest
+새 메일이 도착하였습니다.
+You have received a message in the mail.
+*/
+ MSG_NEW_MAIL = 0x44d,
+/*20080827 to latest
+검색중입니다.
+Searching...
+*/
+ MSG_SEARCHING_ITEM = 0x44e,
+/*20080827 to latest
+더 이상 경매 등록할 수 없습니다. 경매 등록은 최대 5개까지 가능합니다.
+You cannot register more than 5 items in an auction at a time.
+*/
+ MSG_AUCTION_ADD_OVER = 0x44f,
+/*20080827 to latest
+더 이상 경매 물품에 입찰할 수 없습니다. 경매 물품 입찰은 최대 5개까지 가능합니다.
+You cannot place more than 5 bids at a time.
+*/
+ MSG_RESULT_BUY_OVER = 0x450,
+/*20080827 to latest
+삭제하려는 메일에 수령하지 않은 아이템이 있습니다.
+Please accept all items from your mail before deleting.
+*/
+ MSG_MAIL_DELETE_ERROR = 0x451,
+/*20080827 to latest
+메일 제목을 입력하여 주십시오.
+Please enter a title.
+*/
+ MSG_MAIL_SEND_ERROR = 0x452,
+/*20080827 to latest
+/shopping : 클릭 한번으로 상점을 열고 상점이름 오른쪽 클릭으로 상점을 닫습니다 On Off
+/shopping: Enables you to open a shop with a single left-click and close your shop with a single right-click. On Off
+*/
+ MSG_EXPLAIN_SHOPPING = 0x453,
+/*20080827 to latest
+클릭 한번으로 상점을 열고 상점이름을 오른쪽 클릭해서 상점을 닫을수있습니다. [/sh ON]
+You can now open a shop with a single left-click and close your shop with a single right-click. [sh ON].
+*/
+ MSG_SHOPPING_ON = 0x454,
+/*20080827 to latest
+더블클릭 으로 상점을 열게됩니다. [/sh OFF]
+You can open a shop by double-clicking. [/sh OFF]
+*/
+ MSG_SHOPPING_OFF = 0x455,
+/*20080827 to latest
+메일을 보내려면, 제니 입력을 완료해야 합니다.
+Please enter zeny amount before sending mail.
+*/
+ MSG_MAIL_SEND_ERROR2 = 0x456,
+/*20080827 to latest
+경매 수수료가 부족합니다.
+You do not have enough zeny to pay the Auction Fee.
+*/
+ MSG_ADD_MONEY_FALSE = 0x457,
+/*20080827 to latest
+상태보기
+View Status
+*/
+ MSG_HOMUN_SHOWINFO = 0x458,
+/*20080827 to latest
+먹이주기
+Feed
+*/
+ MSG_HOMUN_FEEDING = 0x459,
+/*20080827 to latest
+대기
+Stand By
+*/
+ MSG_HOMUN_WAITING = 0x45a,
+/*20080827 to latest
+슈퍼노비스(남)
+Super Novice (Male)
+*/
+ MSG_JOB_SUPERNOVICE_M = 0x45b,
+/*20080827 to latest
+슈퍼노비스(여)
+Super Novice (Female)
+*/
+ MSG_JOB_SUPERNOVICE_F = 0x45c,
+/*20080827 to latest
+태권소년
+Taekwon Boy
+*/
+ MSG_JOB_TAEKWON_M = 0x45d,
+/*20080827 to latest
+태권소녀
+Taekwon Girl
+*/
+ MSG_JOB_TAEKWON_F = 0x45e,
+/*20080827 to latest
+권성(남)
+Taekwon Master (Male)
+*/
+ MSG_KWONSUNG_M = 0x45f,
+/*20080827 to latest
+권성(여)
+Taekwon Master (Female)
+*/
+ MSG_KWONSUNG_F = 0x460,
+/*20080827 to latest
+소울링커(남)
+Soul Linker (Male)
+*/
+ MSG_SOULLINGKER_M = 0x461,
+/*20080827 to latest
+소울링커(여)
+Soul Linker (Female)
+*/
+ MSG_SOULLINGKER_F = 0x462,
+/*20080827 to latest
+PC방요금제로 2개이상의 계정이 접속되고있습니다. 확인후 다시 사용하시기 바랍니다.
+Please check the connection, more than 2 accounts are connected with Internet Cafe Time Plan.
+*/
+ MSG_BAN_PC_IP_UNFAIR = 0x463,
+/*20080827 to latest
+귀하는 월정액 요금제 사용자 입니다. (남은기간 : %d일)
+Your account is using monthly payment. (Remaining day: %d day)
+*/
+ MSG_BILLING_1 = 0x464,
+/*20080827 to latest
+귀하는 정량 요금제 사용자 입니다. (남은시간 : %d시간 %분 %초)
+Your account is using time limited. (Remaining time: %d hour %d minute %d second)
+*/
+ MSG_BILLING_2 = 0x465,
+/*20080827 to latest
+해당 아이템은 메일에 첨부 할수 없는 아이템입니다.
+This item cannot be mailed.
+*/
+ MSG_MAIL_ITEM_ADD_FAILED = 0x466,
+/*20080827 to latest
+더이상 아이템을 가질수 없습니다. 아이템은 메일로 보관하겠습니다.
+You cannot accept any more items. Please try again later.
+*/
+ MSG_MAIL_ADD_ITEM_OVER_FAILURE = 0x467,
+/*20080827 to latest
+남성
+Male
+*/
+ MSG_PTSEX1 = 0x468,
+/*20080827 to latest
+여성
+Female
+*/
+ MSG_PTSEX2 = 0x469,
+/*20080827 to latest
+새로운 유저입니다
+New User.
+*/
+ MSG_PT_NEWUSER = 0x46a,
+/*20080827 to latest
+E-mail은 캐릭터를 지울때 필요합니다.
+E-mail address is required to delete a character.
+*/
+ MSG_PT_ACINFO = 0x46b,
+/*20080827 to latest
+정확한 형식으로 입력해 주세요.
+Please enter the correct information.
+*/
+ MSG_PT_ACINFO2 = 0x46c,
+/*20080827 to latest
+이 키를 사용하세요
+Please use this key.
+*/
+ MSG_PT_NEWKEYINFO = 0x46d,
+/*20080827 to latest
+정확한 카드 패스워드를 다시 입력해주세요
+Please enter the correct card password.
+*/
+ MSG_PT_FAIL_CARDPASS = 0x46e,
+/*20080827 to latest
+PT정보
+PT Info
+*/
+ MSG_PTID1 = 0x46f,
+/*20080827 to latest
+PT_ID는 %s
+PT_ID is %s
+*/
+ MSG_PTID2 = 0x470,
+/*20080827 to latest
+NUM_ID는 %s
+NUM_ID is %s
+*/
+ MSG_PTID3 = 0x471,
+/*20080827 to latest
+잊지않게 주의하세요
+Please don't forget this information.
+*/
+ MSG_PTID4 = 0x472,
+/*20080827 to latest
+1001
+*/
+ MSG_PT_ERROR_1001 = 0x473,
+/*20080827 to latest
+1002
+*/
+ MSG_PT_ERROR_1002 = 0x474,
+/*20080827 to latest
+1003
+*/
+ MSG_PT_ERROR_1003 = 0x475,
+/*20080827 to latest
+1004
+*/
+ MSG_PT_ERROR_1004 = 0x476,
+/*20080827 to latest
+1006
+*/
+ MSG_PT_ERROR_1006 = 0x477,
+/*20080827 to latest
+1007
+*/
+ MSG_PT_ERROR_1007 = 0x478,
+/*20080827 to latest
+1008
+*/
+ MSG_PT_ERROR_1008 = 0x479,
+/*20080827 to latest
+1009
+*/
+ MSG_PT_ERROR_1009 = 0x47a,
+/*20080827 to latest
+1012
+*/
+ MSG_PT_ERROR_1012 = 0x47b,
+/*20080827 to latest
+1013
+*/
+ MSG_PT_ERROR_1013 = 0x47c,
+/*20080827 to latest
+1014
+*/
+ MSG_PT_ERROR_1014 = 0x47d,
+/*20080827 to latest
+1015
+*/
+ MSG_PT_ERROR_1015 = 0x47e,
+/*20080827 to latest
+1019
+*/
+ MSG_PT_ERROR_1019 = 0x47f,
+/*20080827 to latest
+1020
+Navigation
+*/
+ MSG_PT_ERROR_1020 = 0x480,
+/*20080827 to latest
+1021
+*/
+ MSG_PT_ERROR_1021 = 0x481,
+/*20080827 to latest
+1023
+*/
+ MSG_PT_ERROR_1023 = 0x482,
+/*20080827 to latest
+1024
+*/
+ MSG_PT_ERROR_1024 = 0x483,
+/*20080827 to latest
+1025
+*/
+ MSG_PT_ERROR_1025 = 0x484,
+/*20080827 to latest
+1027
+*/
+ MSG_PT_ERROR_1027 = 0x485,
+/*20080827 to latest
+1028
+*/
+ MSG_PT_ERROR_1028 = 0x486,
+/*20080827 to latest
+10
+*/
+ MSG_PT_ERROR_10 = 0x487,
+/*20080827 to latest
+20
+*/
+ MSG_PT_ERROR_20 = 0x488,
+/*20080827 to latest
+40
+*/
+ MSG_PT_ERROR_40 = 0x489,
+/*20080827 to latest
+50
+*/
+ MSG_PT_ERROR_50 = 0x48a,
+/*20080827 to latest
+60
+*/
+ MSG_PT_ERROR_60 = 0x48b,
+/*20080827 to latest
+70
+*/
+ MSG_PT_ERROR_70 = 0x48c,
+/*20080827 to latest
+80
+*/
+ MSG_PT_ERROR_80 = 0x48d,
+/*20080827 to latest
+90
+*/
+ MSG_PT_ERROR_90 = 0x48e,
+/*20080827 to latest
+100
+*/
+ MSG_PT_ERROR_100 = 0x48f,
+/*20080827 to latest
+110
+*/
+ MSG_PT_ERROR_110 = 0x490,
+/*20080827 to latest
+30포인트를 받으시겠습니까?
+Do you want to receive 30 points?
+*/
+ MSG_PT_POINT1 = 0x491,
+/*20080827 to latest
+30포인트(5시간)이 충전되었습니다
+30 points (5 hours) have been added.
+*/
+ MSG_PT_POINT2 = 0x492,
+/*20080827 to latest
+감정되지 않은 아이템은 경매에 등록할 수 없습니다.
+You cannot register Unidentified Items in auctions.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE = 0x493,
+/*20080827 to latest
+소비 아이템은 경매에 등록할 수 없습니다.
+You cannot register this Consumable Item in an auction.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE2 = 0x494,
+/*20080827 to latest
+메일창을 열려면 카트창을 닫아 주십시요.
+Please close the Cart Window to open the Mail Window.
+*/
+ MSG_CLOSE_MERCHANTITEMWND = 0x495,
+/*20080827 to latest
+카트창을 열려면 메일창을 닫아 주십시요.
+Please close the Mail Window to open the Cart Window.
+*/
+ MSG_CLOSE_MAILWND = 0x496,
+/*20080827 to latest
+탄환이 장착되었습니다.
+Bullets have been equipped.
+*/
+ MSG_MSG_BULLET_EQUIPMENT_SUCCESS = 0x497,
+/*20080827 to latest
+메일이 반송되었습니다.
+The mail has been returned to sender.
+*/
+ MSG_MAIL_RETURN_SUCCESS = 0x498,
+/*20080827 to latest
+메일이 존재하지 않습니다.
+The mail no longer exists.
+*/
+ MSG_MAIL_RETURN_FAILURE = 0x499,
+/*20080827 to latest
+한시간 동안, 동일한 IP로 접속한 유저가 30건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+More than 30 players sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT_ALL = 0x49a,
+/*20080827 to latest
+한시간 동안, 동일한 IP로 10번 이상 접속되었습니다. 확인후 다시 사용하시기 바랍니다.
+More than 10 connections sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT = 0x49b,
+/*20080827 to latest
+게임을 재시작 하십시오
+Please restart the game.
+*/
+ MSG_GAMEGUARD_RESTART = 0x49c,
+/*20080827 to latest
+용병정보 - 아쳐타입
+Mercenary: Archer
+*/
+ MSG_MER_INFO_TYPE_ARCHER = 0x49d,
+/*20080827 to latest
+용병정보 - 검사타입
+Mercenary: Swordman
+*/
+ MSG_MER_INFO_TYPE_SWORDMAN = 0x49e,
+/*20080827 to latest
+용병정보 - 창병타입
+Mercenary: Spearman
+*/
+ MSG_MER_INFO_TYPE_LANCER = 0x49f,
+/*20080827 to latest
+삭제시간
+Expiration
+*/
+ MSG_LEFT_TIME = 0x4a0,
+/*20080827 to latest
+신뢰도
+Loyalty
+*/
+ MSG_MER_FRIENDLY = 0x4a1,
+/*20080827 to latest
+소환횟수
+Summons
+*/
+ MSG_MER_CALLCOUNT = 0x4a2,
+/*20080827 to latest
+Kill
+*/
+ MSG_MER_KILL = 0x4a3,
+/*20080827 to latest
+펫이 배가 고파서 당신을 원망하고 있다는 느낌이 든다.
+You can feel hatred from your pet for neglecting to feed it.
+*/
+ MSG_PET_STARVING = 0x4a4,
+/*20080827 to latest
+[POINT] 테이밍미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You earned %d Taming Mission Ranking Points, giving you a total of %d points.
+*/
+ MSG_GANGSI_POINT = 0x4a5,
+/*20080827 to latest
+[테이밍미션] Target Monster : %s
+[Taming Mission] Target Monster: %s
+*/
+ MSG_GANGSI_MISSION = 0x4a6,
+/*20080827 to latest
+/hunting : 사냥 목록을 보여줍니다.
+/hunting: You can check the your hunting list.
+*/
+ MSG_EXPLAIN_HUNTING = 0x4a7,
+/*20080827 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s는 몇 스킬 찍으셨나요?
+[Angel's Question] Please tell me, how many %s skills do you have?
+*/
+ MSG_DEATH_Q01 = 0x4a8,
+/*20080827 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 소지하시고있는 제니를 십만으로 나누면 얼마가 되시나요?
+[Angel's Question] Please tell me, how much zeny you'll have if you divide it by 100,000?
+*/
+ MSG_DEATH_Q02 = 0x4a9,
+/*20080827 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 오늘이 몇일이신지 아시나요?
+[Angel's Question] Please tell me, what is today's date?
+*/
+ MSG_DEATH_Q03 = 0x4aa,
+/*20080827 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s은 지금 몇이신가요?
+[Angel's Question] Please tell me, how many %s do you have?
+*/
+ MSG_DEATH_Q04 = 0x4ab,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 슈노, 태권계열, 무낙계열을 담당하고있는 SiYeon씨의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in SiYeon's name?
+*/
+ MSG_DEATH_Q05 = 0x4ac,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 귀엽고 어여쁜 라그나로크의 히로인 Munak의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Munak's name?
+*/
+ MSG_DEATH_Q06 = 0x4ad,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 제가 어여뻐하는 Bongun의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Bongun's name?
+*/
+ MSG_DEATH_Q07 = 0x4ae,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 저희가 존재하는 온라인세계 Ragnarok의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, Ragnarok?
+*/
+ MSG_DEATH_Q08 = 0x4af,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 언제나 Online상태인 천사동료들은 큰힘이 되어주죠. Online의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, online?
+*/
+ MSG_DEATH_Q09 = 0x4b0,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 죽음도 두려워하지않는 기사들을 상징하는 단어인 Death의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, death?
+*/
+ MSG_DEATH_Q10 = 0x4b1,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 기사들은 너무 멋진다고 생각해요. Knight의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, knight?
+*/
+ MSG_DEATH_Q11 = 0x4b2,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 중력을 뜻하는 단어인 Gravity의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, gravity?
+*/
+ MSG_DEATH_Q12 = 0x4b3,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 어둠속에서도 밝게 사는게 중요하지요. Dark의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, dark?
+*/
+ MSG_DEATH_Q13 = 0x4b4,
+/*20080827 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 뭐든지 수집하는 Collector의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, collecter?
+*/
+ MSG_DEATH_Q14 = 0x4b5,
+/*20080827 to latest
+[천사의대답] 소녀에게 정확한 사실을 가르쳐주셔서 감사하옵니다.
+[Angel's Answer] Thank you for letting me know~
+*/
+ MSG_DEATH_R01 = 0x4b6,
+/*20080827 to latest
+[천사의대답] 사랑스러우신 분이시군요. 소녀 감탄했사옵니다.
+[Angel's Answer] I'm very pleased with your answer. You are a splendid adventurer.
+*/
+ MSG_DEATH_R02 = 0x4b7,
+/*20080827 to latest
+[천사의대답] 소녀 실망했사옵니다.
+[Angel's Answer] You've disappointed me...
+*/
+ MSG_DEATH_R05 = 0x4b8,
+/*20080827 to latest
+[POINT] 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You earned %d Ranking Points, giving you a total of %d Ranking Points.
+*/
+ MSG_DEATH_POINT = 0x4b9,
+/*20080827 to latest
+[%s]의 소지 캐시 : %d 캐시
+[%s]'s Points: %d Points
+*/
+ MSG_POINT_SHOP = 0x4ba,
+/*20080827 to latest
+선택하지 않은 캐릭터는 삭제 됩니다. 완료하시겠습니까?
+Unselected Characters will be deleted. Continue?
+*/
+ MSG_CONFIRM_SELECT_CHARACTERS = 0x4bb,
+/*20080827 to latest
+9개 이상 선택하실 수 없습니다.
+You cannot select more than 8.
+*/
+ MSG_ERROR_SELECT_CHARACTERS = 0x4bc,
+/*20080827 to latest
+캐릭터명을 '%s' (으)로 변경하시겠습니까?
+Do you want to change your name to '%s'?
+*/
+ MSG_CONFIRM_TO_CHANGE_NAME = 0x4bd,
+/*20080827 to latest
+캐릭터명이 성공적으로 변경되었습니다.
+Character Name has been changed successfully.
+*/
+ MSG_CHANGE_NAME_SUCCESS = 0x4be,
+/*20080827 to latest
+캐릭터명 변경이 실패하였습니다.
+You have failed to change this character's name.
+*/
+ MSG_CHANGE_NAME_FAILURE = 0x4bf,
+/*20080827 to latest
+한 번에 한 종류의 아이템만 구매할 수 있습니다.
+You can purchase only one kind of item at a time.
+*/
+ MSG_CAN_BUY_ONLY_ONEITEM = 0x4c0,
+/*20080827 to latest
+캐릭터가 한개도 선택되지 않았습니다. 반드시 한개 이상의 캐릭터를 선택하여야 합니다.
+No characters were selected. You must select at least one character.
+*/
+ MSG_NO_SELECT_CHARACTERS = 0x4c1,
+/*20080827 to latest
+이미 캐릭터명을 변경한 적이 있습니다. 더 이상 변경 할 수 없습니다.
+This character's name has already been changed. You cannot change a character's name more than once.
+*/
+ MSG_ALREADY_CHANGED_NAME = 0x4c2,
+/*20080827 to latest
+사용자 정보가 정확하지 않습니다.
+User Information is not correct.
+*/
+ MSG_NOTREGISTED_USER = 0x4c3,
+/*20080827 to latest
+다른 사용자가 같은 캐릭터 명을 먼저 사용하였습니다. 다른 캐릭터명을 사용하여 주십시요.
+Another user is using this character name, so please select another one.
+*/
+ MSG_DUPLICATED_CHAR_NAME = 0x4c4,
+/*20080827 to latest
+파티장 권한이 없어 파티원을 소환하지 못했습니다.
+The party member was not summoned because you are not the party leader.
+*/
+ MSG_CANNOT_PARTYCALL = 0x4c5,
+/*20080827 to latest
+현재 맵에는 소환될 파티원이 존재하지 않습니다.
+There is no party member to summon in the current map.
+*/
+ MSG_NO_PARTYMEM_ON_THISMAP = 0x4c6,
+/*20080827 to latest
+이 지역에선 보스몬스터의 흔적을 찾을 수가 없습니다.
+You cannot find any trace of a Boss Monster in this area.
+*/
+ MSG_NOTFIND_BOSSMON = 0x4c7,
+/*20080827 to latest
+보스 몬스터 '%s'(이)가 %d시간 %d분 후에 등장합니다.
+Boss Monster, '%s' will appear in %02d hour(s) and %02d minute(s).
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON = 0x4c8,
+/*20080827 to latest
+보스 몬스터 '%s'의 위치가 미니맵에 표시됩니다.
+The location of Boss Monster, '%s', will be displayed on your Mini-Map.
+*/
+ MSG_SHOW_POSITION_OF_BOSSMON = 0x4c9,
+/*20080827 to 20101026
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20101102 to 20110330
+'%s'를 개봉 하시겠습니까? ^ff0000상자를 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 한번 개봉 된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20110405 to latest
+'%s'를 개봉 하시겠습니까? ^ff0000상자를 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 한번 개봉 된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+Do you want to open '%s'? Once opened, the contents cannot be moved to other locations aside from the Kafra Storage. The item effect isn't doubled, even if the same items are used more than once.
+*/
+ MSG_CONFIRM_TO_OPEN_CASH_ITEM = 0x4ca,
+/*20080827 to latest
+NPC가 존재하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the NPC does not exist.
+*/
+ MSG_BUY_CASH_FAIL_NPC = 0x4cb,
+/*20080827 to latest
+부분 유료화 시스템이 정상 작동하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Kafra Shop System is not working correctly.
+*/
+ MSG_BUY_CASH_FAIL_SYSTEM = 0x4cc,
+/*20080827 to latest
+교환중에는 아이템을 구매 할 수 없습니다.
+You cannot purchase items while you are in a trade.
+*/
+ MSG_BUY_CASH_FAIL_EXCHANGE = 0x4cd,
+/*20080827 to latest
+아이템 정보가 정확하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Item Information was incorrect.
+*/
+ MSG_BUY_CASH_FAIL_ITEM_ID = 0x4ce,
+/*20080827 to latest
+ STR이 향상되었습니다.
+STR has increased.
+*/
+ MSG_ENST_STR = 0x4cf,
+/*20080827 to latest
+ STR이 원래대로 돌아왔습니다.
+STR has returned to normal.
+*/
+ MSG_DSST_STR = 0x4d0,
+/*20080827 to latest
+ AGI이 향상되었습니다.
+AGI has increased.
+*/
+ MSG_ENST_AGI = 0x4d1,
+/*20080827 to latest
+ AGI이 원래대로 돌아왔습니다.
+AGI has returned to normal.
+*/
+ MSG_DSST_AGI = 0x4d2,
+/*20080827 to latest
+ VIT이 향상되었습니다.
+VIT has increased.
+*/
+ MSG_ENST_VIT = 0x4d3,
+/*20080827 to latest
+ VIT이 원래대로 돌아왔습니다.
+VIT has returned to normal.
+*/
+ MSG_DSST_VIT = 0x4d4,
+/*20080827 to latest
+ INT이 향상되었습니다.
+INT has increased.
+*/
+ MSG_ENST_INT = 0x4d5,
+/*20080827 to latest
+ INT이 원래대로 돌아왔습니다.
+INT has returned to normal.
+*/
+ MSG_DSST_INT = 0x4d6,
+/*20080827 to latest
+ DEX이 향상되었습니다.
+DEX has increased.
+*/
+ MSG_ENST_DEX = 0x4d7,
+/*20080827 to latest
+ DEX이 원래대로 돌아왔습니다.
+DEX has returned to normal.
+*/
+ MSG_DSST_DEX = 0x4d8,
+/*20080827 to latest
+ LUK이 향상되었습니다.
+LUK has increased.
+*/
+ MSG_ENST_LUK = 0x4d9,
+/*20080827 to latest
+ LUK이 원래대로 돌아왔습니다.
+LUK has returned to normal.
+*/
+ MSG_DSST_LUK = 0x4da,
+/*20080827 to latest
+ 회피율이 향상되었습니다.
+Flee Rate (Flee) has increased.
+*/
+ MSG_ENST_AVOIDANCE = 0x4db,
+/*20080827 to latest
+ 회피율이 원래대로 돌아왔습니다.
+Flee Rate has returned to normal.
+*/
+ MSG_DSST_AVOIDANCE = 0x4dc,
+/*20080827 to latest
+ 명중률이 향상되었습니다.
+Accuracy Rate (Hit) has increased.
+*/
+ MSG_ENST_HIT = 0x4dd,
+/*20080827 to latest
+ 명중률이 원래대로 돌아왔습니다.
+Accuracy Rate has returned to normal.
+*/
+ MSG_DSST_HIT = 0x4de,
+/*20080827 to latest
+ 크리티컬 확률이 향상되었습니다.
+Critical Attack (Critical) has increased.
+*/
+ MSG_ENST_CRITICALSUCCESSVALUE = 0x4df,
+/*20080827 to latest
+ 크리티컬 확률이 원래대로 돌아왔습니다.
+Critical Attack has returned to normal.
+*/
+ MSG_DSST_CRITICALSUCCESSVALUE = 0x4e0,
+/*20080827 to 20111021
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.5배로 증가합니다.
+20111025 to 20111101
+ 30분간 얻을 수 있는 경험치가 75%% 증가합니다.
+20111102 to latest
+ 30분간 얻을 수 있는 경험치가 50%% 증가합니다.
+You will receive 1.5 times more EXP from hunting monsters for the next 30 minutes.
+*/
+ MSG_PLUSEXP = 0x4e1,
+/*20080827 to latest
+ 30분내 사망시 1회에 한해 경험치 감소가 일어나지 않습니다.
+This character will not receive any EXP penalty if killed within the next 30 minutes.
+*/
+ MSG_DDEATHPENALTY = 0x4e2,
+/*20080827 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 30분간 2배로 증가합니다.
+Regular item drops from monsters will be doubled for the next 30 minutes.
+*/
+ MSG_RECEIVEITEM = 0x4e3,
+/*20080827 to latest
+ 10분간 맵 내에 출현 가능한 보스 몬스터에 대한 정보를 안내해 드립니다.
+Boss Monster Map Information for the next 10 minutes.
+*/
+ MSG_BOSS_ALARM = 0x4e4,
+/*20080827 to 20100629
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20100701 to 20101026
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 %s아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20101102 to 20101130
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 정말로 %s아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20101207 to 20110330
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20110405 to 20120618
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+20120626 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+Do you really want to purchase this item? %d points will be deducted from your total Kafra Credit Points.
+*/
+ MSG_BUY_RECONFIRM = 0x4e5,
+/*20080827 to latest
+ 캐시가 부족합니다.
+ You do not have enough Kafra Credit Points.
+*/
+ MSG_BUY_CASH_FAIL_MONEY = 0x4e6,
+/*20080827 to latest
+ ^ff0000파기일시: %s^000000
+ ^ff0000Expiration Date: %s^000000
+*/
+ MSG_NOTICE_TO_DELETE_TIME = 0x4e7,
+/*20080827 to latest
+ '%s'아이템의 사용시간이 %d분 남았습니다.
+ The '%s' item will disappear in %d minutes.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e8,
+/*20080827 to latest
+ 1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+ '%s' item will be deleted from the Inventory in 1 minute.
+*/
+ MSG_LAST_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e9,
+/*20080827 to latest
+ '%s'아이템이 인벤토리에서 삭제되었습니다.
+ '%s' item has been deleted from the Inventory.
+*/
+ MSG_NOTICE_TO_DELETE_ITEM = 0x4ea,
+/*20080827 to latest
+Input Number
+*/
+ MSG_INPUT_NUMBER = 0x4eb,
+/*20080827 to latest
+%m월 %d일 %H시 %M분
+%m/%d %H:%M
+*/
+ MSG_TIME_TYPE2 = 0x4ec,
+/*20080827 to latest
+보스 몬스터 '%s'(이)가 잠시 후에 등장합니다.
+Boss Monster '%s' will appear within 1 minute.
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON2 = 0x4ed,
+/*20080827 to latest
+용병 스킬목록
+Mercenary Soldier Skill List
+*/
+ MSG_MER_SKILLLIST = 0x4ee,
+/*20080827 to latest
+블랙젬스톤 1개와 백만제니를 소모하는 마법의 실행에 동의합니까?
+Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+*/
+ MSG_DA_EXP_ACCEPT = 0x4ef,
+/*20080827 to latest
+[POINT] 콜렉터랭킹 포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have gained %d Collector Rank Points; you now have a total of %d Collector Rank Points.
+*/
+ MSG_COLLECTOR_POINT = 0x4f0,
+/*20080827 to latest
+[콜렉터랭킹] Target Item : %s
+[Collector Rank] Target Item: %s
+*/
+ MSG_COLLECTOR_MISSION = 0x4f1,
+/*20080827 to latest
+용병 사용시간이 만료되었습니다.
+The mercenary contract has expired.
+*/
+ MSG_MER_FINISH = 0x4f2,
+/*20080827 to latest
+용병이 사망하였습니다.
+The mercenary has died.
+*/
+ MSG_MER_DIE = 0x4f3,
+/*20080827 to latest
+용병이 해고되었습니다.
+You have released the mercenary.
+*/
+ MSG_MER_RETIRE = 0x4f4,
+/*20080827 to latest
+용병이 도망갔습니다.
+The mercenary has run away.
+*/
+ MSG_MER_RUNAWAY = 0x4f5,
+/*20080827 to latest
+ '%s'아이템의 사용시간이 %d초 남았습니다.
+ The '%s' item will disappear in %d seconds.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME2 = 0x4f6,
+/*20080827 to latest
+PC방 프리미엄 서비스 : 경험치 %d%% 증가, 사망 페널티 %d%% 감소, 드롭율 %d%% 증가
+IP Bonus: EXP/JEXP %d%%, Death Penalty %d%%, Item Drop %d%%
+*/
+ MSG_PCBANG_EVENT = 0x4f7,
+/*20080827 to latest
+24시간 이후에 시도하세요
+Symbols in Character Names are forbidden.
+*/
+ MSG_LIMIT_CHAR_DELETE = 0x4f8,
+/*20080827 to latest
+용병이 사용자 인공지능으로 동작합니다.
+Mercenary will follow custom AI.
+*/
+ MSG_MER_USERAI_ON = 0x4f9,
+/*20080827 to latest
+용병이 기본 인공지능으로 동작합니다.
+Mercenary will follow basic AI.
+*/
+ MSG_MER_USERAI_OFF = 0x4fa,
+/*20080827 to latest
+ %s님의
+ %s's
+*/
+ MSG_CHARACTER_NAME = 0x4fb,
+/*20080827 to latest
+%s님이 %s 아이템을 획득하셨습니다.
+%s has acquired %s.
+*/
+ MSG_ITEM_PICKUP_PARTY = 0x4fc,
+/*20080827 to latest
+공개 채팅 메시지 표시
+Public Chat Display
+*/
+ MSG_VIEW_CHAT_MSG = 0x4fd,
+/*20080827 to latest
+귓속말 채팅 메시지 표시
+Whisper Display
+*/
+ MSG_VIEW_WHISPER_MSG = 0x4fe,
+/*20080827 to latest
+파티 채팅 메시지 표시
+Party Chat Display
+*/
+ MSG_VIEW_PARTY_MSG = 0x4ff,
+/*20080827 to latest
+길드 채팅 메시지 표시
+Guild Chat Display
+*/
+ MSG_VIEW_GUILD_MSG = 0x500,
+/*20080827 to latest
+아이템 획득/드롭 메시지 표시
+Item Get/Drop Message Display
+*/
+ MSG_VIEW_GET_ITEM_MSG = 0x501,
+/*20080827 to latest
+장비 장착/해제 메시지 표시
+Equipment On/Off Message Display
+*/
+ MSG_VIEW_EQUIP_MSG = 0x502,
+/*20080827 to latest
+상태이상 메시지 표시
+Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_MSG = 0x503,
+/*20080827 to latest
+파티원의 주요 아이템 획득 메시지 표시
+Party Member's Obtained Item Message Display
+*/
+ MSG_VIEW_GET_ITEM_PARTY_MSG = 0x504,
+/*20080827 to latest
+파티원의 상태이상 메시지 표시
+Party Member's Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_PARTY_MSG = 0x505,
+/*20080827 to latest
+스킬 사용 실패 메시지 표시
+Skill Failure Message Display
+*/
+ MSG_VIEW_FAIL_SKILL_MSG = 0x506,
+/*20080827 to latest
+파티 설정 메시지 표시
+Party Configuration Message Display
+*/
+ MSG_VIEW_PARTY_SETUP_MSG = 0x507,
+/*20080827 to latest
+장비 손상 메시지 표시
+Damaged Equipment Message Display
+*/
+ MSG_VIEW_DAMAGED_EQUIP_MSG = 0x508,
+/*20080827 to latest
+배틀 메시지 창 표시 정보
+Battle Message Window Display
+*/
+ MSG_BATTLE_CHAT_WND_OPTION = 0x509,
+/*20080827 to latest
+[%s]의 소지 한코인 : %d 한코인
+[%s]'s Han Coin: %d Han Coin
+*/
+ MSG_POINT_SHOP_NHN = 0x50a,
+/*20080827 to latest
+일반 메시지
+Public Log
+*/
+ MSG_ST_CHAT = 0x50b,
+/*20080827 to latest
+배틀 메시지
+Battle Log
+*/
+ MSG_BT_CHAT = 0x50c,
+/*20080827 to latest
+휴대폰 인증.
+Mobile Authentication
+*/
+ MSG_PHONE_CONFIRM = 0x50d,
+/*20080827 to latest
+읽기
+Read
+*/
+ MSG_BOOK_READ = 0x50e,
+/*20080827 to latest
+자동낭독
+Auto Read
+*/
+ MSG_BOOK_AUTOREAD = 0x50f,
+/*20080827 to latest
+책갈피
+Bookmark
+*/
+ MSG_BOOK_KEEP = 0x510,
+/*20080827 to latest
+이전페이지
+Previous
+*/
+ MSG_BOOK_PREV = 0x511,
+/*20080827 to latest
+다음페이지
+Next
+*/
+ MSG_BOOK_NEXT = 0x512,
+/*20080827 to latest
+닫기
+Close
+*/
+ MSG_BOOK_CLOSE = 0x513,
+/*20080827 to latest
+%s 장비가 손상되었습니다.
+%s's Equipment has been damaged.
+*/
+ MSG_DAMAGED_EQUIP = 0x514,
+/*20080827 to latest
+%s님의 %s 손상되었습니다.
+%s's %s was damaged.
+*/
+ MSG_DAMAGED_EQUIP_PARTY = 0x515,
+/*20080827 to latest
+무기가
+Weapon
+*/
+ MSG_DAMAGED_WEAPON = 0x516,
+/*20080827 to latest
+갑옷이
+Armor
+*/
+ MSG_DAMAGED_BODY = 0x517,
+/*20080827 to latest
+스킬레벨이 부족합니다. 파티가입 불능
+Insufficient Skill Level for joining a Party
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5_2 = 0x518,
+/*20080827 to latest
+[%s]의 무료 캐시 : %d 캐시
+[%s]'s Free Cash: %d Cash
+*/
+ MSG_POINT_SHOP2 = 0x519,
+/*20080827 to latest
+무료 캐시 사용 :
+Use Free Cash:
+*/
+ MSG_USE_FREE_POINT = 0x51a,
+/*20080827 to latest
+캐시
+Cash
+*/
+ MSG_CASH = 0x51b,
+/*20080827 to latest
+http://payment.ro.hangame.com/index.asp
+*/
+ MSG_SETTLE_WEB_URL_HANGAME = 0x51c,
+/*20080827 to 20090603
+그라비티 회원 정보동의를 하셔야 사용할수있습니다.
+20090605 to latest
+그라비티 회원 정보동의를 하셔야 사용할 수 있습니다.
+You need to accept the Privacy Policy from Gravity in order to use the service.
+*/
+ MSG_BAN_GRAVITY_MEM_AGREE = 0x51d,
+/*20080827 to latest
+이용약관에 동의를 하셔야 본 서비스를 이용하실 수 있습니다.
+You need to accept the User Agreement in order to use the service.
+*/
+ MSG_BAN_GAME_MEM_AGREE = 0x51e,
+/*20080827 to latest
+입력하신 아이디와 비밀번호가 등록된 정보와 일치하지 않습니다.
+Incorrect or nonexistent ID.
+*/
+ MSG_BAN_HAN_VALID = 0x51f,
+/*20080827 to 20100629
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20100701 to 20101026
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 %s아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20101102 to 20101130
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외됩니다.^000000 정말로 %s아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20101207 to 20110330
+ ^ff0000본 아이템을 구매 후 개봉하시면 청약 철회 및 환불 대상에서 제외됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20110405 to 20120618
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20120626 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+Do you really want to purchase these items? You will spend %d Regular Cash Points and %d Free Cash Points.
+*/
+ MSG_BUY_RECONFIRM2 = 0x520,
+/*20080827 to latest
+%d시간이 경과하였습니다.
+%d hour(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME1 = 0x521,
+/*20080827 to latest
+%d시간 %d분이 경과하였습니다.
+%d hour(s) %d minute(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME2 = 0x522,
+/*20080827 to latest
+게임을 종료하세요, 경험치 및 모든게 50%로 조정됩니다
+Please stop playing the game, and take a break. Exp and other features will be reduced to 50%.
+*/
+ MSG_WARNING_MSG1 = 0x523,
+/*20080827 to latest
+불건전 시간대에 접어들었습니다. 게임을 종료하세요, 경험치 및 모든게 0%로 조정됩니다
+Please stop playing the game since you'll need to rest. Exp and other features will be fixed to 0%.
+*/
+ MSG_WARNING_MSG2 = 0x524,
+/*20080827 to latest
+퀘스트 목록
+Quest List
+*/
+ MSG_QUESTWIN = 0x525,
+/*20080827 to latest
+RO SHOP
+*/
+ MSG_RO_SHOP = 0x526,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약이 알수없는 이유로 실패 하였습니다.
+Memorial Dungeon, '%s' is booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN = 0x527,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약이 예약중복으로 실패 하였습니다.
+Failed to book Memorial Dungeon, '%s'.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE = 0x528,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약이 권한문제로 실패 하였습니다.
+Memorial Dungeon, '%s' is already booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT = 0x529,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약이 중복생성요청으로 실패하였습니다.
+Memorial Dungeon, '%s' is created.
+ Please enter in 5 minutes.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST = 0x52a,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약취소가 실패 하였습니다.
+Failed to create Memorial Dungeon, '%s'.
+ Please try again.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_FAIL = 0x52b,
+/*20080827 to latest
+상대방이 파티 초대 거부 상태입니다.
+The character blocked the party invitation.
+*/
+ MSG_JOINMSG_REFUSE = 0x52c,
+/*20080827 to latest
+모든 파티 초대를 거부합니다.
+Block all party invitations.
+*/
+ MSG_INVITE_PARTY_REFUSE = 0x52d,
+/*20080827 to latest
+모든 파티 초대를 수락합니다.
+Allow all party invitations.
+*/
+ MSG_INVITE_PARTY_ACCEPT = 0x52e,
+/*20080827 to latest
+착용하시면 이 아이템은 영구 귀속됩니다. 착용하시겠습니까?
+This item will be permanently bound to this character once it is equipped. Do you really want to equip this item?
+*/
+ MSG_YOURITEM_EQUIP = 0x52f,
+/*20080827 to latest
+%s 아이템이 귀속되었습니다.
+%s is now permanently bound to this character.
+*/
+ MSG_YOURITEM_EQUIPED = 0x530,
+/*20080827 to latest
+캐시가 부족합니다. 무료 캐시 포인트를 입력해 주시기 바랍니다.
+You do not have enough Kafra Credit Points. Please enter whether you have free credit points.
+*/
+ MSG_BUY_TO_FREE_POINT = 0x531,
+/*20080827 to latest
+파티 가입요청
+Request to Join Party
+*/
+ MSG_REQ_JOIN_PARTY3 = 0x532,
+/*20080827 to latest
+공성 정보 메시지 표시
+Display WOE Info
+*/
+ MSG_VIEW_SIEGE_INFO_MSG = 0x533,
+/*20080827 to latest
+메모리얼던젼 '%s'의 예약이 취소 되었습니다.
+Memorial Dungeon %s's reservation has been canceled.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_SUCCESS = 0x534,
+/*20080827 to latest
+메모리얼던젼 '%s' 생성에 실패하였습니다. 다시 시도 하세요.
+Failed to create Memorial Dungeon %s. Please try again.
+*/
+ MSG_MDUNGEON_CREATE_FAIL = 0x535,
+/*20080827 to latest
+이 장소에서는 사용할 수 없는 스킬입니다.
+This skill cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_SKILL_AREA = 0x536,
+/*20080827 to latest
+이 장소에서는 사용할 수 없는 아이템입니다.
+This item cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_USEITEM_AREA = 0x537,
+/*20080827 to latest
+메모리얼 던전
+Memorial Dungeon
+*/
+ MSG_MEMORIAL_DUN = 0x538,
+/*20080827 to latest
+%s 대기중
+%s in Standby
+*/
+ MSG_MEMORIAL_DUN_WAITING = 0x539,
+/*20080827 to latest
+%s 입장 가능
+%s Available
+*/
+ MSG_MEMORIAL_DUN_READY = 0x53a,
+/*20080827 to latest
+%s 진행중
+%s in Progress
+*/
+ MSG_MEMORIAL_DUN_IN = 0x53b,
+/*20080827 to latest
+시간 안에 입장하지 않아 메모리얼 던전이 사라졌습니다.
+No one entered the Memorial Dungeon within its duration; the dungeon has disappeared.
+*/
+ MSG_MEMORIAL_DUN_OUT1 = 0x53c,
+/*20080827 to latest
+이용하시려면 이용 신청을 처음부터 다시 해주시기 바랍니다.
+Please apply for dungeon entry again to play in this dungeon.
+*/
+ MSG_MEMORIAL_DUN_OUT2 = 0x53d,
+/*20080827 to latest
+대기 순위 : ^ff0000%d^000000
+Your Standby Priority: ^ff0000%d^000000
+*/
+ MSG_MEMORIAL_DUN_PRIORITY = 0x53e,
+/*20080827 to latest
+^ff0000%s^000000 내에 입장하지 않을 경우 신청하신 던전이 삭제 됩니다.
+The requested dungeon will be removed if you do not enter within ^ff0000%s^000000.
+*/
+ MSG_MEMORIAL_DUN_NOTIFY = 0x53f,
+/*20080827 to latest
+던전 미션 제한 시간 :
+Dungeon Mission Time Limit:
+*/
+ MSG_MEMORIAL_DUN_NOTIFY2 = 0x540,
+/*20080827 to latest
+메모리얼 던전 예약이 취소되었습니다.
+The Memorial Dungeon reservation has been canceled.
+*/
+ MSG_MEMORIAL_DUN_CANCEL = 0x541,
+/*20080827 to latest
+메모리얼 던전이 유지 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon duration expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_LIVE_TIME_OUT = 0x542,
+/*20080827 to latest
+메모리얼 던전이 입장 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon's entry time limit expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_ENTER_TIME_OUT = 0x543,
+/*20080827 to latest
+메모리얼 던전이 삭제 되었습니다.
+The Memorial Dungeon has been removed.
+*/
+ MSG_MEMORIAL_DUN_DESTROY_REQUEST = 0x544,
+/*20080827 to 20191218
+메모리얼 던전에 시스템 오류가 발생하였습니다. 정상적인 게임 진행을 위해 재접속을 해주십시오.
+A system error has occurred in the Memorial Dungeon. Please relog in to the game to continue playing.
+20191224 to latest
+메모리얼 던전에 통신 장애가 발생하였습니다. 정상적인 게임 진행을 위해 잠시 후, 재접속을 해주십시오.
+*/
+ MSG_MEMORIAL_DUN_ERROR = 0x545,
+/*20080827 to latest
+사용할 수 없는 슬롯입니다.
+This slot is not usable.
+*/
+ MSG_FR_INVALID_SLOT = 0x546,
+/*20080827 to latest
+Base Level이 15를 넘었습니다.
+Your Base Level is over 15.
+*/
+ MSG_FR_BASELVL = 0x547,
+/*20080827 to latest
+Job Level이 15를 넘었습니다.
+Your Job Level is over 15.
+*/
+ MSG_FR_INVALID_JOBLV = 0x548,
+/*20080827 to latest
+해당슬롯 캐릭터에 직업군의 상인이므로 게임을 할 수 없습니다.
+You cannot play the Merchant class character in this slot.
+*/
+ MSG_FR_JOB = 0x549,
+/*20080827 to latest
+추후 사용예정
+Not Yet Implemented
+*/
+ MSG_FR_MAP = 0x54a,
+/*20080827 to latest
+만들수 있는 케릭터 슬롯이 아닙니다.
+You are not eligible to open the Character Slot.
+*/
+ MSG_FR_ERR_MKCHAR_INVALID_SLOT = 0x54b,
+/*20080827 to latest
+삭제할 수 없는 케릭터 입니다.
+This character cannot be deleted.
+*/
+ MSG_FR_ERR_DELCHAR_INVALID_SLOT = 0x54c,
+/*20080827 to latest
+상대방의 장비창이 공개되어 있지 않습니다.
+This character's equipment information is not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSED = 0x54d,
+/*20080827 to latest
+장비창을 공개하지 않습니다.
+Equipment information not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSE = 0x54e,
+/*20080827 to latest
+장비창을 공개합니다.
+Equipment information open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_ACCEPT = 0x54f,
+/*20080827 to latest
+(%s)님 장비창 보기
+Check %s's Equipment Info
+*/
+ MSG_REQ_VIEW_OTHERUSER = 0x550,
+/*20080827 to latest
+%s의 장착아이템
+'%s's Equipment
+*/
+ MSG_OTHERUSER_EQUIPED_ITEM = 0x551,
+/*20080827 to latest
+장비창 공개
+Show Equip
+*/
+ MSG_OPEN_EQUIPED_ITEM = 0x552,
+/*20080827 to latest
+프리미엄 서비스를 이용해 주시기 바랍니다.
+This service is only available for premium users.
+*/
+ MSG_NEED_PREMIUM_SERVICE = 0x553,
+/*20080827 to latest
+무료 사용자는 최대 50000제니까지 소유할 수 있습니다.
+Free Trial users can only hold up to 50,000 zeny.
+*/
+ MSG_FR_INVALID_MONEY = 0x554,
+/*20080827 to latest
+전장채팅 상태가 되었습니다.
+Battlefield Chat has been activated.
+*/
+ MSG_BATTLECHAT_ON = 0x555,
+/*20080827 to latest
+전장채팅 상태가 해제되었습니다.
+Battlefield Chat has been deactivated.
+*/
+ MSG_BATTLECHAT_OFF = 0x556,
+/*20080827 to latest
+용병정보 - 몬스터타입
+Mercenary Info - Monster Type
+*/
+ MSG_MER_INFO_TYPE_MONSTER = 0x557,
+/*20080827 to latest
+전체 맵 보기
+World Map
+*/
+ MSG_RO_MAP = 0x558,
+/*20080827 to latest
+메모리얼던젼이 CLOSE 상태입니다.
+The Memorial Dungeon is now closed.
+*/
+ MSG_MEMORIAL_DUN_CLOSE = 0x559,
+/*20080827 to latest
+^ff0000^ff0000용병을 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+^ff0000Deleting a Mercenary Soldier^000000 will also delete his growth history. Do you really want to proceed with the deletion?
+*/
+ MSG_DELETE_MER = 0x55a,
+/*20080827 to latest
+메모리얼던젼이 OPEN 상태입니다.
+The Memorial Dungeon is now open.
+*/
+ MSG_MEMORIAL_DUN_OPEN = 0x55b,
+/*20080827 to latest
+위의 계정은 아직 통신 안전 키에 연결되지 않았습니다. 먼저 안전 키를 해제하신 뒤 게임에 접속해 주십시오.
+This account has not been confirmed by connecting to the safe communication key. Please connect to the key first, and then log into the game.
+*/
+ MSG_PHONE_BLOCK = 0x55c,
+/*20080827 to latest
+한 아이피로 접속 가능한 유저수를 초과하였습니다.
+The number of accounts connected to this IP has exceeded the limit.
+*/
+ MSG_BAN_PC_IP_LIMIT_ACCESS = 0x55d,
+/*20080827 to latest
+새로운 퀘스트를 받았습니다
+You have received a new quest.
+*/
+ MSG_QUESTGET = 0x55e,
+/*20080827 to latest
+^777777습득조건 :
+^CC3399Requirement:
+*/
+ MSG_FINDTEXT_TO_SKILLDES = 0x55f,
+/*20080827 to latest
+스킬 설명 보기
+View Skill Info
+*/
+ MSG_VIEW_SKILL_DESCRIPT = 0x560,
+/*20080827 to latest
+사용된 스킬 포인트는 다시 되돌릴 수 없습니다. 적용하시겠습니까?
+Once used, skill points cannot be re-allocated. Would you like to use the skill points?
+*/
+ MSG_APPLY_SKILL_UP = 0x561,
+/*20080827 to latest
+노비스·1차직업
+1st
+*/
+ MSG_1TABNAME_SKILLWND = 0x562,
+/*20080827 to latest
+2차·전승직업
+2nd
+*/
+ MSG_2TABNAME_SKILLWND = 0x563,
+/*20080827 to latest
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭종료시간 : %s
+This account has been used for illegal program or hacking program. Block Time: %s
+20081217 to 20081218
+불법프로그램을 사용하였거나 해킹을 시도한 계정이거나 그라비티 이전을 신청한 한게임 계정입니다. 블럭종료시간 : %s
+*/
+ MSG_RE17 = 0x564,
+/*20080827 to latest
+불법프로그램이 실행, 바이러스 감염, 또는 해킹툴이 설치되어 있을 가능성이 있습니다. 정상 클라이언트를 실행하여 주시기 바랍니다. 함께 만드는 밝은 라그나로크가 될 수 있도록 노력하고 있습니다.
+The possibility of exposure to illegal program, PC virus infection or Hacking Tool has been detected. Please execute licensed client. Our team is trying to make a best environment for Ro players.
+*/
+ MSG_RE18 = 0x565,
+/*20080827 to latest
+당신은 지금 건강한 게임 시간 대에 있습니다, 즐거운 게임이 되시길 바랍니다
+You are currently playing in the best game environment. Please enjoy the Ragnarok.
+*/
+ MSG_WARNING_MSG3 = 0x566,
+/*20080827 to 20100721
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.5배로 증가합니다.
+20100727 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.25배로 증가합니다.
+Job Exp points from hunting monsters are increased by 50% for 30 minutes.
+*/
+ MSG_PLUSONLYJOBEXP = 0x567,
+/*20080827 to 20091110
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.25배로 증가합니다.
+20091117 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.2배로 증가합니다.
+Exp points from hunting monsters are increased by 25% for 30 minutes.
+*/
+ MSG_PLUSEXP14532 = 0x568,
+/*20080827 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 2배로 증가합니다.
+EXP points from hunting monsters are increased by 100%% for 30 minutes.
+*/
+ MSG_PLUSEXP14533 = 0x569,
+/*20080827 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 60분간 1.5배로 증가합니다.
+EXP points from hunting monsters are increased by 50% for 60 minutes.
+*/
+ MSG_PLUSEXP12312 = 0x56a,
+/*20080827 to latest
+이 맵에서는 파티를 결성할 수 없습니다.
+Unable to organize a party in this map.
+*/
+ MSG_NOPARTY = 0x56b,
+/*20080827 to latest
+(%s)님은 파티에 참여할 수 없는 맵에 있습니다.
+(%s) are currently in restricted map to join a party.
+*/
+ MSG_NOPARTY2 = 0x56c,
+/*20080827 to latest
+간편아이템샵
+Simple Item Shop
+*/
+ MSG_SIMPLE_CASH_SHOP = 0x56d,
+/*20080827 to latest
+소지 한코인 : %d 한코인
+Han Coin: %d Han Coin
+*/
+ MSG_SIMPLE_POINT_SHOP_NHN = 0x56e,
+/*20080827 to latest
+소지 캐시 : %d 캐시
+RoK Point: %d RoK Point
+*/
+ MSG_SIMPLE_POINT_SHOP = 0x56f,
+/*20080827 to latest
+무료 캐시 : %d 캐시
+Free Cash: %d Cash
+*/
+ MSG_SIMPLE_POINT_SHOP2 = 0x570,
+/*20080827 to latest
+본서버 유저는 프리서버에 접속할수 없습니다.
+An user of this server cannot connect to free server
+*/
+ MSG_MAIN_USER_CANONT_LOGIN_FREE_SERVER = 0x571,
+/*20080827 to latest
+유효기간이 지난 비밀번호 입니다. 다시 로그인하여주십시오.
+Your password has expired. Please log in again
+*/
+ MSG_INVALID_ONETIMELIMIT = 0x572,
+#if PACKETVER >= 20080903
+/*20080903 to latest
+3차직업
+3rd
+*/
+ MSG_3TABNAME_SKILLWND = 0x573,
+#endif
+#if PACKETVER >= 20080917
+/*20080917 to latest
+이 스킬을 사용할 수 없는 대상입니다.
+This skill can't be used on that target.
+*/
+ MSG_USESKILL_FAIL_TOTARGET = 0x574,
+/*20080917 to latest
+안실라 소유 개수가 초과하여 스킬을 사용할 수 없습니다.
+You can't use skill because you have exceeded the number Ancilla possession limit
+*/
+ MSG_USESKILL_FAIL_ANCILLA_NUMOVER = 0x575,
+/*20080917 to latest
+성수가 필요합니다.
+Unable to use the skill to exceed the number of Ancilla.
+*/
+ MSG_USESKILL_FAIL_HOLYWATER = 0x576,
+/*20080917 to latest
+안실라가 필요합니다.
+Holy water is required.
+*/
+ MSG_USESKILL_FAIL_ANCILLA = 0x577,
+/*20080917 to latest
+일정거리 내에 중복될 수 없습니다.
+Ancilla is required.
+*/
+ MSG_USESKILL_FAIL_DUPLICATE_RANGEIN = 0x578,
+/*20080917 to latest
+이 스킬을 사용하기 위해서는 다른 스킬이 필요합니다.
+Cannot be duplicated within a certain distance.
+*/
+ MSG_USESKILL_FAIL_NEED_OTHER_SKILL = 0x579,
+#endif
+#if PACKETVER >= 20080924
+/*20080924 to latest
+이 맵에서는 채팅을 할 수 없습니다.
+This skill requires other skills to be used.
+*/
+ MSG_NO_CHATTING = 0x57a,
+#endif
+#if PACKETVER >= 20081001
+/*20081001 to latest
+3시간이 지났습니다.
+Chat is not allowed in this map
+*/
+ MSG_VET_3HOUR = 0x57b,
+/*20081001 to latest
+5시간이 지났습니다.
+3 hours have passed.
+*/
+ MSG_VET_5HOUR = 0x57c,
+#endif
+#if PACKETVER >= 20081008
+/*20081008 to latest
+게임가드 초기화 에러 또는 구버전의 게임가드 파일입니다. 게임가드 셋업파일을 다시 설치하고 게임을 실행해 보시기 바랍니다.
+5 hours have passed.
+*/
+ MSG_NPGAMEMON_ERROR_GAMEGUARD = 0x57d,
+/*20081008 to latest
+ini 파일이 없거나 변조되었습니다. 게임가드 셋업파일을 설치하면 해결 할 수 있습니다.
+Game guard initialization error or previous version game guard file is installed. Please re-install the setup file and try again
+*/
+ MSG_NPGMUP_ERROR_PARAM = 0x57e,
+/*20081008 to latest
+게임가드와 충돌 프로그램이 발견되었습니다.
+Either ini file is missing or altered. Install game guard setup file to fix the problem
+*/
+ MSG_NPGG_ERROR_COLLISION = 0x57f,
+#endif
+#if PACKETVER >= 20081111
+/*20081111 to latest
+잘못된 클라이언트입니다. 정상적인 클라이언트를 실행하여 주십시요.
+There is a program found that conflicts with game guard
+*/
+ MSG_PROOF_ERROR = 0x580,
+#endif
+#if PACKETVER >= 20081203
+/*20081203 to latest
+모바일 인증을 받아주시기 바랍니다.
+Incorrect client. Please run a normal client
+*/
+ MSG_MOBILE_LOCKSERVER = 0x581,
+#endif
+#if PACKETVER >= 20081217
+/*20081217 to latest
+모바일 인증에 실패하였습니다.
+Thank you to accept mobile authentication.
+*/
+ MSG_FAILED_MOBILE_LOCKSERVER = 0x582,
+/*20081217 to latest
+이스킬은 혼자서 사용할수 없습니다.
+This skill can't be used alone
+*/
+ MSG_USESKILL_FAIL_NEED_HELPER = 0x583,
+/*20081217 to latest
+이스킬은 특정방향으로만 사용할수 있습니다.
+This skill can be used to certain direction only
+*/
+ MSG_USESKILL_FAIL_INVALID_DIR = 0x584,
+/*20081217 to latest
+더이상 소환할수 없습니다.
+Cannot summon spheres anymore.
+*/
+ MSG_USESKILL_FAIL_SUMMON = 0x585,
+/*20081217 to 20130710
+소환된 구체가 존재하지 않습니다.
+20130717 to latest
+소환된 구체가 존재하지 않거나 부족합니다.
+There is no summoned sphere or you do not have enough sphere.
+*/
+ MSG_USESKILL_FAIL_SUMMON_NONE = 0x586,
+/*20081217 to latest
+사용가능한 모방스킬이 존재하지 않습니다.
+There is no imitation skills available.
+*/
+ MSG_USESKILL_FAIL_IMITATION_SKILL_NONE = 0x587,
+/*20081217 to latest
+이 스킬은 중복해서 사용할수 없습니다.
+You can't reuse this skill
+*/
+ MSG_USESKILL_FAIL_DUPLICATE = 0x588,
+/*20081217 to latest
+스킬을 사용할수 없는 상태입니다.
+Skill can't be used in this state
+*/
+ MSG_USESKILL_FAIL_CONDITION = 0x589,
+/*20081217 to latest
+아이템별 최대 소지량을 초과하여 가질 수 없습니다.
+You have exceeded the maximum amount of possession of another item.
+*/
+ MSG_PICKUP_MAXCOUNT_LIMIT = 0x58a,
+#endif
+#if PACKETVER >= 20090204
+/*20090204 to latest
+관리자 권한이 없습니다. 프로그램 최초 실행은 관리자 권한으로 실행하셔야 합니다.
+No administrative privileges. Must first run the program with administrator privileges.
+*/
+ MSG_NPK_ERROR_NOTADMIN = 0x58b,
+/*20090204 to latest
+nProtect KeyCrypt 드라이버 버전이 맞지 않습니다. 시스템 재 부팅 후에 새로 실행 시켜 주십시오.
+nProtect KeyCrypt not the same. Please restart the program and the computer first.
+*/
+ MSG_NPK_ERROR_DRIVERVERSION = 0x58c,
+/*20090204 to latest
+WindowXP 호환성 모드를 사용하고 계십니다. 현재 프로그램에서 호환성 모드를 제거하였습니다. 프로그램을 새로 시작해 주십시오.
+Currently wearing WindowXP Compatibility Mode. The program now removes Compatibility Mode. Please restart the program.
+*/
+ MSG_NPK_ERROR_VERIFYVERSION = 0x58d,
+/*20090204 to latest
+PS/2 키로거가 존재합니다.
+PS/2 keyloggers exist.
+*/
+ MSG_DETECT_PS2KEYLOGGER = 0x58e,
+/*20090204 to latest
+USB 키보드 드라이버 해킹 시도가 탐지되었습니다.
+USB Keylogging attempt was detected.
+*/
+ MSG_DETECT_USBKEYLOGGER = 0x58f,
+/*20090204 to latest
+HHD 모니터링 툴이 탐지되었습니다.
+HHD monitoring tool has been detected.
+*/
+ MSG_DETECT_HHDUSBH = 0x590,
+/*20090204 to latest
+페인트붓이 필요합니다.
+Paintbrush is required.
+*/
+ MSG_USESKILL_FAIL_PAINTBRUSH = 0x591,
+/*20090204 to 20090401
+그림물감이 필요합니다.
+20090408 to latest
+서페이스페인트가 필요합니다.
+Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_SURFACE_PAINTS = 0x592,
+/*20090204 to latest
+지정한 위치에 스킬을 사용할수 없습니다.
+Use the skills that are not at the specified location.
+*/
+ MSG_USESKILL_FAIL_POS = 0x593,
+/*20090204 to latest
+도우미의 SP가 부족합니다.
+Not enough SP.
+*/
+ MSG_USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 0x594,
+#endif
+#if PACKETVER >= 20090211
+/*20090211 to 20090218
+생성 가능 캐릭터 수는 9개입니다!!(임시)
+20090226 to latest
+캐릭터 선택창의 캐릭터가 %d개를 초과하면 게임에 접속할 수 없습니다. 불필요한 캐릭터를 삭제해주십시오.
+Character %d is character selection window cannot connect to the game that exceeds the total. Please remove unwanted characters.
+*/
+ MSG_BAN_OVER_CHARACTER_LIST = 0x595,
+#endif
+#if PACKETVER >= 20090226
+/*20090226 to latest
+목캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_NECK_CANDY = 0x596,
+/*20090226 to latest
+안타까운눈물이 필요합니다.
+Painful Tears is required.
+*/
+ MSG_USESKILL_FAIL_II_MISERABLE_TEAR = 0x597,
+/*20090226 to latest
+목 보호 캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_PROTECT_NECK_CANDY = 0x598,
+/*20090226 to latest
+웨폰 블로킹의 연계로만 사용가능합니다.
+Cooperation is only available with Weapon Blocking.
+*/
+ MSG_USESKILL_FAIL_GC_WEAPONBLOCKING = 0x599,
+/*20090226 to latest
+길로틴크로스의 독을 바른 무기가 필요합니다.
+Poisoned weapons is required.
+*/
+ MSG_USESKILL_FAIL_GC_POISONINGWEAPON = 0x59a,
+/*20090226 to latest
+마도기어 탑승시에만 사용가능합니다.
+Item can only be used when Mado Gear is mounted.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR = 0x59b,
+/*20090226 to latest
+발칸블릿이 필요합니다.
+Vulcan Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_VULCANBULLET = 0x59c,
+/*20090226 to latest
+마도기어 연료가 필요합니다.
+Mado Gear Fuel is required.
+*/
+ MSG_USESKILL_FAIL_II_FUELGAS = 0x59d,
+/*20090226 to latest
+액체냉각탄이 필요합니다.
+Liquid Cold Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_COLDSLOWERBULLET = 0x59e,
+/*20090226 to latest
+캐논볼을 장전 하세요.
+Please load a Cannon Ball.
+*/
+ MSG_USESKILL_FAIL_CANONBALL = 0x59f,
+/*20090226 to latest
+미도기어 가속장치를 착용하세요.
+Please equipped with a Mado Gear Accelerator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 0x5a0,
+/*20090226 to latest
+호버링부스터를 착용하세요.
+Please equipped with a Hovering Booster.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 0x5a1,
+#endif
+#if PACKETVER >= 20090304
+/*20090304 to latest
+[톡신] 독 효과가 무기에 적용되었습니다.
+[Toxin] Poison effect was applied to the weapon.
+*/
+ MSG_TOXIN = 0x5a2,
+/*20090304 to latest
+[패럴라이즈] 독 효과가 무기에 적용되었습니다.
+[Paralysis] Poison effect was applied to the weapon.
+*/
+ MSG_PARALYZE = 0x5a3,
+/*20090304 to latest
+[베놈블리드] 독 효과가 무기에 적용되었습니다.
+[Fatigue] Poison effect was applied to the weapon.
+*/
+ MSG_VENOMBLEED = 0x5a4,
+/*20090304 to latest
+[매직 머쉬룸] 독 효과가 무기에 적용되었습니다.
+[Laughing] Poison effect was applied to the weapon.
+*/
+ MSG_MAGICMUSHROOM = 0x5a5,
+/*20090304 to latest
+[데스 허트] 독 효과가 무기에 적용되었습니다.
+[Disheart] Poison effect was applied to the weapon.
+*/
+ MSG_DEATHHURT = 0x5a6,
+/*20090304 to latest
+[파이렉시아] 독 효과가 무기에 적용되었습니다.
+[Pyrexia] Poison effect was applied to the weapon.
+*/
+ MSG_PHYREXIA = 0x5a7,
+/*20090304 to latest
+[오블리비언 커즈] 독 효과가 무기에 적용되었습니다.
+[Oblivion] Poison effect was applied to the weapon.
+*/
+ MSG_OBLIANCURSE = 0x5a8,
+/*20090304 to latest
+[리치 엔드] 독 효과가 무기에 적용되었습니다.
+[Leech] Poison effect was applied to the weapon.
+*/
+ MSG_RICHEND = 0x5a9,
+#endif
+#if PACKETVER >= 20090311
+/*20090311 to latest
+호버링상태에서만 사용가능합니다.
+Can only be used in Hovering state.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_HOVERING = 0x5aa,
+/*20090311 to latest
+자폭장치를 장착하세요.
+Please equip a Self-Destruct Mechanism.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 0x5ab,
+/*20090311 to latest
+셰이프쉬프터를 장착하세요.
+Please equip a Shape Shift.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 0x5ac,
+/*20090311 to latest
+길로틴독이 필요합니다.
+Guillotine Cross Poison is required.
+*/
+ MSG_USESKILL_FAIL_GUILLONTINE_POISON = 0x5ad,
+/*20090311 to latest
+냉각장치를 장착하세요.
+Please equipped with a Cooling System.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 0x5ae,
+/*20090311 to latest
+자기장필드생성기를 착용하세요.
+Please equipped with a Magnetic Field Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 0x5af,
+/*20090311 to latest
+베리어생성기를 착용하세요.
+Please equipped with a Barrier Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 0x5b0,
+/*20090311 to latest
+광학미채발생기를 착용하세요.
+Please equipped with a Optical Camouflage Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 0x5b1,
+/*20090311 to latest
+리페어키트를 착용하세요.
+Please equipped with a Repair Kit.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 0x5b2,
+/*20090311 to latest
+몽키 스패너가 필요합니다.
+Monkey Wrench is required.
+*/
+ MSG_USESKILL_FAIL_II_MONKEY_SPANNER = 0x5b3,
+#endif
+#if PACKETVER >= 20090318
+/*20090318 to latest
+[%s] 스킬을 시전 할 수 없습니다.
+[%s] Cannot use the skills due to cooldown delay.
+*/
+ MSG_SKILLINTERVAL2 = 0x5b4,
+/*20090318 to latest
+%d레벨 이상은 삭제가 불가능합니다.
+Deletion is impossible for over level %d
+*/
+ MSG_LEMIT_DELETE_LEVEL = 0x5b5,
+/*20090318 to 20110614
+마도기어 탑승시에는 사용할수 없습니다.
+20110622 to latest
+마도기어 탑승시에는 사용 할 수 없습니다.
+Can't be used while on Magic Gear.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_RIDE = 0x5b6,
+#endif
+#if PACKETVER >= 20090319
+/*20090319 to latest
+드래곤 내리기
+Dismount Dragon
+*/
+ MSG_DRAGONOFF = 0x5b7,
+/*20090319 to latest
+마도기어 내리기
+Dismount Magic Gear
+*/
+ MSG_MADOOFF = 0x5b8,
+#endif
+#if PACKETVER >= 20090401
+/*20090401 to latest
+소비
+I
+*/
+ MSG_STORE_TABNAME_0 = 0x5b9,
+/*20090401 to latest
+캐쉬
+Cash
+*/
+ MSG_STORE_TABNAME_1 = 0x5ba,
+/*20090401 to latest
+방어구
+Armors
+*/
+ MSG_STORE_TABNAME_2 = 0x5bb,
+/*20090401 to latest
+무기
+Weapons
+*/
+ MSG_STORE_TABNAME_3 = 0x5bc,
+/*20090401 to latest
+투사체
+Ammo
+*/
+ MSG_STORE_TABNAME_4 = 0x5bd,
+/*20090401 to latest
+카드
+Card
+*/
+ MSG_STORE_TABNAME_5 = 0x5be,
+/*20090401 to latest
+기타
+Other
+*/
+ MSG_STORE_TABNAME_6 = 0x5bf,
+/*20090401 to latest
+클라이언트 응답시간이 초과되어 연결이 끊어집니다.
+Client response time has passed so connection is terminated
+*/
+ MSG_ERROR_HS_TIMEOUT = 0x5c0,
+/*20090401 to latest
+핵쉴드 파일의 버전이 맞지 않습니다. 클라이언트를 재설치 해주십시오.
+Incorrect version of hack shield file. Please reinstall the client
+*/
+ MSG_ERROR_DIFF_CLIENT = 0x5c1,
+#endif
+#if PACKETVER >= 20090408
+/*20090408 to latest
+마법서가 필요합니다.
+[Magic Book] is required.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK = 0x5c2,
+/*20090408 to latest
+마법서가 너무 어려워서 졸음이 몰려온다.
+Feel sleepy since Magic Book is too difficult to understand.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 0x5c3,
+/*20090408 to latest
+보존포인트가 부족합니다.
+Not enough saved point.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 0x5c4,
+/*20090408 to latest
+더이상 마법서를 읽을수 없습니다.
+Can't read a Magic Book anymore.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_READING = 0x5c5,
+/*20090408 to latest
+페이스페인트가 필요합니다.
+Face Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_FACE_PAINTS = 0x5c6,
+/*20090408 to latest
+분장용붓이 필요합니다.
+Brush is required.
+*/
+ MSG_USESKILL_FAIL_II_MAKEUP_BRUSH = 0x5c7,
+/*20090408 to latest
+대기 시간이 초과하였습니다. 다시 로그인 해주십시오.
+Waiting time has passed. Please log in again
+*/
+ MSG_MOBILE_TIMEOVER = 0x5c8,
+/*20090408 to latest
+위험! 이미 동일한 계정이 로그인 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is already logged in. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_ANOTHER_LOGIN = 0x5c9,
+/*20090408 to latest
+위험! 현재 동일한 계정이 모바일 인증 대기 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is waiting for mobile verification. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_WAITING_STATE = 0x5ca,
+#endif
+#if PACKETVER >= 20090506
+/*20090506 to latest
+게임 옵션창
+Game setting window
+*/
+ MSG_ESC_OPTIONWND = 0x5cb,
+/*20090506 to latest
+그래픽 설정
+Graphics Settings
+*/
+ MSG_GRAPHIC_OPTIONWND = 0x5cc,
+/*20090506 to latest
+사운드 설정
+Sound Settings
+*/
+ MSG_SOUND_OPTIONWND = 0x5cd,
+#endif
+#if PACKETVER >= 20090514
+/*20090514 to latest
+변경 할 단축키를 누르거나, 'ESC'키를 눌러 삭제 해 주세요.
+Press a key to assign. Pressing 'ESC' will remove the assigned key.
+*/
+ MSG_HOTKEYWND_NOTICE1 = 0x5ce,
+/*20090514 to latest
+단일 키로 지정 할 수 없는 키입니다.
+Unable to specify a single key.
+*/
+ MSG_HOTKEYWND_NOTICE2 = 0x5cf,
+/*20090514 to latest
+지정 할 수 없는 키입니다.
+Unable to specify the key assigned.
+*/
+ MSG_HOTKEYWND_NOTICE3 = 0x5d0,
+/*20090514 to latest
+'%s'에 사용된 단축키와 중복됩니다. 바꾸시겠습니까?
+Duplicated with ['%s']. Do you still want to change?
+*/
+ MSG_HOTKEYWND_NOTICE4 = 0x5d1,
+/*20090514 to latest
+저장된 단축키 조합이 초기화 됩니다. 초기화 하시겠습니까?
+Initialization is stored in the shortcut key settings. Do you want to initialized?
+*/
+ MSG_HOTKEYWND_NOTICE5 = 0x5d2,
+/*20090514 to latest
+스킬바
+Skill Bar
+*/
+ MSG_HOTKEYWND_TAB1 = 0x5d3,
+/*20090514 to latest
+인터페이스
+Interface
+*/
+ MSG_HOTKEYWND_TAB2 = 0x5d4,
+/*20090514 to latest
+이모션
+Macros
+*/
+ MSG_HOTKEYWND_TAB3 = 0x5d5,
+/*20090514 to latest
+단축키 설정 창
+Shortcut Settings
+*/
+ MSG_HOTKEYWND_TITLE = 0x5d6,
+#endif
+#if PACKETVER >= 20090520
+/*20090520 to latest
+배경음
+BGM
+*/
+ MSG_BGM = 0x5d7,
+/*20090520 to latest
+효과음
+Effect
+*/
+ MSG_SOUND = 0x5d8,
+/*20090520 to latest
+스킨
+Skin
+*/
+ MSG_SKIN = 0x5d9,
+/*20090520 to latest
+채팅방 입장음만 소리남 On
+Chat room entrance sound on
+*/
+ MSG_TINGONLY_ON = 0x5da,
+/*20090520 to latest
+채팅방 입장음만 소리남 Off
+Chat room entrance sound off
+*/
+ MSG_TINGONLY_OFF = 0x5db,
+/*20090520 to latest
+/tingonly : 채팅방 입장음만 들을수있게됩니다
+/tingonly: you can hear only sound like a chat room entry.
+*/
+ MSG_EXPLAIN_TINGONLY = 0x5dc,
+/*20090520 to latest
+/주먹
+/rock
+*/
+ MSG_EMOTION_ROCK = 0x5dd,
+/*20090520 to latest
+/가위
+/scissors
+*/
+ MSG_EMOTION_SCISSOR = 0x5de,
+/*20090520 to latest
+/보
+/paper
+*/
+ MSG_EMOTION_WRAP = 0x5df,
+/*20090520 to latest
+/러브
+/love
+*/
+ MSG_EMOTION_LUV = 0x5e0,
+/*20090520 to latest
+/mobile
+*/
+ MSG_EMOTION_MOBILE = 0x5e1,
+/*20090520 to latest
+/mail
+*/
+ MSG_EMOTION_MAIL = 0x5e2,
+/*20090520 to latest
+/antenna0
+*/
+ MSG_EMOTION_ANTENNA0 = 0x5e3,
+/*20090520 to latest
+/antenna1
+*/
+ MSG_EMOTION_ANTENNA1 = 0x5e4,
+/*20090520 to latest
+/antenna2
+*/
+ MSG_EMOTION_ANTENNA2 = 0x5e5,
+/*20090520 to latest
+/antenna3
+*/
+ MSG_EMOTION_ANTENNA3 = 0x5e6,
+/*20090520 to latest
+/hum
+*/
+ MSG_EMOTION_HUM2 = 0x5e7,
+/*20090520 to latest
+/abs
+*/
+ MSG_EMOTION_ABS = 0x5e8,
+/*20090520 to latest
+/oops
+*/
+ MSG_EMOTION_OOPS = 0x5e9,
+/*20090520 to latest
+/spit
+*/
+ MSG_EMOTION_SPIT = 0x5ea,
+/*20090520 to latest
+/ene
+*/
+ MSG_EMOTION_ENE = 0x5eb,
+/*20090520 to latest
+/panic
+*/
+ MSG_EMOTION_PANIC = 0x5ec,
+/*20090520 to latest
+/whisp
+*/
+ MSG_EMOTION_WHISP = 0x5ed,
+#endif
+#if PACKETVER >= 20090527
+/*20090527 to latest
+지정안함
+Not Assigned
+*/
+ MSG_HOTKEY_NOTHING = 0x5ee,
+#endif
+#if PACKETVER >= 20090529
+/*20090529 to latest
+카트장착시에만 사용가능합니다.
+Only available when cart is mounted.
+*/
+ MSG_USESKILL_FAIL_CART = 0x5ef,
+/*20090529 to latest
+[가시나무 씨앗]이 필요합니다.
+[Thorny Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_THORNS_SEED = 0x5f0,
+/*20090529 to latest
+[흡혈 식물 씨앗]이 필요합니다.
+[Bloodsucker Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 0x5f1,
+/*20090529 to latest
+더이상 시전할수 없습니다.
+Cannot be used anymore.
+*/
+ MSG_USESKILL_FAIL_NO_MORE_SPELL = 0x5f2,
+/*20090529 to latest
+[폭탄버섯포자]가 필요합니다.
+[Bomb Mushroom Spore] is required.
+*/
+ MSG_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 0x5f3,
+/*20090529 to latest
+[화염병]이 필요합니다.
+[Fire Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_GASOLINE_BOOMB = 0x5f4,
+/*20090529 to latest
+[기름병]이 필요합니다.
+[Oil Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_OIL_BOTTLE = 0x5f5,
+/*20090529 to latest
+[폭발가루]가 필요합니다.
+[Explosive Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_EXPLOSION_POWDER = 0x5f6,
+/*20090529 to latest
+[연막가루]가 필요합니다.
+[Smokescreen Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_SMOKE_POWDER = 0x5f7,
+/*20090529 to latest
+[최루가스]가 필요합니다.
+[Tear Gas] is required.
+*/
+ MSG_USESKILL_FAIL_II_TEAR_GAS = 0x5f8,
+/*20090529 to latest
+[염산병]이 필요합니다.
+[Acid Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 0x5f9,
+/*20090529 to latest
+[식인식물병]이 필요합니다.
+[Bottom Man-Eating Plant] is required.
+*/
+ MSG_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 0x5fa,
+/*20090529 to latest
+[만드라고라의 화분]이 필요합니다.
+[Pot of Mandragora] is required.
+*/
+ MSG_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 0x5fb,
+#endif
+#if PACKETVER >= 20090603
+/*20090603 to latest
+파티장 위임
+Party delegation
+*/
+ MSG_YIELD_PARTYMASTER = 0x5fc,
+/*20090603 to latest
+정말 파티장을 위임하시겠습니까?
+Do you want to delegate the real party?
+*/
+ MSG_DO_YOU_REALLY_WANT_YIELD_PARTYMASTER = 0x5fd,
+/*20090603 to latest
+파티장을 위임 할 수 없습니다.
+Party cannot be delegated.
+*/
+ MSG_CANNOT_YIELD_PARTYMASTER = 0x5fe,
+/*20090603 to latest
+변경불가
+Immutable
+*/
+ MSG_FAILED_CHANGE = 0x5ff,
+/*20090603 to latest
+[%s]가 %d개 필요합니다.
+[%s] required '%d' amount.
+*/
+ MSG_USESKILL_FAIL_NEED_ITEM = 0x600,
+#endif
+#if PACKETVER >= 20090605
+/*20090605 to latest
+제련 수치가 하향 조정 되었습니다.
+Is now refining the value lowered.
+*/
+ MSG_ITEM_REFINING_DOWNGRADE = 0x601,
+/*20090605 to latest
+[%s]를 장비하고 있어야 사용할 수 있습니다
+Need to put on [%s] in order to use.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT = 0x602,
+#endif
+#if PACKETVER >= 20090617
+/*20090617 to 20090923
+전장 리스트
+20090929 to latest
+전장 입장 설정
+Battle field entrance setting
+*/
+ MSG_BATTLEFIELD_LIST = 0x603,
+/*20090617 to 20090929
+전장 - [%s] 신청 하시겠습니까?
+20091006 to latest
+% 전장으로 이동 할 수 없는 상태가 되어 전장 신청이 취소 되었습니다.
+Battlefield - [%s] you sign up?
+*/
+ MSG_CANNOT_JOINTO_BATTLEFIELD = 0x604,
+/*20090617 to 20090715
+전장 - [%s] 입장 신청이 완료되었습니다.
+20090722 to 20090929
+입장 신청이 완료되었습니다.
+20091006 to 20100810
+
+20100817 to latest
+
+Current admission application state.
+*/
+ MSG_COMPLETED_JOINTO_BATTLEFIELD = 0x605,
+/*20090617 to 20090624
+전장 - [%s] 입장 하실 수 없습니다.
+20090701 to 20090715
+전장 - [%s] 에 입장 할 수 없는 상태이므로 등록이 취소 되었습니다.
+20090722 to 20090929
+에 입장 할 수 없는 상태이므로 등록이 취소 되었습니다.
+20091006 to latest
+% 전장 입장이 보류 되었습니다. 다른 플레이어를 기다립니다.
+It was unregistered and not be able to enter the state.
+*/
+ MSG_DIFFER_JOINTO_BATTLEFIELD = 0x606,
+/*20090617 to 20090929
+현재 입장 신청 상태입니다.
+20091006 to 20100810
+
+20100817 to latest
+
+Current admission application state.
+*/
+ MSG_STATUS_JOINTO_BATTLEFIELD = 0x607,
+/*20090617 to 20090929
+입장 신청을 취소하시겠습니까?
+20091006 to 20100616
+%s 전장 신청을 정말로 취소하시겠습니까?
+20100622 to latest
+확인 단추를 누르면 전장 신청이 취소됩니다. 아래 단추를 클릭해 주세요.
+Do you want to cancel the admission application?
+*/
+ MSG_REQ_CANCEL_JOINTO_BATTLEFIELD = 0x608,
+/*20090617 to 20090715
+전장 - [%s] 입장 신청이 취소되었습니다.
+20090722 to 20090929
+입장 신청이 취소되었습니다.
+20091006 to latest
+%s 전장 입장 신청이 취소되었습니다.
+Admission request has been cancelled.
+*/
+ MSG_CANCEL_JOINTO_BATTLEFIELD = 0x609,
+/*20090617 to 20090929
+곧 전장으로 이동 합니다.
+20091006 to latest
+잠시후 %s 전장으로 이동 합니다. 공간 이동을 위한 안정적인 상태를 확보해 주시길 바랍니다. (거래 및 공간 이동 기능 일시 중지됨)
+Go to the battlefield quickly.
+*/
+ MSG_MOVETO_BATTLEFIELD = 0x60a,
+/*20090617 to 20091028
+전장 - [%s]
+20091103 to latest
+전장 명칭
+Battlefield - [%s]
+*/
+ MSG_BATTLEFIELD_NAME = 0x60b,
+#endif
+#if PACKETVER >= 20090624
+/*20090624 to latest
+정말 이동 하시겠습니까?
+Do you really want to go back to your savepoint?
+*/
+ MSG_MOVETO_SAVEPOINT = 0x60c,
+/*20090624 to latest
+파티원 찾기 메세지
+Search Message for Party Members
+*/
+ MSG_VIEW_SEEK_PARTY = 0x60d,
+/*20090624 to latest
+파티원 찾기 메세지 옵션이 꺼져있습니다.
+Message option is off the search party members.
+*/
+ MSG_UNVIEW_SEEK_PARTY = 0x60e,
+/*20090624 to latest
+10초간 파티 지원 딜레이가 걸려있습니다.
+10 seconds delay of party support is in effect
+*/
+ MSG_SEEK_PARTY_DEALY = 0x60f,
+#endif
+#if PACKETVER >= 20090701
+/*20090701 to latest
+ 파티장은 '%s' 님 입니다.
+Party leader is '%s'.
+*/
+ MSG_NOTIFY_PARTY_ROLE_MASTER = 0x610,
+/*20090701 to 20090715
+전장 - [%s] : 시스템 오류로 입장 할 수 없습니다.
+20090722 to latest
+시스템 오류로 입장 할 수 없습니다.
+Unable to enter due to system error.
+*/
+ MSG_ERROR_SYSTEM_ERROR_BATTLEFIELD = 0x611,
+/*20090701 to 20090715
+전장 - [%s] : 대기 인원 수 초과로 입장 할 수 없습니다.
+20090722 to latest
+대기 인원 수 초과로 입장 할 수 없습니다.
+Cannot wait to enter the number of excess.
+*/
+ MSG_ERROR_FULL_ESROOM_BATTLEFIELD = 0x612,
+/*20090701 to 20090715
+전장 - [%s] : 이미 신청 되었습니다.
+20090722 to latest
+이미 신청 되었습니다.
+Has already been applied.
+*/
+ MSG_ERROR_DOUBLE_OFFER_BATTLEFIELD = 0x613,
+/*20090701 to 20090715
+전장 - [%s] : 대기 시간이 초과되어 등록이 취소 되었습니다.
+20090722 to latest
+대기 시간이 초과되어 등록이 취소 되었습니다.
+Registration has been cancelled because of the excessive waiting time.
+*/
+ MSG_ERROR_WAIT_TIMEOUT_BATTLEFIELD = 0x614,
+/*20090701 to 20090715
+전장 - [%s] : 입장 조건이 맞지 않아, 등록이 취소 되었습니다.
+20090722 to latest
+입장 조건이 맞지 않아, 등록이 취소 되었습니다.
+Unregistered because admission requirements are not matching.
+*/
+ MSG_ERROR_BATTLEFILD_ENTER_BATTLEFIELD = 0x615,
+/*20090701 to 20090715
+전장 - [%s] : 오류가 발생하여 등록이 취소 되었습니다.
+20090722 to latest
+오류가 발생하여 등록이 취소 되었습니다.
+Was unregistered and error.
+*/
+ MSG_ERROR_DROP_ENTRANCESTATION_BATTLEFIELD = 0x616,
+#endif
+#if PACKETVER >= 20090708
+/*20090708 to latest
+[%s]의 연계 스킬입니다.
+The skill need [%s].
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL = 0x617,
+/*20090708 to latest
+특정스킬 의 연계 스킬입니다.
+The skill need a particular skill.
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL2 = 0x618,
+/*20090708 to latest
+기구체 %d 개가 필요합니다
+Requires %d mind bullets
+*/
+ MSG_USESKILL_FAIL_SPIRITS = 0x619,
+/*20090708 to 20090708
+기구체 %d 개가 필요합니다
+Requires %d mind bullets
+20090715 to latest
+기구체가 필요합니다
+Mind Bullet is required.
+*/
+ MSG_USESKILL_FAIL_SPIRITS2 = 0x61a,
+#endif
+#if PACKETVER >= 20090729
+/*20090729 to latest
+최대 소지량 보다 많은 룬스톤을 제작할 수 없습니다.
+Cannot create rune stone more than the maximum amount.
+*/
+ MSG_RUNESTONE_MAKEERROR_OVERCOUNT = 0x61b,
+/*20090729 to latest
+전장 리스트를 받을 수 없는 상태입니다. 확인 후 다시 시도 해 주세요.
+Not able to receive battle field list. Please check and try again
+*/
+ MSG_ERROR_LIST_OPEN_BATTLEFIELD = 0x61c,
+/*20090729 to latest
+레벨이 부족하여 입장 할 수 없습니다.
+Level is not high enough to enter
+*/
+ MSG_ERROR_LEVEL_LIMIT_BATTLEFIELD = 0x61d,
+#endif
+#if PACKETVER >= 20090805
+/*20090805 to latest
+ 1차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' points in your 1st Tab.
+*/
+ MSG_UPGRADESKILLERROR_MORE_FIRSTJOBSKILL = 0x61e,
+#endif
+#if PACKETVER >= 20091013
+/*20091013 to latest
+ 1차 혹은 2차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' remaining points in your 2nd Tab. 1st Tab is already done.
+*/
+ MSG_UPGRADESKILLERROR_MORE_SECONDJOBSKILL = 0x61f,
+/*20091013 to latest
+변환 가능한 아이템
+Items available for conversion
+*/
+ MSG_ITEMSYOUCANCHANGE = 0x620,
+/*20091013 to latest
+변환할 아이템
+Insert items to convert
+*/
+ MSG_ITEMS_FOR_CHANGE = 0x621,
+/*20091013 to latest
+변환이 불가능한 조합 입니다.
+Inconvertible combination
+*/
+ MSG_SKILL_RECIPE_NOTEXIST = 0x622,
+/*20091013 to latest
+인벤토리의 무게가 너무 무겁습니다.
+Inventory weight is too much
+*/
+ MSG_SKILL_INVENTORY_WEIGHT_OVER = 0x623,
+/*20091013 to latest
+인벤토리를 공간을 확보해주세요.
+Please secure some room in the inventory
+*/
+ MSG_SKILL_INVENTORY_KINDCNT_OVER = 0x624,
+/*20091013 to latest
+재료가 존재하지 않습니다.
+Material doesn't exist
+*/
+ MSG_SKILL_MATERIAL_FAIL = 0x625,
+/*20091013 to latest
+성공하였습니다.
+Successful.
+*/
+ MSG_SKILL_SUCCESS = 0x626,
+/*20091013 to latest
+실패 하였습니다.
+Failed.
+*/
+ MSG_SKILL_FAIL = 0x627,
+/*20091013 to latest
+실패하여 모든 재료가 사라졌습니다.
+all materials are gone due to failure
+*/
+ MSG_SKILL_FAIL_MATERIAL_DESTROY = 0x628,
+/*20091013 to latest
+지정하신 탭 이름이 너무 길어 변경 할 수 없습니다.
+unable to change the name of the specified tab, because it's too long.
+*/
+ MSG_FAILED_CHANGE_TABNAME = 0x629,
+/*20091013 to latest
+더 이상 추가 할 수 없습니다.
+Cannot add more.
+*/
+ MSG_FAILED_ADD_TAB = 0x62a,
+/*20091013 to latest
+인증에 실패 했습니다.
+Authentication failed.
+*/
+ MSG_FAILED_LOCKSERVER = 0x62b,
+/*20091013 to 20101012
+봇 체크
+20101019 to 20101020
+자동 로그인 방지
+20101026 to latest
+자동 입력 방지
+Bot checks
+*/
+ MSG_BOT_CHECK = 0x62c,
+/*20091013 to latest
+감정이 않된 아이템은 재료로 사용할 수 없습니다.
+Items cannot be used in materials cannot be emotional.
+*/
+ MSG_SKILL_FAIL_MATERIAL_IDENTITY = 0x62d,
+/*20091013 to latest
+접속하신 IP는 라그나로크 온라인 이용이 불가능 합니다. 고객 지원 센터 또는 홈페이지로 문의 해 주십시오.
+It is impossible to connect using this IP in Ragnarok Online. Please contact the customer support center or home.
+*/
+ MSG_BAN_IP_BLOCK = 0x62e,
+/*20091013 to latest
+비밀번호가 6회 이상 잘못 입력되어 잠시 동안 접속이 제한됩니다. 고객님의 개인정보를 다시 한 번 확인해 주시길 바랍니다.
+You have entered a wrong password for more than six times, please check your personal information again.
+*/
+ MSG_BAN_INVALID_PWD_CNT = 0x62f,
+/*20091013 to latest
+합성에 사용한 아이템은 소모됩니다. 괜찮겠습니까?
+Consumption items are used in the synthesis. Are you sure?
+*/
+ MSG_MIX_ACCEPT = 0x630,
+/*20091013 to latest
+왼쪽에 보이는 글자 및 숫자조합을 입력해주세요.
+Please input the captcha code found at your left side.
+*/
+ MSG_BOT_CHECK_NOTIC = 0x631,
+/*20091013 to latest
+전장 설명 -
+Describes the battlefield --
+*/
+ MSG_DESCRIBE_BATTLEFIELD = 0x632,
+/*20091013 to latest
+입장 대기 상태 -
+Waiting for admission --
+*/
+ MSG_BATTLEFIELD_STATUS = 0x633,
+/*20091013 to latest
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_HELP = 0x634,
+#endif
+#if PACKETVER >= 20091020
+/*20091020 to latest
+죄송합니다. 해당 직업의 캐릭터는 현재 테스트를 위해서 접속이 금지됩니다.
+Sorry the character you are trying to use is banned for testing connection.
+*/
+ MSG_BAN_NOT_ALLOWED_JOBCLASS = 0x635,
+#endif
+#if PACKETVER >= 20091027
+/*20091027 to latest
+모든 장비 해제
+Remove all equipment
+*/
+ MSG_REMOVE_EQUIPEDITEM = 0x636,
+#endif
+#if PACKETVER >= 20091103
+/*20091103 to latest
+미니 아이콘
+Mini Icon
+*/
+ MSG_MINI_ICON = 0x637,
+/*20091103 to latest
+진영 A : 진영 B
+Camp A: Camp B
+*/
+ MSG_BATTLEFIELD_TEAM = 0x638,
+/*20091103 to 20100616
+대기 상태
+20100622 to latest
+대기열
+Wait
+*/
+ MSG_WAIT_STATUS = 0x639,
+/*20091103 to latest
+전장 신청 취소 알림
+cancellation notice of Battlefield registration.
+*/
+ MSG_NOTIFY_BATTLEFIELD_CANCEL = 0x63a,
+/*20091103 to latest
+전장 필요 인원
+Required field for staff
+*/
+ MSG_BATTLEFIELD_COUNT = 0x63b,
+/*20091103 to latest
+전장 A 대기 인원
+Battlefield staff A is waiting.
+*/
+ MSG_BATTLEFIELD_ATEAM_COUNT = 0x63c,
+/*20091103 to latest
+전장 B 대기 인원
+Battlefield staff B is waiting.
+*/
+ MSG_BATTLEFIELD_BTEAM_COUNT = 0x63d,
+/*20091103 to latest
+내 대기 상황 : %d(진영 A)
+Waiting for my situation: %d (Camp A)
+*/
+ MSG_BATTLEFIELD_ATEAM_WAIT = 0x63e,
+/*20091103 to latest
+내 대기 상황 : %d(진영 B)
+Waiting for my situation: %d (Camp B)
+*/
+ MSG_BATTLEFIELD_BTEAM_WAIT = 0x63f,
+/*20091103 to latest
+전장 아이콘을 보여줍니다.
+Battlefield display icon.
+*/
+ MSG_SHOW_BATTLEFIELD_ICON = 0x640,
+/*20091103 to latest
+전장 아이콘을 보여주지 않습니다.
+Does not display the icon field.
+*/
+ MSG_DONT_SHOW_BATTLEFIELD_ICON = 0x641,
+/*20091103 to latest
+전장 이동 알림
+Field notification was moved.
+*/
+ MSG_NOTIFY_BATTLEFIELD_MOVE = 0x642,
+/*20091103 to latest
+전장 입장 보류 알림
+Admission pending notification of the battlefield
+*/
+ MSG_NOTIFY_BATTLEFIELD_DEFER = 0x643,
+/*20091103 to latest
+누군가
+Anyone
+*/
+ MSG_WHO_IS = 0x644,
+/*20091103 to latest
+ [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] deal '%d' damage on you.
+*/
+ MSG_I_RECEIVED_DAMAGE = 0x645,
+/*20091103 to 20091104
+ [%s]가 [%s](으)로부터 '%d'의 데미지를 받았습니다.
+20091110 to latest
+ [%s]님이 [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] received damage from [%s] with '%d' damage.
+*/
+ MSG_PARTY_RECEIVED_DAMAGE = 0x646,
+/*20091103 to latest
+ [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] received '%d' damage.
+*/
+ MSG_I_GAVE_DAMAGE = 0x647,
+/*20091103 to 20091104
+ [%s님]가 [%s]에게 '%d'의 데미지를 주었습니다.
+20091110 to latest
+ [%s]님이 [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] deal damage to [%s] with '%d' damage.
+*/
+ MSG_PARTY_GAVE_DAMAGE = 0x648,
+/*20091103 to latest
+%s %d 개 드롭
+You dropped '%s' (%d).
+*/
+ MSG_DROP_ITEM = 0x649,
+/*20091103 to latest
+ [%s]퀘스트의 [%s]몬스터를 처치하였습니다. (%d/%d)
+[%s] Quest - defeated [%s] progress (%d/%d)
+*/
+ MSG_CLEAR_QUEST_MONSTER = 0x64a,
+/*20091103 to latest
+%s 퀘스트가 삭제 되었습니다.
+The Quest '%s' has been removed.
+*/
+ MSG_DELETE_QUEST = 0x64b,
+/*20091103 to latest
+[%s]님이
+[%s] has
+*/
+ MSG_NOTIFY_WHO = 0x64c,
+/*20091103 to latest
+'%d'의 경험치를
+You acquired '%d' Experience Points
+*/
+ MSG_NOTIFY_EXP = 0x64d,
+/*20091103 to latest
+'%d'의 잡경험치를
+You acquired '%d' Job Experience Points
+*/
+ MSG_NOTIFY_JOBEXP = 0x64e,
+/*20091103 to latest
+획득했습니다.
+ gained.
+*/
+ MSG_GET = 0x64f,
+/*20091103 to latest
+상실했습니다.
+ has lost.
+*/
+ MSG_LOSS = 0x650,
+/*20091103 to latest
+ [%s](으)로부터 '%d'의 코인을 스틸했습니다.
+From [%s], '%d' coins were stolen.
+*/
+ MSG_NOTIFY_STEAL_COIN = 0x651,
+/*20091103 to latest
+전투 메시지
+Battle Message
+*/
+ MSG_VIEW_COMBAT_MSG = 0x652,
+/*20091103 to latest
+파티원 전투 메시지
+Display Party Battle Message
+*/
+ MSG_VIEW_PARTY_COMBAT_MSG = 0x653,
+/*20091103 to latest
+획득 경험치
+Display Experience Message
+*/
+ MSG_VIEW_GETTING_EXP_MSG = 0x654,
+/*20091103 to latest
+파티원의 획득 경험치
+Display Party Experience Message
+*/
+ MSG_VIEW_PARTY_GETTING_EXP_MSG = 0x655,
+/*20091103 to latest
+퀘스트 정보 표시
+Display Quest Info Message
+*/
+ MSG_VIEW_QUEST_INFO_MSG = 0x656,
+/*20091103 to latest
+전장 정보 표시
+Display Battlefield Message
+*/
+ MSG_VIEW_BATTLEFIELD_INFO_MSG = 0x657,
+#endif
+#if PACKETVER >= 20091104
+/*20091104 to latest
+[%s]에게
+[%s]
+*/
+ MSG_NOTIFY_TARGET_WHO = 0x658,
+/*20091104 to 20091104
+[%s] 스킬을 캐스팅합니다.
+20091110 to latest
+[%s] 스킬을 사용합니다.
+Casts [%s] skill.
+*/
+ MSG_NOTIFY_SKILL_TO_TARGET = 0x659,
+#endif
+#if PACKETVER >= 20091110
+/*20091110 to latest
+기능제한상태
+Activate lock function
+*/
+ MSG_LOCK_MOUSE = 0x65a,
+/*20091110 to latest
+기능제한해제상태
+Deactivate lock function
+*/
+ MSG_UNLOCK_MOUSE = 0x65b,
+#endif
+#if PACKETVER >= 20091201
+/*20091201 to latest
+[%s]님이 [%s](으)로부터 '%s' 를 획득 했습니다.
+Citizens of Midgard, Lady Luck shines upon [%s] !! [%s] has awarded the player with '%s' !!
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN = 0x65c,
+#endif
+#if PACKETVER >= 20091208
+/*20091208 to latest
+소드맨
+Swordman
+*/
+ MSG_JOB_SWORDMAN = 0x65d,
+/*20091208 to latest
+매지션
+Magician
+*/
+ MSG_JOB_MAGICIAN = 0x65e,
+/*20091208 to latest
+아처
+Archer
+*/
+ MSG_JOB_ARCHER = 0x65f,
+/*20091208 to latest
+어콜라이트
+Acolyte
+*/
+ MSG_JOB_ACOLYTE = 0x660,
+/*20091208 to latest
+머첸트
+Merchant
+*/
+ MSG_JOB_MERCHANT = 0x661,
+/*20091208 to latest
+씨프
+Thief
+*/
+ MSG_JOB_THIEF = 0x662,
+/*20091208 to latest
+나이트
+Knight
+*/
+ MSG_JOB_KNIGHT = 0x663,
+/*20091208 to latest
+프리스트
+Priest
+*/
+ MSG_JOB_PRIEST = 0x664,
+/*20091208 to latest
+위저드
+Wizard
+*/
+ MSG_JOB_WIZARD = 0x665,
+/*20091208 to latest
+블랙스미스
+Black Smith
+*/
+ MSG_JOB_BLACKSMITH = 0x666,
+/*20091208 to latest
+헌터
+Hunter
+*/
+ MSG_JOB_HUNTER = 0x667,
+/*20091208 to latest
+어새신
+Assasin
+*/
+ MSG_JOB_ASSASSIN = 0x668,
+/*20091208 to latest
+크루세이더
+Crusader
+*/
+ MSG_JOB_CRUSADER = 0x669,
+/*20091208 to latest
+몽크
+Monk
+*/
+ MSG_JOB_MONK = 0x66a,
+/*20091208 to latest
+세이지
+Sage
+*/
+ MSG_JOB_SAGE = 0x66b,
+/*20091208 to latest
+로그
+Rogue
+*/
+ MSG_JOB_ROGUE = 0x66c,
+/*20091208 to latest
+알케미스트
+Alchemist
+*/
+ MSG_JOB_ALCHEMIST = 0x66d,
+/*20091208 to latest
+바드
+Bard
+*/
+ MSG_JOB_BARD = 0x66e,
+/*20091208 to latest
+댄서
+Dancer
+*/
+ MSG_JOB_DANCER = 0x66f,
+/*20091208 to 20100310
+룬나이트
+20100316 to latest
+룬 나이트
+Rune Knight
+*/
+ MSG_JOB_RUNE_KNIGHT = 0x670,
+/*20091208 to latest
+워록
+Warlock
+*/
+ MSG_JOB_WARLOCK = 0x671,
+/*20091208 to latest
+레인져
+Ranger
+*/
+ MSG_JOB_RANGER = 0x672,
+/*20091208 to 20100310
+아크비숍
+20100316 to latest
+아크 비숍
+Arc Bishop
+*/
+ MSG_JOB_ARCHBISHOP = 0x673,
+/*20091208 to latest
+미케닉
+Mechanic
+*/
+ MSG_JOB_MECHANIC = 0x674,
+/*20091208 to 20100310
+길로틴크로스
+20100316 to latest
+길로틴 크로스
+Guillotine Cross
+*/
+ MSG_JOB_GUILLOTINE_CROSS = 0x675,
+/*20091208 to latest
+로얄가드
+Royal Guard
+*/
+ MSG_JOB_ROYAL_GUARD = 0x676,
+/*20091208 to latest
+소서러
+Sorcerer
+*/
+ MSG_JOB_SORCERER = 0x677,
+/*20091208 to latest
+민스트럴
+Minstrel
+*/
+ MSG_JOB_MINSTREL = 0x678,
+/*20091208 to latest
+원더러
+Wanderer
+*/
+ MSG_JOB_WANDERER = 0x679,
+/*20091208 to latest
+수라
+Sura
+*/
+ MSG_JOB_SURA = 0x67a,
+/*20091208 to latest
+제네릭
+Genetic
+*/
+ MSG_JOB_GENETIC = 0x67b,
+/*20091208 to 20100310
+쉐도우체이서
+20100316 to latest
+쉐도우 체이서
+Shadow Chaser
+*/
+ MSG_JOB_SHADOW_CHASER = 0x67c,
+/*20091208 to 20100113
+소드맨_하이
+20100119 to latest
+소드맨 하이
+High Swordman
+*/
+ MSG_JOB_SWORDMAN_H = 0x67d,
+/*20091208 to 20100113
+매지션_하이
+20100119 to latest
+매지션 하이
+High Magician
+*/
+ MSG_JOB_MAGICIAN_H = 0x67e,
+/*20091208 to 20100113
+아처_하이
+20100119 to latest
+아처 하이
+High Archer
+*/
+ MSG_JOB_ARCHER_H = 0x67f,
+/*20091208 to 20100113
+어콜라이트_하이
+20100119 to latest
+어콜라이트 하이
+High Acolyte
+*/
+ MSG_JOB_ACOLYTE_H = 0x680,
+/*20091208 to 20100113
+머첸트_하이
+20100119 to latest
+머첸트 하이
+High Merchant
+*/
+ MSG_JOB_MERCHANT_H = 0x681,
+/*20091208 to 20100113
+시프_하이
+20100119 to 20100223
+시프 하이
+20100302 to latest
+씨프 하이
+High Thief
+*/
+ MSG_JOB_THIEF_H = 0x682,
+/*20091208 to latest
+로드나이트
+Lord Knight
+*/
+ MSG_JOB_KNIGHT_H = 0x683,
+/*20091208 to latest
+하이프리스트
+High Priest
+*/
+ MSG_JOB_PRIEST_H = 0x684,
+/*20091208 to latest
+하이위저드
+High Wizard
+*/
+ MSG_JOB_WIZARD_H = 0x685,
+/*20091208 to latest
+화이트스미스
+White Smith
+*/
+ MSG_JOB_BLACKSMITH_H = 0x686,
+/*20091208 to latest
+스나이퍼
+Sniper
+*/
+ MSG_JOB_HUNTER_H = 0x687,
+/*20091208 to latest
+어새신크로스
+Assasin Cross
+*/
+ MSG_JOB_ASSASSIN_H = 0x688,
+/*20091208 to latest
+팔라딘
+Paladin
+*/
+ MSG_JOB_CRUSADER_H = 0x689,
+/*20091208 to latest
+챔피온
+Champion
+*/
+ MSG_JOB_MONK_H = 0x68a,
+/*20091208 to latest
+프로페서
+Professor
+*/
+ MSG_JOB_SAGE_H = 0x68b,
+/*20091208 to latest
+스토커
+Stalker
+*/
+ MSG_JOB_ROGUE_H = 0x68c,
+/*20091208 to latest
+크리에이터
+Creator
+*/
+ MSG_JOB_ALCHEMIST_H = 0x68d,
+/*20091208 to latest
+클로운
+Clown
+*/
+ MSG_JOB_BARD_H = 0x68e,
+/*20091208 to latest
+집시
+Gypsy
+*/
+ MSG_JOB_DANCER_H = 0x68f,
+/*20091208 to latest
+노비스
+Wedding
+*/
+ MSG_JOB_NOVICE = 0x690,
+/*20091208 to latest
+하이노비스
+High Novice
+*/
+ MSG_JOB_NOVICE_H = 0x691,
+/*20091208 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_JOB_SUPERNOVICE = 0x692,
+/*20091208 to latest
+건슬링거
+Gunslinger
+*/
+ MSG_JOB_GUNSLINGER = 0x693,
+/*20091208 to latest
+닌자
+Ninja
+*/
+ MSG_JOB_NINJA = 0x694,
+/*20091208 to 20100105
+태권소녀,태권소년
+20100112 to 20100310
+태권소년소녀
+20100316 to latest
+태권소년/소녀
+Taekwon F/M
+*/
+ MSG_JOB_TAEKWON = 0x695,
+/*20091208 to latest
+권성
+Star Gladiator
+*/
+ MSG_JOB_STAR = 0x696,
+/*20091208 to latest
+소울링커
+Soul Linker
+*/
+ MSG_JOB_LINKER = 0x697,
+/*20091208 to latest
+파티모집
+Party Recruitment
+*/
+ MSG_SEEK_PARTY_MEMBER = 0x698,
+/*20091208 to 20100310
+파티 부킹 리스트
+20100316 to latest
+파티 모집 리스트
+Party Booking List
+*/
+ MSG_SEEK_PARTY_LIST = 0x699,
+/*20091208 to latest
+파티 모집 중
+Recruiting Party
+*/
+ MSG_SEEK_PARTY_CHECK = 0x69a,
+#endif
+#if PACKETVER >= 20091215
+/*20091215 to latest
+[활]을 장착한 상태여야 합니다.
+[Bow] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_BOW = 0x69b,
+/*20091215 to latest
+[악기/채찍]을 장착한 상태여야 합니다.
+[Musical Instrument/Whip] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_INSTRUMENT_WHIP = 0x69c,
+/*20091215 to latest
+영문과 숫자만 사용가능합니다.
+Only alphanumeric characters are allowed.
+*/
+ MSG_BAD_CHAR = 0x69d,
+/*20091215 to latest
+알림
+Notice
+*/
+ MSG_ALRAM = 0x69e,
+/*20091215 to latest
+상점 정보가 정확하지 않아 아이템 구매가 실패하였습니다.
+Item purchase failed due to incorrect shop information.
+*/
+ MSG_FAIL_BUY_ITEM_INVALID_MCSTORE = 0x69f,
+#endif
+#if PACKETVER >= 20100105
+/*20100105 to latest
+소지 아이템 창에서 버릴 수 있습니다.
+Item cannot be discarded from the window.
+*/
+ MSG_CAN_DROP_ITEM_TO_ITEMWND = 0x6a0,
+#endif
+#if PACKETVER >= 20100112
+/*20100112 to latest
+시간
+Time
+*/
+ MSG_TIME = 0x6a1,
+/*20100112 to latest
+맵
+Map
+*/
+ MSG_MAP = 0x6a2,
+/*20100112 to latest
+거래 상태에서는 아이템 사용 및 장비 착용/해제를 할 수 없습니다.
+You can't use, equip or disarm items when you're trading.
+*/
+ MSG_CANT_USE_WHEN_OPENED_EXCHANGEWND = 0x6a3,
+/*20100112 to latest
+미지정값
+Unspecified value
+*/
+ MSG_HOTKEY_UNKOWN = 0x6a4,
+#endif
+#if PACKETVER >= 20100126
+/*20100126 to latest
+/stateinfo : 상태 아이콘에 대한 설명을 보여줍니다. On Off
+/stateinfo: Shows the description of status icons. On Off
+*/
+ MSG_EXPLAIN_STATEINFO = 0x6a5,
+/*20100126 to latest
+상태 정보 On : 상태 아이콘에 대한 설명이 표시됩니다.
+Status Information On: Status icon description is enabled.
+*/
+ MSG_SHOW_STATEINFO_ON = 0x6a6,
+/*20100126 to latest
+상태 정보 Off: 상태 아이콘에 대한 설명이 표시되지 않습니다.
+Status Information Off: Status icon description is disabled.
+*/
+ MSG_SHOW_STATEINFO_OFF = 0x6a7,
+/*20100126 to 20100126
+같은 아이템은 한번에 %d개 이상은 살수 없습니다.
+20100202 to latest
+같은 아이템은 한번에 %d개 이상은 살 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_BUY_ITEM2 = 0x6a8,
+#endif
+#if PACKETVER >= 20100202
+/*20100202 to latest
+같은 아이템은 한번에 %d개 이상은 팔 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_SELL_ITEM = 0x6a9,
+/*20100202 to 20100203
+총 구매 가능 개수는 %d개 입니다.
+20100209 to latest
+해당 아이템의 총 구매 가능 개수는 %d개 입니다.
+Can purchase upto %d pieces of the same item at a time.
+*/
+ MSG_CAN_BUY_ITEM_NUM = 0x6aa,
+#endif
+#if PACKETVER >= 20100209
+/*20100209 to latest
+설정한 내용은 정상 종료 시 [%s\%s]에 저장됩니다.
+User customized key is saved to [%s\%s]
+*/
+ MSG_SAVE_HOTKEY_TO_FILE = 0x6ab,
+#endif
+#if PACKETVER >= 20100216
+/*20100216 to latest
+[%s] 님은 현재 교환 신청을 받을 수 없는 상태입니다.
+[%s] is currently on trade and cannot accept the request.
+*/
+ MSG_CHARACTER_IS_BUSY = 0x6ac,
+#endif
+#if PACKETVER >= 20100309
+/*20100309 to latest
+RO_HELP
+RO_HELP.
+*/
+ MSG_RO_HELP = 0x6ad,
+#endif
+#if PACKETVER >= 20100316
+/*20100316 to latest
+모루가 존재 하지 않습니다.
+Anvil does not exist.
+*/
+ MSG_HAVENOT_ANVIL = 0x6ae,
+/*20100316 to latest
+노비스 레벨 10 이하는 귓속말이 금지됩니다
+Novice below level 10 is not allowed to whisper.
+*/
+ MSG_WHISPER_BLOCK_NOVICE_LEVEL10 = 0x6af,
+#endif
+#if PACKETVER >= 20100323
+/*20100323 to latest
+공격
+Attack
+*/
+ MSG_JOB_ATTACKER = 0x6b0,
+/*20100323 to latest
+방어
+Defense
+*/
+ MSG_JOB_TANKER = 0x6b1,
+/*20100323 to latest
+회복
+Consumables
+*/
+ MSG_JOB_HEALER = 0x6b2,
+/*20100323 to latest
+보조
+Support
+*/
+ MSG_JOB_ASSISTANCE = 0x6b3,
+/*20100323 to latest
+파티 모집 관련 명령어
+Party recruitment related command
+*/
+ MSG_DESCRIBE_PARTY_BOOKING = 0x6b4,
+#endif
+#if PACKETVER >= 20100330
+/*20100330 to latest
+길드 동맹신청이 불가능합니다
+Guild alliance application is not possible.
+*/
+ MSG_GUILD_ALLY_REQUEST_DISABLE = 0x6b5,
+/*20100330 to latest
+길드 적대신청이 불가능합니다
+Guild hostility application is not possible.
+*/
+ MSG_GUILD_HOSTILE_REQUEST_DISABLE = 0x6b6,
+/*20100330 to latest
+아지트맵에서는 친구추가가 불가능합니다
+Adding friends is not possible in this map.
+*/
+ MSG_FRIEND_ADD_FALSE_AGIT = 0x6b7,
+#endif
+#if PACKETVER >= 20100406
+/*20100406 to latest
+구매노점 개설
+Buying Store Window
+*/
+ MSG_BUYINGSTORE_MAKEWND_TITLE = 0x6b8,
+/*20100406 to latest
+구매가 :
+Price:
+*/
+ MSG_BUYINGSTORE_MAKEWND_PRICE = 0x6b9,
+/*20100406 to latest
+소지액 :
+Money:
+*/
+ MSG_BUYINGSTORE_MAKEWND_MYZENY = 0x6ba,
+/*20100406 to latest
+구매 한도액
+Purchase Zeny Limit
+*/
+ MSG_BUYINGSTORE_MAKEWND_LIMITZENY = 0x6bb,
+/*20100406 to 20100414
+판매 가능한 아이템 목록
+Available items:
+20100420 to latest
+구매할 아이템을 등록하지 않았습니다. 구매하실 아이템을 등록해 주세요
+Please register the item first that has to be purchased.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADDITEM = 0x6bc,
+/*20100406 to 20100414
+나의 구매노점
+Purchase list:
+20100420 to latest
+%s 아이템의 가격을 입력해 주세요.
+Enter the price for item %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTPRICE = 0x6bd,
+/*20100406 to 20100414
+구매 노점
+Wanted items
+20100420 to latest
+%s 아이템의 가격을 9999만 Zeny이하로 입력해 주세요.
+Enter the price for item %s. It has to be below 99990000 Zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTPRICE = 0x6be,
+/*20100406 to 20100414
+제한금액 : %d Zeny
+20100420 to latest
+%s 아이템의 구매수량을 입력해 주세요.
+Enter the item number for %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTNUM = 0x6bf,
+/*20100406 to 20100414
+%s %s Zeny %d 개
+Buying %s for %s Zeny. Amount: %d.
+20100420 to latest
+%s 아이템의 소지수량과 구매수량의 합이 9999개 이상입니다. 9999개 이하의 수량을 입력해 주세요.
+The sum of purchasing and belonging items is over 9999. The sum has to be bellow 9999.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTNUM = 0x6c0,
+/*20100406 to 20100414
+%s : %s Zeny => %s EA
+%s: %s Zeny => %s ea.
+20100420 to latest
+중복된 아이템이 존재합니다.
+You have duplicate items in your purchase list.
+*/
+ MSG_BUYINGSTORE_MAKEWND_DUPLICATEITEM = 0x6c1,
+/*20100406 to 20100414
+%s %d 개 구매.
+20100420 to latest
+제한 금액을 입력해 주세요
+Enter the limited price.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTLIMITZENY = 0x6c2,
+/*20100406 to 20100414
+아이템을 모두 구매했습니다.
+You purchased all items.
+20100420 to latest
+입력한 제한금액이 소지금액을 초과합니다. 다시 설정해 주세요
+You have entered a greater amount of zeny than you have. Please check your zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTLIMITZENY = 0x6c3,
+/*20100406 to 20100414
+해당 아이템의 총 판매 가능 개수는 %d개 입니다.
+The max. number of items you can sell is %d.
+20100420 to latest
+%s : %s Zeny => %s EA
+%s: %s Zeny => %s ea.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ITEMLIST = 0x6c4,
+/*20100406 to 20100414
+가격이 0 Zeny인 아이템이 존재합니다. 가격을 입력해 주세요.
+20100420 to latest
+구매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORBUYITEMLIST = 0x6c5,
+/*20100406 to 20100414
+가격이 9999만 Zeny이상인 아이템이 존재합니다. 9999만 Zeny 이하의 가격을 입력해 주세요.
+20100420 to latest
+나의 구매노점
+Purchase list:
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_TITLE = 0x6c6,
+/*20100406 to 20100414
+구매수량이 0 개인 아이템이 존재합니다. 수량을 입력해 주세요.
+20100420 to 20110208
+제한금액 : %d Zeny
+20110215 to latest
+제한금액 : %s Zeny
+Price limit: %s Zeny
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_LIMITZENY = 0x6c7,
+/*20100406 to 20100414
+구매수량이 9999개 이상인 아이템이 존재합니다. 9999개 이하의 수량을 입력해 주세요.
+20100420 to latest
+%s %s Zeny %d 개
+Buying %s for %s Zeny. Amount: %d.
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_ITEMINFO = 0x6c8,
+/*20100406 to 20100414
+중복된 아이템이 존재합니다.
+You have duplicate items in your purchase list.
+20100420 to latest
+구매 노점
+Wanted items
+*/
+ MSG_BUYINGSTORE_SHOPWND_TITLE = 0x6c9,
+/*20100406 to 20100414
+구매상점 열기에 실패했습니다.
+20100420 to latest
+판매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORSELLWND_TITLE = 0x6ca,
+/*20100406 to 20100414
+구매상점 열기에 실패했습니다.
+20100420 to latest
+해당 아이템의 총 판매 가능 개수는 %d개 입니다.
+The max. number of items you can sell is %d.
+*/
+ MSG_BUYINGSTORE_SELLWND_LIMITNUM = 0x6cb,
+/*20100406 to 20100414
+구매가능한 최대 갯수를 초과하였습니다.
+20100420 to 20110208
+구매자의 잔액이 부족하니 다시 설정해 주세요
+20110215 to latest
+구매노점의 제한금액을 초과하여 판매할 수 없습니다.
+Buyer has insufficient money, lower the amount of items you're selling.
+*/
+ MSG_BUYINGSTORE_SELLWND_LACKBUYERZENY = 0x6cc,
+/*20100406 to 20100414
+남은 잔액으로 아이템 구매가 불가능 합니다.
+20100420 to latest
+구매상점 개설에 실패했습니다.
+Failed to open purchase shop.
+*/
+ MSG_BUYINGSTORE_OPEN_FAILED = 0x6cd,
+#endif
+#if PACKETVER >= 20100413
+/*20100413 to 20100414
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+20100420 to latest
+아이템의 총 무게가 %d 만큼 소지 한계량을 초과합니다. 다시 설정해 주세요.
+You exceed the total amount of items.
+*/
+ MSG_BUYINGSTORE_OVERWEIGHT = 0x6ce,
+/*20100413 to 20100414
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+20100420 to latest
+제한금액만큼의 아이템을 모두 구매하였습니다.
+You have purchased all items within the limited price.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERLIMITZENY = 0x6cf,
+#endif
+#if PACKETVER >= 20100420
+/*20100420 to latest
+아이템을 모두 구매했습니다.
+You purchased all items.
+*/
+ MSG_BUYINGSTORE_TRADE_BUYCOMPLETE = 0x6d0,
+/*20100420 to latest
+구매자의 잔액이 부족하여 거래가 실패하였습니다.
+Failed to deal because you have not enough Zeny.
+*/
+ MSG_BUYINGSTORE_TRADE_LACKBUYERZENY = 0x6d1,
+/*20100420 to latest
+%s %d개를 %dz에 판매하였습니다.
+You have sold %s. Amount: %d. Total Zeny: %dz
+*/
+ MSG_BUYINGSTORE_TRADE_SELLCOMPLETE = 0x6d2,
+/*20100420 to latest
+%s 아이템은 희망 구매갯수보다 수량이 많아 판매하지 못하였습니다
+%s item could not be sold because you do not have the wanted amount of items.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERCOUNT = 0x6d3,
+/*20100420 to latest
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+20130807 to 20130814
+판매할 아이템을 등록하지 않았습니다. 판매하실 아이템을 등록해 주세요
+Has not registered to sell the item. Please register to sell the item
+*/
+ MSG_USESKILL_FAIL_EL_SUMMON = 0x6d4,
+/*20100420 to latest
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+20130807 to 20130814
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+*/
+ MSG_AGAINSTSERVERSIEGEWARFARE_RESTRICTION = 0x6d5,
+/*20100420 to latest
+OTP 비밀번호는 6자리 입니다.
+OTP password is 6 digits long.
+20130807 to 20130814
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+*/
+ MSG_OTP_MUST_6_CHAR = 0x6d6,
+/*20100420 to latest
+OTP 정보가 없습니다. 관리자에게 문의하시기 바랍니다.
+OTP information is unavailable. Please contact your administrator.
+20130807 to 20130814
+OTP 비밀번호는 6자리 입니다.
+OTP password is 6 digits long.
+*/
+ MSG_DB_ERROR = 0x6d7,
+/*20100420 to latest
+OTP 인증에 실패 했습니다.
+OTP authentication failed.
+20130807 to 20130814
+OTP 정보가 없습니다. 관리자에게 문의하시기 바랍니다.
+OTP information is unavailable. Please contact your administrator.
+*/
+ MSG_OTP_FAILED = 0x6d8,
+/*20100420 to latest
+파티광고가 추가되었습니다
+Party ad has been added.
+20130807 to 20130814
+OTP 인증에 실패 했습니다.
+OTP authentication failed.
+*/
+ MSG_PARTY_BOOKING_NOTIFY = 0x6d9,
+/*20100420 to 20110719
+파티원 모집 중
+20110726 to latest
+모집 중
+Recruit party members
+20130807 to 20130814
+파티광고가 추가되었습니다
+Party ad has been added.
+*/
+ MSG_PARTY_BOOKING_REQURT = 0x6da,
+/*20100420 to latest
+역할
+Roles
+20130807 to 20130814
+모집 중
+Recruit party members
+*/
+ MSG_PARTY_BOOKING_TYPE = 0x6db,
+/*20100420 to latest
+1차 직업
+1st Jobs
+20130807 to 20130814
+역할
+Roles
+*/
+ MSG_PARTY_BOOKING_TYPE_1 = 0x6dc,
+/*20100420 to latest
+2차 직업
+2nd Jobs
+20130807 to 20130814
+1차 직업
+1st Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_2 = 0x6dd,
+/*20100420 to latest
+3-1차 직업
+3-1 Classes
+20130807 to 20130814
+2차 직업
+2nd Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_3_1 = 0x6de,
+/*20100420 to latest
+3-2차 직업
+3-2 Classes
+20130807 to 20130814
+3-1차 직업
+3-1 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_3_2 = 0x6df,
+/*20100420 to latest
+전승 1차 직업
+1st Job High
+20130807 to 20130814
+3-2차 직업
+3-2 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_1PLUS = 0x6e0,
+/*20100420 to latest
+전승 2차 직업
+2nd Jobs High
+20130807 to 20130814
+전승 1차 직업
+1st Job High
+*/
+ MSG_PARTY_BOOKING_TYPE_2PLUS = 0x6e1,
+/*20100420 to latest
+기타 직업군
+Other Jobs
+20130807 to 20130814
+전승 2차 직업
+2nd Jobs High
+*/
+ MSG_PARTY_BOOKING_TYPE_ETC = 0x6e2,
+/*20100420 to latest
+모집 하기
+Recruit
+20130807 to 20130814
+기타 직업군
+Other Jobs
+*/
+ MSG_PARTY_BOOKING_REQURTING = 0x6e3,
+/*20100420 to latest
+파티원을 모집합니다.
+Open party recruitment window.
+20130807 to 20130814
+모집 하기
+Recruit
+*/
+ MSG_PARTY_BOOKING_REQURT_TIP = 0x6e4,
+/*20100420 to 20110719
+검색중 -
+20110726 to latest
+검색 중 -
+Searching -
+20130807 to 20130814
+파티원을 모집합니다.
+Open party recruitment window.
+*/
+ MSG_PARTY_BOOKING_SEARCH = 0x6e5,
+/*20100420 to latest
+모두 선택
+Select All
+20130807 to 20130814
+검색 중 -
+Searching -
+*/
+ MSG_PARTY_BOOKING_ALL_SELECT = 0x6e6,
+/*20100420 to latest
+최소한 하나의 직업이 모집 중이어야 합니다.
+Recruitment of at least one job must be running.
+20130807 to 20130814
+모두 선택
+Select All
+*/
+ MSG_PARTY_BOOKING_ERR1 = 0x6e7,
+/*20100420 to latest
+최소 1개이상의 직업을 선택해 주셔야 합니다.
+You have to select atleast 1 or more jobs.
+20130807 to 20130814
+최소한 하나의 직업이 모집 중이어야 합니다.
+Recruitment of at least one job must be running.
+*/
+ MSG_PARTY_BOOKING_ERR2 = 0x6e8,
+/*20100420 to latest
+선택된 직업은 %d개입니다. 최대 6개까지만 직업을 선택할 수 있습니다.
+You have selected %d Jobs. You can only select up to 6 different jobs.
+20130807 to 20130814
+최소 1개이상의 직업을 선택해 주셔야 합니다.
+You have to select atleast 1 or more jobs.
+*/
+ MSG_PARTY_BOOKING_ERR3 = 0x6e9,
+/*20100420 to latest
+레벨에 숫자 이외의 문자는 들어갈 수 없습니다.
+Only numeric characters are allowed.
+20130807 to 20130814
+선택된 직업은 %d개입니다. 최대 6개까지만 직업을 선택할 수 있습니다.
+You have selected %d Jobs. You can only select up to 6 different jobs.
+*/
+ MSG_PARTY_BOOKING_ERR4 = 0x6ea,
+/*20100420 to latest
+레벨은 1~150 사이의 숫자를 입력해 주세요.
+Please enter levels between 1~150.
+20130807 to 20130814
+레벨에 숫자 이외의 문자는 들어갈 수 없습니다.
+Only numeric characters are allowed.
+*/
+ MSG_PARTY_BOOKING_ERR5 = 0x6eb,
+#endif
+#if PACKETVER >= 20100511
+/*20100511 to latest
+ 해당 맵에서는 의상 장비가 보이지 않습니다.
+Nothing found in the selected map.
+20130807 to 20130814
+레벨은 1~150 사이의 숫자를 입력해 주세요.
+Please enter levels between 1~150.
+*/
+ MSG_DISABLE_COSTUMEITEM_MAP = 0x6ec,
+#endif
+#if PACKETVER >= 20100525
+/*20100525 to latest
+아이템을 착용할 수 있는 레벨이 아닙니다.
+You cannot equip this item with your current level.
+20130807 to 20130814
+ 해당 맵에서는 의상 장비가 보이지 않습니다.
+Nothing found in the selected map.
+*/
+ MSG_CANNOT_EQUIP_ITEM_LEVEL = 0x6ed,
+/*20100525 to latest
+아이템을 사용할 수 있는 레벨이 아닙니다.
+You cannot use this item with your current level.
+20130807 to 20130814
+아이템을 착용할 수 있는 레벨이 아닙니다.
+You cannot equip this item with your current level.
+*/
+ MSG_CANNOT_USE_ITEM_LEVEL = 0x6ee,
+#endif
+#if PACKETVER >= 20100601
+/*20100601 to latest
+ 채팅모드 OnOff 활성화
+Enable Battlemode
+20130807 to 20130814
+아이템을 사용할 수 있는 레벨이 아닙니다.
+You cannot use this item with your current level.
+*/
+ MSG_CHATMODE_ONOFF = 0x6ef,
+/*20100601 to latest
+탭사이즈 크기가 초과되어 추가할 수 없습니다.
+Failed to add because you have reached the limit.
+20130807 to 20130814
+ 채팅모드 OnOff 활성화
+Enable Battlemode
+*/
+ MSG_OVER_TABSIZE = 0x6f0,
+/*20100601 to 20100601
+ 창 표시 정보.
+20100608 to latest
+ 창 표시 정보
+Window Sign Information
+20130807 to 20130814
+탭사이즈 크기가 초과되어 추가할 수 없습니다.
+Failed to add because you have reached the limit.
+*/
+ MSG_SET_CHATINFO = 0x6f1,
+#endif
+#if PACKETVER >= 20100608
+/*20100608 to latest
+판매
+Sell
+20130807 to 20130814
+ 창 표시 정보
+Window Sign Information
+*/
+ MSG_SELL = 0x6f2,
+/*20100608 to latest
+구매
+Purchase
+20130807 to 20130814
+판매
+Sell
+*/
+ MSG_BUY = 0x6f3,
+/*20100608 to latest
+노점 검색
+Search for Vends
+20130807 to 20130814
+구매
+Purchase
+*/
+ MSG_SEARCH_STOREINFO = 0x6f4,
+/*20100608 to latest
+노점 이름
+Shop Name
+20130807 to 20130814
+노점 검색
+Search for Vends
+*/
+ MSG_STORE_NAME = 0x6f5,
+/*20100608 to latest
+수량
+Quantity
+20130807 to 20130814
+노점 이름
+Shop Name
+*/
+ MSG_SEARCH_ITEM_COUNT = 0x6f6,
+/*20100608 to latest
+가격
+Cost
+20130807 to 20130814
+수량
+Quantity
+*/
+ MSG_SEARCH_ITEM_PRICE = 0x6f7,
+/*20100608 to latest
+검색 결과가 너무 많습니다. 검색어를 자세히 입력 해 주세요.
+Too much results have been found. Please do a more precisely search.
+20130807 to 20130814
+가격
+Cost
+*/
+ MSG_SSI_FAILED_OVER_MAXCOUNT = 0x6f8,
+/*20100608 to latest
+해당 노점을 여시겠습니까?
+Do you want to open a street stall?
+20130807 to 20130814
+검색 결과가 너무 많습니다. 검색어를 자세히 입력 해 주세요.
+Too much results have been found. Please do a more precisely search.
+*/
+ MSG_OPEN_SEARCH_STORE = 0x6f9,
+/*20100608 to latest
+SSO 인증에 실패하였습니다.
+Failed to recognize SSO.
+20130807 to 20130814
+해당 노점을 여시겠습니까?
+Do you want to open a street stall?
+*/
+ MSG_SSO_FAILED = 0x6fa,
+#endif
+#if PACKETVER >= 20100615
+/*20100615 to latest
+현재 해당지역으로 이동 할 수 없습니다
+Cannot move to the applied area.
+20130807 to 20130814
+SSO 인증에 실패하였습니다.
+Failed to recognize SSO.
+*/
+ MSG_ZONE_MOVE_FAIL = 0x6fb,
+/*20100615 to 20100622
+포함 검색
+20100629 to latest
+단어가 포함된 아이템 검색
+searching item including the word
+20130807 to 20130814
+현재 해당지역으로 이동 할 수 없습니다
+Cannot move to the applied area.
+*/
+ MSG_SEARCH_INCLUDED = 0x6fc,
+/*20100615 to latest
+탈퇴한 유저입니다.
+User has been expelled.
+20130807 to 20130814
+단어가 포함된 아이템 검색
+searching item including the word
+*/
+ MSG_WITHDREW_USERS = 0x6fd,
+/*20100615 to latest
+게임 이용에 동의하지 않았습니다.
+You have not accepted the user agreements yet.
+20130807 to 20130814
+탈퇴한 유저입니다.
+User has been expelled.
+*/
+ MSG_DIDNOT_AGREE = 0x6fe,
+/*20100615 to latest
+존재 하지 않는 계정입니다.
+You will not be disconnect from the game.
+20130807 to 20130814
+게임 이용에 동의하지 않았습니다.
+You have not accepted the user agreements yet.
+*/
+ MSG_ACCOUNT_DOESNOT_EXIST = 0x6ff,
+/*20100615 to latest
+본 게임은 12세 이용가입니다.
+It is available only for 12 hours.
+20130807 to 20130814
+존재 하지 않는 계정입니다.
+You will not be disconnect from the game.
+*/
+ MSG_AGE_RESTRICTIONS = 0x700,
+#endif
+#if PACKETVER >= 20100616
+/*20100616 to latest
+계정도용 조사를 위한 블럭상태입니다.
+Your account is blocked due to illegal use of the game account.
+20130807 to 20130814
+본 게임은 12세 이용가입니다.
+It is available only for 12 hours.
+*/
+ MSG_ACCOUNT_BLOCK = 0x701,
+/*20100616 to latest
+버그조사를 위한 블럭상태입니다.
+Your account is blocked because there may exist a bug with your account.
+20130807 to 20130814
+계정도용 조사를 위한 블럭상태입니다.
+Your account is blocked due to illegal use of the game account.
+*/
+ MSG_BUG_BLOCK = 0x702,
+#endif
+#if PACKETVER >= 20100622
+/*20100622 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 75% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 75% for 30 minutes.
+20130807 to 20130814
+버그조사를 위한 블럭상태입니다.
+Your account is blocked because there may exist a bug with your account.
+*/
+ MSG_PLUSEXP75 = 0x703,
+/*20100622 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 50% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 50% for 30 minutes.
+20130807 to 20130814
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 75% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 75% for 30 minutes.
+*/
+ MSG_PLUSEXP50 = 0x704,
+/*20100622 to 20100622
+상점 정보가 정확하지 않아 상점을 열 수 없습니다.
+20100629 to latest
+판매(구매) 정보가 없습니다.
+No sales information.
+20130807 to 20130814
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 50% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 50% for 30 minutes.
+*/
+ MSG_FAIL_OPEN_STORE = 0x705,
+/*20100622 to latest
+더 이상 검색 할 수 없습니다.
+Failed to search any further.
+20130807 to 20130814
+판매(구매) 정보가 없습니다.
+No sales information.
+*/
+ MSG_SSI_FAILED_SEARCH_CNT = 0x706,
+/*20100622 to 20100622
+검색이 실패하였습니다.
+20100629 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+20130807 to 20130814
+더 이상 검색 할 수 없습니다.
+Failed to search any further.
+*/
+ MSG_SSI_FAILED_ITEM_DOES_NOT_EXIST = 0x707,
+/*20100622 to latest
+아직 검색 할 수 없습니다.
+Cannot search yet.
+20130807 to 20130814
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_SSI_FAILED_LIMIT_SERACH_TIME = 0x708,
+#endif
+#if PACKETVER >= 20100629
+/*20100629 to 20100707
+카드 이름, 접두사, 접미사
+20100713 to latest
+카드 이름 또는 접두사(접미사)를 입력하세요
+Enter the card name or prefix/suffix.
+20130807 to 20130814
+아직 검색 할 수 없습니다.
+Cannot search yet.
+*/
+ MSG_SSI_TOOLTIP_OF_SERACHING_THE_CARD = 0x709,
+/*20100629 to latest
+남은 검색 횟수 : %d
+Searches left: %d
+20130807 to 20130814
+카드 이름 또는 접두사(접미사)를 입력하세요
+Enter the card name or prefix/suffix.
+*/
+ MSG_SSI_REST_OF_NUMBER_OF_SEARCHES = 0x70a,
+/*20100629 to latest
+검색 된 노점이 없습니다.
+No result has been found.
+20130807 to 20130814
+남은 검색 횟수 : %d
+Searches left: %d
+*/
+ MSG_SSI_FAILED_SEARCH_STORE = 0x70b,
+/*20100629 to latest
+아이템 가격 범위가 잘못되었습니다.
+The item price is too high.
+20130807 to 20130814
+검색 된 노점이 없습니다.
+No result has been found.
+*/
+ MSG_SSI_FAILED_PRICE_ISNOT_VALID = 0x70c,
+/*20100629 to latest
+일반 장비
+Normal Gear
+20130807 to 20130814
+아이템 가격 범위가 잘못되었습니다.
+The item price is too high.
+*/
+ MSG_GENERAL_EQUIPMENT = 0x70d,
+/*20100629 to latest
+의상 장비
+Costume
+20130807 to 20130814
+일반 장비
+Normal Gear
+*/
+ MSG_COSTUME_EQUIPMENT = 0x70e,
+#endif
+#if PACKETVER >= 20100713
+/*20100713 to latest
+분
+minute
+20130807 to 20130814
+의상 장비
+Costume
+*/
+ MSG_MINUTE = 0x70f,
+/*20100713 to latest
+초
+second
+20130807 to 20130814
+분
+minute
+*/
+ MSG_SECOND = 0x710,
+/*20100713 to latest
+아이템 명을 입력해 주세요.
+Please enter the name of the item.
+20130807 to 20130814
+초
+second
+*/
+ MSG_SSI_FAILED_ENTER_THE_NAME_OF_ITEM = 0x711,
+/*20100713 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+20130807 to 20130814
+아이템 명을 입력해 주세요.
+Please enter the name of the item.
+*/
+ MSG_SSI_FAILED_NAME_OF_ITEM_DOES_NOT_EXIST = 0x712,
+#endif
+#if PACKETVER >= 20100720
+/*20100720 to latest
+진입가능한 맵이 존재하지 않습니다.
+The map is not available.
+20130807 to 20130814
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_NOT_EXIST_ENTRYMAP = 0x713,
+/*20100720 to latest
+해당 카드 이름이나 접두사(접미사)는 존재하지 않습니다.
+The selected name or prefix/suffix does not exist.
+20130807 to 20130814
+진입가능한 맵이 존재하지 않습니다.
+The map is not available.
+*/
+ MSG_SSI_FAILED_NAME_OF_CARD_DOES_NOT_EXIST = 0x714,
+#endif
+#if PACKETVER >= 20100727
+/*20100727 to latest
+ 한번에 구매 가능 종류는 10개입니다.
+You can purchase up to 10 items.
+20130807 to 20130814
+해당 카드 이름이나 접두사(접미사)는 존재하지 않습니다.
+The selected name or prefix/suffix does not exist.
+*/
+ MSG_CASH_FAILED_TOTAL_CNT = 0x715,
+/*20100727 to latest
+ 일부 아이템의 구매가 실패하였습니다.
+Some items could not be purchased.
+20130807 to 20130814
+ 한번에 구매 가능 종류는 10개입니다.
+You can purchase up to 10 items.
+*/
+ MSG_CASH_FAILED_BUY_SOME = 0x716,
+#endif
+#if PACKETVER >= 20100730
+/*20100730 to latest
+생년월일 6자리를 입력하세요.(예시:801122)
+Enter your 6-digit DOB(YYMMDD) (e.g: 801122)
+20130807 to 20130814
+ 일부 아이템의 구매가 실패하였습니다.
+Some items could not be purchased.
+*/
+ MSG_ENTER_PEOPLE_BIRTH = 0x717,
+/*20100730 to latest
+알 수 없는 오류가 발생하였습니다.
+Now Logging Out.
+20130807 to 20130814
+생년월일 6자리를 입력하세요.(예시:801122)
+Enter your 6-digit DOB(YYMMDD) (e.g: 801122)
+*/
+ MSG_RESULT_FAIL_UNKNOWN = 0x718,
+/*20100730 to latest
+데이타 베이스 오류가 발생하였습니다.
+A database error has occurred.
+20130807 to 20130814
+알 수 없는 오류가 발생하였습니다.
+Now Logging Out.
+*/
+ MSG_RESULT_FAIL_DATABASE = 0x719,
+/*20100730 to latest
+캐릭터를 삭제하기 위해서는 길드에서 탈퇴 해야 합니다.
+Please leave your guild first in order to remove your character.
+20130807 to 20130814
+데이타 베이스 오류가 발생하였습니다.
+A database error has occurred.
+*/
+ MSG_RESULT_FAIL_GUILD = 0x71a,
+/*20100730 to latest
+캐릭터를 삭제하기 위해서는 파티에서 탈퇴 해야 합니다.
+Please leave your party first in order to remove your character.
+20130807 to 20130814
+캐릭터를 삭제하기 위해서는 길드에서 탈퇴 해야 합니다.
+Please leave your guild first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_PARTY = 0x71b,
+/*20100730 to latest
+시스템 설정으로 인해 삭제할 수 없습니다.
+You cannot delete this character because the delete time has not expired yet.
+20130807 to 20130814
+캐릭터를 삭제하기 위해서는 파티에서 탈퇴 해야 합니다.
+Please leave your party first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_CONFIGURATION = 0x71c,
+/*20100730 to latest
+아직 삭제 가능 시간이 아닙니다.
+You cannot delete this character at the moment.
+20130807 to 20130814
+시스템 설정으로 인해 삭제할 수 없습니다.
+You cannot delete this character because the delete time has not expired yet.
+*/
+ MSG_RESULT_FAIL_DATE = 0x71d,
+/*20100730 to latest
+생년월일이 일치하지 않습니다.
+Your entered birthday does not match.
+20130807 to 20130814
+아직 삭제 가능 시간이 아닙니다.
+You cannot delete this character at the moment.
+*/
+ MSG_RESULT_FAIL_BIRTH = 0x71e,
+/*20100730 to latest
+친밀도가 부족합니다.
+You lack of familiarity.
+20130807 to 20130814
+생년월일이 일치하지 않습니다.
+Your entered birthday does not match.
+*/
+ MSG_USESKILL_FAIL_RELATIONGRADE = 0x71f,
+/*20100730 to latest
+스타일체인지 파이터 상태에서만 사용가능합니다.
+This is only available on style change for fighting classes.
+20130807 to 20130814
+친밀도가 부족합니다.
+You lack of familiarity.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 0x720,
+/*20100730 to latest
+스타일체인지 그래플러 상태에서만 사용가능합니다.
+This is only available on style change for novice.
+20130807 to 20130814
+스타일체인지 파이터 상태에서만 사용가능합니다.
+This is only available on style change for fighting classes.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 0x721,
+#endif
+#if PACKETVER >= 20100817
+/*20100817 to latest
+파티등록실패
+Party Registration failed.
+20130807 to 20130814
+스타일체인지 그래플러 상태에서만 사용가능합니다.
+This is only available on style change for novice.
+*/
+ MSG_PARTY_REGISTRATION_FAILED = 0x722,
+/*20100817 to latest
+검색된 조건의 리스트가 없습니다.
+results have been found.
+20130807 to 20130814
+파티등록실패
+Party Registration failed.
+*/
+ MSG_PARTY_SEARCH_FAILED = 0x723,
+/*20100817 to latest
+광고삭제에 실패했습니다.
+Failed to remove result.
+20130807 to 20130814
+검색된 조건의 리스트가 없습니다.
+results have been found.
+*/
+ MSG_PARTY_AD_DELETE_FAILED = 0x724,
+/*20100817 to latest
+조건에 맞는 광고가 없어 실패했습니다.
+No results have been found.
+20130807 to 20130814
+광고삭제에 실패했습니다.
+Failed to remove result.
+*/
+ MSG_PARTY_NOT_EXIST_AD = 0x725,
+#endif
+#if PACKETVER >= 20100824
+/*20100824 to latest
+결제 정보가 없습니다.
+No payment information has been found.
+20130807 to 20130814
+조건에 맞는 광고가 없어 실패했습니다.
+No results have been found.
+*/
+ MSG_REFUSE_SSO_NOT_PAY_USER = 0x726,
+/*20100824 to latest
+교환 시 스크린샷 찍기
+Screenshot Trade
+20130807 to 20130814
+결제 정보가 없습니다.
+No payment information has been found.
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE = 0x727,
+/*20100824 to latest
+[거래_%s]
+[Trade_%s]
+20130807 to 20130814
+교환 시 스크린샷 찍기
+Screenshot Trade
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE_CHARNAME = 0x728,
+#endif
+#if PACKETVER >= 20100914
+/*20100914 to 20180124
+사망으로 인해 신생명보험서가 자동 소비되었습니다
+20130807 to 20130814
+[거래_%s]
+[Trade_%s]
+20180207 to latest
+사망 시 소지한 아이템으로 경험치 손실을 막았습니다.
+Death due to the auto insurance young people are spending.
+*/
+ MSG_NOTIFY_NEO_INSURANCE_ITEM_USE = 0x729,
+/*20100914 to latest
+대화
+Chat Dialog
+20130807 to 20130814
+사망으로 인해 신생명보험서가 자동 소비되었습니다
+*/
+ MSG_TALK = 0x72a,
+#endif
+#if PACKETVER >= 20101019
+/*20101019 to latest
+중복사용이 불가능합니다.
+Redundant is not available.
+20130807 to 20130814
+대화
+Chat Dialog
+*/
+ MSG_MACRO_DUPLICATE = 0x72b,
+/*20101019 to latest
+사용제한이 걸려있습니다.
+Use the limit that has been set.
+20130807 to 20130814
+중복사용이 불가능합니다.
+Redundant is not available.
+*/
+ MSG_MACRO_POSTDELAY = 0x72c,
+/*20101019 to latest
+현재 사용제한이 걸려 있지 않습니다.
+No user restrictions are set.
+20130807 to 20130814
+사용제한이 걸려있습니다.
+Use the limit that has been set.
+*/
+ MSG_MACRO_NOT_POSTDELAY = 0x72d,
+/*20101019 to latest
+예기치 못한 사유로 인해 접속이 실패하였습니다. 관리자에게 문의해 주시기 바랍니다.
+Connection has failed. Please contact your administrator.
+20130807 to 20130814
+현재 사용제한이 걸려 있지 않습니다.
+No user restrictions are set.
+*/
+ MSG_SSO_ERROR_MSG = 0x72e,
+/*20101019 to latest
+접속 정보 인증 실패하였습니다.
+Failed to authenticate.
+20130807 to 20130814
+예기치 못한 사유로 인해 접속이 실패하였습니다. 관리자에게 문의해 주시기 바랍니다.
+Connection has failed. Please contact your administrator.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_TOKEN = 0x72f,
+/*20101019 to latest
+가입하지 않은 사용자입니다.
+User is offline.
+20130807 to 20130814
+접속 정보 인증 실패하였습니다.
+Failed to authenticate.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_USER = 0x730,
+/*20101019 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+20130807 to 20130814
+가입하지 않은 사용자입니다.
+User is offline.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_AGE = 0x731,
+/*20101019 to latest
+구매하기
+Buy
+20130807 to 20130814
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_NC_BUY = 0x732,
+/*20101019 to latest
+장바구니 비우기
+Cancel.
+20130807 to 20130814
+구매하기
+Buy
+*/
+ MSG_NC_BLANK = 0x733,
+/*20101019 to latest
+첫 페이지
+First page
+20130807 to 20130814
+장바구니 비우기
+Cancel.
+*/
+ MSG_NC_FIRSTPAGE = 0x734,
+/*20101019 to latest
+마지막 페이지
+Last page
+20130807 to 20130814
+첫 페이지
+First page
+*/
+ MSG_NC_LASTPAGE = 0x735,
+/*20101019 to latest
+신규
+New
+20130807 to 20130814
+마지막 페이지
+Last page
+*/
+ MSG_NC_CAT1 = 0x736,
+/*20101019 to latest
+인기
+Headgears
+20130807 to 20130814
+신규
+New
+*/
+ MSG_NC_CAT2 = 0x737,
+/*20101019 to latest
+한정
+Limited
+20130807 to 20130814
+인기
+Headgears
+*/
+ MSG_NC_CAT3 = 0x738,
+/*20101019 to latest
+임대장비
+Rental Items
+20130807 to 20130814
+한정
+Limited
+*/
+ MSG_NC_CAT4 = 0x739,
+/*20101019 to latest
+영구장비
+Equipments
+20130807 to 20130814
+임대장비
+Rental Items
+*/
+ MSG_NC_CAT5 = 0x73a,
+/*20101019 to latest
+버프
+Scrolls
+20130807 to 20130814
+영구장비
+Equipments
+*/
+ MSG_NC_CAT6 = 0x73b,
+/*20101019 to latest
+회복
+Consumables
+20130807 to 20130814
+버프
+Scrolls
+*/
+ MSG_NC_CAT7 = 0x73c,
+/*20101019 to latest
+기타
+Other
+20130807 to 20130814
+회복
+Consumables
+*/
+ MSG_NC_CAT8 = 0x73d,
+/*20101019 to latest
+가격
+Cost
+20130807 to 20130814
+기타
+Other
+*/
+ MSG_NC_COST = 0x73e,
+/*20101019 to latest
+수량
+Quantity
+20130807 to 20130814
+가격
+Cost
+*/
+ MSG_NC_NUM = 0x73f,
+/*20101019 to latest
+개
+Total
+20130807 to 20130814
+수량
+Quantity
+*/
+ MSG_NC_COUNT = 0x740,
+/*20101019 to latest
+무료 캐시 : %s C
+Free Cash: %s C
+20130807 to 20130814
+개
+Total
+*/
+ MSG_NC_FREECASH = 0x741,
+/*20101019 to latest
+소지 캐시 : %s C
+CashPoints: %s C
+20130807 to 20130814
+무료 캐시 : %s C
+Free Cash: %s C
+*/
+ MSG_NC_CASH = 0x742,
+/*20101019 to latest
+이 지역에서는 몬스터 소환이 불가능합니다.
+You cannot summon a monster in this area.
+20130807 to 20130814
+소지 캐시 : %s C
+CashPoints: %s C
+*/
+ MSG_CALLMONSTER_FAIL_AREA = 0x743,
+#endif
+#if PACKETVER >= 20101109
+/*20101109 to latest
+무료캐시 사용량이 전체 금액을 초과하고있습니다
+Exceeded total free cash
+20130807 to 20130814
+이 지역에서는 몬스터 소환이 불가능합니다.
+You cannot summon a monster in this area.
+*/
+ MSG_BUY_CASH_FAIL2 = 0x744,
+/*20101109 to latest
+ 설정한 내용이 [SaveData_ExMacro%d]에 저장됩니다.
+%d seconds left until you can use
+20130807 to 20130814
+무료캐시 사용량이 전체 금액을 초과하고있습니다
+Exceeded total free cash
+*/
+ MSG_MACRO_SAVE_DATA = 0x745,
+#endif
+#if PACKETVER >= 20101123
+/*20101123 to latest
+약 %d 초 후에 사용할 수 있습니다
+Content has been saved in [SaveData_ExMacro%d]
+20130807 to 20130814
+ 설정한 내용이 [SaveData_ExMacro%d]에 저장됩니다.
+%d seconds left until you can use
+*/
+ MSG_ITEM_REUSE_LIMIT_SECOND = 0x746,
+#endif
+#if PACKETVER >= 20101207
+/*20101207 to latest
+[창]을 장착한 상태여야 합니다.
+~ [Windows] must be equipped with.
+20130807 to 20130814
+약 %d 초 후에 사용할 수 있습니다
+Content has been saved in [SaveData_ExMacro%d]
+*/
+ MSG_FAIL_NEED_EQUIPPED_SPEAR = 0x747,
+#endif
+#if PACKETVER >= 20101214
+/*20101214 to latest
+드래곤 탑승시에만 사용가능합니다.
+Available only on the dragon.
+20130807 to 20130814
+[창]을 장착한 상태여야 합니다.
+~ [Windows] must be equipped with.
+*/
+ MSG_USESKILL_FAIL_DRAGON = 0x748,
+/*20101214 to latest
+본 서버에 접속할 수 있는 정원이 초과되어 진입이 불가능 합니다.
+Unable to proceed due to exceeding capacity.
+20130807 to 20130814
+드래곤 탑승시에만 사용가능합니다.
+Available only on the dragon.
+*/
+ MSG_OVER_CONNECT_USER = 0x749,
+#endif
+#if PACKETVER >= 20101228
+/*20101228 to latest
+실명 인증이 되지 않았습니다. 실명인증 사이트로 이동합니다
+Real name has not been verified. Go to name verification site.
+20130807 to 20130814
+본 서버에 접속할 수 있는 정원이 초과되어 진입이 불가능 합니다.
+Unable to proceed due to exceeding capacity.
+*/
+ MSG_AUTHENTICATE = 0x74a,
+#endif
+#if PACKETVER >= 20110104
+/*20110104 to latest
+저장 할 슬롯을 선택 해 주세요
+Please select slot you are going to save.
+20130807 to 20130814
+실명 인증이 되지 않았습니다. 실명인증 사이트로 이동합니다
+Real name has not been verified. Go to name verification site.
+*/
+ MSG_SELECT_SAVESLOT = 0x74b,
+#endif
+#if PACKETVER >= 20110111
+/*20110111 to latest
+%s, 축하드립니다. '%s' 를 얻으셨습니다!
+Congratulation %s, Acquired '%s' !
+20130807 to 20130814
+저장 할 슬롯을 선택 해 주세요
+Please select slot you are going to save.
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN2 = 0x74c,
+#endif
+#if PACKETVER >= 20110118
+/*20110118 to latest
+그루미상태에서는 사용할 수 없습니다
+Unable to use in gloomy state
+20130807 to 20130814
+%s, 축하드립니다. '%s' 를 얻으셨습니다!
+Congratulation %s, Acquired '%s' !
+*/
+ MSG_NOTUSE_GROOMY = 0x74d,
+#endif
+#if PACKETVER >= 20110215
+/*20110215 to latest
+구매물품의 합계금액이 케릭터가 소지할 수 있는 최대 금액을 초과하였습니다
+Purchased products has exceeded the total price.
+20130807 to 20130814
+그루미상태에서는 사용할 수 없습니다
+Unable to use in gloomy state
+*/
+ MSG_BUYINGSTORE_OVERFLOW_MONEY = 0x74e,
+/*20110215 to latest
+현재 맵에서는 파티 가입이 불가능합니다.
+Cannot join a party in this map.
+20130807 to 20130814
+구매물품의 합계금액이 케릭터가 소지할 수 있는 최대 금액을 초과하였습니다
+Purchased products has exceeded the total price.
+*/
+ MSG_PREVENT_PARTY_JOIN = 0x74f,
+/*20110215 to latest
+현재 맵에서는 파티 탈퇴가 불가능합니다.
+Cannot leave a party in this map.
+20130807 to 20130814
+현재 맵에서는 파티 가입이 불가능합니다.
+Cannot join a party in this map.
+*/
+ MSG_PREVENT_PARTY_LEAVE = 0x750,
+/*20110215 to latest
+현재 맵에서는 파티 추방이 불가능합니다.
+Cannot withdraw/break the party in this map.
+20130807 to 20130814
+현재 맵에서는 파티 탈퇴가 불가능합니다.
+Cannot leave a party in this map.
+*/
+ MSG_PREVENT_PARTY_EXPEL = 0x751,
+/*20110215 to latest
+실제 성명
+Real Name
+20130807 to 20130814
+현재 맵에서는 파티 추방이 불가능합니다.
+Cannot withdraw/break the party in this map.
+*/
+ MSG_SDO_REALNAME = 0x752,
+/*20110215 to latest
+신분증 번호
+ID Number
+20130807 to 20130814
+실제 성명
+Real Name
+*/
+ MSG_SDO_ID_NUMBER = 0x753,
+/*20110215 to latest
+이메일
+E-mail
+20130807 to 20130814
+신분증 번호
+ID Number
+*/
+ MSG_SDO_EMAIL = 0x754,
+/*20110215 to latest
+입력이 올바르지 않습니다
+Invalid input
+20130807 to 20130814
+이메일
+E-mail
+*/
+ MSG_SDO_WRONG_VALUE = 0x755,
+#endif
+#if PACKETVER >= 20110222
+/*20110222 to 20130508
+상대방에게 제니 지급에 실패했습니다.
+20130515 to latest
+상대 캐릭터가 최대 보유제니량을 초과하여 거래가 불가능합니다.
+Failed to send the zeny
+20130807 to 20130814
+입력이 올바르지 않습니다
+Invalid input
+*/
+ MSG_MCSTORE_FAIL_SELLER_MONEY_GIVE = 0x756,
+/*20110222 to latest
+해당 직업이 아닙니다.
+This is not a relevant job
+20130807 to 20130814
+상대 캐릭터가 최대 보유제니량을 초과하여 거래가 불가능합니다.
+Failed to send the zeny
+*/
+ MSG_INVALID_CLASS = 0x757,
+/*20110222 to latest
+해당 성별이 아닙니다.
+This is not a relevant gender
+20130807 to 20130814
+해당 직업이 아닙니다.
+This is not a relevant job
+*/
+ MSG_INVALID_GENDER = 0x758,
+/*20110222 to latest
+유저님의 정보가 인증에 성공했습니다.
+User information identification was successful.
+20130807 to 20130814
+해당 성별이 아닙니다.
+This is not a relevant gender
+*/
+ MSG_SUCCESS_AUTHENTICATE = 0x759,
+/*20110222 to latest
+이름이 일치하지 않습니다. 재작성 해주세요.
+Name does not match. Please retry.
+20130807 to 20130814
+유저님의 정보가 인증에 성공했습니다.
+User information identification was successful.
+*/
+ MSG_INVALID_REALNAME = 0x75a,
+/*20110222 to latest
+신분증 번호가 일치하지 않습니다. 재작성 해주세요.
+ID number does not match. Please retry.
+20130807 to 20130814
+이름이 일치하지 않습니다. 재작성 해주세요.
+Name does not match. Please retry.
+*/
+ MSG_INVALID_IDNUMBER = 0x75b,
+/*20110222 to latest
+현재 서비스에 이상이 있으니 잠시 후 재시도 해주세요.
+Service is currently unavailable. Please try again later.
+20130807 to 20130814
+신분증 번호가 일치하지 않습니다. 재작성 해주세요.
+ID number does not match. Please retry.
+*/
+ MSG_INVALID_AUTHENTICATE = 0x75c,
+#endif
+#if PACKETVER >= 20110224
+/*20110224 to latest
+ 탑승 상태에서는 공격을 할 수 없습니다.
+Unable to attack while riding.
+20130807 to 20130814
+현재 서비스에 이상이 있으니 잠시 후 재시도 해주세요.
+Service is currently unavailable. Please try again later.
+*/
+ MSG_CANNOT_ATTACK_IN_RIDING_STATE = 0x75d,
+/*20110224 to latest
+ 탑승 상태에서는 스킬 시전을 할 수 없습니다.
+Unable to cast the skill while riding.
+20130807 to 20130814
+ 탑승 상태에서는 공격을 할 수 없습니다.
+Unable to attack while riding.
+*/
+ MSG_CANNOT_USE_SKILL_IN_RIDING_STATE = 0x75e,
+#endif
+#if PACKETVER >= 20110228
+/*20110228 to 20110228
+비밀번호는 4자리 이상 6자리이하여야만 합니다.
+20110308 to latest
+비밀번호는 4자리이하여야만 합니다.
+Pin number should be 4~6 characters.
+20130807 to 20130814
+ 탑승 상태에서는 스킬 시전을 할 수 없습니다.
+Unable to cast the skill while riding.
+*/
+ MSG_STORE_PASSWORD_4_6 = 0x75f,
+/*20110228 to 20110228
+로그인에 성공했습니다.
+20110308 to latest
+보안 인증에 성공했습니다.
+Secured authentication is successful.
+20130807 to 20130814
+비밀번호는 4자리이하여야만 합니다.
+Pin number should be 4~6 characters.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_SUCCESS = 0x760,
+/*20110228 to 20110228
+세컨드 패스워드의 생성에 성공했습니다.
+20110308 to latest
+보안 패스워드의 생성에 성공했습니다.
+Succeeded in creating 2nd password.
+20130807 to 20130814
+보안 인증에 성공했습니다.
+Secured authentication is successful.
+*/
+ MSG_SECOND_PASSWORD_MAKE_SUCCESS = 0x761,
+/*20110228 to 20110228
+세컨드 패스워드를 삭제했습니다.
+20110308 to latest
+보안 패스워드를 삭제했습니다.
+2nd password has been deleted.
+20130807 to 20130814
+보안 패스워드의 생성에 성공했습니다.
+Succeeded in creating 2nd password.
+*/
+ MSG_SECOND_PASSWORD_DEL_SUCCESS = 0x762,
+/*20110228 to 20110228
+세컨드 패스워드를 수정했습니다.
+20110308 to latest
+보안 패스워드를 수정했습니다.
+2nd password has been corrected.
+20130807 to 20130814
+보안 패스워드를 삭제했습니다.
+2nd password has been deleted.
+*/
+ MSG_SECOND_PASSWORD_EDIT_SUCCESS = 0x763,
+/*20110228 to 20110228
+로그인에 실패했습니다.
+20110308 to latest
+잘못된 패스워드입니다.(%d회남음)
+Password is incorrect.
+20130807 to 20130814
+보안 패스워드를 수정했습니다.
+2nd password has been corrected.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_FAILED = 0x764,
+/*20110228 to 20110228
+세컨드 패스워드의 생성에 실패했습니다.
+20110308 to latest
+보안 패스워드의 생성에 실패했습니다.
+Failed to create 2nd password.
+20130807 to 20130814
+잘못된 패스워드입니다.(%d회남음)
+Password is incorrect.
+*/
+ MSG_SECOND_PASSWORD_MAKE_FAILED = 0x765,
+/*20110228 to 20110228
+세컨드 패스워드 삭제에 실패했습니다.
+20110308 to latest
+보안 패스워드 삭제에 실패했습니다.
+Failed to delete 2nd password.
+20130807 to 20130814
+보안 패스워드의 생성에 실패했습니다.
+Failed to create 2nd password.
+*/
+ MSG_SECOND_PASSWORD_DEL_FAILED = 0x766,
+/*20110228 to 20110228
+세컨드 패스워드의 수정에 실패했습니다.
+20110308 to latest
+보안 패스워드의 수정에 실패했습니다.
+Failed to correct 2nd password.
+20130807 to 20130814
+보안 패스워드 삭제에 실패했습니다.
+Failed to delete 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_FAILED = 0x767,
+/*20110228 to 20110228
+세컨드 비밀번호에는 제한된 번호를 사용할수 없습니다.
+20110308 to latest
+입력하신패스워드는 사용하실수없습니다.
+Unable to use restricted number in 2nd password.
+20130807 to 20130814
+보안 패스워드의 수정에 실패했습니다.
+Failed to correct 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_RESTRICT_PW = 0x768,
+/*20110228 to latest
+주민등록번호는 사용할수없습니다.
+Unable to use your KSSN number.
+20130807 to 20130814
+입력하신패스워드는 사용하실수없습니다.
+Unable to use restricted number in 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_PERSONALNUM_PW = 0x769,
+/*20110228 to 20110228
+보안번호
+20110308 to latest
+이미 패스워드가 존재합니다.
+~There is already a password.
+20130807 to 20130814
+주민등록번호는 사용할수없습니다.
+Unable to use your KSSN number.
+*/
+ MSG_SECOND_PASSWORD_MAKE_DUPLICATED_PW = 0x76a,
+/*20110228 to 20110228
+비밀번호 입력 (4~6자리)
+20110308 to latest
+보안 패스워드
+Security Code
+20130807 to 20130814
+이미 패스워드가 존재합니다.
+~There is already a password.
+*/
+ MSG_SECOND_PASSWORD = 0x76b,
+/*20110228 to 20110228
+ITEM
+20110308 to latest
+계정보안을 위하여 추가적인 패스워드 설정을 권장합니다.
+Account for the additional password security settings are recommended.
+20130807 to 20130814
+보안 패스워드
+Security Code
+*/
+ MSG_SECOND_PASSWORD_INPUT = 0x76c,
+/*20110228 to 20110228
+SKILL
+20110308 to latest
+보안 패스워드 사용을 하지 않습니다.
+Do not use secure password.
+20130807 to 20130814
+계정보안을 위하여 추가적인 패스워드 설정을 권장합니다.
+Account for the additional password security settings are recommended.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_SUCCESS = 0x76d,
+/*20110228 to 20110228
+TACTIC
+20110308 to latest
+보안 패스워드 사용설정에 실패했습니다.
+Use the set security password failed.
+20130807 to 20130814
+보안 패스워드 사용을 하지 않습니다.
+Do not use secure password.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_FAILED = 0x76e,
+/*20110228 to 20110228
+ETC
+20110308 to latest
+보안 패스워드를 사용합니다. 다음로그인부터 적용됩니다.
+Use secure passwords. Will be applied to your next login.
+20130807 to 20130814
+보안 패스워드 사용설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_SUCCESS = 0x76f,
+/*20110228 to 20110228
+COMBAT
+20110308 to latest
+보안 패스워드 사용 설정에 실패했습니다.
+Use the set security password failed.
+20130807 to 20130814
+보안 패스워드를 사용합니다. 다음로그인부터 적용됩니다.
+Use secure passwords. Will be applied to your next login.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_FAILED = 0x770,
+/*20110228 to 20110228
+NON-COMBAT
+20110308 to latest
+계정보안을 위하여 추가적인 패스워드를 설정합니다.
+Added to the security of your account password is set.
+20130807 to 20130814
+보안 패스워드 사용 설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWORD_INFO_1 = 0x771,
+/*20110228 to 20110228
+BUFF
+20110308 to latest
+아래의 숫자버튼을 마우스를 이용하여 4자리를 클릭하세요.
+Use the mouse to enter the 4-digit password below.
+20130807 to 20130814
+계정보안을 위하여 추가적인 패스워드를 설정합니다.
+Added to the security of your account password is set.
+*/
+ MSG_SECOND_PASSWORD_INFO_2 = 0x772,
+/*20110228 to 20110228
+AUTO EQUIPED
+20110308 to latest
+3회이상 잘못된패스워드 입력으로, 종료됩니다.
+Typing an incorrect password 3 times will shut down the client.
+20130807 to 20130814
+아래의 숫자버튼을 마우스를 이용하여 4자리를 클릭하세요.
+Use the mouse to enter the 4-digit password below.
+*/
+ MSG_SECOND_PASSWORD_INFO_3 = 0x773,
+/*20110228 to 20110228
+1st. ATTACK
+20110308 to latest
+ITEM
+20130807 to 20130814
+3회이상 잘못된패스워드 입력으로, 종료됩니다.
+Typing an incorrect password 3 times will shut down the client.
+*/
+ MSG_MACRO_ITEM = 0x774,
+/*20110228 to 20110228
+ATTACK
+20110308 to latest
+SKILL
+20130807 to 20130814
+ITEM
+*/
+ MSG_MACRO_SKILL = 0x775,
+/*20110228 to 20110228
+Next attack time :
+20110308 to latest
+TACTIC
+20130807 to 20130814
+SKILL
+*/
+ MSG_MACRO_TACTIC = 0x776,
+/*20110228 to 20110228
+When died
+20110308 to latest
+ETC
+20130807 to 20130814
+TACTIC
+*/
+ MSG_MACRO_ETC = 0x777,
+/*20110228 to 20110228
+When invited to a party
+When invited to the party
+20110308 to latest
+COMBAT
+20130807 to 20130814
+ETC
+*/
+ MSG_MACRO_COMBAT = 0x778,
+/*20110228 to 20110228
+Pickup Item
+20110308 to latest
+NON-COMBAT
+20130807 to 20130814
+COMBAT
+*/
+ MSG_MACRO_NON_COMBAT = 0x779,
+/*20110228 to 20110228
+Over 85% Weight
+20110308 to latest
+BUFF
+20130807 to 20130814
+NON-COMBAT
+*/
+ MSG_MACRO_BUFF = 0x77a,
+#endif
+#if PACKETVER >= 20110308
+/*20110308 to latest
+AUTO EQUIPED
+20130807 to 20130814
+BUFF
+*/
+ MSG_MACRO_AUTO_EQUIPED = 0x77b,
+/*20110308 to latest
+1st. ATTACK
+20130807 to 20130814
+AUTO EQUIPED
+*/
+ MSG_MACRO_1ST_ATTACK = 0x77c,
+/*20110308 to latest
+ATTACK
+20130807 to 20130814
+1st. ATTACK
+*/
+ MSG_MACRO_ATTACK = 0x77d,
+/*20110308 to latest
+Next attack time :
+20130807 to 20130814
+ATTACK
+*/
+ MSG_MACRO_NEXT_ATK_TIME = 0x77e,
+/*20110308 to latest
+When died
+20130807 to 20130814
+Next attack time :
+*/
+ MSG_MACRO_WHEN_DIED = 0x77f,
+/*20110308 to latest
+When invited to a party
+When invited to the party
+20130807 to 20130814
+When died
+*/
+ MSG_MACRO_WHEN_INVITED_PARTY = 0x780,
+/*20110308 to latest
+Pickup Item
+20130807 to 20130814
+When invited to a party
+When invited to the party
+*/
+ MSG_MACRO_PICKUP_ITEM = 0x781,
+/*20110308 to latest
+Over 85% Weight
+20130807 to 20130814
+Pickup Item
+*/
+ MSG_MACRO_OVERWEIGHT = 0x782,
+/*20110308 to latest
+진행중이던 작업(NPC대화,제조...)을 종료후에 다시 시도하세요.
+Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+20130807 to 20130814
+Over 85% Weight
+*/
+ MSG_BUSY = 0x783,
+/*20110308 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 %d분간 %.2f배로 증가합니다.
+Monster Job hunting experience that you can get through the doubling of %d is %.2f minutes.
+20130807 to 20130814
+진행중이던 작업(NPC대화,제조...)을 종료후에 다시 시도하세요.
+Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+*/
+ MSG_PLUSONLYJOBEXP2 = 0x784,
+#endif
+#if PACKETVER >= 20110315
+/*20110315 to 20110405
+ExMacro_SaveData%d
+20110412 to latest
+SaveData_ExMacro%d
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 %d분간 %.2f배로 증가합니다.
+Monster Job hunting experience that you can get through the doubling of %d is %.2f minutes.
+*/
+ MSG_MACRO_SAVE = 0x785,
+/*20110315 to latest
+ 설정한 내용이 [%s]에 저장됩니다.
+Settings for [%s] are stored in.
+20130807 to 20130814
+SaveData_ExMacro%d
+*/
+ MSG_MACRO_SAVE_DATA2 = 0x786,
+#endif
+#if PACKETVER >= 20110322
+/*20110322 to latest
+보안레벨
+Security level
+20130807 to 20130814
+ 설정한 내용이 [%s]에 저장됩니다.
+Settings for [%s] are stored in.
+*/
+ MSG_SECOND_PASSWORD_LEVEL = 0x787,
+#endif
+#if PACKETVER >= 20110412
+/*20110412 to latest
+현재 캐릭터는 파티 또는 길드에 가입되어 있어서 삭제가 불가능합니다.
+The current character is a party or join the guild can not be deleted.
+20130807 to 20130814
+보안레벨
+Security level
+*/
+ MSG_RESULT_FAIL_CHAR_DELETE = 0x788,
+#endif
+#if PACKETVER >= 20110517
+/*20110517 to latest
+벽이나 물체 근처에서만 사용 할 수 있습니다.
+Objects can be used only near the wall.
+20130807 to 20130814
+현재 캐릭터는 파티 또는 길드에 가입되어 있어서 삭제가 불가능합니다.
+The current character is a party or join the guild can not be deleted.
+*/
+ MSG_USESKILL_FAIL_NEER_WALL = 0x789,
+#endif
+#if PACKETVER >= 20110531
+/*20110531 to latest
+%s : 레벨 %d %s 파티구합니다.
+%s: Level %d %s party to obtain level.
+20130807 to 20130814
+벽이나 물체 근처에서만 사용 할 수 있습니다.
+Objects can be used only near the wall.
+*/
+ MSG_SEEK_PARTY_SET = 0x78a,
+/*20110531 to latest
+탑승 중인 상태에서는 고삐 아이템을 사용할 수 없습니다.
+While boarding reins is not available for items.
+20130807 to 20130814
+%s : 레벨 %d %s 파티구합니다.
+%s: Level %d %s party to obtain level.
+*/
+ MSG_FAIELD_RIDING_OVERLAPPED = 0x78b,
+#endif
+#if PACKETVER >= 20110622
+/*20110622 to latest
+이 스킬은 1%의 경험치가 필요합니다.
+This skill requires 1% experience.
+20130807 to 20130814
+탑승 중인 상태에서는 고삐 아이템을 사용할 수 없습니다.
+While boarding reins is not available for items.
+*/
+ MSG_USESKILL_FAIL_NEED_EXP_1PERCENT = 0x78c,
+#endif
+#if PACKETVER >= 20110628
+/*20110628 to latest
+경 험 치 :
+Experience value:
+20130807 to 20130814
+이 스킬은 1%의 경험치가 필요합니다.
+This skill requires 1% experience.
+*/
+ MSG_EXP_MSG = 0x78d,
+/*20110628 to latest
+드 롭 율 :
+Drop rate:
+20130807 to 20130814
+경 험 치 :
+Experience value:
+*/
+ MSG_DROP_MSG = 0x78e,
+/*20110628 to latest
+사망페널티 :
+Death Penalty:
+20130807 to 20130814
+드 롭 율 :
+Drop rate:
+*/
+ MSG_DEATH_MSG = 0x78f,
+/*20110628 to 20110713
+%d%% (PC방 %d%% + 프리미엄 %d%% + %s서버 %d%%)
+20110713 to latest
+%d%% (PC방 %d%% + TPLUS %d%% + 프리미엄 %d%% + %s서버 %d%%)
+%d%% (PCroom %d%% + TPLUS %d%% + Premium %d%% + %s Server %d%%)
+20130807 to 20130814
+사망페널티 :
+Death Penalty:
+*/
+ MSG_BASIC_EXP_MSG = 0x790,
+/*20110628 to latest
+ 합창스킬을 시전할 파티원의 SP량이 부족합니다.
+Amount of party members to cast the skill Chorus SP is low.
+20130807 to 20130814
+%d%% (PC방 %d%% + TPLUS %d%% + 프리미엄 %d%% + %s서버 %d%%)
+%d%% (PCroom %d%% + TPLUS %d%% + Premium %d%% + %s Server %d%%)
+*/
+ MSG_USESKILL_FAIL_CHORUS_SP_INSUFFICIENT = 0x791,
+#endif
+#if PACKETVER >= 20110706
+/*20110706 to latest
+상대 캐릭터의 소지 아이템 종류의 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the items can not trade because amount is exceeded.
+20130807 to 20130814
+ 합창스킬을 시전할 파티원의 SP량이 부족합니다.
+Amount of party members to cast the skill Chorus SP is low.
+*/
+ MSG_CHARACTER_IS_OVER_COUNT = 0x792,
+/*20110706 to latest
+상대 캐릭터의 해당 아이템의 소지 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the item amount which exceeds makes it impossible to trade.
+20130807 to 20130814
+상대 캐릭터의 소지 아이템 종류의 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the items can not trade because amount is exceeded.
+*/
+ MSG_CHARACTER_IS_EACHITEM_OVER_COUNT = 0x793,
+/*20110706 to latest
+해당 아이템의 소지 한계량 초과로 구입이 불가능합니다.
+Amounts are exceeded the possession of the item is not available for purchase.
+20130807 to 20130814
+상대 캐릭터의 해당 아이템의 소지 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the item amount which exceeds makes it impossible to trade.
+*/
+ MSG_PURCHASE_FAIL_EACHITEM_COUNT = 0x794,
+/*20110706 to 20110706
+잠시후에 다시 시도해주세요.
+20110713 to latest
+광고 등록 대기중입니다.
+Advertising is pending registration.
+20130807 to 20130814
+해당 아이템의 소지 한계량 초과로 구입이 불가능합니다.
+Amounts are exceeded the possession of the item is not available for purchase.
+*/
+ MSG_PARTY_FAILED_TIMEOUT = 0x795,
+/*20110706 to latest
+아래의 파일과 텍스트내용을 함께
+라그나로크 공식홈페이지 -> 고객센터 -> 문의하기를
+이용하여 보내주시기 바랍니다.
+With the following files and text content Ragnarok Official Website -> Support -> Contact Us to submit your comments by:
+20130807 to 20130814
+광고 등록 대기중입니다.
+Advertising is pending registration.
+*/
+ MSG_UNEXCEPTION_MSG1ST = 0x796,
+#endif
+#if PACKETVER >= 20110719
+/*20110719 to latest
+빌링시스템에 오류가 발생햇습니다(%d)
+Has caused an error in billing system(%d)
+20130807 to 20130814
+아래의 파일과 텍스트내용을 함께
+라그나로크 공식홈페이지 -> 고객센터 -> 문의하기를
+이용하여 보내주시기 바랍니다.
+With the following files and text content Ragnarok Official Website -> Support -> Contact Us to submit your comments by:
+*/
+ MSG_INGAMBA_BILLING_ZSVR_ERROR = 0x797,
+/*20110719 to latest
+룬 아이템 소유 개수가 초과 되어 구매가 실패 하였습니다.
+Failed purchase of runes, items exceed the maximum number that can be held.
+20130807 to 20130814
+빌링시스템에 오류가 발생햇습니다(%d)
+Has caused an error in billing system(%d)
+*/
+ MSG_CASH_FAILED_RUNE_OVERCOUNT = 0x798,
+/*20110719 to latest
+개별 아이템 개수가 초과 되어 구매가 실패 하였습니다.
+Exceeded the number of individual items, purchase failed.
+20130807 to 20130814
+룬 아이템 소유 개수가 초과 되어 구매가 실패 하였습니다.
+Failed purchase of runes, items exceed the maximum number that can be held.
+*/
+ MSG_CASH_FAILED_EACHITEM_OVERCOUNT = 0x799,
+/*20110719 to latest
+알 수 없는 오류가 발생하여 구매가 실패 하였습니다.
+Purchase failed due to an unknown error.
+20130807 to 20130814
+개별 아이템 개수가 초과 되어 구매가 실패 하였습니다.
+Exceeded the number of individual items, purchase failed.
+*/
+ MSG_CASH_FAILED_UNKOWN = 0x79a,
+/*20110719 to latest
+잠시 후 다시 시도해 주십시오.
+Please try again later.
+20130807 to 20130814
+알 수 없는 오류가 발생하여 구매가 실패 하였습니다.
+Purchase failed due to an unknown error.
+*/
+ MSG_CASH_FAILED_BUSY = 0x79b,
+/*20110719 to latest
+ 쿠나이 아이템을 장착 한 상태에서만 사용 가능합니다.
+Kunai must be equipped to use this skill.
+20130807 to 20130814
+잠시 후 다시 시도해 주십시오.
+Please try again later.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT_KUNAI = 0x79c,
+#endif
+#if PACKETVER >= 20110726
+/*20110726 to latest
+모집할 최소레벨값을 입력해주세요.
+Please enter the value of the minimum level to be recruited.
+20130807 to 20130814
+ 쿠나이 아이템을 장착 한 상태에서만 사용 가능합니다.
+Kunai must be equipped to use this skill.
+*/
+ MSG_SEEK_PARTY_LEVEL_HELP = 0x79d,
+#endif
+#if PACKETVER >= 20110803
+/*20110803 to latest
+존다기획사NPC 에게 아이템이 수령이 불가능합니다. 소지창의 여유공간을 확보해주세요.
+Jonda agency receipt of the item to the NPC is not possible. Gaining possession of the free space of the window.
+20130807 to 20130814
+모집할 최소레벨값을 입력해주세요.
+Please enter the value of the minimum level to be recruited.
+*/
+ MSG_FAILED_GET_ITEM_FROM_ZONEDA = 0x79e,
+#endif
+#if PACKETVER >= 20110810
+/*20110810 to latest
+이 스킬은 공성전에서만 사용 가능합니다.
+This skill is only available in the siege.
+20130807 to 20130814
+존다기획사NPC 에게 아이템이 수령이 불가능합니다. 소지창의 여유공간을 확보해주세요.
+Jonda agency receipt of the item to the NPC is not possible. Gaining possession of the free space of the window.
+*/
+ MSG_USESKILL_FAIL_SIZE = 0x79f,
+/*20110810 to latest
+이 스킬은 플레이어에게만 사용 가능합니다.
+This skill is available only to the player.
+20130807 to 20130814
+이 스킬은 공성전에서만 사용 가능합니다.
+This skill is only available in the siege.
+*/
+ MSG_USESKILL_FAIL_TOTARGET_PLAYER = 0x7a0,
+/*20110810 to latest
+착용이 금지 된 상태로 착용 할 수 없습니다.
+Forbidden to wear the state can not be worn.
+20130807 to 20130814
+이 스킬은 플레이어에게만 사용 가능합니다.
+This skill is available only to the player.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM_FORBID = 0x7a1,
+/*20110810 to latest
+현재 위치에서는 상점 및 채팅방의 생성이 불가능합니다.
+Current location of the shop and chat room creation is disabled.
+20130807 to 20130814
+착용이 금지 된 상태로 착용 할 수 없습니다.
+Forbidden to wear the state can not be worn.
+*/
+ MSG_USESKILL_FAIL_THERE_ARE_NPC_AROUND = 0x7a2,
+#endif
+#if PACKETVER >= 20110816
+/*20110816 to latest
+Elapsed time: %d:%d:%d / %d:%d:%d
+20130807 to 20130814
+현재 위치에서는 상점 및 채팅방의 생성이 불가능합니다.
+Current location of the shop and chat room creation is disabled.
+*/
+ MSG_REPLAY_ELAPSEDTIME = 0x7a3,
+/*20110816 to latest
+Speed : X 1/4
+20130807 to 20130814
+Elapsed time: %d:%d:%d / %d:%d:%d
+*/
+ MSG_REPLAY_SPEED1_4 = 0x7a4,
+/*20110816 to latest
+Speed : X 1/2
+20130807 to 20130814
+Speed : X 1/4
+*/
+ MSG_REPLAY_SPEED1_2 = 0x7a5,
+/*20110816 to latest
+Speed : X 1
+20130807 to 20130814
+Speed : X 1/2
+*/
+ MSG_REPLAY_SPEED1 = 0x7a6,
+/*20110816 to latest
+Speed : X 2
+20130807 to 20130814
+Speed : X 1
+*/
+ MSG_REPLAY_SPEED2 = 0x7a7,
+/*20110816 to latest
+Speed : X 4
+20130807 to 20130814
+Speed : X 2
+*/
+ MSG_REPLAY_SPEED4 = 0x7a8,
+/*20110816 to latest
+Speed : X 8
+20130807 to 20130814
+Speed : X 4
+*/
+ MSG_REPLAY_SPEED8 = 0x7a9,
+/*20110816 to latest
+Speed : X 16
+20130807 to 20130814
+Speed : X 8
+*/
+ MSG_REPLAY_SPEED16 = 0x7aa,
+/*20110816 to latest
+Speed : 알수없음
+Speed: Unknown
+20130807 to 20130814
+Speed : X 16
+*/
+ MSG_REPLAY_SPEEDUNKNOWN = 0x7ab,
+/*20110816 to latest
+Service Info : %s
+20130807 to 20130814
+Speed : 알수없음
+Speed: Unknown
+*/
+ MSG_REPLAY_CHRVICEINFO = 0x7ac,
+/*20110816 to latest
+Character Name : %s
+20130807 to 20130814
+Service Info : %s
+*/
+ MSG_REPLAY_CHARACTERNAME = 0x7ad,
+/*20110816 to latest
+Map Name : %s
+20130807 to 20130814
+Character Name : %s
+*/
+ MSG_REPLAY_MAPNAME = 0x7ae,
+/*20110816 to latest
+Record Time: %d-%01d-%01d %d: %02d: %02d
+20130807 to 20130814
+Map Name : %s
+*/
+ MSG_REPLAY_RECORDTIME = 0x7af,
+/*20110816 to latest
+Play Time: %02d: %02d: %02d
+20130807 to 20130814
+Record Time: %d-%01d-%01d %d: %02d: %02d
+*/
+ MSG_REPLAY_PLAYTIME = 0x7b0,
+/*20110816 to latest
+No Replay File.
+20130807 to 20130814
+Play Time: %02d: %02d: %02d
+*/
+ MSG_REPLAY_NOREPLAYFILE = 0x7b1,
+/*20110816 to latest
+Server No Matching
+20130807 to 20130814
+No Replay File.
+*/
+ MSG_REPLAY_SERVERNOMATCH = 0x7b2,
+/*20110816 to latest
+Replay Option Setting
+20130807 to 20130814
+Server No Matching
+*/
+ MSG_REPLAY_REPLAYOPTIONSETTING = 0x7b3,
+/*20110816 to latest
+파일 이름을 입력하세요.
+Enter File Name
+20130807 to 20130814
+Replay Option Setting
+*/
+ MSG_REPLAY_ENTERTHEFILENAME = 0x7b4,
+/*20110816 to latest
+Set Replay Save Data
+20130807 to 20130814
+파일 이름을 입력하세요.
+Enter File Name
+*/
+ MSG_REPLAY_SETREPLAYSAVEDATA = 0x7b5,
+/*20110816 to latest
+Set Rec Option
+20130807 to 20130814
+Set Replay Save Data
+*/
+ MSG_REPLAY_SETRECOPTION = 0x7b6,
+/*20110816 to latest
+%.1f %% Pos☞:%d:%d:%d
+%.1f % Pos->:%d:%d:%d
+20130807 to 20130814
+Set Rec Option
+*/
+ MSG_REPLAY_GAGEPOS1 = 0x7b7,
+/*20110816 to latest
+%.1f %% Pos☞:이동불가
+%.1f % Pos->:cannot move
+20130807 to 20130814
+%.1f %% Pos☞:%d:%d:%d
+%.1f % Pos->:%d:%d:%d
+*/
+ MSG_REPLAY_GAGEPOS2 = 0x7b8,
+/*20110816 to latest
+Start
+20130807 to 20130814
+%.1f %% Pos☞:이동불가
+%.1f % Pos->:cannot move
+*/
+ MSG_REPLAY_START = 0x7b9,
+/*20110816 to latest
+Stop
+20130807 to 20130814
+Start
+*/
+ MSG_REPLAY_STOP = 0x7ba,
+/*20110816 to latest
+Input FileName -> Start
+20130807 to 20130814
+Stop
+*/
+ MSG_REPLAY_START2 = 0x7bb,
+/*20110816 to latest
+Open Option
+Open Options
+20130807 to 20130814
+Input FileName -> Start
+*/
+ MSG_REPLAY_OPENOPTION = 0x7bc,
+/*20110816 to latest
+Close Option
+Close Options
+20130807 to 20130814
+Open Option
+Open Options
+*/
+ MSG_REPLAY_CLOSEOPION = 0x7bd,
+/*20110816 to latest
+End
+20130807 to 20130814
+Close Option
+Close Options
+*/
+ MSG_REPLAY_END = 0x7be,
+/*20110816 to latest
+Time
+20130807 to 20130814
+End
+*/
+ MSG_REPLAY_TIME = 0x7bf,
+/*20110816 to latest
+파티&친구
+Party & Friends
+20130807 to 20130814
+Time
+*/
+ MSG_REPLAY_PARTYFRIEND = 0x7c0,
+/*20110816 to latest
+채팅
+Chat
+20130807 to 20130814
+파티&친구
+Party & Friends
+*/
+ MSG_REPLAY_CHAT = 0x7c1,
+/*20110816 to latest
+단축키
+Shortcuts
+20130807 to 20130814
+채팅
+Chat
+*/
+ MSG_REPLAY_SHORTCUTS = 0x7c2,
+/*20110816 to latest
+자동 파일명 생성
+Automatic filename generation
+20130807 to 20130814
+단축키
+Shortcuts
+*/
+ MSG_REPLAY_AUTOMATICFILENAME = 0x7c3,
+/*20110816 to latest
+파일 중복 채크
+Checking for duplicate files
+20130807 to 20130814
+자동 파일명 생성
+Automatic filename generation
+*/
+ MSG_REPLAY_CHECKINGFILE = 0x7c4,
+/*20110816 to latest
+동일한 파일이 존재 합니다.
+The same file exists already.
+20130807 to 20130814
+파일 중복 채크
+Checking for duplicate files
+*/
+ MSG_REPLAY_THESAMEFILEEXISTS = 0x7c5,
+/*20110816 to latest
+Record Start
+20130807 to 20130814
+동일한 파일이 존재 합니다.
+The same file exists already.
+*/
+ MSG_REPLAY_RECORDSTART = 0x7c6,
+/*20110816 to latest
+ is Saved.
+Recording saved
+20130807 to 20130814
+Record Start
+*/
+ MSG_REPLAY_RECORDEND = 0x7c7,
+#endif
+#if PACKETVER >= 20110823
+/*20110823 to latest
+Weight : %3d / %3d
+20130807 to 20130814
+ is Saved.
+Recording saved
+*/
+ MSG_WEIGHT = 0x7c8,
+/*20110823 to latest
+Total : %s C
+Total: %s EUR
+20130807 to 20130814
+Weight : %3d / %3d
+*/
+ MSG_TOTAL = 0x7c9,
+/*20110823 to latest
+[수리검]을 장착한 상태여야 합니다.
+[Shuriken] must be equipped.
+20130807 to 20130814
+Total : %s C
+Total: %s EUR
+*/
+ MSG_FAIL_NEED_EQUIPPED_SYURIKEN = 0x7ca,
+#endif
+#if PACKETVER >= 20110831
+/*20110831 to latest
+Base Lv. %d
+20130807 to 20130814
+[수리검]을 장착한 상태여야 합니다.
+[Shuriken] must be equipped.
+*/
+ MSG__BASIC_MSG_BASE = 0x7cb,
+/*20110831 to latest
+Job Lv. %d
+20130807 to 20130814
+Base Lv. %d
+*/
+ MSG__BASIC_MSG_JOB = 0x7cc,
+/*20110831 to latest
+Zeny : %s
+20130807 to 20130814
+Job Lv. %d
+*/
+ MSG_BASIC_MSG_ZENY = 0x7cd,
+/*20110831 to latest
+Trilinear
+20130807 to 20130814
+Zeny : %s
+*/
+ MSG_GRAPHIC_MSG_TRILINEAR = 0x7ce,
+/*20110831 to latest
+attack
+20130807 to 20130814
+Trilinear
+*/
+ MSG_GRAPHIC_MSG_ATTACK = 0x7cf,
+/*20110831 to latest
+skill
+20130807 to 20130814
+attack
+*/
+ MSG_GRAPHIC_MSG_SKILL = 0x7d0,
+/*20110831 to latest
+item
+20130807 to 20130814
+skill
+*/
+ MSG_GRAPHIC_MSG_ITEM = 0x7d1,
+/*20110831 to latest
+NoCtrl
+Ctrl
+20130807 to 20130814
+item
+*/
+ MSG_GRAPHIC_MSG_NOCTRL = 0x7d2,
+/*20110831 to latest
+전장
+More
+20130807 to 20130814
+NoCtrl
+Ctrl
+*/
+ MSG_GRAPHIC_MSG_BATTLE = 0x7d3,
+/*20110831 to latest
+(Character/Total Slot)
+(Characters/Total slots)
+20130807 to 20130814
+전장
+More
+*/
+ MSG_CHARACTER_MSG_CHARACTERTOTALSLOT = 0x7d4,
+/*20110831 to latest
+Premium Service
+VIP Service
+20130807 to 20130814
+(Character/Total Slot)
+(Characters/Total slots)
+*/
+ MSG_CHARACTER_MSG_PREMIUMSERVICE = 0x7d5,
+/*20110831 to latest
+Premium
+VIP
+20130807 to 20130814
+Premium Service
+VIP Service
+*/
+ MSG_CHARACTER_MSG_PREMIUM = 0x7d6,
+/*20110831 to latest
+Service
+20130807 to 20130814
+Premium
+VIP
+*/
+ MSG_CHARACTER_MSG_SERVICE = 0x7d7,
+/*20110831 to latest
+Billing Service
+VIP
+20130807 to 20130814
+Service
+*/
+ MSG_CHARACTER_MSG_BILLINGSERVICE = 0x7d8,
+/*20110831 to latest
+Billing
+VIP
+20130807 to 20130814
+Billing Service
+VIP
+*/
+ MSG_CHARACTER_MSG_BILLING = 0x7d9,
+/*20110831 to latest
+Command List
+20130807 to 20130814
+Billing
+VIP
+*/
+ MSG_MSG_COMMANDLIST = 0x7da,
+/*20110831 to latest
+LEVEL
+20130807 to 20130814
+Command List
+*/
+ MSG_SEEK_PARTY_LEVEL = 0x7db,
+/*20110831 to latest
+MAP
+20130807 to 20130814
+LEVEL
+*/
+ MSG_SEEK_PARTY_MAP = 0x7dc,
+/*20110831 to latest
+JOB
+20130807 to 20130814
+MAP
+*/
+ MSG_SEEK_PARTY_JOB = 0x7dd,
+#endif
+#if PACKETVER >= 20110906
+/*20110906 to latest
+Not Available
+20130807 to 20130814
+JOB
+*/
+ MSG_MSG_NOTAVAILABLE = 0x7de,
+#endif
+#if PACKETVER >= 20110920
+/*20110920 to 20110929
+[수호 천사의 보호] 스킬은 만렙일 경우, 경험치 100% 이상일 때는 사용할 수 없습니다.
+20111004 to latest
+[수호 천사의 보호] 만렙일 경우 사용할 수 없습니다.
+[Protection of Guardian Angel] You can't use it when you reach the highest level.
+20130807 to 20130814
+Not Available
+*/
+ MSG_MSG_SUPERNOVICE_CHOPOKGI_CAPPEDLEVEL = 0x7df,
+#endif
+#if PACKETVER >= 20110928
+/*20110928 to latest
+정말 이동하시겠습니까?
+Do you really want to move?
+20130807 to 20130814
+[수호 천사의 보호] 만렙일 경우 사용할 수 없습니다.
+[Protection of Guardian Angel] You can't use it when you reach the highest level.
+*/
+ MSG_CHANGE_CHARACTER_SLOT = 0x7e0,
+/*20110928 to latest
+캐릭터 슬롯 이동에 실패했습니다.
+Failed to move Char slot.
+20130807 to 20130814
+정말 이동하시겠습니까?
+Do you really want to move?
+*/
+ MSG_CHANGE_CHARACTER_SLOT_FAILED = 0x7e1,
+#endif
+#if PACKETVER >= 20111004
+/*20111004 to latest
+캐릭터 이름이 잘못 되었습니다.
+Character name is invalid.
+20130807 to 20130814
+캐릭터 슬롯 이동에 실패했습니다.
+Failed to move Char slot.
+*/
+ MSG_CHARACTERNAME_ERROR = 0x7e2,
+/*20111004 to latest
+퀘스트보기창
+Show Quest
+20130807 to 20130814
+캐릭터 이름이 잘못 되었습니다.
+Character name is invalid.
+*/
+ MSG_QUEST_DISPLAY_ONOFF = 0x7e3,
+#endif
+#if PACKETVER >= 20111017
+/*20111017 to 20111021
+정말 탭을 제거하시겠습니까?
+20111025 to 20111116
+청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000됩니다.
+20111122 to latest
+ 청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 만 16세 미만 고객님들의 게임 이용이 제한됩니다.
+Depending on the protection of youth, and 0:00 to 6:00 while under the age of 16 of your game use is limited.
+20130807 to 20130814
+퀘스트보기창
+Show Quest
+*/
+ MSG_SHUTDOWN_ALERT_MSG = 0x7e4,
+/*20111017 to 20111021
+더이상 탭을 제거할 수 없습니다.
+20111025 to latest
+청소년 보호법에 따라, 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000되며, 게임을 종료합니다.
+Depending on the protection of youth, 0:00 to 6:00 ^ff0000 under the age of 16 ^000000 limit your use of the game and the game ends.
+20130807 to 20130814
+ 청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 만 16세 미만 고객님들의 게임 이용이 제한됩니다.
+Depending on the protection of youth, and 0:00 to 6:00 while under the age of 16 of your game use is limited.
+*/
+ MSG_BAN_SHUTDOWN_TEENAGER = 0x7e5,
+/*20111017 to 20111021
+더이상 탭을 추가할 수 없습니다.
+20111025 to latest
+캐릭터 이름을 변경하기 위해서는 길드에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the guild.
+20130807 to 20130814
+청소년 보호법에 따라, 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000되며, 게임을 종료합니다.
+Depending on the protection of youth, 0:00 to 6:00 ^ff0000 under the age of 16 ^000000 limit your use of the game and the game ends.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_GUILD = 0x7e6,
+#endif
+#if PACKETVER >= 20111025
+/*20111025 to latest
+캐릭터 이름을 변경하기 위해서는 파티에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the party.
+20130807 to 20130814
+캐릭터 이름을 변경하기 위해서는 길드에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the guild.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_PARTY = 0x7e7,
+/*20111025 to latest
+알 수 없는 오류로 캐릭터 이름 변경이 실패 하였습니다.
+Character name change failed, due an unknown error.
+20130807 to 20130814
+캐릭터 이름을 변경하기 위해서는 파티에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the party.
+*/
+ MSG_FAILED_RENAME_UNKOWN = 0x7e8,
+#endif
+#if PACKETVER >= 20111101
+/*20111101 to latest
+이미 캐릭터 슬롯변경이 가능한 상태입니다.(%d)
+Ready to change character slot in.(%d)
+20130807 to 20130814
+알 수 없는 오류로 캐릭터 이름 변경이 실패 하였습니다.
+Character name change failed, due an unknown error.
+*/
+ MSG_CHARSLOT_CHANGE_DUPLICATE = 0x7e9,
+/*20111101 to latest
+이미 캐릭터 이름변경이 가능한 상태입니다.(%d)
+Ready to change character name in.(%d)
+20130807 to 20130814
+이미 캐릭터 슬롯변경이 가능한 상태입니다.(%d)
+Ready to change character slot in.(%d)
+*/
+ MSG_CHARNAME_CHANGE_DUPLICATE = 0x7ea,
+/*20111101 to latest
+변경하려는 이름의 길이가 최대크기를 초과하여 캐릭터 이름 변경이 실패 하였습니다.
+Length exceeds the maximum size of the character name you want to change.
+20130807 to 20130814
+이미 캐릭터 이름변경이 가능한 상태입니다.(%d)
+Ready to change character name in.(%d)
+*/
+ MSG_FAILED_RENAME_OVER_LENGTH = 0x7eb,
+/*20111101 to latest
+사용할 수 없는 단어가 포함되어 캐릭터 이름 변경이 실패 하였습니다.
+Name contains invalid characters. Character name change failed.
+20130807 to 20130814
+변경하려는 이름의 길이가 최대크기를 초과하여 캐릭터 이름 변경이 실패 하였습니다.
+Length exceeds the maximum size of the character name you want to change.
+*/
+ MSG_FAILED_RENAME_PREVENTNAM = 0x7ec,
+/*20111101 to latest
+이름 변경이 금지된 상태이므로 캐릭터 이름 변경이 실패 하였습니다.
+The name change is prohibited. Character name change failed.
+20130807 to 20130814
+사용할 수 없는 단어가 포함되어 캐릭터 이름 변경이 실패 하였습니다.
+Name contains invalid characters. Character name change failed.
+*/
+ MSG_FAILED_RENAME_FORBIDDEN = 0x7ed,
+#endif
+#if PACKETVER >= 20111108
+/*20111108 to latest
+완료
+Complete
+20130807 to 20130814
+이름 변경이 금지된 상태이므로 캐릭터 이름 변경이 실패 하였습니다.
+The name change is prohibited. Character name change failed.
+*/
+ MSG_COMPLETE_HUNTING_QUEST = 0x7ee,
+#endif
+#if PACKETVER >= 20111114
+/*20111114 to 20111116
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 %d분간 %d%% 증가합니다.
+20111122 to latest
+ %d분간 얻을 수 있는 경험치가 %d%% 증가합니다.
+During %d minutes your Exp will increase by %d%%.
+20130807 to 20130814
+완료
+Complete
+*/
+ MSG_PLUSEXP_VALUE = 0x7ef,
+/*20111114 to latest
+소환까지 %02d초남았습니다.
+%02d seconds left until summon.
+20130807 to 20130814
+ %d분간 얻을 수 있는 경험치가 %d%% 증가합니다.
+During %d minutes your Exp will increase by %d%%.
+*/
+ MSG_PARTY_RECALL_TIME = 0x7f0,
+/*20111114 to latest
+파티장이 당신을 %s (%s) 로 소환합니다.소환시 %d zeny가 소모됩니다.
+Your party leader summons you to %s (%s). Warp costs %d Zeny.
+20130807 to 20130814
+소환까지 %02d초남았습니다.
+%02d seconds left until summon.
+*/
+ MSG_PARTY_RECALL_INFO = 0x7f1,
+/*20111114 to latest
+소환대상
+Summon target
+20130807 to 20130814
+파티장이 당신을 %s (%s) 로 소환합니다.소환시 %d zeny가 소모됩니다.
+Your party leader summons you to %s (%s). Warp costs %d Zeny.
+*/
+ MSG_RECALL_TARGET = 0x7f2,
+/*20111114 to latest
+차단목록
+Block List
+20130807 to 20130814
+소환대상
+Summon target
+*/
+ MSG_PARTY_BLACKLIST = 0x7f3,
+/*20111114 to 20120207
+파티 광고를 등록하기 위해 1000제니가 소모됩니다.
+20120214 to latest
+파티 광고를 등록하기 위해 %d제니가 소모됩니다.
+%d Zeny will be spent for making party ad.
+20130807 to 20130814
+차단목록
+Block List
+*/
+ MSG_PARTY_CF_PAY = 0x7f4,
+/*20111114 to latest
+파티 광고를 하기 위한 제니가 부족합니다.
+Insufficient Zeny for making party ad.
+20130807 to 20130814
+파티 광고를 등록하기 위해 %d제니가 소모됩니다.
+%d Zeny will be spent for making party ad.
+*/
+ MSG_PARTY_CF_PAY_SHORTAGE_COST = 0x7f5,
+/*20111114 to latest
+)님 파티 가입승인
+) party: accept invitation
+20130807 to 20130814
+파티 광고를 하기 위한 제니가 부족합니다.
+Insufficient Zeny for making party ad.
+*/
+ MSG_PARTY_ADD_OK = 0x7f6,
+/*20111114 to latest
+)님 파티 가입거부
+) party: decline invitation
+20130807 to 20130814
+)님 파티 가입승인
+) party: accept invitation
+*/
+ MSG_PARTY_ADD_REFUSES = 0x7f7,
+/*20111114 to latest
+)님 장비창보기
+) party: show equipment window
+20130807 to 20130814
+)님 파티 가입거부
+) party: decline invitation
+*/
+ MSG_PARTY_ITEM_VIEW = 0x7f8,
+/*20111114 to latest
+한글18글자,영문36글자 입력가능
+Up to 36 english letters can be entered
+20130807 to 20130814
+)님 장비창보기
+) party: show equipment window
+*/
+ MSG_SEEK_PARTY_MEMO_HELP = 0x7f9,
+/*20111114 to latest
+지원하기
+Enter
+20130807 to 20130814
+한글18글자,영문36글자 입력가능
+Up to 36 english letters can be entered
+*/
+ MSG_PARTY_REQUEST = 0x7fa,
+/*20111114 to latest
+1:1대화하기
+1:1 Chat
+20130807 to 20130814
+지원하기
+Enter
+*/
+ MSG_DIRECT_CHAT = 0x7fb,
+/*20111114 to latest
+차단하기
+Block
+20130807 to 20130814
+1:1대화하기
+1:1 Chat
+*/
+ MSG_ADD_BLACKLIST = 0x7fc,
+#endif
+#if PACKETVER >= 20111122
+/*20111122 to latest
+파티장에게 소환되기 위한 제니가 부족합니다.
+Insufficient Zeny for recall.
+20130807 to 20130814
+차단하기
+Block
+*/
+ MSG_PARTY_RECRUIT_NOT_RECALL_PAY = 0x7fd,
+/*20111122 to latest
+메모란에 파티광고를 써주세요.
+Input your party ad.
+20130807 to 20130814
+파티장에게 소환되기 위한 제니가 부족합니다.
+Insufficient Zeny for recall.
+*/
+ MSG_PARTY_RECRUIT_MEMO_ERROR = 0x7fe,
+/*20111122 to latest
+파티장만이 파티광고를 등록할수있습니다.
+Only party leader can register party ad.
+20130807 to 20130814
+메모란에 파티광고를 써주세요.
+Input your party ad.
+*/
+ MSG_PARTY_RECRUIT_ERROR = 0x7ff,
+/*20111122 to latest
+이미 지원한 파티광고입니다.
+You have already accepted this ad.
+20130807 to 20130814
+파티장만이 파티광고를 등록할수있습니다.
+Only party leader can register party ad.
+*/
+ MSG_PARTY_REFUSE_ERROR = 0x800,
+/*20111122 to latest
+내용
+For
+20130807 to 20130814
+이미 지원한 파티광고입니다.
+You have already accepted this ad.
+*/
+ MSG_PARTY_RECRUIT_INFO = 0x801,
+/*20111122 to latest
+장비
+E
+20130807 to 20130814
+내용
+For
+*/
+ MSG_INVENTORY_TABNAME_1 = 0x802,
+/*20111122 to latest
+개인
+F
+20130807 to 20130814
+장비
+E
+*/
+ MSG_INVENTORY_TABNAME_3 = 0x803,
+/*20111122 to latest
+ 아이템 버리기 잠금
+ Drop Lock: On/Off
+20130807 to 20130814
+개인
+F
+*/
+ MSG_ITEM_DROP_LOCK = 0x804,
+/*20111122 to latest
+파티원 찾기 알람
+Party Alarm
+20130807 to 20130814
+ 아이템 버리기 잠금
+ Drop Lock: On/Off
+*/
+ MSG_PARTY_RECRUIT_ALRAM = 0x805,
+#endif
+#if PACKETVER >= 20111207
+/*20111207 to latest
+파티결성
+Create Party
+20130807 to 20130814
+파티원 찾기 알람
+Party Alarm
+*/
+ MSG_CREATE_PARTY = 0x806,
+/*20111207 to latest
+파티탈퇴
+Leave Party
+20130807 to 20130814
+파티결성
+Create Party
+*/
+ MSG_WITHDRAW_PARTY = 0x807,
+/*20111207 to latest
+파티초대
+Party Invitation
+20130807 to 20130814
+파티탈퇴
+Leave Party
+*/
+ MSG_INVITE_PARTY = 0x808,
+/*20111207 to latest
+파티 이름 등록
+Party Name:
+20130807 to 20130814
+파티초대
+Party Invitation
+*/
+ MSG_PUT_PARTY_NAME_IN = 0x809,
+/*20111207 to latest
+초대할 캐릭터 이름
+Player Name:
+20130807 to 20130814
+파티 이름 등록
+Party Name:
+*/
+ MSG_PUT_PLAYER_NAME_IN = 0x80a,
+/*20111207 to latest
+님께 파티가입 요청을 보냈습니다.
+ has recieved an invitation to join your party.
+20130807 to 20130814
+초대할 캐릭터 이름
+Player Name:
+*/
+ MSG_CHARACTER_PARTY_INVITATION_TO_JOIN = 0x80b,
+/*20111207 to latest
+님께서 파티가입을 거절했습니다.
+ rejected your party invitation.
+20130807 to 20130814
+님께 파티가입 요청을 보냈습니다.
+ has recieved an invitation to join your party.
+*/
+ MSG_CHARACTER_REJECT_PARTY_INVITATION = 0x80c,
+/*20111207 to latest
+님께서 파티가입을 수락했습니다.
+ accepted your party invitation.
+20130807 to 20130814
+님께서 파티가입을 거절했습니다.
+ rejected your party invitation.
+*/
+ MSG_CHARACTER_ACCEPT_PARTY_INVITATION = 0x80d,
+/*20111207 to latest
+이미 파티모집중입니다.
+Recruitment is already a party.
+20130807 to 20130814
+님께서 파티가입을 수락했습니다.
+ accepted your party invitation.
+*/
+ MSG_PARTY_RECRUIT_ERROR1 = 0x80e,
+/*20111207 to latest
+이전 검색과 같은 조건입니다.
+Same conditions such as the previous search.
+20130807 to 20130814
+이미 파티모집중입니다.
+Recruitment is already a party.
+*/
+ MSG_PARTY_RECRUIT_ERROR2 = 0x80f,
+/*20111207 to latest
+길드 탈퇴 후 사용 가능합니다.
+Guild after withdrwal.
+20130807 to 20130814
+이전 검색과 같은 조건입니다.
+Same conditions such as the previous search.
+*/
+ MSG_CHARNAME_CHANGE_FILED_GUILDMEMBER = 0x810,
+/*20111207 to latest
+파티 탈퇴 후 사용 가능합니다.
+Party after secession.
+20130807 to 20130814
+길드 탈퇴 후 사용 가능합니다.
+Guild after withdrwal.
+*/
+ MSG_CHARNAME_CHANGE_FILED_PARTYMEMBER = 0x811,
+/*20111207 to latest
+소환 유저가 소환이 안되는 맵에 있습니다.
+The player can not be summoned to this map.
+20130807 to 20130814
+파티 탈퇴 후 사용 가능합니다.
+Party after secession.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR1 = 0x812,
+/*20111207 to 20120229
+파티장이 있는 맵에서는 소환이 안됩니다.
+20120307 to latest
+현재 파티장이 있는 맵에서는 소환이 안됩니다.
+Party Leader is on a map that is restricted to summon players.
+20130807 to 20130814
+소환 유저가 소환이 안되는 맵에 있습니다.
+The player can not be summoned to this map.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR2 = 0x813,
+/*20111207 to latest
+소환거부되었습니다.
+Summon has been denied.
+20130807 to 20130814
+현재 파티장이 있는 맵에서는 소환이 안됩니다.
+Party Leader is on a map that is restricted to summon players.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR3 = 0x814,
+/*20111207 to latest
+소환을 할 수 없습니다.
+Can not be summoned.
+20130807 to 20130814
+소환거부되었습니다.
+Summon has been denied.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR4 = 0x815,
+/*20111207 to latest
+파티초대는 파티장만 가능합니다.
+Only the leader can invite.
+20130807 to 20130814
+소환을 할 수 없습니다.
+Can not be summoned.
+*/
+ MSG_YOU_ARE_NOT_PARTYMASTER = 0x816,
+#endif
+#if PACKETVER >= 20111213
+/*20111213 to latest
+검색할 아이템명 입력 :
+Search item:
+20130807 to 20130814
+파티초대는 파티장만 가능합니다.
+Only the leader can invite.
+*/
+ MSG_NC_ITEM_SEARCH = 0x817,
+/*20111213 to latest
+캐릭터명을 입력하셔야 합니다.
+You must enter a character name.
+20130807 to 20130814
+검색할 아이템명 입력 :
+Search item:
+*/
+ MSG_PLEASE_PUT_CHARACTER_NAME_IN = 0x818,
+/*20111213 to latest
+파티이름을 입력하셔야 합니다.
+You must enter the name of the party.
+20130807 to 20130814
+캐릭터명을 입력하셔야 합니다.
+You must enter a character name.
+*/
+ MSG_PLEASE_PUT_PARTY_NAME_IN = 0x819,
+#endif
+#if PACKETVER >= 20111220
+/*20111220 to latest
+길드 도우미
+Guild Creation Window
+20130807 to 20130814
+파티이름을 입력하셔야 합니다.
+You must enter the name of the party.
+*/
+ MSG_GUILD_HELPER = 0x81a,
+/*20111220 to latest
+가입되어 있는 길드가 없습니다.
+Join a guild or start your own!
+20130807 to 20130814
+길드 도우미
+Guild Creation Window
+*/
+ MSG_NO_GUILD_CURRENTLY_PARTICIPATED_IN = 0x81b,
+/*20111220 to latest
+길드 결성
+Create Guild
+20130807 to 20130814
+가입되어 있는 길드가 없습니다.
+Join a guild or start your own!
+*/
+ MSG_CREATE_GUILD = 0x81c,
+/*20111220 to latest
+생성할 길드 이름
+Guild Name
+20130807 to 20130814
+길드 결성
+Create Guild
+*/
+ MIS_PUT_GUILD_NAME_IN = 0x81d,
+/*20111220 to latest
+길드 결성 도움말
+Guild System
+20130807 to 20130814
+생성할 길드 이름
+Guild Name
+*/
+ MIS_GUILD_TIP = 0x81e,
+/*20111220 to latest
+길드 시스템이란
+What is the guild system
+20130807 to 20130814
+길드 결성 도움말
+Guild System
+*/
+ MIS_GUILD_SYSTEM = 0x81f,
+/*20111220 to latest
+길드이름을 입력하셔야 합니다.
+You must enter the name of your guild.
+20130807 to 20130814
+길드 시스템이란
+What is the guild system
+*/
+ MSG_PLEASE_PUT_GUILD_NAME_IN = 0x820,
+#endif
+#if PACKETVER >= 20111227
+/*20111227 to latest
+지원한 파티에서 거부당했습니다.
+Supported at the party was rejected.
+20130807 to 20130814
+길드이름을 입력하셔야 합니다.
+You must enter the name of your guild.
+*/
+ MSG_PARTY_RECRUIT_REFUSE_VOLUNTEER = 0x821,
+#endif
+#if PACKETVER >= 20120103
+/*20120103 to latest
+서비스 선택.
+Select Service:
+20130807 to 20130814
+지원한 파티에서 거부당했습니다.
+Supported at the party was rejected.
+*/
+ MSG_SERVICESELECT = 0x822,
+/*20120103 to latest
+탈출 가능한 지역.
+Possible escape area.
+20130807 to 20130814
+서비스 선택.
+Select Service:
+*/
+ MSG_SHOW_MAPNAMETITLE = 0x823,
+/*20120103 to latest
+Replay File List
+20130807 to 20130814
+탈출 가능한 지역.
+Possible escape area.
+*/
+ MSG_REPLAY_STR_REPLAYFILELIST = 0x824,
+/*20120103 to latest
+File info
+20130807 to 20130814
+Replay File List
+*/
+ MSG_REPLAY_STR_FILEINFO = 0x825,
+/*20120103 to latest
+File List
+20130807 to 20130814
+File info
+*/
+ MSG_REPLAY_STR_FILELIST = 0x826,
+#endif
+#if PACKETVER >= 20120117
+/*20120117 to latest
+%s 아이템은 거래가 불가능 합니다.
+%s Item deal not possible.
+20130807 to 20130814
+File List
+*/
+ MSG_NOT_MOVEABLE_TRADE = 0x827,
+#endif
+#if PACKETVER >= 20120207
+/*20120207 to latest
+길드해체
+Disband the Guild
+20130807 to 20130814
+%s 아이템은 거래가 불가능 합니다.
+%s Item deal not possible.
+*/
+ MSG_GUILD_DISBAND = 0x828,
+/*20120207 to latest
+해체할 길드 이름
+Enter Guild Name
+20130807 to 20130814
+길드해체
+Disband the Guild
+*/
+ MSG_PUT_DISBAND_GUILDNAME = 0x829,
+#endif
+#if PACKETVER >= 20120214
+/*20120214 to latest
+접속하지 않았거나 존재하지 않는 캐릭터입니다.
+The character is not online or does not exist.
+20130807 to 20130814
+해체할 길드 이름
+Enter Guild Name
+*/
+ MSG_JOINGUILD_NOTEXIST_USER = 0x82a,
+#endif
+#if PACKETVER >= 20120228
+/*20120228 to latest
+팔콘 호출에 실패하였습니다.
+Failed to call Falcon.
+20130807 to 20130814
+접속하지 않았거나 존재하지 않는 캐릭터입니다.
+The character is not online or does not exist.
+*/
+ MSG_FAILED_SET_EFFECT_BIRD = 0x82b,
+#endif
+#if PACKETVER >= 20120307
+/*20120307 to 20120321
+%d%% ( 프리미엄 %d%% + %s서버 %d%% )
+20120328 to latest
+%d%% ( 기본 100%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%%(default 100%%+ Premium%d%%+%s Server%d%%)
+20130807 to 20130814
+팔콘 호출에 실패하였습니다.
+Failed to call Falcon.
+*/
+ MSG_BASIC_EXP_MSG_BRZ = 0x82c,
+/*20120307 to latest
+해당 유저는 현재 공성전에 참가하고 있습니다.
+This user is currently participating in the siege.
+20130807 to 20130814
+%d%% ( 기본 100%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%%(default 100%%+ Premium%d%%+%s Server%d%%)
+*/
+ MSG_JOINGUILD_TARGET_USER_IN_SIEGEMAP = 0x82d,
+/*20120307 to latest
+동일한 맵에서만 파티장 변경이 가능합니다.
+It is only possible to change the party leader while on the same map.
+20130807 to 20130814
+해당 유저는 현재 공성전에 참가하고 있습니다.
+This user is currently participating in the siege.
+*/
+ MSG_PARTY_MASTER_CHANGE_SAME_MAP = 0x82e,
+/*20120307 to latest
+현재 지역에서는 파티장 변경이 불가능합니다.
+In the current region it is not possible to change the party.
+20130807 to 20130814
+동일한 맵에서만 파티장 변경이 가능합니다.
+It is only possible to change the party leader while on the same map.
+*/
+ MSG_CANNOT_PARTY_MASTER_CHANGE_IN_MAP = 0x82f,
+/*20120307 to latest
+그리폰 내리기
+Gryphon making
+20130807 to 20130814
+현재 지역에서는 파티장 변경이 불가능합니다.
+In the current region it is not possible to change the party.
+*/
+ MSG_ROYAL_CHIKENOFF = 0x830,
+/*20120307 to 20120307
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+20120314 to latest
+%d월 %d일 %d시 %d분 %d초
+Delete: %d/%d - %d:%d:%d
+20130807 to 20130814
+그리폰 내리기
+Gryphon making
+*/
+ MSG_TIME_TYPE3 = 0x831,
+#endif
+#if PACKETVER >= 20120314
+/*20120314 to latest
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+20130807 to 20130814
+%d월 %d일 %d시 %d분 %d초
+Delete: %d/%d - %d:%d:%d
+*/
+ MSG_JOINGUILD_REQ_USER_IN_SIEGEMAP = 0x832,
+/*20120314 to latest
+전장에 입장 대기를 신청하셨습니다.
+You are now in the battlefield queue.
+20130807 to 20130814
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+*/
+ MSG_BATTLEFIELD_MSG_REQUEST_JOINWAIT = 0x833,
+/*20120314 to latest
+인원이 가득 찼습니다.
+Queuing has finished.
+20130807 to 20130814
+전장에 입장 대기를 신청하셨습니다.
+You are now in the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_FULL = 0x834,
+/*20120314 to latest
+확인되지 않은 전장명입니다.
+Invalid name of the battlefield.
+20130807 to 20130814
+인원이 가득 찼습니다.
+Queuing has finished.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_NAME = 0x835,
+/*20120314 to latest
+확인되지 않은 신청타입입니다.
+Invalid type of application.
+20130807 to 20130814
+확인되지 않은 전장명입니다.
+Invalid name of the battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_TYPE = 0x836,
+/*20120314 to latest
+최대 인원을 초과하였습니다.
+People count exceeded.
+20130807 to 20130814
+확인되지 않은 신청타입입니다.
+Invalid type of application.
+*/
+ MSG_BATTLEFIELD_MSG_MAXOVER = 0x837,
+/*20120314 to latest
+입장 레벨이 맞지 않습니다.
+Your level doesn't fit this battlefield rules.
+20130807 to 20130814
+최대 인원을 초과하였습니다.
+People count exceeded.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_NOTLEVEL = 0x838,
+/*20120314 to latest
+중복 신청하셨습니다.
+Duplicate application.
+20130807 to 20130814
+입장 레벨이 맞지 않습니다.
+Your level doesn't fit this battlefield rules.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_OVERLAP = 0x839,
+/*20120314 to latest
+재접속후 다시 신청하여 주시기 바랍니다.
+After reconnecting, please re-apply.
+20130807 to 20130814
+중복 신청하셨습니다.
+Duplicate application.
+*/
+ MSG_BATTLEFIELD_MSG_RESTART = 0x83a,
+/*20120314 to latest
+직업이 맞지 않습니다.
+Your class can't participate in this battlefield.
+20130807 to 20130814
+재접속후 다시 신청하여 주시기 바랍니다.
+After reconnecting, please re-apply.
+*/
+ MSG_BATTLEFIELD_MSG_NOTJOB = 0x83b,
+/*20120314 to latest
+파티장이나 길드장만이 신청할 수 있습니다.
+Only party leader / guild master can apply.
+20130807 to 20130814
+직업이 맞지 않습니다.
+Your class can't participate in this battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_ONLYBOSS = 0x83c,
+/*20120314 to latest
+전장을 이용 중인 팀원이 있어 신청이 불가능 합니다.
+You can't apply while your team member is already on a battlefield.
+20130807 to 20130814
+파티장이나 길드장만이 신청할 수 있습니다.
+Only party leader / guild master can apply.
+*/
+ MSG_BATTLEFIELD_MSG_BUSY_PARTYMEMBER = 0x83d,
+/*20120314 to latest
+전장 입장 대기가 취소되었습니다.
+You have left the battlefield queue.
+20130807 to 20130814
+전장을 이용 중인 팀원이 있어 신청이 불가능 합니다.
+You can't apply while your team member is already on a battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOINWAIT = 0x83e,
+/*20120314 to latest
+잘못된 전장명 입니다.
+Wrong battlefield name.
+20130807 to 20130814
+전장 입장 대기가 취소되었습니다.
+You have left the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_WRONG_NAME = 0x83f,
+/*20120314 to latest
+전장 입장 대기 순위에 없습니다.
+You are not in the battlefield queue list
+20130807 to 20130814
+잘못된 전장명 입니다.
+Wrong battlefield name.
+*/
+ MSG_BATTLEFIELD_MSG_NOTRANK = 0x840,
+/*20120314 to latest
+선택하신 전장은 현재 이용하실 수 없으므로 대기가 취소됩니다.
+The selected arena is unavailable; your application has been cancelled
+20130807 to 20130814
+전장 입장 대기 순위에 없습니다.
+You are not in the battlefield queue list
+*/
+ MSG_BATTLEFIELD_MSG_FAIL_CHOICE = 0x841,
+/*20120314 to latest
+전장 입장을 취소하였습니다.
+You have left the queue
+20130807 to 20130814
+선택하신 전장은 현재 이용하실 수 없으므로 대기가 취소됩니다.
+The selected arena is unavailable; your application has been cancelled
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOIN = 0x842,
+/*20120314 to latest
+전장에 입장하시겠습니까?
+Are you sure you want to join a battleground?
+20130807 to 20130814
+전장 입장을 취소하였습니다.
+You have left the queue
+*/
+ MSG_BATTLEFIELD_MSG_DOYOU_JOIN = 0x843,
+/*20120314 to latest
+전장 입장 신청 시스템
+[Battlefield application rules]
+20130807 to 20130814
+전장에 입장하시겠습니까?
+Are you sure you want to join a battleground?
+*/
+ MSG_BATTLEFIELD_HELP1 = 0x844,
+/*20120314 to latest
+입장 신청 및 전장으로의 공간이동 불가 상황
+Application and position into the battlefield cannot be applied under this circumtances
+20130807 to 20130814
+전장 입장 신청 시스템
+[Battlefield application rules]
+*/
+ MSG_BATTLEFIELD_HELP2 = 0x845,
+/*20120314 to latest
+1. 여러 종류의 전장을 동시에 신청할 수 없습니다.
+1. Different types of battle can not be applied simultaneously.
+20130807 to 20130814
+입장 신청 및 전장으로의 공간이동 불가 상황
+Application and position into the battlefield cannot be applied under this circumtances
+*/
+ MSG_BATTLEFIELD_HELP3 = 0x846,
+/*20120314 to latest
+2. 개인 / 파티 / 길드 전장을 동시에 신청할 수 없습니다.
+2. Personal / party / guild battle can not be applied simultaneously.
+20130807 to 20130814
+1. 여러 종류의 전장을 동시에 신청할 수 없습니다.
+1. Different types of battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP4 = 0x847,
+/*20120314 to latest
+3. 파티 전장 신청은 파티장만 신청할 수 있으며,
+3. Parties can only be applied by their party leaders.
+20130807 to 20130814
+2. 개인 / 파티 / 길드 전장을 동시에 신청할 수 없습니다.
+2. Personal / party / guild battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP5 = 0x848,
+/*20120314 to latest
+오프라인중이거나 오프라인 된 파티원은 대기열에서 누락됩니다.
+Offline party members won't proceed to the queue.
+20130807 to 20130814
+3. 파티 전장 신청은 파티장만 신청할 수 있으며,
+3. Parties can only be applied by their party leaders.
+*/
+ MSG_BATTLEFIELD_HELP6 = 0x849,
+/*20120314 to latest
+4. 전장 신청은 전장 맵을 제외한 모든 곳에서 신청 가능하나,
+4. You can add request to enter the arena from any map except for those who don't allow teleport/warp.
+20130807 to 20130814
+오프라인중이거나 오프라인 된 파티원은 대기열에서 누락됩니다.
+Offline party members won't proceed to the queue.
+*/
+ MSG_BATTLEFIELD_HELP7 = 0x84a,
+/*20120314 to latest
+입장한 위치가 마을, 필드, 일반 던전이 아닐 경우 복귀 시 캐릭터 저장 좌표로 이동 됩니다.
+When the battle is finished your character will be returned to the current spot or (if it's not possible) to the save point.
+20130807 to 20130814
+4. 전장 신청은 전장 맵을 제외한 모든 곳에서 신청 가능하나,
+4. You can add request to enter the arena from any map except for those who don't allow teleport/warp.
+*/
+ MSG_BATTLEFIELD_HELP8 = 0x84b,
+/*20120314 to latest
+5. 전장의 보상 및 기타 서비스는 각 마을에 위치한 전장 모병관을 통해 전장 대기실에서 이용해 주십시오.
+5. You can view and choose rewards in the arena waiting room.
+20130807 to 20130814
+입장한 위치가 마을, 필드, 일반 던전이 아닐 경우 복귀 시 캐릭터 저장 좌표로 이동 됩니다.
+When the battle is finished your character will be returned to the current spot or (if it's not possible) to the save point.
+*/
+ MSG_BATTLEFIELD_HELP9 = 0x84c,
+/*20120314 to latest
+전장 입장 신청 도움말
+Request help battle position
+20130807 to 20130814
+5. 전장의 보상 및 기타 서비스는 각 마을에 위치한 전장 모병관을 통해 전장 대기실에서 이용해 주십시오.
+5. You can view and choose rewards in the arena waiting room.
+*/
+ MSG_BATTLEFIELD_HELP10 = 0x84d,
+/*20120314 to latest
+%s 전장이 시작됩니다.
+%s battle begins.
+20130807 to 20130814
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_START = 0x84e,
+/*20120314 to latest
+전장으로 이동하시겠습니까?
+Do you want to enter the arena?
+20130807 to 20130814
+%s 전장이 시작됩니다.
+%s battle begins.
+*/
+ MSG_BATTLEFIELD_DOYOU_MOVE = 0x84f,
+/*20120314 to latest
+[주의]
+[Note]
+20130807 to 20130814
+전장으로 이동하시겠습니까?
+Do you want to enter the arena?
+*/
+ MSG_BATTLEFIELD_WARNINGMSG1 = 0x850,
+/*20120314 to latest
+현재 위치가 마을, 필드 혹은 일반던전이
+When the battle is finished your character will
+20130807 to 20130814
+[주의]
+[Note]
+*/
+ MSG_BATTLEFIELD_WARNINGMSG2 = 0x851,
+/*20120314 to latest
+아닐 경우 전장 종료 후 저장된 위치로
+be returned to the current spot or (if it's not
+20130807 to 20130814
+현재 위치가 마을, 필드 혹은 일반던전이
+When the battle is finished your character will
+*/
+ MSG_BATTLEFIELD_WARNINGMSG3 = 0x852,
+/*20120314 to latest
+되돌아가게 됩니다.
+possible) to the save point.
+20130807 to 20130814
+아닐 경우 전장 종료 후 저장된 위치로
+be returned to the current spot or (if it's not
+*/
+ MSG_BATTLEFIELD_WARNINGMSG4 = 0x853,
+/*20120314 to latest
+다른 이의 요청 결과를 기다리고 있습니다.
+Waiting for the opponents.
+20130807 to 20130814
+되돌아가게 됩니다.
+possible) to the save point.
+*/
+ MSG_BATTLEFIELD_WAIT_PLAYER = 0x854,
+/*20120314 to latest
+전장 입장 요청
+Battlefield position request
+20130807 to 20130814
+다른 이의 요청 결과를 기다리고 있습니다.
+Waiting for the opponents.
+*/
+ MSG_BATTLEFIELD_REQUEST_JOIN = 0x855,
+/*20120314 to latest
+수락대기시간:%d초
+Accept standby time:%d seconds
+20130807 to 20130814
+전장 입장 요청
+Battlefield position request
+*/
+ MSG_BATTLEFIELD_WAITTIME_D = 0x856,
+/*20120314 to latest
+입장 대기 상태
+Standby position
+20130807 to 20130814
+수락대기시간:%d초
+Accept standby time:%d seconds
+*/
+ MSG_BATTLEFIELD_STATE_JOINWAIT = 0x857,
+/*20120314 to latest
+전장 명칭: %s
+Battlefield name:%s
+20130807 to 20130814
+입장 대기 상태
+Standby position
+*/
+ MSG_BATTLEFIELD_NAME_S = 0x858,
+/*20120314 to latest
+전장 필요 인원: %d
+Persons required:%d
+20130807 to 20130814
+전장 명칭: %s
+Battlefield name:%s
+*/
+ MSG_BATTLEFIELD_MEMBER_D = 0x859,
+/*20120314 to latest
+내 대기순번: %d
+Your position:%d
+20130807 to 20130814
+전장 필요 인원: %d
+Persons required:%d
+*/
+ MSG_BATTLEFIELD_MYRANK_D = 0x85a,
+/*20120314 to latest
+명칭 :
+Name:
+20130807 to 20130814
+내 대기순번: %d
+Your position:%d
+*/
+ MSG_BATTLEFIELD_DP_TITLE = 0x85b,
+/*20120314 to latest
+목표 :
+Goal:
+20130807 to 20130814
+명칭 :
+Name:
+*/
+ MSG_BATTLEFIELD_DP_AIM = 0x85c,
+/*20120314 to latest
+전장의 인원 구성 :
+Format:
+20130807 to 20130814
+목표 :
+Goal:
+*/
+ MSG_BATTLEFIELD_DP_MEMBER = 0x85d,
+/*20120314 to latest
+참여조건 :
+Level:
+20130807 to 20130814
+전장의 인원 구성 :
+Format:
+*/
+ MSG_BATTLEFIELD_DP_REQUIRED = 0x85e,
+/*20120314 to latest
+보상(승) :
+Win:
+20130807 to 20130814
+참여조건 :
+Level:
+*/
+ MSG_BATTLEFIELD_DP_WIN = 0x85f,
+/*20120314 to latest
+보상(무) :
+Draw:
+20130807 to 20130814
+보상(승) :
+Win:
+*/
+ MSG_BATTLEFIELD_DP_DRAW = 0x860,
+/*20120314 to latest
+보상(패) :
+Loss:
+20130807 to 20130814
+보상(무) :
+Draw:
+*/
+ MSG_BATTLEFIELD_DP_LOSS = 0x861,
+/*20120314 to latest
+전장을 개인으로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the individuals battle?
+20130807 to 20130814
+보상(패) :
+Loss:
+*/
+ MSG_BATTLEFIELD_DOYOU_SINGLE = 0x862,
+/*20120314 to latest
+전장을 파티로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the parties battle?
+20130807 to 20130814
+전장을 개인으로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the individuals battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_PALTY = 0x863,
+/*20120314 to latest
+전장을 길드로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the guilds battle?
+20130807 to 20130814
+전장을 파티로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the parties battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_GUILD = 0x864,
+/*20120314 to latest
+전장 목록
+Battleground List
+20130807 to 20130814
+전장을 길드로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the guilds battle?
+*/
+ MSG_BATTLEFIELD_LIST2 = 0x865,
+/*20120314 to latest
+%d VS %d
+20130807 to 20130814
+전장 목록
+Battleground List
+*/
+ MSG_BATTLEFIELD_D_VS_D = 0x866,
+/*20120314 to latest
+Base LV %d 이하
+LV %d and lower
+20130807 to 20130814
+%d VS %d
+*/
+ MSG_BATTLEFIELD_LEVELDOWN_D = 0x867,
+/*20120314 to latest
+Base LV %d 이상
+LV %d and higher
+20130807 to 20130814
+Base LV %d 이하
+LV %d and lower
+*/
+ MSG_BATTLEFIELD_LEVELUP_D = 0x868,
+/*20120314 to latest
+Base LV %d ~ %d
+LV %d ~ %d
+20130807 to 20130814
+Base LV %d 이상
+LV %d and higher
+*/
+ MSG_BATTLEFIELD_LEVEL_D_D = 0x869,
+/*20120314 to latest
+제한 없음
+No restrictions
+20130807 to 20130814
+Base LV %d ~ %d
+LV %d ~ %d
+*/
+ MSG_BATTLEFIELD_LIMITLESS = 0x86a,
+/*20120314 to latest
+[해당 맵에서는 신청하실 수 없습니다.]
+[You can't apply on this map.]
+20130807 to 20130814
+제한 없음
+No restrictions
+*/
+ MSG_BATTLEFIELD_MSG_NOT_JOINMAP = 0x86b,
+/*20120314 to latest
+[전장 재신청까지 약 1분의 대기시간을 필요로 합니다.]
+[You must wait about 1 minute to apply.]
+20130807 to 20130814
+[해당 맵에서는 신청하실 수 없습니다.]
+[You can't apply on this map.]
+*/
+ MSG_BATTLEFIELD_MSG_WAIT_1MM = 0x86c,
+/*20120314 to latest
+[파티에 먼저 가입하셔야 합니다.]
+[You must be in a party.]
+20130807 to 20130814
+[전장 재신청까지 약 1분의 대기시간을 필요로 합니다.]
+[You must wait about 1 minute to apply.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_PALTYJOIN = 0x86d,
+/*20120314 to latest
+[파티장만 신청 가능합니다.]
+[Only party leader can apply.]
+20130807 to 20130814
+[파티에 먼저 가입하셔야 합니다.]
+[You must be in a party.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_PALTYBOSS = 0x86e,
+/*20120314 to latest
+[접속되어있는 파티인원수가 많습니다.]
+[Too many party members online.]
+20130807 to 20130814
+[파티장만 신청 가능합니다.]
+[Only party leader can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_PARTYMEMBER = 0x86f,
+/*20120314 to latest
+[길드에 먼저 가입하셔야 합니다.]
+[You must be in a guild.]
+20130807 to 20130814
+[접속되어있는 파티인원수가 많습니다.]
+[Too many party members online.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_GUILDJOIN = 0x870,
+/*20120314 to latest
+[길드장만 신청 가능합니다.]
+[Only guild master can apply.]
+20130807 to 20130814
+[길드에 먼저 가입하셔야 합니다.]
+[You must be in a guild.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_GUILDBOSS = 0x871,
+/*20120314 to latest
+[접속되어있는 길드인원수가 많습니다.]
+[Too many guild members online.]
+20130807 to 20130814
+[길드장만 신청 가능합니다.]
+[Only guild master can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_GUILDMEMBER = 0x872,
+/*20120314 to 20120314
+아이템 합치기
+20120320 to latest
+이동예약
+Moving Book
+20130807 to 20130814
+[접속되어있는 길드인원수가 많습니다.]
+[Too many guild members online.]
+*/
+ MSG_RESERVE_CHANGE_CHARACTER_SLOT = 0x873,
+/*20120314 to 20120314
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+20120320 to latest
+이동
+Move
+20130807 to 20130814
+이동예약
+Moving Book
+*/
+ MSG_CHARACTER_SLOT_CHANGE = 0x874,
+/*20120314 to 20120314
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+20120320 to latest
+이름변경
+Rename
+20130807 to 20130814
+이동
+Move
+*/
+ MSG_CHANGE_CHARACTER_NAME = 0x875,
+/*20120314 to 20120314
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+20120320 to latest
+Make Character
+Create Character
+20130807 to 20130814
+이름변경
+Rename
+*/
+ MSG_MSG_MAKECHARCTER = 0x876,
+/*20120314 to 20120314
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+20120320 to latest
+http://ro.game.gnjoy.com/
+20130807 to 20130814
+Make Character
+Create Character
+*/
+ MSG_UAE_URL = 0x877,
+#endif
+#if PACKETVER >= 20120320
+/*20120320 to latest
+(%s) Server
+20130807 to 20130814
+http://ro.game.gnjoy.com/
+*/
+ MSG_UAE_SERVERSTR = 0x878,
+/*20120320 to 20120328
+아이템 합치기
+20120404 to latest
+아이템 병합(모두선택 Ctrl+클릭)
+Item Merge
+20130807 to 20130814
+(%s) Server
+*/
+ MSG_MERGE_ITEM = 0x879,
+/*20120320 to latest
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+20130807 to 20130814
+아이템 병합(모두선택 Ctrl+클릭)
+Item Merge
+*/
+ MSG_SELECT_ITEM_TO_MERGE = 0x87a,
+/*20120320 to latest
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+20130807 to 20130814
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+*/
+ MSG_MERGE_ITEM_SUCCESS = 0x87b,
+/*20120320 to latest
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+20130807 to 20130814
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_MERGE = 0x87c,
+/*20120320 to latest
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+20130807 to 20130814
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+*/
+ MSG_MERGE_ITEM_FAILED_MAX_COUNT = 0x87d,
+#endif
+#if PACKETVER >= 20120321
+/*20120321 to latest
+좌로 회전
+Rotate left
+20130807 to 20130814
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+*/
+ MSG_CHARACTER_LEFT_ROLL = 0x87e,
+/*20120321 to latest
+우로 회전
+Rotate right
+20130807 to 20130814
+좌로 회전
+Rotate left
+*/
+ MSG_CHARACTER_RIGHT_ROLL = 0x87f,
+#endif
+#if PACKETVER >= 20120328
+/*20120328 to latest
+(%s)님의 이전서버 정보보기
+(%s) to view the old server information
+20130807 to 20130814
+우로 회전
+Rotate right
+*/
+ MSG_VIEW_BEFORE_WORLDINFO = 0x880,
+/*20120328 to latest
+기존 서버 정보
+Existing server information
+20130807 to 20130814
+(%s)님의 이전서버 정보보기
+(%s) to view the old server information
+*/
+ MSG_VIEW_BEFORE_WORLDINFO_TITLE = 0x881,
+/*20120328 to latest
+^ff0000기존 서버 : ^0000ff
+^ff0000Existing server: ^0000ff
+20130807 to 20130814
+기존 서버 정보
+Existing server information
+*/
+ MSG_VIEW_BEFORE_SERVERINFO = 0x882,
+/*20120328 to latest
+^ff0000기존 캐릭명 : ^0000ff
+^ff0000Existing character: ^0000ff
+20130807 to 20130814
+^ff0000기존 서버 : ^0000ff
+^ff0000Existing server: ^0000ff
+*/
+ MSG_VIEW_BEFORE_CHARNAME = 0x883,
+/*20120328 to latest
+공격한 몬스터의 HP가 표시됩니다.
+Show monster HP bar when attacking.
+20130807 to 20130814
+^ff0000기존 캐릭명 : ^0000ff
+^ff0000Existing character: ^0000ff
+*/
+ MSG_MONSTER_HP_ON = 0x884,
+/*20120328 to 20120328
+공격한 몬스터의 HP가 표시되지 않습니다..
+20120404 to latest
+공격한 몬스터의 HP가 표시되지 않습니다.
+Hide monster HP bar when attacking.
+20130807 to 20130814
+공격한 몬스터의 HP가 표시됩니다.
+Show monster HP bar when attacking.
+*/
+ MSG_MONSTER_HP_OFF = 0x885,
+#endif
+#if PACKETVER >= 20120404
+/*20120404 to latest
+병합 가능한 아이템이 존재하지 않습니다
+Merge does not exist as an item
+20130807 to 20130814
+공격한 몬스터의 HP가 표시되지 않습니다.
+Hide monster HP bar when attacking.
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_EXIST = 0x886,
+/*20120404 to latest
+병합 가능한 아이템이 존재하지 않습니다.
+Merge items available does not exist.
+20130807 to 20130814
+병합 가능한 아이템이 존재하지 않습니다
+Merge does not exist as an item
+*/
+ MSG_NOT_EXIST_MERGE_ITEM = 0x887,
+/*20120404 to latest
+진행중
+Act
+20130807 to 20130814
+병합 가능한 아이템이 존재하지 않습니다.
+Merge items available does not exist.
+*/
+ MSG_QUESTUI_TAB_PROCESS = 0x888,
+/*20120404 to latest
+보류중
+Pen
+20130807 to 20130814
+진행중
+Act
+*/
+ MSG_QUESTUI_TAB_HOLD = 0x889,
+/*20120404 to latest
+추천
+Rec
+20130807 to 20130814
+보류중
+Pen
+*/
+ MSG_QUESTUI_TAB_BEST = 0x88a,
+/*20120404 to latest
+에피소드
+Episode
+20130807 to 20130814
+추천
+Rec
+*/
+ MSG_QUESTUI_TAB_EPISODE = 0x88b,
+/*20120404 to latest
+로컬
+Loc
+20130807 to 20130814
+에피소드
+Episode
+*/
+ MSG_QUESTUI_TAB_LOCAL = 0x88c,
+/*20120404 to latest
+이벤트
+Evt
+20130807 to 20130814
+로컬
+Loc
+*/
+ MSG_QUESTUI_TAB_EVENT = 0x88d,
+/*20120404 to latest
+신규
+New
+20130807 to 20130814
+이벤트
+Evt
+*/
+ MSG_QUESTUI_TAB_NEW = 0x88e,
+/*20120404 to latest
+사냥몬스터
+Monsters to kill
+20130807 to 20130814
+신규
+New
+*/
+ MSG_QUESTUI_HUNTMONSTER = 0x88f,
+/*20120404 to latest
+보상아이템
+Rewards
+20130807 to 20130814
+사냥몬스터
+Monsters to kill
+*/
+ MSG_QUESTUI_REWARDITEM = 0x890,
+/*20120404 to latest
+필요아이템
+Required Items
+20130807 to 20130814
+보상아이템
+Rewards
+*/
+ MSG_QUESTUI_NEEDITEM = 0x891,
+/*20120404 to latest
+제한시간
+Time Limit
+20130807 to 20130814
+필요아이템
+Required Items
+*/
+ MSG_QUESTUI_TIMELIMIT = 0x892,
+/*20120404 to latest
+마감시간
+Deadline
+20130807 to 20130814
+제한시간
+Time Limit
+*/
+ MSG_QUESTUI_CLOSINGTIME = 0x893,
+#endif
+#if PACKETVER >= 20120417
+/*20120417 to latest
+검색
+Search
+20130807 to 20130814
+마감시간
+Deadline
+*/
+ MSG_NAVIGATION_SEARCH = 0x894,
+/*20120417 to latest
+목표로 안내
+Navigation
+20130807 to 20130814
+검색
+Search
+*/
+ MSG_NAVIGATION_TARGETGO = 0x895,
+/*20120417 to latest
+길 정보
+Back to Navigation
+20130807 to 20130814
+목표로 안내
+Navigation
+*/
+ MSG_NAVIGATION_ROUTEINFO = 0x896,
+/*20120417 to latest
+검색 정보
+Find Information
+20130807 to 20130814
+길 정보
+Back to Navigation
+*/
+ MSG_NAVIGATION_SEARCHINFO = 0x897,
+/*20120417 to latest
+보기 모드 변경
+Toggle Minimap
+20130807 to 20130814
+검색 정보
+Find Information
+*/
+ MSG_NAVIGATION_VIEWCHANGE = 0x898,
+/*20120417 to 20130109
+안내 지시 색상 변경
+20130115 to latest
+외부 길정보 파일 읽기
+Read Information from External File
+20130807 to 20130814
+보기 모드 변경
+Toggle Minimap
+*/
+ MSG_NAVIGATION_LIGHTCHANGE = 0x899,
+/*20120417 to latest
+종료
+Exit
+20130807 to 20130814
+외부 길정보 파일 읽기
+Read Information from External File
+*/
+ MSG_NAVIGATION_END = 0x89a,
+/*20120417 to latest
+기본 UI로 변경
+Change the Default UI
+20130807 to 20130814
+종료
+Exit
+*/
+ MSG_NAVIGATION_BASE = 0x89b,
+/*20120417 to latest
+간편 UI로 변경
+Change to Default UI
+20130807 to 20130814
+기본 UI로 변경
+Change the Default UI
+*/
+ MSG_NAVIGATION_MINI = 0x89c,
+/*20120417 to latest
+도움말
+Help
+20130807 to 20130814
+간편 UI로 변경
+Change to Default UI
+*/
+ MSG_NAVIGATION_HELP = 0x89d,
+/*20120417 to latest
+ALL
+20130807 to 20130814
+도움말
+Help
+*/
+ MSG_NAVIGATION_ALL = 0x89e,
+/*20120417 to latest
+Map
+20130807 to 20130814
+ALL
+*/
+ MSG_NAVIGATION_MAP = 0x89f,
+/*20120417 to latest
+Npc
+20130807 to 20130814
+Map
+*/
+ MSG_NAVIGATION_NPC = 0x8a0,
+/*20120417 to latest
+Mob
+20130807 to 20130814
+Npc
+*/
+ MSG_NAVIGATION_MOB = 0x8a1,
+/*20120417 to latest
+검색 단어 설정 (Ex: 단어 단어 ...
+Enter search string... (Ex: word word ...)
+20130807 to 20130814
+Mob
+*/
+ MSG_NAVIGATION_SETSTRING = 0x8a2,
+/*20120417 to latest
+Scroll
+20130807 to 20130814
+검색 단어 설정 (Ex: 단어 단어 ...
+Enter search string... (Ex: word word ...)
+*/
+ MSG_NAVIGATION_SCROLL = 0x8a3,
+/*20120417 to latest
+던전이동 스크롤 사용 적용
+Use Scroll?
+20130807 to 20130814
+Scroll
+*/
+ MSG_NAVIGATION_USESCROLL = 0x8a4,
+/*20120417 to latest
+Service
+20130807 to 20130814
+던전이동 스크롤 사용 적용
+Use Scroll?
+*/
+ MSG_NAVIGATION_SERVICE = 0x8a5,
+/*20120417 to latest
+위치 이동 서비스 허용
+Use Kafra Warp?
+20130807 to 20130814
+Service
+*/
+ MSG_NAVIGATION_USESERVICE = 0x8a6,
+/*20120417 to latest
+Plane
+20130807 to 20130814
+위치 이동 서비스 허용
+Use Kafra Warp?
+*/
+ MSG_NAVIGATION_PLANE = 0x8a7,
+/*20120417 to latest
+비공정 이동 적용
+Use Airship?
+20130807 to 20130814
+Plane
+*/
+ MSG_NAVIGATION_USEPLANE = 0x8a8,
+/*20120417 to latest
+>> 목표 정보를 읽지 못함!
+>> Failed to read the target information.
+20130807 to 20130814
+비공정 이동 적용
+Use Airship?
+*/
+ MSG_NAVIGATION_TARGETUNKNOWN = 0x8a9,
+/*20120417 to latest
+<< 안내중 >>
+>> Destination <<
+20130807 to 20130814
+>> 목표 정보를 읽지 못함!
+>> Failed to read the target information.
+*/
+ MSG_NAVIGATION_GOING = 0x8aa,
+/*20120417 to latest
+<< 검색중... >>
+<< Goal >>
+20130807 to 20130814
+<< 안내중 >>
+>> Destination <<
+*/
+ MSG_NAVIGATION_SEARCHING = 0x8ab,
+/*20120417 to latest
+-----------
+20130807 to 20130814
+<< 검색중... >>
+<< Goal >>
+*/
+ MSG_NAVIGATION_UN = 0x8ac,
+/*20120417 to latest
+Navigation
+20130807 to 20130814
+-----------
+*/
+ MSG_NAVIGATION_NAVI = 0x8ad,
+/*20120417 to latest
+== 검색 결과(%d)==
+= Found (%d) ==
+20130807 to 20130814
+Navigation
+*/
+ MSG_NAVIGATION_SEARCHRESULT_D = 0x8ae,
+/*20120417 to latest
+Npc)%s:%s
+20130807 to 20130814
+== 검색 결과(%d)==
+= Found (%d) ==
+*/
+ MSG_NAVIGATION_NPC_S_S = 0x8af,
+/*20120417 to latest
+Mob)%s:%s
+20130807 to 20130814
+Npc)%s:%s
+*/
+ MSG_NAVIGATION_MOB_S_S = 0x8b0,
+/*20120417 to latest
+Map)%s
+20130807 to 20130814
+Mob)%s:%s
+*/
+ MSG_NAVIGATION_MAP_S = 0x8b1,
+/*20120417 to latest
+======== 결과 정보 ==========
+======== Results ==========
+20130807 to 20130814
+Map)%s
+*/
+ MSG_NAVIGATION_RESULTINFO = 0x8b2,
+/*20120417 to latest
+거리 : %d Sell %d WarpMove
+Dist %d Cell %d WarpMove
+20130807 to 20130814
+======== 결과 정보 ==========
+======== Results ==========
+*/
+ MSG_NAVIGATION_LENGTH = 0x8b3,
+/*20120417 to latest
+목표맵: %s(%s)
+Coords %s(%s)
+20130807 to 20130814
+거리 : %d Sell %d WarpMove
+Dist %d Cell %d WarpMove
+*/
+ MSG_NAVIGATION_TARGETMAP_S_S = 0x8b4,
+/*20120417 to latest
+목표 : %s(%d, %d)
+Goal:%s (%d,%d)
+20130807 to 20130814
+목표맵: %s(%s)
+Coords %s(%s)
+*/
+ MSG_NAVIGATION_TARGET_S_D_D = 0x8b5,
+/*20120417 to latest
+보스
+Boss
+20130807 to 20130814
+목표 : %s(%d, %d)
+Goal:%s (%d,%d)
+*/
+ MSG_NAVIGATION_BOSS = 0x8b6,
+/*20120417 to latest
+일반
+General
+20130807 to 20130814
+보스
+Boss
+*/
+ MSG_NAVIGATION_NORMAL = 0x8b7,
+/*20120417 to latest
+목표 : %s(%s)
+Goal:
+20130807 to 20130814
+일반
+General
+*/
+ MSG_NAVIGATION_TARGET_S_S = 0x8b8,
+/*20120417 to latest
+목표: (%d, %d)
+Goal: (%d, %d)
+20130807 to 20130814
+목표 : %s(%s)
+Goal:
+*/
+ MSG_NAVIGATION_TARGET_D_D = 0x8b9,
+/*20120417 to latest
+======= 길 안내 정보 =======
+======= Guidance =======
+20130807 to 20130814
+목표: (%d, %d)
+Goal: (%d, %d)
+*/
+ MSG_NAVIGATION_GOINFO = 0x8ba,
+/*20120417 to latest
+%2d) Item:%s => %s 사용!
+%2d) Item:%s => %s Use!
+20130807 to 20130814
+======= 길 안내 정보 =======
+======= Guidance =======
+*/
+ MSG_NAVIGATION_ITEM_S_S = 0x8bb,
+/*20120417 to latest
+%2d) %s(%d,%d)=>(%d,%d)
+20130807 to 20130814
+%2d) Item:%s => %s 사용!
+%2d) Item:%s => %s Use!
+*/
+ MSG_NAVIGATION_D_S_D_D_D_D = 0x8bc,
+/*20120417 to latest
+E%2d) %s(%d,%d)=>(%d,%d)
+20130807 to 20130814
+%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_E_D_S_D_D_D_D = 0x8bd,
+/*20120417 to latest
+E%2d) %s
+20130807 to 20130814
+E%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_E_D_S = 0x8be,
+/*20120417 to latest
+안내중 입니다! 종료 하시겠습니까?
+Do you want to cancel navigation?
+20130807 to 20130814
+E%2d) %s
+*/
+ MSG_NAVIGATION_GOEXIT = 0x8bf,
+/*20120417 to latest
+내비게이션 도움말
+How to Use Navigation
+20130807 to 20130814
+안내중 입니다! 종료 하시겠습니까?
+Do you want to cancel navigation?
+*/
+ MSG_NAVIGATION_HELPTITLE = 0x8c0,
+/*20120417 to latest
+------------------- 명령어 --------------------
+------------------- Instruction --------------------
+20130807 to 20130814
+내비게이션 도움말
+How to Use Navigation
+*/
+ MSG_NAVIGATION_HELP1 = 0x8c1,
+/*20120417 to latest
+1. /navigation /navi
+1) /Navigation or /navi
+20130807 to 20130814
+------------------- 명령어 --------------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP2 = 0x8c2,
+/*20120417 to 20120418
+ ex)/navi prontera 100 100 -> 맵이름, 100, 100
+20120424 to latest
+ ex)/navi prontera 100/100 -> 맵이름, 100/100
+ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+20130807 to 20130814
+1. /navigation /navi
+1) /Navigation or /navi
+*/
+ MSG_NAVIGATION_HELP3 = 0x8c3,
+/*20120417 to 20120418
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+20120424 to latest
+ 기본 명령어는 제니, 비공정 검색을 기본으로 합니다.
+2) /Navigation2 or /navi2
+20130807 to 20130814
+ ex)/navi prontera 100/100 -> 맵이름, 100/100
+ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP4 = 0x8c4,
+/*20120417 to 20120418
+ ex) /navi2 prontera 100090 111
+20120424 to latest
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+20130807 to 20130814
+ 기본 명령어는 제니, 비공정 검색을 기본으로 합니다.
+2) /Navigation2 or /navi2
+*/
+ MSG_NAVIGATION_HELP5 = 0x8c5,
+/*20120417 to 20120418
+-> 맵이름, 위치(100 90), scrool/ zeny/ plane (1:사용함 0: 사용안함)
+20120424 to latest
+ ex) /navi2 prontera 100/100 1/1/1
+-> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+20130807 to 20130814
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+*/
+ MSG_NAVIGATION_HELP6 = 0x8c6,
+/*20120417 to 20120418
+※ /navi2 의 경우 반드시 위치 좌표를 붙여서 3 자리로 적어야 한다
+20120424 to latest
+-> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+20130807 to 20130814
+ ex) /navi2 prontera 100/100 1/1/1
+-> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP7 = 0x8c7,
+/*20120417 to 20120418
+3. /$$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+20120424 to latest
+3. $$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+3) /$$ Output all the items (Can take a while...)
+20130807 to 20130814
+-> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP8 = 0x8c8,
+/*20120417 to 20120418
+4. /$$lv30 해당 레벨의 몬스터 출력
+20120424 to latest
+4. $$lv30 해당 레벨의 몬스터 출력
+4) /$$ Lv30 monsters are placed in the output
+20130807 to 20130814
+3. $$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+3) /$$ Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP9 = 0x8c9,
+/*20120417 to 20120418
+5. /$$lv20~30 해당 레벨 범위의 몬스터 출력
+20120424 to latest
+5. $$lv20~30 해당 레벨 범위의 몬스터 출력
+5) /$$ Lv20~30 monsters in that level range are placed in the output
+20130807 to 20130814
+4. $$lv30 해당 레벨의 몬스터 출력
+4) /$$ Lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP10 = 0x8ca,
+/*20120417 to latest
+------------------- 설명 --------------------
+------------------- Description --------------------
+20130807 to 20130814
+5. $$lv20~30 해당 레벨 범위의 몬스터 출력
+5) /$$ Lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_NAVIGATION_HELP11 = 0x8cb,
+/*20120417 to latest
+1.검색 종류는 전체, 맵, Npc, 몬스터 으로 분류 된다.
+1) One can search for monsters, npcs, maps, or all at once
+20130807 to 20130814
+------------------- 설명 --------------------
+------------------- Description --------------------
+*/
+ MSG_NAVIGATION_HELP12 = 0x8cc,
+/*20120417 to latest
+2.명령어로 검색한다. 규칙은 검색 하려는 문자열이 모두 포함된 정보를 출력 한다.
+2) You can press the search button to get results. It will out put the results depending on what rule you choose
+20130807 to 20130814
+1.검색 종류는 전체, 맵, Npc, 몬스터 으로 분류 된다.
+1) One can search for monsters, npcs, maps, or all at once
+*/
+ MSG_NAVIGATION_HELP13 = 0x8cd,
+/*20120417 to latest
+ ex) 프론 카프 -> 검색 결과 프론테라의 카프라를 모두 출력 한다.
+ex) Drop down box -> Select "Npc", then type in the box "Kafra". Results will now be displayed
+20130807 to 20130814
+2.명령어로 검색한다. 규칙은 검색 하려는 문자열이 모두 포함된 정보를 출력 한다.
+2) You can press the search button to get results. It will out put the results depending on what rule you choose
+*/
+ MSG_NAVIGATION_HELP14 = 0x8ce,
+/*20120417 to latest
+3.리스트에서 항목을 선택하면 정보가 출력된다.
+3) When you select an item from a list, information about it are displayed.
+20130807 to 20130814
+ ex) 프론 카프 -> 검색 결과 프론테라의 카프라를 모두 출력 한다.
+ex) Drop down box -> Select "Npc", then type in the box "Kafra". Results will now be displayed
+*/
+ MSG_NAVIGATION_HELP15 = 0x8cf,
+/*20120417 to latest
+ 출력 되고 있는 목표가 있을때 안내 버튼을 클릭하면 해당 목표로 길을 안내 한다.
+-> When button is clicked, it will point you towards your destination if available
+20130807 to 20130814
+3.리스트에서 항목을 선택하면 정보가 출력된다.
+3) When you select an item from a list, information about it are displayed.
+*/
+ MSG_NAVIGATION_HELP16 = 0x8d0,
+/*20120417 to latest
+4.scrool/ zeny/ plane 상자를 원하는 만큼 체크하여 더 빠른 경로를 안내 받을 수 있다.
+4) Scroll | Zeny | Plane options can be checked to find a faster route
+20130807 to 20130814
+ 출력 되고 있는 목표가 있을때 안내 버튼을 클릭하면 해당 목표로 길을 안내 한다.
+-> When button is clicked, it will point you towards your destination if available
+*/
+ MSG_NAVIGATION_HELP17 = 0x8d1,
+/*20120417 to latest
+5.안내 버튼이 눌러지면 결과 리스트창은 길안내 리스트 장으로 변경 된다.
+5) Guide button is pressed, the result list window displays where routes can change direction
+20130807 to 20130814
+4.scrool/ zeny/ plane 상자를 원하는 만큼 체크하여 더 빠른 경로를 안내 받을 수 있다.
+4) Scroll | Zeny | Plane options can be checked to find a faster route
+*/
+ MSG_NAVIGATION_HELP18 = 0x8d2,
+/*20120417 to latest
+6.검색 리스트창 하단 버튼을 이용하여
+6) Using the button below, search results can be found
+20130807 to 20130814
+5.안내 버튼이 눌러지면 결과 리스트창은 길안내 리스트 장으로 변경 된다.
+5) Guide button is pressed, the result list window displays where routes can change direction
+*/
+ MSG_NAVIGATION_HELP19 = 0x8d3,
+/*20120417 to latest
+ [결과 리스트 창] <-> [길 안내 정보 창] 으로 보기 모드 변경 가능하다.
+-> [Results List Window] <-> [View Modes can be switched]
+20130807 to 20130814
+6.검색 리스트창 하단 버튼을 이용하여
+6) Using the button below, search results can be found
+*/
+ MSG_NAVIGATION_HELP20 = 0x8d4,
+/*20120417 to latest
+Level:%d (보스)
+Level:%d (Boss)
+20130807 to 20130814
+ [결과 리스트 창] <-> [길 안내 정보 창] 으로 보기 모드 변경 가능하다.
+-> [Results List Window] <-> [View Modes can be switched]
+*/
+ MSG_NAVIGATION_LEVEL_D_BOSS = 0x8d5,
+/*20120417 to latest
+Level:%d (일반)
+Level:%d (Mob)
+20130807 to 20130814
+Level:%d (보스)
+Level:%d (Boss)
+*/
+ MSG_NAVIGATION_LEVEL_D_NORMAL = 0x8d6,
+/*20120417 to latest
+수속성%d
+Water %d
+20130807 to 20130814
+Level:%d (일반)
+Level:%d (Mob)
+*/
+ MSG_NAVIGATION_PROPERTY1 = 0x8d7,
+/*20120417 to latest
+지속성%d
+Earth %d
+20130807 to 20130814
+수속성%d
+Water %d
+*/
+ MSG_NAVIGATION_PROPERTY2 = 0x8d8,
+/*20120417 to latest
+화속성%d
+Fire %d
+20130807 to 20130814
+지속성%d
+Earth %d
+*/
+ MSG_NAVIGATION_PROPERTY3 = 0x8d9,
+/*20120417 to latest
+풍속성%d
+Wind %d
+20130807 to 20130814
+화속성%d
+Fire %d
+*/
+ MSG_NAVIGATION_PROPERTY4 = 0x8da,
+/*20120417 to latest
+독속성%d
+Poison %d
+20130807 to 20130814
+풍속성%d
+Wind %d
+*/
+ MSG_NAVIGATION_PROPERTY5 = 0x8db,
+/*20120417 to latest
+성속성%d
+Holy %d
+20130807 to 20130814
+독속성%d
+Poison %d
+*/
+ MSG_NAVIGATION_PROPERTY6 = 0x8dc,
+/*20120417 to latest
+암속성%d
+Shadow %d
+20130807 to 20130814
+성속성%d
+Holy %d
+*/
+ MSG_NAVIGATION_PROPERTY7 = 0x8dd,
+/*20120417 to latest
+염속성%d
+Ghost %d
+20130807 to 20130814
+암속성%d
+Shadow %d
+*/
+ MSG_NAVIGATION_PROPERTY8 = 0x8de,
+/*20120417 to latest
+언데드%d
+Undead %d
+20130807 to 20130814
+염속성%d
+Ghost %d
+*/
+ MSG_NAVIGATION_PROPERTY9 = 0x8df,
+/*20120417 to latest
+무속성%d
+Neutral %d
+20130807 to 20130814
+언데드%d
+Undead %d
+*/
+ MSG_NAVIGATION_PROPERTY0 = 0x8e0,
+/*20120417 to latest
+중형
+Medium
+20130807 to 20130814
+무속성%d
+Neutral %d
+*/
+ MSG_NAVIGATION_SCALE1 = 0x8e1,
+/*20120417 to latest
+대형
+Large
+20130807 to 20130814
+중형
+Medium
+*/
+ MSG_NAVIGATION_SCALE2 = 0x8e2,
+/*20120417 to latest
+소형
+Small
+20130807 to 20130814
+대형
+Large
+*/
+ MSG_NAVIGATION_SCALE0 = 0x8e3,
+/*20120417 to latest
+불사형
+Undead
+20130807 to 20130814
+소형
+Small
+*/
+ MSG_NAVIGATION_RACE1 = 0x8e4,
+/*20120417 to latest
+동물형
+Brute
+20130807 to 20130814
+불사형
+Undead
+*/
+ MSG_NAVIGATION_RACE2 = 0x8e5,
+/*20120417 to latest
+식물형
+Plant
+20130807 to 20130814
+동물형
+Brute
+*/
+ MSG_NAVIGATION_RACE3 = 0x8e6,
+/*20120417 to latest
+곤충형
+Insect
+20130807 to 20130814
+식물형
+Plant
+*/
+ MSG_NAVIGATION_RACE4 = 0x8e7,
+/*20120417 to latest
+어패형
+Fish
+20130807 to 20130814
+곤충형
+Insect
+*/
+ MSG_NAVIGATION_RACE5 = 0x8e8,
+/*20120417 to latest
+악마형
+Demon
+20130807 to 20130814
+어패형
+Fish
+*/
+ MSG_NAVIGATION_RACE6 = 0x8e9,
+/*20120417 to latest
+인간형
+Demi-Human
+20130807 to 20130814
+악마형
+Demon
+*/
+ MSG_NAVIGATION_RACE7 = 0x8ea,
+/*20120417 to latest
+천사형
+Angel
+20130807 to 20130814
+인간형
+Demi-Human
+*/
+ MSG_NAVIGATION_RACE8 = 0x8eb,
+/*20120417 to latest
+용족
+Dragon
+20130807 to 20130814
+천사형
+Angel
+*/
+ MSG_NAVIGATION_RACE9 = 0x8ec,
+/*20120417 to latest
+무형
+Formless
+20130807 to 20130814
+용족
+Dragon
+*/
+ MSG_NAVIGATION_RACE0 = 0x8ed,
+/*20120417 to latest
+%s 이동 클릭
+Click to move %s
+20130807 to 20130814
+무형
+Formless
+*/
+ MSG_NAVIGATION_MOVECLICK = 0x8ee,
+/*20120417 to latest
+Npc 이동 서비스 이용
+Move to the Kafra Service Npc
+20130807 to 20130814
+%s 이동 클릭
+Click to move %s
+*/
+ MSG_NAVIGATION_NPCMOVE = 0x8ef,
+/*20120417 to latest
+NPC 클릭
+Click the NPC
+20130807 to 20130814
+Npc 이동 서비스 이용
+Move to the Kafra Service Npc
+*/
+ MSG_NAVIGATION_NPCCLICK = 0x8f0,
+/*20120417 to latest
+%s 이동
+Move %s
+20130807 to 20130814
+NPC 클릭
+Click the NPC
+*/
+ MSG_NAVIGATION_S_MOVE = 0x8f1,
+/*20120417 to latest
+비공정 이동
+Move to the Airship Service
+20130807 to 20130814
+%s 이동
+Move %s
+*/
+ MSG_NAVIGATION_PLANEMOVE = 0x8f2,
+/*20120417 to latest
+워프 이용
+By Warp
+20130807 to 20130814
+비공정 이동
+Move to the Airship Service
+*/
+ MSG_NAVIGATION_WARPUSE = 0x8f3,
+/*20120417 to latest
+도착점 : ( %d %d )
+End Points: (%d %d)
+20130807 to 20130814
+워프 이용
+By Warp
+*/
+ MSG_NAVIGATION_TARGETPOINT_D_D = 0x8f4,
+/*20120417 to 20170517
+네비게이션이 지원 되지 않는 지역 입니다.
+20130807 to 20130814
+도착점 : ( %d %d )
+End Points: (%d %d)
+20170524 to latest
+내비게이션이 지원 되지 않는 지역 입니다.
+That does not support the navigation area
+*/
+ MSG_NAVIGATION_UNKNOWNMAP = 0x8f5,
+/*20120417 to latest
+찾고자 하는 목적이 불분명 합니다.
+The purpose is unclear
+20130807 to 20130814
+네비게이션이 지원 되지 않는 지역 입니다.
+*/
+ MSG_NAVIGATION_RS_UNKNOWN = 0x8f6,
+/*20120417 to latest
+매칭이 맞지 않는 맵이다.
+Does not meet the map requirement
+20130807 to 20130814
+찾고자 하는 목적이 불분명 합니다.
+The purpose is unclear
+*/
+ MSG_NAVIGATION_RS_NOTSAMEMAP = 0x8f7,
+/*20120417 to latest
+출발 지역에 대한 정보 설정 실패!
+Information Failure | Change settings
+20130807 to 20130814
+매칭이 맞지 않는 맵이다.
+Does not meet the map requirement
+*/
+ MSG_NAVIGATION_RS_FAILSTARTDATA = 0x8f8,
+/*20120417 to latest
+도착 지점에 대한 정보 설정 실패!
+Failed to set info for location!
+20130807 to 20130814
+출발 지역에 대한 정보 설정 실패!
+Information Failure | Change settings
+*/
+ MSG_NAVIGATION_RS_FAILTARGET = 0x8f9,
+/*20120417 to latest
+길 찾기 실패
+Failed to find a path
+20130807 to 20130814
+도착 지점에 대한 정보 설정 실패!
+Failed to set info for location!
+*/
+ MSG_NAVIGATION_RS_FAILROUTE = 0x8fa,
+/*20120417 to latest
+플레이어 위치 찾기 실패
+Failed to find players
+20130807 to 20130814
+길 찾기 실패
+Failed to find a path
+*/
+ MSG_NAVIGATION_RS_FAILPLAYER = 0x8fb,
+/*20120417 to latest
+내비게이션에 정보가 없습니다.
+No Information
+20130807 to 20130814
+플레이어 위치 찾기 실패
+Failed to find players
+*/
+ MSG_NAVIGATION_RS_NODATA = 0x8fc,
+/*20120417 to latest
+해당 맵은 길찾기가 지원 되지 않는 맵입니다.
+Map doesn't support directions
+20130807 to 20130814
+내비게이션에 정보가 없습니다.
+No Information
+*/
+ MSG_NAVIGATION_RS_MAPNOTNAVIGATION = 0x8fd,
+/*20120417 to latest
+목표를 지정 하시기 바랍니다.
+Please specify target goals.
+20130807 to 20130814
+해당 맵은 길찾기가 지원 되지 않는 맵입니다.
+Map doesn't support directions
+*/
+ MSG_NAVIGATION_RS_FAILTARGETROUTE = 0x8fe,
+/*20120417 to latest
+도착.
+Found
+20130807 to 20130814
+목표를 지정 하시기 바랍니다.
+Please specify target goals.
+*/
+ MSG_NAVIGATION_RS_SUCCESS = 0x8ff,
+/*20120417 to latest
+길 안내가 시작 되었습니다.
+Directions were started
+20130807 to 20130814
+도착.
+Found
+*/
+ MSG_NAVIGATION_RS_START = 0x900,
+/*20120417 to latest
+찾고자 하는 몬스터가 있는 맵 입니다.
+Is the map that your looking for mob
+20130807 to 20130814
+길 안내가 시작 되었습니다.
+Directions were started
+*/
+ MSG_NAVIGATION_RS_MOBTARGETMAP = 0x901,
+/*20120417 to latest
+찾고자 하는 맵이 해당 맵 입니다.
+Map appears on the guide you are looking for
+20130807 to 20130814
+찾고자 하는 몬스터가 있는 맵 입니다.
+Is the map that your looking for mob
+*/
+ MSG_NAVIGATION_RS_TARGETMAP = 0x902,
+/*20120417 to latest
+아이템을 사용하여 이동하여 주시기 바랍니다.
+Please navigate using the item
+20130807 to 20130814
+찾고자 하는 맵이 해당 맵 입니다.
+Map appears on the guide you are looking for
+*/
+ MSG_NAVIGATION_RS_SCROLL = 0x903,
+/*20120417 to latest
+안내하는 위치로 이동하시기 바랍니다.
+Please follow the instruction to reach your destination.
+20130807 to 20130814
+아이템을 사용하여 이동하여 주시기 바랍니다.
+Please navigate using the item
+*/
+ MSG_NAVIGATION_RS_ROUTE_SUCCESS = 0x904,
+/*20120417 to latest
+목표 맵에 도착하였습니다.
+Arrived at the target map
+20130807 to 20130814
+안내하는 위치로 이동하시기 바랍니다.
+Please follow the instruction to reach your destination.
+*/
+ MSG_NAVIGATION_RS_MAPTMAP_SUCCESS = 0x905,
+/*20120417 to latest
+찾고자 하는 Npc가 있는 맵에 도착 하였습니다. Npc로 이동하시기 바랍니다.
+Arrived on the map that has the Npc your looking for. Go to that NPC
+20130807 to 20130814
+목표 맵에 도착하였습니다.
+Arrived at the target map
+*/
+ MSG_NAVIGATION_RS_NPCTMAP_SUCCESS = 0x906,
+/*20120417 to latest
+찾고자 하는 Mob이 서식하는 맵에 도착 하였습니다.
+You have arrived at the mob you were looking for
+20130807 to 20130814
+찾고자 하는 Npc가 있는 맵에 도착 하였습니다. Npc로 이동하시기 바랍니다.
+Arrived on the map that has the Npc your looking for. Go to that NPC
+*/
+ MSG_NAVIGATION_RS_MOBTMAP_SUCCESS = 0x907,
+/*20120417 to latest
+이전과 동일한 목표 입니다.
+You have reached your goal
+20130807 to 20130814
+찾고자 하는 Mob이 서식하는 맵에 도착 하였습니다.
+You have arrived at the mob you were looking for
+*/
+ MSG_NAVIGATION_RS_POSTMAP_SUCCESS = 0x908,
+/*20120417 to latest
+가리키는 방향으로 가시기 바랍니다.
+Please go to indicated direction.
+20130807 to 20130814
+이전과 동일한 목표 입니다.
+You have reached your goal
+*/
+ MSG_NAVIGATION_RS_SAMETARGET = 0x909,
+/*20120417 to latest
+목표가 여기 입니다.
+The goal has been reached
+20130807 to 20130814
+가리키는 방향으로 가시기 바랍니다.
+Please go to indicated direction.
+*/
+ MSG_NAVIGATION_RS_HERE = 0x90a,
+/*20120417 to latest
+Navigation >: %s
+20130807 to 20130814
+목표가 여기 입니다.
+The goal has been reached
+*/
+ MSG_NAVIGATION_PRINT_S = 0x90b,
+/*20120417 to latest
+Navigation >: 안내하는 %s(을)를 이용하여
+Navigation >: Talk to Guide "%s" (A)
+20130807 to 20130814
+Navigation >: %s
+*/
+ MSG_NAVIGATION_PRINT_GO_S = 0x90c,
+/*20120417 to latest
+Navigation >: 맵(%s)으로 이동하시기 바랍니다
+Navigation >: Move to (%s) map
+20130807 to 20130814
+Navigation >: 안내하는 %s(을)를 이용하여
+Navigation >: Talk to Guide "%s" (A)
+*/
+ MSG_NAVIGATION_PRINT_MAP_S = 0x90d,
+/*20120417 to latest
+Navigation >: 맵(%s)을 선택하여 이동 하시기 바랍니다
+Navigation >: Choose (%s) Map from Kafra
+20130807 to 20130814
+Navigation >: 맵(%s)으로 이동하시기 바랍니다
+Navigation >: Move to (%s) map
+*/
+ MSG_NAVIGATION_PRINT_SELECTMAP_S = 0x90e,
+/*20120417 to latest
+Navigation >: 비공정으로 이동 하시기 바랍니다
+Navigation >: Please go to the AirShip
+20130807 to 20130814
+Navigation >: 맵(%s)을 선택하여 이동 하시기 바랍니다
+Navigation >: Choose (%s) Map from Kafra
+*/
+ MSG_NAVIGATION_PRINT_PLANE = 0x90f,
+/*20120417 to latest
+Navigation >: 워프를 이용하여 다음 지역으로 이동하시기 바랍니다.
+Navigation >: Get to your destination by using WarpPortal
+20130807 to 20130814
+Navigation >: 비공정으로 이동 하시기 바랍니다
+Navigation >: Please go to the AirShip
+*/
+ MSG_NAVIGATION_PRINT_WARP = 0x910,
+/*20120417 to latest
+Item:
+20130807 to 20130814
+Navigation >: 워프를 이용하여 다음 지역으로 이동하시기 바랍니다.
+Navigation >: Get to your destination by using WarpPortal
+*/
+ MSG_NAVIGATION_PRINT_ITEM = 0x911,
+/*20120417 to latest
+$$
+20130807 to 20130814
+Item:
+*/
+ MSG_NAVIGATION_ZZ = 0x912,
+/*20120417 to latest
+$$lv
+20130807 to 20130814
+$$
+*/
+ MSG_NAVIGATION_ZZLV = 0x913,
+/*20120417 to latest
+~
+20130807 to 20130814
+$$lv
+*/
+ MSG_NAVIGATION_ZZLIMIT = 0x914,
+/*20120417 to latest
+$$all
+20130807 to 20130814
+~
+*/
+ MSG_NAVIGATION_ZZALL = 0x915,
+#endif
+#if PACKETVER >= 20120424
+/*20120424 to latest
+구매 확인서
+Confirm Deal
+20130807 to 20130814
+$$all
+*/
+ MSG_SHOP_ITEM_BAY_TITLE = 0x916,
+/*20120424 to latest
+구입하려는 아이템들의 총가격은
+Below is the total cost:
+20130807 to 20130814
+구매 확인서
+Confirm Deal
+*/
+ MSG_SHOP_ITEM_BAY_MAG1 = 0x917,
+/*20120424 to latest
+Zeny 입니다.
+ Zeny to complete the transaction.
+20130807 to 20130814
+구입하려는 아이템들의 총가격은
+Below is the total cost:
+*/
+ MSG_SHOP_ITEM_BAY_MAG2 = 0x918,
+/*20120424 to latest
+구입하시겠습니까?
+Press buy to confirm.
+20130807 to 20130814
+Zeny 입니다.
+ Zeny to complete the transaction.
+*/
+ MSG_SHOP_ITEM_BAY_MAG3 = 0x919,
+#endif
+#if PACKETVER >= 20120502
+/*20120502 to 20120529
+%.3f%% (PC방 %.3f%% + TPLUS %.3f%% + 프리미엄 %.3f%% + %s서버 %.3f%%)
+20120601 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + 프리미엄 %.1f%% + %s서버 %.1f%%)
+%.1f% (PCRoom %.1f% + TPLUS %.1f% + Premium %.1f% + %sServer %.1f%)
+20130807 to 20130814
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BASIC_EXP_MSG2 = 0x91a,
+#endif
+#if PACKETVER >= 20120508
+/*20120508 to latest
+카드 북
+Card Book
+20130807 to 20130814
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + 프리미엄 %.1f%% + %s서버 %.1f%%)
+%.1f% (PCRoom %.1f% + TPLUS %.1f% + Premium %.1f% + %sServer %.1f%)
+*/
+ MSG_CARDWIN = 0x91b,
+#endif
+#if PACKETVER >= 20120515
+/*20120515 to latest
+%d%% [ ( 기본 100%% + %s서버 %d%% ) * 활성 %.1f ]
+%d%% [ ( Basic 100%% + %sServer %d%% ) * Active %.1f ]
+20130807 to 20130814
+카드 북
+Card Book
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN = 0x91c,
+/*20120515 to latest
+%d%% [ 기본 100%% + %s서버 %d%% ]
+%d%% [ Basic 100%% + %sServer %d%% ]
+20130807 to 20130814
+%d%% [ ( 기본 100%% + %s서버 %d%% ) * 활성 %.1f ]
+%d%% [ ( Basic 100%% + %sServer %d%% ) * Active %.1f ]
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN_DEATH = 0x91d,
+#endif
+#if PACKETVER >= 20120523
+/*20120523 to latest
+이곳은 PK 지역입니다. 미성년자는 자발적으로 떠나주시기 바랍니다.
+This is PK region. Minors,Please leave immediately.
+20130807 to 20130814
+%d%% [ 기본 100%% + %s서버 %d%% ]
+%d%% [ Basic 100%% + %sServer %d%% ]
+*/
+ MSG_CAUTION_PKZONE = 0x91e,
+/*20120523 to latest
+피로도
+Fatigue
+20130807 to 20130814
+이곳은 PK 지역입니다. 미성년자는 자발적으로 떠나주시기 바랍니다.
+This is PK region. Minors,Please leave immediately.
+*/
+ MSG_FATIGUE = 0x91f,
+/*20120523 to 20120529
+건강상태 이며 게임수익은 100%%입니다.
+20120601 to latest
+건강상태 이며 게임수익은 100%입니다.
+Health and gaming revenue is 100%%.
+20130807 to 20130814
+피로도
+Fatigue
+*/
+ MSG_FATIGUE_LEVEL_ZERO = 0x920,
+/*20120523 to 20120529
+지금은 피로상태이므로 손님의 게임수익은 50%% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+20120601 to latest
+지금은 피로상태이므로 손님의 게임수익은 50% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+Fatigue because it is now a guest of the gaming revenue is down 50 percent.Hope for the proper health
+20130807 to 20130814
+건강상태 이며 게임수익은 100%입니다.
+Health and gaming revenue is 100%%.
+*/
+ MSG_FATIGUE_LEVEL_HALF = 0x921,
+/*20120523 to 20120529
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+20120601 to latest
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+Now because it is a non-health to the health of the guests want to offline games. If you still are online gaming revenue because the damage to the health of the game falls to 0% again after 5 hours will be restored offline.
+20130807 to 20130814
+지금은 피로상태이므로 손님의 게임수익은 50% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+Fatigue because it is now a guest of the gaming revenue is down 50 percent.Hope for the proper health
+*/
+ MSG_FATIGUE_LEVEL_FULL = 0x922,
+/*20120523 to latest
+접속시간 %d 분이 되었습니다.
+Online since %d minutes
+20130807 to 20130814
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+Now because it is a non-health to the health of the guests want to offline games. If you still are online gaming revenue because the damage to the health of the game falls to 0% again after 5 hours will be restored offline.
+*/
+ MSG_FATIGUE_MESSAGE0 = 0x923,
+/*20120523 to latest
+접속시간 %d 시간이 되었습니다.
+Online Time: %d
+20130807 to 20130814
+접속시간 %d 분이 되었습니다.
+Online since %d minutes
+*/
+ MSG_FATIGUE_MESSAGE1 = 0x924,
+/*20120523 to latest
+접속시간 %d 시간 %d 분이 되었습니다.
+Online since %d hours and %d minutes
+20130807 to 20130814
+접속시간 %d 시간이 되었습니다.
+Online Time: %d
+*/
+ MSG_FATIGUE_MESSAGE2 = 0x925,
+/*20120523 to latest
+/monsterhp : 공격한 몬스터의 HP정보를 표시합니다. On Off
+/monsterhp: Show the hp of attacked monster. On off
+20130807 to 20130814
+접속시간 %d 시간 %d 분이 되었습니다.
+Online since %d hours and %d minutes
+*/
+ MSG_EXPLAIN_MONSTERHP = 0x926,
+#endif
+#if PACKETVER >= 20120529
+/*20120529 to latest
+스킬포인트 :
+Skill Points:
+20130807 to 20130814
+/monsterhp : 공격한 몬스터의 HP정보를 표시합니다. On Off
+/monsterhp: Show the hp of attacked monster. On off
+*/
+ MSG_SKILLPOINT2 = 0x927,
+#endif
+#if PACKETVER >= 20120601
+/*20120601 to latest
+인증서버로 부터의 응답이 없습니다. 다시 시도해 주세요
+There is no response from the authentification server. Please try again
+20130807 to 20130814
+스킬포인트 :
+Skill Points:
+*/
+ MSG_BAN_BILLING_SERVER_ERROR = 0x928,
+#endif
+#if PACKETVER >= 20120612
+/*20120612 to latest
+암호를 변경하여 주시기 바랍니다.
+Please change your password
+20130807 to 20130814
+인증서버로 부터의 응답이 없습니다. 다시 시도해 주세요
+There is no response from the authentification server. Please try again
+*/
+ MSG_REFUSE_CHANGE_PASSWD_FORCE = 0x929,
+/*20120612 to latest
+http://www.ragnarok.co.kr
+20130807 to 20130814
+암호를 변경하여 주시기 바랍니다.
+Please change your password
+*/
+ MSG_REFUSE_CHANGE_PASSWD_SITE = 0x92a,
+/*20120612 to latest
+고객님께서는 현재 접속금지 시간입니다.
+Guest access is prohibited
+20130807 to 20130814
+http://www.ragnarok.co.kr
+*/
+ MSG_PLANNED_TIME_SHUTDOWN = 0x92b,
+/*20120612 to latest
+셧다운제도에 의해 고객님의 게임제한 시간은 %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d에 게임이 종료될 예정입니다.
+Your System is been Shutdown, %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d is the end time.
+20130807 to 20130814
+고객님께서는 현재 접속금지 시간입니다.
+Guest access is prohibited
+*/
+ MSG_SHOUTDOWN_TIME = 0x92c,
+#endif
+#if PACKETVER >= 20120626
+/*20120626 to latest
+고객님의 계정은 선택적 셧다운이 적용된 계정이며, 잔여시간은 %1.2d시간 %1.2d분입니다. 게임 이용에 참고해주시기 바랍니다.
+Selected System Shutdown is activated in your account,Time Left: %1.2d hours %1.2d minutes.
+20130807 to 20130814
+셧다운제도에 의해 고객님의 게임제한 시간은 %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d에 게임이 종료될 예정입니다.
+Your System is been Shutdown, %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d is the end time.
+*/
+ MSG_PARTIAL_SHOUTDOWN_TIME = 0x92d,
+#endif
+#if PACKETVER >= 20120702
+/*20120702 to latest
+리플레이
+Replay
+20130807 to 20130814
+고객님의 계정은 선택적 셧다운이 적용된 계정이며, 잔여시간은 %1.2d시간 %1.2d분입니다. 게임 이용에 참고해주시기 바랍니다.
+Selected System Shutdown is activated in your account,Time Left: %1.2d hours %1.2d minutes.
+*/
+ MSG_MENU_REPLAYWND = 0x92e,
+/*20120702 to latest
+매크로
+Macro
+20130807 to 20130814
+리플레이
+Replay
+*/
+ MSG_MENU_MACROWND = 0x92f,
+/*20120702 to latest
+Webbrowser
+20130807 to 20130814
+매크로
+Macro
+*/
+ MSG_MENU_WEBBROWSERWND = 0x930,
+/*20120702 to 20170517
+네비게이션
+20130807 to 20130814
+Webbrowser
+20170524 to latest
+내비게이션
+Navigation
+*/
+ MSG_MENU_NAVIGATIONWND = 0x931,
+/*20120702 to latest
+UAEURL
+20130807 to 20130814
+네비게이션
+*/
+ MSG_MENU_UAEURLWND = 0x932,
+/*20120702 to latest
+ 클랜정보
+Clan Information
+20130807 to 20130814
+UAEURL
+*/
+ MSG_CLAN_INFOMANAGE = 0x933,
+/*20120702 to latest
+클랜레벨
+Clan Level
+20130807 to 20130814
+ 클랜정보
+Clan Information
+*/
+ MSG_CLAN_LEVEL = 0x934,
+/*20120702 to latest
+클랜명
+Clan Name
+20130807 to 20130814
+클랜레벨
+Clan Level
+*/
+ MSG_CLAN_NAME = 0x935,
+/*20120702 to latest
+클랜마크
+Clan Mark
+20130807 to 20130814
+클랜명
+Clan Name
+*/
+ MSG_CLAN_MARK = 0x936,
+/*20120702 to latest
+동맹클랜
+Ally Clan
+20130807 to 20130814
+클랜마크
+Clan Mark
+*/
+ MSG_ALLY_CLAN = 0x937,
+/*20120702 to 20130529
+적대길드
+Antagonists
+20130605 to latest
+적대클랜
+Antagonist Clan
+20130807 to 20130814
+동맹클랜
+Ally Clan
+*/
+ MSG_HOSTILITY_CLAN = 0x938,
+/*20120702 to latest
+클랜에게 보냄
+Send to Clan
+20130807 to 20130814
+적대클랜
+Antagonist Clan
+*/
+ MSG_SEND_TO_CLAN = 0x939,
+/*20120702 to latest
+마스터이름
+ClanMaster Name
+20130807 to 20130814
+클랜에게 보냄
+Send to Clan
+*/
+ MSG_CLAN_MASTER_NAME = 0x93a,
+/*20120702 to latest
+조합원수
+Number of Members
+20130807 to 20130814
+마스터이름
+ClanMaster Name
+*/
+ MSG_CLAN_NUM_MEMBER = 0x93b,
+/*20120702 to 20120702
+조합원 평균레벨
+Avg.lvl of Guildsmen
+20120710 to latest
+관리영지
+Castles Owned
+20130807 to 20130814
+조합원수
+Number of Members
+*/
+ MSG_CLAN_MANAGE_LAND = 0x93c,
+/*20120702 to 20130814
+관리영지
+Castles Owned
+20120716 to latest
+클랜 채팅 메시지 표시
+Clan Chat Messages
+*/
+ MSG_VIEW_CLAN_MSG = 0x93d,
+#endif
+#if PACKETVER >= 20120716
+/*20120716 to latest
+충전 페이지로 이동합니다.
+Go to Page Charged.
+20130807 to 20130814
+클랜 채팅 메시지 표시
+Clan Chat Messages
+*/
+ MSG_TWWAB_WARRING = 0x93e,
+/*20120716 to 20120716
+http://ro.game.gnjoy.com/
+20120724 to latest
+https://gfb.gameflier.com/Billing/ingame/index_new.asp?
+20130807 to 20130814
+충전 페이지로 이동합니다.
+Go to Page Charged.
+*/
+ MSG_TWWAB_URL = 0x93f,
+#endif
+#if PACKETVER >= 20120724
+/*20120724 to latest
+캐릭터 만들기
+Create char
+20130807 to 20130814
+https://gfb.gameflier.com/Billing/ingame/index_new.asp?
+*/
+ MSG_STR_MAKECHARACTER = 0x940,
+/*20120724 to latest
+캐릭명이 일치하지 않습니다.
+Name does not match
+20130807 to 20130814
+캐릭터 만들기
+Create char
+*/
+ MSG_CHR_DELETE_RESERVED_FAIL_CHARNAME = 0x941,
+/*20120724 to latest
+캐릭터명을 입력하세요
+Enter the name of character
+20130807 to 20130814
+캐릭명이 일치하지 않습니다.
+Name does not match
+*/
+ MSG_CHR_DELETE_RESERVED_INPUTCONFIRMSTR_WND_TITLE = 0x942,
+/*20120724 to 20120822
+/bufftimer : 버프에 쿨타이머를 표시합니다. On Off
+20120830 to latest
+성별 선택 창
+Sex Selection Window
+20130807 to 20130814
+캐릭터명을 입력하세요
+Enter the name of character
+*/
+ MSG_SELECT_SEX = 0x943,
+/*20120724 to 20120822
+버프에 쿨타이머가 표시됩니다.
+20120830 to latest
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+20130807 to 20130814
+성별 선택 창
+Sex Selection Window
+*/
+ MSG_SPRITE_ALTER = 0x944,
+/*20120724 to 20120822
+버프에 쿨타이머가 표시되지 않습니다.
+20120830 to latest
+해당 아이템을 개봉하여 획득되는 아이템들은 캐릭터 귀속 아이템 (창고이동 불가능) 입니다. 본 캐릭터에 사용하시는 것이 맞으신지 확인해주시기 바랍니다. 상자를 개봉하시겠습니까?
+Items obtained by opening the item is character bounded (can not move to storage). Do you want to open the box?
+20130807 to 20130814
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+*/
+ MSG_CONFIRM_TO_OPEN_EVENT_ITEM = 0x945,
+#endif
+#if PACKETVER >= 20120808
+/*20120808 to 20120822
+성별 선택 창
+Sex Selection Window
+20120925 to latest
+게임 설정
+Game Settings
+20130807 to 20130814
+해당 아이템을 개봉하여 획득되는 아이템들은 캐릭터 귀속 아이템 (창고이동 불가능) 입니다. 본 캐릭터에 사용하시는 것이 맞으신지 확인해주시기 바랍니다. 상자를 개봉하시겠습니까?
+Items obtained by opening the item is character bounded (can not move to storage). Do you want to open the box?
+*/
+ MSG_GAME_SETTING = 0x946,
+#endif
+#if PACKETVER >= 20120822
+/*20120822 to 20120822
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+20120925 to latest
+게임 시스템
+Game System
+20130807 to 20130814
+게임 설정
+Game Settings
+*/
+ MSG_SYSTEM_SETTING = 0x947,
+#endif
+#if PACKETVER >= 20120925
+/*20120925 to latest
+게임 커맨드
+Game Commands
+20130807 to 20130814
+게임 시스템
+Game System
+*/
+ MSG_COMMAND_SETTING = 0x948,
+/*20120925 to 20120926
+게임 커맨드 리스트
+20121010 to latest
+게임 커맨드 ON/OFF
+Game Command ON/OFF
+20130807 to 20130814
+게임 커맨드
+Game Commands
+*/
+ MSG_COMMAND_LIST = 0x949,
+/*20120925 to latest
+매크로
+Macro
+20130807 to 20130814
+게임 커맨드 ON/OFF
+Game Command ON/OFF
+*/
+ MSG_MACRO_LIST = 0x94a,
+/*20120925 to latest
+이지역은 아이템교환이 금지 되어 있습니다
+Trading is prohibited in this Map
+20130807 to 20130814
+매크로
+Macro
+*/
+ MSG_EXCHANGEITEM_DENY_MAP = 0x94b,
+/*20120925 to latest
+이지역은 카트이용이 금지 되어 있습니다
+Vending is prohibited in this Map
+20130807 to 20130814
+이지역은 아이템교환이 금지 되어 있습니다
+Trading is prohibited in this Map
+*/
+ MSG_CART_USE_DENY_MAP = 0x94c,
+#endif
+#if PACKETVER >= 20121010
+/*20121010 to latest
+이지역은 태양과달과별의 기적 효과가 발생하지 않습니다.
+In this Map,Effect of Mirace of Sun and Moon is nullified.
+20130807 to 20130814
+이지역은 카트이용이 금지 되어 있습니다
+Vending is prohibited in this Map
+*/
+ MSG_BLOCK_SUNMOONSTAR_MIRACLE = 0x94d,
+/*20121010 to latest
+랭킹 보드
+Ranking Board
+20130807 to 20130814
+이지역은 태양과달과별의 기적 효과가 발생하지 않습니다.
+In this Map,Effect of Mirace of Sun and Moon is nullified.
+*/
+ MSG_RANKING_BOARD = 0x94e,
+/*20121010 to latest
+순위
+Rank
+20130807 to 20130814
+랭킹 보드
+Ranking Board
+*/
+ MSG_RANKING_NUMBER = 0x94f,
+/*20121010 to latest
+이름
+Name
+20130807 to 20130814
+순위
+Rank
+*/
+ MSG_RANKING_NAME = 0x950,
+/*20121010 to latest
+포인트
+Points
+20130807 to 20130814
+이름
+Name
+*/
+ MSG_RANKING_POINT = 0x951,
+/*20121010 to latest
+BlackSmith
+20130807 to 20130814
+포인트
+Points
+*/
+ MSG_RANKING_BLACKSMITH = 0x952,
+/*20121010 to latest
+Alchemist
+20130807 to 20130814
+BlackSmith
+*/
+ MSG_RANKING_ALCHEMIST = 0x953,
+/*20121010 to latest
+Taekwon
+20130807 to 20130814
+Alchemist
+*/
+ MSG_RANKING_TAEKWON = 0x954,
+/*20121010 to latest
+Killer
+20130807 to 20130814
+Taekwon
+*/
+ MSG_RANKING_KILLER = 0x955,
+/*20121010 to 20121011
+Munak
+20121017 to 20121107
+1 vs 1
+20121114 to latest
+7 vs 7
+20130807 to 20130814
+Killer
+*/
+ MSG_RANKING_BATTLE_7VS7_ALL = 0x956,
+/*20121010 to 20121011
+DeathKnight
+20121017 to 20130814
+7 vs 7
+20121114 to latest
+RuneKnight
+*/
+ MSG_RANKING_RUNE_KNIGHT = 0x957,
+/*20121010 to 20121011
+Collector
+20121017 to 20121107
+Select Ranking Type
+20121114 to latest
+Warlock
+20130807 to 20130814
+RuneKnight
+*/
+ MSG_RANKING_WARLOCK = 0x958,
+/*20121010 to 20121011
+Select Ranking Type
+20121017 to 20121107
+Ranking Type
+20121114 to latest
+Ranger
+20130807 to 20130814
+Warlock
+*/
+ MSG_RANKING_RANGER = 0x959,
+/*20121010 to 20121011
+Ranking Type
+20121114 to latest
+Mechanic
+20130807 to 20130814
+Ranger
+*/
+ MSG_RANKING_MECHANIC = 0x95a,
+#endif
+#if PACKETVER >= 20121114
+/*20121114 to latest
+GuillotineCross
+20130807 to 20130814
+Mechanic
+*/
+ MSG_RANKING_GUILLOTINE_CROSS = 0x95b,
+/*20121114 to latest
+Archbishop
+20130807 to 20130814
+GuillotineCross
+*/
+ MSG_RANKING_ARCHBISHOP = 0x95c,
+/*20121114 to latest
+RoyalGuard
+20130807 to 20130814
+Archbishop
+*/
+ MSG_RANKING_ROYAL_GUARD = 0x95d,
+/*20121114 to latest
+Sorcerer
+20130807 to 20130814
+RoyalGuard
+*/
+ MSG_RANKING_SORCERER = 0x95e,
+/*20121114 to latest
+Minstrel
+20130807 to 20130814
+Sorcerer
+*/
+ MSG_RANKING_MINSTREL = 0x95f,
+/*20121114 to latest
+Wanderer
+20130807 to 20130814
+Minstrel
+*/
+ MSG_RANKING_WANDERER = 0x960,
+/*20121114 to latest
+Genetic
+20130807 to 20130814
+Wanderer
+*/
+ MSG_RANKING_GENETIC = 0x961,
+/*20121114 to latest
+ShadowChaser
+20130807 to 20130814
+Genetic
+*/
+ MSG_RANKING_SHADOW_CHASER = 0x962,
+/*20121114 to latest
+Sura
+20130807 to 20130814
+ShadowChaser
+*/
+ MSG_RANKING_SURA = 0x963,
+/*20121114 to latest
+Kagerou
+20130807 to 20130814
+Sura
+*/
+ MSG_RANKING_KAGEROU = 0x964,
+/*20121114 to latest
+Oboro
+20130807 to 20130814
+Kagerou
+*/
+ MSG_RANKING_OBORO = 0x965,
+/*20121114 to latest
+Select Ranking Type
+20130807 to 20130814
+Oboro
+*/
+ MSG_RANKING_SELECT = 0x966,
+/*20121114 to latest
+Ranking Type
+20130807 to 20130814
+Select Ranking Type
+*/
+ MSG_RANKING_TYPE = 0x967,
+/*20121114 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dSeconds
+20130807 to 20130814
+Ranking Type
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_SEC = 0x968,
+/*20121114 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d분 %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dMinutes %d Seconds
+20130807 to 20130814
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dSeconds
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_MIN = 0x969,
+/*20121114 to latest
+CBT 초청 유저가 아닙니다
+CBT is not an invited user
+20130807 to 20130814
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d분 %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dMinutes %d Seconds
+*/
+ MSG_CBT_ACTIVE_USER_CHECK = 0x96a,
+#endif
+#if PACKETVER >= 20121128
+/*20121128 to latest
+ -------------- Navigation 명령어 --------------
+------------------- Instruction --------------------
+20130807 to 20130814
+CBT 초청 유저가 아닙니다
+CBT is not an invited user
+*/
+ MSG_NAVIGATION_HELP_1 = 0x96b,
+/*20121128 to latest
+/navigation /navi : /navi yuno 100/100 ->> 맵이름, 위치(100/100)
+1) /Navigation or /navi ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+20130807 to 20130814
+ -------------- Navigation 명령어 --------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP_2 = 0x96c,
+/*20121128 to latest
+/navigation2 /navi2 : /navi2 yuno 100/100 1/1/1 ->> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+2) /Navigation2 or /navi2 ex) /navi2 prontera 100 111 -> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+20130807 to 20130814
+/navigation /navi : /navi yuno 100/100 ->> 맵이름, 위치(100/100)
+1) /Navigation or /navi ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP_3 = 0x96d,
+/*20121128 to latest
+ -------------- Navigation 검색창 명령어 -------
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+20130807 to 20130814
+/navigation2 /navi2 : /navi2 yuno 100/100 1/1/1 ->> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+2) /Navigation2 or /navi2 ex) /navi2 prontera 100 111 -> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP_4 = 0x96e,
+/*20121128 to latest
+$$all : 모든 항목 출력 (Type 구분자에서 출력 종류를 나눌수 있다.)
+3) $$all Output all the items (Can take a while...)
+20130807 to 20130814
+ -------------- Navigation 검색창 명령어 -------
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP_5 = 0x96f,
+/*20121128 to latest
+$$lv30 : 해당 레벨의 몬스터 출력 (숫자는 변경 가능)
+4) $$lv30 monsters are placed in the output
+20130807 to 20130814
+$$all : 모든 항목 출력 (Type 구분자에서 출력 종류를 나눌수 있다.)
+3) $$all Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP_6 = 0x970,
+/*20121128 to latest
+$$lv20~30 : 해당 레벨 범위의 몬스터 출력 (숫자는 변경 가능)
+5) $$lv20~30 monsters in that level range are placed in the output
+20130807 to 20130814
+$$lv30 : 해당 레벨의 몬스터 출력 (숫자는 변경 가능)
+4) $$lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP_7 = 0x971,
+/*20121128 to latest
+1 vs 1
+20130807 to 20130814
+$$lv20~30 : 해당 레벨 범위의 몬스터 출력 (숫자는 변경 가능)
+5) $$lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_RANKING_BATTLE_1VS1_ALL = 0x972,
+#endif
+#if PACKETVER >= 20121205
+/*20121205 to latest
+특수 장비
+Special Gear
+20130807 to 20130814
+1 vs 1
+*/
+ MSG_SHADOW_EQUIPMENT = 0x973,
+#endif
+#if PACKETVER >= 20130109
+/*20130109 to latest
+%d 번째 캐릭터의 직업 정보가 이상합니다. 고객센터로 문의 부탁 드립니다. ErrorCode(%d)
+%d First character of the profession is more than information. Please contact the Customer Care Center. ErrorCode(%d)
+20130807 to 20130814
+특수 장비
+Special Gear
+*/
+ MSG_CHARACTERERROR_JOB = 0x974,
+#endif
+#if PACKETVER >= 20130115
+/*20130115 to latest
+(%s) %d / %d
+20130807 to 20130814
+%d 번째 캐릭터의 직업 정보가 이상합니다. 고객센터로 문의 부탁 드립니다. ErrorCode(%d)
+%d First character of the profession is more than information. Please contact the Customer Care Center. ErrorCode(%d)
+*/
+ MSG_NAVIGATION_ALL_S = 0x975,
+/*20130115 to latest
+%s-%s(%d/%d)
+20130807 to 20130814
+(%s) %d / %d
+*/
+ MSG_NAVIGATION_ALL_SD = 0x976,
+#endif
+#if PACKETVER >= 20130121
+/*20130121 to latest
+접속자 수 초과로 서버에 더이상 접속할 수 없습니다.
+Server Exceeded the maximum number of users,Cannot Connect anymore users.
+20130807 to 20130814
+%s-%s(%d/%d)
+*/
+ MSG_REFUSE_OVER_USERLIMIT = 0x977,
+/*20130121 to latest
+서버접속 실패 (%d)
+Server Connection Failed (%d)
+20130807 to 20130814
+접속자 수 초과로 서버에 더이상 접속할 수 없습니다.
+Server Exceeded the maximum number of users,Cannot Connect anymore users.
+*/
+ MSG_REFUSE_ERRORCODE = 0x978,
+/*20130121 to latest
+로그인 허용시간 초과
+Login Timeout Permitted
+20130807 to 20130814
+서버접속 실패 (%d)
+Server Connection Failed (%d)
+*/
+ MSG_REFUSE_DISCONNECT_KEEP_TIME = 0x979,
+/*20130121 to latest
+로그인 중 인증서버로부터 인증이 실패하였습니다.
+Login Authentication Failed from Authentication Server.
+20130807 to 20130814
+로그인 허용시간 초과
+Login Timeout Permitted
+*/
+ MSG_REFUSE_WEB_AUTH_FAILED = 0x97a,
+#endif
+#if PACKETVER >= 20130206
+/*20130206 to latest
+길드이름에 공백문자를 사용할 수 없습니다.
+Guild Cannot use Space in the name.
+20130807 to 20130814
+로그인 중 인증서버로부터 인증이 실패하였습니다.
+Login Authentication Failed from Authentication Server.
+*/
+ MSG_GUILDNAME_CHECK = 0x97b,
+#endif
+#if PACKETVER >= 20130215
+/*20130215 to latest
+고객님 안녕하세요!
+Hey,Hello There
+20130807 to 20130814
+길드이름에 공백문자를 사용할 수 없습니다.
+Guild Cannot use Space in the name.
+*/
+ MSG_BILLING_CHN_1 = 0x97c,
+/*20130215 to latest
+고객님의 이용 시간은 %d년 %d 월 %d일 %d:%d 에 종료됩니다.
+Available Time will End on %d month %d hour %d:%d
+20130807 to 20130814
+고객님 안녕하세요!
+Hey,Hello There
+*/
+ MSG_BILLING_CHN_2 = 0x97d,
+/*20130215 to latest
+고객님의 이용 시간은 아직 많이 남았으니 안심하고 플레이하세요!
+You've lot of time,Play in Peace.
+20130807 to 20130814
+고객님의 이용 시간은 %d년 %d 월 %d일 %d:%d 에 종료됩니다.
+Available Time will End on %d month %d hour %d:%d
+*/
+ MSG_BILLING_CHN_3 = 0x97e,
+/*20130215 to latest
+고객님의 이용 시간은 이번 주 내로 종료 됩니다. 종료 전에 충전을 하시기 바랍니다.
+Your hours will be terminated within this week. Please Charge before termination.
+20130807 to 20130814
+고객님의 이용 시간은 아직 많이 남았으니 안심하고 플레이하세요!
+You've lot of time,Play in Peace.
+*/
+ MSG_BILLING_CHN_4 = 0x97f,
+/*20130215 to latest
+고객님의 이용 시간은 24시간 내에 종료됩니다. 빨리 충전하시기 바랍니다.
+Your hours will be terminated within 24 hours.Please Charge Quickly.
+20130807 to 20130814
+고객님의 이용 시간은 이번 주 내로 종료 됩니다. 종료 전에 충전을 하시기 바랍니다.
+Your hours will be terminated within this week. Please Charge before termination.
+*/
+ MSG_BILLING_CHN_5 = 0x980,
+/*20130215 to latest
+현재 고객님의 이용 시간은 %d시간 남았습니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d hours.Charge the game for uninterrupted play.
+20130807 to 20130814
+고객님의 이용 시간은 24시간 내에 종료됩니다. 빨리 충전하시기 바랍니다.
+Your hours will be terminated within 24 hours.Please Charge Quickly.
+*/
+ MSG_BILLING_CHN_6 = 0x981,
+/*20130215 to latest
+현재 고객님의 이용 시간은 %d분 남았습니다. 이용시간이 끝난 후 강제적으로 종료됩니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d minutes.Charge the game for uninterrupted play.
+20130807 to 20130814
+현재 고객님의 이용 시간은 %d시간 남았습니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d hours.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_7 = 0x982,
+/*20130215 to latest
+고객님의 이용 시간은 %d시간 %d분 남았습니다.
+Time Left: %d hours %d minutes
+20130807 to 20130814
+현재 고객님의 이용 시간은 %d분 남았습니다. 이용시간이 끝난 후 강제적으로 종료됩니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d minutes.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_8 = 0x983,
+/*20130215 to latest
+%d%% ( 기본 100%% + PC방 %d%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%% ( Basic 100%% + PCRoom %d%% + Premium %d%% + %sServer %d%% )
+20130807 to 20130814
+고객님의 이용 시간은 %d시간 %d분 남았습니다.
+Time Left: %d hours %d minutes
+*/
+ MSG_BASIC_EXP_MSG_THAI = 0x984,
+/*20130215 to latest
+고객님의 이용 시간은 %d시간 %d분 후에 종료됩니다.
+After %d hours %d minutes, your game will be terminated.
+20130807 to 20130814
+%d%% ( 기본 100%% + PC방 %d%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%% ( Basic 100%% + PCRoom %d%% + Premium %d%% + %sServer %d%% )
+*/
+ MSG_CHN_BILLING_EXPIRE_TIME = 0x985,
+#endif
+#if PACKETVER >= 20130220
+/*20130220 to latest
+유저님의 계정은 영구 접속금지 되였습니다
+This Account is permanently Banned.
+20130807 to 20130814
+고객님의 이용 시간은 %d시간 %d분 후에 종료됩니다.
+After %d hours %d minutes, your game will be terminated.
+*/
+ MSG_CHN_BLOCK_FOREVER = 0x986,
+/*20130220 to latest
+유저님의 계정은 접속금지 되였습니다
+ 해지 시간 : %04d-%02d-%02d %02d:%02d
+This Account is banned.
+Termination Time:%04d-%02d-%02d %02d:%02d
+20130807 to 20130814
+유저님의 계정은 영구 접속금지 되였습니다
+This Account is permanently Banned.
+*/
+ MSG_CHN_BLOCK = 0x987,
+#endif
+#if PACKETVER >= 20130227
+/*20130227 to latest
+몬스터(Tab)
+Monster(Tab)
+20130807 to 20130814
+유저님의 계정은 접속금지 되였습니다
+ 해지 시간 : %04d-%02d-%02d %02d:%02d
+This Account is banned.
+Termination Time:%04d-%02d-%02d %02d:%02d
+*/
+ MSG_WORLDMAP_MSG1 = 0x988,
+/*20130227 to latest
+맵(Alt)
+Map(Alt)
+20130807 to 20130814
+몬스터(Tab)
+Monster(Tab)
+*/
+ MSG_WORLDMAP_MSG2 = 0x989,
+/*20130227 to latest
+안내 정보
+Product Information
+20130807 to 20130814
+맵(Alt)
+Map(Alt)
+*/
+ MSG_WORLDMAP_MSG3 = 0x98a,
+/*20130227 to latest
+검색 정보
+Find Information
+20130807 to 20130814
+안내 정보
+Product Information
+*/
+ MSG_WORLDMAP_MSG4 = 0x98b,
+/*20130227 to latest
+비공정
+AirShip
+20130807 to 20130814
+검색 정보
+Find Information
+*/
+ MSG_WORLDMAP_MSG5 = 0x98c,
+/*20130227 to latest
+카프라
+Kafra
+20130807 to 20130814
+비공정
+AirShip
+*/
+ MSG_WORLDMAP_MSG6 = 0x98d,
+/*20130227 to latest
+(도착)
+(Arrival)
+20130807 to 20130814
+카프라
+Kafra
+*/
+ MSG_WORLDMAP_MSG7 = 0x98e,
+#endif
+#if PACKETVER >= 20130313
+/*20130313 to latest
+Mob)%s:%s(%s)
+20130807 to 20130814
+(도착)
+(Arrival)
+*/
+ MSG_NAVIGATION_MOB_S_S_S = 0x98f,
+/*20130313 to latest
+분포도:%s
+Distribution:%s
+20130807 to 20130814
+Mob)%s:%s(%s)
+*/
+ MSG_NAVIGATION_NUM = 0x990,
+/*20130313 to latest
+매우많음
+Very Plenty
+20130807 to 20130814
+분포도:%s
+Distribution:%s
+*/
+ MSG_NAVIGATION_NUM1 = 0x991,
+/*20130313 to latest
+많음
+Plenty
+20130807 to 20130814
+매우많음
+Very Plenty
+*/
+ MSG_NAVIGATION_NUM2 = 0x992,
+/*20130313 to latest
+보통
+Normal
+20130807 to 20130814
+많음
+Plenty
+*/
+ MSG_NAVIGATION_NUM3 = 0x993,
+/*20130313 to latest
+적음
+Low
+20130807 to 20130814
+보통
+Normal
+*/
+ MSG_NAVIGATION_NUM4 = 0x994,
+/*20130313 to latest
+매우적음
+Very Low
+20130807 to 20130814
+적음
+Low
+*/
+ MSG_NAVIGATION_NUM5 = 0x995,
+#endif
+#if PACKETVER >= 20130320
+/*20130320 to latest
+은행을 이용할 수 없습니다. 잠시 후 다시 시도하세요.
+The bank is not available. Please try again in a few minutes.
+20130807 to 20130814
+매우적음
+Very Low
+*/
+ MSG_BANK_SYSTEM_ERROR = 0x996,
+/*20130320 to latest
+은행 잔고가 부족합니다.
+Bank balance is low.
+20130807 to 20130814
+은행을 이용할 수 없습니다. 잠시 후 다시 시도하세요.
+The bank is not available. Please try again in a few minutes.
+*/
+ MSG_BANK_WITHDRAW_NO_MONEY = 0x997,
+#endif
+#if PACKETVER >= 20130327
+/*20130327 to latest
+보유한 Zeny 가 부족해서 입금할 수 없습니다.
+You don't have enough zeny
+20130807 to 20130814
+은행 잔고가 부족합니다.
+Bank balance is low.
+*/
+ MSG_BANK_DEPOSIT_NO_MONEY = 0x998,
+/*20130327 to latest
+1 Zeny 이상 입금 가능합니다.
+Minimum Deposit Amount: 1 zeny
+20130807 to 20130814
+보유한 Zeny 가 부족해서 입금할 수 없습니다.
+You don't have enough zeny
+*/
+ MSG_BANK_DEPOSIT_ZERO = 0x999,
+/*20130327 to latest
+1 Zeny 이상 출금 가능합니다.
+Minimum Withdrawal Amount: 1 zeny
+20130807 to 20130814
+1 Zeny 이상 입금 가능합니다.
+Minimum Deposit Amount: 1 zeny
+*/
+ MSG_BANK_WITHDRAW_ZERO = 0x99a,
+/*20130327 to 20130529
+보유 Zeny 는 21 억을 넘을 수 없습니다.
+20130605 to latest
+보유 Zeny 는 2,147,483,647 Zeny를 넘을 수 없습니다.
+You cannot hold more than 2,147,483,647 Zeny
+20130807 to 20130814
+1 Zeny 이상 출금 가능합니다.
+Minimum Withdrawal Amount: 1 zeny
+*/
+ MSG_BANK_OVER_INT_MAX = 0x99b,
+/*20130327 to latest
+your account is lock by mobil otp
+your account is lock by mobile otp
+20130807 to 20130814
+보유 Zeny 는 2,147,483,647 Zeny를 넘을 수 없습니다.
+You cannot hold more than 2,147,483,647 Zeny
+*/
+ MSG_REFUSE_MOTP_LOCK = 0x99c,
+/*20130327 to latest
+MOTP auth fail
+20130807 to 20130814
+your account is lock by mobil otp
+your account is lock by mobile otp
+*/
+ MSG_REFUSE_MOTP_AUTH_FAIL = 0x99d,
+/*20130327 to latest
+%d분간 몬스터에게 얻을 수 있는 Job경험치가 %d%% 증가합니다.
+For %d minutes,Job Experience obtained from monster is increased by %d%%
+20130807 to 20130814
+MOTP auth fail
+*/
+ MSG_JOBPLUSEXP_VALUE = 0x99e,
+#endif
+#if PACKETVER >= 20130410
+/*20130410 to 20130410
+소지 Zeny : %d Zeny
+20130417 to latest
+소지 Zeny : %s Zeny
+Current Zeny: %s Zeny
+20130807 to 20130814
+%d분간 몬스터에게 얻을 수 있는 Job경험치가 %d%% 증가합니다.
+For %d minutes,Job Experience obtained from monster is increased by %d%%
+*/
+ MSG_BANK_MY_ZENY = 0x99f,
+/*20130410 to latest
+Zeny
+20130807 to 20130814
+소지 Zeny : %s Zeny
+Current Zeny: %s Zeny
+*/
+ MSG_BANK_ZENY = 0x9a0,
+/*20130410 to 20130515
+* 최대 21억 Zeny까지만 보관이 가능합니다.
+20130522 to 20130529
+최대 2,147,483,647억 Zeny까지만 보관이 가능합니다.
+20130605 to 20130605
+최대 2,147,483,647 Zeny까지만 보관이 가능합니다.
+20130612 to latest
+최대 2,147,483,647 Zeny 까지만 보관이 가능합니다.
+The Maximum amount is 2,147,483,647 Zeny
+20130807 to 20130814
+Zeny
+*/
+ MSG_BANK_WARNING = 0x9a1,
+#endif
+#if PACKETVER >= 20130515
+/*20130515 to latest
+총알이 부족합니다.
+Insufficient bullet
+20130807 to 20130814
+최대 2,147,483,647 Zeny 까지만 보관이 가능합니다.
+The Maximum amount is 2,147,483,647 Zeny
+*/
+ MSG_NEED_MORE_BULLET = 0x9a2,
+/*20130515 to latest
+10억제니 이상 입력하셔도 가격은 10억 제니로 판매됩니다.
+You entered more than 1 Billion Zeny, the price will be set to 1 Billion Zeny.
+20130807 to 20130814
+총알이 부족합니다.
+Insufficient bullet
+*/
+ MSG_OVERPRICE_MAX = 0x9a3,
+#endif
+#if PACKETVER >= 20130605
+/*20130605 to latest
+AuthTicket is Not Vaild
+AuthTicket is Not Valid
+20130807 to 20130814
+10억제니 이상 입력하셔도 가격은 10억 제니로 판매됩니다.
+You entered more than 1 Billion Zeny, the price will be set to 1 Billion Zeny.
+*/
+ MSG_NOT_VALID_AUTH_TICKET = 0x9a4,
+/*20130605 to 20130605
+ErrorCode : %d, ErrorValue : %d
+20130612 to latest
+ErrorCategory : %d, ErrorCode : %d (%d,%d,%d,%d)
+ErrorCode : %d, ErrorValue : %d
+20130807 to 20130814
+AuthTicket is Not Vaild
+AuthTicket is Not Valid
+*/
+ MSG_STEAMAGENCY_ERROR = 0x9a5,
+#endif
+#if PACKETVER >= 20130618
+/*20130618 to 20130618
+%d%% ( Primary 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+20130626 to latest
+%d%% ( Basic 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+%d%% ( Basic 100%% + Premium %d%% + Internet cafe %d%% + %s Server %d%% )
+20130807 to 20130814
+ErrorCategory : %d, ErrorCode : %d (%d,%d,%d,%d)
+ErrorCode : %d, ErrorValue : %d
+*/
+ MSG_BASIC_EXP_MSG_INDONESIA = 0x9a6,
+/*20130618 to 20130925
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d분간 %d배로 증가합니다.
+20130807 to 20130814
+%d%% ( Basic 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+%d%% ( Basic 100%% + Premium %d%% + Internet cafe %d%% + %s Server %d%% )
+20130925 to latest
+ %d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE = 0x9a7,
+/*20130618 to 20130925
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d시 %.2d분간 %d배로 증가합니다.
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d분간 %d배로 증가합니다.
+20130925 to latest
+ %d시 %.2d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dhour %.2dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE_1 = 0x9a8,
+#endif
+#if PACKETVER >= 20130626
+/*20130626 to latest
+%s 의 가격이
+The price of^0000FF %s^000000
+20130807 to 20130814
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d시 %.2d분간 %d배로 증가합니다.
+*/
+ MSG_WARNING_PRICE1 = 0x9a9,
+/*20130626 to latest
+100000000
+20130807 to 20130814
+%s 의 가격이
+The price of^0000FF %s^000000
+*/
+ MSG_WARNING_PRICE2 = 0x9aa,
+/*20130626 to latest
+ ^ff0000%d^0000ff억
+ is over ^FF0000%d^0000FF Billion^000000 Zeny and
+20130807 to 20130814
+100000000
+*/
+ MSG_WARNING_PRICE3 = 0x9ab,
+/*20130626 to latest
+10000000
+20130807 to 20130814
+ ^ff0000%d^0000ff억
+ is over ^FF0000%d^0000FF Billion^000000 Zeny and
+*/
+ MSG_WARNING_PRICE4 = 0x9ac,
+/*20130626 to latest
+ ^ff0000%d^0000ff천만
+ more than^FF0000 %d0^0000FF Million^000000 Zeny
+20130807 to 20130814
+10000000
+*/
+ MSG_WARNING_PRICE5 = 0x9ad,
+/*20130626 to latest
+^0000ffZeny 이상^000000입니다.
+입력금액이 맞습니까?
+. Is this correct?
+20130807 to 20130814
+ ^ff0000%d^0000ff천만
+ more than^FF0000 %d0^0000FF Million^000000 Zeny
+*/
+ MSG_WARNING_PRICE6 = 0x9ae,
+/*20130626 to latest
+천만Zeny이상 안전확인
+Safety check for more than 10m Zeny
+20130807 to 20130814
+^0000ffZeny 이상^000000입니다.
+입력금액이 맞습니까?
+. Is this correct?
+*/
+ MSG_WARNING_PRICE7 = 0x9af,
+/*20130626 to latest
+https://www.warpportal.com/account/login.aspx?ReturnUrl=%2faccount%2fpayment.aspx
+20130807 to 20130814
+천만Zeny이상 안전확인
+Safety check for more than 10m Zeny
+*/
+ MSG_AMERICA_CASHSHOP_URL = 0x9b0,
+/*20130626 to 20131023
+https://kepler.warpportal.com/steam/purchase/?step=1&steamid=76561198071003044&game=rose&accountname=khanhtest111&lang=en
+20130807 to 20130814
+https://www.warpportal.com/account/login.aspx?ReturnUrl=%2faccount%2fpayment.aspx
+20131030 to latest
+https://kepler.warpportal.com/ro1/purchase/?step=1&steamid=%lld&accountname=
+https://kepler.warpportal.com/ror/purchase/?step=1&steamid=%lld&accountname=
+*/
+ MSG_AMERICA_CASHSHOP_URL_STEAM = 0x9b1,
+/*20130626 to latest
+지상의 끝, 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 생겨난 거대한 균열, 그리고 근원을 알 수 없는 미궁숲.
+A giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim, and you do not know the source of the labyrinth forest.
+20130807 to 20130814
+https://kepler.warpportal.com/steam/purchase/?step=1&steamid=76561198071003044&game=rose&accountname=khanhtest111&lang=en
+*/
+ MSG_QUEST_INFO_01 = 0x9b2,
+/*20130626 to latest
+이것은 여행의 끝을 알리는 표식인가, 새로운 세계를 여는 지표인가! 수호자는 노랫말 같은 유혹에 점차 넋을 잃어가고 있었다.
+This is a marker indicating the end of the trip, a new world is opening indicators! Guardian, such as the lyrics to the temptation was gradually losing the soul.
+20130807 to 20130814
+지상의 끝, 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 생겨난 거대한 균열, 그리고 근원을 알 수 없는 미궁숲.
+A giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim, and you do not know the source of the labyrinth forest.
+*/
+ MSG_QUEST_INFO_02 = 0x9b3,
+/*20130626 to latest
+수천 년의 세월이 흐르는 동안, 그 스스로가 홀로 안간힘을 쓰며 지켜낸 것이 무엇이었는지, 봉인 되어 긴 시간을 갇혀버린 것은 오히려 자신이 아니었는지 혼란을 느끼고 있었다.
+For thousands of years, a mysterious melody has mesmerized the guardian. After a millennia of slumber, the guardian became confused about what he had been protecting all these years, and began to suspect that he might be the one who has been sealed and hidden away.
+20130807 to 20130814
+이것은 여행의 끝을 알리는 표식인가, 새로운 세계를 여는 지표인가! 수호자는 노랫말 같은 유혹에 점차 넋을 잃어가고 있었다.
+This is a marker indicating the end of the trip, a new world is opening indicators! Guardian, such as the lyrics to the temptation was gradually losing the soul.
+*/
+ MSG_QUEST_INFO_03 = 0x9b4,
+/*20130626 to latest
+유혹의 노랫말이 최고조에 이르렀을 때, 지상의 끝 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 거대한 균열이 생겨났고, 그로 인해 두 세계간의 왕래가 끊기면서 사람들은 큰 불편을 겪게 되었다.
+When the melody reached its peak, a giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim. As a result, the two worlds were cut off from each other, causing a big problem for the people.
+20130807 to 20130814
+수천 년의 세월이 흐르는 동안, 그 스스로가 홀로 안간힘을 쓰며 지켜낸 것이 무엇이었는지, 봉인 되어 긴 시간을 갇혀버린 것은 오히려 자신이 아니었는지 혼란을 느끼고 있었다.
+For thousands of years, a mysterious melody has mesmerized the guardian. After a millennia of slumber, the guardian became confused about what he had been protecting all these years, and began to suspect that he might be the one who has been sealed and hidden away.
+*/
+ MSG_QUEST_INFO_04 = 0x9b5,
+/*20130626 to latest
+비프로스트의 통로는 이제 미궁숲 뿐. 근원조차 알 수 없는 그곳을 무사히 통과 한 사람은 지금까지 아무도 없었다.
+Now, the only way to get to Bifrost is through the Labyrinth Forest. Nobody knows how the forest came to exist, and nobody has ever come out of it alive...
+20130807 to 20130814
+유혹의 노랫말이 최고조에 이르렀을 때, 지상의 끝 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 거대한 균열이 생겨났고, 그로 인해 두 세계간의 왕래가 끊기면서 사람들은 큰 불편을 겪게 되었다.
+When the melody reached its peak, a giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim. As a result, the two worlds were cut off from each other, causing a big problem for the people.
+*/
+ MSG_QUEST_INFO_05 = 0x9b6,
+/*20130626 to latest
+숱한 모험가들을 집어 삼킨 혼돈의 지옥, 미궁숲은 그 속을 방황하는 이름 모를 여인의 마음처럼 더욱 깊고 혼란스럽게 확장되고 있었다.
+Swallowed countless adventurers to put a hell of confusion, wandering in the forest labyrinth of nowhere, like the heart of a woman was being extend deeper confusion.
+20130807 to 20130814
+비프로스트의 통로는 이제 미궁숲 뿐. 근원조차 알 수 없는 그곳을 무사히 통과 한 사람은 지금까지 아무도 없었다.
+Now, the only way to get to Bifrost is through the Labyrinth Forest. Nobody knows how the forest came to exist, and nobody has ever come out of it alive...
+*/
+ MSG_QUEST_INFO_06 = 0x9b7,
+#endif
+#if PACKETVER >= 20130717
+/*20130717 to latest
+숫자만 입력 가능합니다.
+You can enter only numbers.
+20130807 to 20130814
+숱한 모험가들을 집어 삼킨 혼돈의 지옥, 미궁숲은 그 속을 방황하는 이름 모를 여인의 마음처럼 더욱 깊고 혼란스럽게 확장되고 있었다.
+Swallowed countless adventurers to put a hell of confusion, wandering in the forest labyrinth of nowhere, like the heart of a woman was being extend deeper confusion.
+*/
+ MSG_BANK_CHECK_NUM = 0x9b8,
+#endif
+#if PACKETVER >= 20130724
+/*20130724 to latest
+교환창 또는 상점이 활성화 된 상태에서는 입출금을 하실수 없습니다.
+Exchange or store window is active and can not register the withdrawal.
+20130807 to 20130814
+숫자만 입력 가능합니다.
+You can enter only numbers.
+*/
+ MSG_BANK_PROHIBIT = 0x9b9,
+#endif
+#if PACKETVER >= 20130731
+/*20130731 to latest
+바로가기
+Go to
+20130807 to 20130814
+교환창 또는 상점이 활성화 된 상태에서는 입출금을 하실수 없습니다.
+Exchange or store window is active and can not register the withdrawal.
+*/
+ MSG_QUEST_INFO_00 = 0x9ba,
+/*20130731 to latest
+아이템 비교
+Item Compare
+20130807 to 20130814
+바로가기
+Go to
+*/
+ MSG_ITEM_COMPARISON = 0x9bb,
+#endif
+#if PACKETVER >= 20130807
+/*20130807 to 20130814
+아이템 비교
+Item Compare
+20130821 to latest
+현재 장착하려고 하는 총기가 장착하고 있는 탄환에 맞지 않습니다
+Now you are trying to mount the gun equipped with bullet does not meet
+*/
+ MSG_WRONG_GUN = 0x9bc,
+/*20130807 to 20130814
+현재 장착하려고 하는 총기가 장착하고 있는 탄환에 맞지 않습니다
+Now you are trying to mount the gun equipped with bullet does not meet
+20130821 to latest
+현재 장착하려고 하는 탄환이 장착하고 있는 총기와 맞지 않습니다
+Now you are trying to mount the guns and bullets will not fit mounted
+*/
+ MSG_WRONG_BULLET = 0x9bd,
+/*20130807 to 20130814
+현재 장착하려고 하는 탄환이 장착하고 있는 총기와 맞지 않습니다
+Now you are trying to mount the guns and bullets will not fit mounted
+20130821 to latest
+판매할 아이템을 등록하지 않았습니다. 판매하실 아이템을 등록해 주세요
+Has not registered to sell the item. Please register to sell the item
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADD_GOODS = 0x9be,
+#endif
+#if PACKETVER >= 20130821
+/*20130821 to latest
+ITEM
+*/
+ MSG_ITEM_IN_MAIL_SYSTEM = 0x9bf,
+#endif
+#if PACKETVER >= 20130828
+/*20130828 to 20130911
+길드 창고를 이용할 수 없습니다. 잠시 후 이용해주세요.
+20130917 to latest
+길드 창고를 이용할 수 없습니다.
+Guild storage is not available.
+*/
+ MSG_GUILD_STORAGE_OPEN_ERROR = 0x9c0,
+/*20130828 to latest
+길드에 가입되어 있지 않습니다. 가입 후 이용해주세요.
+Guild is not subscribed to. After signing up, please use
+*/
+ MSG_GUILD_STORAGE_OPEN_NO_JOIN_GUILD = 0x9c1,
+/*20130828 to latest
+다른 길드원이 사용중입니다. 잠시 후 이용해주세요.
+Two other guild members are in use. Please use it after a while.
+*/
+ MSG_GUILD_STORAGE_WARNING_USING_ANOTHER_MEMBER = 0x9c2,
+/*20130828 to latest
+창고권한
+Storage Permission
+*/
+ MSG_GUILD_STORAGE_PERMISSON = 0x9c3,
+/*20130828 to latest
+길드창고
+Guild Storage
+*/
+ MSG_GUILD_STORAGE_TITLE = 0x9c4,
+/*20130828 to 20130828
+길드창고의 사용 권한이 없습니다. 길드 마스터에게 요청하세요.
+20130904 to latest
+길드창고의 사용 권한이 없습니다.
+You do not have permission to use guild storage.
+*/
+ MSG_GUILD_STORAGE_PERMISSON_WARNING_MSG = 0x9c5,
+#endif
+#if PACKETVER >= 20130917
+/*20130917 to latest
+한정판매 등록창
+Limited Sale Registration Window
+*/
+ MSG_BARGAINSALE_TOOLWND_TITLE = 0x9c6,
+/*20130917 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NAME = 0x9c7,
+/*20130917 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NUMBER = 0x9c8,
+/*20130917 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_COUNT = 0x9c9,
+/*20130917 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_STARTTIME = 0x9ca,
+/*20130917 to latest
+판매할 시간
+Time to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_PERIODTIME = 0x9cb,
+/*20130917 to latest
+판매할 갯수를 입력해 주세요
+Please enter number you want to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_COUNT_MSG = 0x9cc,
+/*20130917 to latest
+판매 시작시간을 입력해 주세요
+Enter start time of sale
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_STARTTIME_MSG = 0x9cd,
+/*20130917 to latest
+판매 시작시간의 범위가 맞지 않습니다
+Start time does not match the scope of sales.
+*/
+ MSG_BARGAINSALE_TOOLWND_WRONG_RANGE_MSG = 0x9ce,
+/*20130917 to latest
+판매할 시간을 입력해 주세요
+Please enter the time
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_PERIODTIME_MSG = 0x9cf,
+/*20130917 to latest
+Item DB Name을 입력해 주세요
+Please enter the Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_ITEMDBNAME_MSG = 0x9d0,
+/*20130917 to latest
+Item ID 조회에 실패하였습니다. 확인 후 다시 시도해 주시기 바랍니다
+Item ID lookup failed. Please try again later
+*/
+ MSG_BARGAINSALE_TOOLWND_ITEMID_CHECK_FAILED_MSG = 0x9d1,
+/*20130917 to latest
+>> ItemName : %s / Price : %dc / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName: %s / Price: %dc / Quantity: %d / TimeOfSale: %dMonth:%dDay:%dMinute:%dSecond ~ %dMonth:%dDay:%dMinute:%dSecond
+*/
+ MSG_BARGAINSALE_TOOLWND_RESULT_FORMAT = 0x9d2,
+/*20130917 to latest
+등록에 성공하였습니다
+Registration successful
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_SUCCESS_MSG = 0x9d3,
+/*20130917 to latest
+등록에 실패하였습니다. 다시 시도해 주시기 바랍니다.
+Registration failure. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_FAILED_MSG = 0x9d4,
+/*20130917 to latest
+이미 등록된 아이템이 있습니다. 다시 시도해 주시기 바랍니다.
+Item has already been registered. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_ALREADY_REGISTERED_MSG = 0x9d5,
+/*20130917 to latest
+아이템 삭제에 실패 하였습니다. 다시 시도해 주시기 바랍니다.
+Failed to delete the item. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_FAILED_MSG = 0x9d6,
+/*20130917 to latest
+%s 아이템이 삭제되었습니다.
+%s item has been deleted.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_SUCCESS_MSG = 0x9d7,
+/*20130917 to latest
+특가
+Special
+*/
+ MSG_BARGAINSALE_CASHSHOP_TAB_NAME = 0x9d8,
+/*20130917 to latest
+한정판매 아이템 판매수량 갱신
+Sales limited sale item update
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_BTN_TOOLTIP = 0x9d9,
+/*20130917 to latest
+판매종료
+Discontinued
+*/
+ MSG_BARGAINSALE_CASHSHOP_TIMER = 0x9da,
+/*20130917 to latest
+수량갱신이 필요합니다
+Quantity update is required
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_MSG = 0x9db,
+/*20130917 to latest
+재고가 부족하여 %d 개 만큼만 구입합니다
+The %d is out of stock or to buy as much as
+*/
+ MSG_BARGAINSALE_CASHSHOP_CHECK_COUNT_MSG = 0x9dc,
+/*20130917 to latest
+%s 아이템의 특가판매가 시작되었습니다
+%s Items are on sale
+*/
+ MSG_BARGAINSALE_START_MSG = 0x9dd,
+/*20130917 to latest
+%s 아이템의 매진 또는 판매시간만료로 인해 한정판매가 종료되었습니다
+%s time-out or sale of the items sold has been shut down due to the limited sales
+*/
+ MSG_BARGAINSALE_CLOSE_MSG = 0x9de,
+/*20130917 to latest
+/한정판매
+/limitedsale
+*/
+ MSG_BARGAINSALE_TOOLWND_CALL = 0x9df,
+#endif
+#if PACKETVER >= 20131002
+/*20131002 to latest
+http://www.ragnarokeurope.com/news/home-r70.html
+*/
+ MSG_FRANCE_CASHSHOP_URL = 0x9e0,
+/*20131002 to latest
+http://www.ragnarokeurope.com/index.php?rubrique=70&Steam
+*/
+ MSG_FRANCE_CASHSHOP_URL_STEAM = 0x9e1,
+#endif
+#if PACKETVER >= 20131016
+/*20131016 to latest
+구입에 성공한 품목
+Item purchase successful
+*/
+ MSG_PARA_RESULT_TITLE = 0x9e2,
+/*20131016 to latest
+주문량이 재고량을 초과하였습니다.
+You do not have enough items.
+*/
+ MSG_PARA_WRONG_PURCHASE_COUNT_MSG = 0x9e3,
+/*20131016 to latest
+초대할수 없는 케릭터 이름입니다.
+Name of the character that cannot be invited.
+*/
+ MSG_PARTY_INVITE = 0x9e4,
+/*20131016 to latest
+길드초대할수 없는 케릭터 이름입니다.
+You cannot invite the character to the guild.
+*/
+ MSG_GUILD_INVITE = 0x9e5,
+/*20131016 to latest
+일부 품목은 이미 판매되어 구입에 실패하였습니다.
+Item already Sold,Purchase Failed.
+*/
+ MSG_PARA_PURCHASE_ITEM_FAIL = 0x9e6,
+#endif
+#if PACKETVER >= 20131030
+/*20131030 to latest
+현재 위치에서 워프 장소를 기억 할 수 없습니다.
+The warp spot cannot be memorized in current position.
+*/
+ MSG_NOWARPSKILL2 = 0x9e7,
+/*20131030 to latest
+무게가 초과되어 아이템을 구매할 수 없습니다.
+Cannot purchase item, You exceeded the weight.
+*/
+ MSG_PARA_PURCHASE_ITEM_WEIGHT = 0x9e8,
+/*20131030 to latest
+No.
+*/
+ MSG_GUILD_STORAGE_NUMBER = 0x9e9,
+/*20131030 to latest
+아이템
+Item
+*/
+ MSG_GUILD_STORAGE_ITEM = 0x9ea,
+/*20131030 to latest
+개수
+Number
+*/
+ MSG_GUILD_STORAGE_ITEM_COUNT = 0x9eb,
+/*20131030 to latest
+이름
+Name
+*/
+ MSG_GUILD_STORAGE_USER_NAME = 0x9ec,
+/*20131030 to latest
+시간
+Time
+*/
+ MSG_GUILD_STORAGE_LOG_TIME = 0x9ed,
+/*20131030 to latest
+입/출
+Input/Output
+*/
+ MSG_GUILD_STORAGE_ITEM_IN_OUT = 0x9ee,
+/*20131030 to latest
+로그가 존재하지 않습니다.
+Log does not exist.
+*/
+ MSG_GUILD_STORAGE_LOG_FINISH = 0x9ef,
+/*20131030 to latest
+전 체
+Entire
+*/
+ MSG_GUILD_STORAGE_LOG_ALL = 0x9f0,
+/*20131030 to latest
+넣 기
+Insert Symbol
+*/
+ MSG_GUILD_STORAGE_LOG_IN = 0x9f1,
+/*20131030 to latest
+빼 기
+Remaining Time
+*/
+ MSG_GUILD_STORAGE_LOG_OUT = 0x9f2,
+#endif
+#if PACKETVER >= 20131106
+/*20131106 to latest
+길드 창고 내역
+Guild Storage Logs
+*/
+ MSG_GUILD_STORAGE_LOG_WND_NAME = 0x9f3,
+/*20131106 to latest
+내역은 최근 100개만 표시됩니다.
+100 entries are displayed.
+*/
+ MSG_GUILD_STORAGE_LOG_CAUTION = 0x9f4,
+#endif
+#if PACKETVER >= 20131120
+/*20131120 to 20131120
+%s : +%d
+20131127 to latest
+길드창고의 사용 시간 2분이 경과되어 자동으로 종료됩니다.
+Guild Storage is open only for 2 minutes, and will close automatically.
+*/
+ MSG_GUILD_STORAGE_CLOSE_TIMEOUT = 0x9f5,
+#endif
+#if PACKETVER >= 20131204
+/*20131204 to latest
+Incorrect GameSamba ID. Please Try Again.
+*/
+ MSG_INCORRECT_GAMESAMBEID = 0x9f6,
+/*20131204 to latest
+%s [%d옵션] : %d 개
+%s [%d Option]: %d Quantity
+*/
+ MSG_EA5 = 0x9f7,
+#endif
+#if PACKETVER >= 20131211
+/*20131211 to latest
+코인이 필요합니다.
+Requires a Coin.
+*/
+ MSG_USESKILL_FAIL_COINTS = 0x9f8,
+/*20131211 to latest
+코인이 %d 개가 필요합니다.
+%d Coins are required.
+*/
+ MSG_USESKILL_FAIL_COINTS_NUM = 0x9f9,
+/*20131211 to latest
+개틀링건 계열의 총기류를 장착한 상태여야 합니다.
+Gatling Gun should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GATLING = 0x9fa,
+/*20131211 to latest
+샷건 계열의 총기류를 장착한 상태여야 합니다.
+Shotguns should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_SHOTGUN = 0x9fb,
+/*20131211 to latest
+라이플 계열의 총기류를 장착한 상태여야 합니다.
+Rifle should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_RIFLE = 0x9fc,
+/*20131211 to latest
+리볼버 계열의 총기류를 장착한 상태여야 합니다.
+Pair of Revolver should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_HANDGUN = 0x9fd,
+/*20131211 to latest
+성속성 블릿을 장착해야 합니다
+[Silver Bullet] weapon class must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_PROPERTY_SAINT_BULLET = 0x9fe,
+/*20131211 to latest
+아이템 판매 내역
+Item Sell History
+*/
+ MSG_MERCHANT_SOLD_ITEM_LOG = 0x9ff,
+/*20131211 to latest
+아이템 구매 내역
+Item Purchase History
+*/
+ MSG_MERCHANT_ITEM_BUY_LOG = 0xa00,
+#endif
+#if PACKETVER >= 20131218
+/*20131218 to latest
+그레네이드런쳐 계열의 총기류를 장착한 상태여야 합니다.
+Grenade Launcher should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GRANADE = 0xa01,
+/*20131218 to latest
+[히트배럴],[매드니스 캔슬러],[플래티넘 알터] 의 효과들은 중첩하여 사용할 수 없습니다.
+[Heat barrel],[Last Stand],[Platinum Alter] cannot be used while sitting.
+*/
+ MSG_FAIL_DUPLICATE_HEAT_BARREL_GS_MADNESSCANCEL_P_ALTER = 0xa02,
+#endif
+#if PACKETVER >= 20131223
+/*20131223 to latest
+현재 맵에서는 사용할 수 없는 스킬입니다.
+Cannot use skill in this map.
+*/
+ MSG_USESKILL_FAIL_MAP = 0xa03,
+#endif
+#if PACKETVER >= 20140108
+/*20140108 to latest
+길드 창고를 이용중인 경우 창고의 모든 아이템이 사라지게 됩니다.
+If you are using a guild storage, all items inside it will disappear.
+*/
+ MSG_GUILD_STORAGE_WARNING = 0xa04,
+#endif
+#if PACKETVER >= 20140115
+/*20140115 to latest
+http://ragnarok.gamesamba.com/paytest.html
+http://ragnarok.gamesamba.com/
+*/
+ MSG_AMERICA_CASHSHOP_URL_GAMESAMBA = 0xa05,
+/*20140115 to latest
+로그인을 위해 패스워드를 입력해주세요.
+Please enter a password to login.
+*/
+ MSG_SECOND_PASSWORD_INFO_4 = 0xa06,
+#endif
+#if PACKETVER >= 20140129
+/*20140129 to latest
+펫 진화
+Pet Evolution
+*/
+ MSG_PET_EVOLUTION = 0xa07,
+/*20140129 to latest
+진화 - %s
+Evolution - %s
+*/
+ MSG_PET_EVOLUTION_WITH_PET_NAME = 0xa08,
+/*20140129 to latest
+진화에는 다음의 재료가 필요합니다.
+Evolution requires the following ingredients:
+*/
+ MSG_PET_EVOLUTION_NEED_ITEM = 0xa09,
+/*20140129 to latest
+진화 하시겠습니까?
+Are you sure you want to evolve your pet?
+*/
+ MSG_DO_YOU_WANT_TO_EVOLVE_PET = 0xa0a,
+/*20140129 to latest
+알 수 없는 오류
+Unknown Error
+*/
+ MSG_PET_EVOLUTION_FAIL_UNKNOWN = 0xa0b,
+/*20140129 to latest
+소환된펫을 갖고 있지 않습니다.
+Pet Cannot be hatched.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOTEXIST_CALLPET = 0xa0c,
+/*20140129 to latest
+요청한 것이 펫알이 아닙니다.
+It is not requested petal.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOT_PETEGG = 0xa0d,
+/*20140129 to 20140205
+진화가 불가능한 요청입니다.
+20140212 to latest
+진화 재료가 부족합니다.
+Evolution material is low.
+*/
+ MSG_PET_EVOLUTION_FAIL_RECIPE = 0xa0e,
+/*20140129 to latest
+진화에 필요한 재료가 부족합니다.
+Insufficient materials for evolution.
+*/
+ MSG_PET_EVOLUTION_FAIL_MATERIAL = 0xa0f,
+/*20140129 to latest
+친밀도가 절친인 상태에서만 진화가 가능합니다.
+Loyal Intimacy is required to evolve.
+*/
+ MSG_PET_EVOLUTION_FAIL_RG_FAMILIAR = 0xa10,
+#endif
+#if PACKETVER >= 20140212
+/*20140212 to 20170830
+자동 먹이 주기
+20170906 to latest
+펫 자동 먹이 주기
+Automatic feeding
+*/
+ MSG_PET_AUTO_FEEDING = 0xa11,
+/*20140212 to latest
+펫에게 먹이를 주었습니다. '%s' 잔여량 %d개
+Feeding the pet. %d '%d' remaining
+*/
+ MSG_PET_AUTO_FEEDING_REST = 0xa12,
+/*20140212 to 20170830
+자동 먹이 주기 활성화 On
+20170906 to latest
+펫 자동 먹이 주기 활성화 On
+Automatic feeding turned On
+*/
+ MSG_PET_AUTO_FEEDING_ON = 0xa13,
+/*20140212 to 20170830
+자동 먹이 주기 활성화 Off
+20170906 to latest
+펫 자동 먹이 주기 활성화 Off
+Automatic feeding turned Off
+*/
+ MSG_PET_AUTO_FEEDING_OFF = 0xa14,
+/*20140212 to latest
+갱신
+Update
+*/
+ MSG_REFRESH = 0xa15,
+/*20140212 to 20140702
+%d 분전
+20140709 to latest
+%d 분 전
+%d minutes ago
+*/
+ MSG_TIME_LINE_MINUTE = 0xa16,
+/*20140212 to 20140702
+%d 시간전
+20140709 to latest
+%d 시간 전
+%d hours ago
+*/
+ MSG_TIME_LINE_HOUR = 0xa17,
+/*20140212 to 20140702
+%d 일전
+20140709 to latest
+%d 일 전
+%d days ago
+*/
+ MSG_TIME_LINE_DAY = 0xa18,
+#endif
+#if PACKETVER >= 20140319
+/*20140319 to latest
+%d%% ( Premium %d%% + %s Server )
+%d%%% ( Premium %d%%% + %s Server )
+*/
+ MSG_BASIC_EXP_MSG_PH = 0xa19,
+#endif
+#if PACKETVER >= 20140326
+/*20140326 to latest
+우편 발송
+Mailed
+*/
+ MSG_SEND_MAIL = 0xa1a,
+/*20140326 to latest
+메일이 전송되었습니다.
+Your mail has been sent.
+*/
+ MSG_MAIL_SENT = 0xa1b,
+/*20140326 to latest
+아이템이 인벤토리로 이동되었습니다.
+This item has been moved to the inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_SUCCEED = 0xa1c,
+/*20140326 to latest
+아이템 받기가 실패하였습니다.
+Failed to get items.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_FAILED = 0xa1d,
+/*20140326 to latest
+인벤토리를 비워주세요
+Please empty your inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_OVERWEIGHT = 0xa1e,
+/*20140326 to latest
+제니를 받았습니다.
+Zeny received.
+*/
+ MSG_GET_ZENY_FROM_MAIL_SUCCEED = 0xa1f,
+/*20140326 to latest
+제니 받기가 실패하였습니다.
+Failed to get zeny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_FAILED = 0xa20,
+/*20140326 to latest
+제니의 한계치를 넘었습니다.
+Exceeded the limits of zenny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_OVERAMOUNT = 0xa21,
+/*20140326 to latest
+아이템 첨부 성공
+Items attached success
+*/
+ MSG_SET_ITEMS_TO_MAIL_SUCCEED = 0xa22,
+/*20140326 to latest
+받는 사람의 이름이 반드시 들어가야 합니다.
+The name of the recipient must be included.
+*/
+ MSG_INVALID_MAIL_RECIEVER_INFO = 0xa23,
+/*20140326 to 20140416
+제목의 길이는 4자이상 이어야 합니다.
+20140423 to 20141001
+제목의 길이는 4자이상 16자 이하여야 합니다.
+20141008 to latest
+제목의 길이는 한글 2자~25자, 영문 4자~50자 이어야 합니다.
+The length of the title must be 4 to 50 characters long.
+*/
+ MSG_INVALID_MAIL_TITLE_INFO = 0xa24,
+/*20140326 to latest
+메일 전송이 실패하였습니다.
+Mail delivery failed.
+*/
+ MSG_FAILED_SEND_MAIL = 0xa25,
+/*20140326 to latest
+적절하지 못한 아이템으로 전송 실패하였습니다.
+Transmission has failed to inappropriate items.
+*/
+ MSG_FAILED_SEND_MAIL_ITEM = 0xa26,
+/*20140326 to latest
+받는 사람의 정보가 존재하지 않습니다.
+Information of the recipient does not exist.
+*/
+ MSG_FAIELD_SEND_MAIL_TO = 0xa27,
+#endif
+#if PACKETVER >= 20140402
+/*20140402 to latest
+%s [%d옵션]
+%s [%d Option]
+*/
+ MSG_EA6 = 0xa28,
+/*20140402 to latest
+레벨은 1~%d 사이의 숫자를 입력해 주세요.
+Level, enter a number between 1 and %d.
+*/
+ MSG_PARTY_BOOKING_ERR5R2 = 0xa29,
+#endif
+#if PACKETVER >= 20140409
+/*20140409 to latest
+소지창의 여유공간을 확보해주세요.
+Please free the window possessing space.
+*/
+ MSG_ITEM_WND_OVERFULL = 0xa2a,
+/*20140409 to 20140416
+수신자의 메일 보관 용량이 초과되었습니다.
+20140423 to latest
+메일 보내기 횟수가 초과되었습니다.
+Sending mail count exceeded.
+*/
+ MSG_FAILED_MAIL_LIMIT_CNT = 0xa2b,
+#endif
+#if PACKETVER >= 20140416
+/*20140416 to latest
+메일을 열 수 없습니다.
+You can not open the mail.
+*/
+ MSG_FAILED_TO_WRITE_MAIL = 0xa2c,
+/*20140416 to latest
+You are currently joined in CLan !!
+You currently belong to a clan.
+*/
+ MSG_JOINED_IN_CLAN = 0xa2d,
+/*20140416 to latest
+골드 PC방 마일리지 정보
+Gold PC rooms mileage information
+*/
+ MSG_GOLDPCCAFE_MILEAGE = 0xa2e,
+#endif
+#if PACKETVER >= 20140423
+/*20140423 to latest
+펫 액세서리를 해제해야 진화가 가능합니다.
+Unequip pet accessories first to start evolution
+*/
+ MSG_PET_EVOLUTION_FAIL_PET_ACC_OFF = 0xa2f,
+/*20140423 to 20140430
+ / %d 분후
+20140508 to 20140702
+%d 분후
+20140709 to latest
+%d 분 후
+%d minutes later
+*/
+ MSG_TIME_LINE_MINUTE2 = 0xa30,
+/*20140423 to 20140430
+ / %d 시간후
+20140508 to 20140702
+%d 시간후
+20140709 to latest
+%d 시간 후
+%d hours later
+*/
+ MSG_TIME_LINE_HOUR2 = 0xa31,
+/*20140423 to 20140430
+ / %d 일후
+20140508 to 20140702
+%d 일후
+20140709 to latest
+%d 일 후
+%d days later
+*/
+ MSG_TIME_LINE_DAY2 = 0xa32,
+/*20140423 to latest
+확인 버튼을 눌러 C-CODE를 확인하세요.
+Press the OK button to confirm the C-CODE.
+*/
+ MSG_INVALID_CCODE_INFO = 0xa33,
+/*20140423 to latest
+첨부된 물품을 획득 후 삭제가 가능합니다.
+After obtaining the attached article can be deleted.
+*/
+ MSG_FAILED_DELETE_MAIL = 0xa34,
+/*20140423 to latest
+현재 보유 제니 보다 많은 제니를 보낼 수 없습니다.
+You can not send any more zeny.
+*/
+ MSG_FAILED_SEND_MAIL_ZENY = 0xa35,
+/*20140423 to latest
+수수료 : %s Zeny
+Fee: %s Zeny
+*/
+ MSG_SEND_MAIL_COMMISSION = 0xa36,
+/*20140423 to latest
+받는 사람의 이름이 존재하지 않습니다.
+The recipient's name does not exist.
+*/
+ MSG_FAILE_MAIL_RECIEVER_INFO = 0xa37,
+#endif
+#if PACKETVER >= 20140430
+/*20140430 to latest
+E X P : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_EXPMSG = 0xa38,
+/*20140430 to latest
+DROP : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DROPMSG = 0xa39,
+/*20140430 to latest
+DEATH : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DEATHMSG = 0xa3a,
+#endif
+#if PACKETVER >= 20140514
+/*20140514 to 20140528
+보유 가능한 최대 마일리지 : %d
+20140605 to latest
+골드 PC방 마일리지는 최대 %d점까지 모을 수 있습니다.
+You can accumulate points of PC Gold-club up to %d points maximum.
+*/
+ MSG_MILEAGE_HELP = 0xa3b,
+#endif
+#if PACKETVER >= 20140521
+/*20140521 to 20140521
+아이템 버리기가 불 가능한 서버 입니다.
+Items discard is imposible in server.
+20140528 to latest
+해당 서버에서 사용 할 수 없는 기능 입니다
+This function can not be used on the server.
+*/
+ MSG_RESTRAINT_OF_TRADE_1 = 0xa3c,
+/*20140521 to latest
+수래 이용이 불 가능한 서버 입니다.
+Imposible to use in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_2 = 0xa3d,
+/*20140521 to latest
+옥션 이용이 불 가능한 서버 입니다.
+The auction is not available in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_3 = 0xa3e,
+/*20140521 to latest
+거래가 불 가능한 서버 입니다.
+The deal is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_4 = 0xa3f,
+/*20140521 to 20140521
+아이템 편지 보내기가 불 가능한 서버 입니다.
+20140528 to latest
+아이템 버리기가 불 가능한 서버 입니다.
+Items discard is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_5 = 0xa40,
+/*20140521 to latest
+상점 판매 기능을 사용할수 없습니다.
+Stores selling features are not available.
+*/
+ MSG_RESTRAINT_OF_TRADE_6 = 0xa41,
+/*20140521 to latest
+소환물의 SP가 부족합니다.
+The SP's summoned enough.
+*/
+ MSG_USESKILL_FAIL_SUMMON_SP_INSUFFICIENT = 0xa42,
+#endif
+#if PACKETVER >= 20140528
+/*20140528 to 20140702
+Weight : %s/%s
+20140709 to latest
+%s/%s
+*/
+ MSG_SEND_MAIL_WEIGHT = 0xa43,
+/*20140528 to latest
+메일 내용의 최대 길이는 1K 이하 입니다.
+The maximum length of the message content is 1K.
+*/
+ MSG_INVALID_MAIL_CONTENTS_INFO = 0xa44,
+/*20140528 to latest
+아이템 첨부 실패
+Failed to attach an item.
+*/
+ MSG_SET_ITEMS_TO_MAIL_FAILED = 0xa45,
+/*20140528 to latest
+메일에 첨부할수 있는 아이템의 무게가 초과되었습니다.
+The weight of the items that can be attached to mail has been exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVER_WEIGHT = 0xa46,
+#endif
+#if PACKETVER >= 20140611
+/*20140611 to latest
+이미 서비스 중입니다. 잠시 후 다시 시도해 주세요.
+Is already in service. Please try again in a few minutes.
+*/
+ MSG_DYNAMICNPC_FAIL_DUPLICATENAME = 0xa47,
+#endif
+#if PACKETVER >= 20140618
+/*20140618 to 20140924
+환상의 룰렛창을 열 수 없습니다.
+20141001 to latest
+행운의 룰렛창을 열 수 없습니다.
+Unable to open the window of Lucky Roulette.
+*/
+ MSG_FAILED_OPEN_ROULLETTE = 0xa48,
+/*20140618 to 20140924
+환상의 룰렛창을 닫을 수 없습니다.
+20141001 to latest
+행운의 룰렛창을 닫을 수 없습니다.
+Unable to close the window of the Lucky Roulette.
+*/
+ MSG_FAILED_CLOSE_ROULLETTE = 0xa49,
+/*20140618 to 20140924
+환상의 룰렛을 시작 할 수 없습니다.
+20141001 to latest
+행운의 룰렛을 시작 할 수 없습니다.
+You can not start a roulette wheel of fortune.
+*/
+ MSG_FAILED_GENERATE_ROULLETTE = 0xa4a,
+/*20140618 to 20140924
+환상의 룰렛을 시작하기 위해서는 포인트가 필요합니다.
+20141001 to latest
+행운의 룰렛을 시작하기 위해서는 포인트가 필요합니다.
+Points is required to play Lucky Roulette.
+*/
+ MSG_NOT_ENOUGH_ROULLETTE_POINT = 0xa4b,
+/*20140618 to latest
+당첨된 아이템을 수령할 수 없습니다.
+You can not receive a winning items.
+*/
+ MSG_FAILED_RECV_ITEM = 0xa4c,
+#endif
+#if PACKETVER >= 20140625
+/*20140625 to latest
+인벤토리에 아이템 개수가 초과되었습니다.
+The number of items in the inventory has been exceeded.
+*/
+ MSG_FAILED_RECV_ITEM_OVERCOUNT = 0xa4d,
+/*20140625 to latest
+무게가 초과하였습니다. 소지창의 여유공간을 확보해주세요.
+The weight has been exceeded. Please free up the possesion window.
+*/
+ MSG_FAILED_RECV_ITEM_OVERWEIGHT = 0xa4e,
+/*20140625 to latest
+노점 개설 실패.
+Failed to open stalls.
+*/
+ MSG_MERCHANTSHOP_MAKING_FAIL = 0xa4f,
+/*20140625 to latest
+룰렛이 돌고 있습니다. 경품을 확인 후에 다시 시도해주세요.
+The roulette wheel is spinning. Please try again after checking with prizes.
+*/
+ MSG_FAILED_CLOSE_ROULLETTEWND = 0xa50,
+#endif
+#if PACKETVER >= 20140702
+/*20140702 to 20140917
+환상의 룰렛
+20140924 to latest
+행운의 룰렛
+Lucky Roulette
+*/
+ MSG_ROULLETTE_WND = 0xa51,
+/*20140702 to latest
+아이템 판매 시 소리로 알림
+Notify when item sell out
+*/
+ MSG_SOUNDEFFECT_ITEMSELLWND = 0xa52,
+#endif
+#if PACKETVER >= 20140709
+/*20140709 to latest
+수수료를 확인해주세요.
+Please check the fees.
+*/
+ MSG_FAILED_SEND_MAIL_ITEMS = 0xa53,
+/*20140709 to 20140716
+유저이름확인
+20140723 to latest
+유저이름 확인
+Verify user name
+*/
+ MSG_CHECK_USER_NAME = 0xa54,
+/*20140709 to latest
+삭제 예정
+Schedule deletion
+*/
+ MSG_DELETE_DUE_DATE = 0xa55,
+#endif
+#if PACKETVER >= 20140723
+/*20140723 to latest
+달성과제
+Achievable challenge
+*/
+ MSG_ACHIEVEMENT_SYSTEM = 0xa56,
+/*20140723 to latest
+달성총점
+Achieve overall
+*/
+ MSG_ACHIEVEMENT_TOTAL_SCORE = 0xa57,
+/*20140723 to latest
+달성등급
+Achieve rank
+*/
+ MSG_ACHIEVEMENT_GRADE = 0xa58,
+/*20140723 to 20150225
+다음 보상박스까지 [%5d]점
+20150225 to latest
+다음 달성등급까지 [%5d]점
+The following compensation box until [% 5d] point
+*/
+ MSG_ACHIEVEMENT_SCORE_REQUIRED_TO_REWARD = 0xa59,
+/*20140723 to 20140723
+개요
+Overview
+20140730 to latest
+진척상황
+Progress
+*/
+ MSG_ACHIEVEMENT_SUMMARY_TITLE = 0xa5a,
+/*20140723 to 20140723
+일반
+General
+20140730 to latest
+최근 달성 업적
+Recent Achievements
+*/
+ MSG_ACHIEVEMENT_RECENT_ACHIEVEMENT = 0xa5b,
+/*20140723 to 20140723
+캐릭터
+Role
+20140730 to 20140924
+개다래 열매 품목
+20141001 to latest
+仙貝 품목
+Cracker Item
+*/
+ MSG_CASH_GEDARE1 = 0xa5c,
+/*20140723 to 20140723
+행동
+Action
+20140730 to 20140924
+개다래 열매 : %d / %d GD
+20141001 to latest
+仙貝 : %d / %d
+Cracker : %d / %d
+*/
+ MSG_CASH_GEDARE2 = 0xa5d,
+/*20140723 to 20140723
+전투
+Battle
+20140730 to 20140924
+개다래 열매가 부족합니다.
+20141001 to latest
+仙貝가 부족합니다.
+Cracker is low.
+*/
+ MSG_CASH_GEDARE_FAIL_MONEY = 0xa5e,
+/*20140723 to 20140723
+모험
+Adventure
+20140730 to 20140924
+%s GD
+20141001 to latest
+%s
+*/
+ MSG_CASH_GEDARE_MONEY = 0xa5f,
+/*20140723 to 20140723
+결투
+Duel
+20140813 to latest
+개요
+Overview
+*/
+ MSG_ACHIEVEMENT_TAB_SUMMARY = 0xa60,
+/*20140723 to 20140723
+수련
+Lily
+20140813 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL = 0xa61,
+/*20140723 to 20140723
+퀘스트
+Quest
+20140813 to latest
+캐릭터
+Role
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_CHARACTER = 0xa62,
+/*20140723 to 20140723
+에피소드
+Episode
+20140813 to latest
+행동
+Action
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_ACTION = 0xa63,
+/*20140723 to 20140723
+이벤트
+Evt
+20140813 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_REST = 0xa64,
+/*20140723 to 20140723
+활동
+20140813 to latest
+모험
+Adventure
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE = 0xa65,
+/*20140723 to 20140723
+커뮤니티
+20140813 to latest
+룬미드가츠
+Rune Midgarts
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_RUNEMIDGARTS = 0xa66,
+/*20140723 to 20140723
+제련
+Refining
+20140813 to latest
+슈발츠발드
+Schwartzvald
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_SCHWARZWALD = 0xa67,
+/*20140723 to 20140723
+경제
+20140813 to latest
+아루나펠츠
+Arunafeltz
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ARUNAFELTZ = 0xa68,
+/*20140723 to 20140723
+생활
+20140813 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ANOTHERWORLD = 0xa69,
+/*20140723 to 20140723
+축제
+20140813 to latest
+로컬라이징
+Localizing
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_LOCALIZING = 0xa6a,
+/*20140723 to 20140723
+위업
+Feat
+20140813 to latest
+던전
+Dungeon
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_DUNGEON = 0xa6b,
+/*20140723 to 20140723
+달성한 과제
+Achieved challenge
+20140813 to latest
+전투
+Battle
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE = 0xa6c,
+/*20140723 to 20140723
+진척상황
+Progress
+20140813 to latest
+결투
+Duel
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_PVP = 0xa6d,
+/*20140723 to 20140723
+최근 달성 업적
+Recent Achievements
+20140813 to latest
+수련
+Lily
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_TRAINING = 0xa6e,
+#endif
+#if PACKETVER >= 20140813
+/*20140813 to latest
+퀘스트
+Quest
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST = 0xa6f,
+/*20140813 to latest
+에피소드
+Episode
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_EPISODE = 0xa70,
+/*20140813 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_GENERAL = 0xa71,
+/*20140813 to latest
+메모리얼
+Memorial
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL = 0xa72,
+/*20140813 to latest
+미드가르드
+Midgard
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_MIDGARD = 0xa73,
+/*20140813 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_ANOTHERWORLD = 0xa74,
+/*20140813 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_REST = 0xa75,
+/*20140813 to latest
+위업
+Feat
+*/
+ MSG_ACHIEVEMENT_TAB_ACHIEVEMENT = 0xa76,
+/*20140813 to latest
+달성한 과제
+Achieved challenge
+*/
+ MSG_ACHIEVEMENT_TAB_TOTAL = 0xa77,
+/*20140813 to latest
+더 이상 추가할 수 없습니다.
+You cannot add anymore.
+*/
+ MSG_FAIL_ADD_ACHIEVEMENT_TRACING = 0xa78,
+/*20140813 to latest
+< %s > 달성하였습니다.
+< %S > achieved.
+*/
+ MSG_NOTICE_COMPLETE_ACHIEVEMENT = 0xa79,
+#endif
+#if PACKETVER >= 20140827
+/*20140827 to latest
+only otp user login allow
+Only OTP users are allowed
+*/
+ MSG_OTPUSER_ONLY = 0xa7a,
+#endif
+#if PACKETVER >= 20140917
+/*20140917 to latest
+이 버튼을 누를 시, 지정된 상품을 받게되며 룰렛은 초기화 됩니다.
+When this button pressed, you will receive a specified initialized roulette item.
+*/
+ MSG_GET_ROULLETE_PRIZE = 0xa7b,
+/*20140917 to latest
+이 버튼을 누를 시, 깜빡이는 화살표의 라인부터 룰렛을 시작 합니다.
+When this button pressed, the flashing arrows from the lines of the roulette wheel begins.
+*/
+ MSG_NOTICE_NEXT_ROULLETE_STAGE = 0xa7c,
+/*20140917 to latest
+칭호
+Style
+*/
+ MSG_TITLE_EQUIPMENT = 0xa7d,
+/*20140917 to latest
+칭호 해제
+Title release
+*/
+ MSG_TAKEOFF_TITLE = 0xa7e,
+/*20140917 to latest
+길드 생성을 할 수 없는 지역입니다.
+Can't create a Guild in this area.
+*/
+ MSG_GUILD_MAKE_GUILD_NOT_PERMITTED_MAP = 0xa7f,
+/*20140917 to latest
+길드 해체를 할 수 없는 지역입니다.
+Can't disband a Guild in this area.
+*/
+ MSG_GUILD_DISORGANIZE_GUILD_NOT_PERMITTED_MAP = 0xa80,
+/*20140917 to latest
+길드 가입을 할 수 없는 지역입니다.
+Can't join a Guild in this area.
+*/
+ MSG_GUILD_JOIN_GUILD_NOT_PERMITTED_MAP = 0xa81,
+/*20140917 to latest
+길드 탈퇴를 할 수 없는 지역입니다.
+Can't leave a Guild in this area.
+*/
+ MSG_GUILD_LEAVE_GUILD_NOT_PERMITTED_MAP = 0xa82,
+/*20140917 to latest
+길드원 추방을 할 수 없는 지역입니다.
+Can't deport a Guild in this area.
+*/
+ MSG_GUILD_EXPEL_GUILD_NOT_PERMITTED_MAP = 0xa83,
+/*20140917 to latest
+길드직위 변경을 할 수 없는 지역입니다.
+Can't change a Guild title in this area
+*/
+ MSG_GUILD_POSITION_CHANGE_NOT_PERMITTED_MAP = 0xa84,
+/*20140917 to latest
+아이템 소지량을 5칸이상 비워주세요
+Please empty at least 5 amount of possession in item window.
+*/
+ MSG_NOT_ENOUGH_SPACE_IN_ITEM_BODY = 0xa85,
+/*20140917 to latest
+E X P : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_EXPMSG = 0xa86,
+/*20140917 to latest
+DROP : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DROPMSG = 0xa87,
+/*20140917 to latest
+DEATH : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DEATHMSG = 0xa88,
+/*20140917 to latest
+첨부할 수 있는 아이템의 갯수가 초과되었습니다.
+The number of items that can be attached is exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVERCOUNT = 0xa89,
+/*20140917 to latest
+아이템 구매 시 소리로 알림
+Notify when item purchased
+*/
+ MSG_SOUNDEFFECT_ITEMBUYWND = 0xa8a,
+#endif
+#if PACKETVER >= 20140924
+/*20140924 to latest
+첨부할 수 없는 아이템입니다.
+Unable to attach the items.
+*/
+ MSG_ID_A8B = 0xa8b,
+#endif
+#if PACKETVER >= 20141001
+/*20141001 to latest
+꽝에 당첨되었으므로 다음 상위 단계의 룰렛을 돌리실 수 없습니다.
+Because you can not win a slam room and turn the roulette of the next higher step.
+*/
+ MSG_ID_A8C = 0xa8c,
+/*20141001 to latest
+답장쓰기
+Replying
+*/
+ MSG_ID_A8D = 0xa8d,
+/*20141001 to latest
+내용읽기
+Read more
+*/
+ MSG_ID_A8E = 0xa8e,
+/*20141001 to latest
+메일삭제
+Delete message
+*/
+ MSG_ID_A8F = 0xa8f,
+/*20141001 to latest
+仙貝 : %d
+Crackers : %d
+*/
+ MSG_ID_A90 = 0xa90,
+/*20141001 to latest
+%s %s 仙貝
+%s %s crackers
+*/
+ MSG_ID_A91 = 0xa91,
+/*20141001 to latest
+仙貝
+Crackers
+*/
+ MSG_ID_A92 = 0xa92,
+/*20141001 to latest
+Total : %d 仙貝
+Total : %d Crackers
+*/
+ MSG_ID_A93 = 0xa93,
+/*20141001 to latest
+%d -> %s 仙貝
+%d -> %s Crackers
+*/
+ MSG_ID_A94 = 0xa94,
+/*20141001 to latest
+%s 仙貝
+%s Crackers
+*/
+ MSG_ID_A95 = 0xa95,
+/*20141001 to latest
+ Current 仙貝 : %s
+ Current Crackers : %s
+*/
+ MSG_ID_A96 = 0xa96,
+/*20141001 to latest
+ %s : %s 仙貝
+ %s : %s Crackers
+*/
+ MSG_ID_A97 = 0xa97,
+/*20141001 to latest
+%10s 仙貝
+%10s Crackers
+*/
+ MSG_ID_A98 = 0xa98,
+/*20141001 to latest
+Total : %s 仙貝
+Total : %s Crackers
+*/
+ MSG_ID_A99 = 0xa99,
+/*20141001 to latest
+※수수료 3% / 최소 1仙貝의 수수료 차감
+* Commission 3% / Minimum 1 Crackers comission deducted
+*/
+ MSG_ID_A9A = 0xa9a,
+/*20141001 to latest
+仙貝 입니다.
+The Crackers.
+*/
+ MSG_ID_A9B = 0xa9b,
+/*20141001 to latest
+^0000ff仙貝 이상^000000입니다.
+입력금액이 맞습니까?
+^0000ff more than crackers^000000Did you enter the correct amount?
+*/
+ MSG_ID_A9C = 0xa9c,
+/*20141001 to latest
+10억仙貝이상 안전 확인
+Over than 10billions secure check
+*/
+ MSG_ID_A9D = 0xa9d,
+/*20141001 to latest
+10억 仙貝 이상 입력하셔도 가격은 10억 仙貝로 판매됩니다.
+If you fill over 1 billion, the price will be automatically set as 10 billion Xianbei.
+*/
+ MSG_ID_A9E = 0xa9e,
+/*20141001 to latest
+9,999仙貝 이상 입력하셔도 가격은 9,999仙貝로 판매됩니다.
+If you fill over 9,999 Xianbei, the price will automatically set as 9,999 Xianbei.
+*/
+ MSG_ID_A9F = 0xa9f,
+/*20141001 to latest
+가격이 0 仙貝인 아이템이 존재 합니다. 상점을 열수 없습니다!
+There are items priced 0 Xianbei. You cannot open vending.
+*/
+ MSG_ID_AA0 = 0xaa0,
+/*20141001 to latest
+상대 캐릭터가 최대 보유 仙貝량을 초과하여 거래가 불가능 합니다.
+The opponent is over the Xianbei limit. Trade failed.
+*/
+ MSG_ID_AA1 = 0xaa1,
+/*20141001 to latest
+%s 아이템의 가격을 10억仙貝 이하로 입력해 주세요.
+Please fill out %s item price less than 1 billion Xianbei.
+*/
+ MSG_ID_AA2 = 0xaa2,
+/*20141001 to latest
+%s : %s 仙貝 => %s EA
+%s: %s Xianbei => %s ea
+*/
+ MSG_ID_AA3 = 0xaa3,
+/*20141001 to latest
+제한 금액 : %s 仙貝
+Limited price: %s Xianbei
+*/
+ MSG_ID_AA4 = 0xaa4,
+/*20141001 to latest
+%s %s 仙貝 %d 개
+%s %s %d Xianbei
+*/
+ MSG_ID_AA5 = 0xaa5,
+/*20141001 to latest
+%s %d개를 %d 仙貝에 판매 하였습니다. 수수료는 3%% 입니다.
+%d %s are sold. In total %d Xianbei. 3%% charge will be imposed.
+*/
+ MSG_ID_AA6 = 0xaa6,
+#endif
+#if PACKETVER >= 20141008
+/*20141008 to latest
+RODEX
+*/
+ MSG_ID_AA7 = 0xaa7,
+/*20141008 to latest
+SEND
+*/
+ MSG_ID_AA8 = 0xaa8,
+/*20141008 to latest
+RECEIVE
+*/
+ MSG_ID_AA9 = 0xaa9,
+#endif
+#if PACKETVER >= 20141015
+/*20141015 to latest
+메일 작성창을 닫아주세요.
+Please close the mail compose window.
+*/
+ MSG_ID_AAA = 0xaaa,
+#endif
+#if PACKETVER >= 20141022
+/*20141022 to latest
+서버접근거부(A)
+Server access denied(A)
+*/
+ MSG_ID_AAB = 0xaab,
+/*20141022 to latest
+서버접근거부(B)
+Server access denied(B)
+*/
+ MSG_ID_AAC = 0xaac,
+#endif
+#if PACKETVER >= 20141112
+/*20141112 to latest
+장착된 화살/탄환 을 해제해야합니다.
+Unequipped Arrow/Ammunition.
+*/
+ MSG_ID_AAD = 0xaad,
+#endif
+#if PACKETVER >= 20141119
+/*20141119 to latest
+인벤토리의 아이템이 소모되어 로덱스 쓰기창을 닫습니다.
+Consuming item in inventory will close mail compose window.
+*/
+ MSG_ID_AAE = 0xaae,
+/*20141119 to latest
+소지하신 돋보기가 없습니다.
+Do not have Magnifier.
+*/
+ MSG_ID_AAF = 0xaaf,
+#endif
+#if PACKETVER >= 20141210
+/*20141210 to latest
+아이템을 버릴려면 메일 쓰기창을 닫아주세요.
+Close email window if you want to discard item.
+*/
+ MSG_ID_AB0 = 0xab0,
+/*20141210 to latest
+상대방이 친구 요청중입니다
+The opponent has already requested you to be a friend.
+*/
+ MSG_ID_AB1 = 0xab1,
+#endif
+#if PACKETVER >= 20141217
+/*20141217 to latest
+SCRIPT ERROR AID
+*/
+ MSG_ID_AB2 = 0xab2,
+/*20141217 to 20141231
+
+Errorfile : %s
+ErrorLine : %d 줄
+ErrorContext: %s
+20150107 to latest
+
+Errorfile : %s
+ErrorLine : %d 줄
+ErrorContent:
+*이전 줄 : %s
+*Errorline : %s
+*다음 줄:
+ %s
+
+Errorfile : %s
+ErrorLine : %d item
+ErrorContext: %s
+*/
+ MSG_ID_AB3 = 0xab3,
+#endif
+#if PACKETVER >= 20141223
+/*20141223 to latest
+ ^ff0000해당 아이템을 구매 하시겠습니까? %d포인트 및 %d 仙貝가 차감 됩니다.
+^ff0000Are you sure want to purchase the item? after confirmation will consume %d point and %d crackers.
+*/
+ MSG_ID_AB4 = 0xab4,
+/*20141223 to latest
+닫기
+Close
+*/
+ MSG_ID_AB5 = 0xab5,
+/*20141223 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_AB6 = 0xab6,
+/*20141223 to latest
+퀘스트 아이콘 보기
+View Quest icon
+*/
+ MSG_ID_AB7 = 0xab7,
+/*20141223 to latest
+편의시설
+Facility
+*/
+ MSG_ID_AB8 = 0xab8,
+/*20141223 to latest
+편의시설 아이콘 보기
+View Facility icon
+*/
+ MSG_ID_AB9 = 0xab9,
+/*20141223 to latest
+길드원/파티원
+Guild/Party
+*/
+ MSG_ID_ABA = 0xaba,
+/*20141223 to 20150311
+길드원/파티원 표시
+20150318 to latest
+길드원/파티원 보기
+Show Guild/Party
+*/
+ MSG_ID_ABB = 0xabb,
+/*20141223 to latest
+기록하기
+Record
+*/
+ MSG_ID_ABC = 0xabc,
+/*20141223 to latest
+보스몬스터
+Boss Monster
+*/
+ MSG_ID_ABD = 0xabd,
+/*20141223 to latest
+나
+I
+*/
+ MSG_ID_ABE = 0xabe,
+/*20141223 to latest
+삭제 하시겠습니까?
+Are you sure want to delete it?
+*/
+ MSG_ID_ABF = 0xabf,
+/*20141223 to latest
+퀘스트 NPC
+Quest NPC
+*/
+ MSG_ID_AC0 = 0xac0,
+/*20141223 to latest
+메모할 내용을 기록합니다
+Record content
+*/
+ MSG_ID_AC1 = 0xac1,
+/*20141223 to latest
+저장하기
+Store
+*/
+ MSG_ID_AC2 = 0xac2,
+/*20141223 to latest
+메모하기
+Record
+*/
+ MSG_ID_AC3 = 0xac3,
+/*20141223 to latest
+%s [%d옵션] %d개
+%s [%d Property] %d ea
+*/
+ MSG_ID_AC4 = 0xac4,
+/*20141223 to latest
+%s [%d옵션] %s Zeny
+%s [%d Property] %s Zeny
+*/
+ MSG_ID_AC5 = 0xac5,
+#endif
+#if PACKETVER >= 20141231
+/*20141231 to latest
+%s [%d옵션] %d %s %d -> %s %s
+%s [%d Property] %d %s %d -> %s %s
+*/
+ MSG_ID_AC6 = 0xac6,
+/*20141231 to latest
+%s [%d옵션] %d %s %s %s
+%s [%d Property] %d %s %s %s
+*/
+ MSG_ID_AC7 = 0xac7,
+/*20141231 to latest
+%s [%d옵션] %d -> %s %s
+%s [%d Property] %d -> %s %s
+*/
+ MSG_ID_AC8 = 0xac8,
+/*20141231 to latest
+%s [%d옵션] %s %s
+%s [%d Property] %s %s
+*/
+ MSG_ID_AC9 = 0xac9,
+#endif
+#if PACKETVER >= 20150107
+/*20150107 to latest
+최소 거래 단위 100 仙貝 이상으로 설정 하셔야 합니다.
+The minimum trading unit must be 100 crackers or more.
+*/
+ MSG_ID_ACA = 0xaca,
+#endif
+#if PACKETVER >= 20150114
+/*20150114 to latest
+머리 색
+Hair color
+*/
+ MSG_ID_ACB = 0xacb,
+/*20150114 to latest
+머리 모양
+Hair style
+*/
+ MSG_ID_ACC = 0xacc,
+/*20150114 to latest
+옷 색
+Cloth color
+*/
+ MSG_ID_ACD = 0xacd,
+/*20150114 to latest
+옷 모양
+Cloth pattern
+*/
+ MSG_ID_ACE = 0xace,
+#endif
+#if PACKETVER >= 20150217
+/*20150217 to latest
+지원되지 않는 맵 입니다.
+Unsupported Map.
+*/
+ MSG_ID_ACF = 0xacf,
+#endif
+#if PACKETVER >= 20150304
+/*20150304 to 20150318
+2147483647 Zeny 이하로 입력 하십시오.
+20150325 to latest
+2,147,483,647 Zeny 이하로 입력 하십시오.
+Enter Zeny Below 2,147,483,647.
+*/
+ MSG_ID_AD0 = 0xad0,
+/*20150304 to latest
+1 Zeny 이상 입력 하십시오.
+Please Enter atleast 1 zeny.
+*/
+ MSG_ID_AD1 = 0xad1,
+/*20150304 to latest
+보유한 Zeny 가 없습니다.
+You do not hold any zeny.
+*/
+ MSG_ID_AD2 = 0xad2,
+/*20150304 to latest
+제니 창고
+Zeny Storage
+*/
+ MSG_ID_AD3 = 0xad3,
+/*20150304 to latest
+창고보유액
+in Bank
+*/
+ MSG_ID_AD4 = 0xad4,
+/*20150304 to latest
+소지금
+on hand
+*/
+ MSG_ID_AD5 = 0xad5,
+/*20150304 to latest
+입금
+Deposit
+*/
+ MSG_ID_AD6 = 0xad6,
+/*20150304 to latest
+출금
+Withdraw
+*/
+ MSG_ID_AD7 = 0xad7,
+/*20150304 to latest
+1 z UP
+*/
+ MSG_ID_AD8 = 0xad8,
+/*20150304 to latest
+1 z Down
+*/
+ MSG_ID_AD9 = 0xad9,
+/*20150304 to latest
+Max
+*/
+ MSG_ID_ADA = 0xada,
+/*20150304 to latest
+입력값이 없습니다
+There is no Input value
+*/
+ MSG_ID_ADB = 0xadb,
+/*20150304 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_ADC = 0xadc,
+/*20150304 to latest
+입력값 필요
+Input Required
+*/
+ MSG_ID_ADD = 0xadd,
+/*20150304 to latest
+문자 입력 불가
+Numbers only
+*/
+ MSG_ID_ADE = 0xade,
+/*20150304 to latest
+최대 입력 초과
+Exceeded max input
+*/
+ MSG_ID_ADF = 0xadf,
+/*20150304 to latest
+최소 입력 미만
+Below Minimum Input
+*/
+ MSG_ID_AE0 = 0xae0,
+/*20150304 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_AE1 = 0xae1,
+/*20150304 to latest
+은행 잔고 부족
+Insufficient funds
+*/
+ MSG_ID_AE2 = 0xae2,
+/*20150304 to latest
+최대 보유 Zeny 초과
+Exceeded max zeny
+*/
+ MSG_ID_AE3 = 0xae3,
+#endif
+#if PACKETVER >= 20150311
+/*20150311 to latest
+드롭 X
+Drop X
+*/
+ MSG_ID_AE4 = 0xae4,
+/*20150311 to latest
+창고 X
+Storage X
+*/
+ MSG_ID_AE5 = 0xae5,
+/*20150311 to latest
+카트 X
+Cart X
+*/
+ MSG_ID_AE6 = 0xae6,
+/*20150311 to latest
+메일 X
+Mail X
+*/
+ MSG_ID_AE7 = 0xae7,
+/*20150311 to latest
+교환창 X
+Trade X
+*/
+ MSG_ID_AE8 = 0xae8,
+/*20150311 to latest
+경매장 X
+Auction X
+*/
+ MSG_ID_AE9 = 0xae9,
+/*20150311 to latest
+길드창고 X
+Guild Storage X
+*/
+ MSG_ID_AEA = 0xaea,
+/*20150311 to latest
+NPC에게 판매 X
+Sell to NPC X
+*/
+ MSG_ID_AEB = 0xaeb,
+/*20150311 to latest
+이동제한이 있는 아이템입니다.
+Item moves restriction.
+*/
+ MSG_ID_AEC = 0xaec,
+#endif
+#if PACKETVER >= 20150401
+/*20150401 to latest
+캐릭터를 생성해주세요!
+Please Create a Character!
+*/
+ MSG_ID_AED = 0xaed,
+#endif
+#if PACKETVER >= 20150415
+/*20150415 to latest
+장착된 투사체 아이템을 해제해야 합니다.
+You need to disarm the equipped projectiles.
+*/
+ MSG_ID_AEE = 0xaee,
+#endif
+#if PACKETVER >= 20150513
+/*20150513 to latest
+인원 초과로 메모리얼 던전에 입장 할 수 없습니다
+You cannot enter Memorial Dungeon with excess members
+*/
+ MSG_ID_AEF = 0xaef,
+/*20150513 to latest
+인원수 초과로 인해 메모리얼 던전 입장이 거부되었습니다
+Memorial Dungeon Access was denied due to exceeding number of players
+*/
+ MSG_ID_AF0 = 0xaf0,
+#endif
+#if PACKETVER >= 20150603
+/*20150603 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF1 = 0xaf1,
+/*20150603 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF2 = 0xaf2,
+/*20150603 to latest
+중복된 아이템이 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to multiple same item.
+*/
+ MSG_ID_AF3 = 0xaf3,
+/*20150603 to latest
+중복된 효과가 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to effect of same consumed item.
+*/
+ MSG_ID_AF4 = 0xaf4,
+#endif
+#if PACKETVER >= 20150701
+/*20150701 to latest
+화면 흔들림 효과 ON
+Flicker Effect ON
+*/
+ MSG_ID_AF5 = 0xaf5,
+/*20150701 to latest
+화면 흔들림 효과 OFF
+Flicker Effect OFF
+*/
+ MSG_ID_AF6 = 0xaf6,
+#endif
+#if PACKETVER >= 20150708
+/*20150708 to latest
+불법 프로그램 발견되었습니다
+Illegal Programs has been detected
+*/
+ MSG_ID_AF7 = 0xaf7,
+#endif
+#if PACKETVER >= 20150722
+/*20150722 to latest
+메일 보내기
+Send Mail
+*/
+ MSG_ID_AF8 = 0xaf8,
+#endif
+#if PACKETVER >= 20150729
+/*20150729 to latest
+E X P : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AF9 = 0xaf9,
+/*20150729 to latest
+DROP : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFA = 0xafa,
+/*20150729 to latest
+DEATH : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFB = 0xafb,
+#endif
+#if PACKETVER >= 20150826
+/*20150826 to 20180919
+ 해당 태그는 이름으로 사용하실 수 없습니다.
+Name with this tag cannot be used.
+20181002 to latest
+ 해당 내용은 이름으로 사용하실 수 없습니다.
+You cannot use the tag as a name.
+*/
+ MSG_ID_AFC = 0xafc,
+#endif
+#if PACKETVER >= 20150916
+/*20150916 to latest
+???? bdbac5b8c0cfb8b52098de
+Style Shop
+*/
+ MSG_ID_AFD = 0xafd,
+#endif
+#if PACKETVER >= 20151028
+/*20151028 to 20151125
+쿠폰 없음, 상점에서 구매해야해요.
+20151202 to latest
+쿠폰 없음. Cash Shop에서 아이템을 구매해 주세요.
+No serial number, Please visit the store to buy.
+*/
+ MSG_ID_AFE = 0xafe,
+/*20151028 to 20151125
+아이템창의 쿠폰 상자를 열어주세요
+20151202 to latest
+인벤토리에서 아이템 쿠폰 상자를 열어주세요.
+Please turn on Serial item number window box.
+*/
+ MSG_ID_AFF = 0xaff,
+/*20151028 to 20151125
+은행
+Bank
+20151202 to latest
+해당 스타일 정보를 삭제하시겠습니까?
+Bank
+*/
+ MSG_ID_B00 = 0xb00,
+/*20151028 to 20151125
+슬롯이 꽉 찼습니다. 캐릭터를 삭제 후 사용해 주시기 바랍니다
+20151202 to latest
+슬롯이 꽉 찼습니다. 내 스타일에서 캐릭터 삭제 후 사용해 주십시오.
+Slot is full, please delete a character.
+*/
+ MSG_ID_B01 = 0xb01,
+/*20151028 to 20151125
+사용하신 아이템은 되돌릴 수 없습니다. 적용하시겠습니까?
+20151202 to latest
+비용을 지불하고 현재 스타일을 적용하시겠습니까?
+(※ 비용은 반환되지 않습니다.)
+Item cannot be restored, are you sure want to apply it?
+*/
+ MSG_ID_B02 = 0xb02,
+#endif
+#if PACKETVER >= 20151104
+/*20151104 to 20151125
+관심 스타일로 등록되었습니다
+20151202 to latest
+현재 스타일을 저장하였습니다.
+Registered as the following style.
+*/
+ MSG_ID_B03 = 0xb03,
+/*20151104 to 20151125
+은행에 충분한 제니가 있습니다. 먼저 은행으로 가세요.
+20151202 to latest
+보유 Zeny 부족. 은행에 충분한 Zeny가 있습니다.
+There are plenty of golds in the bank, Please go to the bank now.
+*/
+ MSG_ID_B04 = 0xb04,
+#endif
+#if PACKETVER >= 20151118
+/*20151118 to latest
+으로 이동합니다.
+moving...
+*/
+ MSG_ID_B05 = 0xb05,
+/*20151118 to latest
+해당 국가의 영공통과에 대한 허가가 나지 않았습니다.
+You are not allowed to fly over the sovereign airspace of the country.
+*/
+ MSG_ID_B06 = 0xb06,
+/*20151118 to latest
+마나로 대기불안정이 계속되어 비공정 운행이 불가능합니다.
+Airship flight is temporarily unavailable due to atmospheric instability caused by magic.
+*/
+ MSG_ID_B07 = 0xb07,
+/*20151118 to latest
+개인 비공정
+Private airship
+*/
+ MSG_ID_B08 = 0xb08,
+/*20151118 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_B09 = 0xb09,
+/*20151118 to latest
+개인 비공정 이용에 필요한 제니가 부족합니다.
+Not enough Zeny to use the private airship.
+*/
+ MSG_ID_B0A = 0xb0a,
+/*20151118 to 20170920
+개인 비공정 이용에 필요한 통조림이 부족합니다.
+20170927 to latest
+개인 비공정 이용에 필요한 아이템이 부족합니다.
+Not enough Cans to use the private airship.
+*/
+ MSG_ID_B0B = 0xb0b,
+/*20151118 to latest
+개인 비공정을 이용할 수 있는 레벨이 아닙니다.
+You cannot meet the level to use the private airship.
+*/
+ MSG_ID_B0C = 0xb0c,
+/*20151118 to latest
+선택한 지점으론 개인비공정이 이동할 수 없습니다.
+You cannot move to the selected point by the private airship.
+*/
+ MSG_ID_B0D = 0xb0d,
+/*20151118 to latest
+현 지점에선 개인비공정을 이용할 수 없습니다.
+You cannot use the private airship where you are now.
+*/
+ MSG_ID_B0E = 0xb0e,
+#endif
+#if PACKETVER >= 20151125
+/*20151125 to 20151125
+악세사리
+Accessory
+20151202 to latest
+액세서리
+Accessory
+*/
+ MSG_ID_B0F = 0xb0f,
+/*20151125 to latest
+세컨드코스튬
+Second costume
+*/
+ MSG_ID_B10 = 0xb10,
+/*20151125 to 20151125
+즐겨찾기
+20151202 to latest
+내 스타일
+Wardrobe
+*/
+ MSG_ID_B11 = 0xb11,
+/*20151125 to 20151125
+염색을 할 수 없는 머리스타일입니다.
+20151202 to latest
+염색할 수 없는 헤어스타일입니다.
+This hairstyle cannot be dyed.
+*/
+ MSG_ID_B12 = 0xb12,
+/*20151125 to 20151125
+화살표를 눌러 마음에 드는 스타일을 선택할 수 있어요.
+20151202 to latest
+화살표를 눌러 마음에 드는 스타일을 선택해 보세요.
+Press an arrow to choose the style you want.
+*/
+ MSG_ID_B13 = 0xb13,
+#endif
+#if PACKETVER >= 20151202
+/*20151202 to 20151202
+스타일 새로운 스타일을 확인해 보세요.
+(※ 액세서리 구매 시 RODEX로 발송됩니다.)
+20151209 to latest
+새로운 스타일을 확인해 보세요.
+(※ 액세서리 구매 시 RODEX로 발송됩니다.)
+Come and see the new styles.
+(Purchased accessories will be sent via RODEX.)
+*/
+ MSG_ID_B14 = 0xb14,
+#endif
+#if PACKETVER >= 20151223
+/*20151223 to latest
+기본 스타일
+Basic style
+*/
+ MSG_ID_B15 = 0xb15,
+#endif
+#if PACKETVER >= 20160106
+/*20160106 to latest
+ 해당 스킬은 BaseLv %d 이상부터 스킬 포인트 투자가 가능합니다.
+You can level up the skill from the base Lv. %d.
+*/
+ MSG_ID_B16 = 0xb16,
+#endif
+#if PACKETVER >= 20160113
+/*20160113 to latest
+해당 특수기호는 이름에 사용하실 수 없습니다.
+Special symbol can't be used in name
+*/
+ MSG_ID_B17 = 0xb17,
+/*20160113 to latest
+MHP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxHP is to low to use this skill
+*/
+ MSG_ID_B18 = 0xb18,
+/*20160113 to latest
+MSP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxSP is to low to use this skill
+*/
+ MSG_ID_B19 = 0xb19,
+#endif
+#if PACKETVER >= 20160203
+/*20160203 to latest
+아이템 비교하기
+Compare items
+*/
+ MSG_ID_B1A = 0xb1a,
+/*20160203 to latest
+아이템 버리기 잠금
+Drop lock
+*/
+ MSG_ID_B1B = 0xb1b,
+#endif
+#if PACKETVER >= 20160224
+/*20160224 to latest
+스크린샷 파일이 첨부 되지 않았습니다.
+Screenshots are not attached
+*/
+ MSG_ID_B1C = 0xb1c,
+/*20160224 to 20160511
+SNS통신
+20160518 to 20160817
+TWITTER
+20160824 to latest
+Twitter
+*/
+ MSG_ID_B1D = 0xb1d,
+/*20160224 to latest
+일반
+General
+*/
+ MSG_ID_B1E = 0xb1e,
+/*20160224 to latest
+공지
+Notice
+*/
+ MSG_ID_B1F = 0xb1f,
+/*20160224 to latest
+반송
+Clear
+*/
+ MSG_ID_B20 = 0xb20,
+/*20160224 to latest
+새로고침
+Refresh
+*/
+ MSG_ID_B21 = 0xb21,
+/*20160224 to latest
+%d분
+%d minute
+*/
+ MSG_ID_B22 = 0xb22,
+/*20160224 to latest
+%d시간
+%d hour
+*/
+ MSG_ID_B23 = 0xb23,
+/*20160224 to latest
+%d일
+%d day
+*/
+ MSG_ID_B24 = 0xb24,
+/*20160224 to latest
+반송됨
+Returned
+*/
+ MSG_ID_B25 = 0xb25,
+/*20160224 to latest
+선택한 메일을 삭제하시겠습니까?
+Do you want to delete the message?
+*/
+ MSG_ID_B26 = 0xb26,
+#endif
+#if PACKETVER >= 20160302
+/*20160302 to latest
+위치표시
+Show information
+*/
+ MSG_ID_B27 = 0xb27,
+/*20160302 to latest
+확대
+Zoom In
+*/
+ MSG_ID_B28 = 0xb28,
+/*20160302 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_B29 = 0xb29,
+/*20160302 to latest
+맵보기
+Maximize
+*/
+ MSG_ID_B2A = 0xb2a,
+/*20160302 to latest
+월드보기
+Show world map
+*/
+ MSG_ID_B2B = 0xb2b,
+/*20160302 to latest
+아이템 소지 종류수
+Total possession item type
+*/
+ MSG_ID_B2C = 0xb2c,
+#endif
+#if PACKETVER >= 20160309
+/*20160309 to latest
+/minimap
+*/
+ MSG_ID_B2D = 0xb2d,
+/*20160309 to latest
+미니맵 버튼을 표시합니다
+Show minimap buttons
+*/
+ MSG_ID_B2E = 0xb2e,
+/*20160309 to latest
+미니맵 버튼을 표시하지 않습니다
+Hide minimap buttons
+*/
+ MSG_ID_B2F = 0xb2f,
+/*20160309 to latest
+길드 접속자 정렬
+Show guild member login status
+*/
+ MSG_ID_B30 = 0xb30,
+#endif
+#if PACKETVER >= 20160323
+/*20160323 to latest
+친밀도 : %s
+Intimacy: %s
+*/
+ MSG_ID_B31 = 0xb31,
+/*20160323 to latest
+확인 전
+Confirmation
+*/
+ MSG_ID_B32 = 0xb32,
+#endif
+#if PACKETVER >= 20160330
+/*20160330 to latest
+파티 이름
+Team name
+*/
+ MSG_ID_B33 = 0xb33,
+/*20160330 to latest
+파티장
+Leader
+*/
+ MSG_ID_B34 = 0xb34,
+/*20160330 to latest
+제한 시간 초과. 클라이언트를 종료합니다.
+Time limit exceeded. Closing the client
+*/
+ MSG_ID_B35 = 0xb35,
+/*20160330 to latest
+잘못된 입력입니다. 클라이언트를 종료합니다.
+Input error. Closing the client
+*/
+ MSG_ID_B36 = 0xb36,
+/*20160330 to latest
+정답 입니다. 보상으로 소정의 버프가 주어집니다.
+Incorrect input. A small buff has given to you
+*/
+ MSG_ID_B37 = 0xb37,
+/*20160330 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_B38 = 0xb38,
+/*20160330 to latest
+입력한 답이 [%s]가 맞습니까?
+Your entered answer is [%s]. Is it right?
+*/
+ MSG_ID_B39 = 0xb39,
+/*20160330 to latest
+선택된 이미지가 없습니다.
+Icon is unchecked
+*/
+ MSG_ID_B3A = 0xb3a,
+/*20160330 to latest
+잘못된 입력입니다. (남은 기회 %d번)
+Incorrect input (Remaining chance: %d)
+*/
+ MSG_ID_B3B = 0xb3b,
+/*20160330 to latest
+총 %d명의 유저를 신고하시겠습니까?
+Do you want to announce %d to player?
+*/
+ MSG_ID_B3C = 0xb3c,
+/*20160330 to latest
+유저에게 메시지를 보냈습니다.
+Message has been sent to player
+*/
+ MSG_ID_B3D = 0xb3d,
+/*20160330 to latest
+불법 프로그램 단속에 필요한 데이터가 미등록 상태입니다.
+Needed Data for Query illegal software are not signed.
+*/
+ MSG_ID_B3E = 0xb3e,
+/*20160330 to latest
+이미 매크로 감시중인 유저입니다.
+The player is being monitored.
+*/
+ MSG_ID_B3F = 0xb3f,
+/*20160330 to latest
+매크로가 등록되었습니다..
+Already signed in investigation system.
+*/
+ MSG_ID_B40 = 0xb40,
+/*20160330 to latest
+이미지 등록에 실패하였습니다.
+Failed to store icon.
+*/
+ MSG_ID_B41 = 0xb41,
+/*20160330 to latest
+정답 등록에 실패하였습니다.
+Failed to store replied answer.
+*/
+ MSG_ID_B42 = 0xb42,
+/*20160330 to latest
+안녕하세요. 불법프로그램 단속중입니다.
+Hello, illegal software is being monitored.
+*/
+ MSG_ID_B43 = 0xb43,
+/*20160330 to latest
+지정된 시간내에 아래의 문자를 입력해주세요.
+Please enter the text below within the specified time.
+*/
+ MSG_ID_B44 = 0xb44,
+/*20160330 to latest
+3회 오류시 운영정책에 의거하여 영구블록됩니다.
+According to game regulation, when you enter the wrong text three times, you will get banned.
+*/
+ MSG_ID_B45 = 0xb45,
+/*20160330 to latest
+남은 횟수 : %d
+Remaining chance : %d
+*/
+ MSG_ID_B46 = 0xb46,
+/*20160330 to latest
+캐릭터
+Role
+*/
+ MSG_ID_B47 = 0xb47,
+/*20160330 to latest
+범위
+Range
+*/
+ MSG_ID_B48 = 0xb48,
+/*20160330 to latest
+캐릭터 선택은 좌클릭으로 합니다.
+You use the left mouse button to specify the role
+*/
+ MSG_ID_B49 = 0xb49,
+/*20160330 to latest
+범위 선택은 우클릭으로 합니다.
+You use the left mouse button to specify the range
+*/
+ MSG_ID_B4A = 0xb4a,
+/*20160330 to latest
+범위 크기를 지정하기 위해서는 엔터를 입력해주세요
+Not a valid range, please press Enter
+*/
+ MSG_ID_B4B = 0xb4b,
+/*20160330 to latest
+E X P : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4C = 0xb4c,
+/*20160330 to latest
+DROP : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4D = 0xb4d,
+/*20160330 to latest
+DEATH : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4E = 0xb4e,
+/*20160330 to 20160330
+변경된 캐릭명 %s 로 전송했습니다. 확인 바랍니다
+20160406 to latest
+변경된 캐릭명으로 발송했습니다. 변경된 캐릭명 : %s
+The role name will be sent: %s
+*/
+ MSG_ID_B4F = 0xb4f,
+#endif
+#if PACKETVER >= 20160427
+/*20160427 to latest
+합성에 필요한 재료
+Synthesis of the required materials
+*/
+ MSG_ID_B50 = 0xb50,
+/*20160427 to latest
+조합 재료가 부족해서 조합할 수 없습니다.
+Insufficient synthesis materials
+*/
+ MSG_ID_B51 = 0xb51,
+#endif
+#if PACKETVER >= 20160504
+/*20160504 to latest
+해당 재료는 %d개가 필요합니다.
+Required material %d ea.
+*/
+ MSG_ID_B52 = 0xb52,
+/*20160504 to latest
+제련도가 낮아서 조합할 수 없습니다.
+Refine value is to low for synthesis
+*/
+ MSG_ID_B53 = 0xb53,
+/*20160504 to latest
+모험가중개소에 등록 하시겠습니까?
+Do you want to sign in to the adventurers?
+*/
+ MSG_ID_B54 = 0xb54,
+#endif
+#if PACKETVER >= 20160511
+/*20160511 to latest
+자유롭게 코멘트를 남겨보세요.
+Please leave a message
+*/
+ MSG_ID_B55 = 0xb55,
+#endif
+#if PACKETVER >= 20160518
+/*20160518 to latest
+그림에 보이는 문자를 입력해주세요.
+Please enter the text on the graph
+*/
+ MSG_ID_B56 = 0xb56,
+/*20160518 to latest
+%d초 남았습니다
+%d second left
+*/
+ MSG_ID_B57 = 0xb57,
+/*20160518 to latest
+OTP 인증번호 6자리를 입력해 주세요
+Please enter your 6 identification number.
+*/
+ MSG_ID_B58 = 0xb58,
+/*20160518 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_B59 = 0xb59,
+/*20160518 to latest
+6자리의 숫자가 아닙니다. 다시 확인해 주세요
+It's not a 6 identification number. Please try again
+*/
+ MSG_ID_B5A = 0xb5a,
+#endif
+#if PACKETVER >= 20160601
+/*20160601 to latest
+이미 삭제된 메일입니다.
+The message has been deleted
+*/
+ MSG_ID_B5B = 0xb5b,
+#endif
+#if PACKETVER >= 20160615
+/*20160615 to latest
+개인 비공정으로 이동할 지역을 선택해주세요.
+Please select the area where the private airship will move
+*/
+ MSG_ID_B5C = 0xb5c,
+/*20160615 to latest
+E X P : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5D = 0xb5d,
+/*20160615 to latest
+DROP : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5E = 0xb5e,
+/*20160615 to latest
+DEATH : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5F = 0xb5f,
+/*20160615 to latest
+목적지로 이동중입니다.
+Move to the destination
+*/
+ MSG_ID_B60 = 0xb60,
+#endif
+#if PACKETVER >= 20160629
+/*20160629 to latest
+[%s] 파일이 존재하지 않아 default AI 로 동작합니다
+The [%s] is not present, the default AI will be used instead.
+*/
+ MSG_ID_B61 = 0xb61,
+/*20160629 to 20160630
+ %.1f%% ( Premium %.1f%% + %s %.1f%%)
+20160706 to latest
+ %.1f%% ( Basic 100.0%% + Premium %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_B62 = 0xb62,
+#endif
+#if PACKETVER >= 20160706
+/*20160706 to latest
+이 자리에 노점을 세우시겠습니까?
+Would you like to open a shop at this location?
+*/
+ MSG_ID_B63 = 0xb63,
+#endif
+#if PACKETVER >= 20160713
+/*20160713 to latest
+도람족은 해당 의상을 입을 수 없습니다.
+Doram race can't wear this clothes
+*/
+ MSG_ID_B64 = 0xb64,
+/*20160713 to 20160727
+구입한 물건이 로덱스로 배송되었습니다.
+20160803 to latest
+판매 노점에서 거래한 아이템이 로덱스로 배송되었습니다.
+Props open-air store sales will be traded in RODEX
+*/
+ MSG_ID_B65 = 0xb65,
+/*20160713 to latest
+30,000 z
+*/
+ MSG_ID_B66 = 0xb66,
+/*20160713 to latest
+말랑도 특산 통조림 100개
+Malangdo Special Can 100 pc
+*/
+ MSG_ID_B67 = 0xb67,
+#endif
+#if PACKETVER >= 20160720
+/*20160720 to latest
+무게가 80%를 초과하여 진행할 수 없습니다.
+Cannot carry anymore because weight limit over 80%
+*/
+ MSG_ID_B68 = 0xb68,
+/*20160720 to latest
+판매되지 못한 상품이 로덱스로 배송되었습니다.
+Unsold items are sent to RODEX
+*/
+ MSG_ID_B69 = 0xb69,
+#endif
+#if PACKETVER >= 20160727
+/*20160727 to latest
+장착 모습
+Preview
+*/
+ MSG_ID_B6A = 0xb6a,
+/*20160727 to latest
+길드마스터 위임
+Assign Guild Leader
+*/
+ MSG_ID_B6B = 0xb6b,
+/*20160727 to latest
+정말로 %s님께 길드마스터를 위임하시겠습니까? 위임 후 당신의 지위는 %s님과 지위가 바뀌게 됩니다.
+Are sure want to assign %s as guild leader? After assigned your position will become %s
+*/
+ MSG_ID_B6C = 0xb6c,
+/*20160727 to latest
+철회
+Cancel
+*/
+ MSG_ID_B6D = 0xb6d,
+/*20160727 to latest
+노점을 철수하시겠습니까?
+Do you want to close the shop?
+*/
+ MSG_ID_B6E = 0xb6e,
+/*20160727 to latest
+%02d일 %02d시간 %02d분 %02d초
+%02d day %02d hour %02d minute %02d second
+*/
+ MSG_ID_B6F = 0xb6f,
+/*20160727 to latest
+접속불가
+Unable to sign in
+*/
+ MSG_ID_B70 = 0xb70,
+/*20160727 to latest
+접속가능인원을 초과하여 접속이 불가능 합니다.
+Unable to sign in because the maximum number of sign-in is exceeded
+*/
+ MSG_ID_B71 = 0xb71,
+/*20160727 to latest
+노점을 설치할 위치를 선택해주세요.
+Please select a location for your shop
+*/
+ MSG_ID_B72 = 0xb72,
+/*20160727 to latest
+펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+Pet name will be changed to ^0000ff^0000ff %s^000000^000000, do you want to continue?
+*/
+ MSG_ID_B73 = 0xb73,
+#endif
+#if PACKETVER >= 20160803
+/*20160803 to 20160803
+판매 일시 :
+20160810 to latest
+거래 일시 :
+Trade date :
+*/
+ MSG_ID_B74 = 0xb74,
+/*20160803 to 20160803
+판매 아이템 :
+20160810 to latest
+거래 아이템 :
+Trade item :
+*/
+ MSG_ID_B75 = 0xb75,
+/*20160803 to 20160803
+판매 수량 :
+20160810 to latest
+거래 수량 :
+Trade quantity :
+*/
+ MSG_ID_B76 = 0xb76,
+/*20160803 to 20160803
+판매 단가 :
+20160810 to latest
+거래 단가 :
+Trade price :
+*/
+ MSG_ID_B77 = 0xb77,
+/*20160803 to 20160803
+판매 금액 :
+20160810 to latest
+거래 금액 :
+Total trade :
+*/
+ MSG_ID_B78 = 0xb78,
+/*20160803 to latest
+노점 판매 아이템
+Open vending sales agent
+*/
+ MSG_ID_B79 = 0xb79,
+/*20160803 to latest
+노점 구매 아이템
+Open vending purchase agent
+*/
+ MSG_ID_B7A = 0xb7a,
+/*20160803 to latest
+판매 노점 아르바이트 종료
+Close vending sales agent
+*/
+ MSG_ID_B7B = 0xb7b,
+/*20160803 to latest
+구매 노점 아르바이트 종료
+Close vending purchase agent
+*/
+ MSG_ID_B7C = 0xb7c,
+/*20160803 to latest
+남은 금액:
+Balance:
+*/
+ MSG_ID_B7D = 0xb7d,
+/*20160803 to latest
+아이템 리스트:
+Item list:
+*/
+ MSG_ID_B7E = 0xb7e,
+/*20160803 to latest
+노점 아르바이트생
+Vending agent
+*/
+ MSG_ID_B7F = 0xb7f,
+/*20160803 to latest
+반환 아이템:
+Returned item:
+*/
+ MSG_ID_B80 = 0xb80,
+/*20160803 to latest
+반환 수량:
+Returned quantity:
+*/
+ MSG_ID_B81 = 0xb81,
+/*20160803 to latest
+반환 일시:
+Returned date:
+*/
+ MSG_ID_B82 = 0xb82,
+/*20160803 to latest
+구매 노점에서 거래한 금액이 로덱스로 배송되었습니다
+Total trade will be sent to RODEX
+*/
+ MSG_ID_B83 = 0xb83,
+/*20160803 to latest
+사용할 수 없는 이름입니다.
+Name isn't available
+*/
+ MSG_ID_B84 = 0xb84,
+#endif
+#if PACKETVER >= 20160817
+/*20160817 to latest
+상품이 도착했습니다.
+Item has been delivered
+*/
+ MSG_ID_B85 = 0xb85,
+/*20160817 to latest
+구입해주셔서 감사합니다.
+Thank you for purchasing
+*/
+ MSG_ID_B86 = 0xb86,
+#endif
+#if PACKETVER >= 20160824
+/*20160824 to latest
+NPC에게 아이템을 판매하지 않습니다.
+Press again to unlock
+*/
+ MSG_ID_B87 = 0xb87,
+/*20160824 to latest
+아이템 판매 잠금
+Lock from NPC selling
+*/
+ MSG_ID_B88 = 0xb88,
+/*20160824 to latest
+근처에서 소환가능 위치를 찾을수 없습니다.
+There is no callable location nearby
+*/
+ MSG_ID_B89 = 0xb89,
+/*20160824 to latest
+전체 화면 캡쳐
+Capture full screens
+*/
+ MSG_ID_B8A = 0xb8a,
+/*20160824 to latest
+부분 화면 캡쳐
+Capture part of screen
+*/
+ MSG_ID_B8B = 0xb8b,
+/*20160824 to latest
+보내기
+Send
+*/
+ MSG_ID_B8C = 0xb8c,
+/*20160824 to latest
+가족 분과 담당자
+Family Affairs agent
+*/
+ MSG_ID_B8D = 0xb8d,
+/*20160824 to latest
+가족 사항 변동 안내
+Acknowledgement of family member registrations.
+*/
+ MSG_ID_B8E = 0xb8e,
+/*20160824 to latest
+안녕하십니까.
+
+금일 "%s"님과 "%s"님의 자녀인 "%s"님이 독립하여 단독 세대를 구성하였습니다.
+
+이에 서면으로 안내를 드립니다.
+
+가족 관계 확인을 원하시는 분은 프론테라 동사무소의 담당 직원에게 문의하시기 바랍니다.
+
+감사합니다.
+Dear whom it may concern.
+
+ Today, \"%s\" and \"%s\" 's son/daughter \"%s\" has fully separated and independent from your member of family.
+
+Hereat, we inform you in writing.
+
+Please contact to Prontera Family Affairs if you have any enquiries.
+
+Thank you.
+*/
+ MSG_ID_B8F = 0xb8f,
+#endif
+#if PACKETVER >= 20160831
+/*20160831 to latest
+장착
+Equip
+*/
+ MSG_ID_B90 = 0xb90,
+/*20160831 to latest
+이미지 없음
+No image
+*/
+ MSG_ID_B91 = 0xb91,
+#endif
+#if PACKETVER >= 20160907
+/*20160907 to 20160921
+%s은(는) 현재 호출을 차단한 상태입니다.
+20160928 to latest
+[%s]은(는) 현재 호출을 차단한 상태입니다.
+[%s] is blocking Call Massage.
+*/
+ MSG_ID_B92 = 0xb92,
+#endif
+#if PACKETVER >= 20160913
+/*20160913 to latest
+현재 공성전이 진행중이므로, 길드마스터를 위임 할 수 없습니다.
+Currently in WoE hours, unable to delegate Guild leader
+*/
+ MSG_ID_B93 = 0xb93,
+/*20160913 to latest
+현재 길드장 위임을 받은지 만 하루가 지나지 않아, 길드장을 위임할 수 없습니다.
+You have to wait for one day before delegating a new Guild leader
+*/
+ MSG_ID_B94 = 0xb94,
+/*20160913 to latest
+아이가 되면 전승을 할 수 없고 스텟의 제한이 있으며 HP와 SP가 줄어듭니다.
+그래도 괜찮습니까?
+When adopted, character will not able to transcend, maximum stats will be limited, MaxHP and MaxSP will be reduced.
+Are you sure you want to continue?
+*/
+ MSG_ID_B95 = 0xb95,
+/*20160913 to latest
+제련
+Refining
+*/
+ MSG_ID_B96 = 0xb96,
+/*20160913 to latest
+대장장이의 축복을 사용중입니다.
+Use Blacksmith's Blessing
+*/
+ MSG_ID_B97 = 0xb97,
+/*20160913 to latest
+제니가 부족합니다.
+Insufficient zeny
+*/
+ MSG_ID_B98 = 0xb98,
+/*20160913 to latest
+대장장이의 축복 개수가 부족합니다.
+Not enough Blacksmith's Blessing
+*/
+ MSG_ID_B99 = 0xb99,
+/*20160913 to latest
+해당 장비는 제련이 불가능합니다.
+This equipment can not be refined
+*/
+ MSG_ID_B9A = 0xb9a,
+/*20160913 to 20170621
+제련 성공!
+20170628 to latest
+제련 성공
+Upgrade success!
+*/
+ MSG_ID_B9B = 0xb9b,
+/*20160913 to 20170621
+제련 실패!
+20170628 to latest
+제련 실패
+Upgrade failed!
+*/
+ MSG_ID_B9C = 0xb9c,
+/*20160913 to latest
+돌아가기
+Back
+*/
+ MSG_ID_B9D = 0xb9d,
+/*20160913 to latest
+성공
+Success
+*/
+ MSG_ID_B9E = 0xb9e,
+/*20160913 to latest
+원래대로
+Return
+*/
+ MSG_ID_B9F = 0xb9f,
+#endif
+#if PACKETVER >= 20160921
+/*20160921 to latest
+씨와의
+With Mr/Miss
+*/
+ MSG_ID_BA0 = 0xba0,
+/*20160921 to latest
+호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+The Homunculus's name will be changed to^0000ff^0000ff %s^000000^000000, Are you sure?
+*/
+ MSG_ID_BA1 = 0xba1,
+#endif
+#if PACKETVER >= 20160928
+/*20160928 to latest
+호출이 허용된 상태입니다. (호출 기능 ON)
+Call function is ON
+*/
+ MSG_ID_BA2 = 0xba2,
+/*20160928 to latest
+호출이 차단된 상태입니다. (호출 기능 OFF)
+Call function is OFF
+*/
+ MSG_ID_BA3 = 0xba3,
+/*20160928 to latest
+호출 메시지 표시
+Display Call messages
+*/
+ MSG_ID_BA4 = 0xba4,
+/*20160928 to latest
+해당 캐릭터가 현재 노점 아이템을 사용 중이므로 삭제할 수 없습니다.
+This character is currently opening a shop and can't be deleted
+*/
+ MSG_ID_BA5 = 0xba5,
+/*20160928 to latest
+이미 동일한 노점 NPC가 설치 중입니다.
+The same vend shop NPC has been set up
+*/
+ MSG_ID_BA6 = 0xba6,
+/*20160928 to latest
+노점을 설치할 수 없는 위치입니다.
+Opening shop is not allowed on this location
+*/
+ MSG_ID_BA7 = 0xba7,
+/*20160928 to latest
+다른 캐릭터가 있는 위치에는 노점을 설치할 수 없습니다.
+Opening shop is not allowed when there is other character
+*/
+ MSG_ID_BA8 = 0xba8,
+#endif
+#if PACKETVER >= 20161005
+/*20161005 to latest
+펫 먹이주기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+Failed to feed pet, please close RODEX window
+*/
+ MSG_ID_BA9 = 0xba9,
+/*20161005 to latest
+장비 세트 설정
+Set item setting
+*/
+ MSG_ID_BAA = 0xbaa,
+/*20161005 to latest
+장착 하기
+Equip
+*/
+ MSG_ID_BAB = 0xbab,
+#endif
+#if PACKETVER >= 20161019
+/*20161019 to latest
+제련 실패시 장비가 사라집니다.
+Equipment will dissapear when refine fails
+*/
+ MSG_ID_BAC = 0xbac,
+/*20161019 to latest
+제련 실패시 장비의 제련도가 내려갑니다.
+Equipment's refine level will decreased when refine fails
+*/
+ MSG_ID_BAD = 0xbad,
+/*20161019 to latest
+제련 실패시 장비의 제련도가 내려가거나 사라질 수 있습니다.
+Equipment will dissapear or refine level will decreased when refine fails
+*/
+ MSG_ID_BAE = 0xbae,
+#endif
+#if PACKETVER >= 20161026
+/*20161026 to latest
+제련 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+You cannot use RODEX while refining. RODEX has closed.
+*/
+ MSG_ID_BAF = 0xbaf,
+/*20161026 to latest
+제련 중에는 로덱스를 사용할 수 없습니다.
+You cannot use RODEX while refining.
+*/
+ MSG_ID_BB0 = 0xbb0,
+/*20161026 to latest
+제련을 진행하려면 다른 창을 닫아주세요.
+Please close other windows to continue.
+*/
+ MSG_ID_BB1 = 0xbb1,
+/*20161026 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_ID_BB2 = 0xbb2,
+/*20161026 to latest
+오오라가 표시되지 않습니다 [오오라 OFF]
+Turn Off Aura [Auta OFF]
+*/
+ MSG_ID_BB3 = 0xbb3,
+/*20161026 to latest
+오오라가 Off 상태입니다. Off 를 해제하고 시도해 주세요
+Aura is turned off. Please turn it on and try again
+*/
+ MSG_ID_BB4 = 0xbb4,
+/*20161026 to latest
+스킬 발동시 최소 %d개의 탄알이 필요합니다.
+You need %d bullet(s) to activate the skill.
+*/
+ MSG_ID_BB5 = 0xbb5,
+/*20161026 to latest
+장비 세트를 변경하시겠습니까?
+Do you want to change the equipment set?
+*/
+ MSG_ID_BB6 = 0xbb6,
+/*20161026 to latest
+죽은 상태에서는 할 수 없습니다
+You can not do it while you are dead.
+*/
+ MSG_ID_BB7 = 0xbb7,
+/*20161026 to latest
+캐스팅 도중에는 할 수 없습니다
+You can not do it while casting
+*/
+ MSG_ID_BB8 = 0xbb8,
+/*20161026 to latest
+거래 도중에는 할 수 없습니다
+You can not do it while trading
+*/
+ MSG_ID_BB9 = 0xbb9,
+/*20161026 to latest
+노점 개설 도중에는 할 수 없습니다
+You can not do it while opening vendor
+*/
+ MSG_ID_BBA = 0xbba,
+/*20161026 to latest
+NPC 이용중에는 할 수 없습니다
+You can not do it while using NPC
+*/
+ MSG_ID_BBB = 0xbbb,
+/*20161026 to latest
+채팅방 이용중에는 할 수 없습니다
+You can not do it while using chatting room
+*/
+ MSG_ID_BBC = 0xbbc,
+/*20161026 to latest
+파티원 전원이 접속 상태가 아닙니다.
+Party members are not connected.
+*/
+ MSG_ID_BBD = 0xbbd,
+/*20161026 to latest
+스킬 발동시 최소 %d개의 화살이 필요합니다.
+You need %d arrow(s) to activate the skill.
+*/
+ MSG_ID_BBE = 0xbbe,
+#endif
+#if PACKETVER >= 20161102
+/*20161102 to latest
+아이템 정렬
+Align items
+*/
+ MSG_ID_BBF = 0xbbf,
+/*20161102 to latest
+아이템을 버리려면 장비 설정 창을 닫아주세요.
+Please close item setting window to dump item.
+*/
+ MSG_ID_BC0 = 0xbc0,
+#endif
+#if PACKETVER >= 20161109
+/*20161109 to latest
+교체 할 수 있는 아이템이 없습니다.
+There is no item to replace.
+*/
+ MSG_ID_BC1 = 0xbc1,
+/*20161109 to latest
+삭제된 캐릭터
+Deleted character
+*/
+ MSG_ID_BC2 = 0xbc2,
+/*20161109 to 20161109
+제련 중에는 은행을 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+20161116 to latest
+%Y.%m.%d
+*/
+ MSG_ID_BC3 = 0xbc3,
+/*20161109 to 20161109
+제련 중에는 은행을 사용할 수 없습니다.
+You can not use bank while refining.
+20161116 to latest
+접속일: %s
+Access date: %s
+*/
+ MSG_ID_BC4 = 0xbc4,
+#endif
+#if PACKETVER >= 20161116
+/*20161116 to latest
+제련 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+You can not use bank while refining. Bank has closed.
+*/
+ MSG_ID_BC5 = 0xbc5,
+/*20161116 to latest
+제련 중에는 은행을 사용할 수 없습니다.
+You can not use bank while refining.
+*/
+ MSG_ID_BC6 = 0xbc6,
+/*20161116 to latest
+장비 세트 설정 중인 아이템입니다.
+The item has bind to set equipment.
+*/
+ MSG_ID_BC7 = 0xbc7,
+#endif
+#if PACKETVER >= 20161123
+/*20161123 to latest
+인간
+Human
+*/
+ MSG_ID_BC8 = 0xbc8,
+/*20161123 to latest
+검사, 법사, 상인, 복사, 도둑, 궁수
+Swordman, Mage, Merchant, Acolyte, Thief, Archer
+*/
+ MSG_ID_BC9 = 0xbc9,
+/*20161123 to latest
+도람
+Doram
+*/
+ MSG_ID_BCA = 0xbca,
+/*20161123 to latest
+소환사
+Summoner
+*/
+ MSG_ID_BCB = 0xbcb,
+/*20161123 to latest
+미드가르드 대륙의 대표 종족. 무한한 잠재력과 뛰어난 적응력으로 문제 해결에 탁월한 것이 특징이다.
+Delegate race of Midgard. Very talented race to solve a problem with inifite potential and great adaptability.
+*/
+ MSG_ID_BCC = 0xbcc,
+/*20161123 to latest
+파-스타 대륙의 대표적인 종족 중 하나로, 선천적으로 호기심이 강하고 발랄한 성격을 지녔다.
+One of delegate race of Far-star continent with natural born curiosity and sparky character.
+*/
+ MSG_ID_BCD = 0xbcd,
+/*20161123 to latest
+소지 한계량이 70%를 초과하거나, 인벤토리에 10칸 이상의 여유 공간이 부족한 상태입니다.
+Weight limit has reached toover 70%. Or less then 10 invenrory space.
+*/
+ MSG_ID_BCE = 0xbce,
+/*20161123 to latest
+C
+EUR
+*/
+ MSG_ID_BCF = 0xbcf,
+/*20161123 to latest
+C
+EUR
+*/
+ MSG_ID_BD0 = 0xbd0,
+/*20161123 to latest
+다른 일을 하는 중입니다.
+Doing in other activity.
+*/
+ MSG_ID_BD1 = 0xbd1,
+/*20161123 to latest
+오버히트 리미트 : %d
+Overheat limit : %d
+*/
+ MSG_ID_BD2 = 0xbd2,
+#endif
+#if PACKETVER >= 20161130
+/*20161130 to latest
+메모리얼 던전 이용 중엔 초대 및 탈퇴가 되지 않습니다.
+You cannot invite or withdraw while in memorial dungeon.
+*/
+ MSG_ID_BD3 = 0xbd3,
+/*20161130 to latest
+비속어가 포함되어있습니다.
+다시 한번 확인해주세요.
+Expletive has detected.
+Please check again.
+*/
+ MSG_ID_BD4 = 0xbd4,
+#endif
+#if PACKETVER >= 20161207
+/*20161207 to latest
+아이디는 %d자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Please enter over %d characters. If you don't have user account, please click [Register] button on the bottom left.
+*/
+ MSG_ID_BD5 = 0xbd5,
+/*20161207 to latest
+비밀번호는 %d자 이상 입력해주세요.
+Please enter the password over %d characters.
+*/
+ MSG_ID_BD6 = 0xbd6,
+/*20161207 to latest
+진행중이던 작업을 종료후 다시 시도하세요.
+Please finish your current work and try it again.
+*/
+ MSG_ID_BD7 = 0xbd7,
+/*20161207 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + %s서버 %.1f%%)
+%.1f%% (Internet-Cafe %.1f%% + TPLUS %.1f%% + %sServer %.1f%%)
+*/
+ MSG_ID_BD8 = 0xbd8,
+/*20161207 to latest
+아이템을 등록할 수 없습니다
+The item cannot be registered.
+*/
+ MSG_ID_BD9 = 0xbd9,
+#endif
+#if PACKETVER >= 20161214
+/*20161214 to latest
+/100
+/300
+*/
+ MSG_ID_BDA = 0xbda,
+/*20161214 to latest
+/2000
+/4000
+*/
+ MSG_ID_BDB = 0xbdb,
+/*20161214 to latest
+https://member.gnjoy.com.tw/mRO_SecPwd.aspx
+*/
+ MSG_ID_BDC = 0xbdc,
+/*20161214 to latest
+등록할 emblem이 존재하지 않습니다. emblem 폴더에 파일을 넣고 시도해 주세요
+The emblem you want to register does not exist. Insert it in the emblem file and try again
+*/
+ MSG_ID_BDD = 0xbdd,
+/*20161214 to 20170315
+#라그나로크 #Ragnarok
+20170322 to latest
+라그나로크
+Ragnarok Ragnarok
+*/
+ MSG_ID_BDE = 0xbde,
+/*20161214 to 20161214
+스크린샷에 자신 이외의 캐리터명이 표시되는 경우나 채팅창에 자신 이외의 캐릭터 대화가 표시되는 경우, 해당 사용자에게 반드시 양해를 구한 후 사용 해 주시기 바랍니다.
+20161221 to latest
+스크린샷에 자신 이외의 캐릭터명이 표시되는 경우나 채팅창에 자신 이외의 캐릭터 대화가 표시되는 경우, 해당 사용자에게 반드시 양해를 구한 후 사용 해 주시기 바랍니다.
+If your screenshot or chat box includes other users besides yourself, first ask permission from the other users before using it.
+*/
+ MSG_ID_BDF = 0xbdf,
+#endif
+#if PACKETVER >= 20161221
+/*20161221 to latest
+현재 상태에선 장비를 교체할 수 없습니다
+You cannot change equipment in current condition
+*/
+ MSG_ID_BE0 = 0xbe0,
+/*20161221 to latest
+해당 유저의 이름을 가져오고 있습니다
+Getting the user's name
+*/
+ MSG_ID_BE1 = 0xbe1,
+/*20161221 to latest
+해당 메시지는 사용 할 수 없는 내용을 포함하고 있습니다.
+This message includes contents you are not able to use.
+*/
+ MSG_ID_BE2 = 0xbe2,
+/*20161221 to latest
+아이템 구입에 실패하였습니다.
+Failed to purchase item.
+*/
+ MSG_ID_BE3 = 0xbe3,
+/*20161221 to latest
+신분증번호 하위 7자리가 일치하지 않습니다.
+The lower numbers of the identification number does not match.
+*/
+ MSG_ID_BE4 = 0xbe4,
+#endif
+#if PACKETVER >= 20161228
+/*20161228 to latest
+닫기
+Close
+*/
+ MSG_ID_BE5 = 0xbe5,
+/*20161228 to latest
+규칙
+Rule
+*/
+ MSG_ID_BE6 = 0xbe6,
+/*20161228 to latest
+1회 구매
+Purchase 1x
+*/
+ MSG_ID_BE7 = 0xbe7,
+/*20161228 to latest
+10회 구매
+Purchase 10x
+*/
+ MSG_ID_BE8 = 0xbe8,
+/*20161228 to latest
+100회 구매
+Purchase 100x
+*/
+ MSG_ID_BE9 = 0xbe9,
+/*20161228 to latest
+1등 당첨
+Win 1st prize
+*/
+ MSG_ID_BEA = 0xbea,
+/*20161228 to latest
+2등 당첨
+Win 2nd prize
+*/
+ MSG_ID_BEB = 0xbeb,
+/*20161228 to latest
+3등 당첨
+Win 3rd prize
+*/
+ MSG_ID_BEC = 0xbec,
+/*20161228 to 20170111
+복권 구매 금액
+Lottery purchase amount
+20170118 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BED = 0xbed,
+/*20161228 to 20170111
+참여 캐릭터
+Participating character
+20170118 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BEE = 0xbee,
+/*20161228 to latest
+제니 로또 당첨자
+Zeny Lottery winner
+*/
+ MSG_ID_BEF = 0xbef,
+/*20161228 to 20170111
+복권 진행일
+20170118 to latest
+복권 구매 금액
+Lottery purchase amount
+*/
+ MSG_ID_BF0 = 0xbf0,
+/*20161228 to latest
+참여 캐릭터
+Participating character
+*/
+ MSG_ID_BF1 = 0xbf1,
+/*20161228 to latest
+1등
+1st Price
+*/
+ MSG_ID_BF2 = 0xbf2,
+/*20161228 to latest
+2등
+2nd Price
+*/
+ MSG_ID_BF3 = 0xbf3,
+/*20161228 to latest
+3등
+3rd Price
+*/
+ MSG_ID_BF4 = 0xbf4,
+/*20161228 to latest
+구매 보상 아이템
+Purchase Reward Item
+*/
+ MSG_ID_BF5 = 0xbf5,
+/*20161228 to latest
+^1a1a1a복권 ^b%d개^/b를
+^4435b2%dZeny^1a1a1a로
+구매하시겠습니까?
+^1a1a1a Do you want to purchase ^b%d lottery tickets for
+^4435b2%dZeny^1a1a1a?
+*/
+ MSG_ID_BF6 = 0xbf6,
+/*20161228 to latest
+복권을 성공적으로 구매하였습니다.
+You have successfully purchased the lottery ticket.
+*/
+ MSG_ID_BF7 = 0xbf7,
+/*20161228 to latest
+소지 제니가 부족하여 복권을 구매 할 수 없습니다.
+Not enough Zeny to purchase lottey ticket.
+*/
+ MSG_ID_BF8 = 0xbf8,
+/*20161228 to latest
+최대 복권 구매 횟수는 1000회를 초과 할 수 없습니다.
+You are only able to purchase the tickets upto 1000 times.
+*/
+ MSG_ID_BF9 = 0xbf9,
+/*20161228 to latest
+예
+Yes
+*/
+ MSG_ID_BFA = 0xbfa,
+/*20161228 to latest
+아니요
+No
+*/
+ MSG_ID_BFB = 0xbfb,
+/*20161228 to latest
+HP
+*/
+ MSG_ID_BFC = 0xbfc,
+/*20161228 to latest
+SP
+*/
+ MSG_ID_BFD = 0xbfd,
+/*20161228 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFE = 0xbfe,
+/*20161228 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFF = 0xbff,
+/*20161228 to latest
+Exp
+*/
+ MSG_ID_C00 = 0xc00,
+/*20161228 to latest
+ all on
+*/
+ MSG_ID_C01 = 0xc01,
+/*20161228 to latest
+Play Replay Flie
+Start replay
+*/
+ MSG_ID_C02 = 0xc02,
+/*20161228 to latest
+P
+*/
+ MSG_ID_C03 = 0xc03,
+/*20161228 to latest
+Total
+*/
+ MSG_ID_C04 = 0xc04,
+/*20161228 to latest
+Basicinfo
+*/
+ MSG_ID_C05 = 0xc05,
+/*20161228 to latest
+Equip
+Equipment
+*/
+ MSG_ID_C06 = 0xc06,
+/*20161228 to latest
+Item
+Items
+*/
+ MSG_ID_C07 = 0xc07,
+/*20161228 to latest
+Skill
+Skills
+*/
+ MSG_ID_C08 = 0xc08,
+/*20161228 to latest
+Guild
+*/
+ MSG_ID_C09 = 0xc09,
+/*20161228 to latest
+Party
+*/
+ MSG_ID_C0A = 0xc0a,
+/*20161228 to latest
+Chatting
+Chat
+*/
+ MSG_ID_C0B = 0xc0b,
+/*20161228 to latest
+Shortcut
+Hotkeys
+*/
+ MSG_ID_C0C = 0xc0c,
+/*20161228 to latest
+Status
+*/
+ MSG_ID_C0D = 0xc0d,
+/*20161228 to latest
+ALL
+*/
+ MSG_ID_C0E = 0xc0e,
+/*20161228 to latest
+User Defined File Name
+Custom file name
+*/
+ MSG_ID_C0F = 0xc0f,
+/*20161228 to latest
+Repeated File Check
+Check file
+*/
+ MSG_ID_C10 = 0xc10,
+/*20161228 to latest
+on
+*/
+ MSG_ID_C11 = 0xc11,
+/*20161228 to latest
+<Basic Skin>
+<Basic>
+*/
+ MSG_ID_C12 = 0xc12,
+/*20161228 to latest
+Select Skin
+Choose skin
+*/
+ MSG_ID_C13 = 0xc13,
+#endif
+#if PACKETVER >= 20170111
+/*20170111 to latest
+현재 복권에 참여 중이라 삭제할 수 없습니다
+You cannot delete it because you are currently participating in the lottery
+*/
+ MSG_ID_C14 = 0xc14,
+/*20170111 to latest
+/achievement
+*/
+ MSG_ID_C15 = 0xc15,
+/*20170111 to latest
+제니 복권
+Zeny Lottery ticket
+*/
+ MSG_ID_C16 = 0xc16,
+/*20170111 to latest
+제니 복권 %d등 당첨 보상
+Zenyy Lottery %dprize reward
+*/
+ MSG_ID_C17 = 0xc17,
+/*20170111 to latest
+%d등 당첨 보상: %s
+%dprize reward: %s
+*/
+ MSG_ID_C18 = 0xc18,
+/*20170111 to latest
+제니 복권 누적 구매 보상
+Zeny Lottery Cumulative purchase reward
+*/
+ MSG_ID_C19 = 0xc19,
+/*20170111 to latest
+누적 %d회 보상: %s
+Cumulative %d times reward: %s
+*/
+ MSG_ID_C1A = 0xc1a,
+/*20170111 to latest
+제니 복권 구매 환불
+Zeny Lottery Refund
+*/
+ MSG_ID_C1B = 0xc1b,
+/*20170111 to 20170111
+환불 금액: %d Zeny
+환불 사유: 서버 내 복권 추첨 달성 실패
+20170118 to latest
+환불 금액: %d Zeny
+환불 사유: 서버 내 복권 추첨 달성 실패
+Refund amount: %d Zeny
+Reason for Refund: Failed to draw lottery in the server
+*/
+ MSG_ID_C1C = 0xc1c,
+/*20170111 to latest
+미니 파티창 추가
+Add Mini Party Chat
+*/
+ MSG_ID_C1D = 0xc1d,
+/*20170111 to latest
+미니 파티창 삭제
+Delete Mini Party Chat
+*/
+ MSG_ID_C1E = 0xc1e,
+#endif
+#if PACKETVER >= 20170118
+/*20170118 to latest
+복권 추첨이 모두 종료 되었습니다! 당첨자를 확인해주세요
+The lottery draw had ended! Check the winner!
+*/
+ MSG_ID_C1F = 0xc1f,
+/*20170118 to latest
+%d월 %d일
+%dMonth %dDay
+*/
+ MSG_ID_C20 = 0xc20,
+/*20170118 to latest
+다음 등급까지
+Till the next grade
+*/
+ MSG_ID_C21 = 0xc21,
+/*20170118 to latest
+전체
+All
+*/
+ MSG_ID_C22 = 0xc22,
+/*20170118 to latest
+미완료
+Incomplete
+*/
+ MSG_ID_C23 = 0xc23,
+/*20170118 to latest
+(달성!)
+(Accomplished!)
+*/
+ MSG_ID_C24 = 0xc24,
+/*20170118 to latest
+(미달성)
+(Not Accomplished)
+*/
+ MSG_ID_C25 = 0xc25,
+#endif
+#if PACKETVER >= 20170208
+/*20170208 to latest
+장비 교체
+Change equipment
+*/
+ MSG_ID_C26 = 0xc26,
+/*20170208 to latest
+CHANGE
+*/
+ MSG_ID_C27 = 0xc27,
+/*20170208 to latest
+힘 파라메터
+ ^cc0000근접 물리 공격력^ffffff, 소지무게
+Power Parameter
+ ^cc0000Melee PhysicalAttack^ffffff, Carrying Weight
+*/
+ MSG_ID_C28 = 0xc28,
+/*20170208 to latest
+민첩성 파라메터
+^cc0000공격 속도^ffffff, 회피율, 물리 방어력
+Agility Parameter
+^cc0000Attack Speed^ffffff, Dodge, Physical Defense
+*/
+ MSG_ID_C29 = 0xc29,
+/*20170208 to latest
+체력 파라메터
+^cc0000최대 체력^ffffff, 물리 방어력, 마법 방어력
+HP Parameter
+^cc0000Max HP^ffffff, Physical Defense, Magic Defense
+*/
+ MSG_ID_C2A = 0xc2a,
+/*20170208 to latest
+지력 파라메터
+^cc0000마법 공격력^ffffff, 캐스팅 시간, 마법 방어력
+Intellect Parameter
+^cc0000Magic Attack^ffffff, Casting Time, Magic Defense
+*/
+ MSG_ID_C2B = 0xc2b,
+/*20170208 to latest
+손재주 파라메터
+^cc0000원거리 물리 공격력^ffffff, 명중률, 캐스팅 시간, 마법 공격력
+Handcraft Parameter
+^cc0000Long Range Physical Attack^ffffff, Accuracy, Casting Time, Magic Attack
+*/
+ MSG_ID_C2C = 0xc2c,
+/*20170208 to latest
+운 파라메터
+^cc0000치명타율^ffffff, 명중률, 물리공격력, 마법공격력, 회피율
+Moon Parameter
+^cc0000Critical Rate^ffffff, Accuracy, Physical Attack, Magic Attack, Dodge
+*/
+ MSG_ID_C2D = 0xc2d,
+/*20170208 to latest
+물리 공격력
+Physical Attack
+*/
+ MSG_ID_C2E = 0xc2e,
+/*20170208 to latest
+물리 방어력
+Physical Defense
+*/
+ MSG_ID_C2F = 0xc2f,
+/*20170208 to latest
+명중률
+Accuracy
+*/
+ MSG_ID_C30 = 0xc30,
+/*20170208 to latest
+치명타율
+Critical Rate
+*/
+ MSG_ID_C31 = 0xc31,
+/*20170208 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_ID_C32 = 0xc32,
+/*20170208 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_ID_C33 = 0xc33,
+/*20170208 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_ID_C34 = 0xc34,
+/*20170208 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_ID_C35 = 0xc35,
+/*20170208 to latest
+회피율
+Dodge
+*/
+ MSG_ID_C36 = 0xc36,
+/*20170208 to latest
+공격 속도
+Attack Speed
+*/
+ MSG_ID_C37 = 0xc37,
+#endif
+#if PACKETVER >= 20170215
+/*20170215 to latest
+단축키 안내
+Shortcut
+*/
+ MSG_ID_C38 = 0xc38,
+/*20170215 to latest
+옵션
+Option
+*/
+ MSG_ID_C39 = 0xc39,
+/*20170215 to latest
+스킬 단축키 (F1 ~ F9)
+Skill Shortcut Key (F1 ~ F9)
+*/
+ MSG_ID_C3A = 0xc3a,
+/*20170215 to latest
+이미지 캡쳐
+Capture Image
+*/
+ MSG_ID_C3B = 0xc3b,
+/*20170215 to latest
+확대
+Zoom In
+*/
+ MSG_ID_C3C = 0xc3c,
+/*20170215 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_C3D = 0xc3d,
+/*20170215 to latest
+길드
+Guild
+*/
+ MSG_ID_C3E = 0xc3e,
+/*20170215 to latest
+은행
+Bank
+*/
+ MSG_ID_C3F = 0xc3f,
+/*20170215 to latest
+우편
+Mail
+*/
+ MSG_ID_C40 = 0xc40,
+/*20170215 to latest
+캐시 상점
+Cash Shop
+*/
+ MSG_ID_C41 = 0xc41,
+/*20170215 to latest
+앉기
+Sit
+*/
+ MSG_ID_C42 = 0xc42,
+/*20170215 to latest
+이동
+Move
+*/
+ MSG_ID_C43 = 0xc43,
+/*20170215 to latest
+회전
+Rotate
+*/
+ MSG_ID_C44 = 0xc44,
+/*20170215 to latest
+파티장은 파티장을 다른 파티원에게 위임 후 탈퇴 가능합니다.
+The Party Leader can be dropped out only after another party member becomes a Party Leader.
+*/
+ MSG_ID_C45 = 0xc45,
+/*20170215 to latest
+이 동영상을 그만 보시겠습니까?
+Do you want to stop viewing this video?
+*/
+ MSG_ID_C46 = 0xc46,
+/*20170215 to latest
+ 장비가 장비 교체 창에 장착 되었습니다.
+ gear has been equipped in the gear equipment pop-up.
+*/
+ MSG_ID_C47 = 0xc47,
+/*20170215 to latest
+ 장비가 장비 교체 창에서 해제 되었습니다.
+ gear has been removed in the gear equipment pop-up.
+*/
+ MSG_ID_C48 = 0xc48,
+#endif
+#if PACKETVER >= 20170222
+/*20170222 to latest
+현재가 마지막 라인입니다.
+This is the last line.
+*/
+ MSG_ID_C49 = 0xc49,
+/*20170222 to latest
+%.1f%% ( 기본 100%% + 프리미엄 %.1f%%+ %s서버 %.1f%% )
+%.1f%% ( Base 100%% + Premium %.1f%%+ %sServer %.1f%% )
+*/
+ MSG_ID_C4A = 0xc4a,
+#endif
+#if PACKETVER >= 20170228
+/*20170228 to latest
+한자
+Chinese character
+*/
+ MSG_ID_C4B = 0xc4b,
+/*20170228 to latest
+단축키 설정
+Shortcut Settings
+*/
+ MSG_ID_C4C = 0xc4c,
+#endif
+#if PACKETVER >= 20170308
+/*20170308 to latest
+당신의 정액제 기간은 %s에 종료됩니다.
+Your subscription will be ended on%s.
+*/
+ MSG_ID_C4D = 0xc4d,
+/*20170308 to latest
+리플레이 파일을 찾지 못하였습니다.
+Cannot find the replay file.
+*/
+ MSG_ID_C4E = 0xc4e,
+/*20170308 to 20170801
+신발
+Head
+20170809 to latest
+의상
+Shoes
+*/
+ MSG_ID_C4F = 0xc4f,
+/*20170308 to 20170801
+머리
+Costume
+20170809 to latest
+신발
+Head
+*/
+ MSG_ID_C50 = 0xc50,
+/*20170308 to latest
+갑옷
+Armor
+*/
+ MSG_ID_C51 = 0xc51,
+/*20170308 to latest
+어깨
+Shoulders
+*/
+ MSG_ID_C52 = 0xc52,
+/*20170308 to latest
+악세
+Accessory
+*/
+ MSG_ID_C53 = 0xc53,
+/*20170308 to 20170801
+의상
+Shoes
+20170809 to latest
+머리
+Costume
+*/
+ MSG_ID_C54 = 0xc54,
+/*20170308 to latest
+차순정렬
+Sort Order
+*/
+ MSG_ID_C55 = 0xc55,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+일반 장비
+Normal Gear
+*/
+ MSG_ID_C56 = 0xc56,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+특수 장비
+Special Gear
+*/
+ MSG_ID_C57 = 0xc57,
+/*20170308 to 20170308
+
+Current admission application state.
+20170315 to latest
+칭호
+Style
+*/
+ MSG_ID_C58 = 0xc58,
+#endif
+#if PACKETVER >= 20170315
+/*20170315 to latest
+/quake : 화면 흔들림 효과 On/Off
+/quake : Screen Shaking Effect On/Off
+*/
+ MSG_ID_C59 = 0xc59,
+/*20170315 to latest
+/aura2 : 오오라를 완전히 Off 시킬 수 있습니다 On Off
+/aura2 : You can completely turn off the aurora On/Off
+*/
+ MSG_ID_C5A = 0xc5a,
+/*20170315 to latest
+기본 설정
+Default Settings
+*/
+ MSG_ID_C5B = 0xc5b,
+/*20170315 to latest
+고급 설정
+Advanced Settings
+*/
+ MSG_ID_C5C = 0xc5c,
+/*20170315 to latest
+기본설정값이 적용됩니다.
+The Default Settings will be applied.
+*/
+ MSG_ID_C5D = 0xc5d,
+/*20170315 to latest
+기본 설정값이 적용됩니다. 동의하십니까?
+The Default Settings will be applied. Do you agree?
+*/
+ MSG_ID_C5E = 0xc5e,
+/*20170315 to latest
+설정값이 적용됩니다. 동의하십니까?
+The settings will be applied. Do you agree?
+*/
+ MSG_ID_C5F = 0xc5f,
+/*20170315 to latest
+설정값을 적용하려면 재시작이 필요합니다. 동의하십니까?
+Need to restart to apply the settings. Do you agree?
+*/
+ MSG_ID_C60 = 0xc60,
+/*20170315 to latest
+안개
+Fog
+*/
+ MSG_ID_C61 = 0xc61,
+/*20170315 to latest
+오오라 간략화
+Simplified aurora
+*/
+ MSG_ID_C62 = 0xc62,
+/*20170315 to latest
+오오라켜기
+Turn on aurora
+*/
+ MSG_ID_C63 = 0xc63,
+/*20170315 to latest
+이펙트 표시
+Show Effect
+*/
+ MSG_ID_C64 = 0xc64,
+/*20170315 to latest
+음영 표시
+Show Shadows
+*/
+ MSG_ID_C65 = 0xc65,
+/*20170315 to latest
+No Shift
+*/
+ MSG_ID_C66 = 0xc66,
+/*20170315 to latest
+하드웨어 T&L 가속기능을 선택합니다
+Select Hardware T&L Acceleration Function
+*/
+ MSG_ID_C67 = 0xc67,
+/*20170315 to latest
+게임의 해상도를 선택합니다
+Select Game Resolution
+*/
+ MSG_ID_C68 = 0xc68,
+/*20170315 to latest
+전체화면 사용
+Use full screen
+*/
+ MSG_ID_C69 = 0xc69,
+/*20170315 to latest
+마우스 고정
+Fix mouse
+*/
+ MSG_ID_C6A = 0xc6a,
+/*20170315 to latest
+이펙트 설정
+Effect Settings
+*/
+ MSG_ID_C6B = 0xc6b,
+/*20170315 to latest
+Control 설정
+Control Settings
+*/
+ MSG_ID_C6C = 0xc6c,
+/*20170315 to latest
+그래픽 장치 설정
+Graphic Device Settings
+*/
+ MSG_ID_C6D = 0xc6d,
+/*20170315 to latest
+그래픽 해상도 설정
+Graphic Resolution Settings
+*/
+ MSG_ID_C6E = 0xc6e,
+/*20170315 to latest
+전체 화면 유무 설정
+Full Screen Settings
+*/
+ MSG_ID_C6F = 0xc6f,
+/*20170315 to latest
+마우스 고정 여부 설정
+Fix mouse Settings
+*/
+ MSG_ID_C70 = 0xc70,
+/*20170315 to latest
+수수료 :
+Commission :
+*/
+ MSG_ID_C71 = 0xc71,
+/*20170315 to latest
+수수료 총액 :
+Total commission amount :
+*/
+ MSG_ID_C72 = 0xc72,
+/*20170315 to latest
+수신인 설정
+Select receiver
+*/
+ MSG_ID_C73 = 0xc73,
+/*20170315 to latest
+수신그룹 설정
+Select receiving group
+*/
+ MSG_ID_C74 = 0xc74,
+/*20170315 to latest
+크기 변경(F10)
+Change size(F10)
+*/
+ MSG_ID_C75 = 0xc75,
+/*20170315 to latest
+메일함을 불러오는 중 입니다.
+불필요한 메일은 ^c92114삭제^000000해 주세요~!!
+Loading the mailbox.
+^c92114Delete^000000unnecessary emails!!
+*/
+ MSG_ID_C76 = 0xc76,
+/*20170315 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_C77 = 0xc77,
+/*20170315 to latest
+제목
+Title
+*/
+ MSG_ID_C78 = 0xc78,
+/*20170315 to latest
+보낸이
+Sender
+*/
+ MSG_ID_C79 = 0xc79,
+#endif
+#if PACKETVER >= 20170322
+/*20170322 to latest
+라그나로크 클라이언트와 동시에 실행이 불가능 합니다. setup을 종료합니다
+*/
+ MSG_ID_C7A = 0xc7a,
+/*20170322 to latest
+추가 기능 설정
+*/
+ MSG_ID_C7B = 0xc7b,
+/*20170322 to latest
+This account does not exist.
+*/
+ MSG_ID_C7C = 0xc7c,
+/*20170322 to latest
+Passwords do not match.
+*/
+ MSG_ID_C7D = 0xc7d,
+/*20170322 to latest
+Failed to pass IP authentication
+*/
+ MSG_ID_C7E = 0xc7e,
+/*20170322 to latest
+No identification number, supplement your registration information
+*/
+ MSG_ID_C7F = 0xc7f,
+/*20170322 to latest
+Account block
+*/
+ MSG_ID_C80 = 0xc80,
+/*20170322 to latest
+System error
+*/
+ MSG_ID_C81 = 0xc81,
+/*20170322 to latest
+unknown error found.
+*/
+ MSG_ID_C82 = 0xc82,
+#endif
+#if PACKETVER >= 20170329
+/*20170329 to latest
+길안내 아이콘 설정
+*/
+ MSG_ID_C83 = 0xc83,
+/*20170329 to latest
+길 안내 정보 UI
+*/
+ MSG_ID_C84 = 0xc84,
+/*20170329 to latest
+길 안내 정보 열기
+*/
+ MSG_ID_C85 = 0xc85,
+/*20170329 to latest
+현재 위치 공유
+*/
+ MSG_ID_C86 = 0xc86,
+/*20170329 to latest
+검색결과[0]
+*/
+ MSG_ID_C87 = 0xc87,
+/*20170329 to latest
+검색&안내
+*/
+ MSG_ID_C88 = 0xc88,
+/*20170329 to 20170329
+위치 값은 음수 값이 들어 올 수 없습니다.
+20170405 to latest
+위치가 올바르지 않습니다.
+*/
+ MSG_ID_C89 = 0xc89,
+/*20170329 to latest
+검색결과[%d]
+*/
+ MSG_ID_C8A = 0xc8a,
+/*20170329 to latest
+길안내 표시를 위한 아이콘 설정
+*/
+ MSG_ID_C8B = 0xc8b,
+/*20170329 to latest
+길 찾기에 zeny 허용
+*/
+ MSG_ID_C8C = 0xc8c,
+/*20170329 to latest
+내비게이션 도킹 해제
+*/
+ MSG_ID_C8D = 0xc8d,
+/*20170329 to latest
+활성화 하지 않은 계정입니다.
+*/
+ MSG_ID_C8E = 0xc8e,
+#endif
+#if PACKETVER >= 20170405
+/*20170405 to latest
+클릭한 위치가 채팅창에 공유 됩니다.
+*/
+ MSG_ID_C8F = 0xc8f,
+/*20170405 to latest
+4. Service 항목을 선택하면 Zeny&비공정 이용을 고려하여 안내 한다.
+*/
+ MSG_ID_C90 = 0xc90,
+/*20170405 to latest
+5. [<-] 버튼 : 길안내 모드 <-> 검색 모드를 바꾸거나
+*/
+ MSG_ID_C91 = 0xc91,
+/*20170405 to latest
+공유하기 모드 -> 서치 모드로 돌아갈때 사용 된다.
+*/
+ MSG_ID_C92 = 0xc92,
+/*20170405 to latest
+경험치 %lld 얻음
+*/
+ MSG_ID_C93 = 0xc93,
+/*20170405 to latest
+'%lld'의 경험치를
+*/
+ MSG_ID_C94 = 0xc94,
+/*20170405 to 20170517
+^b- 노점 수수료 안내^/b
+노점 설정 가격에 따라 일정 비율의 수수료가 부가됩니다.
+
+ ^b> 수수료 비율^/b
+각 금액에 따른 수수료의 비율은 아래와 같습니다.
+
+0 z ~ 10,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,001 z ~ 100,000 z
+ = 수수료율 : ^1567fe2%^000000
+100,001 z ~ 1,000,000 z
+ = 수수료율 : ^1567fe4%^000000
+1,000,001 z ~ 10,000,000 z
+ = 수수료율 : ^1567fe6%^000000
+10,000,001 z ~ 100,000,000 z
+ = 수수료율 : ^1567fe8%^000000
+100,000,001 z 이상
+ = 수수료율 : ^1567fe10%^000000
+20170524 to latest
+^b- 노점 수수료 안내^/b
+노점 설정 가격에 따라 일정 비율의 수수료가 부가됩니다.
+
+ ^b> 수수료 비율^/b
+각 금액에 따른 수수료의 비율은 아래와 같습니다.
+
+0 z ~ 10,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,001 z ~ 100,000 z
+ = 수수료율 : ^1567fe0%^000000
+100,001 z ~ 1,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+1,000,001 z ~ 10,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,000,001 z ~ 100,000,000 z
+ = 수수료율 : ^1567fe5%^000000
+100,000,001 z 이상
+ = 수수료율 : ^1567fe5%^000000
+*/
+ MSG_ID_C95 = 0xc95,
+/*20170405 to latest
+실거래가 :
+*/
+ MSG_ID_C96 = 0xc96,
+/*20170405 to latest
+※ 아이템 판매시, 실거래가만큼 제니를 획득합니다.
+*/
+ MSG_ID_C97 = 0xc97,
+/*20170405 to latest
+※ 아이템 구매시, 실거래가만큼 제니가 차감됩니다.
+*/
+ MSG_ID_C98 = 0xc98,
+/*20170405 to latest
+채팅방 개설
+*/
+ MSG_ID_C99 = 0xc99,
+#endif
+#if PACKETVER >= 20170412
+/*20170412 to latest
+해당 캐릭터는 파티가입이 가능하지 않은 레벨입니다.
+*/
+ MSG_ID_C9A = 0xc9a,
+/*20170412 to latest
+'%lld'의 잡경험치를
+*/
+ MSG_ID_C9B = 0xc9b,
+/*20170412 to latest
+잡경험치 %lld 얻음
+*/
+ MSG_ID_C9C = 0xc9c,
+#endif
+#if PACKETVER >= 20170419
+/*20170419 to latest
+현재위치(대로)에는 노점을 개설할 수 없습니다.
+*/
+ MSG_ID_C9D = 0xc9d,
+#endif
+#if PACKETVER >= 20170426
+/*20170426 to latest
+초 후 가능합니다.
+*/
+ MSG_ID_C9E = 0xc9e,
+#endif
+#if PACKETVER >= 20170517
+/*20170517 to latest
+파티원
+*/
+ MSG_ID_C9F = 0xc9f,
+/*20170517 to latest
+SNS 전송실패(%d)
+*/
+ MSG_ID_CA0 = 0xca0,
+/*20170517 to latest
+SNS 서버 연결실패
+*/
+ MSG_ID_CA1 = 0xca1,
+/*20170517 to latest
+SNS 로그인 후 사용 가능합니다.
+*/
+ MSG_ID_CA2 = 0xca2,
+/*20170517 to latest
+접속 할 수 있는 주소가 존재하지 않습니다.
+*/
+ MSG_ID_CA3 = 0xca3,
+#endif
+#if PACKETVER >= 20170531
+/*20170531 to latest
+미니파티창이 겹쳐져 있어 사용하실 수 없습니다.
+*/
+ MSG_ID_CA4 = 0xca4,
+/*20170531 to latest
+나의 판매노점
+*/
+ MSG_ID_CA5 = 0xca5,
+#endif
+#if PACKETVER >= 20170614
+/*20170614 to latest
+BOX
+*/
+ MSG_ID_CA6 = 0xca6,
+/*20170614 to latest
+팁박스
+*/
+ MSG_ID_CA7 = 0xca7,
+#endif
+#if PACKETVER >= 20170621
+/*20170621 to latest
+트윗을 성공했습니다.
+*/
+ MSG_ID_CA8 = 0xca8,
+#endif
+#if PACKETVER >= 20170628
+/*20170628 to latest
+다시하기
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CA9 = 0xca9,
+/*20170628 to 20170809
+제련재료가 변경되어 다시하기가 비활성화 되었습니다.
+20170816 to latest
+다시하기가 비활성화되었습니다. 제련 재료를 다시 선택해주세요.
+*/
+ MSG_ID_CAA = 0xcaa,
+/*20170628 to latest
+제련석이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAB = 0xcab,
+/*20170628 to latest
+제니가 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAC = 0xcac,
+/*20170628 to latest
+대장장이의 축복이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAD = 0xcad,
+/*20170628 to latest
+아이템이 파괴되었습니다.
+*/
+ MSG_ID_CAE = 0xcae,
+/*20170628 to latest
+모든 스테이터스가 감소되었습니다.
+*/
+ MSG_ID_CAF = 0xcaf,
+/*20170628 to latest
+모든 스테이터스 감소 효과가 해제되었습니다.
+*/
+ MSG_ID_CB0 = 0xcb0,
+/*20170628 to latest
+OTP 비밀번호는 8자리 입니다.
+*/
+ MSG_ID_CB1 = 0xcb1,
+#endif
+#if PACKETVER >= 20170705
+/*20170705 to latest
+통합계정
+*/
+ MSG_ID_CB2 = 0xcb2,
+/*20170705 to latest
+라그나로크
+*/
+ MSG_ID_CB3 = 0xcb3,
+/*20170705 to latest
+서비스 점검 중입니다.
+*/
+ MSG_ID_CB4 = 0xcb4,
+/*20170705 to latest
+검색어를 입력해주세요
+*/
+ MSG_ID_CB5 = 0xcb5,
+/*20170705 to latest
+MOTP
+*/
+ MSG_ID_CB6 = 0xcb6,
+/*20170705 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_CB7 = 0xcb7,
+/*20170705 to latest
+휴대폰에 다운받은 GNJOY MOTP를 실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_CB8 = 0xcb8,
+#endif
+#if PACKETVER >= 20170712
+/*20170712 to latest
+파티장을 위임할 파티원이 존재하지 않습니다. 파티를 해산하시겠습니까?
+*/
+ MSG_ID_CB9 = 0xcb9,
+#endif
+#if PACKETVER >= 20170719
+/*20170719 to latest
+ - 만18세이상
+*/
+ MSG_ID_CBA = 0xcba,
+/*20170719 to latest
+ - 유료서버
+*/
+ MSG_ID_CBB = 0xcbb,
+/*20170719 to latest
+ - 무료서버
+*/
+ MSG_ID_CBC = 0xcbc,
+/*20170719 to latest
+쾌적
+*/
+ MSG_ID_CBD = 0xcbd,
+/*20170719 to latest
+보통
+Normal
+*/
+ MSG_ID_CBE = 0xcbe,
+/*20170719 to latest
+혼잡
+*/
+ MSG_ID_CBF = 0xcbf,
+/*20170719 to latest
+포화
+*/
+ MSG_ID_CC0 = 0xcc0,
+/*20170719 to latest
+map
+*/
+ MSG_ID_CC1 = 0xcc1,
+/*20170719 to latest
+월드창고는 인벤토리 아이템만 입출고 할 수 있습니다.
+*/
+ MSG_ID_CC2 = 0xcc2,
+/*20170719 to latest
+월드창고에는 펫알을 입고할 수 없습니다.
+*/
+ MSG_ID_CC3 = 0xcc3,
+/*20170719 to latest
+월드창고에는 제작아이템을 입고할 수 없습니다.
+*/
+ MSG_ID_CC4 = 0xcc4,
+/*20170719 to latest
+%s 에서는 출고 할 수 없는 아이템입니다.
+*/
+ MSG_ID_CC5 = 0xcc5,
+#endif
+#if PACKETVER >= 20170726
+/*20170726 to latest
+던전 파괴
+*/
+ MSG_ID_CC6 = 0xcc6,
+/*20170726 to latest
+[%s] 님이 제련을 성공하여, [+%d %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_CC7 = 0xcc7,
+/*20170726 to latest
+[%s] 님이 [+%d %s] 아이템의 제련에 실패하였습니다.
+*/
+ MSG_ID_CC8 = 0xcc8,
+/*20170726 to latest
+파티장을 위임한 이후에 탈퇴할 수 있습니다.
+*/
+ MSG_ID_CC9 = 0xcc9,
+#endif
+#if PACKETVER >= 20170809
+/*20170809 to latest
+오름
+*/
+ MSG_ID_CCA = 0xcca,
+/*20170809 to latest
+내림
+*/
+ MSG_ID_CCB = 0xccb,
+/*20170809 to latest
+기본
+*/
+ MSG_ID_CCC = 0xccc,
+/*20170809 to latest
+변조된 파일이 발견되었습니다. 게임을 다시 실행시켜주세요.
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CCD = 0xccd,
+#endif
+#if PACKETVER >= 20170823
+/*20170823 to latest
+%s 은(는) 이맵에서 이동이 제한된 아이템입니다.
+*/
+ MSG_ID_CCE = 0xcce,
+#endif
+#if PACKETVER >= 20170906
+/*20170906 to latest
+스스로
+먹이먹기
+*/
+ MSG_ID_CCF = 0xccf,
+/*20170906 to latest
+로덱스 작성창이 열려있는 동안 호문클루스가 먹이를 먹지 못합니다.
+*/
+ MSG_ID_CD0 = 0xcd0,
+/*20170906 to latest
+호문클루스가 먹이를 먹었습니다. '%s' 잔여량 %d개
+*/
+ MSG_ID_CD1 = 0xcd1,
+/*20170906 to latest
+호문클루스 스스로 먹이 먹기 활성화 On
+*/
+ MSG_ID_CD2 = 0xcd2,
+/*20170906 to latest
+호문클루스 스스로 먹이 먹기 활성화 Off
+*/
+ MSG_ID_CD3 = 0xcd3,
+/*20170906 to latest
+호문클루스는 주인이 획득하는 경험치의
+10%만큼을 자신의 경험치로 분배 받습니다.
+*/
+ MSG_ID_CD4 = 0xcd4,
+/*20170906 to latest
+확률 : %d%%
+*/
+ MSG_ID_CD5 = 0xcd5,
+/*20170906 to latest
+해당 대상은 호문의 공격대상이 아닙니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD6 = 0xcd6,
+/*20170906 to latest
+호문의 공격대상이 존재하지 않습니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD7 = 0xcd7,
+#endif
+#if PACKETVER >= 20170913
+/*20170913 to latest
+판매 리스트
+*/
+ MSG_ID_CD8 = 0xcd8,
+/*20170913 to latest
+구입 리스트
+*/
+ MSG_ID_CD9 = 0xcd9,
+/*20170913 to latest
+신규
+New
+*/
+ MSG_ID_CDA = 0xcda,
+/*20170913 to latest
+인기
+Headgears
+*/
+ MSG_ID_CDB = 0xcdb,
+/*20170913 to latest
+한정
+Limited
+*/
+ MSG_ID_CDC = 0xcdc,
+/*20170913 to latest
+임대장비
+Rental Items
+*/
+ MSG_ID_CDD = 0xcdd,
+/*20170913 to latest
+영구장비
+Equipments
+*/
+ MSG_ID_CDE = 0xcde,
+/*20170913 to latest
+버프
+Scrolls
+*/
+ MSG_ID_CDF = 0xcdf,
+/*20170913 to latest
+회복
+Consumables
+*/
+ MSG_ID_CE0 = 0xce0,
+/*20170913 to latest
+기타
+Other
+*/
+ MSG_ID_CE1 = 0xce1,
+/*20170913 to latest
+특가
+Special
+*/
+ MSG_ID_CE2 = 0xce2,
+/*20170913 to latest
+충전하기
+*/
+ MSG_ID_CE3 = 0xce3,
+/*20170913 to latest
+구입하기
+*/
+ MSG_ID_CE4 = 0xce4,
+/*20170913 to 20171206
+https://payment.gnjoy.com/bill/login.grv
+20171213 to latest
+http://member.gnjoy.com/user/pay/chargelist.asp
+*/
+ MSG_ID_CE5 = 0xce5,
+/*20170913 to latest
+아이템 검색
+*/
+ MSG_ID_CE6 = 0xce6,
+/*20170913 to latest
+무료캐시
+*/
+ MSG_ID_CE7 = 0xce7,
+/*20170913 to latest
+무료캐시 사용
+*/
+ MSG_ID_CE8 = 0xce8,
+/*20170913 to latest
+소지캐시
+*/
+ MSG_ID_CE9 = 0xce9,
+/*20170913 to latest
+수량갱신
+*/
+ MSG_ID_CEA = 0xcea,
+/*20170913 to latest
+성제(여)
+*/
+ MSG_ID_CEB = 0xceb,
+/*20170913 to latest
+소울리퍼(여)
+*/
+ MSG_ID_CEC = 0xcec,
+/*20170913 to latest
+성제(남)
+*/
+ MSG_ID_CED = 0xced,
+/*20170913 to latest
+소울리퍼(남)
+*/
+ MSG_ID_CEE = 0xcee,
+#endif
+#if PACKETVER >= 20170920
+/*20170920 to latest
+무게가 %d 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+*/
+ MSG_ID_CEF = 0xcef,
+/*20170920 to latest
+한 번에 구입 가능한 아이템의 가짓수는 8개입니다.
+*/
+ MSG_ID_CF0 = 0xcf0,
+/*20170920 to 20190228
+http://gift.zhaouc.com/#/index
+http://gift.zhaouc.com/
+20190306 to latest
+http://gift.zhaouc.com/
+*/
+ MSG_ID_CF1 = 0xcf1,
+#endif
+#if PACKETVER >= 20170927
+/*20170927 to latest
+UNKNOWN ERROR:%d
+*/
+ MSG_ID_CF2 = 0xcf2,
+/*20170927 to latest
+NOT USER
+*/
+ MSG_ID_CF3 = 0xcf3,
+/*20170927 to latest
+THIS ACCOUNT ID IS BLOCKED
+*/
+ MSG_ID_CF4 = 0xcf4,
+/*20170927 to latest
+COUNTRY REJECT (OR NOT AVALIABLE USER )
+*/
+ MSG_ID_CF5 = 0xcf5,
+/*20170927 to latest
+NOT MATCH PASSWORD
+*/
+ MSG_ID_CF6 = 0xcf6,
+/*20170927 to latest
+NOT EMAIL CERT
+*/
+ MSG_ID_CF7 = 0xcf7,
+/*20170927 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CF8 = 0xcf8,
+/*20170927 to latest
+COUNTRY REJECT
+*/
+ MSG_ID_CF9 = 0xcf9,
+/*20170927 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CFA = 0xcfa,
+/*20170927 to latest
+WEB BLOCK
+*/
+ MSG_ID_CFB = 0xcfb,
+/*20170927 to latest
+AGE LIMIT USER
+*/
+ MSG_ID_CFC = 0xcfc,
+/*20170927 to latest
+PASSWORD HAS NOT BEEN CHANGED FOR MORE THAN 90DAYS
+*/
+ MSG_ID_CFD = 0xcfd,
+/*20170927 to latest
+INPUT DATA ERROR
+*/
+ MSG_ID_CFE = 0xcfe,
+/*20170927 to latest
+ERROR DATABASE
+*/
+ MSG_ID_CFF = 0xcff,
+/*20170927 to latest
+ERROR SYSTEM
+*/
+ MSG_ID_D00 = 0xd00,
+/*20170927 to 20171025
+%s 지불
+20171101 to latest
+%s 소모
+*/
+ MSG_ID_D01 = 0xd01,
+/*20170927 to latest
+비용지불
+*/
+ MSG_ID_D02 = 0xd02,
+/*20170927 to latest
+출발 가능한 맵이 아닙니다.
+*/
+ MSG_ID_D03 = 0xd03,
+/*20170927 to latest
+이동 불가능한 맵입니다
+*/
+ MSG_ID_D04 = 0xd04,
+/*20170927 to latest
+아이템이 부족합니다.
+*/
+ MSG_ID_D05 = 0xd05,
+/*20170927 to latest
+줄 바꿈 없이 한 줄로 입력해주세요.
+*/
+ MSG_ID_D06 = 0xd06,
+#endif
+#if PACKETVER >= 20171011
+/*20171011 to latest
+불량 단어가 포함된 이름은 등록할 수 없습니다.
+*/
+ MSG_ID_D07 = 0xd07,
+#endif
+#if PACKETVER >= 20171018
+/*20171018 to latest
+회원 가입을 위해 공식 홈페이지로 이동됩니다.
+*/
+ MSG_ID_D08 = 0xd08,
+#endif
+#if PACKETVER >= 20171025
+/*20171025 to latest
+TokenAgency 서버 연결 실패
+*/
+ MSG_ID_D09 = 0xd09,
+/*20171025 to latest
+과금정보
+*/
+ MSG_ID_D0A = 0xd0a,
+/*20171025 to latest
+삭제예약
+*/
+ MSG_ID_D0B = 0xd0b,
+/*20171025 to latest
+예약취소
+*/
+ MSG_ID_D0C = 0xd0c,
+/*20171025 to latest
+게임시작
+*/
+ MSG_ID_D0D = 0xd0d,
+/*20171025 to latest
+삭제
+Delete
+*/
+ MSG_ID_D0E = 0xd0e,
+/*20171025 to latest
+Character List
+*/
+ MSG_ID_D0F = 0xd0f,
+/*20171025 to latest
+공지
+Notice
+*/
+ MSG_ID_D10 = 0xd10,
+/*20171025 to latest
+생성
+*/
+ MSG_ID_D11 = 0xd11,
+/*20171025 to latest
+Hair Style
+*/
+ MSG_ID_D12 = 0xd12,
+/*20171025 to latest
+Hair Color
+*/
+ MSG_ID_D13 = 0xd13,
+/*20171025 to latest
+중복확인
+*/
+ MSG_ID_D14 = 0xd14,
+/*20171025 to latest
+%d시 %d분 %d초
+*/
+ MSG_ID_D15 = 0xd15,
+/*20171025 to latest
+MOTP 입력 시간이 초과되었습니다. 처음부터 다시 로그인해주십시오.
+*/
+ MSG_ID_D16 = 0xd16,
+/*20171025 to latest
+뒤로가기
+*/
+ MSG_ID_D17 = 0xd17,
+#endif
+#if PACKETVER >= 20171101
+/*20171101 to latest
+아이템을 사용할 수 없습니다.
+*/
+ MSG_ID_D18 = 0xd18,
+/*20171101 to latest
+동일한 맵으로 이동할 수 없습니다.
+*/
+ MSG_ID_D19 = 0xd19,
+/*20171101 to latest
+사망시 이동이 불가능합니다.
+*/
+ MSG_ID_D1A = 0xd1a,
+/*20171101 to latest
+캐릭터 생성
+*/
+ MSG_ID_D1B = 0xd1b,
+#endif
+#if PACKETVER >= 20171108
+/*20171108 to latest
+모험가 중개소 등록
+*/
+ MSG_ID_D1C = 0xd1c,
+/*20171108 to 20191120
+모집 중단
+20191127 to latest
+모험가 중개소 등록하기
+*/
+ MSG_ID_D1D = 0xd1d,
+/*20171108 to 20191120
+모험가 중개소 설정
+20191127 to latest
+모집 중단
+*/
+ MSG_ID_D1E = 0xd1e,
+/*20171108 to 20191120
+전 지역
+20191127 to latest
+메모
+Note
+*/
+ MSG_ID_D1F = 0xd1f,
+/*20171108 to 20191120
+직접기재
+20191127 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_D20 = 0xd20,
+/*20171108 to 20191120
+검사계열
+20191127 to latest
+필드
+*/
+ MSG_ID_D21 = 0xd21,
+/*20171108 to 20191120
+법사계열
+20191127 to latest
+던전
+Dungeon
+*/
+ MSG_ID_D22 = 0xd22,
+/*20171108 to 20191120
+궁수계열
+20191127 to latest
+MD
+*/
+ MSG_ID_D23 = 0xd23,
+/*20171108 to 20191120
+복사계열
+20191127 to latest
+낙원단
+*/
+ MSG_ID_D24 = 0xd24,
+/*20171108 to 20191120
+상인계열
+20191127 to latest
+기타
+Other
+*/
+ MSG_ID_D25 = 0xd25,
+/*20171108 to 20191120
+도둑계열
+20191127 to latest
+검색
+Search
+*/
+ MSG_ID_D26 = 0xd26,
+/*20171108 to 20191120
+태권계열
+20191127 to latest
+초기화
+*/
+ MSG_ID_D27 = 0xd27,
+/*20171108 to 20191120
+닌자계열
+20191127 to latest
+파티가입신청
+*/
+ MSG_ID_D28 = 0xd28,
+/*20171108 to 20191120
+건슬링거계열
+20191127 to latest
+목적
+*/
+ MSG_ID_D29 = 0xd29,
+/*20171108 to 20191120
+도람족계열
+20191127 to latest
+※욕설, 현거래등 운영 규칙에 위배되는 목적으로 사용 시 처벌 받을 수 있습니다.
+*/
+ MSG_ID_D2A = 0xd2a,
+/*20171108 to 20191120
+지역명
+20191127 to latest
+등록하기
+Register
+*/
+ MSG_ID_D2B = 0xd2b,
+/*20171108 to 20191120
+지역명 검색
+20191127 to latest
+사용할 수 없는 단어가 포함되어 있습니다.
+*/
+ MSG_ID_D2C = 0xd2c,
+/*20171108 to 20191120
+가입 요청하기
+20191127 to latest
+파티가입
+*/
+ MSG_ID_D2D = 0xd2d,
+/*20171108 to 20191120
+신고하기
+20191127 to latest
+1:1대화
+*/
+ MSG_ID_D2E = 0xd2e,
+/*20171108 to 20191120
+파티 모집 중단
+20191127 to latest
+모집 중지
+*/
+ MSG_ID_D2F = 0xd2f,
+/*20171108 to 20191120
+지역명을 입력해주세요.
+20191127 to latest
+수정하기
+*/
+ MSG_ID_D30 = 0xd30,
+/*20171108 to 20191120
+지역
+20191127 to latest
+전체
+All
+*/
+ MSG_ID_D31 = 0xd31,
+/*20171108 to 20191120
+전 직업
+20191127 to latest
+[%s] 님이 파티가입을 신청했습니다.
+*/
+ MSG_ID_D32 = 0xd32,
+/*20171108 to latest
+로그인
+*/
+ MSG_ID_D33 = 0xd33,
+/*20171108 to latest
+계정
+*/
+ MSG_ID_D34 = 0xd34,
+/*20171108 to latest
+종료
+Exit
+*/
+ MSG_ID_D35 = 0xd35,
+/*20171108 to latest
+신청
+*/
+ MSG_ID_D36 = 0xd36,
+/*20171108 to latest
+접속
+*/
+ MSG_ID_D37 = 0xd37,
+/*20171108 to latest
+확인
+*/
+ MSG_ID_D38 = 0xd38,
+/*20171108 to latest
+휴대폰에 다운받은 GNJOY MOTP를
+*/
+ MSG_ID_D39 = 0xd39,
+/*20171108 to latest
+실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_D3A = 0xd3a,
+/*20171108 to latest
+NPC가 있는 맵의 랜덤 좌표로 이동 됩니다.
+*/
+ MSG_ID_D3B = 0xd3b,
+/*20171108 to latest
+태권
+Taekwon
+*/
+ MSG_ID_D3C = 0xd3c,
+/*20171108 to 20171115
+ 님이 차단 상태로 설정되었습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D3D = 0xd3d,
+#endif
+#if PACKETVER >= 20171115
+/*20171115 to 20171115
+ 님을 차단 상태로 설정하는데 실패하였습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부 요청 실패
+*/
+ MSG_ID_D3E = 0xd3e,
+/*20171115 to 20171115
+ 님을 차단 상태로 설정하는데 실패하였습니다.(인원 초과)
+20171122 to latest
+ 에게 전체채팅 및 귓말 거부 요청실패 (인원초과)
+*/
+ MSG_ID_D3F = 0xd3f,
+/*20171115 to 20171115
+ 님이 차단 해제 되었습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D40 = 0xd40,
+/*20171115 to 20171115
+ 님을 차단 해제하는데 실패하였습니다.
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패
+*/
+ MSG_ID_D41 = 0xd41,
+/*20171115 to 20171115
+ 님을 차단 해제하는데 실패하였습니다.(인원 초과)
+20171122 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패 (인원초과)
+*/
+ MSG_ID_D42 = 0xd42,
+/*20171115 to latest
+차단 리스트가 없습니다
+Ignore-list is empty
+*/
+ MSG_ID_D43 = 0xd43,
+/*20171115 to latest
+-차단 리스트-
+Characters in ignore-list:
+*/
+ MSG_ID_D44 = 0xd44,
+/*20171115 to latest
+진행중
+Act
+*/
+ MSG_ID_D45 = 0xd45,
+/*20171115 to latest
+추천
+Rec
+*/
+ MSG_ID_D46 = 0xd46,
+/*20171115 to latest
+보류중
+Pen
+*/
+ MSG_ID_D47 = 0xd47,
+/*20171115 to latest
+QUEST
+*/
+ MSG_ID_D48 = 0xd48,
+/*20171115 to latest
+내용
+For
+*/
+ MSG_ID_D49 = 0xd49,
+/*20171115 to latest
+몬스터
+*/
+ MSG_ID_D4A = 0xd4a,
+/*20171115 to latest
+보상
+*/
+ MSG_ID_D4B = 0xd4b,
+/*20171115 to latest
+EXP
+*/
+ MSG_ID_D4C = 0xd4c,
+/*20171115 to latest
+JEXP
+*/
+ MSG_ID_D4D = 0xd4d,
+/*20171115 to latest
+아이템
+Item
+*/
+ MSG_ID_D4E = 0xd4e,
+/*20171115 to latest
+진행/보류
+*/
+ MSG_ID_D4F = 0xd4f,
+/*20171115 to latest
+하단으로 이동
+*/
+ MSG_ID_D50 = 0xd50,
+/*20171115 to latest
+간편 퀘스트창에 표시
+*/
+ MSG_ID_D51 = 0xd51,
+/*20171115 to latest
+입력시간
+*/
+ MSG_ID_D52 = 0xd52,
+#endif
+#if PACKETVER >= 20171122
+/*20171122 to latest
+아이디 저장
+*/
+ MSG_ID_D53 = 0xd53,
+/*20171122 to latest
+비밀번호
+Password
+*/
+ MSG_ID_D54 = 0xd54,
+/*20171122 to latest
+아이디
+*/
+ MSG_ID_D55 = 0xd55,
+/*20171122 to latest
+회원가입
+*/
+ MSG_ID_D56 = 0xd56,
+/*20171122 to 20191120
+노비스계열
+20191127 to latest
+파티장
+Leader
+*/
+ MSG_ID_D57 = 0xd57,
+/*20171122 to 20191120
+슈퍼노비스계열
+20191127 to latest
+파티에 가입할 수 있는 레벨이 아닙니다.
+*/
+ MSG_ID_D58 = 0xd58,
+/*20171122 to latest
+모험가 중개소 등록에 실패했습니다.
+*/
+ MSG_ID_D59 = 0xd59,
+/*20171122 to latest
+모험가 중개소에 등록되었습니다.
+*/
+ MSG_ID_D5A = 0xd5a,
+/*20171122 to 20180328
+직업을 한 개 이상 선택해주세요.
+20180404 to 20191120
+모집을 희망하는 파티원의 직업을 한 개 이상 선택해 주세요.
+20191127 to latest
+검색내용입력
+*/
+ MSG_ID_D5B = 0xd5b,
+/*20171122 to 20191127
+지역명을 두 글자 이상 입력해주세요.
+20191204 to latest
+탱커
+*/
+ MSG_ID_D5C = 0xd5c,
+/*20171122 to latest
+%.1f%% (+ %s서버 %.1f%%)
+*/
+ MSG_ID_D5D = 0xd5d,
+/*20171122 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D5E = 0xd5e,
+/*20171122 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D5F = 0xd5f,
+/*20171122 to latest
+/ex or /차단 : 전체채팅 및 귓말 차단 캐릭터 리스트
+*/
+ MSG_ID_D60 = 0xd60,
+/*20171122 to latest
+/exall or /차단전부 : 모두에게 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D61 = 0xd61,
+/*20171122 to latest
+/inall or /해제전부 : 모두에게 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D62 = 0xd62,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D63 = 0xd63,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 거부요청 실패
+*/
+ MSG_ID_D64 = 0xd64,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D65 = 0xd65,
+/*20171122 to latest
+모두에게 전체채팅 및 귓말 가능요청 실패
+*/
+ MSG_ID_D66 = 0xd66,
+/*20171122 to latest
+오프닝
+*/
+ MSG_ID_D67 = 0xd67,
+#endif
+#if PACKETVER >= 20171206
+/*20171206 to latest
+로그인 화면으로 돌아가시겠습니까?
+*/
+ MSG_ID_D68 = 0xd68,
+/*20171206 to latest
+힘과 공격력이 강해졌습니다.
+*/
+ MSG_ID_D69 = 0xd69,
+/*20171206 to latest
+힘, 지능, 손재주 및 명중률이 증가하였습니다.
+*/
+ MSG_ID_D6A = 0xd6a,
+/*20171206 to latest
+방어력 및 HP가 증가되었습니다.
+*/
+ MSG_ID_D6B = 0xd6b,
+/*20171206 to latest
+젤스타
+*/
+ MSG_ID_D6C = 0xd6c,
+/*20171206 to latest
+계정버프
+*/
+ MSG_ID_D6D = 0xd6d,
+/*20171206 to latest
+정액서비스
+*/
+ MSG_ID_D6E = 0xd6e,
+#endif
+#if PACKETVER >= 20171213
+/*20171213 to latest
+현재 접속이 지연되고 있습니다. 순차적으로 접속이 가능하니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D6F = 0xd6f,
+/*20171213 to latest
+현재 접속이 지연되고 있으니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D70 = 0xd70,
+/*20171213 to latest
+불량 단어가 포함된 이름은 검색할 수 없습니다.
+*/
+ MSG_ID_D71 = 0xd71,
+/*20171213 to 20191127
+파티 마스터가 요청을 받을 수 없는 맵에 있습니다.
+20191204 to latest
+파티 마스터가 요청을 받을 수 없는 상태입니다.
+*/
+ MSG_ID_D72 = 0xd72,
+/*20171213 to latest
+파티를 찾을 수 없습니다.
+*/
+ MSG_ID_D73 = 0xd73,
+/*20171213 to 20180328
+님의 파티요청입니다.
+20180404 to 20191127
+님의 파티 가입 요청입니다.
+20191204 to latest
+딜러
+*/
+ MSG_ID_D74 = 0xd74,
+#endif
+#if PACKETVER >= 20171220
+/*20171220 to latest
+http://ro.gnjoy.com
+*/
+ MSG_ID_D75 = 0xd75,
+/*20171220 to latest
+▲
+*/
+ MSG_ID_D76 = 0xd76,
+/*20171220 to latest
+▼
+*/
+ MSG_ID_D77 = 0xd77,
+#endif
+#if PACKETVER >= 20171227
+/*20171227 to latest
+이미 친구입니다
+*/
+ MSG_ID_D78 = 0xd78,
+/*20171227 to latest
+상대방을 찾을 수 없습니다
+*/
+ MSG_ID_D79 = 0xd79,
+/*20171227 to latest
+이미 다른 캐릭터가 친구 신청 중입니다.
+*/
+ MSG_ID_D7A = 0xd7a,
+/*20171227 to latest
+혼구슬 표시 ON
+*/
+ MSG_ID_D7B = 0xd7b,
+/*20171227 to latest
+혼구슬 표시 OFF
+*/
+ MSG_ID_D7C = 0xd7c,
+#endif
+#if PACKETVER >= 20180117
+/*20180117 to latest
+해당 계정은 2차 비밀번호 오입력으로 인해 게임내 접속이 제한된 상태입니다.
+ %02d시간 %02d분 후에 접속제한이 해제되며, 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7D = 0xd7d,
+/*20180117 to latest
+보안패스워드를 3회이상 틀리셨습니다. 계정 보안을 위해 24시간동안 게임내 접속이 제한됩니다.
+ 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7E = 0xd7e,
+/*20180117 to latest
+운영진
+*/
+ MSG_ID_D7F = 0xd7f,
+/*20180117 to latest
+%d일차 출석 보상이 지급되었습니다.
+*/
+ MSG_ID_D80 = 0xd80,
+/*20180117 to 20180117
+계정설정정보 받아오는데 실패 했습니다.( 재시도를 위해서는 재시작 해야 합니다. )
+20180124 to latest
+계정 설정 데이터를 불러오는 중에 오류가 발생했습니다. ( 재시도를 위해서는 재시작 해야 합니다. )
+*/
+ MSG_ID_D81 = 0xd81,
+/*20180117 to latest
+해당 스킬은 파티 상태에서 사용 가능합니다.
+*/
+ MSG_ID_D82 = 0xd82,
+#endif
+#if PACKETVER >= 20180124
+/*20180124 to latest
+파티 모집을 중단하였습니다.
+*/
+ MSG_ID_D83 = 0xd83,
+/*20180124 to latest
+길드 상납 경험치는 최대 %d%%까지 가능합니다.
+*/
+ MSG_ID_D84 = 0xd84,
+/*20180124 to latest
+길드 레벨이 최대여서 더 이상 경험치를 상납할 수 없습니다.
+*/
+ MSG_ID_D85 = 0xd85,
+#endif
+#if PACKETVER >= 20180207
+/*20180207 to latest
+계정보안을 위하여 MOTP미사용자는 홈페이지 로그인만 가능합니다.
+홈페이지로 로그인을 시도해주시기 바랍니다.
+*/
+ MSG_ID_D86 = 0xd86,
+/*20180207 to latest
+물리 공격력과 마법 공격력이 향상되었습니다.
+*/
+ MSG_ID_D87 = 0xd87,
+/*20180207 to latest
+물리 공격력과 마법 공격력이 감소되었습니다.
+*/
+ MSG_ID_D88 = 0xd88,
+/*20180207 to latest
+%s 출석체크 보상
+%s Attendance Check Reward
+*/
+ MSG_ID_D89 = 0xd89,
+/*20180207 to 20180502
+이벤트 기간 : %02d월 %02d일 ~ %2d월 %2d일 24:00까지
+Event period : From %02d/%02d ~ Until %2d/%2d (Month/Day) 24:00
+20180516 to latest
+이벤트 기간 : %02d월 %02d일 ~ %02d월 %02d일 24:00까지
+*/
+ MSG_ID_D8A = 0xd8a,
+/*20180207 to latest
+%d일차
+%d Day
+*/
+ MSG_ID_D8B = 0xd8b,
+/*20180207 to latest
+%d일차 출석체크
+클릭해주세요~!
+%d Day attendance check
+Please click~!
+*/
+ MSG_ID_D8C = 0xd8c,
+/*20180207 to latest
+%d일차 출석 성공!
+%d Day attendance success!
+*/
+ MSG_ID_D8D = 0xd8d,
+/*20180207 to latest
+D-day
+*/
+ MSG_ID_D8E = 0xd8e,
+/*20180207 to latest
+일
+Day
+*/
+ MSG_ID_D8F = 0xd8f,
+/*20180207 to latest
+출석체크에 실패하였습니다. 다시 실행해주세요.
+Attendance Check failed. Please run again.
+*/
+ MSG_ID_D90 = 0xd90,
+/*20180207 to latest
+출석체크
+Attendance Check
+*/
+ MSG_ID_D91 = 0xd91,
+/*20180207 to latest
+현재 출석체크 이벤트 기간이 아닙니다
+This is not the current attendance check event
+*/
+ MSG_ATTENDANCE_UNAVAILABLE = 0xd92,
+/*20180207 to 20180328
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다
+20180404 to latest
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+*/
+ MSG_ID_D93 = 0xd93,
+/*20180207 to latest
+개인 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+
+*/
+ MSG_ID_D94 = 0xd94,
+#endif
+#if PACKETVER >= 20180213
+/*20180213 to latest
+메시지
+*/
+ MSG_ID_D95 = 0xd95,
+/*20180213 to latest
+트위터에 메세지 전송을 실패 했습니다.
+*/
+ MSG_ID_D96 = 0xd96,
+/*20180213 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_D97 = 0xd97,
+#endif
+#if PACKETVER >= 20180307
+/*20180307 to latest
+몬스터의 테이밍이 불가능한 지역입니다.
+*/
+ MSG_ID_D98 = 0xd98,
+#endif
+#if PACKETVER >= 20180321
+/*20180321 to latest
+순위를 가져오고 있습니다...
+*/
+ MSG_ID_D99 = 0xd99,
+/*20180321 to latest
+해당 스킬은 파티장일때만 사용 가능합니다.
+*/
+ MSG_ID_D9A = 0xd9a,
+#endif
+#if PACKETVER >= 20180404
+/*20180404 to latest
+파트너의 SP가 부족하거나, 스킬 사용 불가 상태입니다.
+*/
+ MSG_ID_D9B = 0xd9b,
+/*20180404 to latest
+아르바이트 노점 강제 종료 알림메일
+*/
+ MSG_ID_D9C = 0xd9c,
+/*20180404 to latest
+안녕하세요. 운영팀입니다.
+해당 아르바이트 노점은 운영정책 위배되는 사항이 확인되어 강제 종료되었습니다.
+자세한 확인을 원하시는 경우에는 1:1 문의를 접수해 주시기 바랍니다.
+감사합니다
+*/
+ MSG_ID_D9D = 0xd9d,
+/*20180404 to latest
+50% 이상의 값을 입력할 수 없습니다.
+The guild tax rate can't be set to more than 50%.
+*/
+ MSG_ID_D9E = 0xd9e,
+/*20180404 to 20191204
+파티 가입 요청을 보냈습니다.
+20191211 to latest
+파티가 모험가 중개소에 등록되어, 파티장을 변경 할 수 없습니다.
+*/
+ MSG_ID_D9F = 0xd9f,
+/*20180404 to latest
+모험가 중개소에 파티를 등록할 수 없습니다
+*/
+ MSG_ID_DA0 = 0xda0,
+/*20180404 to latest
+수락
+*/
+ MSG_ID_DA1 = 0xda1,
+/*20180404 to latest
+거절
+*/
+ MSG_ID_DA2 = 0xda2,
+/*20180404 to 20191127
+설정 권한은 파티장에게 있습니다.
+20191204 to latest
+힐러
+*/
+ MSG_ID_DA3 = 0xda3,
+/*20180404 to latest
+해당 캐릭터를 찾을 수 없습니다.
+*/
+ MSG_ID_DA4 = 0xda4,
+/*20180404 to latest
+노점 강제 철거
+*/
+ MSG_ID_DA5 = 0xda5,
+/*20180404 to latest
+해당 파티의 파티장을 찾을 수 없습니다.
+*/
+ MSG_ID_DA6 = 0xda6,
+/*20180404 to latest
+잡레벨이 낮아 파티에 가입 할 수 없습니다.
+*/
+ MSG_ID_DA7 = 0xda7,
+/*20180404 to latest
+현재 요청자가 파티가입이 불가능한 지역에 있습니다.
+*/
+ MSG_ID_DA8 = 0xda8,
+/*20180404 to latest
+파티 인원수가 초과되었습니다.
+*/
+ MSG_ID_DA9 = 0xda9,
+/*20180404 to latest
+%s 파티의 파티장이 파티 가입을 승인했습니다.
+*/
+ MSG_ID_DAA = 0xdaa,
+/*20180404 to latest
+%s 파티의 파티장이 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAB = 0xdab,
+/*20180404 to latest
+%s 님이 이미 파티에 가입 중입니다.
+*/
+ MSG_ID_DAC = 0xdac,
+/*20180404 to latest
+%s 님의 파티 가입을 수락했습니다.
+*/
+ MSG_ID_DAD = 0xdad,
+/*20180404 to latest
+%s 님의 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAE = 0xdae,
+/*20180404 to latest
+파티 요청을 받을 수 없는 상태여서 %s님의 신청이 거절되었습니다.
+*/
+ MSG_ID_DAF = 0xdaf,
+/*20180404 to latest
+모험가 중개소 리스트
+*/
+ MSG_ID_DB0 = 0xdb0,
+/*20180404 to latest
+파티 가입 요청
+*/
+ MSG_ID_DB1 = 0xdb1,
+/*20180404 to 20191120
+파티장이 아닌 경우, 모험가 중개소에 파티를 등록할 수 없습니다.
+20191127 to latest
+파티장이 아닌 경우 모험가 중개소에 파티를 등록할 수 없습니다.
+*/
+ MSG_ID_DB2 = 0xdb2,
+/*20180404 to 20180404
+파티 모집 중단에 실패했습니다.
+20180418 to latest
+파티 모집을 중단할 수 없습니다.
+*/
+ MSG_ID_DB3 = 0xdb3,
+#endif
+#if PACKETVER >= 20180418
+/*20180418 to 20191127
+존재하지 않는 파티 글입니다.
+20191204 to latest
+보조
+Support
+*/
+ MSG_ID_DB4 = 0xdb4,
+/*20180418 to 20180418
+시야 확장
+20180425 to latest
+Zoom Out
+*/
+ MSG_ID_DB5 = 0xdb5,
+/*20180418 to 20180418
+%s : 시야확장을 켜거나 끌수 있습니다 On Off
+20180425 to latest
+%s : Zoom Out을 켜거나 끌수 있습니다 On Off
+*/
+ MSG_ID_DB6 = 0xdb6,
+/*20180418 to 20180418
+시야를 확장합니다(On)
+20180425 to latest
+Zoom Out 기능을 켭니다 (On)
+*/
+ MSG_ID_DB7 = 0xdb7,
+/*20180418 to 20180418
+시야확장을 해제합니다(Off)
+20180425 to latest
+Zoom Out 기능을 해제합니다 (Off)
+*/
+ MSG_ID_DB8 = 0xdb8,
+/*20180418 to 20180418
+/expandsight
+20180425 to latest
+/zoom
+*/
+ MSG_ID_DB9 = 0xdb9,
+/*20180418 to latest
+모험가 중개소
+*/
+ MSG_ID_DBA = 0xdba,
+/*20180418 to latest
+파티장인 경우, 가입 요청을 할 수 없습니다.
+*/
+ MSG_ID_DBB = 0xdbb,
+/*20180418 to 20191204
+모험가 중개소에 등록 중입니다. 잠시만 기다려 주세요.
+20191211 to latest
+파티 가입 최대 레벨은 최소 레벨 설정보다 높아야 합니다.
+*/
+ MSG_ID_DBC = 0xdbc,
+/*20180418 to latest
+더 이상 직업을 선택할 수 없습니다.
+*/
+ MSG_ID_DBD = 0xdbd,
+/*20180418 to 20191120
+게임 중 해당 유저의 가입 요청을 받지 않습니다.
+20191127 to latest
+게임 중 해당 유저의 가입 요청을 받지 않습니다.(클라이언트 종료 전까지 유효)
+*/
+ MSG_ID_DBE = 0xdbe,
+#endif
+#if PACKETVER >= 20180502
+/*20180502 to latest
+잠시 후 다시 열어주시기 바랍니다.
+*/
+ MSG_ID_DBF = 0xdbf,
+/*20180502 to latest
+공성시작 전 %d분 동안은 해당 기능을 이용하실 수 없습니다.
+*/
+ MSG_ID_DC0 = 0xdc0,
+#endif
+#if PACKETVER >= 20180516
+/*20180516 to latest
+/viewclear
+*/
+ MSG_ID_DC1 = 0xdc1,
+/*20180516 to latest
+건물 반 투명화 ON
+*/
+ MSG_ID_DC2 = 0xdc2,
+/*20180516 to latest
+건물 반 투명화 OFF
+*/
+ MSG_ID_DC3 = 0xdc3,
+/*20180516 to latest
+건물 투명화
+*/
+ MSG_ID_DC4 = 0xdc4,
+/*20180516 to latest
+알로 되돌리기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+*/
+ MSG_ID_DC5 = 0xdc5,
+/*20180516 to latest
+Emblem Frame
+*/
+ MSG_ID_DC6 = 0xdc6,
+/*20180516 to latest
+Emblem 테두리를 그려줍니다
+*/
+ MSG_ID_DC7 = 0xdc7,
+/*20180516 to latest
+Emblem 테두리를 그려주지 않습니다
+*/
+ MSG_ID_DC8 = 0xdc8,
+#endif
+#if PACKETVER >= 20180605
+/*20180605 to latest
+장착된 무기가 없습니다.
+*/
+ MSG_ID_DC9 = 0xdc9,
+/*20180605 to latest
+에너지 구체가 부족합니다.
+*/
+ MSG_ID_DCA = 0xdca,
+/*20180605 to latest
+배울 수 없는 스킬(%s)이 포함되어있습니다.
+*/
+ MSG_ID_DCB = 0xdcb,
+/*20180605 to latest
+/frame
+*/
+ MSG_ID_DCC = 0xdcc,
+#endif
+#if PACKETVER >= 20180620
+/*20180620 to latest
+웨폰 블로킹 발동후 제한시간 내에 사용가능한 스킬입니다.
+*/
+ MSG_ID_DCD = 0xdcd,
+#endif
+#if PACKETVER >= 20180704
+/*20180704 to latest
+아이디혹은 패스워드가 잘못되었읍니다.
+*/
+ MSG_ID_DCE = 0xdce,
+#endif
+#if PACKETVER >= 20180718
+/*20180718 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DCF = 0xdcf,
+/*20180718 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD0 = 0xdd0,
+/*20180718 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD1 = 0xdd1,
+#endif
+#if PACKETVER >= 20180829
+/*20180829 to latest
+영문이나 러시아어 단독으로만 사용이 가능합니다.
+Forbidden symbols in character name.
+*/
+ MSG_ID_DD2 = 0xdd2,
+/*20180829 to latest
+you must have an AccessTicket to login
+*/
+ MSG_ID_DD3 = 0xdd3,
+/*20180829 to latest
+창고를 불러오는 중입니다.
+Loading....
+*/
+ MSG_ID_DD4 = 0xdd4,
+/*20180829 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_DD5 = 0xdd5,
+#endif
+#if PACKETVER >= 20180919
+/*20180919 to latest
+삭제
+Delete
+*/
+ MSG_ID_DD6 = 0xdd6,
+/*20180919 to latest
+답장
+Reply
+*/
+ MSG_ID_DD7 = 0xdd7,
+/*20180919 to latest
+전송
+Send
+*/
+ MSG_ID_DD8 = 0xdd8,
+/*20180919 to latest
+이름확인
+Name Check
+*/
+ MSG_ID_DD9 = 0xdd9,
+/*20180919 to latest
+공지
+Notice
+*/
+ MSG_ID_DDA = 0xdda,
+/*20180919 to latest
+일반
+General
+*/
+ MSG_ID_DDB = 0xddb,
+/*20180919 to latest
+반송
+Clear
+*/
+ MSG_ID_DDC = 0xddc,
+/*20180919 to latest
+검색
+Search
+*/
+ MSG_ID_DDD = 0xddd,
+#endif
+#if PACKETVER >= 20181031
+/*20181031 to latest
+펫 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDE = 0xdde,
+/*20181031 to latest
+호문 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDF = 0xddf,
+/*20181031 to latest
+화폐
+*/
+ MSG_ID_DE0 = 0xde0,
+/*20181031 to latest
+%s %d개
+*/
+ MSG_ID_DE1 = 0xde1,
+/*20181031 to latest
+교환에 실패하였습니다.
+*/
+ MSG_ID_DE2 = 0xde2,
+/*20181031 to latest
+교환이 잘 이루어졌습니다.
+*/
+ MSG_ID_DE3 = 0xde3,
+/*20181031 to latest
+교환에 필요한 재화가 부족합니다.
+*/
+ MSG_ID_DE4 = 0xde4,
+/*20181031 to latest
+해당 아이템은 이미 판매되어 재고가 부족합니다.
+*/
+ MSG_ID_DE5 = 0xde5,
+/*20181031 to latest
+사망
+*/
+ MSG_ID_DE6 = 0xde6,
+/*20181031 to latest
+PvP
+*/
+ MSG_ID_DE7 = 0xde7,
+/*20181031 to latest
+아이템 소지 확장
+*/
+ MSG_ID_DE8 = 0xde8,
+/*20181031 to 20181031
+(^0000ff%s^000000)을 소모하여, 아이템 최대 소지 종류수를 확장하시겠습니까?
+(^0000ff%d^000000)에서 (^0000ff%d^000000)로 확장됩니다.
+^ff0000※ 소모된 아이템 및 확장된 최대 소지 종류수는 되돌릴 수 없습니다.^000000
+20181107 to latest
+^0000ff%s^000000을 소모하여, 아이템 최대 소지 종류수를 확장하시겠습니까?
+(^0000ff%d^000000)에서 (^0000ff%d^000000)로 확장됩니다.
+^ff0000※ 소모된 아이템 및 확장된 최대 소지 종류수는 되돌릴 수 없습니다.^000000
+*/
+ MSG_ID_DE9 = 0xde9,
+/*20181031 to 20181031
+아이템 소지 종류 수 확장에 실패하였습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 실패하였습니다.
+*/
+ MSG_ID_DEA = 0xdea,
+/*20181031 to 20181031
+아이템 소지 종류 수 확장을 위해, 다른 작업을 종료하여 주시기 바랍니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장을 위해, 다른 작업을 종료하여 주시기 바랍니다.
+*/
+ MSG_ID_DEB = 0xdeb,
+/*20181031 to 20181031
+아이템 소지 확장에 필요한 아이템을 소지하고 있지 않습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 필요한 아이템을 소지하고 있지 않습니다.
+*/
+ MSG_ID_DEC = 0xdec,
+/*20181031 to 20181031
+이미 아이템 소지 종류 수 확장이 최대로 적용 중입니다.
+20181107 to latest
+더 이상 아이템 최대 소지 종류수를 확장 할 수 없습니다.
+*/
+ MSG_ID_DED = 0xded,
+/*20181031 to 20181031
+아이템 소지 확장에 성공하였습니다.
+20181107 to latest
+아이템 최대 소지 종류수 확장에 성공하였습니다.
+*/
+ MSG_ID_DEE = 0xdee,
+#endif
+#if PACKETVER >= 20181121
+/*20181121 to latest
+같은 아이템을 %d개 이상 가질 수 없습니다.
+*/
+ MSG_ID_DEF = 0xdef,
+/*20181121 to latest
+소지 한계량 초과로 구입이 불가능합니다.
+*/
+ MSG_ID_DF0 = 0xdf0,
+/*20181121 to latest
+해당 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_ID_DF1 = 0xdf1,
+#endif
+#if PACKETVER >= 20181205
+/*20181205 to latest
+성제
+*/
+ MSG_ID_DF2 = 0xdf2,
+/*20181205 to latest
+소울리퍼
+*/
+ MSG_ID_DF3 = 0xdf3,
+#endif
+#if PACKETVER >= 20181212
+/*20181212 to latest
+설정한 내용은 정상 종료 시 서버에 저장됩니다.
+*/
+ MSG_ID_DF4 = 0xdf4,
+#endif
+#if PACKETVER >= 20190109
+/*20190109 to latest
+Capture Monster
+Taming monster
+*/
+ MSG_ID_DF5 = 0xdf5,
+/*20190109 to latest
+message
+*/
+ MSG_ID_DF6 = 0xdf6,
+/*20190109 to latest
+TITLE
+Header
+*/
+ MSG_ID_DF7 = 0xdf7,
+/*20190109 to latest
+데미지 표기 확장
+*/
+ MSG_ID_DF8 = 0xdf8,
+#endif
+#if PACKETVER >= 20190213
+/*20190213 to latest
+맵 이름 표기
+*/
+ MSG_ID_DF9 = 0xdf9,
+/*20190213 to latest
+시스템 메세지 : 현재 노점보기 기능이 %s 상태입니다. (/노점보기)
+*/
+ MSG_ID_DFA = 0xdfa,
+/*20190213 to latest
+수직 동기
+*/
+ MSG_ID_DFB = 0xdfb,
+/*20190213 to latest
+자료
+*/
+ MSG_ID_DFC = 0xdfc,
+/*20190213 to 20190228
+http://rodata.zhaouc.com/renwu.html#container
+20190306 to latest
+http://rodata.zhaouc.com/renwu.html
+*/
+ MSG_ID_DFD = 0xdfd,
+/*20190213 to latest
+작위
+*/
+ MSG_ID_DFE = 0xdfe,
+/*20190213 to latest
+프레임 제한
+*/
+ MSG_ID_DFF = 0xdff,
+#endif
+#if PACKETVER >= 20190220
+/*20190220 to latest
+%d개를 초과할 경우 더 이상 설치 할 수 없습니다.
+*/
+ MSG_ID_E00 = 0xe00,
+/*20190220 to latest
+목적지
+*/
+ MSG_ID_E01 = 0xe01,
+#endif
+#if PACKETVER >= 20190306
+/*20190306 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_E02 = 0xe02,
+/*20190306 to latest
+등록할 수 없는 파일입니다.
+*/
+ MSG_ID_E03 = 0xe03,
+#endif
+#if PACKETVER >= 20190320
+/*20190320 to latest
+선택 삭제
+*/
+ MSG_ID_E04 = 0xe04,
+/*20190320 to latest
+모두 삭제
+*/
+ MSG_ID_E05 = 0xe05,
+/*20190320 to latest
+[%s]편지함의 모든 메일을 삭제하시겠습니까?
+*/
+ MSG_ID_E06 = 0xe06,
+/*20190320 to latest
+선택 받기
+*/
+ MSG_ID_E07 = 0xe07,
+/*20190320 to latest
+모두 받기
+*/
+ MSG_ID_E08 = 0xe08,
+/*20190320 to latest
+선택한 메일의 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E09 = 0xe09,
+/*20190320 to latest
+[%s]편지함의 모든 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E0A = 0xe0a,
+#endif
+#if PACKETVER >= 20190403
+/*20190403 to latest
+스킬바2
+*/
+ MSG_ID_E0B = 0xe0b,
+/*20190403 to latest
+스킬바 교체
+*/
+ MSG_ID_E0C = 0xe0c,
+/*20190403 to latest
+←
+*/
+ MSG_ID_E0D = 0xe0d,
+/*20190403 to latest
+↑
+*/
+ MSG_ID_E0E = 0xe0e,
+/*20190403 to latest
+→
+*/
+ MSG_ID_E0F = 0xe0f,
+/*20190403 to latest
+↓
+*/
+ MSG_ID_E10 = 0xe10,
+/*20190403 to latest
+▤
+*/
+ MSG_ID_E11 = 0xe11,
+/*20190403 to latest
+←
+*/
+ MSG_ID_E12 = 0xe12,
+/*20190403 to latest
+로딩중에는 창을 닫을 수 없습니다.
+*/
+ MSG_ID_E13 = 0xe13,
+#endif
+#if PACKETVER >= 20190417
+/*20190417 to latest
+리딩 스펠북으로 저장된 마법이 없습니다.
+*/
+ MSG_ID_E14 = 0xe14,
+/*20190417 to latest
+이동 시 사용한 아이템은 재교환이 불가능합니다.
+*/
+ MSG_ID_E15 = 0xe15,
+/*20190417 to latest
+자유이동권을 구매 하였습니다
+*/
+ MSG_ID_E16 = 0xe16,
+/*20190417 to latest
+자유이동권 사용 중, 관련 아이템을 소모하지 않습니다.
+*/
+ MSG_ID_E17 = 0xe17,
+/*20190417 to latest
+적용
+*/
+ MSG_ID_E18 = 0xe18,
+/*20190417 to latest
+중지
+*/
+ MSG_ID_E19 = 0xe19,
+#endif
+#if PACKETVER >= 20190508
+/*20190508 to latest
+자유이동권
+*/
+ MSG_ID_E1A = 0xe1a,
+/*20190508 to latest
+%d시간 이용, %s %d개
+*/
+ MSG_ID_E1B = 0xe1b,
+/*20190508 to latest
+자유이용권 사용중
+*/
+ MSG_ID_E1C = 0xe1c,
+/*20190508 to latest
+특성 스테이터스
+*/
+ MSG_ID_E1D = 0xe1d,
+/*20190508 to latest
+파워 파라메터
+^cc0000물리 공격력, 특성 공격력^ffffff 증가
+*/
+ MSG_ID_E1E = 0xe1e,
+/*20190508 to latest
+스테미나 파라메터
+^cc0000물리 저항력^ffffff 증가
+*/
+ MSG_ID_E1F = 0xe1f,
+/*20190508 to latest
+위즈덤 파라메터
+^cc0000마법 저항력^ffffff 증가
+*/
+ MSG_ID_E20 = 0xe20,
+/*20190508 to latest
+스펠 파라메터
+^cc0000마법 공격력, 마법 공격력^ffffff 증가
+*/
+ MSG_ID_E21 = 0xe21,
+/*20190508 to latest
+컨센트레이션 파라메터
+^cc0000명중률, 회피율, 특성 물리/마법 공격력^ffffff 증가
+*/
+ MSG_ID_E22 = 0xe22,
+/*20190508 to latest
+크리에이티브 파라메터
+^cc0000특성 힐 회복량, 크리티컬 데미지 비율^ffffff 증가
+*/
+ MSG_ID_E23 = 0xe23,
+/*20190508 to latest
+특성 물리 공격력
+*/
+ MSG_ID_E24 = 0xe24,
+/*20190508 to latest
+특성 마법 공격력
+*/
+ MSG_ID_E25 = 0xe25,
+/*20190508 to latest
+물리 저항력
+*/
+ MSG_ID_E26 = 0xe26,
+/*20190508 to latest
+마법 저항력
+*/
+ MSG_ID_E27 = 0xe27,
+/*20190508 to latest
+특성 힐 회복량
+*/
+ MSG_ID_E28 = 0xe28,
+/*20190508 to latest
+크리티컬 데미지 비율
+*/
+ MSG_ID_E29 = 0xe29,
+/*20190508 to latest
+특성 파라메터 레벨업에 사용되는 포인트
+*/
+ MSG_ID_E2A = 0xe2a,
+/*20190508 to latest
+J.Lv
+*/
+ MSG_ID_E2B = 0xe2b,
+/*20190508 to latest
+AP
+*/
+ MSG_ID_E2C = 0xe2c,
+#endif
+#if PACKETVER >= 20190522
+/*20190522 to latest
+영지로 이동
+*/
+ MSG_ID_E2D = 0xe2d,
+/*20190522 to latest
+상업도/방어도 확인
+*/
+ MSG_ID_E2E = 0xe2e,
+/*20190522 to 20190605
+관리영지 "%s"(으)로 이동하시겠습니까?
+(1회 이동 시 마다 1,000제니가 소모됩니다.
+공성전 시간에는 제니의 소모가 100배로 증가합니다.)
+20190619 to 20190626
+관리영지 "%s"(으)로 이동하시겠습니까?
+이동 시 마다 %d제니가 소모됩니다.
+20190703 to latest
+관리영지 "%s"(으)로 이동하시겠습니까?
+이동 시 마다 %d제니가 소모됩니다.
+(공성전 시간에는 %d제니가 소모됩니다.)
+*/
+ MSG_ID_E2F = 0xe2f,
+/*20190522 to latest
+
+관리영지 "%s"
+
+방어도: %d / %d
+상업도: %d / %d
+*/
+ MSG_ID_E30 = 0xe30,
+/*20190522 to 20190703
+공성 영지 내에서는 다른 공성 영지로 이동 할 수 없습니다.
+20190717 to latest
+공성 영지에서는 사용할 수 없는 기능입니다.
+*/
+ MSG_ID_E31 = 0xe31,
+#endif
+#if PACKETVER >= 20190619
+/*20190619 to latest
+기본 기능 스킬을 습득하지 않은 캐릭터입니다.
+*/
+ MSG_ID_E32 = 0xe32,
+#endif
+#if PACKETVER >= 20190703
+/*20190703 to latest
+접속하신 IP는 라그나로크 제로 이용이 불가능합니다.
+고객센터 또는 홈페이지로 문의해 주십시오.
+*/
+ MSG_ID_E33 = 0xe33,
+#endif
+#if PACKETVER >= 20190717
+/*20190717 to latest
+탑승/장착 해제
+*/
+ MSG_ID_E34 = 0xe34,
+/*20190717 to latest
+가져오기
+*/
+ MSG_ID_E35 = 0xe35,
+/*20190717 to latest
+직전 노점에 등록된 아이템 정보를 가져옵니다.
+*/
+ MSG_ID_E36 = 0xe36,
+/*20190717 to latest
+서버 이슈로 인해 로그인이 제한되고 있습니다.
+*/
+ MSG_ID_E37 = 0xe37,
+/*20190717 to latest
+메시지
+*/
+ MSG_ID_E38 = 0xe38,
+/*20190717 to latest
++18 이상만 플레이가 가능합니다.
+*/
+ MSG_ID_E39 = 0xe39,
+/*20190717 to latest
+3시간 이상의 게임 플레이를 권장하지 않습니다.
+*/
+ MSG_ID_E3A = 0xe3a,
+/*20190717 to latest
+AP가 부족합니다.
+*/
+ MSG_ID_E3B = 0xe3b,
+#endif
+#if PACKETVER >= 20190731
+/*20190731 to latest
+제련도가 높아서 조합할 수 없습니다.
+*/
+ MSG_ID_E3C = 0xe3c,
+/*20190731 to latest
+제련도가 조합에 필요한 요구치보다 높습니다.
+*/
+ MSG_ID_E3D = 0xe3d,
+/*20190731 to 20191107
+'카드가 끼워져있거나 인챈트 되어 있습니다.
+20191113 to latest
+카드가 끼워져있거나 인챈트 되어 있습니다.
+*/
+ MSG_ID_E3E = 0xe3e,
+/*20190731 to latest
+∞
+?
+*/
+ MSG_ID_E3F = 0xe3f,
+/*20190731 to latest
+Z
+*/
+ MSG_ID_E40 = 0xe40,
+/*20190731 to latest
+Total : %s Zeny
+*/
+ MSG_ID_E41 = 0xe41,
+#endif
+#if PACKETVER >= 20190821
+/*20190821 to latest
+계정한정판매 등록창
+Limited Account Registration Window
+*/
+ MSG_ID_E42 = 0xe42,
+/*20190821 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_ID_E43 = 0xe43,
+/*20190821 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_ID_E44 = 0xe44,
+/*20190821 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_ID_E45 = 0xe45,
+/*20190821 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_ID_E46 = 0xe46,
+/*20190821 to latest
+판매 종료시간
+Sale end time
+*/
+ MSG_ID_E47 = 0xe47,
+/*20190821 to latest
+계정 한정
+Account only
+*/
+ MSG_ID_E48 = 0xe48,
+/*20190821 to latest
+판매기간 : %d월 %d일 %d시 %d분
+Sale period:% d month% d day% d hours% d
+*/
+ MSG_ID_E49 = 0xe49,
+/*20190821 to 20191002
+구입가능 %d개
+% D available
+20191016 to latest
+계정당 구매가능
+*/
+ MSG_ID_E4A = 0xe4a,
+/*20190821 to latest
+%d개 한정
+limited to% d
+*/
+ MSG_ID_E4B = 0xe4b,
+/*20190821 to latest
+>> ItemName : %s / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName:% s / Quantity:% d / Sales Period:% d Month:% d Day:% d Hour:% d Minute ~% d Month:% d Day:% d Hour:% d Minute
+*/
+ MSG_ID_E4C = 0xe4c,
+/*20190821 to latest
+Sold Out
+*/
+ MSG_ID_E4D = 0xe4d,
+/*20190821 to latest
+[%s]은(는) 현재 소환할 수 없는 지역에 있습니다.
+% s] is currently in a region that cannot be summoned.
+*/
+ MSG_ID_E4E = 0xe4e,
+/*20190821 to latest
+~ %d월 %d일 %d시 %d분
+% d min% d days% d days
+*/
+ MSG_ID_E4F = 0xe4f,
+/*20190821 to latest
+상품을 더이상 추가할 수 없습니다
+Can't add any more items
+*/
+ MSG_ID_E50 = 0xe50,
+#endif
+#if PACKETVER >= 20190828
+/*20190828 to latest
+장착 중인 아이템은 교환할 수 없습니다. 장착을 해제한 뒤 시도해 주시길 바랍니다.
+The item being mounted cannot be exchanged. Please unmount it and try again.
+*/
+ MSG_ID_E51 = 0xe51,
+#endif
+#if PACKETVER >= 20190904
+/*20190904 to latest
+길드 창고 이용 중엔 캐릭터 선택창으로 이동 할 수 없습니다.
+You can not move to the character selection window while using the Guild Warehouse.
+*/
+ MSG_ID_E52 = 0xe52,
+/*20190904 to latest
+아이템 태그가 포함되어 있어 사용할 수 없습니다.
+Item tag is included and cannot be used.
+*/
+ MSG_ID_E53 = 0xe53,
+/*20190904 to latest
+Monster
+*/
+ MSG_ID_E54 = 0xe54,
+/*20190904 to latest
+Unknown
+*/
+ MSG_ID_E55 = 0xe55,
+/*20190904 to latest
+Undead
+*/
+ MSG_ID_E56 = 0xe56,
+/*20190904 to latest
+Animal
+*/
+ MSG_ID_E57 = 0xe57,
+/*20190904 to latest
+Plant
+*/
+ MSG_ID_E58 = 0xe58,
+/*20190904 to latest
+Insect
+*/
+ MSG_ID_E59 = 0xe59,
+/*20190904 to latest
+Marine
+*/
+ MSG_ID_E5A = 0xe5a,
+/*20190904 to latest
+Devil
+*/
+ MSG_ID_E5B = 0xe5b,
+/*20190904 to latest
+Human
+*/
+ MSG_ID_E5C = 0xe5c,
+/*20190904 to latest
+Angel
+*/
+ MSG_ID_E5D = 0xe5d,
+/*20190904 to latest
+Dragon
+*/
+ MSG_ID_E5E = 0xe5e,
+#endif
+#if PACKETVER >= 20190918
+/*20190918 to latest
+Balance: %s %c
+*/
+ MSG_ID_E5F = 0xe5f,
+/*20190918 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money will be deducted from your total balance.
+*/
+ MSG_ID_E60 = 0xe60,
+/*20190918 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %s캐시, 무료 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money and %s Free Points will be deducted from your total balance.
+*/
+ MSG_ID_E61 = 0xe61,
+/*20190918 to latest
+호출이 거부되었습니다.
+*/
+ MSG_ID_E62 = 0xe62,
+/*20190918 to latest
+구매 한도액은 소지액을 초과할 수 없습니다.
+*/
+ MSG_ID_E63 = 0xe63,
+/*20190918 to latest
+노점을 여는데 실패하였습니다. 구매노점 개설을 닫아주시기 바랍니다.
+*/
+ MSG_ID_E64 = 0xe64,
+#endif
+#if PACKETVER >= 20191002
+/*20191002 to latest
+판매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E65 = 0xe65,
+/*20191002 to latest
+구매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E66 = 0xe66,
+/*20191002 to latest
+VTC 인증에 실패하였습니다.
+*/
+ MSG_ID_E67 = 0xe67,
+#endif
+#if PACKETVER >= 20191016
+/*20191016 to latest
+물물교환 중에는 장비를 착용할 수 없습니다.
+*/
+ MSG_ID_E68 = 0xe68,
+/*20191016 to latest
+교환하려는 품목
+*/
+ MSG_ID_E69 = 0xe69,
+/*20191016 to latest
+ 1차, 2차, 3차 직업 스킬 %d개를 더 올려 주십시오.
+*/
+ MSG_ID_E6A = 0xe6a,
+#endif
+#if PACKETVER >= 20191030
+/*20191030 to latest
+같은 아이템은 %d개까지 소유할 수 있습니다.
+*/
+ MSG_ID_E6B = 0xe6b,
+/*20191030 to latest
+같은 아이템은 한 번에 %d개까지 교환할 수 있습니다.
+*/
+ MSG_ID_E6C = 0xe6c,
+/*20191030 to latest
+해당 로덱스는 "%s"서버에서 열 수 있습니다.
+*/
+ MSG_ID_E6D = 0xe6d,
+/*20191030 to latest
+[공지]편지함의 모든 메일을 삭제하시겠습니까 ?
+(해당 "%s"서버의 메일만 삭제됩니다.)
+*/
+ MSG_ID_E6E = 0xe6e,
+/*20191030 to latest
+[공지]편지함의 모든 첨부 물품을 받으시겠습니까?
+(해당 "%s"서버의 메일의 물품만 받으실 수 있습니다.)
+*/
+ MSG_ID_E6F = 0xe6f,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 삭제 가능합니다.
+*/
+ MSG_ID_E70 = 0xe70,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 물품 받기가 가능합니다.
+*/
+ MSG_ID_E71 = 0xe71,
+/*20191030 to latest
+해당 메일은 "%s"서버에서만 내용읽기가 가능합니다.
+*/
+ MSG_ID_E72 = 0xe72,
+/*20191030 to latest
+합계 : %d z
+*/
+ MSG_ID_E73 = 0xe73,
+/*20191030 to latest
+메세지
+*/
+ MSG_ID_E74 = 0xe74,
+#endif
+#if PACKETVER >= 20191106
+/*20191106 to latest
+구매상점 개설 중에는 개인상점의 물건을 구입할 수 없습니다.
+*/
+ MSG_ID_E75 = 0xe75,
+#endif
+#if PACKETVER >= 20191113
+/*20191113 to latest
+등급강화가 성공적으로 되었습니다.
+*/
+ MSG_ID_E76 = 0xe76,
+/*20191113 to latest
+등급강화가 실패하였습니다.
+*/
+ MSG_ID_E77 = 0xe77,
+/*20191113 to latest
+등급 수치가 하향 조정 되었습니다.
+*/
+ MSG_ID_E78 = 0xe78,
+/*20191113 to latest
+장비가 파괴되었습니다.
+*/
+ MSG_ID_E79 = 0xe79,
+/*20191113 to latest
+장비가 보호되었습니다.
+*/
+ MSG_ID_E7A = 0xe7a,
+/*20191113 to latest
+재료가 선택되지 않았습니다.
+*/
+ MSG_ID_E7B = 0xe7b,
+/*20191113 to latest
+재료가 부족합니다.
+*/
+ MSG_ID_E7C = 0xe7c,
+/*20191113 to latest
+소지 금액이 부족합니다.
+*/
+ MSG_ID_E7D = 0xe7d,
+/*20191113 to latest
+아이템 공간이 부족합니다.
+*/
+ MSG_ID_E7E = 0xe7e,
+/*20191113 to latest
+장비가 보호되고 있습니다.
+*/
+ MSG_ID_E7F = 0xe7f,
+/*20191113 to latest
+장비가 파괴될 수 있습니다.
+*/
+ MSG_ID_E80 = 0xe80,
+/*20191113 to latest
+등급강화 실패 시 등급이 내려갑니다.
+*/
+ MSG_ID_E81 = 0xe81,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+*/
+ MSG_ID_E82 = 0xe82,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다.
+*/
+ MSG_ID_E83 = 0xe83,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+*/
+ MSG_ID_E84 = 0xe84,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다.
+*/
+ MSG_ID_E85 = 0xe85,
+/*20191113 to latest
+[%s] 님이 등급강화를 성공하여, [%s등급 %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_E86 = 0xe86,
+/*20191113 to latest
+[%s] 님이 [%s등급 %s] 아이템의 등급강화에 실패하였습니다.
+*/
+ MSG_ID_E87 = 0xe87,
+/*20191113 to latest
+등급 강화가 불가능한 장비입니다.
+*/
+ MSG_ID_E88 = 0xe88,
+/*20191113 to latest
+체인지 메테리얼
+*/
+ MSG_ID_E89 = 0xe89,
+/*20191113 to latest
+가나다 정렬
+*/
+ MSG_ID_E8A = 0xe8a,
+/*20191113 to 20191224
+기본 결과물은 %s %d개 이나, 낮은 확률로 최대 %d개까지 생성될 수 있습니다.
+20200108 to latest
+※[%s] %d~%d개 제작
+*/
+ MSG_ID_E8B = 0xe8b,
+/*20191113 to latest
+성공 %d%%
+*/
+ MSG_ID_E8C = 0xe8c,
+/*20191113 to latest
+아이템 태그는 소지한 아이템만 태그할 수 있습니다.
+*/
+ MSG_ID_E8D = 0xe8d,
+#endif
+#if PACKETVER >= 20191127
+/*20191127 to latest
+공격력 및 특성 공격력이 증가되었습니다.
+*/
+ MSG_ID_E8E = 0xe8e,
+/*20191127 to latest
+강인한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E8F = 0xe8f,
+/*20191127 to latest
+HP 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_E90 = 0xe90,
+/*20191127 to latest
+굳건한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E91 = 0xe91,
+/*20191127 to latest
+공격 속도 및 유도 공격 확률이 증가되었습니다.
+*/
+ MSG_ID_E92 = 0xe92,
+/*20191127 to latest
+신실한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E93 = 0xe93,
+/*20191127 to latest
+POW, CRT 및 CON 이 증가되었습니다.
+*/
+ MSG_ID_E94 = 0xe94,
+/*20191127 to latest
+베네딕툼 효과가 해제되었습니다.
+*/
+ MSG_ID_E95 = 0xe95,
+/*20191127 to latest
+SPL, WIS 및 CRT 가 증가되었습니다.
+*/
+ MSG_ID_E96 = 0xe96,
+/*20191127 to latest
+렐리지오 효과가 해제되었습니다.
+*/
+ MSG_ID_E97 = 0xe97,
+/*20191127 to latest
+특성 공격력 및 특성 마법 공격력이 증가되었습니다.
+*/
+ MSG_ID_E98 = 0xe98,
+/*20191127 to latest
+콤페텐티아 효과가 해제되었습니다.
+*/
+ MSG_ID_E99 = 0xe99,
+/*20191127 to latest
+크리티컬 데미지 비율이 증가되었습니다.
+*/
+ MSG_ID_E9A = 0xe9a,
+/*20191127 to latest
+프레센스 아치에스 효과가 해제되었습니다.
+*/
+ MSG_ID_E9B = 0xe9b,
+/*20191127 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9C = 0xe9c,
+/*20191127 to latest
+아르구투스 텔룸 효과가 해제되었습니다.
+*/
+ MSG_ID_E9D = 0xe9d,
+/*20191127 to latest
+마법 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9E = 0xe9e,
+/*20191127 to latest
+아르구투스 비타 효과가 해제되었습니다.
+*/
+ MSG_ID_E9F = 0xe9f,
+/*20191127 to latest
+Num: %d/%d Weight: %d/%d
+*/
+ MSG_ID_EA0 = 0xea0,
+#endif
+#if PACKETVER >= 20191204
+/*20191204 to latest
+서번트 웨폰 효과가 해제되었습니다.
+*/
+ MSG_ID_EA1 = 0xea1,
+/*20191204 to latest
+챠징 피어스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA2 = 0xea2,
+/*20191204 to latest
+비고르 효과가 해제되었습니다.
+*/
+ MSG_ID_EA3 = 0xea3,
+/*20191204 to latest
+공격력이 증가하고, 방어력이 감소되었습니다.
+*/
+ MSG_ID_EA4 = 0xea4,
+/*20191204 to latest
+어택 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA5 = 0xea5,
+/*20191204 to latest
+방어력이 증가하고, 공격력이 감소되었습니다.
+*/
+ MSG_ID_EA6 = 0xea6,
+/*20191204 to latest
+가드 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA7 = 0xea7,
+/*20191204 to latest
+배리어가 부여되었습니다.
+*/
+ MSG_ID_EA8 = 0xea8,
+/*20191204 to latest
+가디언 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EA9 = 0xea9,
+/*20191204 to latest
+헌신 효과로 받는 데미지가 감소되었습니다.
+*/
+ MSG_ID_EAA = 0xeaa,
+/*20191204 to latest
+리바운드 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAB = 0xeab,
+/*20191204 to latest
+성속성 마법 데미지와 암/불사속성 내성이 증가되었습니다.
+*/
+ MSG_ID_EAC = 0xeac,
+/*20191204 to latest
+홀리 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAD = 0xead,
+/*20191204 to latest
+즉시 부활 효과가 부여되었습니다.
+*/
+ MSG_ID_EAE = 0xeae,
+/*20191204 to latest
+얼티메이트 세크리파이스 효과가 해제되었습니다.
+*/
+ MSG_ID_EAF = 0xeaf,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB0 = 0xeb0,
+/*20191204 to latest
+클라이막스 효과가 해제되었습니다.
+*/
+ MSG_ID_EB1 = 0xeb1,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB2 = 0xeb2,
+/*20191204 to latest
+쉐도우 익시드 효과가 해제되었습니다.
+*/
+ MSG_ID_EB3 = 0xeb3,
+/*20191204 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_EB4 = 0xeb4,
+/*20191204 to latest
+포텐트 베넘 효과가 해제되었습니다.
+*/
+ MSG_ID_EB5 = 0xeb5,
+/*20191204 to latest
+매 공격 시, 일정 확률로 대상이 받는 데미지를 증가시킵니다.
+*/
+ MSG_ID_EB6 = 0xeb6,
+/*20191204 to latest
+인챈팅 쉐도우 효과가 해제되었습니다.
+*/
+ MSG_ID_EB7 = 0xeb7,
+#endif
+#if PACKETVER >= 20191211
+/*20191211 to latest
+토벌 카운트 On
+*/
+ MSG_ID_EB8 = 0xeb8,
+/*20191211 to latest
+토벌 카운트 Off
+*/
+ MSG_ID_EB9 = 0xeb9,
+/*20191211 to latest
+대상의 AP가 최대치입니다
+*/
+ MSG_ID_EBA = 0xeba,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBB = 0xebb,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBC = 0xebc,
+#endif
+#if PACKETVER >= 20191218
+/*20191218 to latest
+서번트 웨폰 %d개가 필요합니다.
+*/
+ MSG_ID_EBD = 0xebd,
+/*20191218 to latest
+https://member.gnjoy.com.tw/billing.aspx
+*/
+ MSG_ID_EBE = 0xebe,
+#endif
+#if PACKETVER >= 20200108
+/*20200108 to latest
+역순 정렬
+*/
+ MSG_ID_EBF = 0xebf,
+/*20200108 to latest
+검색 내용 입력
+*/
+ MSG_ID_EC0 = 0xec0,
+/*20200108 to latest
+검색
+Search
+*/
+ MSG_ID_EC1 = 0xec1,
+#endif
+#if PACKETVER >= 20200122
+/*20200122 to latest
+리서치 리포트 상태가 됩니다.
+*/
+ MSG_ID_EC2 = 0xec2,
+/*20200122 to latest
+리서치 리포트 상태가 해제됩니다.
+*/
+ MSG_ID_EC3 = 0xec3,
+/*20200122 to latest
+제조에 성공 했습니다.
+*/
+ MSG_ID_EC4 = 0xec4,
+/*20200122 to latest
+제조에 실패 했습니다.
+*/
+ MSG_ID_EC5 = 0xec5,
+/*20200122 to latest
+쉐도우 장비가 파괴 및 해제에서 보호됩니다.
+*/
+ MSG_ID_EC6 = 0xec6,
+/*20200122 to latest
+풀 쉐도우 프로텍션이 해제됩니다.
+*/
+ MSG_ID_EC7 = 0xec7,
+/*20200122 to latest
+식물형, 무형 몬스터에게 주는 데미지가 증가합니다.
+*/
+ MSG_ID_EC8 = 0xec8,
+/*20200122 to latest
+지옥 나무의 가루효과가 사라집니다.
+*/
+ MSG_ID_EC9 = 0xec9,
+#endif
+#if PACKETVER >= 20200205
+/*20200205 to latest
+공격 장치가 활성화되었습니다.
+*/
+ MSG_ID_ECA = 0xeca,
+/*20200205 to latest
+공격 장치가 해제되었습니다.
+*/
+ MSG_ID_ECB = 0xecb,
+/*20200205 to latest
+물리 방어력 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_ECC = 0xecc,
+/*20200205 to latest
+방어 장치가 해제되었습니다.
+*/
+ MSG_ID_ECD = 0xecd,
+/*20200205 to latest
+검색
+Search
+*/
+ MSG_ID_ECE = 0xece,
+#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
+
+};
+#endif /* MAP_MESSAGES_RE_H */
diff --git a/src/map/messages_sak.h b/src/map/messages_sak.h
new file mode 100644
index 000000000..723f1f1f4
--- /dev/null
+++ b/src/map/messages_sak.h
@@ -0,0 +1,8268 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_MESSAGES_SAK_H
+#define MAP_MESSAGES_SAK_H
+
+/* This file is autogenerated, please do not commit manual changes
+
+Latest version: 20090617
+*/
+
+enum clif_messages {
+/*20031029 to latest
+동의 하십니까?
+Do you agree?
+*/
+ MSG_DO_YOU_AGREE = 0x0,
+/*20031029 to latest
+서버 연결 실패
+Failed to Connect to Server.
+*/
+ MSG_SERVER_CONNECTION_FAILED = 0x1,
+/*20031029 to latest
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+*/
+ MSG_UNABLE_TO_CONNECT_SERVER = 0x2,
+/*20031029 to 20080618
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+20080624 to latest
+서버와 연결이 끊어졌습니다!
+Disconnected from Server!
+*/
+ MSG_BANNED = 0x3,
+/*20031029 to latest
+서버 종료됨
+Server Closed.
+*/
+ MSG_SERVER_OFF = 0x4,
+/*20031029 to latest
+같은 계정으로 다른 사용자가 로그인 하였습니다.
+Someone has Logged in with this ID.
+*/
+ MSG_DOUBLE_LOGIN_PROHIBITED = 0x5,
+/*20031029 to latest
+등록되지 않은 계정입니다. 다시 확인 바랍니다.
+Unregistered ID. Please make sure you have a registered account and you have correctly typed in the user ID.
+*/
+ MSG_INCORRECT_USERID = 0x6,
+/*20031029 to 20070704
+비밀번호가 틀립니다
+20070710 to latest
+입력하신 비밀번호가 올바르지 않습니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_PASSWORD = 0x7,
+/*20031029 to latest
+본 ID 는 사용기간이 만료 되었습니다
+This ID is expired.
+*/
+ MSG_ID_EXPIRED = 0x8,
+/*20031029 to latest
+서버 접근 거부
+Rejected from Server.
+*/
+ MSG_ACCESS_DENIED = 0x9,
+/*20031029 to latest
+같은 캐릭터 이름이 있습니다.
+Character Name already exists.
+*/
+ MSG_CHARACTER_NAME_ALREADY_EXISTS = 0xa,
+/*20031029 to latest
+캐릭터 생성 거부됨
+Character Creation is denied.
+*/
+ MSG_CHARACTER_CREATION_DENIED = 0xb,
+/*20031029 to latest
+캐릭터 삭제 거부
+Character Deletion is denied.
+*/
+ MSG_CANNOT_DELETE_CHARACTER = 0xc,
+/*20031029 to latest
+방제목를 입력하세요.
+Please Enter Room Title.
+*/
+ MSG_ENTER_ROOM_TITLE = 0xd,
+/*20031029 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_SENTANGE = 0xe,
+/*20031029 to latest
+암호를 입력하세요.
+Please enter Password.
+*/
+ MSG_ENTER_PASSWORD = 0xf,
+/*20031029 to latest
+암호를 영문 4자 이상 입력하세요.
+Please enter Password. Passwords must be at least 4 characters long.
+*/
+ MSG_Enter_Password_more_than_4_char = 0x10,
+/*20031029 to latest
+종료 하시겠습니까?
+Are you sure that you want to quit?
+*/
+ MSG_DO_YOU_REALLY_WANT_TO_QUIT = 0x11,
+/*20031029 to latest
+4자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Passwords are at least 4 characters long. Please try again.
+*/
+ MSG_NAME_MUST_EXCEED_4_CHAR = 0x12,
+/*20031029 to 20070704
+캐릭터를 삭제하겠습니까?
+20070618 to latest
+한 번 삭제된 캐릭터 및 관련 정보는 다시 복구되지 않습니다. 캐릭터를 삭제하시겠습니까?
+Are you sure that you want to delete this character?
+*/
+ MSG_DELETE_CHARACTER = 0x13,
+/*20031029 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_NAME = 0x14,
+/*20031029 to latest
+이름을 입력해 주세요.(한글 2자 영문 4자 이상)
+Character Name must be at least 4 characters long.
+*/
+ MSG_ENTER_NAME_MORE_THAN_4_CHAR = 0x15,
+/*20031029 to latest
+명령어 일람: /h
+Command List: /h | /help
+*/
+ MSG_LIST_COMMAND = 0x16,
+/*20031029 to latest
+이펙트 On
+Effects On
+*/
+ MSG_EFFECT_ON = 0x17,
+/*20031029 to latest
+이펙트 Off
+Effects Off
+*/
+ MSG_EFFECT_OFF = 0x18,
+/*20031029 to latest
+사운드 볼륨
+Sound Volume
+*/
+ MSG_VOLUME_OF_SOUND = 0x19,
+/*20031029 to latest
+배경음악 볼륨
+BGM Volume
+*/
+ MSG_VOLUME_OF_BGM = 0x1a,
+/*20031029 to latest
+효과음 On
+Sound Effects On
+*/
+ MSG_SOUND_ON = 0x1b,
+/*20031029 to latest
+효과음 Off
+Sound Effects Off
+*/
+ MSG_SOUND_OFF = 0x1c,
+/*20031029 to latest
+프레임스킵 On
+Frame Skip On
+*/
+ MSG_FRAME_SKIP_ON = 0x1d,
+/*20031029 to latest
+프레임스킵 Off
+Frame Skip Off
+*/
+ MSG_FRAME_SKIP_OFF = 0x1e,
+/*20031029 to latest
+배경음악 On
+BGM On
+*/
+ MSG_BGM_ON = 0x1f,
+/*20031029 to latest
+배경음악 Off
+BGM Off
+*/
+ MSG_BGM_OFF = 0x20,
+/*20031029 to latest
+/h or /help: 명령어 일람
+/h or /help: Shows this Command Help List
+*/
+ MSG_EXPLAIN_HELP = 0x21,
+/*20031029 to latest
+/w or /who or /접속자 or /누구: 현재 접속자수 보기
+/w or /who or /player or /who: wiew current the number of player
+*/
+ MSG_EXPLAIN_WHO = 0x22,
+/*20031029 to latest
+/음악 : 배경음악 On Off
+/music: Turns BGM On or Off
+*/
+ MSG_EXPLAIN_MUSIC = 0x23,
+/*20031029 to latest
+/효과음 : 효과음 On Off
+/sound: Turns Sound Effects On or Off
+*/
+ MSG_EXPLAIN_SOUND = 0x24,
+/*20031029 to latest
+/이펙트 : 이펙트 On Off
+/effect: Effects On or Off
+*/
+ MSG_EXPLAIN_EFFECT = 0x25,
+/*20031029 to latest
+/좌표 or /장소: 현재 위치 표시
+/where: Shows your present location
+*/
+ MSG_EXPLAIN_POS = 0x26,
+/*20031029 to latest
+/skip : 프래임스킵 On Off
+/skip: Turns Frame Skip On or Off
+*/
+ MSG_EXPLAIN_FRAMESKIP = 0x27,
+/*20031029 to latest
+/v (0~127): 효과음 볼륨조정
+/v (0~127): Controls the volume of the Sound Effects
+*/
+ MSG_EXPLAIN_SOUNDVOLUME = 0x28,
+/*20031029 to latest
+/bv (0~127): 배경음악 볼륨조정
+/bv (0~127): Controls the volume of the BGM
+*/
+ MSG_EXPLAIN_BGMVOLUME = 0x29,
+/*20031029 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당캐릭터에 대해 귓말차단
+/ex (Character Name): Blocks whispering from the Character
+*/
+ MSG_EXPLAIN_SAYISOLATION = 0x2a,
+/*20031029 to latest
+/ex or /차단 : 귓말차단 캐릭터 리스트
+/ex: View a list of Characters you have Blocked
+*/
+ MSG_EXPLAIN_LIST_SAYISOLATION_CHAR = 0x2b,
+/*20031029 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당캐릭터에 대해 귓말허용
+/in (Character Name): Allows whispering from the Character
+*/
+ MSG_EXPLAIN_SAY_PERMIT = 0x2c,
+/*20031029 to latest
+/inall or /해제전부 : 모두에게 귓말허용
+/inall: Allows whispers from anyone
+*/
+ MSG_EXPLAIN_SAY_PERMITALL = 0x2d,
+/*20031029 to latest
+/exall or /차단전부 : 모두에게 귓말차단
+/exall: Blocks whispers from everyone
+*/
+ MSG_EXPLAIN_SAY_ISOLATEALL = 0x2e,
+/*20031029 to latest
+다른유저 캐릭터를 마우스 오른버튼을 누르고 있는 상태에서 왼버튼으로 클릭하면 그캐릭터이름이 귓말콤보박스에 저장됩니다.
+Right click on a character and select [Register as a Friend] to add a person to your Friend List.
+*/
+ MSG_EXPLAIN_TIP1 = 0x2f,
+/*20031029 to latest
+단축아이탬창(F12) 소비장비 아이템을 드래그한후 사용하세요. 사용키(F1F2F3F4F5F6F7F8F9)
+F12 Brings up a Hotkey Window which allows you to drag and drop Recovery Items, Equipment and Skills into it for faster access.
+*/
+ MSG_EXPLAIN_TIP2 = 0x30,
+/*20031029 to latest
+같은말을 3번이상 연속해서 전송할 수 없습니다.
+You can't type the same word/phrase more than 3 times.
+*/
+ MSG_NO_SAME_SENTANCE = 0x31,
+/*20031029 to latest
+불량단어 검출로 전송이 중단 되었습니다.
+Chat Filter: Yeah, uh, I don't think so buddy...
+*/
+ MSG_NO_SEND_BECAUSE_INSULT = 0x32,
+/*20031029 to latest
+같은아이템은 한번만 올릴수 있습니다.
+You cannot overlap items on a window.
+*/
+ MSG_CAN_DRAG_ITEM_OLNY_ONETIME = 0x33,
+/*20031029 to latest
+무게가 초과하여 아이템을 가질 수 없습니다.
+You cannot carry more items because you are overweight.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_WEIGHT = 0x34,
+/*20031029 to latest
+아이템을 가질 수 없습니다.
+You cannot get the item.
+*/
+ MSG_CANT_GET_ITEM = 0x35,
+/*20031029 to latest
+거래가 잘 이루어졌습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SECCESS = 0x36,
+/*20031029 to latest
+돈이 부족합니다.
+You do not have enough zeny.
+*/
+ MSG_INSUFFICIENT_MONEY = 0x37,
+/*20031029 to latest
+무게가 초과 되었습니다.
+You are over your Weight Limit.
+*/
+ MSG_OVER_WEIGHT = 0x38,
+/*20031029 to latest
+거래가 실패 했습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAIL = 0x39,
+/*20031029 to latest
+모두에게 귓말거부상태로됨
+You've blocked whispers from everyone.
+*/
+ MSG_REFUSE_HEAR_ALL = 0x3a,
+/*20031029 to latest
+모두에게 귓말거부요청 실패함
+You've failed to block all whispers.
+*/
+ MSG_REQ_REFUSE_HEAR_ALL_FAIL = 0x3b,
+/*20031029 to latest
+모두에게 귓말가능상태가됨
+You've allowed whispers from everyone.
+*/
+ MSG_HEAR_ALL = 0x3c,
+/*20031029 to latest
+모두에게 귓말가능요청 실패함
+You've failed to allow all whispers.
+*/
+ MSG_REQ_HEAR_ALL_FAIL = 0x3d,
+/*20031029 to latest
+귓말 거부 리스트가 없습니다
+You have no Block List.
+*/
+ MSG_NO_REFUSE_HEAR_LIST = 0x3e,
+/*20031029 to latest
+-귓말 거부 리스트-
+[ Character Block List ]
+*/
+ MSG_REFUSE_HEAR_LIST = 0x3f,
+/*20031029 to latest
+방이 잘 만들어 졌습니다.
+Room has been successfully created.
+*/
+ MSG_ROOM_IS_MADE = 0x40,
+/*20031029 to latest
+방갯수가 허용갯수를 초과 하였습니다.
+Room Limit Exceeded.
+*/
+ MSG_TOO_MANY_ROOM = 0x41,
+/*20031029 to latest
+같은 방제목이 있습니다.
+Same Room exists.
+*/
+ MSG_SAME_ROOM_TITLE = 0x42,
+/*20031029 to latest
+인원초과로 방에 들어갈 수 없습니다.
+The Room is full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_ROOM = 0x43,
+/*20031029 to latest
+강제로 퇴장된 방입니다.
+You have been kicked out of this room.
+*/
+ MSG_YOU_HAVE_BANNED_FROM_THE_ROOM = 0x44,
+/*20031029 to latest
+교환요청을 거절 했습니다.
+The deal has been rejected.
+*/
+ MSG_REJECT_DEAL = 0x45,
+/*20031029 to latest
+교환가능거리를 벗어났습니다.
+You are too far away from the person to trade.
+*/
+ MSG_TOO_FAR_TO_DEAL = 0x46,
+/*20031029 to latest
+해당 캐릭터가 없습니다.
+The Character is not currently online or does not exist.
+*/
+ MSG_CHARACTER_IS_NOT_EXIST = 0x47,
+/*20031029 to latest
+다른캐릭터와 교환중입니다.
+The person is in another deal.
+*/
+ MSG_CHARACTER_IS_DEALING = 0x48,
+/*20031029 to latest
+상태캐릭터 중량초과로 올려놓을수가 없습니다.
+*/
+ MSG_CHARACTER_IS_OVER_WEIGHT = 0x49,
+/*20031029 to latest
+거래가 취소 되었습니다.
+The deal has been canceled.
+*/
+ MSG_DEAL_IS_CANCELED = 0x4a,
+/*20031029 to latest
+아이템 교환이 잘 되었습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SUCCESS = 0x4b,
+/*20031029 to latest
+아이템 교환이 실패 하였습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAILED = 0x4c,
+/*20031029 to latest
+파티가 만들어졌습니다.
+Party has successfully been organized.
+*/
+ MSG_PARTY_MAKE_SUCCEED = 0x4d,
+/*20031029 to latest
+같은 파티이름이 있습니다.
+That Party Name already exists.
+*/
+ MSG_SAME_PARTY_NAME = 0x4e,
+/*20031029 to latest
+이미 파티에 속해있습니다.
+The Character is already in a party.
+*/
+ MSG_YOU_ARE_ALREADY_IN_PARTY = 0x4f,
+/*20031029 to latest
+다른파티에 가입되어 있습니다.
+The Character already joined another party.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_PARTY = 0x50,
+/*20031029 to latest
+파티가입을 거부했습니다.
+Request for party rejected.
+*/
+ MSG_CHARACTER_REJECT_JOIN = 0x51,
+/*20031029 to latest
+파티가입을 수락했습니다.
+Request for party accepted.
+*/
+ MSG_CHARACTER_ACCEPT_JOIN = 0x52,
+/*20031029 to latest
+파티정원을 초과했습니다.
+Party Capacity exceeded.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_PARTY = 0x53,
+/*20031029 to latest
+파티에서 탈퇴하였습니다.
+You left the party.
+*/
+ MSG_YOU_LEAVE_FROM_PARTY = 0x54,
+/*20031029 to latest
+전체에게 보냄
+Send to All
+*/
+ MSG_SEND_TO_ALL = 0x55,
+/*20031029 to latest
+파티에게 보냄
+Send to Party
+*/
+ MSG_SEND_TO_PARTY = 0x56,
+/*20031029 to latest
+님과의 거래요청
+Request a deal with %s
+*/
+ MSG_REQ_DEAL_WITH = 0x57,
+/*20031029 to latest
+님 파티에 가입요청
+Ask %s to join your party
+*/
+ MSG_REQ_JOIN_PARTY = 0x58,
+/*20031029 to latest
+비공개 :
+Pri:
+*/
+ MSG_ROOM_PRIVATE = 0x59,
+/*20031029 to latest
+공개 :
+Pub:
+*/
+ MSG_ROOM_PUBLIC = 0x5a,
+/*20031029 to latest
+마지막 체크지점부터 시작하려면 '재시작'을 캐릭터 선택으로 돌아가려면 '종료'를 눌러주세요.
+Click ''Restart'' to go back to your save point or click ''Exit'' to select another character.
+*/
+ MSG_RESTART_MSG = 0x5b,
+/*20031029 to latest
+원하는 거래를 선택하세요.
+Please select a Deal Type.
+*/
+ MSG_SELECT_DEAL_TYPE = 0x5c,
+/*20031029 to latest
+님이 거래를 요청했습니다.
+ requests a deal.
+*/
+ MSG_SUGGEST_DEAL = 0x5d,
+/*20031029 to latest
+ 파티에서 초청 메시지가 왔습니다. 합류하겠습니까?
+ Party has sent you an invitation. Would you like to join?
+*/
+ MSG_SUGGEST_JOIN_PARTY = 0x5e,
+/*20031029 to latest
+명령이 틀렸습니다.
+Invalid Command
+*/
+ MSG_INVALID_COMMAND = 0x5f,
+/*20031029 to latest
+탈퇴하기
+Leave party
+*/
+ MSG_LEAVE_PARTY = 0x60,
+/*20031029 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL = 0x61,
+/*20031029 to latest
+쪽지보내기
+Send Message
+*/
+ MSG_MSG = 0x62,
+/*20031029 to latest
+1:1 대화
+1:1 Chat
+*/
+ MSG_1ON1 = 0x63,
+/*20031029 to latest
+정보
+Information
+*/
+ MSG_CHARACTER_INFO = 0x64,
+/*20031029 to latest
+파티설정
+Party Setup
+*/
+ MSG_PARTY_SETTING = 0x65,
+/*20031029 to latest
+친구
+Friend
+*/
+ MSG_FRIEND = 0x66,
+/*20031029 to latest
+파티
+Party
+*/
+ MSG_PARTY = 0x67,
+/*20031029 to latest
+장착아이템
+Equipment
+*/
+ MSG_EQUIPED_ITEM = 0x68,
+/*20031029 to latest
+스테이터스
+Status
+*/
+ MSG_STATUS_ = 0x69,
+/*20031029 to latest
+소지아이템
+Inventory
+*/
+ MSG_ITEM = 0x6a,
+/*20031029 to latest
+/결성 [파티이름] : 파티결성 /탈퇴 : 파티탈퇴
+/organize ''Party Name'' To organize a party. Type /leave To leave a Party.
+*/
+ MSG_EXPLAIN_PARTY = 0x6b,
+/*20031029 to latest
+자신이 파티리더일때 캐릭터를 오른버튼으로 클릭하면 파티에 가입요청하기 메뉴가 뜹니다.
+If you are the party master, you can invite someone into your party by right-clicking on a Character.
+*/
+ MSG_EXPLAIN_TIP3 = 0x6c,
+/*20031029 to latest
+회복
+Consumables
+*/
+ MSG_RESTORE = 0x6d,
+/*20031029 to latest
+공격
+Attack
+*/
+ MSG_ATTACK = 0x6e,
+/*20031029 to latest
+보조
+Support
+*/
+ MSG_SUPPORT = 0x6f,
+/*20031029 to latest
+전체
+All
+*/
+ MSG_ALL = 0x70,
+/*20031029 to latest
+무기
+Weapons
+*/
+ MSG_WEAPON = 0x71,
+/*20031029 to latest
+방어
+Defense
+*/
+ MSG_DEFENCE = 0x72,
+/*20031029 to latest
+수
+Water
+*/
+ MSG_WATER = 0x73,
+/*20031029 to latest
+지
+Earth
+*/
+ MSG_EARTH = 0x74,
+/*20031029 to latest
+화
+Fire
+*/
+ MSG_FIRE = 0x75,
+/*20031029 to latest
+풍
+Wind
+*/
+ MSG_WIND = 0x76,
+/*20031029 to latest
+같은종류의 장비아이템은 한번에 한개만 살 수 있습니다.
+Please avoid buying 2 of the same items at one time.
+*/
+ MSG_EQUIPITEM_OLNY_ONE = 0x77,
+/*20031029 to latest
+창모드에서 실행 할때는 16비트 컬러로 맞춰주세요.
+Please change your desktop Color Depth to 16-bit when running Ragnarok in windowed mode.
+*/
+ MSG_ONLY_16BIT_WHEN_WINDOWMODE = 0x78,
+/*20031029 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_PLEASE_BE_PATIENT = 0x79,
+/*20031029 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_WAITING_RESPONSE_FROM_SERVER = 0x7a,
+/*20031029 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_MAKING_CHARACTER = 0x7b,
+/*20031029 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_DELETING_CHARACTER = 0x7c,
+/*20031029 to latest
+방 만들기
+Make a Room
+*/
+ MSG_MAKING_ROOM = 0x7d,
+/*20031029 to latest
+방셋팅 바꾸기
+Room Setup
+*/
+ MSG_CHANGE_ROOM_SETTING = 0x7e,
+/*20031029 to latest
+강퇴시키기
+Kick Character Out
+*/
+ MSG_BAN = 0x7f,
+/*20031029 to latest
+방장권한 주기
+Give Master Authority
+*/
+ MSG_GIVE_GIVE_ROOM_POWER = 0x80,
+/*20031029 to latest
+정보보기
+View Information
+*/
+ MSG_SEE_INFORMATION_OF_CHARACTER = 0x81,
+/*20031029 to latest
+대화방
+Chat Room
+*/
+ MSG_CHAT_ROOM = 0x82,
+/*20031029 to latest
+명
+Ppl
+*/
+ MSG_COUNT_UNIT_OF_PEOPLE = 0x83,
+/*20031029 to latest
+/앉기 or /sit : 앉기. 앉아있을때 서기
+/sit: Sit command. If you are sitting, you will stand instead.
+*/
+ MSG_EXPLAIN_SIT = 0x84,
+/*20031029 to latest
+/서기 or /stand : 서기. 서있을때 앉기
+/stand: Stand command. If you are standing, you will sit instead.
+*/
+ MSG_EXPLAIN_STAND = 0x85,
+/*20031029 to latest
+/채팅방 or /chat : 채팅방 만들기창 띄우기
+/chat: Creates a Chat Room
+*/
+ MSG_EXPLAIN_MAKE_CHAT = 0x86,
+/*20031029 to latest
+/q : 채팅방 나가기.
+/q: Leaves a Chat Room
+*/
+ MSG_EXPLAIN_EXIT_CHAT_ROOM = 0x87,
+/*20031029 to latest
+/거래 [캐릭터이름] or /교환 [캐릭터이름] or /deal [캐릭터이름] : 해당 캐릭터와 거래요청
+/deal ''Character Name'' Requests a deal with a character
+*/
+ MSG_EXPLAIN_DEAL = 0x88,
+/*20031029 to latest
+/결성 [파티이름] or /organize [파티이름] : 파티결성
+/organize ''Party Name'' Organizes a party
+*/
+ MSG_EXPLAIN_ORGANIZE_PARTY = 0x89,
+/*20031029 to latest
+/탈퇴 or /leave : 파티 탈퇴
+/leave: Leaves a party
+*/
+ MSG_EXPLAIN_LEAVE_PARTY = 0x8a,
+/*20031029 to latest
+/제명 [캐릭터이름] or /expel [캐릭터이름] : 해당캐릭터를 파티에서 제명시킴
+/expel ''Character Name'' kicks a Character out of your party
+*/
+ MSG_EXPLAIN_EXPEL_PARTY_MEMBER = 0x8b,
+/*20031029 to latest
+[Alt] + [End] : 플레이어 hp/sp 게이지 On Off
+[Alt] + [End]: Turns HP/SP Bar On or Off
+*/
+ MSG_EXPLAIN_TIP4 = 0x8c,
+/*20031029 to latest
+[Alt] + [Home] : 지면 커서 표시 On Off
+[Alt] + [Home]: Turns Ground Cursor On or Off
+*/
+ MSG_EXPLAIN_TIP5 = 0x8d,
+/*20031029 to latest
+[Insert] : 앉기 서기
+[Insert]: Makes you sit or stand. (Hotkey to toggle between /sit and /stand)
+*/
+ MSG_EXPLAIN_TIP6 = 0x8e,
+/*20031029 to latest
+MVP가 되셨습니다!! MVP 아이템은
+Congratulations! You are the MVP! Your reward item is
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM = 0x8f,
+/*20031029 to latest
+ !!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM2 = 0x90,
+/*20031029 to latest
+MVP가 되셨습니다!! 특별경험치
+Congratulations! You are the MVP! Your reward EXP Points are
+*/
+ MSG_YOU_RECEIVE_MVP_EXP = 0x91,
+/*20031029 to latest
+ 획득!!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_EXP2 = 0x92,
+/*20031029 to latest
+MVP가 되셨습니다만 무게초과로 MVP 아이템을 가질 수 없었습니다!!
+You are the MVP, but you can't take the reward because you are over your weight limit.
+*/
+ MSG_YOU_THROW_MVPITEM = 0x93,
+/*20031029 to latest
+ 없는 캐릭터 이름 입니다.
+There is no such character name or the user is offline.
+*/
+ MSG_NOT_EXIST_CHARACTER = 0x94,
+/*20031029 to latest
+ 수신 거부 상태입니다.
+ doesn't want to receive your messages.
+*/
+ MSG_NO_RECEIVE_MODE = 0x95,
+/*20031029 to latest
+ 모든 캐릭터에 대해 수신 거부 상태 입니다.
+ is not in the mood to talk with anyone.
+*/
+ MSG_NO_RECEIVE_MODE_FOR_ALL = 0x96,
+/*20031029 to latest
+캐릭터 접속끊기 성공.
+Killed/Disconnected User.
+*/
+ MSG_SUCCESS_DISCONNECT_CHARACTER = 0x97,
+/*20031029 to latest
+캐릭터 접속끊기 실패.
+Kill has failed.
+*/
+ MSG_FAIL_DISCONNECT_CHARACTER = 0x98,
+/*20031029 to latest
+%s %d 개 획득
+You got %s (%d).
+*/
+ MSG_GET_ITEM = 0x99,
+/*20031029 to latest
+[Alt] + [=] : 알파벳 간격이 넓어졌을때 되돌리기.
+[Alt] + [=]: Fix the interval error between letters.
+*/
+ MSG_EXPLAIN_TIP7 = 0x9a,
+/*20031029 to latest
+[F10] : 채팅창 크기조정 [Alt] + [F10] : 채팅창 On Off
+[F10]: To toggle Chat Window size; [Alt] + [F10]: Toggle Chat Window On or Off
+*/
+ MSG_EXPLAIN_TIP8 = 0x9b,
+/*20031029 to latest
+귓속말 하는법 : 채팅창 왼쪽 입력란에 캐릭터이름을 입력하고 오른쪽 입력란에 말을 입력하면 됩니다. TAB키로 두입력란 사이로 커서를 이동할 수 있습니다.
+How to Whisper: Enter a Character's Name on the left side of chat window and type your message on the right side. The Tab key helps you move between these boxes.
+*/
+ MSG_EXPLAIN_TIP9 = 0x9c,
+/*20031029 to latest
+/! /? /기쁨 /하트 /땀 /아하 /짜증 /화 /돈 /... /가위 /바위 /보 : Alt + (1~9) Ctrl + (-=\) 에 대응되는 명령어 입니다.
+/!,/?,/ho,/lv,/lv2,/swt,/ic,/an,/ag,/$,/….,/thx,/wah,/sry,/heh,/swt2,/hmm,/no1,/??,/omg,/oh,/X,/hp,/go,/sob,/gg,/kis,/kis2,/pif,/ok: Emotion icons corresponding to Alt + (1~9) Ctrl + (-=\\)
+*/
+ MSG_EXPLAIN_TIP10 = 0x9d,
+/*20031029 to latest
+파티원에게 말하는법 : 말의 제일앞에 '%'를 붙이면 파티원에게 말이 갑니다. (예: "%안녕")
+How to Speak to Party: Add % in front of every message.(Example: \%Hello\)
+*/
+ MSG_EXPLAIN_TIP11 = 0x9e,
+/*20031029 to latest
+스킬레벨이 부족합니다. 교환 불능.
+You haven't learned enough Basic Skills to Trade.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE1 = 0x9f,
+/*20031029 to latest
+스킬레벨이 부족합니다. 이모션 불능.
+You haven't learned enough Basic Skills to use Emotion icons.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE2 = 0xa0,
+/*20031029 to latest
+스킬레벨이 부족합니다. 앉기 불능.
+You haven't learned enough Basic Skills to Sit.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE3 = 0xa1,
+/*20031029 to latest
+스킬레벨이 부족합니다. 채팅방만들기 불능.
+You haven't learned enough Basic Skills to create a chat room.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE4 = 0xa2,
+/*20031029 to latest
+스킬레벨이 부족합니다. 파티만들기 불능
+You haven't learned enough Basic Skills to Party.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5 = 0xa3,
+/*20031029 to latest
+스킬레벨이 부족합니다. 외치기 불능
+You haven't learned enough skills to Shout.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE6 = 0xa4,
+/*20031029 to latest
+스킬레벨이 부족합니다. pk 불능
+You haven't learned enough skills for Pking.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE7 = 0xa5,
+/*20031029 to latest
+사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY = 0xa6,
+/*20031029 to latest
+아이템 상점
+Item Shop
+*/
+ MSG_ITEM_STORE = 0xa7,
+/*20031029 to latest
+팔고자하는 품목
+Selling Items
+*/
+ MSG_ITEMS_FOR_SELL = 0xa8,
+/*20031029 to latest
+보관아이템
+Storage
+*/
+ MSG_ITEMS_THAT_IS_STORED = 0xa9,
+/*20031029 to latest
+ 장비가 장착 되었습니다.
+ is put on.
+*/
+ MSG_ITEM_IS_EQUIPED = 0xaa,
+/*20031029 to latest
+ 장비가 해제 되었습니다.
+ is taken off.
+*/
+ MSG_ITEM_IS_REMOVED = 0xab,
+/*20031029 to latest
+귓말리스트에 이름넣기
+To add names on the Whispering List
+*/
+ MSG_ADD_TO_WHISPER_CHAR_LIST = 0xac,
+/*20031029 to latest
+스크린샷 찍는법 : [Print Screen]키나 [Scroll Lock]키를 누르면 됩니다.
+How to Take Screen Shots: Press [Print Screen] or [Scroll Lock]
+*/
+ MSG_EXPLAIN_TIP12 = 0xad,
+/*20031029 to latest
+오늘의 팁
+Tip of the Day
+*/
+ MSG_TIPOFTHEDAY = 0xae,
+/*20031029 to latest
+^3850a0알고 계셨습니까... ^000000 //^709fed
+^3850a0Did you know...?^709fed
+*/
+ MSG_DIDYOUKNOW = 0xaf,
+/*20031029 to latest
+시작할때 열기
+Display at startup
+*/
+ MSG_SHOWTIPSATSTARTUP = 0xb0,
+/*20031029 to latest
+/tip : 오늘의팁 열기
+/tip: Opens ''Tip of the Day''
+*/
+ MSG_EXPLAIN_OPENTIP = 0xb1,
+/*20031029 to latest
+현재 접속자 %d명
+There are %d Players Currently Connected.
+*/
+ MSG_NUMPEOPLE = 0xb2,
+/*20031029 to latest
+(%s)님이 입장 하였습니다.
+(%s) has entered.
+*/
+ MSG_USERGETINTHEROOM = 0xb3,
+/*20031029 to latest
+(%s)님이 퇴장 하였습니다.
+(%s) has left.
+*/
+ MSG_USERGETOUTOFTHEROOM = 0xb4,
+/*20031029 to latest
+(%s)님이 강제 퇴장 되었습니다.
+(%s) was kicked out.
+*/
+ MSG_USERGETOUTOFTHEROOMBYFORCE = 0xb5,
+/*20031029 to latest
+ %d 개
+%d ea.
+*/
+ MSG_EA = 0xb6,
+/*20031029 to latest
+%s : %d 개
+%s: %d ea.
+*/
+ MSG_EA2 = 0xb7,
+/*20031029 to latest
+%s %s : %d 개
+%s %s: %d
+*/
+ MSG_EA3 = 0xb8,
+/*20031029 to latest
+팔 수 있는 품목
+Available Items to sell
+*/
+ MSG_ITEMSYOUCANSELL = 0xb9,
+/*20031029 to latest
+상점에서 파는 품목
+Shop Items
+*/
+ MSG_SHOPITEMS = 0xba,
+/*20031029 to latest
+알 수 없는곳
+Unknown Area
+*/
+ MSG_NOWHERE = 0xbb,
+/*20031029 to latest
+서버와 언어가 맞지 않습니다.
+Your Client language doesn't match the Server language.
+*/
+ MSG_CLIENTTYPEMISMATCH = 0xbc,
+/*20031029 to latest
+아이템을 버릴려면 장비창을 닫으세요.
+Please move your equipment to the inventory. And close the equipment window.
+*/
+ MSG_CLOSEEQUIPWND = 0xbd,
+/*20031029 to latest
+영어만 됩니다.
+This server provides English Text Characters Only.
+*/
+ MSG_ENGLISHONLY = 0xbe,
+/*20031029 to latest
+지금은 지원되지 않습니다.
+This is not implemented yet.
+*/
+ MSG_NOTSUPPORTEDYET = 0xbf,
+/*20031029 to latest
+귓말 리스트가 없습니다.
+No Whisper List.
+*/
+ MSG_NOWHISPERLIST = 0xc0,
+/*20031029 to latest
+ 에게 귓말거부상태로됨
+: Whispering Blocked.
+*/
+ MSG_WHISPERIGNORESUCCESS = 0xc1,
+/*20031029 to latest
+ 에게 귓말거부 요청실패함
+: Whispering Block has failed.
+*/
+ MSG_WHISPERIGNOREFAILED1 = 0xc2,
+/*20031029 to latest
+ 에게 귓말거부 요청실패함 (인원초과)
+: Whispering Block has failed. Block List is full.
+*/
+ MSG_WHISPERIGNOREFAILED2 = 0xc3,
+/*20031029 to latest
+ 에게 귓말가능상태로됨
+: Whispering accepted.
+*/
+ MSG_WHISPERNOIGNORESUCCESS = 0xc4,
+/*20031029 to latest
+ 에게 귓말가능 요청실패함
+: Command has failed.
+*/
+ MSG_WHISPERNOIGNOREFAILED1 = 0xc5,
+/*20031029 to latest
+ 에게 귓말가능 요청실패함 (인원초과)
+: Command has failed. Block List is full.
+*/
+ MSG_WHISPERNOIGNOREFAILED2 = 0xc6,
+/*20031029 to latest
+이름의 처음과 마지막에는 공백문자를 사용할 수 없습니다.
+You cannot put a space at the beginning or end of a name.
+*/
+ MSG_NO_SPACE_IN_NAME = 0xc7,
+/*20031029 to latest
+비공개
+Private
+*/
+ MSG_ROOM_PRIVATE2 = 0xc8,
+/*20031029 to latest
+공개
+Public
+*/
+ MSG_ROOM_PUBLIC2 = 0xc9,
+/*20031029 to latest
+SP가 부족합니다.
+Not Enough SP
+*/
+ MSG_USESKILL_FAIL_SP_INSUFFICIENT = 0xca,
+/*20031029 to latest
+HP가 부족합니다.
+Not Enough HP
+*/
+ MSG_USESKILL_FAIL_HP_INSUFFICIENT = 0xcb,
+/*20031029 to latest
+스킬사용 실패.
+Skill has failed.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE8 = 0xcc,
+/*20031029 to latest
+훔치기 실패.
+Steal has failed.
+*/
+ MSG_FAIL_STEAL = 0xcd,
+/*20031029 to latest
+교환창
+Trade
+*/
+ MSG_EXCHANGE = 0xce,
+/*20031029 to latest
+독걸기 실패.
+Envenom skill has failed.
+*/
+ MSG_FAIL_POISON = 0xcf,
+/*20031029 to latest
+이 아이디로는 이 서버에 접속할 수 없습니다.
+You cannot use this ID on this server.
+*/
+ MSG_ID_MISMATCH = 0xd0,
+/*20031029 to latest
+스피드가 향상되었습니다.
+Your Speed has increased.
+*/
+ MSG_SPEEDUP = 0xd1,
+/*20031029 to latest
+스피드가 감소되었습니다.
+Your Speed has decreased.
+*/
+ MSG_SPEEDDOWN = 0xd2,
+/*20031029 to latest
+/기억 : 워프할 장소 기억(워프 스킬이 있는경우)
+/memo: To memorize a place as Warp Point (If you are an Acolyte Class character)
+*/
+ MSG_EXPLAIN_TIP13 = 0xd3,
+/*20031029 to latest
+임의의 위치
+Random Area
+*/
+ MSG_RANDOM_POS = 0xd4,
+/*20031029 to latest
+워프 할 위치를 선택하세요.
+Select an Area to Warp
+*/
+ MSG_SELECTWHERETOWARP = 0xd5,
+/*20031029 to latest
+스킬레벨이 부족합니다.
+Skill Level is not high enough
+*/
+ MSG_NOTENOUGHSKILLLEVEL = 0xd6,
+/*20031029 to latest
+저장된 워프할 장소가 없습니다.
+There are no memorized locations (Memo Points).
+*/
+ MSG_NO_STORED_PLACE_TO_WARP = 0xd7,
+/*20031029 to latest
+워프 관련 스킬이 없습니다.
+You haven't learned Warp.
+*/
+ MSG_NOWARPSKILL = 0xd8,
+/*20031029 to latest
+워프 장소로 저장됨.
+Saved location as a Memo Point for Warp Skill.
+*/
+ MSG_WARPPOINTSTORED = 0xd9,
+/*20031029 to latest
+취소
+Cancel
+*/
+ MSG_CANCEL = 0xda,
+/*20031029 to latest
+스킬 사용후 시간이 충분히 지나지 않았습니다.
+There is a Delay after using a Skill.
+*/
+ MSG_SKILLINTERVAL = 0xdb,
+/*20031029 to latest
+한번에 가질 수 있는 아이템 종류수를 초과하여 아이템을 가질 수 없습니다.
+You can't have this item because you will exceed the weight limit.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_COUNT = 0xdc,
+/*20031029 to latest
+아이템 최대 종류수를 초과 하였습니다.
+Out of the maximum capacity
+*/
+ MSG_INSUFFICIENT_OVER_COUNT = 0xdd,
+/*20031029 to latest
+수레아이템
+Cart Items
+*/
+ MSG_MERCHANTITEM = 0xde,
+/*20031029 to latest
+수레 벗기
+Take off Cart
+*/
+ MSG_CARTOFF = 0xdf,
+/*20031029 to latest
+노점 개설
+Opening a stall
+*/
+ MSG_MERCHANTSHOPMAKER = 0xe0,
+/*20031029 to 20041207
+노점이름를 입력하세요.
+20041213 to latest
+노점이름을 입력하세요.
+Please Name your Shop.
+*/
+ MSG_ENTER_SHOP_TITLE = 0xe1,
+/*20031029 to latest
+나의 노점
+My Shop
+*/
+ MSG_ITEM_MY_STORE = 0xe2,
+/*20031029 to latest
+상인 아이템 상점
+Merchant Shop
+*/
+ MSG_ITEM_MERCHANT_STORE = 0xe3,
+/*20031029 to latest
+상인에게 사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY_FROM_MERCHANT = 0xe4,
+/*20031029 to latest
+%s 사기 실패 %s
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT = 0xe5,
+/*20031029 to latest
+재고 부족.
+Out of Stock
+*/
+ MSG_INSUFFICIENT_STOCK = 0xe6,
+/*20031029 to latest
+%s %d 개 팔림.
+%s %d sold.
+*/
+ MSG_ITEM_IS_SOLD = 0xe7,
+/*20031029 to latest
+노점에서 팔 수 있는 아이템
+Available Items for Vending
+*/
+ MSG_MERCHANTMIRRORITEM = 0xe8,
+/*20031029 to latest
+돈이 부족해서 스킬을 쓸 수 없습니다.
+*/
+ MSG_SKILL_FAIL_MONEY = 0xe9,
+/*20031029 to latest
+사용할 대상을 선택하세요
+Select a Target.
+*/
+ MSG_SELECTTARGET = 0xea,
+/*20031029 to latest
+/pk on : pk On /pk off : pk Off
+/pk on: Turns PK On. /pk off: Turns PK Off.
+*/
+ MSG_EXPLAIN_TIP14 = 0xeb,
+/*20031029 to latest
+노점
+Shop
+*/
+ MSG_STREETSHOP = 0xec,
+/*20031029 to latest
+수레 아이템 [Alt+W]
+Cart Items [Alt+W]
+*/
+ MSG_OPENCARTWINDOW = 0xed,
+/*20031029 to latest
+기본정보
+Basic Information
+*/
+ MSG_BASICINFOWND = 0xee,
+/*20031029 to latest
+이무기로는 이스킬을 사용할수 없습니다.
+The skill cannot be used with this weapon.
+*/
+ MSG_USESKILL_FAIL_NOT_SUITABLE_WEAPON = 0xef,
+/*20031029 to latest
+%s 사기 실패 재고 부족 현재 재고 %d 개.
+Buying %s has been failed. Out of Stock. Current Stock %d.
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT_NO_STOCK = 0xf0,
+/*20031029 to latest
+서버와 동기화가 틀려 연결이 끊어졌습니다.
+You've been disconnected due to a time gap between you and the server.
+*/
+ MSG_SPEEDHACK = 0xf1,
+/*20031029 to latest
+화살을 장착하세요
+Please equip the proper ammunition first.
+*/
+ MSG_ERR_ATTACK_ARROW = 0xf2,
+/*20031029 to latest
+중량과다로 공격이나 스킬을 사용할 수 없습니다.
+You can't attack or use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_ATTACK_WEIGHT = 0xf3,
+/*20031029 to latest
+중량과다로 스킬을 사용할 수 없습니다.
+You can't use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_SKILL_WEIGHT = 0xf4,
+/*20031029 to latest
+화살이 장착되었습니다.
+Ammunition has been equipped.
+*/
+ MSG_MSG_ARROW_EQUIPMENT_SUCCESS = 0xf5,
+/*20031029 to latest
+레드젬스톤이 필요합니다.
+Red Gemstone required.
+*/
+ MSG_NEED_REDJAMSTONE = 0xf6,
+/*20031029 to latest
+블루젬스톤이 필요합니다.
+Blue Gemstone required.
+*/
+ MSG_NEED_BLUEJAMSTONE = 0xf7,
+/*20031029 to latest
+힘 파라메터
+Strength
+*/
+ MSG_DESC_STR = 0xf8,
+/*20031029 to latest
+민첩성 파라메터
+Agility
+*/
+ MSG_DESC_AGI = 0xf9,
+/*20031029 to latest
+체력 파라메터
+Vitality
+*/
+ MSG_DESC_VIT = 0xfa,
+/*20031029 to latest
+지력 파라메터
+Intelligence
+*/
+ MSG_DESC_INT = 0xfb,
+/*20031029 to latest
+손재주 파라메터
+Dexterity
+*/
+ MSG_DESC_DEX = 0xfc,
+/*20031029 to latest
+운 파라메터
+Luck
+*/
+ MSG_DESC_LUK = 0xfd,
+/*20031029 to latest
+공격력
+Hit Point
+*/
+ MSG_DESC_ATK = 0xfe,
+/*20031029 to latest
+방어력
+Defence Rate
+*/
+ MSG_DESC_DEF = 0xff,
+/*20031029 to latest
+명중률
+Accuracy
+*/
+ MSG_DESC_HIT = 0x100,
+/*20031029 to latest
+필살공격률
+Critical Attack
+*/
+ MSG_DESC_CRI = 0x101,
+/*20031029 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_DESC_GUILD = 0x102,
+/*20031029 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_DESC_POINT = 0x103,
+/*20031029 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_DESC_MATK = 0x104,
+/*20031029 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_DESC_MDEF = 0x105,
+/*20031029 to latest
+회피율
+Dodge
+*/
+ MSG_DESC_FLEE = 0x106,
+/*20031029 to latest
+공격스피드
+Attack Speed
+*/
+ MSG_DESC_ASPD = 0x107,
+/*20031029 to latest
+지역당 수용인원 초과로 접속할 수 없습니다.
+Server is jammed due to over population. Please try again shortly.
+*/
+ MSG_PC_OVERFLOW = 0x108,
+/*20031029 to latest
+옵션
+Option
+*/
+ MSG_OPTIONWND = 0x109,
+/*20031029 to latest
+E-MAIL 인증이 되지않았거나 블럭된 계정입니다.
+Account ID blocked by the Game Master Team.
+*/
+ MSG_ID_EMAIL_CONFIRM_NEEDED = 0x10a,
+/*20031029 to latest
+비밀번호가 틀립니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_LOGIN_PASSWORD = 0x10b,
+/*20031029 to latest
+머리모양 선택
+Choose Hairstyle
+*/
+ MSG_SELECT_HAIR_STYLE = 0x10c,
+/*20031029 to latest
+공격력
+Hit Point
+*/
+ MSG_ATK = 0x10d,
+/*20031029 to latest
+방어력
+Defence Rate
+*/
+ MSG_DEF = 0x10e,
+/*20031029 to latest
+공격스냅 On
+Attack Snap On
+*/
+ MSG_ATTACK_SNAP_ON = 0x10f,
+/*20031029 to latest
+공격스냅 Off
+Attack Snap Off
+*/
+ MSG_ATTACK_SNAP_OFF = 0x110,
+/*20031029 to latest
+스킬스냅 On
+Skill Snap On
+*/
+ MSG_SKILL_SNAP_ON = 0x111,
+/*20031029 to latest
+스킬스냅 Off
+Skill Snap Off
+*/
+ MSG_SKILL_SNAP_OFF = 0x112,
+/*20031029 to latest
+/스냅 or /snap: 몬스터 공격시 스냅 On Off /스킬스냅 or /skillsnap: 스킬로 몬스터 공격시 스냅 On Off /아이템스냅 or /itemsnap: 아이템 주울때 스냅 On Off
+/snap: Turns snap On | Off for fights, /skillsnap: Turns snap On | Off for skills. /itemsnap: Turns snap On | Off for items on the grounds.
+*/
+ MSG_EXPLAIN_SNAP = 0x113,
+/*20031029 to latest
+아이템스냅 On
+Item Snap On
+*/
+ MSG_ITEM_SNAP_ON = 0x114,
+/*20031029 to latest
+아이템스냅 Off
+Item Snap Off
+*/
+ MSG_ITEM_SNAP_OFF = 0x115,
+/*20031029 to latest
+스냅
+Snap
+*/
+ MSG_SNAP = 0x116,
+/*20031029 to latest
+한가지 아이템을 3만개 이상 가질수 없습니다.
+You cannot carry more than 30,000 of one kind of item.
+*/
+ MSG_CANT_GET_ITEM_OVERCOUNT_ONEITEM = 0x117,
+/*20031029 to latest
+레벨 30이상의 캐릭터는 삭제할 수 없습니다. 삭제를 원하시면 관계자에게 문의 하세요.
+You cannot delete a Character with a level greater than 30. If you want to delete the character please contact a Game Master.
+*/
+ MSG_CANT_DELETE_CHARACTER_OVER_30_LEVEL = 0x118,
+/*20031029 to latest
+이이템 교환중에는 아이템을 사고 팔 수 없습니다.
+*/
+ MSG_FAIL_BUY_ITEM_ITEM_EXCHANGING = 0x119,
+/*20031029 to latest
+상점명
+Shop Name
+*/
+ MSG_STALL_NAME = 0x11a,
+/*20031029 to latest
+스킬목록
+Skill Tree
+*/
+ MSG_SKILLLIST = 0x11b,
+/*20031029 to latest
+스킬포인트 : %d
+Skill Point: %d
+*/
+ MSG_SKILLPOINT = 0x11c,
+/*20031029 to latest
+스킬사용 실패
+Skill has failed.
+*/
+ MSG_USESKILL_FAIL = 0x11d,
+/*20031029 to latest
+패시브
+Passive
+*/
+ MSG_PASSIVE = 0x11e,
+/*20031029 to latest
+각자 취득
+Individual
+*/
+ MSG_EXPDIV1 = 0x11f,
+/*20031029 to latest
+균등하게 분배
+Shared
+*/
+ MSG_EXPDIV2 = 0x120,
+/*20031029 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMCOLLECT1 = 0x121,
+/*20031029 to latest
+파티 전체 공유
+Party Share
+*/
+ MSG_ITEMCOLLECT2 = 0x122,
+/*20031029 to latest
+파티 설정
+Party Setup
+*/
+ MSG_PARTYSETTING = 0x123,
+/*20031029 to latest
+경험치 분배방식
+How to share EXP
+*/
+ MSG_HOWEXPDIV = 0x124,
+/*20031029 to latest
+아이템 수집방식
+How to share Items
+*/
+ MSG_HOWITEMCOLLECT = 0x125,
+/*20031029 to latest
+파티 리더만 설정할 수 있습니다.
+Only the Party Leader can change this setting.
+*/
+ MSG_ONLY_PARTYMASTER = 0x126,
+/*20031029 to latest
+아이템 갯수 안물어보기
+Toggle Item Amount.
+*/
+ MSG_NOQUESTION_ITEMCOUNT = 0x127,
+/*20031029 to latest
+^ff0000%d^000000 초 후에 캐릭터가 지워집니다. 취소 하려면 취소 버튼을 누르세요.
+Character will be deleted after ^ff0000%d^000000 seconds. Press Cancel to quit.
+*/
+ MSG_CHARARATER_DELETE_COUNT = 0x128,
+/*20031029 to latest
+교환할 수 있는 최대 아이템 갯수는 10가지 입니다.
+You cannot trade more than 10 types of items per trade.
+*/
+ MSG_MAXEXCHANGE_IS_10_KIND = 0x129,
+/*20031029 to latest
+이서버를 이용할 수 없는 나이입니다.
+You are underaged.
+*/
+ MSG_LIMIT_AGE = 0x12a,
+/*20031029 to latest
+이메일 주소를 입력하세요.
+Please enter the deletion password.
+*/
+ MSG_ENTER_EMAIL = 0x12b,
+/*20031029 to latest
+이메일 주소 입력하기
+E-mail Address (Case Sensitive).
+*/
+ MSG_ENTER_EMAIL_TOOLTIP = 0x12c,
+/*20031029 to latest
+이메일 주소가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect e-mail address.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_EMAIL = 0x12d,
+/*20031029 to 20070703
+주민등록번호 뒷자리를 입력하세요.
+20070618 to 20070622
+비밀번호를 한 번 더 입력해 주시기 바랍니다.
+20070704 to latest
+계정 비밀번호를 입력하세요.
+Enter Second Serial Cord of your Social Security number.
+*/
+ MSG_ENTER_PEOPLE_REG_NUMBER = 0x12e,
+/*20031029 to 20070703
+주민등록번호 뒷자리가 틀려서 캐릭터가 삭제 되지 않았습니다.
+20070618 to 20070622
+비밀번호가 맞지 않아 캐릭터가 삭제 되지 않았습니다.
+20070704 to latest
+비밀번호가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect SSN.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_PEOPLE_REG_NUMBER = 0x12f,
+/*20031029 to latest
+한번에 15가지 이상의 아이템을 팔 수 없습니다.
+You can't sell more than 15 types of Items at one time.
+*/
+ MSG_CANT_SELL_OVER_15 = 0x130,
+/*20031029 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_UNDER_AGE = 0x131,
+/*20031029 to latest
+무게가 50 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+HP/SP will not be restored when your carried weight is over 50% of the Weight Limit.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT = 0x132,
+/*20031029 to latest
+무게가 90 퍼센트 이상일때는 공격과 스킬을 사용할 수 없습니다.
+You can't use Skills or Attack while your carried weight is over 90% of your Weight Limit.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT = 0x133,
+/*20031029 to latest
+HP SP가 자연적으로 회복이 가능한 상태가 되었습니다.
+Your HP/SP are now being restored naturally.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT_RELEASED = 0x134,
+/*20031029 to latest
+공격과 스킬이 가능한 상태가 되었습니다.
+Attack and Skills are now available.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT_RELEASED = 0x135,
+/*20031029 to latest
+서버 점검중입니다.
+Your Game's Exe File is not the latest version.
+*/
+ MSG_INVALID_VERSION = 0x136,
+/*20031029 to latest
+아이템이 모두 팔렸습니다.
+Items are sold out.
+*/
+ MSG_ITEM_IS_SOLD_OUT = 0x137,
+/*20031029 to latest
+채팅내용 파일로 저장하기
+Save Chat as Text File
+*/
+ MSG_WRITE_CHAT_TO_FILE = 0x138,
+/*20031029 to latest
+/갈무리 or /savechat : 채팅 내용 파일로 저장하기.
+/savechat: Save a Chat Log
+*/
+ MSG_EXPLAIN_SAVE_CHAT = 0x139,
+/*20031029 to latest
+계정 만들기
+Register
+*/
+ MSG_MAKEACCOUNT = 0x13a,
+/*20031029 to latest
+수신거부하기
+Reject Whispering
+*/
+ MSG_REQ_EX_LIST = 0x13b,
+/*20031029 to latest
+수신거부해제하기
+Allow Whispering
+*/
+ MSG_REQ_IN = 0x13c,
+/*20031029 to latest
+미스표시 On
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_ON = 0x13d,
+/*20031029 to latest
+미스표시 Off
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_OFF = 0x13e,
+/*20031029 to latest
+카메라고정 On
+Camera Zooming On
+*/
+ MSG_FIXED_CAMERA_ON = 0x13f,
+/*20031029 to latest
+카메라고정 Off
+Camera Zooming Off
+*/
+ MSG_FIXED_CAMERA_OFF = 0x140,
+/*20031029 to latest
+/camera : 플레이어에게 카메라고정 On Off /miss : 미스이펙트 On Off
+/camera: Camera Zooming On or Off. /miss: Toggle ''Miss'' display
+*/
+ MSG_EXPLAIN_CAMERA_MISS = 0x141,
+/*20031029 to latest
+스킬정보보기
+View Skill Info
+*/
+ MSG_SEE_INFORMATION_OF_SKILL = 0x142,
+/*20031029 to latest
+스킬이름바꾸기
+Change Skill
+*/
+ MSG_CHANGE_SKILL_NAME = 0x143,
+/*20031029 to latest
+스프라이트 해상도
+Sprite Resolution
+*/
+ MSG_SPRITE_RESOLUTION = 0x144,
+/*20031029 to latest
+텍스쳐 해상도
+Texture Resolution
+*/
+ MSG_TEXTURE_RESOLUTION = 0x145,
+/*20031029 to latest
+디테일 조정
+Arrange Detail
+*/
+ MSG_DETAILLEVELWND = 0x146,
+/*20031029 to latest
+%s Zeny 획득
+You got %s Zeny
+*/
+ MSG_GET_ZENY = 0x147,
+/*20031029 to latest
+길드명
+Guild Name
+*/
+ MSG_GUILDNAME = 0x148,
+/*20031029 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILDLEVEL = 0x149,
+/*20031029 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_GUILD_MASTER_NAME = 0x14a,
+/*20031029 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_NUM_MEMBER = 0x14b,
+/*20031029 to latest
+조합원 평균레벨
+Avg.lvl of Guildsmen
+*/
+ MSG_GUILD_AVG_MEMBER_LEVEL = 0x14c,
+/*20031029 to latest
+관리영지
+Castles Owned
+*/
+ MSG_GUILD_MANAGE_LAND = 0x14d,
+/*20031029 to latest
+성향
+Tendency
+*/
+ MSG_GUILD_FAIR = 0x14e,
+/*20031029 to latest
+경험치
+EXP
+*/
+ MSG_GUILD_EXP = 0x14f,
+/*20031029 to latest
+길드엠블렘
+Emblem
+*/
+ MSG_GUILD_EMBLEM = 0x150,
+/*20031029 to latest
+길드상납포인트
+Tax Point
+*/
+ MSG_GUILD_POINT = 0x151,
+/*20031029 to latest
+동맹길드
+Alliances
+*/
+ MSG_ALLY_GUILD = 0x152,
+/*20031029 to latest
+적대길드
+Antagonists
+*/
+ MSG_HOSTILITY_GUILD = 0x153,
+/*20031029 to latest
+길드정보
+Guild Info
+*/
+ MSG_GUILDINFOMANAGE = 0x154,
+/*20031029 to latest
+조합원정보
+Guildsmen Info
+*/
+ MSG_GUILDMEMBERMANAGE = 0x155,
+/*20031029 to latest
+직위설정
+Position
+*/
+ MSG_GUILDPOSITIONMANAGE = 0x156,
+/*20031029 to latest
+길드스킬
+Guild Skill
+*/
+ MSG_GUILDSKILL = 0x157,
+/*20031029 to latest
+추방자 리스트
+Expel History
+*/
+ MSG_GUILDBANISHEDMEMBER = 0x158,
+/*20031029 to latest
+공지사항
+Guild Notice
+*/
+ MSG_GUILDNOTICE = 0x159,
+/*20031029 to latest
+전체길드 리스트
+Entire Guild List
+*/
+ MSG_GUILDTOTALINFO = 0x15a,
+/*20031029 to latest
+귓말 리스트
+Whispering List
+*/
+ MSG_WHISPERLISTWND = 0x15b,
+/*20031029 to latest
+귓말창 열기
+Open Whispering Window
+*/
+ MSG_OPENWHISPERLISTWND = 0x15c,
+/*20031029 to latest
+귓말 리스트 창 여는법 : [Alt] + [H] 를 누르면 귓말 리스트 창이 열립니다.
+How to Open Whispering List: Press [Alt] + [H]
+*/
+ MSG_EXPLAIN_WHISPER_LIST_WND = 0x15d,
+/*20031029 to latest
+자동으로 귓말창 열기
+Open Whispering List Automatically
+*/
+ MSG_AUTOOPENWHISPERLISTWND = 0x15e,
+/*20031029 to latest
+지우기
+Delete
+*/
+ MSG_DELETE = 0x15f,
+/*20031029 to latest
+다음부터 열리지 않음
+Close since next
+*/
+ MSG_DONTOPEN = 0x160,
+/*20031029 to latest
+마지막으로 접속한 시간
+Last Log-in Time
+*/
+ MSG_LAST_LOGIN_TIME = 0x161,
+/*20031029 to latest
+마지막으로 접속한 IP
+Last Log-in IP
+*/
+ MSG_LAST_LOGIN_IP = 0x162,
+/*20031029 to latest
+친구 설정
+Friend Setup
+*/
+ MSG_FRIEND_SETTING = 0x163,
+/*20031029 to latest
+정말 지우시겠습니까?
+Are you sure that you want to delete?
+*/
+ MSG_DO_YOU_REALLY_WANT_DELETE = 0x164,
+/*20031029 to latest
+정말 탈퇴하시겠습니까?
+Are you sure that you want to leave?
+*/
+ MSG_DO_YOU_REALLY_WANT_LEAVE = 0x165,
+/*20031029 to latest
+친구로 등록하기
+Register as a Friend
+*/
+ MSG_ADD_TO_FRIEND_CHAR_LIST = 0x166,
+/*20031029 to latest
+친구일때 자동으로 1:1창 열기
+Open 1:1 Chat between Friends
+*/
+ MSG_AUTOOPENWHISPERLISTWND_FRIEND = 0x167,
+/*20031029 to latest
+1:1창 열기
+Open 1:1 Chat
+*/
+ MSG_OPEN_1ON1_WINDOW = 0x168,
+/*20031029 to latest
+친구가 아닐때 자동으로 1:1창 열기
+Open 1:1 Chat between Strangers
+*/
+ MSG_AUTOOPEN_1ON1_WINDOW = 0x169,
+/*20031029 to latest
+1:1창 열릴때 소리로 알림
+Alarm when you recieve a 1:1 Chat
+*/
+ MSG_WHISPER_OPEN_SOUND = 0x16a,
+/*20031029 to latest
+정말 제명시키시겠습니까?
+Are you sure that you want to expel?
+*/
+ MSG_DO_YOU_REALLY_WANT_EXPEL = 0x16b,
+/*20031029 to latest
+%s 님이 길드를 탈퇴했습니다.
+%s has withdrawn from the guild.
+*/
+ MSG_USER_LEFT_GUILD = 0x16c,
+/*20031029 to latest
+탈퇴사유 : %s
+Secession Reason: %s
+*/
+ MSG_REASON_LEAVE_GUILD = 0x16d,
+/*20031029 to latest
+길드 해체 실패
+*/
+ MSG_DISORGANIZE_GUILD_FAILURE = 0x16e,
+/*20031029 to latest
+길드해체사유 : %s
+Disband Reason: %s
+*/
+ MSG_DISORGANIZATION_REASON = 0x16f,
+/*20031029 to latest
+해당 계정은 삭제된 아이디 입니다.
+This ID has been removed.
+*/
+ MSG_DELETED_ACCOUNT = 0x170,
+/*20031029 to latest
+판매가 :
+Price:
+*/
+ MSG_SELLPRICE = 0x171,
+/*20031029 to latest
+%s 님이 길드에서 추방되었습니다.
+%s has been expelled from our guild.
+*/
+ MSG_BAN_GUILD = 0x172,
+/*20031029 to latest
+추방사유 : %s
+Expulsion Reason: %s
+*/
+ MSG_REASON_BAN_GUILD = 0x173,
+/*20031029 to latest
+아이템을 착용할 수 없습니다.
+You can't put this item on.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM = 0x174,
+/*20031029 to latest
+파티설정을 변경할 수 없습니다.
+You can't modify Party Setup.
+*/
+ MSG_PARTYSETTING_CHANGE_IMPOSSIBLE = 0x175,
+/*20031029 to latest
+길드가 만들어 졌습니다.
+Guild has been Created.
+*/
+ MSG_GUILD_MAKE_SUCCESS = 0x176,
+/*20031029 to latest
+이미 길드에 속해있습니다.
+You are already in a Guild.
+*/
+ MSG_GUILD_MAKE_ALREADY_MEMBER = 0x177,
+/*20031029 to latest
+같은이름의 길드가 존재합니다.
+That Guild Name already exists.
+*/
+ MSG_GUILD_MAKE_GUILD_EXIST = 0x178,
+/*20031029 to latest
+ 길드에서 초청 메시지가 왔습니다. 가입하겠습니까?
+ Guild has sent you an invitation. Would you like to join this Guild?
+*/
+ MSG_SUGGEST_JOIN_GUILD = 0x179,
+/*20031029 to latest
+다른길드에 가입되어 있습니다.
+He/She is already in a Guild.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_GUILD = 0x17a,
+/*20031029 to latest
+길드가입을 거절 했습니다.
+Offer Rejected
+*/
+ MSG_CHARACTER_REJECT_JOIN_GUILD = 0x17b,
+/*20031029 to latest
+길드가입을 수락했습니다.
+Offer Accepted
+*/
+ MSG_CHARACTER_ACCEPT_JOIN_GUILD = 0x17c,
+/*20031029 to latest
+길드정원을 초과했습니다.
+Your Guild is Full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_GUILD = 0x17d,
+/*20031029 to latest
+(%s)님 길드에 가입요청
+Send (%s) a Guild invitation
+*/
+ MSG_REQ_JOIN_GUILD = 0x17e,
+/*20031029 to latest
+스킬 레벨이 모자라서 매너포인트를 줄 수 없습니다.
+You haven't learned enough skills for aligning.
+*/
+ MSG_NOT_ENOUGH_FOR_MANNER_POINT = 0x17f,
+/*20031029 to latest
+매너 포인트 주기 성공
+Aligning completed.
+*/
+ MSG_GIVING_MANNER_POINT_SUCCESS = 0x180,
+/*20031029 to latest
+오늘 이미 사용했습니다.
+You already spent your point for today.
+*/
+ MSG_YOU_USE_TODAY_ALREADY = 0x181,
+/*20031029 to latest
+이캐릭터에게 지급한지 한달이 지나지 않았습니다.
+Hasn't been a month yet since you aligned this person.
+*/
+ MSG_ONE_MONTH_NOT_PASSED = 0x182,
+/*20031029 to latest
+%s 님으로부터 플러스 매너 포인트를 받았습니다.
+Remember, Spamming isn't nice.
+*/
+ MSG_RECEIVE_PLUS_MANNER_POINT = 0x183,
+/*20031029 to latest
+%s 님으로부터 마이너스 매너 포인트를 받았습니다.
+Please refrain from ill-mannered conduct, thank you.
+*/
+ MSG_RECEIVE_MINUS_MANNER_POINT = 0x184,
+/*20031029 to latest
+채팅 금지 시간 줄이기(풀기)
+Align with a Good Point
+*/
+ MSG_GIVE_PLUS_MANNER_POINT = 0x185,
+/*20031029 to latest
+채팅 금지 시간 늘이기(걸기)
+Align with a Bad Point
+*/
+ MSG_GIVE_MINUS_MANNER_POINT = 0x186,
+/*20031029 to latest
+(%s)님과의 거래요청
+Request a deal with (%s)
+*/
+ MSG_REQ_DEAL_WITH2 = 0x187,
+/*20031029 to latest
+(%s)님 파티에 가입요청
+Ask (%s) to join your party
+*/
+ MSG_REQ_JOIN_PARTY2 = 0x188,
+/*20031029 to latest
+ 길드에서 동맹요청 메시지가 왔습니다. 동맹하겠습니까?
+ Guild is asking you to agree to an Alliance with them. Do you accept?
+*/
+ MSG_SUGGEST_ALLY_GUILD = 0x189,
+/*20031029 to latest
+이미 동맹되어 있습니다.
+This Guild is already your Ally.
+*/
+ MSG_REQALLYGUILD_ALREADY_ALLIED = 0x18a,
+/*20031029 to latest
+동맹을 거절 했습니다.
+You reject the offer
+*/
+ MSG_REQALLYGUILD_REJECT = 0x18b,
+/*20031029 to latest
+동맹을 수락 했습니다.
+You accept the offer
+*/
+ MSG_REQALLYGUILD_ACCEPT = 0x18c,
+/*20031029 to latest
+상대길드의 동맹길드의 수가 초과 되었습니다.
+They have too many Alliances.
+*/
+ MSG_REQALLYGUILD_OVERSIZE = 0x18d,
+/*20031029 to latest
+길드의 동맹길드의 수가 초과 되었습니다.
+You have too many Alliances.
+*/
+ MSG_REQALLYMYGUILD_OVERSIZE = 0x18e,
+/*20031029 to latest
+길드 동맹 요청
+Set this guild as an Alliance
+*/
+ MSG_REQ_ALLY_GUILD = 0x18f,
+/*20031029 to latest
+길드가 성공적으로 해체 되었습니다.
+Guild was successfully disbanded.
+*/
+ MSG_DISORGANIZE_GUILD_SUCCESS = 0x190,
+/*20031029 to latest
+주민등록번호가 틀려서 길드가 해체되지 않았습니다.
+You have failed to disband the guild due to your incorrect SSN.
+*/
+ MSG_DISORGANIZE_GUILD_INVALIDKEY = 0x191,
+/*20031029 to latest
+길드맴버가 존재해서 길드가 해체되지 않았습니다.
+You have failed to disband the guild because there are guildsmen still present.
+*/
+ MSG_DISORGANIZE_GUILD_MEMBEREXIST = 0x192,
+/*20031029 to latest
+길드 적대 요청
+Set this guild as an Antagonist
+*/
+ MSG_REQ_HOSTILE_GUILD = 0x193,
+/*20031029 to latest
+머리색깔 선택
+Choose Hair Color
+*/
+ MSG_SELECT_HAIR_COLOR = 0x194,
+/*20031029 to latest
+길드결성시 필요한 아이템이 없습니다.
+You don't have necessary item to create a Guild.
+*/
+ MSG_GUILD_MAKE_GUILD_NONE_ITEM = 0x195,
+/*20031029 to latest
+몬스터 정보
+Monster Info
+*/
+ MSG_MONSTER_INFO_WINDOW = 0x196,
+/*20031029 to latest
+이름
+Name
+*/
+ MSG_NAME = 0x197,
+/*20031029 to latest
+레벨
+Level
+*/
+ MSG_LEVEL = 0x198,
+/*20031029 to latest
+HP
+*/
+ MSG_HP = 0x199,
+/*20031029 to latest
+크기
+Size
+*/
+ MSG_SIZE = 0x19a,
+/*20031029 to latest
+종족
+Type
+*/
+ MSG_RACETYPE = 0x19b,
+/*20031029 to latest
+MDEF
+*/
+ MSG_MDEFPOWER = 0x19c,
+/*20031029 to latest
+속성
+Attribute
+*/
+ MSG_PROPERTY = 0x19d,
+/*20031029 to latest
+無
+Neutral
+*/
+ MSG_PROPERTY_NEUTURAL = 0x19e,
+/*20031029 to latest
+水
+Water
+*/
+ MSG_PROPERTY_WATER = 0x19f,
+/*20031029 to latest
+地
+Earth
+*/
+ MSG_PROPERTY_EARTH = 0x1a0,
+/*20031029 to latest
+火
+Fire
+*/
+ MSG_PROPERTY_FIRE = 0x1a1,
+/*20031029 to latest
+風
+Wind
+*/
+ MSG_PROPERTY_WIND = 0x1a2,
+/*20031029 to latest
+毒
+Poison
+*/
+ MSG_PROPERTY_POISON = 0x1a3,
+/*20031029 to latest
+聖
+Holy
+*/
+ MSG_PROPERTY_SAINT = 0x1a4,
+/*20031029 to latest
+暗
+Shadow
+*/
+ MSG_PROPERTY_DARK = 0x1a5,
+/*20031029 to latest
+念
+Ghost
+*/
+ MSG_PROPERTY_MENTAL = 0x1a6,
+/*20031029 to latest
+死
+Undead
+*/
+ MSG_PROPERTY_UNDEAD = 0x1a7,
+/*20031029 to latest
+현재는 아이템을 만들 수 없습니다.
+You can't create items yet.
+*/
+ MSG_CANT_MAKE_ITEM = 0x1a8,
+/*20031029 to latest
+제조 목록
+Item List you can craft
+*/
+ MSG_MAKE_LIST = 0x1a9,
+/*20031029 to latest
+ 만들기
+ Create
+*/
+ MSG_MAKE_TARGET = 0x1aa,
+/*20031029 to latest
+ 에 필요한 재료:
+'s materials
+*/
+ MSG_REQUIRE_FOR_MAKE_TARGET = 0x1ab,
+/*20031029 to latest
+ 만들기 실패
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL = 0x1ac,
+/*20031029 to latest
+ 만들기 성공
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS = 0x1ad,
+/*20031029 to latest
+%s 만들기를 실패하였습니다.
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL_MSG = 0x1ae,
+/*20031029 to latest
+%s 만들기를 성공했습니다.
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS_MSG = 0x1af,
+/*20031029 to latest
+레벨이 부족합니다.
+You are not the required lvl.
+*/
+ MSG_NOT_ENOUGH_LEVEL = 0x1b0,
+/*20031029 to latest
+레벨이 너무 높습니다.
+Too high lvl for this job.
+*/
+ MSG_TOO_HIGH_LEVEL = 0x1b1,
+/*20031029 to latest
+직업이 적합하지 않습니다.
+Not the suitable job for this type of work.
+*/
+ MSG_NOT_ACCEPTABLE_JOB = 0x1b2,
+/*20031029 to latest
+토키 박스 트랩 메세지
+Record a message in the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW = 0x1b3,
+/*20031029 to latest
+기록할 메세지를 입력하시기 바랍니다.
+Please type a message for the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW_MSG = 0x1b4,
+/*20031029 to latest
+길드에게 보냄
+Send to Guild
+*/
+ MSG_SEND_TO_GUILD = 0x1b5,
+/*20031029 to latest
+결제된 계정이 아닙니다. 결제 페이지로 이동하시겠습니까?
+You didn't pay for this ID. Would you like to pay for it now?
+*/
+ MSG_NOT_SETTLED = 0x1b6,
+/*20031029 to latest
+서버가 혼잡한 관계로 잠시후 다시 시도해 주시기 바랍니다.
+Server is jammed due to overpopulation. Please try again after few minutes.
+*/
+ MSG_ACCOUNT_BUSY = 0x1b7,
+/*20031029 to latest
+지난 접속 정보가 남아 있습니다. 30초정도 지난뒤에 다시 시도해 주시기 바랍니다.
+Server still recognizes your last log-in. Please try again after a few minutes.
+*/
+ MSG_INFORMATION_REMAINED = 0x1b8,
+/*20031029 to latest
+매 풀어주기
+Release Falcon
+*/
+ MSG_BIRDOFF = 0x1b9,
+/*20031029 to latest
+페코페코 내리기
+Dismount
+*/
+ MSG_CHIKENOFF = 0x1ba,
+/*20031029 to latest
+小
+Small
+*/
+ MSG_SIZE_SMALL = 0x1bb,
+/*20031029 to latest
+中
+Med
+*/
+ MSG_SIZE_MIDDLE = 0x1bc,
+/*20031029 to latest
+大
+Big
+*/
+ MSG_SIZE_BIG = 0x1bd,
+/*20031029 to latest
+더블
+Double
+*/
+ MSG_DOUBLE = 0x1be,
+/*20031029 to latest
+트리플
+Triple
+*/
+ MSG_TRIPLE = 0x1bf,
+/*20031029 to latest
+쿼드로플
+Quadruple
+*/
+ MSG_QUADROPLE = 0x1c0,
+/*20031029 to latest
+%s 까지 로그인을 금지하고 있습니다.
+You are prohibited to log in until %s.
+*/
+ MSG_LOGIN_REFUSE_BLOCKED_UNTIL = 0x1c1,
+/*20031029 to latest
+의
+'s
+*/
+ MSG_MANUFACTURED_NORMAL_ITEM = 0x1c2,
+/*20031029 to latest
+의 파이어
+'s Fire
+*/
+ MSG_MANUFACTURED_FIRE_ITEM = 0x1c3,
+/*20031029 to latest
+의 아이스
+'s Ice
+*/
+ MSG_MANUFACTURED_ICE_ITEM = 0x1c4,
+/*20031029 to latest
+의 윈드
+'s Wind
+*/
+ MSG_MANUFACTURED_WIND_ITEM = 0x1c5,
+/*20031029 to latest
+의 어스
+'s Earth
+*/
+ MSG_MANUFACTURED_EARTH_ITEM = 0x1c6,
+/*20031029 to latest
+211.239.161.246
+38.144.194.2
+*/
+ MSG_ACCOUNT_ADDRESS = 0x1c7,
+/*20031029 to latest
+6900
+*/
+ MSG_ACCOUNT_PORT = 0x1c8,
+/*20031029 to latest
+http://www.ragnarok.co.kr
+*/
+ MSG_REGISTRATION_WEB_URL = 0x1c9,
+/*20031029 to latest
+%s 사용자 강제 종료
+Kill %s
+*/
+ MSG_BAN_USER = 0x1ca,
+/*20031029 to latest
+무지쎈
+Very Strong
+*/
+ MSG_ONE_STARPIECE = 0x1cb,
+/*20031029 to latest
+무지무지쎈
+Very Very Strong
+*/
+ MSG_TWO_STARPIECE = 0x1cc,
+/*20031029 to 20031029
+무지무지무지쎈
+20031103 to latest
+무무무쎈
+Very Very Very Strong
+*/
+ MSG_THREE_STARPIECE = 0x1cd,
+/*20031029 to latest
+길드 추방 사유
+The Reason of Expulsion
+*/
+ MSG_GUILD_KICK_REASON = 0x1ce,
+/*20031029 to latest
+ 공격 속도가 증가했습니다.
+Attack Speed is up.
+*/
+ MSG_INCATTACKSPEED = 0x1cf,
+/*20031029 to latest
+ 공격 속도가 감소했습니다.
+Attack Speed is down.
+*/
+ MSG_DECATTACKSPEED = 0x1d0,
+/*20031029 to latest
+ 무기의 공격력이 향상되었습니다.
+Weapon Damage is improved.
+*/
+ MSG_INCWEAPONATTACK = 0x1d1,
+/*20031029 to latest
+ 무기의 공격력이 감소되었습니다.
+Weapon Damage is reduced.
+*/
+ MSG_DECWEAPONATTACK = 0x1d2,
+/*20031029 to latest
+ 시전 딜레이가 줄었습니다.
+Cast Delay is reduced.
+*/
+ MSG_FASTPREDELAY = 0x1d3,
+/*20031029 to latest
+ 시전 딜레이가 정상으로 되었습니다.
+Cast Delay has returned to normal.
+*/
+ MSG_NORMALPREDELAY = 0x1d4,
+/*20031029 to latest
+ 무기에 독속성이 부여되었습니다.
+Weapon is temporarily enchanted with Poison.
+*/
+ MSG_WEAPONPROPERTYPOISON = 0x1d5,
+/*20031029 to latest
+ 무기에 성속성이 부여되었습니다.
+Weapon is temporarily enchanted with an elemental property.
+*/
+ MSG_WEAPONPROPERTYSAINT = 0x1d6,
+/*20031029 to latest
+ 무기의 원래속성이 적용되었습니다.
+Weapon has changed back to normal.
+*/
+ MSG_WEAPONPROPERTYORIGINAL = 0x1d7,
+/*20031029 to latest
+ 방어구에 성속성이 부여되었습니다.
+Armor has been enchanted with the Holy Ghost.
+*/
+ MSG_ARMORPROPERTYSAINT = 0x1d8,
+/*20031029 to latest
+ 방어구의 원래속성이 적용되었습니다.
+Armor has changed back to normal.
+*/
+ MSG_ARMORPROPERTYORIGINAL = 0x1d9,
+/*20031029 to latest
+ 배리어 상태가 되었습니다.
+Barrier Formed.
+*/
+ MSG_BARRIOR = 0x1da,
+/*20031029 to latest
+ 배리어 상태가 해제 되었습니다.
+Barrier Canceled.
+*/
+ MSG_DISAPPEARBARRIOR = 0x1db,
+/*20031029 to latest
+ 소형, 중형, 대형 몬스터에게 100% 공격력을 줍니다.
+Weapon Perfection Initiated.
+*/
+ MSG_PERFECTDAMAGE = 0x1dc,
+/*20031029 to latest
+ 웨폰퍼펙션 모드가 해제 되었습니다.
+Weapon perfection Canceled.
+*/
+ MSG_DISAPPEARPERFECTDAMAGE = 0x1dd,
+/*20031029 to latest
+ 무기가 파괴될 가능성이 높아진 대신 무기의 공격력이 증가하였습니다.
+Power-Thrust Initiated.
+*/
+ MSG_OVERTHRUSTING = 0x1de,
+/*20031029 to 20050118
+ 오버트러스팅 상태가 해제 되었습니다.
+20050124 to latest
+ 오버트러스트 상태가 해제 되었습니다.
+Power-Thrust Canceled.
+*/
+ MSG_DISAPPEAROVERTHRUSTING = 0x1df,
+/*20031029 to latest
+ 무기의 최대 성능을 끌어냅니다.
+Maximize-Power Initiated.
+*/
+ MSG_MAXIMIZE = 0x1e0,
+/*20031029 to latest
+ 맥시마이즈 상태가 해제 되었습니다.
+Maximize-Power Canceled.
+*/
+ MSG_DISAPPEARMAXIMIZE = 0x1e1,
+/*20031029 to latest
+[신서버]
+[New Server]
+*/
+ MSG_SERVER_PROPERTY_NEW = 0x1e2,
+/*20031029 to latest
+(%d 명)
+(%d players)
+*/
+ MSG_SERVER_USER_COUNT = 0x1e3,
+/*20031029 to latest
+(점검중)
+(On the maintenance)
+*/
+ MSG_SERVER_INSPECTING = 0x1e4,
+/*20031029 to latest
+길드멤버 %s님이 접속하셨습니다.
+Guild member %s has connected.
+*/
+ MSG_GUILD_MEMBER_STATUS_ONLINE = 0x1e5,
+/*20031029 to latest
+길드멤버 %s님이 종료하셨습니다.
+Guild member %s has disconnected.
+*/
+ MSG_GUILD_MEMBER_STATUS_OFFLINE = 0x1e6,
+/*20031029 to latest
+경험치 %d 얻음
+You got %d Base EXP.
+*/
+ MSG_GOT_EXPERIENCE_POINT = 0x1e7,
+/*20031029 to latest
+잡경험치 %d 얻음
+You got %d Job EXP.
+*/
+ MSG_GOT_JOB_EXPERIENCE_POINT = 0x1e8,
+/*20031029 to latest
+길드에서 탈퇴 했습니다.
+You left the guild.
+*/
+ MSG_LEFT_GUILD = 0x1e9,
+/*20031029 to latest
+길드에서 추방 당했습니다.
+You have been expelled from the Guild.
+*/
+ MSG_BAN_FROM_GUILD = 0x1ea,
+/*20031029 to latest
+아이템 감정 성공
+Item Appraisal has completed successfully.
+*/
+ MSG_ITEM_IDENTIFY_SUCCEESS = 0x1eb,
+/*20031029 to latest
+아이템 감정 실패
+Item appraisal has failed.
+*/
+ MSG_ITEM_IDENTIFY_FAIL = 0x1ec,
+/*20031029 to latest
+아이템 조합 성공
+Compounding has completed successfully.
+*/
+ MSG_ITEM_COMPOUNDING_SUCCEESS = 0x1ed,
+/*20031029 to latest
+아이템 조합 실패
+Compounding has failed.
+*/
+ MSG_ITEM_COMPOUNDING_FAIL = 0x1ee,
+/*20031029 to latest
+길드 적대 성공
+Antagonist has been set.
+*/
+ MSG_HOSTILE_GUILD_SUCCEESS = 0x1ef,
+/*20031029 to latest
+적대 길드수 초과로 길드 적대 실패
+Guild has too many Antagonists.
+*/
+ MSG_TOO_MANY_HOSTILE_GUILD = 0x1f0,
+/*20031029 to latest
+이미 적대 길드 입니다
+Already set as an Antagonist
+*/
+ MSG_ALREADY_REGISTERED_HOSTILE_GUILD = 0x1f1,
+/*20031029 to latest
+제련이 성공적으로 되었습니다.
+Upgrade has been completed successfully.
+*/
+ MSG_ITEM_REFINING_SUCCEESS = 0x1f2,
+/*20031029 to latest
+제련이 실패하였습니다.
+Upgrade has failed.
+*/
+ MSG_ITEM_REFINING_FAIL = 0x1f3,
+/*20031029 to 20040311
+텔레포트 불가능 지역입니다.
+20040315 to latest
+이곳에서는 순간이동이 불가능합니다.
+Unavailable Area to Teleport
+*/
+ MSG_IMPOSSIBLE_TELEPORT_AREA = 0x1f4,
+/*20031029 to 20040311
+텔레포트 가능 지역입니다.
+20040315 to latest
+이 장소는 기억할 수 없습니다.
+Unable to memorize this place as Warp Point
+*/
+ MSG_POSSIBLE_TELEPORT_AREA = 0x1f5,
+/*20031029 to latest
+지금은 종료할 수 없습니다.
+Please wait 10 seconds before trying to log out.
+*/
+ MSG_CANT_EXIT_NOW = 0x1f6,
+/*20031029 to latest
+직위
+Position
+*/
+ MSG_POSITION = 0x1f7,
+/*20031029 to latest
+직업
+Job
+*/
+ MSG_JOB = 0x1f8,
+/*20031029 to latest
+메모
+Note
+*/
+ MSG_MEMO = 0x1f9,
+/*20031029 to latest
+기여
+Devotion
+*/
+ MSG_CONTRIBUTION = 0x1fa,
+/*20031029 to latest
+상납경험치
+Tax Point
+*/
+ MSG_EXP_CONTIRIBUTION = 0x1fb,
+/*20031029 to latest
+길드탈퇴
+Leave Guild
+*/
+ MSG_LEAVE_GUILD = 0x1fc,
+/*20031029 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL_GUILD = 0x1fd,
+/*20031029 to latest
+서열
+Rank
+*/
+ MSG_GRADE = 0x1fe,
+/*20031029 to latest
+직위명
+Position Title
+*/
+ MSG_POSITION_NAME = 0x1ff,
+/*20031029 to latest
+가입권한
+Invitation
+*/
+ MSG_JOIN_AUTHORITY = 0x200,
+/*20031029 to latest
+처벌권한
+Punish
+*/
+ MSG_PENALTY_AUTORITY = 0x201,
+/*20031029 to latest
+상납%
+Tax %
+*/
+ MSG_CONTRIBUTION_PERCENT = 0x202,
+/*20031029 to latest
+제목
+Title
+*/
+ MSG_TITLE = 0x203,
+/*20031029 to latest
+내용
+For
+*/
+ MSG_CONTENTS = 0x204,
+/*20031029 to latest
+길드이름
+Guild Name
+*/
+ MSG_GUILD_NAME = 0x205,
+/*20031029 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILD_LEVEL = 0x206,
+/*20031029 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_PEOPLE_COUNT = 0x207,
+/*20031029 to latest
+랭킹
+Ranking
+*/
+ MSG_RANKING = 0x208,
+/*20031029 to latest
+아이템 감정
+Item Appraisal
+*/
+ MSG_ITEM_IDENTIFY = 0x209,
+/*20031029 to latest
+아이템 조합
+Insert Card
+*/
+ MSG_ITEM_COMPOUNDING = 0x20a,
+/*20031029 to latest
+탈퇴 사유를 입력해주세요.
+Please enter the reason of Secession.
+*/
+ MSG_PLEASE_INPUT_WHY_LEAVING = 0x20b,
+/*20031029 to latest
+추방 사유를 입력해주세요.
+Please enter the reason of Expulsion.
+*/
+ MSG_PELASE_INPUT_WHY_EXPEL = 0x20c,
+/*20031029 to latest
+상점을 닫으세요.
+Please close Shop.
+*/
+ MSG_PLEASE_CLOSE_STORE = 0x20d,
+/*20031029 to latest
+스킬 이름
+Skill
+*/
+ MSG_SKILL_NAME = 0x20e,
+/*20031029 to latest
+아이템 이름
+Item Name
+*/
+ MSG_ITEM_NAME = 0x20f,
+/*20031029 to 20031118
+https://pay.ragnarok.co.kr
+20031119 to latest
+https://payment.ragnarok.co.kr
+https://pay.ragnarok.co.kr (Billing Web)
+*/
+ MSG_SETTLE_WEB_URL = 0x210,
+/*20031029 to latest
+게임방에서 사용가능한 IP개수가 모두 사용중입니다. 개인 계정으로 결제 하시겠습니까?
+IP capacity of this Internet Cafe is full. Would you like to pay the personal base?
+*/
+ MSG_BAN_IP_OVERFLOW = 0x211,
+/*20031029 to latest
+결제시간이 다되어 게임을 종료합니다.
+You are out of available paid playing time. Game will be shut down automatically.
+*/
+ MSG_BAN_PAY_OUT = 0x212,
+/*20031029 to latest
+이름이 너무 깁니다. 한글 11자 영문 23자 이내로 써주십시오.
+Name is too long. Please enter a name no greater than 23 english characters.
+*/
+ MSG_NAMELENGTH_TOO_LONG = 0x213,
+/*20031029 to latest
+deleted
+Character will be deleted in %d seconds.
+*/
+ MSG_DELETE_AFTER_10_SECOND = 0x214,
+/*20031029 to latest
+귀하는 개인 정액제 사용자입니다.
+You paid with the personal regular base.
+*/
+ MSG_BILLING_100 = 0x215,
+/*20031029 to latest
+귀하는 개인정량제 사용자입니다.
+You paid with the personal regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_200 = 0x216,
+/*20031029 to latest
+귀하는 개인 무료 사용자입니다.
+You are free!
+*/
+ MSG_BILLING_300 = 0x217,
+/*20031029 to latest
+귀하는 개인 무료 허용기간 사용자입니다.
+You are free for the test, your available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_400 = 0x218,
+/*20031029 to latest
+귀하는 게임방 정액제 사용자입니다.
+You paid with the Internet Cafe regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_500 = 0x219,
+/*20031029 to latest
+귀하는 게임방 정량제 사용자입니다.
+You paid with the Time Limit for Internet Cafe. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_501 = 0x21a,
+/*20031029 to latest
+귀하는 게임방 무료 허용기간 사용자입니다.
+You are free for the test of Internet Cafe version .
+*/
+ MSG_BILLING_600 = 0x21b,
+/*20031029 to latest
+귀하는 게임방 무료 사용자입니다.
+You are free for the Internet Cafe version.
+*/
+ MSG_BILLING_700 = 0x21c,
+/*20031029 to latest
+귀하는 종량제 사이트 이용자입니다.
+You paid on the Time Limit Website.
+*/
+ MSG_BILLING_800 = 0x21d,
+/*20031029 to latest
+이모션 목록
+Emotion icon List
+*/
+ MSG_EMOTION_LIST = 0x21e,
+/*20031029 to latest
+/이모션
+/emo
+*/
+ MSG_VIEW_EMOTION = 0x21f,
+/*20031029 to latest
+/!
+*/
+ MSG_EMOTION_SURPRISE = 0x220,
+/*20031029 to latest
+/?
+*/
+ MSG_EMOTION_QUESTION = 0x221,
+/*20031029 to latest
+/기쁨
+/ho
+*/
+ MSG_EMOTION_DELIGHT = 0x222,
+/*20031029 to latest
+/하트
+/lv
+*/
+ MSG_EMOTION_THROB = 0x223,
+/*20031029 to latest
+/왕하트
+/lv2
+*/
+ MSG_EMOTION_BIGTHROB = 0x224,
+/*20031029 to latest
+/땀
+/swt
+*/
+ MSG_EMOTION_SWEAT = 0x225,
+/*20031029 to latest
+/아하
+/ic
+*/
+ MSG_EMOTION_AHA = 0x226,
+/*20031029 to latest
+/짜증
+/an
+*/
+ MSG_EMOTION_FRET = 0x227,
+/*20031029 to latest
+/화
+/ag
+*/
+ MSG_EMOTION_ANGER = 0x228,
+/*20031029 to latest
+/돈
+/$
+*/
+ MSG_EMOTION_MONEY = 0x229,
+/*20031029 to latest
+/...
+*/
+ MSG_EMOTION_THINK = 0x22a,
+/*20031029 to latest
+/감사
+/thx
+*/
+ MSG_EMOTION_THANKS = 0x22b,
+/*20031029 to latest
+/꽥
+/wah
+*/
+ MSG_EMOTION_KEK = 0x22c,
+/*20031029 to latest
+/죄송
+/sry
+*/
+ MSG_EMOTION_SORRY = 0x22d,
+/*20031029 to latest
+/웃음
+/heh
+*/
+ MSG_EMOTION_SMILE = 0x22e,
+/*20031029 to latest
+/뻘뻘
+/swt2
+*/
+ MSG_EMOTION_PROFUSELY_SWEAT = 0x22f,
+/*20031029 to latest
+/긁적
+/hmm
+*/
+ MSG_EMOTION_SCRATCH = 0x230,
+/*20031029 to latest
+/최고
+/no1
+*/
+ MSG_EMOTION_BEST = 0x231,
+/*20031029 to latest
+/두리번
+/??
+*/
+ MSG_EMOTION_STARE_ABOUT = 0x232,
+/*20031029 to latest
+/헉
+/omg
+*/
+ MSG_EMOTION_HUK = 0x233,
+/*20031029 to latest
+/오
+/oh
+*/
+ MSG_EMOTION_O = 0x234,
+/*20031029 to latest
+/엑스
+/X
+*/
+ MSG_EMOTION_X = 0x235,
+/*20031029 to latest
+/헬프
+/hlp
+*/
+ MSG_EMOTION_HELP = 0x236,
+/*20031029 to latest
+/가
+/go
+*/
+ MSG_EMOTION_GO = 0x237,
+/*20031029 to latest
+/엉엉
+/sob
+*/
+ MSG_EMOTION_CRY = 0x238,
+/*20031029 to latest
+/킥킥
+/gg
+*/
+ MSG_EMOTION_KIK = 0x239,
+/*20031029 to latest
+/쪽
+/kis
+*/
+ MSG_EMOTION_CHUP = 0x23a,
+/*20031029 to latest
+/쪽쪽
+/kis2
+*/
+ MSG_EMOTION_CHUPCHUP = 0x23b,
+/*20031029 to latest
+/흥
+/pif
+*/
+ MSG_EMOTION_HNG = 0x23c,
+/*20031029 to latest
+/응
+/ok
+*/
+ MSG_EMOTION_OK = 0x23d,
+/*20031029 to latest
+단축키 목록
+Shortcut List
+*/
+ MSG_SHORTCUT_LIST = 0x23e,
+/*20031029 to latest
+귀하의 계정은 보류되었습니다.
+Your account is suspended.
+*/
+ MSG_BAN_PAY_SUSPEND = 0x23f,
+/*20031029 to latest
+과금 정책 변경으로 인해 일시 종료됩니다. 다시 접속하여 주시기 바랍니다.
+Your connection is terminated due to change in the billing policy. Please connect again.
+*/
+ MSG_BAN_PAY_CHANGE = 0x240,
+/*20031029 to latest
+어카운트 서버에 인증된 IP와 귀하의 IP가 달라 연결을 종료합니다.
+Your connection is terminated because your IP doesn't match the authorized IP from the account server.
+*/
+ MSG_BAN_PAY_WRONGIP = 0x241,
+/*20031029 to latest
+게임방 IP에서 개인 종량제 과금을 막기 위해 연결을 종료합니다. 개인 종량제 과금을 사용하기 위해서는 게임방IP로 등록이 되지 않은 IP를 사용해 주세요.
+Your connection is terminated to prevent charging from your account's play time.
+*/
+ MSG_BAN_PAY_PNGAMEROOM = 0x242,
+/*20031029 to latest
+귀하는 운영자에 의해 강제 종료 되었습니다.
+You have been forced to disconnect by the Game Master Team.
+*/
+ MSG_BAN_OP_FORCE = 0x243,
+/*20031029 to latest
+무게가 90%를 초과하여 스킬을 사용할 수 없습니다.
+You can't use this Skill because you are over your Weight Limit.
+*/
+ MSG_USESKILL_FAIL_WEIGHTOVER = 0x244,
+/*20031029 to latest
+무명
+Nameless
+*/
+ MSG_NAMELESS_USER = 0x245,
+/*20031029 to latest
+축하합니다. %s님의 현재 랭킹이 %d위로 상승하였습니다.
+Congratulations! %s ranking has gone up to %d.
+*/
+ MSG_RANK_IN_TEN = 0x246,
+/*20031029 to latest
+안타깝게도 %s님의 현재 랭킹이 %d위로 하락하였습니다.
+What a pity! %s ranking has gone down to %d.
+*/
+ MSG_RANK_OUT_TEN = 0x247,
+/*20031029 to latest
+Pet Info
+*/
+ MSG_PET_INFO = 0x248,
+/*20031029 to latest
+만복도
+Hunger
+*/
+ MSG_PET_HUNGRY = 0x249,
+/*20031029 to latest
+친밀도
+Intimacy
+*/
+ MSG_PET_FRIENDLY = 0x24a,
+/*20031029 to latest
+상점과 채팅방을 동시에 열수 없습니다.
+Please avoid opening a chatroom while vending.
+*/
+ MSG_CANT_OPEN_STORE_WHILE_CHAT = 0x24b,
+/*20031029 to latest
+개
+Total
+*/
+ MSG_EA4 = 0x24c,
+/*20031029 to latest
+%s 를 전투불능으로 만들었습니다.
+You have knocked down %s.
+*/
+ MSG_SLAIN = 0x24d,
+/*20031029 to latest
+%s 님에 의해 전투불능 상태가 되었습니다.
+You have been knocked down by %s.
+*/
+ MSG_SLAINBY = 0x24e,
+/*20031029 to latest
+먹이 - '%s' 아이템이 존재하지 않습니다..
+Feed - "%s" is not available.
+*/
+ MSG_NOT_EXIST_PET_FOOD = 0x24f,
+/*20031029 to latest
+먹이 주기
+Feed Pet
+*/
+ MSG_PET_FEEDING = 0x250,
+/*20031029 to latest
+퍼포먼스
+Performance
+*/
+ MSG_PET_PERFORMANCE = 0x251,
+/*20031029 to latest
+알로 되돌리기
+Return to Egg Shell
+*/
+ MSG_PET_RETURN_EGG = 0x252,
+/*20031029 to latest
+악세사리 해제
+Unequip Accessory
+*/
+ MSG_PET_ACC_OFF = 0x253,
+/*20031029 to latest
+Pet 상태 보기
+Check Pet Status
+*/
+ MSG_PET_SHOWINFO = 0x254,
+/*20031029 to latest
+악세사리
+Accessory
+*/
+ MSG_PET_ACCESSARY = 0x255,
+/*20031029 to latest
+장착됨
+Equipped
+*/
+ MSG_ITEM_EQUIPED = 0x256,
+/*20031029 to latest
+펫 리스트
+Pet List
+*/
+ MSG_PET_EGG_LIST = 0x257,
+/*20031029 to latest
+장착 안됨
+Unequipped
+*/
+ MSG_ITEM_UNEQUIPED = 0x258,
+/*20031029 to latest
+정말로 먹이를 주시겠습니까?
+Are you sure that you want to feed your pet?
+*/
+ MSG_SURE_TO_FEED_PET = 0x259,
+/*20031029 to latest
+가격을 쓰실땐 숫자(0~9)만 써주십시오.
+Only the numbers (0~9) are available.
+*/
+ MSG_CAN_INPUT_NUMBER_ONLY = 0x25a,
+/*20031029 to latest
+감정되지 않은 아이템은 판매할 수 없습니다.
+You cannot sell unidentified items.
+*/
+ MSG_CANT_SELL_UNIDENTIFIED_ITEM = 0x25b,
+/*20031029 to latest
+가격이 0 Zeny인 아이템이 존재합니다. 계속 하시겠습니까?
+Item at 0 Zeny exists. Do you wish to continue?
+*/
+ MSG_YOU_HAVE_FREE_ITEM_ON_SHOP = 0x25c,
+/*20031029 to latest
+[새로 추가된 이모션 리스트]
+[New Emotion List]
+*/
+ MSG_NEW_EMOTION_LIST = 0x25d,
+/*20031029 to latest
+일본쪽 베타 사용자들에게 전하는 메세지. -> 겅호에서 재가입 하세요.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE1 = 0x25e,
+/*20031029 to latest
+일본쪽 과금이 종료된 사용자들에게 전하는 메세지. -> 돈내라. 두 번내라.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE2 = 0x25f,
+/*20031029 to latest
+같은 계정의 캐릭터가 이미 가입되어있습니다.
+Character in the same account already joined.
+*/
+ MSG_ALREADY_SAME_AID_JOINED = 0x260,
+/*20031029 to latest
+(%d 명) - 만18세이상
+(%d ppl) - over the age 18
+*/
+ MSG_SERVER_PROPERTY_ADULT = 0x261,
+/*20031029 to latest
+ 프로보크 상태가 되었습니다.
+Provoke initiated.
+*/
+ MSG_ENST_PROVOKE = 0x262,
+/*20031029 to latest
+ 프로보크 상태가 해제되었습니다.
+Provoke canceled.
+*/
+ MSG_DSST_PROVOKE = 0x263,
+/*20031029 to latest
+ 인듀어 상태가 되었습니다.
+Endure initiated.
+*/
+ MSG_ENST_ENDURE = 0x264,
+/*20031029 to latest
+ 인듀어 상태가 해제되었습니다.
+Endure canceled.
+*/
+ MSG_DSST_ENDURE = 0x265,
+/*20031029 to latest
+ 집중력 향상 상태가 되었습니다.
+Improve Concentration initiated.
+*/
+ MSG_ENST_CONCENTRATION = 0x266,
+/*20031029 to latest
+ 집중력 향상 상태가 해제되었습니다.
+Improve Concentration canceled.
+*/
+ MSG_DSST_CONCENTRATION = 0x267,
+/*20031029 to latest
+ 하이딩 상태가 되었습니다.
+Hiding Initiated.
+*/
+ MSG_ENST_HIDING = 0x268,
+/*20031029 to latest
+ 하이딩 상태가 해제되었습니다.
+Hiding Canceled.
+*/
+ MSG_DSST_HIDING = 0x269,
+/*20031029 to latest
+ 클로킹 상태가 되었습니다.
+Cloaking initiated.
+*/
+ MSG_ENST_CLOAKING = 0x26a,
+/*20031029 to latest
+ 클로킹 상태가 해제되었습니다.
+Cloaking canceled.
+*/
+ MSG_DSST_CLOAKING = 0x26b,
+/*20031029 to latest
+ 독을 반사 할 수 있는 상태가 되었습니다.
+Poison React initiated.
+*/
+ MSG_ENST_POISONREACT = 0x26c,
+/*20031029 to latest
+ 포이즌 리액트 상태가 해제되었습니다.
+Poison React canceled.
+*/
+ MSG_DSST_POISONREACT = 0x26d,
+/*20031029 to latest
+ 이동속도가 감소하였습니다.
+Speed reduced.
+*/
+ MSG_ENST_QUAGMIRE = 0x26e,
+/*20031029 to latest
+ 콰그마이어 상태가 해제되었습니다.
+Quagmire canceled.
+*/
+ MSG_DSST_QUAGMIRE = 0x26f,
+/*20031029 to latest
+ 방어력이 증가되었습니다.
+Defense increased.
+*/
+ MSG_ENST_ANGELUS = 0x270,
+/*20031029 to 20031224
+ 안젤루스 상태가 해제돼었습니다.
+20031229 to latest
+ 안젤루스 상태가 해제되었습니다.
+Angelus canceled.
+*/
+ MSG_DSST_ANGELUS = 0x271,
+/*20031029 to latest
+ 힘과 지능, 덱스가 증가하였습니다.
+Blessing aligned.
+*/
+ MSG_ENST_BLESSING = 0x272,
+/*20031029 to latest
+ 블레싱 상태가 해제되었습니다.
+Blessing canceled.
+*/
+ MSG_DSST_BLESSING = 0x273,
+/*20031029 to latest
+ 시그넘 크루시스를 사용하였습니다.
+Signum Crusis initiated.
+*/
+ MSG_ENST_CRUCIS = 0x274,
+/*20031029 to latest
+ 시그넘 크루시스 상태가 해제되었습니다.
+Signum Crusis canceled.
+*/
+ MSG_DSST_CRUCIS = 0x275,
+/*20031029 to latest
+ 독이 퍼지는 속도가 느려졌습니다.
+Slow Poison initiated.
+*/
+ MSG_ENST_SLOWPOISON = 0x276,
+/*20031029 to latest
+ 슬로우 포이즌 상태가 해제되었습니다.
+Slow Poison Canceled.
+*/
+ MSG_DSST_SLOWPOISON = 0x277,
+/*20031029 to latest
+ SP의 회복 속도가 향상 되었습니다.
+HP/SP recovery increased.
+*/
+ MSG_ENST_MAGNIFICAT = 0x278,
+/*20031029 to latest
+ 마니피캇 상태가 해제되었습니다.
+Magnificat canceled.
+*/
+ MSG_DSST_MAGNIFICAT = 0x279,
+/*20031029 to latest
+ 행운이 향상되었습니다.
+Luck increased.
+*/
+ MSG_ENST_GLORIA = 0x27a,
+/*20031029 to latest
+ 글로리아 상태가 해제되었습니다.
+Gloria canceled.
+*/
+ MSG_DSST_GLORIA = 0x27b,
+/*20031029 to latest
+ 1회 공격에 두 배 데미지를 받는 상태가 되었습니다.
+You will received double damage from all attacking opponents.
+*/
+ MSG_ENST_LEXAETERNA = 0x27c,
+/*20031029 to latest
+ 렉스에테르나 상태가 해제되었습니다.
+Lex Eterna canceled.
+*/
+ MSG_DSST_LEXAETERNA = 0x27d,
+/*20031029 to latest
+ 공격속도가 증가하였습니다.
+Attack Speed increased.
+*/
+ MSG_ENST_ADRENALINE = 0x27e,
+/*20031029 to latest
+ 공격속도가 감소하였습니다.
+Attack Speed reduced.
+*/
+ MSG_DSST_ADRENALINE = 0x27f,
+/*20031029 to latest
+ 페코에 올라 탔습니다.
+You've just been on a Peco Peco.
+*/
+ MSG_ENST_RIDING = 0x280,
+/*20031029 to latest
+ 페코에서 내렸습니다.
+You've just got off of a Peco Peco.
+*/
+ MSG_DSST_RIDING = 0x281,
+/*20031029 to latest
+ 팔콘을 장착하였습니다.
+You've just carried a Falcon with.
+*/
+ MSG_ENST_FALCON = 0x282,
+/*20031029 to latest
+ 팔콘을 풀어주었습니다.
+You've just released a Falcon.
+*/
+ MSG_DSST_FALCON = 0x283,
+/*20031029 to latest
+ 죽은척하기 상태가 되었습니다.
+Play Dead initiated.
+*/
+ MSG_ENST_TRICKDEAD = 0x284,
+/*20031029 to latest
+ 죽은척하기 상태가 해제되었습니다.
+Play Dead canceled.
+*/
+ MSG_DSST_TRICKDEAD = 0x285,
+/*20031029 to latest
+ 힘이 강해졌습니다.
+STR improved.
+*/
+ MSG_ENST_SHOUT = 0x286,
+/*20031029 to latest
+ 힘이 원래대로 돌아왔습니다.
+STR turned back to normal.
+*/
+ MSG_DSST_SHOUT = 0x287,
+/*20031029 to latest
+ 에너지코트 상태가 되었습니다.
+Energy Coat initiated.
+*/
+ MSG_ENST_ENERGYCOAT = 0x288,
+/*20031029 to latest
+ 에너지코트 상태가 해제되었습니다.
+Energy Coat canceled.
+*/
+ MSG_DSST_ENERGYCOAT = 0x289,
+/*20031029 to latest
+ 방어구가 파괴되었습니다.
+Armor destroyed.
+*/
+ MSG_ENST_BROKENAMOR = 0x28a,
+/*20031029 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENAMOR = 0x28b,
+/*20031029 to latest
+ 무기가 파괴되었니다.
+Weapon destroyed.
+*/
+ MSG_ENST_BROKENWEAPON = 0x28c,
+/*20031029 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENWEAPON = 0x28d,
+/*20031029 to latest
+ 환영상태가 되었습니다.
+Invisibility initiated.
+*/
+ MSG_ENST_ILLUSION = 0x28e,
+/*20031029 to latest
+ 환영상태가 해제되었습니다.
+Invisibility canceled.
+*/
+ MSG_DSST_ILLUSION = 0x28f,
+/*20031029 to latest
+과금 정보 처리가 늦어지고 있어 접속이 지연되고 있습니다. 잠시 후에 다시 시도해 주시기 바랍니다.
+Sorry. It is delayed due to the process of payment. Please re-connect in a minute.
+*/
+ MSG_REFUSE_BLOCK_TEMPORARY = 0x290,
+/*20031029 to 20060403
+장착된 화살을 해제 하여야 합니다.
+20060410 to 20061009
+장착된 화살 또는 탄환을 해제 하여야 합니다.
+20061016 to latest
+장착된 화살/탄환/수리검 을 해제해야합니다.
+You must unequip ammunition first.
+*/
+ MSG_UNEQUIP_ARROW = 0x291,
+/*20031029 to latest
+화살 목록
+Arrow List
+*/
+ MSG_ARROW_LIST = 0x292,
+/*20031029 to latest
+카트 목록
+Cart List
+*/
+ MSG_CART_LIST = 0x293,
+/*20031029 to latest
+카트를 장착한 상태여야 합니다.
+You must have a Pushcart.
+*/
+ MSG_MUST_EQUIP_CART = 0x294,
+/*20031029 to latest
+채팅방을 개설 할 수 없습니다.
+You cannot open a Chat Window.
+*/
+ MSG_CANT_MAKE_CHAT_ROOM = 0x295,
+/*20031029 to latest
+라그나로크 홈페이지로 접속하여 계정을 만듭니다. 처음 계정을 만드시면 3일 동안은 무료로 이용하실 수 있습니다.
+Registering an account is the first step to accessing the game. Do you want to visit the registration page now?
+*/
+ MSG_3DAY_FREE = 0x296,
+/*20031029 to latest
+앉은 상태에서는 이 아이템을 사용할 수 없습니다.
+You cannot use this item while sitting.
+*/
+ MSG_CANT_USE_WHEN_SITDOWN = 0x297,
+/*20031029 to 20040413
+운영자에 의한 채팅 및 스킬 금지가 %d 분간 남아 있습니다.
+20040419 to 20040713
+운영자에 의한 채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+20040726 to latest
+채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+Your use of skills and chat will be blocked for the next %d minutes.
+*/
+ MSG_BAD_MANNER_REMAIN = 0x298,
+/*20031029 to 20040413
+운영자에 의한 채팅 및 스킬 금지가 해지 되었습니다.
+20040419 to 20040713
+운영자에 의한 채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+20040726 to latest
+채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+Your use of skills and chat have been reinstated.
+*/
+ MSG_BAD_MANNER_END = 0x299,
+/*20031029 to latest
+-[장착안됨]
+- [Not equipped]
+*/
+ MSG_REF_UNEQUIP = 0x29a,
+/*20031029 to latest
+배고픔
+Very Hungry
+*/
+ MSG_VERY_HUNGRY = 0x29b,
+/*20031029 to latest
+출출함
+Hungry
+*/
+ MSG_HUNGRY = 0x29c,
+/*20031029 to latest
+보통
+Normal
+*/
+ MSG_NORMAL = 0x29d,
+/*20031029 to latest
+배부름
+Satisfied
+*/
+ MSG_REPLETE = 0x29e,
+/*20031029 to latest
+아주 배부름
+Stuffed
+*/
+ MSG_VERY_REPLETE = 0x29f,
+/*20031029 to latest
+서먹서먹함
+Awkward
+*/
+ MSG_VERY_AWKWARD = 0x2a0,
+/*20031029 to latest
+어색함
+Shy
+*/
+ MSG_AWKWARD = 0x2a1,
+/*20031029 to latest
+친함
+Cordial
+*/
+ MSG_FRIENDLY = 0x2a2,
+/*20031029 to latest
+절친함
+Loyal
+*/
+ MSG_VERY_FRIENDLY = 0x2a3,
+/*20031029 to latest
+알수 없음
+Unknown
+*/
+ MSG_UNKNOWN = 0x2a4,
+/*20031029 to 20080520
+(태국)귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+20080527 to latest
+귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d day %d hour %d minute.
+*/
+ MSG_BILLING_DAY_HOUR_MINUTES = 0x2a5,
+/*20031029 to 20080520
+(태국)이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+20080527 to latest
+이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+Your account is already connected to account server.
+*/
+ MSG_BAN_INFORMATION_REMAINED_ANOTHER_ACCOUNT = 0x2a6,
+/*20031029 to 20080520
+(태국)귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+20080527 to latest
+귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d hour %d minute.
+*/
+ MSG_BILLING_HOUR_MINUTES = 0x2a7,
+/*20031029 to 20080520
+(태국)귀하는 무료 사용자 입니다.
+20080527 to latest
+귀하는 무료 사용자 입니다.
+Your account is a free account.
+*/
+ MSG_BILLING_FREE_USER = 0x2a8,
+/*20031029 to 20080520
+(태국)이 계정으로 사크라이에 접속할수 없습니다.
+20080527 to latest
+이 계정으로 사크라이에 접속할수 없습니다.
+This account can't connect the Sakray server.
+*/
+ MSG_REFUSE_NONSAKRAY_ID_BLOCKED = 0x2a9,
+/*20031029 to latest
+펫의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Your pet name must be 23 characters or less.
+*/
+ MSG_PETNAME_IN23 = 0x2aa,
+/*20031029 to latest
+이름은 단 한번만 바꿀수 있습니다. 펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You may change your pet's name only once. Your pet's name will be changed to ^0000ff^0000ff %s^000000^000000. Do you wish to continue?
+*/
+ MSG_PETNAME_CHANGE_ONLYONCE = 0x2ab,
+/*20031029 to latest
+/폰트
+/font
+*/
+ MSG_NAMEBALLOON_TYPE = 0x2ac,
+/*20031029 to latest
+길드에 남은 제니가 부족하여 작업이 실패하였습니다.
+Your guild lacks the funds to pay for this venture.
+*/
+ MSG_GUILDZENY_NOT_ENOUGH = 0x2ad,
+/*20031029 to latest
+길드가 소유할 수 있는 최대 금액을 초과하여 작업이 실패하였습니다.
+Your guild zeny limit prevents you from performing this action.
+*/
+ MSG_GUILDZENY_OVER = 0x2ae,
+/*20031029 to latest
+이펙트 간략화 On
+Simplified effects have been activated.
+*/
+ MSG_MINEFFECT_ON = 0x2af,
+/*20031029 to latest
+이펙트 간략화 Off
+Simplified effects have been deactivated.
+*/
+ MSG_MINEFFECT_OFF = 0x2b0,
+/*20031029 to latest
+자본금
+Required Fee
+*/
+ MSG_CAPITAL = 0x2b1,
+/*20031029 to latest
+아이템을 바닥에 버리려면, 아이템 창을 열어 주십시오.
+If you wish to drop an item, you must first open your Item Window (alt+e).
+*/
+ MSG_OPEN_ITEMWND_TO_THROW = 0x2b2,
+/*20031029 to latest
+PC방 요금이 종료하여 개인 요금제로 전환합니다. 개인 요금으로 게임을 계속 하시겠습니까?
+Internet Cafe Time Plan has been ended. Would you like to continue the game with your personal play time?
+*/
+ MSG_ASK_PNGAMEROOM = 0x2b3,
+/*20031029 to latest
+
+20080520 to 20080520
+
+Current admission application state.
+*/
+ MSG_REPLY_REMAINTIME = 0x2b4,
+/*20031029 to latest
+
+20080520 to 20080520
+
+Current admission application state.
+*/
+ MSG_INFO_REMAINTIME = 0x2b5,
+/*20031029 to latest
+돈이 모자라거나, 가질 수 있는 최대 금액을 초과하였습니다.
+Your lack of zeny or your zeny limit have prevented you from performing this action.
+*/
+ MSG_OVER_OR_LOW_MONEY = 0x2b6,
+/*20031029 to latest
+전투불능 상태가 되었습니다. esc키를 누르시면 선택창이 뜹니다.
+Your character has fainted. Push the ESC key to restart.
+*/
+ MSG_PRESS_ESC_TO_RESTART = 0x2b7,
+/*20031029 to latest
+ %d 개 획득
+- %d obtained.
+*/
+ MSG_EA_OBTAIN = 0x2b8,
+/*20031029 to latest
+스펠 리스트
+Spell List
+*/
+ MSG_SPELL_LIST = 0x2b9,
+/*20031029 to latest
+/최소화
+/minimize
+*/
+ MSG_MINEFFECT = 0x2ba,
+/*20031029 to latest
+이 아이템은 손상되어 있습니다..
+This item has been damaged.
+*/
+ MSG_DAMAGED_ITEM = 0x2bb,
+/*20031029 to latest
+/noshift : 쉬프트를 누르지않고 힐로 적을 공격할수있게됩니다 On Off
+/noshift: You may use your ''force heal'' ability without the Shift key. On | Off
+*/
+ MSG_EXPLAIN_NOSHIFT = 0x2bc,
+/*20031029 to 20040223
+시프트를 누르지 않고도 힐로 몬스터를 공격할수 있습니다 [ON]
+20040225 to latest
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns ON]
+[no shift] option activated. [ON]
+*/
+ MSG_NOSHIFT_ON = 0x2bd,
+/*20031029 to 20040223
+시프트를 누르지 않고도 힐로 몬스터를 공격할수 있습니다 [OFF]
+20040225 to 20040315
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+20040322 to latest
+시프트를 눌러야 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+[no shift] option deactivated. [OFF]
+*/
+ MSG_NOSHIFT_OFF = 0x2be,
+/*20031029 to latest
+MSI_REFUSE_BAN_BY_DBA
+*/
+ MSG_REFUSE_BAN_BY_DBA = 0x2bf,
+/*20031029 to latest
+MSI_REFUSE_EMAIL_NOT_CONFIRMED
+*/
+ MSG_REFUSE_EMAIL_NOT_CONFIRMED = 0x2c0,
+/*20031029 to latest
+MSI_REFUSE_BAN_BY_GM
+*/
+ MSG_REFUSE_BAN_BY_GM = 0x2c1,
+/*20031029 to latest
+MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+*/
+ MSG_REFUSE_TEMP_BAN_FOR_DBWORK = 0x2c2,
+/*20031029 to latest
+MSI_REFUSE_SELF_LOCK
+*/
+ MSG_REFUSE_SELF_LOCK = 0x2c3,
+/*20031029 to latest
+MSI_REFUSE_NOT_PERMITTED_GROUP
+*/
+ MSG_REFUSE_NOT_PERMITTED_GROUP = 0x2c4,
+/*20031029 to latest
+MSI_REFUSE_WAIT_FOR_SAKRAY_ACTIVE
+*/
+ MSG_REFUSE_WAIT_FOR_SAKRAY_ACTIVE = 0x2c5,
+/*20031029 to latest
+/aura : 오오라를 간략화 시킬수있습니다 On Off
+/aura: Simplify Aura effect On | Off
+*/
+ MSG_EXPLAIN_AURA = 0x2c6,
+/*20031029 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_AURA_ON = 0x2c7,
+/*20031029 to latest
+오오라가 간략화되서 표시됩니다 [오오라 OFF]
+Simplify Aura enabled. [ON]
+*/
+ MSG_AURA_OFF = 0x2c8,
+/*20031029 to latest
+채팅금지 기록 %d 회
+Chat block record %d times
+*/
+ MSG_PROHIBIT_LOG = 0x2c9,
+/*20031029 to latest
+채팅 금지 리스트
+Chat block list
+*/
+ MSG_PROHIBIT_LIST = 0x2ca,
+/*20031029 to latest
+/이름표시 or /showname : 캐릭터의 이름 표시 방식을 변경합니다.
+/showname: Change the name font type.
+*/
+ MSG_EXPLAIN_SHOWNAMETYPE = 0x2cb,
+/*20031029 to latest
+/noctrl : 콘트롤을 누르지않아도 자동공격이 됩니다. On Off
+/noctrl | /nc: Auto attack without pressing ctrl key. On | Off
+*/
+ MSG_EXPLAIN_NOCTRL = 0x2cc,
+/*20031029 to 20040223
+콘트롤을 누르지 않아도 자동공격을 합니다 [자동공격 ON]
+20040225 to latest
+콘트롤을 누르지 않아도 자동공격을 합니다 [/nc ON]
+Use auto attack without Ctrl. [Auto attack ON]
+*/
+ MSG_NOCTRL_ON = 0x2cd,
+/*20031029 to 20040223
+콘트롤을 눌러야 자동공격을 합니다 [자동공격 OFF]
+20040225 to latest
+콘트롤을 눌러야 자동공격을 합니다 [/nc OFF]
+Use auto attack with Ctrl. [Auto attack OFF]
+*/
+ MSG_NOCTRL_OFF = 0x2ce,
+/*20031029 to latest
+채팅 금지 주기
+Mute this player.
+*/
+ MSG_APPEND_PROHIBIT = 0x2cf,
+/*20031029 to latest
+채팅 금지 완전 풀기 & 로그 삭제
+Unmute player & Erase mute time.
+*/
+ MSG_ERASE_PROHIBIT = 0x2d0,
+/*20031029 to latest
+채팅 금지 시간 줄이기(로그 삭제 안됨)
+Decrease Player Mute time.
+*/
+ MSG_REDUCE_PROHIBIT = 0x2d1,
+/*20031029 to latest
+폰트가 정상적으로 바뀌었습니다 [이름표시방식 1]
+Normal Font Displayed. [showname type 1]
+*/
+ MSG_SHOWNAME_ON = 0x2d2,
+/*20031029 to latest
+폰트가 가늘게 바뀌면서 파티명도 표시됩니다 [이름표시방식 2]
+Font will be thin and party name will be shown [showname type 2]
+*/
+ MSG_SHOWNAME_OFF = 0x2d3,
+/*20031029 to latest
+/doridori : 연속해서 이 명령어를 쳐주면 캐릭터가 도리도리 ^^;;
+/doridori: Shake head
+*/
+ MSG_EXPLAIN_DORIDORI = 0x2d4,
+/*20031029 to latest
+인터넷 카페에서 과금을 하고 있습니다.
+Internet room is paying now.
+*/
+ MSG_BILLING_INTERNET_CAFE = 0x2d5,
+/*20031029 to latest
+정액제 과금은 %d일 %d시간 %d분이 남았습니다.
+종량제 과금은 %d시간 %d분이 남았습니다.
+Prepaid voucher validate until %d days %d hours %d minutes later.
+Time limit voucher validate untill %d hours %d minutes later.
+*/
+ MSG_BILLING_BOTH = 0x2d6,
+/*20031029 to latest
+/bingbing : 연속해서 이 명령어를 쳐주면 캐릭터가 빙글빙글 ^^;;
+/bingbing: Rotates player counter clockwise.
+*/
+ MSG_EXPLAIN_BINGBING = 0x2d7,
+/*20031029 to latest
+/bangbang : 연속해서 이 명령어를 쳐주면 캐릭터가 뱅글뱅글 ^^;;
+/bangbang: Rotates player clockwise.
+*/
+ MSG_EXPLAIN_BANGBANG = 0x2d8,
+/*20031029 to latest
+/skillfail : 빨간색의 스킬사용 실패 메세지를 표시하지 않습니다 On Off
+/skillfail: Display red font message when skill fails. On | Off
+*/
+ MSG_EXPLAIN_SKILLFAIL = 0x2d9,
+/*20031029 to 20040223
+스킬사용 실패 메세지를 표시합니다 [표시 ON]
+20040225 to latest
+스킬사용 실패 메세지를 표시합니다 [/sf ON]
+Skill fail messages will be displayed. [Display On]
+*/
+ MSG_SKILLFAIL_ON = 0x2da,
+/*20031029 to 20040223
+스킬사용 실패 메세지를 표시하지 않습니다 [표시 OFF]
+20040225 to latest
+스킬사용 실패 메세지를 표시하지 않습니다 [/sf OFF]
+Skill fail messages will not be displayed. [Display OFF]
+*/
+ MSG_SKILLFAIL_OFF = 0x2db,
+/*20031029 to latest
+/notalkmsg : 채팅내용을 채팅창에 표시하지 않습니다 On Off
+/notalkmsg: Chat will not be displayed in chat window. On | Off
+*/
+ MSG_EXPLAIN_NOTALKMSG = 0x2dc,
+/*20031029 to 20040223
+채팅내용을 채팅창에 표시합니다 [표시 ON]
+20040225 to latest
+채팅내용을 채팅창에 표시합니다 [/nm ON]
+Chat content will be displayed in the chat window. [Display ON]
+*/
+ MSG_NOTALKMSG_ON = 0x2dd,
+/*20031029 to 20040223
+채팅내용을 채팅창에 표시하지않습니다 [표시 OFF]
+20040225 to latest
+채팅내용을 채팅창에 표시하지않습니다 [/nm OFF]
+Chat content will not be displayed in the chat window. [Display OFF]
+*/
+ MSG_NOTALKMSG_OFF = 0x2de,
+/*20031029 to 20040423
+/set1 : /noctrl + /showname + /skillfail
+20040426 to 20040707
+/set1 : /noctrl + /showname + /skillfail , /set2 : + /q3
+20040707 to latest
+/set1 : /nc + /showname + /sf + /wi, /set2 : + /q3
+/set1: /noctrl + /showname + /skillfail
+*/
+ MSG_EXPLAIN_SET1 = 0x2df,
+/*20031029 to latest
+/fog : FOG이펙트를 키거나 끌수있습니다 On Off
+/fog: Fog effect. On | Off
+*/
+ MSG_EXPLAIN_FOG = 0x2e0,
+/*20031029 to latest
+ 청혼을 해왔습니다. 승낙하시겠습니까?
+You have received a marriage proposal. Do you accept?
+*/
+ MSG_SUGGEST_COUPLE = 0x2e1,
+/*20031029 to latest
+아이템 분배 방식
+Item sharing type
+*/
+ MSG_HOWITEMDIV = 0x2e2,
+/*20031029 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMDIV1 = 0x2e3,
+/*20031029 to latest
+균등하게 분배
+Shared
+*/
+ MSG_ITEMDIV2 = 0x2e4,
+#if PACKETVER >= 20031103
+/*20031103 to latest
+nProtect KeyCrypt
+*/
+ MSG_KEYCRYPT = 0x2e5,
+/*20031103 to latest
+Keyboard Driver가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+Keyboard Driver has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_INSTALL_KEYDRIVER = 0x2e6,
+/*20031103 to latest
+설치가 완료 되었습니다.
+
+시스템을 Reboot 합니다.
+Installation has been completed.
+
+System will be rebooted.
+*/
+ MSG_KEYCRYPT_REBOOT = 0x2e7,
+/*20031103 to latest
+설치 실패.
+Installation has been failed.
+*/
+ MSG_KEYCRYPT_INSTALLFAIL = 0x2e8,
+/*20031103 to latest
+키보드 보안을 적용하지 않고 계속합니다.
+Keyboard Security will be skipped.
+*/
+ MSG_KEYCRYPT_SKIPKEYCRYPT = 0x2e9,
+/*20031103 to latest
+키보드 보안에 필요한 파일이 존재하지 않습니다.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+Required file for Keyboard Security is not existing.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+*/
+ MSG_KEYCRYPT_NOKEYCRYPTFILE = 0x2ea,
+/*20031103 to latest
+USB Keyboard가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+USB Keyboard has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_USBKEYBOARD = 0x2eb,
+/*20031103 to latest
+ftp://ragnarok.nefficient.co.kr/pub/ragnarok/ragnarok0526.exe
+*/
+ MSG_FINDHACK_PATH = 0x2ec,
+/*20031103 to latest
+FindHack이 정상적으로 설치가 되어있지 않습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.(%d).
+FindHack is not installed correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.(%d).
+*/
+ MSG_FINDHACK_NOTINSTALLED = 0x2ed,
+/*20031103 to latest
+해킹툴이 존재하지만 치료가 정상적으로 되지 않았습니다. 라그나로크가 실행되지 않습니다.
+Hacking tool is existing but it hasn't been cleaned. Rangarok Online will not be executed.
+*/
+ MSG_FINDHACK_HACKTOOLEXIST = 0x2ee,
+/*20031103 to latest
+해킹툴 진단 프로그램이 정상적으로 다운로드 되지 않았습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+Hacking tool scan program has not been downloaded correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_CANTDOWNLOAD = 0x2ef,
+/*20031103 to latest
+NPX.DLL 등록에러 이거나 FindHack 구동에 필요한 파일이 없습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+NPX.DLL register error or there is no necessary file to run FindHack. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_NOFILE = 0x2f0,
+/*20031103 to latest
+예외사항이 발생했습니다. (02-3281-0361)로 문의해주세요. 리턴값(%d)
+Exceptional Error. Please contact the customer support. Return Value: (%d)
+*/
+ MSG_FINDHACK_EXCEPTION = 0x2f1,
+/*20031103 to latest
+종료버튼을 클릭 하셨습니다.
+Exit button has been clicked.
+*/
+ MSG_FINDHACK_EXITPRESSED = 0x2f2,
+/*20031103 to latest
+Findhack 업데이트 서버접근 실패하였습니다. 잠시 후에 다시 시도해 주시거나 그라비티 운영팀으로 연락해주시기 바랍니다.
+Unable to connect Findhack Update Server. Please try again or contact the customer support.
+*/
+ MSG_FINDHACK_UPDATEFAILED = 0x2f3,
+/*20031103 to latest
+사랑받고있는
+Beloved
+*/
+ MSG_NAMED_PET = 0x2f4,
+/*20031103 to 20031103
+신고용 갈무리 파일을 저장합니다.
+20031110 to latest
+/report or /신고 : 신고용 갈무리 파일을 저장합니다.
+/report: Save a chat log file.
+*/
+ MSG_REPORTCOMMAND_EXPLANATION = 0x2f5,
+/*20031103 to 20031112
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+20031117 to latest
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로 사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+Chat logs are not accepted as evidence for any ill-mannered violation on account of possible file modifications. However this feature is provided for players' personal reference.
+*/
+ MSG_REPORTTEXT_HEADER = 0x2f6,
+#endif
+#if PACKETVER >= 20031110
+/*20031110 to latest
+당신을 사랑해요 ♡
+I love you.
+*/
+ MSG_LOVE_SKILL = 0x2f7,
+#endif
+#if PACKETVER >= 20031124
+/*20031124 to latest
+화면 또는 이펙트가 밝아서 눈에 부담이 되시는분들은 모니터의 밝기를 조정해주시기바랍니다.
+Please adjust your monitor/video brightness if effects appear too bright.
+*/
+ MSG_EXPLAIN_BRIGHT = 0x2f8,
+#endif
+#if PACKETVER >= 20031218
+/*20031218 to latest
+전체화면모드가 잘안되는 경우에 게임실행후 ALT+TAB으로 화면을 전환하면 잘되는 기종도 있습니다
+If full screen mode fails to work, it is suggested you alt+tab [or ctrl+esc] to inactivate and reactivate the Ragnarok Client.
+*/
+ MSG_EXPLAIN_ALTTAB = 0x2f9,
+#endif
+#if PACKETVER >= 20031223
+/*20031223 to latest
+(%d 명) - 유료서버
+(%d players) - Pay to Play Server
+*/
+ MSG_SERVER_PROPERTY_PAY = 0x2fa,
+/*20031223 to latest
+(%d 명) - 무료서버
+(%d players) - Free Server
+*/
+ MSG_SERVER_PROPERTY_FREE = 0x2fb,
+/*20031223 to latest
+무료 회원은 유료 서버로 접속할 수 없습니다.
+Trial players can't connect Pay to Play Server.
+*/
+ MSG_CANT_CONNECT_TO_PAY_SERVER = 0x2fc,
+#endif
+#if PACKETVER >= 20040107
+/*20040107 to 20040108
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [QUICK ON]
+20040112 to latest
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [/q1 ON]
+Right click menu skills for F9 are Enabled.[/q1 ON]
+*/
+ MSG_QUICKSPELL_ON = 0x2fd,
+/*20040107 to 20040108
+마우스 우클릭으로 스킬을 사용하지 못합니다 [QUICK OFF]
+20040112 to latest
+마우스 우클릭으로 스킬을 사용하지 못합니다 [/q1 OFF]
+Right click menu skills for F9 are Disabled.[/q1 OFF]
+*/
+ MSG_QUICKSPELL_OFF = 0x2fe,
+/*20040107 to 20040119
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+20040126 to latest
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+/quickspell: Right-click menu enables you to use skills assigned to the F9 hotkey. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL = 0x2ff,
+#endif
+#if PACKETVER >= 20040112
+/*20040112 to latest
+마우스의 WHEEL을 사용해서 F7 과 F8에 저장한 스킬을 사용합니다 [/q2 ON]
+Mouse wheel skills for F7 and F8 are Enabled.[/q2 ON]
+*/
+ MSG_QUICKSPELL2_ON = 0x300,
+/*20040112 to latest
+마우스 WHEEL로 스킬을 사용하지 못합니다 [/q2 OFF]
+Mouse wheel skills for F7 and F8 are Disabled.[/q2 OFF]
+*/
+ MSG_QUICKSPELL2_OFF = 0x301,
+/*20040112 to 20040119
+/quickspell2 : 마우스 WHEEL로 F7 과 F8에 저장한 스킬을 사용합니다 On Off
+20040126 to latest
+/quickspell2 : 마우스 WHEEL을 위,아래로 굴려서 F7과F8에 저장한 스킬을 사용합니다 On Off
+/quickspell2: By rolling the mouse wheel up and down, you are able to use skills registered on F7 and F8 hotkeys. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL2 = 0x302,
+/*20040112 to latest
+/q3 : /quickspell (/q1) + /quickspell2 (/q2)
+/q3: /quickspell (/q1) + /quickspell2 (/q2)
+*/
+ MSG_EXPLAIN_QUICKSPELL3 = 0x303,
+#endif
+#if PACKETVER >= 20040202
+/*20040202 to latest
+/찌릿
+/bzz
+*/
+ MSG_EMOTION_STARE = 0x304,
+/*20040202 to latest
+/밥
+/rice
+*/
+ MSG_EMOTION_HUNGRY = 0x305,
+/*20040202 to latest
+/멋져
+/awsm
+*/
+ MSG_EMOTION_COOL = 0x306,
+/*20040202 to latest
+/메롱
+/meh
+*/
+ MSG_EMOTION_MERONG = 0x307,
+/*20040202 to latest
+/부끄
+/shy
+*/
+ MSG_EMOTION_SHY = 0x308,
+/*20040202 to latest
+/쓱쓱
+/pat
+*/
+ MSG_EMOTION_GOODBOY = 0x309,
+/*20040202 to latest
+/엠탐
+/mp
+*/
+ MSG_EMOTION_SPTIME = 0x30a,
+/*20040202 to latest
+/질질
+/slur
+*/
+ MSG_EMOTION_SEXY = 0x30b,
+/*20040202 to latest
+/컴온
+/com
+*/
+ MSG_EMOTION_COMEON = 0x30c,
+/*20040202 to latest
+/하품
+/yawn
+*/
+ MSG_EMOTION_SLEEPY = 0x30d,
+/*20040202 to latest
+/축하
+/grat
+*/
+ MSG_EMOTION_CONGRATULATION = 0x30e,
+/*20040202 to latest
+/피탐
+/hp
+*/
+ MSG_EMOTION_HPTIME = 0x30f,
+/*20040202 to latest
+/이모션 : 현재 사용가능한 이모션의 리스트를 보여줍니다.
+/emotion: views the emoticon list.
+*/
+ MSG_EXPLAIN_EMOTION = 0x310,
+#endif
+#if PACKETVER >= 20040223
+/*20040223 to 20040302
+키보드를 이용해서 스킬단축창2 와 3의 스킬들을 사용합니다. [/bm ON]
+20040308 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용합니다. [/bm ON]
+Skills assigned to shortcut windows 1, 2, 3 are Enabled. [/bm ON]
+*/
+ MSG_BATTLE_ON = 0x311,
+/*20040223 to 20040302
+키보드를 이용해서 스킬단축창2 와 3의 스킬들을 사용하지못합니다. [/bm OFF]
+20040308 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용하지못합니다. [/bm OFF]
+Skills assigned to shortcut windows 1, 2, 3 are Disabled. [/bm OFF]
+*/
+ MSG_BATTLE_OFF = 0x312,
+/*20040223 to latest
+/battlemode : Q ~ O 를 누르면 스킬단축창2의 스킬들이 사용됩니다.
+/battlemode: allows you to use skills assigned to Shortcut Window 2 by pressing Q ~ O keys.
+*/
+ MSG_EXPLAIN_BATTLE = 0x313,
+/*20040223 to 20040302
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다. On Off
+20040308 to latest
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다.
+A ~ L keys allow you to use skills assigned to Shortcut Window 3.
+*/
+ MSG_EXPLAIN_BATTLE2 = 0x314,
+/*20040223 to latest
+라그나로크를 실행하실때 다른 프로그램을 띄우시면 게임이 느려질수도있습니다.
+Please remember, programs running in the background while playing may affect the game's performance.
+*/
+ MSG_EXPLAIN_LAG = 0x315,
+#endif
+#if PACKETVER >= 20040302
+/*20040302 to 20041130
+천사님 제 목소리 들리세여? ^^;
+20041206 to latest
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+*/
+ MSG_SUPERNOVICE1 = 0x316,
+/*20040302 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_SUPERNOVICE2 = 0x317,
+/*20040302 to 20041130
+예여~
+20041206 to latest
+예요~
+Super Novice~
+*/
+ MSG_SUPERNOVICE3 = 0x318,
+/*20040302 to 20041130
+저 좀 도와주세여~ ㅠ_ㅠ
+20041206 to latest
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE4 = 0x319,
+#endif
+#if PACKETVER >= 20040308
+/*20040308 to 20041012
+ 입양을 요청해왔습니다. 승낙하시겠습니까?
+20041018 to latest
+님께서 당신을 입양시키고 싶어하십니다. 승낙하시겠습니까?
+ wishes to adopt you. Do you accept?
+*/
+ MSG_SUGGEST_BABY = 0x31a,
+/*20040308 to latest
+ Z ~ > 을 누르면 스킬단축창1의 스킬들이 사용됩니다. On Off
+Z ~ > keys allow you to use skills assigned on shortcut window 1. On | Off
+*/
+ MSG_EXPLAIN_BATTLE3 = 0x31b,
+/*20040308 to latest
+ Space를 한번 누른뒤에 글자를 입력하면 채팅을 할수있습니다.
+Press the space bar to Chat when in Battle mode [/battlemode | /bm].
+*/
+ MSG_EXPLAIN_BATTLE4 = 0x31c,
+/*20040308 to latest
+게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다.
+"Either there's no Game Guard installed on the program or Game Guard is cracked. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_AUTH_GAMEGUARD = 0x31d,
+/*20040308 to latest
+윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다.
+Some of Windows system files have been damaged. Please re-install your Internet Explorer.
+*/
+ MSG_NPGAMEMON_ERROR_CRYPTOAPI = 0x31e,
+/*20040308 to latest
+게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다.
+"Failed to run Game Guard. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_EXECUTE = 0x31f,
+/*20040308 to latest
+불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다.
+"At least one hazardous program has been detected. Please, terminate all the unnecessary programs before executing Game Guard."
+*/
+ MSG_NPGAMEMON_ERROR_ILLEGAL_PRG = 0x320,
+/*20040308 to latest
+게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 방화벽 상태를 점검해보시기 바랍니다.
+"Game Guard update is canceled. If the disconnection continues, please, check your internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_ABORT = 0x321,
+/*20040308 to latest
+게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 인터넷 및 방화벽 상태를 점검해 보시기 바랍니다.
+"Failed to connect to Game Guard update server. Try to connect again later, or try to check the internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_CONNECT = 0x322,
+/*20040308 to latest
+게임가드 업데이트를 완료하지 못 했습니다. 바이러스 검사를 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정한 후 게임을 실행해 보시기 바랍니다.
+"Can't complete Game Guard update process. Please, try to execute a vaccine program to remove viruses. Or, please try to modify the settings of your PC managing tool if you are using any."
+*/
+ MSG_NPGMUP_ERROR_AUTH = 0x323,
+#endif
+#if PACKETVER >= 20040311
+/*20040311 to latest
+/notrade : 거래신청을 자동으로 거절합니다 On Off
+/notrade: Declines trade offers automatically. On | Off
+*/
+ MSG_EXPLAIN_NOTRADE = 0x324,
+/*20040311 to 20040804
+거래신청을 자동으로 거절합니다 [/nt ON]
+20040809 to latest
+거래신청과 친구등록요청을 자동으로 거절합니다 [/nt ON]
+Auto decline trade offers has been Enabled. [/nt ON]
+*/
+ MSG_NOTRADE_ON = 0x325,
+/*20040311 to 20040804
+거래신청을 정상적으로 받습니다 [/nt OFF]
+20040809 to latest
+거래신청과 친구등록요청을 정상적으로 받습니다 [/nt OFF]
+Auto decline trade offers has been Disabled. [/nt OFF]
+*/
+ MSG_NOTRADE_OFF = 0x326,
+#endif
+#if PACKETVER >= 20040329
+/*20040329 to latest
+같은 아이템은 한번에 30000개 이상은 살수 없습니다.
+You cannot buy more than 30,000ea items at once.
+*/
+ MSG_LIMIT_BUY_ITEM = 0x327,
+/*20040329 to latest
+재료가 충분하지 않습니다.
+You do not have enough ingredients.
+*/
+ MSG_NOT_ENOUGH_SOURCE = 0x328,
+#endif
+#if PACKETVER >= 20040419
+/*20040419 to latest
+%s에 계정정보가 남아있습니다.
+Login information remains at %s.
+*/
+ MSG_ALREADY_CONNECT = 0x329,
+#endif
+#if PACKETVER >= 20040423
+/*20040423 to 20040429
+해킹조사에 관련되어 %s 까지 로그인을 금지하고 있습니다.
+20040503 to 20040906
+해킹 관련 조사를 위해 로그인이 금지되 었습니다. 자세한 문의는 해킹관련 메일로 하여주시기 바랍니다.
+20040913 to latest
+계정도용 조사를 위해 로그인이 금지되었습니다. 자세한 문의는 계정도용 관련 문의 메일로 해주시기 바랍니다.
+Account has been locked for a hacking investigation. Please contact the GM Team for more information.
+*/
+ MSG_HACKING_INVESTIGATION = 0x32a,
+/*20040423 to 20040429
+버그조사에 관련되어 %s 까지 로그인을 금지하고 있습니다.
+20040503 to latest
+귀하는 버그관련 조사중이므로 일시적으로 접속을 금합니다
+This account has been temporarily prohibited from login due to a bug-related investigation.
+*/
+ MSG_BUG_INVESTIGATION = 0x32b,
+/*20040423 to latest
+수리가능한 아이템
+Repairable items
+*/
+ MSG_REPAIRITEMLIST = 0x32c,
+#endif
+#if PACKETVER >= 20040426
+/*20040426 to latest
+아이템 수리 성공
+Item has been successfully repaired.
+*/
+ MSG_ITEM_REPAIR_SUCCEESS = 0x32d,
+/*20040426 to latest
+아이템 수리 실패 (재료 또는 상대와의 거리등을 확인해주십시요)
+You have failed to repair this item. Please check the distance between you and opponent.
+*/
+ MSG_ITEM_REPAIR_FAIL = 0x32e,
+#endif
+#if PACKETVER >= 20040531
+/*20040531 to latest
+시스템 상황을 지속적으로 체크 합니다.[운영자모드] [/sc ON]
+System process enabled [GM mode] [/sc ON]
+*/
+ MSG_SYSTEM_CHECK_ON = 0x32f,
+/*20040531 to latest
+시스템 상황을 지속적으로 체크 하지 않습니다.[운영자모드] [/sc OFF]
+System process disabled [GM mode] [/sc OFF]
+*/
+ MSG_SYSTEM_CHECK_OFF = 0x330,
+/*20040531 to latest
+/systemcheck : 시스템 상황을 지속적으로 체크 합니다.[운영자모드]
+/systemcheck: Check the system process [GM mode] On | Off
+*/
+ MSG_EXPLAIN_SYSTEM_CHECK = 0x331,
+#endif
+#if PACKETVER >= 20040614
+/*20040614 to latest
+(%s)님이 친구 신청을 하셨습니다. 친구가 되시겠습니까?
+(%s) wishes to be friends with you. Would you like to accept?
+*/
+ MSG_SUGGEST_JOIN_FRIEND = 0x332,
+#endif
+#if PACKETVER >= 20040621
+/*20040621 to latest
+더 이상 친구 등록을 하실수 없습니다.
+Your Friend List is full.
+*/
+ MSG_FRIEND_ADD_ME_OVERSIZE = 0x333,
+/*20040621 to latest
+(%s)님이 더 이상 친구 등록을 하실수 없습니다.
+(%s)'s Friend List is full.
+*/
+ MSG_FRIEND_ADD_OTHER_OVERSIZE = 0x334,
+/*20040621 to latest
+(%s)님과 친구가 되셨습니다.
+You have become friends with (%s).
+*/
+ MSG_FRIEND_ADD_SUCCEED = 0x335,
+/*20040621 to latest
+(%s)님이 친구 되기를 원하지 않습니다.
+(%s) does not want to be friends with you.
+*/
+ MSG_FRIEND_ADD_FALSE = 0x336,
+/*20040621 to latest
+이 캐릭터는 %s 까지 블럭되어있습니다.
+This character will be blocked to use until %s.
+*/
+ MSG_BLOCKED = 0x337,
+/*20040621 to 20040621
+천만제니이상을 입력하신 아이템은 천만제니로 판매됩니다.
+20040628 to latest
+천만제니 이상 입력하셔도 가격은 천만제니로 판매됩니다.
+Price will be fixed at 10,000,000 zeny, even if you enter higher price.
+*/
+ MSG_OVERPRICE = 0x338,
+#endif
+#if PACKETVER >= 20040628
+/*20040628 to latest
+(적음)
+(Very low)
+*/
+ MSG_LITTLEUSER = 0x339,
+/*20040628 to latest
+(약간 적음)
+(Low)
+*/
+ MSG_ALITTLEUSER = 0x33a,
+/*20040628 to latest
+(보통)
+(Normal)
+*/
+ MSG_NORMLEUSER = 0x33b,
+/*20040628 to latest
+(많음)
+(High)
+*/
+ MSG_MANYUSER = 0x33c,
+/*20040628 to latest
+(매우 많음)
+(Very high)
+*/
+ MSG_VERYMANYUSER = 0x33d,
+/*20040628 to 20040713
+비매너에 의해 GM으로부터 채팅금지가 %d 분간 적용됩니다.
+20040726 to latest
+비매너에 의해 운영자로부터 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d minutes by the GM Team.
+*/
+ MSG_GM_BAD_MANNER_START = 0x33e,
+/*20040628 to latest
+GM에 의한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_REMAIN = 0x33f,
+/*20040628 to latest
+GM에 의한 채팅금지가 해지 되었습니다.
+You have been released from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_END = 0x340,
+/*20040628 to 20040713
+도배 방지 시스템으로 인한 채팅금지가 %d 분간 적용됩니다.
+20040726 to latest
+도배 방지 시스템으로 인한 자동 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d as an automatic penalty.
+*/
+ MSG_AUTO_BAD_MANNER_START = 0x341,
+/*20040628 to latest
+도배 방지 시스템으로 인한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from auto penalty.
+*/
+ MSG_AUTO_BAD_MANNER_REMAIN = 0x342,
+/*20040628 to latest
+도배 방지 시스템으로 인한 채팅금지가 해지되었습니다. 게임진행 시에는 도배에 대해서 주의하여 주시기 바랍니다.
+You have been released from the auto penalty. Please refrain from spamming in-game.
+*/
+ MSG_AUTO_BAD_MANNER_END = 0x343,
+#endif
+#if PACKETVER >= 20040705
+/*20040705 to latest
+%s님과 %s님이 이혼하셨습니다.
+%s and %s have divorced from each other.
+*/
+ MSG_DIVORCE = 0x344,
+/*20040705 to 20041108
+星鬪士 %s의 태양의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Space.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 태양의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE1 = 0x345,
+/*20040705 to 20041108
+星鬪士 %s의 달의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Space.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 달의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE2 = 0x346,
+/*20040705 to 20041108
+星鬪士 %s의 별의 장소로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Space.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 별의 장소로 %s 가 지정됐습니다.
+*/
+ MSG_STARPLACE3 = 0x347,
+/*20040705 to 20040726
+星鬪士 %s의 태양의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 태양의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 장소는 %s 입니다
+Gravity %s's Solar Space: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 태양의 장소는 %s 입니다
+*/
+ MSG_STARPLACE4 = 0x348,
+/*20040705 to 20040726
+星鬪士 %s의 달의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 달의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 장소는 %s 입니다
+Gravity %s's Luna Space: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 달의 장소는 %s 입니다
+*/
+ MSG_STARPLACE5 = 0x349,
+/*20040705 to 20040726
+星鬪士 %s의 별의 장소 : %s
+20040804 to 20041108
+星鬪士 %s의 별의 장소는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 장소는 %s 입니다
+Gravity %s's Stellar Space: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 별의 장소는 %s 입니다
+*/
+ MSG_STARPLACE6 = 0x34a,
+#endif
+#if PACKETVER >= 20040707
+/*20040707 to 20041108
+星鬪士 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Monster.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER1 = 0x34b,
+/*20040707 to 20041108
+星鬪士 %s의 달의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 달의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Monster.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 달의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER2 = 0x34c,
+/*20040707 to 20041108
+星鬪士 %s의 별의 몬스터로 %s 가 지정됐습니다.
+20041115 to latest
+拳聖 %s의 별의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Monster.
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 별의 몬스터로 %s 가 지정됐습니다.
+*/
+ MSG_STARMONSTER3 = 0x34d,
+/*20040707 to 20040726
+星鬪士 %s의 태양의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 태양의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 태양의 몬스터는 %s 입니다
+Gravity %s's Solar Monster: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 태양의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER4 = 0x34e,
+/*20040707 to 20040726
+星鬪士 %s의 달의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 달의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 달의 몬스터는 %s 입니다
+Gravity %s's Luna Monster: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 달의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER5 = 0x34f,
+/*20040707 to 20040726
+星鬪士 %s의 별의 몬스터 : %s
+20040804 to 20041108
+星鬪士 %s의 별의 몬스터는 %s 입니다
+20041115 to latest
+拳聖 %s의 별의 몬스터는 %s 입니다
+Gravity %s's Stellar Monster: %s
+20041220 to 20050817
+태양과 달과 별의 전사 %s의 별의 몬스터는 %s 입니다
+*/
+ MSG_STARMONSTER6 = 0x350,
+/*20040707 to latest
+/window : 창 위치 이동시 다른 창과 달라붙는 속성이 들어갑니다 On Off
+/window: Display windows will snap/dock together. On | Off
+*/
+ MSG_EXPLAIN_WINDOW = 0x351,
+/*20040707 to latest
+창 위치 이동시 다른 창과 잘 붙습니다 [/wi ON]
+Display window docking enabled. [/wi ON]
+*/
+ MSG_WINDOW_ON = 0x352,
+/*20040707 to latest
+창 위치 이동시 다른 창과 붙으려는 속성을 가지지 않습니다 [/wi OFF]
+Display window docking disabled. [/wi OFF]
+*/
+ MSG_WINDOW_OFF = 0x353,
+#endif
+#if PACKETVER >= 20040713
+/*20040713 to latest
+/pvpinfo : 자신의 PVP 승패와 PVP 포인트를 알 수 있습니다.
+/pvpinfo: shows your PVP result and PVP points.
+*/
+ MSG_EXPLAIN_PVP_INFO = 0x354,
+/*20040713 to latest
+현재 %d승, %d패, PVP포인트는 %d입니다.
+You have won %d times and have lost %d times in PVP. Current points %d.
+*/
+ MSG_PVP_INFO = 0x355,
+#endif
+#if PACKETVER >= 20040726
+/*20040726 to latest
+매너 포인트를 성공적으로 보냈습니다.
+A manner point has been successfully aligned.
+*/
+ MSG_SEND_MANNER_POINT = 0x356,
+#endif
+#if PACKETVER >= 20040809
+/*20040809 to latest
+현재 이곳은 PK 가능 지역입니다. 불의의 공격에 유의 하시기 바랍니다.
+You are in a PK area. Please beware of sudden attack.
+*/
+ MSG_PKZONE = 0x357,
+#endif
+#if PACKETVER >= 20040817
+/*20040817 to latest
+게임가드 업데이트가 바이러스나 스파이웨어와의 충돌로 실패했습니다. 백신 프로그램/스파이웨어 제거 프로그램을 사용한 후 접속해 주십시기 바랍니다
+Game Guard update has been failed when either Virus or Spyware conflicted with. Please, Uninstall Spyware and Virus protection program before you log in.
+*/
+ MSG_NPGAMEMON_ERROR_100ERROR = 0x358,
+#endif
+#if PACKETVER >= 20040823
+/*20040823 to latest
+윈도우 호환성 문제로 프로그램을 종료합니다. 게임을 다시 실행해 주시기 바랍니다
+Program has encountered an error related to Windows compatibility. Please start the game again.
+*/
+ MSG_NPGAMEMON_XP_COMPATIBILITY = 0x359,
+#endif
+#if PACKETVER >= 20040906
+/*20040906 to latest
+채팅, 스킬, 아이템을 사용할수없게 되었습니다.
+You have been blocked from chatting, using skills and items.
+*/
+ MSG_PK_HONOR = 0x35a,
+/*20040906 to latest
+캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while this character is being deleted.
+*/
+ MSG_DELETING_CHAR = 0x35b,
+/*20040906 to latest
+결혼 상대자의 캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while your spouse character is being deleted.
+*/
+ MSG_DELETING_SPOUSE_CHAR = 0x35c,
+#endif
+#if PACKETVER >= 20040913
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE = 0x35d,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN = 0x35e,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN = 0x35f,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER = 0x360,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE = 0x361,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT = 0x362,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF = 0x363,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT = 0x364,
+/*20040913 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST = 0x365,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD = 0x366,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH = 0x367,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER = 0x368,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN = 0x369,
+/*20040913 to latest
+Novice
+*/
+ MSG_NOVICE_W = 0x36a,
+/*20040913 to latest
+Swordman
+*/
+ MSG_SWORDMAN_W = 0x36b,
+/*20040913 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN_W = 0x36c,
+/*20040913 to latest
+Archer
+*/
+ MSG_ARCHER_W = 0x36d,
+/*20040913 to latest
+Acolyte
+*/
+ MSG_ACOLYTE_W = 0x36e,
+/*20040913 to latest
+Merchant
+*/
+ MSG_MERCHANT_W = 0x36f,
+/*20040913 to latest
+Thief
+*/
+ MSG_THIEF_W = 0x370,
+/*20040913 to latest
+Knight
+*/
+ MSG_KNIGHT_W = 0x371,
+/*20040913 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST_W = 0x372,
+/*20040913 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD_W = 0x373,
+/*20040913 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH_W = 0x374,
+/*20040913 to latest
+Hunter
+*/
+ MSG_HUNTER_W = 0x375,
+/*20040913 to latest
+Assassin
+*/
+ MSG_ASSASSIN_W = 0x376,
+#endif
+#if PACKETVER >= 20041018
+/*20041018 to latest
+(%s)님을 아이로 입양신청
+Send an adoption request to %s
+*/
+ MSG_REQ_JOIN_BABY = 0x377,
+/*20041018 to 20041025
+아이가 되시면 전승을 하실수 없게 됩니다. 그래도 괜찮습니까?
+20041101 to latest
+아이가 되면 전승을 할수없고 스텟은 80이상 올릴수없게되며 HP와 SP가 줄어듭니다. 그래도 괜찮습니까?
+When you become a child, you will be unable to become a Transcendent Class character, all stats will be limited to a maximum of 80, and Max HP/SP will be reduced. Are you sure that you want to be adopted?
+*/
+ MSG_SUGGEST_BABY2 = 0x378,
+#endif
+#if PACKETVER >= 20041101
+/*20041101 to latest
+모든 나쁜 상태이상이 제거 되었습니다.
+All abnormal status effects have been removed.
+*/
+ MSG_GOSPEL1 = 0x379,
+/*20041101 to latest
+1분간 모든 상태이상에 대해 면역이 됩니다.
+You will be immune to abnormal status effects for the next minute.
+*/
+ MSG_GOSPEL2 = 0x37a,
+/*20041101 to latest
+1분간 최대 생명력이 크게 늘어납니다.
+Your Max HP will stay increased for the next minute.
+*/
+ MSG_GOSPEL3 = 0x37b,
+/*20041101 to latest
+1분간 최대 마법력이 크게 늘어납니다.
+Your Max SP will stay increased for the next minute.
+*/
+ MSG_GOSPEL4 = 0x37c,
+/*20041101 to latest
+1분간 모든 능력이 크게 상승합니다.
+All of your Stats will stay increased for the next minute.
+*/
+ MSG_GOSPEL5 = 0x37d,
+/*20041101 to latest
+1분간 사용하는 무기에 성스러운 속성이 부여됩니다.
+Your weapon will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL6 = 0x37e,
+/*20041101 to latest
+1분간 사용하는 갑옷에 성스러운 속성이 부여됩니다.
+Your armor will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL7 = 0x37f,
+/*20041101 to latest
+10초간 방어력이 크게 상승합니다.
+Your Defense will stay increased for the next 10 seconds.
+*/
+ MSG_GOSPEL8 = 0x380,
+/*20041101 to latest
+1분간 공격력이 크게 증가합니다.
+Your Attack strength will be increased for the next minute.
+*/
+ MSG_GOSPEL9 = 0x381,
+/*20041101 to latest
+1분간 명중률과 회피율이 크게 상승합니다.
+Your Accuracy and Flee Rate will be increased for the next minute.
+*/
+ MSG_GOSPEL10 = 0x382,
+#endif
+#if PACKETVER >= 20041108
+/*20041108 to latest
+아이를 한번 입양했던 부부는 추가 입양이 불가능합니다.
+You cannot adopt more than 1 child.
+*/
+ MSG_BABY1 = 0x383,
+/*20041108 to latest
+부부가 둘다 레벨70이 넘어야 아이를 입양할수있습니다.
+You must be at least character level 70 in order to adopt someone.
+*/
+ MSG_BABY2 = 0x384,
+/*20041108 to 20041108
+블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Blacksmith rank points. Your point total is %d.
+*/
+ MSG_BLACKSMITH_POINT = 0x385,
+/*20041108 to 20041108
+알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+20041115 to latest
+[POINT] 알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Alchemist rank points. Your point total is %d.
+*/
+ MSG_ALCHEMIST_POINT = 0x386,
+#endif
+#if PACKETVER >= 20041115
+/*20041115 to 20041130
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE11 = 0x387,
+/*20041115 to 20041130
+슈퍼노비스
+Super Novice
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE12 = 0x388,
+/*20041115 to 20041130
+예요~
+Super Novice~
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE13 = 0x389,
+/*20041115 to 20041130
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+20041206 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE14 = 0x38a,
+/*20041115 to latest
+/notalkmsg2 : 채팅내용을 채팅창에 표시하지 않습니다 (길드말 포함) On Off
+/notalkmsg2: Hides chat messages(including guild chat). On Off
+*/
+ MSG_EXPLAIN_NOTALKMSG2 = 0x38b,
+/*20041115 to latest
+채팅내용을 채팅창에 표시합니다 [/nm2 ON]
+Show chat messages. [/nm2 ON]
+*/
+ MSG_NOTALKMSG2_ON = 0x38c,
+/*20041115 to latest
+채팅내용을 채팅창에 표시하지않습니다 (길드말 포함) [/nm2 OFF]
+Hide chat messages(including guild chat) [/nm2 OFF]
+*/
+ MSG_NOTALKMSG2_OFF = 0x38d,
+#endif
+#if PACKETVER >= 20041129
+/*20041129 to latest
+제련가능한 아이템
+Upgradable Weapons
+*/
+ MSG_REFINEITEMLIST = 0x38e,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_SUCCEESS = 0x38f,
+/*20041129 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_FAIL = 0x390,
+/*20041129 to latest
+무기제련스킬의 레벨이 부족해서 %s 제련을 할수없습니다.
+You cannot upgrade %s until you level up your Upgrade Weapon skill.
+*/
+ MSG_ITEM_REFINE_FAIL_LEVEL = 0x391,
+/*20041129 to latest
+제련에 필요한 아이템 (%s) 이 없으므로 제련할수없습니다.
+You lack a necessary item %s to upgrade this weapon.
+*/
+ MSG_ITEM_REFINE_FAIL_MATERIAL = 0x392,
+#endif
+#if PACKETVER >= 20041206
+/*20041206 to latest
+완벽하게 코팅되어있어서 풀스트립이 통하지 않습니다.
+Full Divestment cannot pierce the target. The target is fully shielded.
+*/
+ MSG_FULLSTRIP = 0x393,
+#endif
+#if PACKETVER >= 20041213
+/*20041213 to latest
+결혼한 캐릭터는 입양시킬수 없습니다.
+You cannot adopt a married person.
+*/
+ MSG_BABY3 = 0x394,
+#endif
+#if PACKETVER >= 20041220
+/*20041220 to latest
+친구로 등록된 이름과 비슷하지만 등록된 이름이 아닙니다. 아는사람인지 확인하십시요.
+This name is not registered in your Friend List. Please check the name again.
+*/
+ MSG_ID_WARNING = 0x395,
+/*20041220 to latest
+/hi 또는 /hi 문장 : 친구로 등록된 캐릭터들에게 인사를 합니다.
+/hi or /hi message: Send greetings to people who are online and registered on your Friend List.
+*/
+ MSG_EXPLAIN_HI = 0x396,
+#endif
+#if PACKETVER >= 20041227
+/*20041227 to latest
+길드원의 이름과 비슷하지만 길드원이 아닙니다. 길드원인지 확인하십시요.
+This character is not your guildsman. Please check the name again.
+*/
+ MSG_ID_WARNING_GUILD = 0x397,
+#endif
+#if PACKETVER >= 20050117
+/*20050117 to latest
+9999만제니 이상 입력하셔도 가격은 9999만제니로 판매됩니다.
+Please be aware that the maximum selling price is fixed as 2 Billion. You cannot sell an item higher than that.
+*/
+ MSG_OVERPRICE9999 = 0x398,
+#endif
+#if PACKETVER >= 20050131
+/*20050131 to latest
+친구의 귓속말은 [ Friend ] , 길드원은 [ Member ] 로 표시됩니다.
+Whispers from friends are displayed as [ Friend ], and ones from guildsmen are displayed as [ Member ].
+*/
+ MSG_EXPLAIN_SACHING1 = 0x399,
+/*20050131 to latest
+( From 캐릭터이름 : ) 이라고 표시 되는 귓속말은 친구나 길드원이 아닙니다.
+( From character name: ) is from an anonymous character who is neither your friend nor guildsman.
+*/
+ MSG_EXPLAIN_SACHING2 = 0x39a,
+#endif
+#if PACKETVER >= 20050214
+/*20050214 to 20050310
+블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/blacksmith : 블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+/blacksmith: Shows top 10 Blacksmiths in the server.
+*/
+ MSG_EXPLAIN_BLACKSMITH = 0x39b,
+/*20050214 to 20050310
+알케미스트의 상위 10위권 랭킹을 보여줍니다.
+20050314 to latest
+/alchemist : 알케미스트의 상위 10위권 랭킹을 보여줍니다.
+/alchemist: Shows top 10 Alchemists in the server.
+*/
+ MSG_EXPLAIN_ALCHEMIST = 0x39c,
+/*20050214 to latest
+ALT+Y : 여러가지 명령어를 쉽게 쓸수있는 윈도우가 열립니다.
+ALT+Y: Opens a window which allows you to use various commands with ease.
+*/
+ MSG_EXPLAIN_ALTY = 0x39d,
+#endif
+#if PACKETVER >= 20050328
+/*20050328 to latest
+[POINT] 태권미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Tae-Kwon Mission rank points. Your point total is %d.
+*/
+ MSG_TAEKWON_POINT = 0x39e,
+#endif
+#if PACKETVER >= 20050404
+/*20050404 to latest
+[태권미션] Target Monster : %s (%d%%)
+[Taekwon Mission] Target Monster: %s (%d%%)
+*/
+ MSG_TAEKWON_MISSION = 0x39f,
+#endif
+#if PACKETVER >= 20050502
+/*20050502 to latest
+게임가드 초기화 에러 : %lu
+Error - Failed to initialize GameGuard: %lu
+*/
+ MSG_INIT_ERROR = 0x3a0,
+/*20050502 to latest
+스피드핵이 감지되었습니다.
+Speed Hack has been detected.
+*/
+ MSG_SPEEDHACK_DETECT = 0x3a1,
+/*20050502 to latest
+불법 프로그램 (%s) 가 발견되었습니다
+The illegal program, (%s) has been detected.
+*/
+ MSG_GAMEHACK_DETECT = 0x3a2,
+/*20050502 to latest
+게임이나 게임가드가 변조되었습니다.
+The Game or Gameguard has been cracked.
+*/
+ MSG_GAMEHACK_DOUBT = 0x3a3,
+/*20050502 to latest
+게임가드가 실행 중 입니다. 잠시 후에 다시 실행해보시기 바랍니다.
+GameGuard is currently running. Please wait for sometime and restart the game.
+*/
+ MSG_ERROR_EXIST = 0x3a4,
+/*20050502 to latest
+게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다.
+The Game or GameGuard is already running. Please close the game and restart the game.
+*/
+ MSG_GAME_EXIST = 0x3a5,
+/*20050502 to latest
+게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다.
+Failed to intialize GameGuard. Please try again after rebooting the system or closing other programs.
+*/
+ MSG_ERROR_INIT = 0x3a6,
+/*20050502 to latest
+바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다.
+Failed to load the scan module of virus and hacking tool. It's caused by lack of memory or PC virus infection.
+*/
+ MSG_ERROR_NPSCAN = 0x3a7,
+#endif
+#if PACKETVER >= 20050509
+/*20050509 to latest
+호문클루스 정보
+Homunculus Info
+*/
+ MSG_HOMUN_INFO = 0x3a8,
+#endif
+#if PACKETVER >= 20050511
+/*20050511 to latest
+호문클루스 스킬목록
+Homunculus Skill List
+*/
+ MSG_HOMUN_SKILLLIST = 0x3a9,
+#endif
+#if PACKETVER >= 20050523
+/*20050523 to latest
+호문클루스의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Please give your Homunculus a name no longer than 23 letters.
+*/
+ MSG_HOMUN_NAME_IN23 = 0x3aa,
+/*20050523 to latest
+이름은 단 한번만 바꿀수 있습니다. 호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You can name a Homunculus only once. You have entered the name, ^0000ff%s^000000. Would you like to continue?
+*/
+ MSG_HOMUN_NAME_CHANGE_ONLYONCE = 0x3ab,
+/*20050523 to latest
+지금은 부재중~
+(Away)
+*/
+ MSG_AUTO_MSG = 0x3ac,
+/*20050523 to latest
+[자동응답]
+[Automated Message]
+*/
+ MSG_AUTO_MSG2 = 0x3ad,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답합니다.
+Send an automated message while you are away.
+*/
+ MSG_AUTO_MSG_ON = 0x3ae,
+/*20050523 to latest
+부재시 타인의 귓말에 자동응답하지 않습니다.
+Cancel automated away message.
+*/
+ MSG_AUTO_MSG_OFF = 0x3af,
+/*20050523 to latest
+자동 응답 메시지를 입력하세요.
+Please enter Away Message.
+*/
+ MSG_ENTER_AUTO_MSG = 0x3b0,
+#endif
+#if PACKETVER >= 20050530
+/*20050530 to latest
+/번쩍
+/fsh
+*/
+ MSG_EMOTION_SPARK = 0x3b1,
+/*20050530 to latest
+/빙빙
+/spin
+*/
+ MSG_EMOTION_CONFUSE = 0x3b2,
+/*20050530 to latest
+/하아
+/sigh
+*/
+ MSG_EMOTION_OHNO = 0x3b3,
+/*20050530 to latest
+/덤덤
+/dum
+*/
+ MSG_EMOTION_HUM = 0x3b4,
+/*20050530 to latest
+/시끌
+/crwd
+*/
+ MSG_EMOTION_BLABLA = 0x3b5,
+/*20050530 to latest
+/좌절
+/desp
+*/
+ MSG_EMOTION_OTL = 0x3b6,
+/*20050530 to latest
+/주사위
+/dice
+*/
+ MSG_EMOTION_DICE = 0x3b7,
+/*20050530 to latest
+/pk : 학살자의 상위 10위권 랭킹을 보여줍니다.
+/pk: Shows top 10 Slayers in the server.
+*/
+ MSG_EXPLAIN_KILLER_RANK = 0x3b8,
+/*20050530 to latest
+[POINT] 학살자 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Slayer rank points. Your point total is %d.
+*/
+ MSG_KILLER_POINT = 0x3b9,
+#endif
+#if PACKETVER >= 20050608
+/*20050608 to latest
+진화 가능
+Evolution Available
+*/
+ MSG_HOMUN_EVOLVE = 0x3ba,
+/*20050608 to latest
+^ff0000^ff0000호문클루스를 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+You have decided to delete this Homunculus ^ff0000^ff0000. When deleted, the homunculus and its history will be deleted and they cannot be restored in the future. Would you like to continue?
+*/
+ MSG_DELETE_HOMUN = 0x3bb,
+#endif
+#if PACKETVER >= 20050613
+/*20050613 to latest
+호문의 상태를 파일에 저장합니다.
+Save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_ON = 0x3bc,
+/*20050613 to latest
+호문의 상태를 파일에 저장하지 않습니다.
+Do not save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_OFF = 0x3bd,
+/*20050613 to latest
+Crusader
+*/
+ MSG_CRUSADER = 0x3be,
+/*20050613 to latest
+Monk
+*/
+ MSG_MONK = 0x3bf,
+/*20050613 to latest
+Sage
+*/
+ MSG_SAGE = 0x3c0,
+/*20050613 to latest
+Rouge
+Rogue
+*/
+ MSG_ROGUE = 0x3c1,
+/*20050613 to latest
+Alchemist
+*/
+ MSG_ALCHEMIST = 0x3c2,
+/*20050613 to latest
+Bard
+*/
+ MSG_BARD = 0x3c3,
+/*20050613 to latest
+Crusader_W
+Crusader
+*/
+ MSG_CRUSADER_W = 0x3c4,
+/*20050613 to latest
+Monk_W
+Monk
+*/
+ MSG_MONK_W = 0x3c5,
+/*20050613 to latest
+Sage_W
+Sage
+*/
+ MSG_SAGE_W = 0x3c6,
+/*20050613 to latest
+Rouge_W
+Rogue
+*/
+ MSG_ROGUE_W = 0x3c7,
+/*20050613 to latest
+Alchemist_W
+Alchemist
+*/
+ MSG_ALCHEMIST_W = 0x3c8,
+/*20050613 to latest
+Dancer
+*/
+ MSG_DANCER = 0x3c9,
+/*20050613 to latest
+Novice High
+High Novice
+*/
+ MSG_NOVICE_H = 0x3ca,
+/*20050613 to latest
+Swordman High
+High Swordman
+*/
+ MSG_SWORDMAN_H = 0x3cb,
+/*20050613 to latest
+Magician High
+High Mage
+*/
+ MSG_MAGICIAN_H = 0x3cc,
+/*20050613 to latest
+Archer High
+High Archer
+*/
+ MSG_ARCHER_H = 0x3cd,
+/*20050613 to latest
+Acolyte High
+High Acolyte
+*/
+ MSG_ACOLYTE_H = 0x3ce,
+/*20050613 to latest
+Merchant High
+High Merchant
+*/
+ MSG_MERCHANT_H = 0x3cf,
+/*20050613 to latest
+Thief High
+High Thief
+*/
+ MSG_THIEF_H = 0x3d0,
+/*20050613 to latest
+Novice High_W
+High Novice
+*/
+ MSG_NOVICE_H_W = 0x3d1,
+/*20050613 to latest
+Swordman High_W
+High Swordman
+*/
+ MSG_SWORDMAN_H_W = 0x3d2,
+/*20050613 to latest
+Magician High_W
+High Mage
+*/
+ MSG_MAGICIAN_H_W = 0x3d3,
+/*20050613 to latest
+Archer High_W
+High Archer
+*/
+ MSG_ARCHER_H_W = 0x3d4,
+/*20050613 to latest
+Acolyte High_W
+High Acolyte
+*/
+ MSG_ACOLYTE_H_W = 0x3d5,
+/*20050613 to latest
+Merchant High_W
+High Merchant
+*/
+ MSG_MERCHANT_H_W = 0x3d6,
+/*20050613 to latest
+Thief High_W
+High Thief
+*/
+ MSG_THIEF_H_W = 0x3d7,
+/*20050613 to latest
+Lord Knight
+*/
+ MSG_KNIGHT_H = 0x3d8,
+/*20050613 to latest
+High Priest
+*/
+ MSG_PRIEST_H = 0x3d9,
+/*20050613 to latest
+High Wizard
+*/
+ MSG_WIZARD_H = 0x3da,
+/*20050613 to latest
+White Smith
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H = 0x3db,
+/*20050613 to latest
+Sniper
+*/
+ MSG_HUNTER_H = 0x3dc,
+/*20050613 to latest
+Saaassin Cross
+Assassin Cross
+*/
+ MSG_ASSASSIN_H = 0x3dd,
+/*20050613 to latest
+Lord Knight_W
+Lord Knight
+*/
+ MSG_KNIGHT_H_W = 0x3de,
+/*20050613 to latest
+High Priest_W
+High Priest
+*/
+ MSG_PRIEST_H_W = 0x3df,
+/*20050613 to latest
+High Wizard_W
+High Wizard
+*/
+ MSG_WIZARD_H_W = 0x3e0,
+/*20050613 to latest
+White Smith_W
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H_W = 0x3e1,
+/*20050613 to latest
+Sniper_W
+Sniper
+*/
+ MSG_HUNTER_H_W = 0x3e2,
+/*20050613 to latest
+Saaassin Cross_W
+Assassin Cross
+*/
+ MSG_ASSASSIN_H_W = 0x3e3,
+/*20050613 to latest
+Paladin
+*/
+ MSG_CRUSADER_H = 0x3e4,
+/*20050613 to latest
+Champion
+*/
+ MSG_MONK_H = 0x3e5,
+/*20050613 to latest
+Professor
+Scholar
+*/
+ MSG_SAGE_H = 0x3e6,
+/*20050613 to latest
+Stalker
+*/
+ MSG_ROGUE_H = 0x3e7,
+/*20050613 to latest
+Creator
+Biochemist
+*/
+ MSG_ALCHEMIST_H = 0x3e8,
+/*20050613 to latest
+Clown
+Minstrel
+*/
+ MSG_BARD_H = 0x3e9,
+/*20050613 to latest
+Paladin_W
+Paladin
+*/
+ MSG_CRUSADER_H_W = 0x3ea,
+/*20050613 to latest
+Champion_W
+Champion
+*/
+ MSG_MONK_H_W = 0x3eb,
+/*20050613 to latest
+Professor_W
+Professor
+*/
+ MSG_SAGE_H_W = 0x3ec,
+/*20050613 to latest
+Stalker_W
+Stalker
+*/
+ MSG_ROGUE_H_W = 0x3ed,
+/*20050613 to latest
+Creator_W
+Creator
+*/
+ MSG_ALCHEMIST_H_W = 0x3ee,
+/*20050613 to latest
+Gypsy
+*/
+ MSG_DANCER_H = 0x3ef,
+/*20050613 to latest
+비밀번호가 지정되어 있지 않습니다. 새로운 비밀번호를 지정하시겠습니까?
+You have not set a password yet. Would you like to create one now?
+*/
+ MSG_STORE_PASSWORD_REQ = 0x3f0,
+/*20050613 to latest
+비밀번호를 3회 틀려셨습니다. 나중에 다시 시도해 주세요.
+You have incorrectly entered the password 3 times. Please try again later.
+*/
+ MSG_STORE_PASSWORD_PENALTY = 0x3f1,
+/*20050613 to latest
+비밀번호 변경이 실패하였습니다.
+Password creation has failed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_NG = 0x3f2,
+/*20050613 to latest
+비밀번호는 4자리 이상 8자리이하여야만 합니다.
+Password must be 4~8 letters long.
+*/
+ MSG_STORE_PASSWORD_4_8 = 0x3f3,
+/*20050613 to latest
+비밀번호
+Password
+*/
+ MSG_STORE_PASSWORD = 0x3f4,
+/*20050613 to latest
+신규 비밀번호
+New Password
+*/
+ MSG_STORE_NEW_PASSWORD = 0x3f5,
+/*20050613 to latest
+확인 비밀번호
+Confirm Password
+*/
+ MSG_STORE_RENEW_PASSWORD = 0x3f6,
+/*20050613 to latest
+비밀번호 변경이 완료되었습니다.
+Password has been changed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_OK = 0x3f7,
+/*20050613 to latest
+비밀번호가 서로 다릅니다.
+Password does not match.
+*/
+ MSG_STORE_PASSWORD_MISMATCH = 0x3f8,
+/*20050613 to latest
+비밀번호 입력
+Enter Password
+*/
+ MSG_STORE_PASSWORD_INPUT = 0x3f9,
+#endif
+#if PACKETVER >= 20050624
+/*20050624 to 20050624
+호문이 아사 직전입니다!!! 밥좀 주셈~!!
+20050628 to latest
+호문이 아사 직전입니다! 먹이를 주지 않으면 가출하게됩니다.
+Your Homunculus is starving. Please feed it, otherwise it will leave you.
+*/
+ MSG_HOMUN_HUNGRY = 0x3fa,
+/*20050624 to latest
+경험치
+EXP
+*/
+ MSG_HOMUN_EXP = 0x3fb,
+#endif
+#if PACKETVER >= 20050628
+/*20050628 to latest
+[EVENT] 이벤트에 당첨되셨습니다. 게임내에서 아이템을 지급받으십시요.
+*/
+ MSG_EVENT_RESULT = 0x3fc,
+#endif
+#if PACKETVER >= 20050704
+/*20050704 to latest
+싫어함
+Hate
+*/
+ MSG_HATE = 0x3fd,
+/*20050704 to 20050704
+매우 싫어함
+20050711 to latest
+매우싫어함
+Hate with a Passion
+*/
+ MSG_VERYHATE = 0x3fe,
+#endif
+#if PACKETVER >= 20050718
+/*20050718 to latest
+호문클루스가 사용자 인공지능으로 동작합니다.
+Homunculus has been customized.
+*/
+ MSG_HOMUN_USERAI_ON = 0x3ff,
+/*20050718 to latest
+호문클루스가 기본 인공지능으로 동작합니다.
+Homunculus has been activated with the basic AI.
+*/
+ MSG_HOMUN_USERAI_OFF = 0x400,
+#endif
+#if PACKETVER >= 20050808
+/*20050808 to latest
+편지목록
+Mail List
+*/
+ MSG_MAIL_LIST = 0x401,
+/*20050808 to latest
+편지쓰기
+Write Mail
+*/
+ MSG_MAIL_WRITE = 0x402,
+/*20050808 to latest
+편지읽기
+Read Mail
+*/
+ MSG_MAIL_READ = 0x403,
+#endif
+#if PACKETVER >= 20050817
+/*20050817 to latest
+한번 지정하시면 변경이 불가능합니다! 이 맵으로 지정하시겠습니까?
+You cannot change a map's designation once it is designated. Are you sure that you want to designate this map?
+*/
+ MSG_STARPLACE_ACCEPT = 0x404,
+#endif
+#if PACKETVER >= 20050822
+/*20050822 to 20050822
+보내실 아이템이 추가 되었습니다.
+20050829 to 20051017
+아이템창에 아이템이 추가 되었습니다.
+20051024 to latest
+메일 아이템을 수령했습니다.
+Item has been added in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_SUCCESS = 0x405,
+/*20050822 to 20050822
+보내실 아이템이 추가 되지 않았습니다.
+20050829 to 20051017
+아이템창에 아이템이 추가 되지 않았습니다.
+20051024 to latest
+메일 아이템을 수령하지 못했습니다.
+You have failed to add the item in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_FAILURE = 0x406,
+/*20050822 to latest
+메일 보내기가 성공하였습니다.
+You have successfully mailed a message.
+*/
+ MSG_MAIL_SEND_SUCCESS = 0x407,
+/*20050822 to latest
+메일 보내기가 실패하였습니다. 받는 사람이 존재하지 않습니다.
+You have failed to mail a message. Recipient does not exist.
+*/
+ MSG_MAIL_USER_NOT_FOUND = 0x408,
+#endif
+#if PACKETVER >= 20050829
+/*20050829 to latest
+[태양과 달과 별의 천사] 지정했던 장소들과 몬스터들이 초기화됐습니다!
+[Solar, Lunar and Stellar Angel] Designated places and monsters have been reset.
+*/
+ MSG_STAR_ANGEL = 0x409,
+/*20050829 to latest
+경매 등록이 실패했습니다.
+The minimum starting bid for auctions is 10,000,000 zeny.
+*/
+ MSG_AUCTION_ADD_FALSE = 0x40a,
+/*20050829 to latest
+경매 등록이 성공했습니다.
+You have successfully started a new auction.
+*/
+ MSG_AUCTION_ADD_TRUE = 0x40b,
+/*20050829 to latest
+해당 경매가 취소되었습니다.
+The auction has been canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL = 0x40c,
+/*20050829 to latest
+입찰자가 있는 경매는 취소할 수 없습니다.
+An auction with at least one bidder cannot be canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL_FALSE = 0x40d,
+#endif
+#if PACKETVER >= 20050905
+/*20050905 to latest
+메일 삭제가 성공하였습니다.
+Mail has been successfully deleted.
+*/
+ MSG_MAIL_DELETE_SUCCESS = 0x40e,
+/*20050905 to latest
+메일 삭제가 실패하였습니다.
+You have failed to delete the mail.
+*/
+ MSG_MAIL_DELETE_FAILURE = 0x40f,
+#endif
+#if PACKETVER >= 20050912
+/*20050912 to latest
+던지는 단검이 장착되었습니다.
+You have equipped throwing daggers.
+*/
+ MSG_MSG_KNIFE_EQUIPMENT_SUCCESS = 0x410,
+#endif
+#if PACKETVER >= 20050926
+/*20050926 to latest
+%s 님이 로그인했습니다.
+%s has logged in.
+*/
+ MSG_LOGIN_FRIEND = 0x411,
+/*20050926 to latest
+%s 님이 로그아웃했습니다.
+%s has logged out.
+*/
+ MSG_LOGOUT_FRIEND = 0x412,
+#endif
+#if PACKETVER >= 20051004
+/*20051004 to latest
+/loginout : 길드원과 친구들의 접속관련 메세지를 보여줍니다. On Off
+/loginout: Shows guildsmen and friends online status. On Off
+*/
+ MSG_EXPLAIN_LOGINOUT = 0x413,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시합니다. [/li ON]
+Display online status of friends in Chat Window. [/li ON]
+*/
+ MSG_LOGINOUT_ON = 0x414,
+/*20051004 to latest
+친구들의 접속관련 메세지를 대화창에 표시하지않습니다. [/li OFF]
+Do not display online status of friends in Chat Window. [/li OFF]
+*/
+ MSG_LOGINOUT_OFF = 0x415,
+/*20051004 to latest
+이미 실행중입니다.
+It is already running.
+*/
+ MSG_SGP_CODE_ALREADY_RUNNING = 0x416,
+/*20051004 to latest
+매크로 사용이 감지되었습니다.
+Use of Macro program has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MACRO = 0x417,
+/*20051004 to latest
+스피드해킹이 감지되었습니다.
+Use of Speed hack has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_SPEEDHACK = 0x418,
+/*20051004 to latest
+API 후킹이 감지되었습니다.
+API Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_APIHOOK = 0x419,
+/*20051004 to latest
+메시지 후킹이 감지되었습니다.
+Message Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MSGHOOK = 0x41a,
+/*20051004 to latest
+모듈이 변조 또는 손상되었거나 버전이 일치하지 않습니다.
+Module has been modified or damaged or its version does not match.
+*/
+ MSG_SGP_CODE_NOT_EQUALENCRYPTEDDATA = 0x41b,
+#endif
+#if PACKETVER >= 20051010
+/*20051010 to latest
+(태국)귀하는 게임방 과금으로 로그인 하셨습니다.
+(Thailand) You have logged in game with PC cafe payment.
+*/
+ MSG_BILLING_PCB = 0x41c,
+#endif
+#if PACKETVER >= 20051017
+/*20051017 to latest
+이전
+Prev
+*/
+ MSG_PREV_PAGE = 0x41d,
+/*20051017 to latest
+다음
+Next
+*/
+ MSG_NEXT_PAGE = 0x41e,
+/*20051017 to latest
+경매
+Auction
+*/
+ MSG_AUCTION = 0x41f,
+/*20051017 to latest
+물품보기
+Product List
+*/
+ MSG_AUCTION_VIEW = 0x420,
+/*20051017 to latest
+등록하기
+Register
+*/
+ MSG_AUCTION_ADD = 0x421,
+/*20051017 to latest
+판매 진행상태
+Sale Status
+*/
+ MSG_AUCTION_SELL = 0x422,
+/*20051017 to latest
+구매 진행상태
+Purchase Status
+*/
+ MSG_AUCTION_BUY = 0x423,
+/*20051017 to latest
+아이템
+Item
+*/
+ MSG_ITEM2 = 0x424,
+/*20051017 to latest
+아이템명
+Name
+*/
+ MSG_ITEM_NAME2 = 0x425,
+/*20051017 to latest
+가격 / 즉시구입가격
+Current Bid / Max Bid
+*/
+ MSG_ITEM_PRICE = 0x426,
+/*20051017 to latest
+판매자
+Seller
+*/
+ MSG_SELLER = 0x427,
+/*20051017 to latest
+구매자
+Buyer
+*/
+ MSG_BUYER = 0x428,
+/*20051017 to latest
+종료시간
+End Time
+*/
+ MSG_FINISH_TIME = 0x429,
+/*20051017 to latest
+%m월 %d일 %H시
+%m %d %H
+*/
+ MSG_TIME_TYPE = 0x42a,
+/*20051017 to latest
+시간설정
+Time (Hr)
+*/
+ MSG_SET_TIME = 0x42b,
+/*20051017 to latest
+수수료
+Fee
+*/
+ MSG_CHARGE = 0x42c,
+/*20051017 to latest
+검색 된 아이템이 없습니다.
+*/
+ MSG_NOTHING_SEARCH_ITEM = 0x42d,
+/*20051017 to latest
+현재 판매중인 아이템이 없습니다.
+Your Sale List is empty.
+*/
+ MSG_NOTHING_SEARCH_SELL_ITEM = 0x42e,
+/*20051017 to latest
+현재 구매중인 아이템이 없습니다.
+Your Purchase List is empty.
+*/
+ MSG_NOTHING_SEARCH_BUY_ITEM = 0x42f,
+/*20051017 to latest
+경매정보가 정확하지 않습니다.
+Auction Information is incorrect or incomplete.
+*/
+ MSG_ERROR_AUCTION_ITEM_INFO = 0x430,
+/*20051017 to latest
+경매에 등록할 아이템 정보가 없습니다.
+You must drag and drop an item from your Inventory into the Register Window to begin a new auction.
+*/
+ MSG_NOTHING_AUCTION_ITEM_INFO = 0x431,
+/*20051017 to latest
+이미 등록된 경매입니다.
+The auction has already been registered.
+*/
+ MSG_ERROR_ADD_AUCTION = 0x432,
+/*20051017 to latest
+제시가격
+Starting Bid
+*/
+ MSG_PRICE = 0x433,
+/*20051017 to latest
+구입희망가격
+Current Bid
+*/
+ MSG_PRICE2 = 0x434,
+/*20051017 to latest
+즉시구입가격
+Buy Now Price
+*/
+ MSG_PRICE3 = 0x435,
+/*20051017 to latest
+현재소지제니
+Your Current Zeny
+*/
+ MSG_PRICE4 = 0x436,
+/*20051017 to latest
+현재최고가격
+Highest Bid
+*/
+ MSG_PRICE5 = 0x437,
+/*20051017 to latest
+이전입찰가격
+Previous Bid
+*/
+ MSG_PRICE6 = 0x438,
+/*20051017 to latest
+추가입찰가격
+Next Bid
+*/
+ MSG_PRICE7 = 0x439,
+/*20051017 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BUY_ACTION_ITEM = 0x43a,
+/*20051017 to latest
+이 가격에 판매하시겠습니까?
+Would you like to sell this item?
+*/
+ MSG_SELL_ACTION_ITEM = 0x43b,
+/*20051017 to latest
+입찰하기
+Place Bid
+*/
+ MSG_BUY_AUCTION = 0x43c,
+/*20051017 to latest
+즉시구매하기
+Buy Now
+*/
+ MSG_BUY_AUCTION2 = 0x43d,
+/*20051017 to latest
+경매종료하기
+End the Auction
+*/
+ MSG_BUY_AUCTION3 = 0x43e,
+/*20051017 to latest
+재입찰하기
+Place another Bid
+*/
+ MSG_FINISH_AUCTION = 0x43f,
+/*20051017 to latest
+해당 경매에 대한 입찰이 성공했습니다.
+You have placed a bid.
+*/
+ MSG_RESULT_BUY_TRUE = 0x440,
+/*20051017 to latest
+해당 경매에 대한 입찰이 실패했습니다.
+You have failed to place a bid.
+*/
+ MSG_RESULT_BUY_FALSE = 0x441,
+/*20051017 to latest
+제니가 충분하지 않습니다.
+You do not have enough zeny.
+*/
+ MSG_RESULT_BUY_FALSE_MONEY = 0x442,
+#endif
+#if PACKETVER >= 20051024
+/*20051024 to latest
+방어구
+Armors
+*/
+ MSG_EQUIP = 0x443,
+/*20051024 to latest
+카드
+Card
+*/
+ MSG_CARD = 0x444,
+/*20051024 to latest
+기타
+Other
+*/
+ MSG_ETC = 0x445,
+/*20051024 to latest
+경매번호
+Bid
+*/
+ MSG_AUCTION_NUM = 0x446,
+/*20051024 to latest
+검색
+Search
+*/
+ MSG_AUCTION_SEARCH = 0x447,
+/*20051024 to latest
+해당 경매를 종료했습니다.
+You have ended the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_TRUE = 0x448,
+/*20051024 to latest
+해당 경매를 종료 할 수 없습니다.
+You cannot end the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_FALSE = 0x449,
+/*20051024 to latest
+경매 번호가 정확하지 않습니다.
+Bid Number is incorrect.
+*/
+ MSG_RESULT_AUCTION_ID_FALSE = 0x44a,
+/*20051024 to latest
+받는이
+To
+*/
+ MSG_SENDER = 0x44b,
+#endif
+#if PACKETVER >= 20051205
+/*20051205 to latest
+제 목
+Title
+*/
+ MSG_TITLE2 = 0x44c,
+/*20051205 to latest
+새 메일이 도착하였습니다.
+You have received a message in the mail.
+*/
+ MSG_NEW_MAIL = 0x44d,
+/*20051205 to latest
+검색중입니다.
+Searching...
+*/
+ MSG_SEARCHING_ITEM = 0x44e,
+/*20051205 to latest
+더 이상 경매 등록할 수 없습니다. 경매 등록은 최대 5개까지 가능합니다.
+You cannot register more than 5 items in an auction at a time.
+*/
+ MSG_AUCTION_ADD_OVER = 0x44f,
+/*20051205 to latest
+더 이상 경매 물품에 입찰할 수 없습니다. 경매 물품 입찰은 최대 5개까지 가능합니다.
+You cannot place more than 5 bids at a time.
+*/
+ MSG_RESULT_BUY_OVER = 0x450,
+/*20051205 to latest
+삭제하려는 메일에 수령하지 않은 아이템이 있습니다.
+Please accept all items from your mail before deleting.
+*/
+ MSG_MAIL_DELETE_ERROR = 0x451,
+/*20051205 to latest
+메일 제목을 입력하여 주십시오.
+Please enter a title.
+*/
+ MSG_MAIL_SEND_ERROR = 0x452,
+/*20051205 to latest
+/shopping : 클릭 한번으로 상점을 열고 상점이름 오른쪽 클릭으로 상점을 닫습니다 On Off
+/shopping: Enables you to open a shop with a single left-click and close your shop with a single right-click. On Off
+*/
+ MSG_EXPLAIN_SHOPPING = 0x453,
+/*20051205 to latest
+클릭 한번으로 상점을 열고 상점이름을 오른쪽 클릭해서 상점을 닫을수있습니다. [/sh ON]
+You can now open a shop with a single left-click and close your shop with a single right-click. [sh ON].
+*/
+ MSG_SHOPPING_ON = 0x454,
+/*20051205 to latest
+더블클릭 으로 상점을 열게됩니다. [/sh OFF]
+You can open a shop by double-clicking. [/sh OFF]
+*/
+ MSG_SHOPPING_OFF = 0x455,
+/*20051205 to latest
+메일을 보내려면, 제니 입력을 완료해야 합니다.
+Please enter zeny amount before sending mail.
+*/
+ MSG_MAIL_SEND_ERROR2 = 0x456,
+/*20051205 to latest
+경매 수수료가 부족합니다.
+You do not have enough zeny to pay the Auction Fee.
+*/
+ MSG_ADD_MONEY_FALSE = 0x457,
+/*20051205 to latest
+상태보기
+View Status
+*/
+ MSG_HOMUN_SHOWINFO = 0x458,
+/*20051205 to latest
+먹이주기
+Feed
+*/
+ MSG_HOMUN_FEEDING = 0x459,
+/*20051205 to latest
+대기
+Stand By
+*/
+ MSG_HOMUN_WAITING = 0x45a,
+/*20051205 to latest
+슈퍼노비스(남)
+Super Novice (Male)
+*/
+ MSG_JOB_SUPERNOVICE_M = 0x45b,
+/*20051205 to latest
+슈퍼노비스(여)
+Super Novice (Female)
+*/
+ MSG_JOB_SUPERNOVICE_F = 0x45c,
+/*20051205 to latest
+태권소년
+Taekwon Boy
+*/
+ MSG_JOB_TAEKWON_M = 0x45d,
+/*20051205 to latest
+태권소녀
+Taekwon Girl
+*/
+ MSG_JOB_TAEKWON_F = 0x45e,
+/*20051205 to latest
+권성(남)
+Taekwon Master (Male)
+*/
+ MSG_KWONSUNG_M = 0x45f,
+/*20051205 to latest
+권성(여)
+Taekwon Master (Female)
+*/
+ MSG_KWONSUNG_F = 0x460,
+/*20051205 to latest
+소울링커(남)
+Soul Linker (Male)
+*/
+ MSG_SOULLINGKER_M = 0x461,
+/*20051205 to latest
+소울링커(여)
+Soul Linker (Female)
+*/
+ MSG_SOULLINGKER_F = 0x462,
+/*20051205 to latest
+PC방요금제로 2개이상의 계정이 접속되고있습니다. 확인후 다시 사용하시기 바랍니다.
+Please check the connection, more than 2 accounts are connected with Internet Cafe Time Plan.
+*/
+ MSG_BAN_PC_IP_UNFAIR = 0x463,
+/*20051205 to latest
+귀하는 월정액 요금제 사용자 입니다. (남은기간 : %d일)
+Your account is using monthly payment. (Remaining day: %d day)
+*/
+ MSG_BILLING_1 = 0x464,
+/*20051205 to latest
+귀하는 정량 요금제 사용자 입니다. (남은시간 : %d시간 %분 %초)
+Your account is using time limited. (Remaining time: %d hour %d minute %d second)
+*/
+ MSG_BILLING_2 = 0x465,
+#endif
+#if PACKETVER >= 20051212
+/*20051212 to latest
+해당 아이템은 메일에 첨부 할수 없는 아이템입니다.
+This item cannot be mailed.
+*/
+ MSG_MAIL_ITEM_ADD_FAILED = 0x466,
+/*20051212 to latest
+더이상 아이템을 가질수 없습니다. 아이템은 메일로 보관하겠습니다.
+You cannot accept any more items. Please try again later.
+*/
+ MSG_MAIL_ADD_ITEM_OVER_FAILURE = 0x467,
+#endif
+#if PACKETVER >= 20060109
+/*20060109 to latest
+남성
+Male
+*/
+ MSG_PTSEX1 = 0x468,
+/*20060109 to latest
+여성
+Female
+*/
+ MSG_PTSEX2 = 0x469,
+/*20060109 to latest
+새로운 유저입니다
+New User.
+*/
+ MSG_PT_NEWUSER = 0x46a,
+/*20060109 to latest
+E-mail은 캐릭터를 지울때 필요합니다.
+E-mail address is required to delete a character.
+*/
+ MSG_PT_ACINFO = 0x46b,
+/*20060109 to latest
+정확한 형식으로 입력해 주세요.
+Please enter the correct information.
+*/
+ MSG_PT_ACINFO2 = 0x46c,
+/*20060109 to latest
+이 키를 사용하세요
+Please use this key.
+*/
+ MSG_PT_NEWKEYINFO = 0x46d,
+/*20060109 to latest
+정확한 카드 패스워드를 다시 입력해주세요
+Please enter the correct card password.
+*/
+ MSG_PT_FAIL_CARDPASS = 0x46e,
+/*20060109 to latest
+PT정보
+PT Info
+*/
+ MSG_PTID1 = 0x46f,
+/*20060109 to latest
+PT_ID는 %s
+PT_ID is %s
+*/
+ MSG_PTID2 = 0x470,
+/*20060109 to latest
+NUM_ID는 %s
+NUM_ID is %s
+*/
+ MSG_PTID3 = 0x471,
+/*20060109 to latest
+잊지않게 주의하세요
+Please don't forget this information.
+*/
+ MSG_PTID4 = 0x472,
+/*20060109 to latest
+1001
+*/
+ MSG_PT_ERROR_1001 = 0x473,
+/*20060109 to latest
+1002
+*/
+ MSG_PT_ERROR_1002 = 0x474,
+/*20060109 to latest
+1003
+*/
+ MSG_PT_ERROR_1003 = 0x475,
+/*20060109 to latest
+1004
+*/
+ MSG_PT_ERROR_1004 = 0x476,
+/*20060109 to latest
+1006
+*/
+ MSG_PT_ERROR_1006 = 0x477,
+/*20060109 to latest
+1007
+*/
+ MSG_PT_ERROR_1007 = 0x478,
+/*20060109 to latest
+1008
+*/
+ MSG_PT_ERROR_1008 = 0x479,
+/*20060109 to latest
+1009
+*/
+ MSG_PT_ERROR_1009 = 0x47a,
+/*20060109 to latest
+1012
+*/
+ MSG_PT_ERROR_1012 = 0x47b,
+/*20060109 to latest
+1013
+*/
+ MSG_PT_ERROR_1013 = 0x47c,
+/*20060109 to latest
+1014
+*/
+ MSG_PT_ERROR_1014 = 0x47d,
+/*20060109 to latest
+1015
+*/
+ MSG_PT_ERROR_1015 = 0x47e,
+/*20060109 to latest
+1019
+*/
+ MSG_PT_ERROR_1019 = 0x47f,
+/*20060109 to latest
+1020
+Navigation
+*/
+ MSG_PT_ERROR_1020 = 0x480,
+/*20060109 to latest
+1021
+*/
+ MSG_PT_ERROR_1021 = 0x481,
+/*20060109 to latest
+1023
+*/
+ MSG_PT_ERROR_1023 = 0x482,
+/*20060109 to latest
+1024
+*/
+ MSG_PT_ERROR_1024 = 0x483,
+/*20060109 to latest
+1025
+*/
+ MSG_PT_ERROR_1025 = 0x484,
+/*20060109 to latest
+1027
+*/
+ MSG_PT_ERROR_1027 = 0x485,
+/*20060109 to latest
+1028
+*/
+ MSG_PT_ERROR_1028 = 0x486,
+/*20060109 to latest
+10
+*/
+ MSG_PT_ERROR_10 = 0x487,
+/*20060109 to latest
+20
+*/
+ MSG_PT_ERROR_20 = 0x488,
+/*20060109 to latest
+40
+*/
+ MSG_PT_ERROR_40 = 0x489,
+/*20060109 to latest
+50
+*/
+ MSG_PT_ERROR_50 = 0x48a,
+/*20060109 to latest
+60
+*/
+ MSG_PT_ERROR_60 = 0x48b,
+/*20060109 to latest
+70
+*/
+ MSG_PT_ERROR_70 = 0x48c,
+/*20060109 to latest
+80
+*/
+ MSG_PT_ERROR_80 = 0x48d,
+/*20060109 to latest
+90
+*/
+ MSG_PT_ERROR_90 = 0x48e,
+/*20060109 to latest
+100
+*/
+ MSG_PT_ERROR_100 = 0x48f,
+/*20060109 to latest
+110
+*/
+ MSG_PT_ERROR_110 = 0x490,
+#endif
+#if PACKETVER >= 20060126
+/*20060126 to latest
+30포인트를 받으시겠습니까?
+Do you want to receive 30 points?
+*/
+ MSG_PT_POINT1 = 0x491,
+/*20060126 to latest
+30포인트(5시간)이 충전되었습니다
+30 points (5 hours) have been added.
+*/
+ MSG_PT_POINT2 = 0x492,
+#endif
+#if PACKETVER >= 20060213
+/*20060213 to latest
+감정되지 않은 아이템은 경매에 등록할 수 없습니다.
+You cannot register Unidentified Items in auctions.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE = 0x493,
+/*20060213 to latest
+소비 아이템은 경매에 등록할 수 없습니다.
+You cannot register this Consumable Item in an auction.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE2 = 0x494,
+#endif
+#if PACKETVER >= 20060306
+/*20060306 to latest
+메일창을 열려면 카트창을 닫아 주십시요.
+Please close the Cart Window to open the Mail Window.
+*/
+ MSG_CLOSE_MERCHANTITEMWND = 0x495,
+/*20060306 to latest
+카트창을 열려면 메일창을 닫아 주십시요.
+Please close the Mail Window to open the Cart Window.
+*/
+ MSG_CLOSE_MAILWND = 0x496,
+#endif
+#if PACKETVER >= 20060313
+/*20060313 to latest
+탄환이 장착되었습니다.
+Bullets have been equipped.
+*/
+ MSG_MSG_BULLET_EQUIPMENT_SUCCESS = 0x497,
+/*20060313 to latest
+메일이 반송되었습니다.
+The mail has been returned to sender.
+*/
+ MSG_MAIL_RETURN_SUCCESS = 0x498,
+/*20060313 to latest
+메일이 존재하지 않습니다.
+The mail no longer exists.
+*/
+ MSG_MAIL_RETURN_FAILURE = 0x499,
+#endif
+#if PACKETVER >= 20060522
+/*20060522 to 20060522
+한시간 동안, 동일한 IP로 접속한 유저가 60건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+20060523 to latest
+한시간 동안, 동일한 IP로 접속한 유저가 30건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+More than 30 players sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT_ALL = 0x49a,
+/*20060522 to latest
+한시간 동안, 동일한 IP로 10번 이상 접속되었습니다. 확인후 다시 사용하시기 바랍니다.
+More than 10 connections sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT = 0x49b,
+/*20060522 to latest
+게임을 재시작 하십시오
+Please restart the game.
+*/
+ MSG_GAMEGUARD_RESTART = 0x49c,
+#endif
+#if PACKETVER >= 20060703
+/*20060703 to latest
+용병정보 - 아쳐타입
+Mercenary: Archer
+*/
+ MSG_MER_INFO_TYPE_ARCHER = 0x49d,
+/*20060703 to latest
+용병정보 - 검사타입
+Mercenary: Swordman
+*/
+ MSG_MER_INFO_TYPE_SWORDMAN = 0x49e,
+/*20060703 to latest
+용병정보 - 창병타입
+Mercenary: Spearman
+*/
+ MSG_MER_INFO_TYPE_LANCER = 0x49f,
+/*20060703 to 20070108
+남은시간
+20070115 to latest
+삭제시간
+Expiration
+*/
+ MSG_LEFT_TIME = 0x4a0,
+/*20060703 to latest
+신뢰도
+Loyalty
+*/
+ MSG_MER_FRIENDLY = 0x4a1,
+/*20060703 to latest
+소환횟수
+Summons
+*/
+ MSG_MER_CALLCOUNT = 0x4a2,
+/*20060703 to latest
+Kill
+*/
+ MSG_MER_KILL = 0x4a3,
+#endif
+#if PACKETVER >= 20060904
+/*20060904 to latest
+펫이 배가 고파서 당신을 원망하고 있다는 느낌이 든다.
+You can feel hatred from your pet for neglecting to feed it.
+*/
+ MSG_PET_STARVING = 0x4a4,
+/*20060904 to latest
+[POINT] 테이밍미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You earned %d Taming Mission Ranking Points, giving you a total of %d points.
+*/
+ MSG_GANGSI_POINT = 0x4a5,
+/*20060904 to latest
+[테이밍미션] Target Monster : %s
+[Taming Mission] Target Monster: %s
+*/
+ MSG_GANGSI_MISSION = 0x4a6,
+#endif
+#if PACKETVER >= 20060918
+/*20060918 to latest
+/hunting : 사냥 목록을 보여줍니다.
+/hunting: You can check the your hunting list.
+*/
+ MSG_EXPLAIN_HUNTING = 0x4a7,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s는 몇 스킬 찍으셨나요?
+[Angel's Question] Please tell me, how many %s skills do you have?
+*/
+ MSG_DEATH_Q01 = 0x4a8,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 소지하시고있는 제니를 십만으로 나누면 얼마가 되시나요?
+[Angel's Question] Please tell me, how much zeny you'll have if you divide it by 100,000?
+*/
+ MSG_DEATH_Q02 = 0x4a9,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 오늘이 몇일이신지 아시나요?
+[Angel's Question] Please tell me, what is today's date?
+*/
+ MSG_DEATH_Q03 = 0x4aa,
+/*20060918 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s은 지금 몇이신가요?
+[Angel's Question] Please tell me, how many %s do you have?
+*/
+ MSG_DEATH_Q04 = 0x4ab,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 슈노, 태권계열, 무낙계열을 담당하고있는 SiYeon씨의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in SiYeon's name?
+*/
+ MSG_DEATH_Q05 = 0x4ac,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 귀엽고 어여쁜 라그나로크의 히로인 Munak의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Munak's name?
+*/
+ MSG_DEATH_Q06 = 0x4ad,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 제가 어여뻐하는 Bongun의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Bongun's name?
+*/
+ MSG_DEATH_Q07 = 0x4ae,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 저희가 존재하는 온라인세계 Ragnarok의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, Ragnarok?
+*/
+ MSG_DEATH_Q08 = 0x4af,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 언제나 Online상태인 천사동료들은 큰힘이 되어주죠. Online의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, online?
+*/
+ MSG_DEATH_Q09 = 0x4b0,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 죽음도 두려워하지않는 기사들을 상징하는 단어인 Death의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, death?
+*/
+ MSG_DEATH_Q10 = 0x4b1,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 기사들은 너무 멋진다고 생각해요. Knight의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, knight?
+*/
+ MSG_DEATH_Q11 = 0x4b2,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 중력을 뜻하는 단어인 Gravity의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, gravity?
+*/
+ MSG_DEATH_Q12 = 0x4b3,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 어둠속에서도 밝게 사는게 중요하지요. Dark의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, dark?
+*/
+ MSG_DEATH_Q13 = 0x4b4,
+/*20060918 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 뭐든지 수집하는 Collector의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, collecter?
+*/
+ MSG_DEATH_Q14 = 0x4b5,
+/*20060918 to latest
+[천사의대답] 소녀에게 정확한 사실을 가르쳐주셔서 감사하옵니다.
+[Angel's Answer] Thank you for letting me know~
+*/
+ MSG_DEATH_R01 = 0x4b6,
+/*20060918 to latest
+[천사의대답] 사랑스러우신 분이시군요. 소녀 감탄했사옵니다.
+[Angel's Answer] I'm very pleased with your answer. You are a splendid adventurer.
+*/
+ MSG_DEATH_R02 = 0x4b7,
+/*20060918 to latest
+[천사의대답] 소녀 실망했사옵니다.
+[Angel's Answer] You've disappointed me...
+*/
+ MSG_DEATH_R05 = 0x4b8,
+#endif
+#if PACKETVER >= 20060925
+/*20060925 to latest
+[POINT] 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You earned %d Ranking Points, giving you a total of %d Ranking Points.
+*/
+ MSG_DEATH_POINT = 0x4b9,
+#endif
+#if PACKETVER >= 20060927
+/*20060927 to 20070417
+[%s]의 소지 Point : %d Point
+20070423 to latest
+[%s]의 소지 캐시 : %d 캐시
+[%s]'s Points: %d Points
+*/
+ MSG_POINT_SHOP = 0x4ba,
+#endif
+#if PACKETVER >= 20061009
+/*20061009 to latest
+선택하지 않은 캐릭터는 삭제 됩니다. 완료하시겠습니까?
+Unselected Characters will be deleted. Continue?
+*/
+ MSG_CONFIRM_SELECT_CHARACTERS = 0x4bb,
+/*20061009 to latest
+9개 이상 선택하실 수 없습니다.
+You cannot select more than 8.
+*/
+ MSG_ERROR_SELECT_CHARACTERS = 0x4bc,
+#endif
+#if PACKETVER >= 20061016
+/*20061016 to latest
+캐릭터명을 '%s' (으)로 변경하시겠습니까?
+Do you want to change your name to '%s'?
+*/
+ MSG_CONFIRM_TO_CHANGE_NAME = 0x4bd,
+/*20061016 to latest
+캐릭터명이 성공적으로 변경되었습니다.
+Character Name has been changed successfully.
+*/
+ MSG_CHANGE_NAME_SUCCESS = 0x4be,
+/*20061016 to latest
+캐릭터명 변경이 실패하였습니다.
+You have failed to change this character's name.
+*/
+ MSG_CHANGE_NAME_FAILURE = 0x4bf,
+/*20061016 to latest
+한 번에 한 종류의 아이템만 구매할 수 있습니다.
+You can purchase only one kind of item at a time.
+*/
+ MSG_CAN_BUY_ONLY_ONEITEM = 0x4c0,
+#endif
+#if PACKETVER >= 20061017
+/*20061017 to 20061017
+캐릭터가 하나도 선택되지 않았습니다. 반드시 하나 이상의 캐릭터를 선택하여야 합니다.
+20061023 to latest
+캐릭터가 한개도 선택되지 않았습니다. 반드시 한개 이상의 캐릭터를 선택하여야 합니다.
+No characters were selected. You must select at least one character.
+*/
+ MSG_NO_SELECT_CHARACTERS = 0x4c1,
+#endif
+#if PACKETVER >= 20061023
+/*20061023 to latest
+이미 캐릭터명을 변경한 적이 있습니다. 더 이상 변경 할 수 없습니다.
+This character's name has already been changed. You cannot change a character's name more than once.
+*/
+ MSG_ALREADY_CHANGED_NAME = 0x4c2,
+/*20061023 to latest
+사용자 정보가 정확하지 않습니다.
+User Information is not correct.
+*/
+ MSG_NOTREGISTED_USER = 0x4c3,
+/*20061023 to latest
+다른 사용자가 같은 캐릭터 명을 먼저 사용하였습니다. 다른 캐릭터명을 사용하여 주십시요.
+Another user is using this character name, so please select another one.
+*/
+ MSG_DUPLICATED_CHAR_NAME = 0x4c4,
+#endif
+#if PACKETVER >= 20061030
+/*20061030 to latest
+파티장 권한이 없어 파티원을 소환하지 못했습니다.
+The party member was not summoned because you are not the party leader.
+*/
+ MSG_CANNOT_PARTYCALL = 0x4c5,
+/*20061030 to latest
+현재 맵에는 소환될 파티원이 존재하지 않습니다.
+There is no party member to summon in the current map.
+*/
+ MSG_NO_PARTYMEM_ON_THISMAP = 0x4c6,
+/*20061030 to latest
+이 지역에선 보스몬스터의 흔적을 찾을 수가 없습니다.
+You cannot find any trace of a Boss Monster in this area.
+*/
+ MSG_NOTFIND_BOSSMON = 0x4c7,
+/*20061030 to 20070122
+보스 몬스터 '%s'의 등장 예정시간 %02d시:%02d분
+20070129 to 20071204
+보스 몬스터 '%s'(이)가 %d시 %d분 후에 등장합니다.
+20071211 to latest
+보스 몬스터 '%s'(이)가 %d시간 %d분 후에 등장합니다.
+Boss Monster, '%s' will appear in %02d hour(s) and %02d minute(s).
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON = 0x4c8,
+/*20061030 to latest
+보스 몬스터 '%s'의 위치가 미니맵에 표시됩니다.
+The location of Boss Monster, '%s', will be displayed on your Mini-Map.
+*/
+ MSG_SHOW_POSITION_OF_BOSSMON = 0x4c9,
+#endif
+#if PACKETVER >= 20061106
+/*20061106 to 20061211
+%s를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20061218 to 20070618
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20070619 to 20071218
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+20080102 to latest
+'%s'를 개봉 하시겠습니까? 한번 개봉된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+*/
+ MSG_CONFIRM_TO_OPEN_CASH_ITEM = 0x4ca,
+/*20061106 to latest
+NPC가 존재하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the NPC does not exist.
+*/
+ MSG_BUY_CASH_FAIL_NPC = 0x4cb,
+/*20061106 to latest
+부분 유료화 시스템이 정상 작동하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Kafra Shop System is not working correctly.
+*/
+ MSG_BUY_CASH_FAIL_SYSTEM = 0x4cc,
+/*20061106 to latest
+교환중에는 아이템을 구매 할 수 없습니다.
+You cannot purchase items while you are in a trade.
+*/
+ MSG_BUY_CASH_FAIL_EXCHANGE = 0x4cd,
+/*20061106 to latest
+아이템 정보가 정확하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Item Information was incorrect.
+*/
+ MSG_BUY_CASH_FAIL_ITEM_ID = 0x4ce,
+#endif
+#if PACKETVER >= 20061204
+/*20061204 to latest
+ STR이 향상되었습니다.
+STR has increased.
+*/
+ MSG_ENST_STR = 0x4cf,
+/*20061204 to latest
+ STR이 원래대로 돌아왔습니다.
+STR has returned to normal.
+*/
+ MSG_DSST_STR = 0x4d0,
+/*20061204 to latest
+ AGI이 향상되었습니다.
+AGI has increased.
+*/
+ MSG_ENST_AGI = 0x4d1,
+/*20061204 to latest
+ AGI이 원래대로 돌아왔습니다.
+AGI has returned to normal.
+*/
+ MSG_DSST_AGI = 0x4d2,
+/*20061204 to latest
+ VIT이 향상되었습니다.
+VIT has increased.
+*/
+ MSG_ENST_VIT = 0x4d3,
+/*20061204 to latest
+ VIT이 원래대로 돌아왔습니다.
+VIT has returned to normal.
+*/
+ MSG_DSST_VIT = 0x4d4,
+/*20061204 to latest
+ INT이 향상되었습니다.
+INT has increased.
+*/
+ MSG_ENST_INT = 0x4d5,
+/*20061204 to latest
+ INT이 원래대로 돌아왔습니다.
+INT has returned to normal.
+*/
+ MSG_DSST_INT = 0x4d6,
+/*20061204 to latest
+ DEX이 향상되었습니다.
+DEX has increased.
+*/
+ MSG_ENST_DEX = 0x4d7,
+/*20061204 to latest
+ DEX이 원래대로 돌아왔습니다.
+DEX has returned to normal.
+*/
+ MSG_DSST_DEX = 0x4d8,
+/*20061204 to latest
+ LUK이 향상되었습니다.
+LUK has increased.
+*/
+ MSG_ENST_LUK = 0x4d9,
+/*20061204 to latest
+ LUK이 원래대로 돌아왔습니다.
+LUK has returned to normal.
+*/
+ MSG_DSST_LUK = 0x4da,
+/*20061204 to latest
+ 회피율이 향상되었습니다.
+Flee Rate (Flee) has increased.
+*/
+ MSG_ENST_AVOIDANCE = 0x4db,
+/*20061204 to latest
+ 회피율이 원래대로 돌아왔습니다.
+Flee Rate has returned to normal.
+*/
+ MSG_DSST_AVOIDANCE = 0x4dc,
+/*20061204 to latest
+ 명중률이 향상되었습니다.
+Accuracy Rate (Hit) has increased.
+*/
+ MSG_ENST_HIT = 0x4dd,
+/*20061204 to latest
+ 명중률이 원래대로 돌아왔습니다.
+Accuracy Rate has returned to normal.
+*/
+ MSG_DSST_HIT = 0x4de,
+/*20061204 to latest
+ 크리티컬 확률이 향상되었습니다.
+Critical Attack (Critical) has increased.
+*/
+ MSG_ENST_CRITICALSUCCESSVALUE = 0x4df,
+/*20061204 to latest
+ 크리티컬 확률이 원래대로 돌아왔습니다.
+Critical Attack has returned to normal.
+*/
+ MSG_DSST_CRITICALSUCCESSVALUE = 0x4e0,
+/*20061204 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.5배로 증가합니다.
+*/
+ MSG_PLUSEXP = 0x4e1,
+/*20061204 to latest
+ 30분내 사망시 1회에 한해 경험치 감소가 일어나지 않습니다.
+This character will not receive any EXP penalty if killed within the next 30 minutes.
+*/
+ MSG_DDEATHPENALTY = 0x4e2,
+/*20061204 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 30분간 2배로 증가합니다.
+Regular item drops from monsters will be doubled for the next 30 minutes.
+*/
+ MSG_RECEIVEITEM = 0x4e3,
+/*20061204 to latest
+ 10분간 맵 내에 출현 가능한 보스 몬스터에 대한 정보를 안내해 드립니다.
+Boss Monster Map Information for the next 10 minutes.
+*/
+ MSG_BOSS_ALARM = 0x4e4,
+/*20061204 to 20061211
+ 정말로 %s아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20061218 to 20070417
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d포인트가 차감됩니다.
+20070423 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+20080610 to latest
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, %d캐시가 차감됩니다.
+*/
+ MSG_BUY_RECONFIRM = 0x4e5,
+#endif
+#if PACKETVER >= 20061211
+/*20061211 to 20061211
+'%s'아이템의 사용시간이 %d분 남았습니다.
+20061218 to 20070417
+ 포인트가 부족합니다.
+20070423 to latest
+ 캐시가 부족합니다.
+ You do not have enough Kafra Credit Points.
+*/
+ MSG_BUY_CASH_FAIL_MONEY = 0x4e6,
+/*20061211 to 20061211
+1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+20061218 to latest
+ ^ff0000파기일시: %s^000000
+ ^ff0000Expiration Date: %s^000000
+*/
+ MSG_NOTICE_TO_DELETE_TIME = 0x4e7,
+/*20061211 to 20061211
+'%s'아이템이 인벤토리에서 삭제되었습니다.
+20061218 to latest
+ '%s'아이템의 사용시간이 %d분 남았습니다.
+ The '%s' item will disappear in %d minutes.
+20070102 to 20070312
+ '%s'아이템의 사용시간이 %s 남았습니다.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e8,
+#endif
+#if PACKETVER >= 20061218
+/*20061218 to latest
+ 1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+ '%s' item will be deleted from the Inventory in 1 minute.
+*/
+ MSG_LAST_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e9,
+/*20061218 to latest
+ '%s'아이템이 인벤토리에서 삭제되었습니다.
+ '%s' item has been deleted from the Inventory.
+*/
+ MSG_NOTICE_TO_DELETE_ITEM = 0x4ea,
+#endif
+#if PACKETVER >= 20070102
+/*20070102 to latest
+Input Number
+*/
+ MSG_INPUT_NUMBER = 0x4eb,
+/*20070102 to latest
+%m월 %d일 %H시 %M분
+%m/%d %H:%M
+*/
+ MSG_TIME_TYPE2 = 0x4ec,
+#endif
+#if PACKETVER >= 20070129
+/*20070129 to 20071120
+보스 몬스터 '%s'(이)가 1분 이내에 등장합니다.
+20071127 to latest
+보스 몬스터 '%s'(이)가 잠시 후에 등장합니다.
+Boss Monster '%s' will appear within 1 minute.
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON2 = 0x4ed,
+/*20070129 to latest
+용병 스킬목록
+Mercenary Soldier Skill List
+*/
+ MSG_MER_SKILLLIST = 0x4ee,
+/*20070129 to latest
+블랙젬스톤 1개와 백만제니를 소모하는 마법의 실행에 동의합니까?
+Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+*/
+ MSG_DA_EXP_ACCEPT = 0x4ef,
+#endif
+#if PACKETVER >= 20070220
+/*20070220 to latest
+[POINT] 콜렉터랭킹 포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have gained %d Collector Rank Points; you now have a total of %d Collector Rank Points.
+*/
+ MSG_COLLECTOR_POINT = 0x4f0,
+/*20070220 to latest
+[콜렉터랭킹] Target Item : %s
+[Collector Rank] Target Item: %s
+*/
+ MSG_COLLECTOR_MISSION = 0x4f1,
+#endif
+#if PACKETVER >= 20070227
+/*20070227 to latest
+용병 사용시간이 만료되었습니다.
+The mercenary contract has expired.
+*/
+ MSG_MER_FINISH = 0x4f2,
+/*20070227 to latest
+용병이 사망하였습니다.
+The mercenary has died.
+*/
+ MSG_MER_DIE = 0x4f3,
+/*20070227 to latest
+용병이 해고되었습니다.
+You have released the mercenary.
+*/
+ MSG_MER_RETIRE = 0x4f4,
+/*20070227 to latest
+용병이 도망갔습니다.
+The mercenary has run away.
+*/
+ MSG_MER_RUNAWAY = 0x4f5,
+#endif
+#if PACKETVER >= 20070319
+/*20070319 to latest
+ '%s'아이템의 사용시간이 %d초 남았습니다.
+ The '%s' item will disappear in %d seconds.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME2 = 0x4f6,
+#endif
+#if PACKETVER >= 20070326
+/*20070326 to 20070821
+PC방 이벤트 : 경험치 증가 %d%%, 죽을때 경험치 %d%%, 드롭율 증가 %d%%
+20070828 to latest
+PC방 프리미엄 서비스 : 경험치 %d%% 증가, 사망 페널티 %d%% 감소, 드롭율 %d%% 증가
+IP Bonus: EXP/JEXP %d%%, Death Penalty %d%%, Item Drop %d%%
+*/
+ MSG_PCBANG_EVENT = 0x4f7,
+#endif
+#if PACKETVER >= 20070402
+/*20070402 to latest
+24시간 이후에 시도하세요
+Symbols in Character Names are forbidden.
+*/
+ MSG_LIMIT_CHAR_DELETE = 0x4f8,
+#endif
+#if PACKETVER >= 20070416
+/*20070416 to latest
+용병이 사용자 인공지능으로 동작합니다.
+Mercenary will follow custom AI.
+*/
+ MSG_MER_USERAI_ON = 0x4f9,
+/*20070416 to latest
+용병이 기본 인공지능으로 동작합니다.
+Mercenary will follow basic AI.
+*/
+ MSG_MER_USERAI_OFF = 0x4fa,
+#endif
+#if PACKETVER >= 20070611
+/*20070611 to latest
+ %s님의
+ %s's
+*/
+ MSG_CHARACTER_NAME = 0x4fb,
+/*20070611 to 20070801
+%s님이 %s를 획득하셨습니다.
+20070807 to latest
+%s님이 %s 아이템을 획득하셨습니다.
+%s has acquired %s.
+*/
+ MSG_ITEM_PICKUP_PARTY = 0x4fc,
+/*20070611 to latest
+공개 채팅 메시지 표시
+Public Chat Display
+*/
+ MSG_VIEW_CHAT_MSG = 0x4fd,
+/*20070611 to latest
+귓속말 채팅 메시지 표시
+Whisper Display
+*/
+ MSG_VIEW_WHISPER_MSG = 0x4fe,
+/*20070611 to latest
+파티 채팅 메시지 표시
+Party Chat Display
+*/
+ MSG_VIEW_PARTY_MSG = 0x4ff,
+/*20070611 to latest
+길드 채팅 메시지 표시
+Guild Chat Display
+*/
+ MSG_VIEW_GUILD_MSG = 0x500,
+/*20070611 to latest
+아이템 획득/드롭 메시지 표시
+Item Get/Drop Message Display
+*/
+ MSG_VIEW_GET_ITEM_MSG = 0x501,
+/*20070611 to latest
+장비 장착/해제 메시지 표시
+Equipment On/Off Message Display
+*/
+ MSG_VIEW_EQUIP_MSG = 0x502,
+/*20070611 to latest
+상태이상 메시지 표시
+Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_MSG = 0x503,
+/*20070611 to latest
+파티원의 주요 아이템 획득 메시지 표시
+Party Member's Obtained Item Message Display
+*/
+ MSG_VIEW_GET_ITEM_PARTY_MSG = 0x504,
+/*20070611 to latest
+파티원의 상태이상 메시지 표시
+Party Member's Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_PARTY_MSG = 0x505,
+/*20070611 to latest
+스킬 사용 실패 메시지 표시
+Skill Failure Message Display
+*/
+ MSG_VIEW_FAIL_SKILL_MSG = 0x506,
+/*20070611 to latest
+파티 설정 메시지 표시
+Party Configuration Message Display
+*/
+ MSG_VIEW_PARTY_SETUP_MSG = 0x507,
+/*20070611 to latest
+장비 손상 메시지 표시
+Damaged Equipment Message Display
+*/
+ MSG_VIEW_DAMAGED_EQUIP_MSG = 0x508,
+/*20070611 to latest
+배틀 메시지 창 표시 정보
+Battle Message Window Display
+*/
+ MSG_BATTLE_CHAT_WND_OPTION = 0x509,
+/*20070611 to latest
+[%s]의 소지 한코인 : %d 한코인
+[%s]'s Han Coin: %d Han Coin
+*/
+ MSG_POINT_SHOP_NHN = 0x50a,
+#endif
+#if PACKETVER >= 20070618
+/*20070618 to latest
+일반 메시지
+Public Log
+*/
+ MSG_ST_CHAT = 0x50b,
+/*20070618 to latest
+배틀 메시지
+Battle Log
+*/
+ MSG_BT_CHAT = 0x50c,
+/*20070618 to latest
+휴대폰 인증.
+Mobile Authentication
+*/
+ MSG_PHONE_CONFIRM = 0x50d,
+/*20070618 to latest
+읽기
+Read
+*/
+ MSG_BOOK_READ = 0x50e,
+/*20070618 to latest
+자동낭독
+Auto Read
+*/
+ MSG_BOOK_AUTOREAD = 0x50f,
+/*20070618 to latest
+책갈피
+Bookmark
+*/
+ MSG_BOOK_KEEP = 0x510,
+/*20070618 to latest
+이전페이지
+Previous
+*/
+ MSG_BOOK_PREV = 0x511,
+/*20070618 to latest
+다음페이지
+Next
+*/
+ MSG_BOOK_NEXT = 0x512,
+/*20070618 to latest
+닫기
+Close
+*/
+ MSG_BOOK_CLOSE = 0x513,
+#endif
+#if PACKETVER >= 20070622
+/*20070622 to latest
+%s 장비가 손상되었습니다.
+%s's Equipment has been damaged.
+*/
+ MSG_DAMAGED_EQUIP = 0x514,
+/*20070622 to latest
+%s님의 %s 손상되었습니다.
+%s's %s was damaged.
+*/
+ MSG_DAMAGED_EQUIP_PARTY = 0x515,
+/*20070622 to latest
+무기가
+Weapon
+*/
+ MSG_DAMAGED_WEAPON = 0x516,
+/*20070622 to latest
+갑옷이
+Armor
+*/
+ MSG_DAMAGED_BODY = 0x517,
+/*20070622 to latest
+스킬레벨이 부족합니다. 파티가입 불능
+Insufficient Skill Level for joining a Party
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5_2 = 0x518,
+#endif
+#if PACKETVER >= 20070628
+/*20070628 to latest
+[%s]의 무료 캐시 : %d 캐시
+[%s]'s Free Cash: %d Cash
+*/
+ MSG_POINT_SHOP2 = 0x519,
+/*20070628 to latest
+무료 캐시 사용 :
+Use Free Cash:
+*/
+ MSG_USE_FREE_POINT = 0x51a,
+/*20070628 to latest
+캐시
+Cash
+*/
+ MSG_CASH = 0x51b,
+#endif
+#if PACKETVER >= 20070710
+/*20070710 to latest
+http://payment.ro.hangame.com/index.asp
+*/
+ MSG_SETTLE_WEB_URL_HANGAME = 0x51c,
+/*20070710 to 20090603
+그라비티 회원 정보동의를 하셔야 사용할수있습니다.
+20090610 to latest
+그라비티 회원 정보동의를 하셔야 사용할 수 있습니다.
+You need to accept the Privacy Policy from Gravity in order to use the service.
+*/
+ MSG_BAN_GRAVITY_MEM_AGREE = 0x51d,
+/*20070710 to latest
+이용약관에 동의를 하셔야 본 서비스를 이용하실 수 있습니다.
+You need to accept the User Agreement in order to use the service.
+*/
+ MSG_BAN_GAME_MEM_AGREE = 0x51e,
+/*20070710 to 20080520
+존재하지 않는 한게임 ID이거나 잘못된 ID입니다.
+20080527 to latest
+입력하신 아이디와 비밀번호가 등록된 정보와 일치하지 않습니다.
+Incorrect or nonexistent ID.
+*/
+ MSG_BAN_HAN_VALID = 0x51f,
+#endif
+#if PACKETVER >= 20070711
+/*20070711 to 20080603
+ 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+20080610 to latest
+ 본 아이템은 청약 철회나 환불 대상에서 제외되는 아이템입니다. 정말로 '%s'아이템을 구매하시겠습니까?, 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+*/
+ MSG_BUY_RECONFIRM2 = 0x520,
+#endif
+#if PACKETVER >= 20070718
+/*20070718 to latest
+%d시간이 경과하였습니다.
+%d hour(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME1 = 0x521,
+/*20070718 to latest
+%d시간 %d분이 경과하였습니다.
+%d hour(s) %d minute(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME2 = 0x522,
+/*20070718 to latest
+게임을 종료하세요, 경험치 및 모든게 50%로 조정됩니다
+Please stop playing the game, and take a break. Exp and other features will be reduced to 50%.
+*/
+ MSG_WARNING_MSG1 = 0x523,
+/*20070718 to latest
+불건전 시간대에 접어들었습니다. 게임을 종료하세요, 경험치 및 모든게 0%로 조정됩니다
+Please stop playing the game since you'll need to rest. Exp and other features will be fixed to 0%.
+*/
+ MSG_WARNING_MSG2 = 0x524,
+#endif
+#if PACKETVER >= 20070724
+/*20070724 to latest
+퀘스트 목록
+Quest List
+*/
+ MSG_QUESTWIN = 0x525,
+#endif
+#if PACKETVER >= 20070807
+/*20070807 to latest
+RO SHOP
+RO Shop
+*/
+ MSG_RO_SHOP = 0x526,
+#endif
+#if PACKETVER >= 20070821
+/*20070821 to 20070904
+메모리얼던젼 '%s'이 예약되었습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 알수없는 이유로 실패 하였습니다.
+Memorial Dungeon, '%s' is booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN = 0x527,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 예약이 실패했습니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 예약중복으로 실패 하였습니다.
+Failed to book Memorial Dungeon, '%s'.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE = 0x528,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 이미 예약중입니다.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 권한문제로 실패 하였습니다.
+Memorial Dungeon, '%s' is already booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT = 0x529,
+/*20070821 to 20070904
+메모리얼던젼 '%s'가 생성 되었습니다
+ 5분내에 입장하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약이 중복생성요청으로 실패하였습니다.
+Memorial Dungeon, '%s' is created.
+ Please enter in 5 minutes.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST = 0x52a,
+/*20070821 to 20070904
+메모리얼던젼 '%s' 생성에 실패했습니다.
+ 나중에 다시 시도하세요.
+20070911 to latest
+메모리얼던젼 '%s'의 예약취소가 실패 하였습니다.
+Failed to create Memorial Dungeon, '%s'.
+ Please try again.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_FAIL = 0x52b,
+/*20070821 to latest
+상대방이 파티 초대 거부 상태입니다.
+The character blocked the party invitation.
+*/
+ MSG_JOINMSG_REFUSE = 0x52c,
+#endif
+#if PACKETVER >= 20070828
+/*20070828 to latest
+모든 파티 초대를 거부합니다.
+Block all party invitations.
+*/
+ MSG_INVITE_PARTY_REFUSE = 0x52d,
+/*20070828 to latest
+모든 파티 초대를 수락합니다.
+Allow all party invitations.
+*/
+ MSG_INVITE_PARTY_ACCEPT = 0x52e,
+#endif
+#if PACKETVER >= 20070904
+/*20070904 to latest
+착용하시면 이 아이템은 영구 귀속됩니다. 착용하시겠습니까?
+This item will be permanently bound to this character once it is equipped. Do you really want to equip this item?
+*/
+ MSG_YOURITEM_EQUIP = 0x52f,
+/*20070904 to latest
+%s 아이템이 귀속되었습니다.
+%s is now permanently bound to this character.
+*/
+ MSG_YOURITEM_EQUIPED = 0x530,
+/*20070904 to latest
+캐시가 부족합니다. 무료 캐시 포인트를 입력해 주시기 바랍니다.
+You do not have enough Kafra Credit Points. Please enter whether you have free credit points.
+*/
+ MSG_BUY_TO_FREE_POINT = 0x531,
+/*20070904 to latest
+파티 가입요청
+Request to Join Party
+*/
+ MSG_REQ_JOIN_PARTY3 = 0x532,
+#endif
+#if PACKETVER >= 20070912
+/*20070912 to latest
+공성 정보 메시지 표시
+Display WOE Info
+*/
+ MSG_VIEW_SIEGE_INFO_MSG = 0x533,
+/*20070912 to latest
+메모리얼던젼 '%s'의 예약이 취소 되었습니다.
+Memorial Dungeon %s's reservation has been canceled.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_SUCCESS = 0x534,
+/*20070912 to latest
+메모리얼던젼 '%s' 생성에 실패하였습니다. 다시 시도 하세요.
+Failed to create Memorial Dungeon %s. Please try again.
+*/
+ MSG_MDUNGEON_CREATE_FAIL = 0x535,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 스킬입니다.
+This skill cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_SKILL_AREA = 0x536,
+/*20070912 to latest
+이 장소에서는 사용할 수 없는 아이템입니다.
+This item cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_USEITEM_AREA = 0x537,
+#endif
+#if PACKETVER >= 20070918
+/*20070918 to latest
+메모리얼 던전
+Memorial Dungeon
+*/
+ MSG_MEMORIAL_DUN = 0x538,
+/*20070918 to latest
+%s 대기중
+%s in Standby
+*/
+ MSG_MEMORIAL_DUN_WAITING = 0x539,
+/*20070918 to latest
+%s 입장 가능
+%s Available
+*/
+ MSG_MEMORIAL_DUN_READY = 0x53a,
+/*20070918 to 20071120
+%s 내부
+20071127 to latest
+%s 진행중
+%s in Progress
+*/
+ MSG_MEMORIAL_DUN_IN = 0x53b,
+/*20070918 to latest
+시간 안에 입장하지 않아 메모리얼 던전이 사라졌습니다.
+No one entered the Memorial Dungeon within its duration; the dungeon has disappeared.
+*/
+ MSG_MEMORIAL_DUN_OUT1 = 0x53c,
+/*20070918 to latest
+이용하시려면 이용 신청을 처음부터 다시 해주시기 바랍니다.
+Please apply for dungeon entry again to play in this dungeon.
+*/
+ MSG_MEMORIAL_DUN_OUT2 = 0x53d,
+/*20070918 to latest
+대기 순위 : ^ff0000%d^000000
+Your Standby Priority: ^ff0000%d^000000
+*/
+ MSG_MEMORIAL_DUN_PRIORITY = 0x53e,
+/*20070918 to latest
+^ff0000%s^000000 내에 입장하지 않을 경우 신청하신 던전이 삭제 됩니다.
+The requested dungeon will be removed if you do not enter within ^ff0000%s^000000.
+*/
+ MSG_MEMORIAL_DUN_NOTIFY = 0x53f,
+/*20070918 to latest
+던전 미션 제한 시간 :
+Dungeon Mission Time Limit:
+*/
+ MSG_MEMORIAL_DUN_NOTIFY2 = 0x540,
+/*20070918 to latest
+메모리얼 던전 예약이 취소되었습니다.
+The Memorial Dungeon reservation has been canceled.
+*/
+ MSG_MEMORIAL_DUN_CANCEL = 0x541,
+/*20070918 to latest
+메모리얼 던전이 유지 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon duration expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_LIVE_TIME_OUT = 0x542,
+/*20070918 to latest
+메모리얼 던전이 입장 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon's entry time limit expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_ENTER_TIME_OUT = 0x543,
+/*20070918 to latest
+메모리얼 던전이 삭제 되었습니다.
+The Memorial Dungeon has been removed.
+*/
+ MSG_MEMORIAL_DUN_DESTROY_REQUEST = 0x544,
+/*20070918 to latest
+메모리얼 던전에 시스템 오류가 발생하였습니다. 정상적인 게임 진행을 위해 재접속을 해주십시오.
+A system error has occurred in the Memorial Dungeon. Please relog in to the game to continue playing.
+*/
+ MSG_MEMORIAL_DUN_ERROR = 0x545,
+/*20070918 to latest
+사용할 수 없는 슬롯입니다.
+This slot is not usable.
+*/
+ MSG_FR_INVALID_SLOT = 0x546,
+/*20070918 to latest
+Base Level이 15를 넘었습니다.
+Your Base Level is over 15.
+*/
+ MSG_FR_BASELVL = 0x547,
+/*20070918 to latest
+Job Level이 15를 넘었습니다.
+Your Job Level is over 15.
+*/
+ MSG_FR_INVALID_JOBLV = 0x548,
+/*20070918 to latest
+해당슬롯 캐릭터에 직업군의 상인이므로 게임을 할 수 없습니다.
+You cannot play the Merchant class character in this slot.
+*/
+ MSG_FR_JOB = 0x549,
+/*20070918 to latest
+추후 사용예정
+Not Yet Implemented
+*/
+ MSG_FR_MAP = 0x54a,
+/*20070918 to latest
+만들수 있는 케릭터 슬롯이 아닙니다.
+You are not eligible to open the Character Slot.
+*/
+ MSG_FR_ERR_MKCHAR_INVALID_SLOT = 0x54b,
+/*20070918 to latest
+삭제할 수 없는 케릭터 입니다.
+This character cannot be deleted.
+*/
+ MSG_FR_ERR_DELCHAR_INVALID_SLOT = 0x54c,
+/*20070918 to latest
+상대방의 장비창이 공개되어 있지 않습니다.
+This character's equipment information is not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSED = 0x54d,
+/*20070918 to latest
+장비창을 공개하지 않습니다.
+Equipment information not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSE = 0x54e,
+/*20070918 to latest
+장비창을 공개합니다.
+Equipment information open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_ACCEPT = 0x54f,
+/*20070918 to latest
+(%s)님 장비창 보기
+Check %s's Equipment Info
+*/
+ MSG_REQ_VIEW_OTHERUSER = 0x550,
+/*20070918 to latest
+%s의 장착아이템
+'%s's Equipment
+*/
+ MSG_OTHERUSER_EQUIPED_ITEM = 0x551,
+/*20070918 to latest
+장비창 공개
+Show Equip
+*/
+ MSG_OPEN_EQUIPED_ITEM = 0x552,
+#endif
+#if PACKETVER >= 20071002
+/*20071002 to latest
+프리미엄 서비스를 이용해 주시기 바랍니다.
+This service is only available for premium users.
+*/
+ MSG_NEED_PREMIUM_SERVICE = 0x553,
+/*20071002 to latest
+무료 사용자는 최대 50000제니까지 소유할 수 있습니다.
+Free Trial users can only hold up to 50,000 zeny.
+*/
+ MSG_FR_INVALID_MONEY = 0x554,
+#endif
+#if PACKETVER >= 20071009
+/*20071009 to latest
+전장채팅 상태가 되었습니다.
+Battlefield Chat has been activated.
+*/
+ MSG_BATTLECHAT_ON = 0x555,
+/*20071009 to latest
+전장채팅 상태가 해제되었습니다.
+Battlefield Chat has been deactivated.
+*/
+ MSG_BATTLECHAT_OFF = 0x556,
+#endif
+#if PACKETVER >= 20071017
+/*20071017 to latest
+용병정보 - 몬스터타입
+Mercenary Info - Monster Type
+*/
+ MSG_MER_INFO_TYPE_MONSTER = 0x557,
+#endif
+#if PACKETVER >= 20071106
+/*20071106 to latest
+전체 맵 보기
+World Map
+*/
+ MSG_RO_MAP = 0x558,
+#endif
+#if PACKETVER >= 20071127
+/*20071127 to latest
+메모리얼던젼이 CLOSE 상태입니다.
+The Memorial Dungeon is now closed.
+*/
+ MSG_MEMORIAL_DUN_CLOSE = 0x559,
+#endif
+#if PACKETVER >= 20071204
+/*20071204 to latest
+^ff0000^ff0000용병을 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+^ff0000Deleting a Mercenary Soldier^000000 will also delete his growth history. Do you really want to proceed with the deletion?
+*/
+ MSG_DELETE_MER = 0x55a,
+#endif
+#if PACKETVER >= 20071211
+/*20071211 to latest
+메모리얼던젼이 OPEN 상태입니다.
+The Memorial Dungeon is now open.
+*/
+ MSG_MEMORIAL_DUN_OPEN = 0x55b,
+#endif
+#if PACKETVER >= 20080108
+/*20080108 to latest
+위의 계정은 아직 통신 안전 키에 연결되지 않았습니다. 먼저 안전 키를 해제하신 뒤 게임에 접속해 주십시오.
+This account has not been confirmed by connecting to the safe communication key. Please connect to the key first, and then log into the game.
+*/
+ MSG_PHONE_BLOCK = 0x55c,
+/*20080108 to latest
+한 아이피로 접속 가능한 유저수를 초과하였습니다.
+The number of accounts connected to this IP has exceeded the limit.
+*/
+ MSG_BAN_PC_IP_LIMIT_ACCESS = 0x55d,
+#endif
+#if PACKETVER >= 20080219
+/*20080219 to latest
+새로운 퀘스트를 받았습니다
+You have received a new quest.
+*/
+ MSG_QUESTGET = 0x55e,
+#endif
+#if PACKETVER >= 20080401
+/*20080401 to latest
+^777777습득조건 :
+^CC3399Requirement:
+*/
+ MSG_FINDTEXT_TO_SKILLDES = 0x55f,
+/*20080401 to latest
+스킬 설명 보기
+View Skill Info
+*/
+ MSG_VIEW_SKILL_DESCRIPT = 0x560,
+#endif
+#if PACKETVER >= 20080408
+/*20080408 to latest
+사용된 스킬 포인트는 다시 되돌릴 수 없습니다. 적용하시겠습니까?
+Once used, skill points cannot be re-allocated. Would you like to use the skill points?
+*/
+ MSG_APPLY_SKILL_UP = 0x561,
+/*20080408 to latest
+노비스·1차직업
+1st
+*/
+ MSG_1TABNAME_SKILLWND = 0x562,
+/*20080408 to latest
+2차·전승직업
+2nd
+*/
+ MSG_2TABNAME_SKILLWND = 0x563,
+/*20080408 to 20080520
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭시간 : %s
+20080527 to latest
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭종료시간 : %s
+This account has been used for illegal program or hacking program. Block Time: %s
+20081217 to 20081218
+불법프로그램을 사용하였거나 해킹을 시도한 계정이거나 그라비티 이전을 신청한 한게임 계정입니다. 블럭종료시간 : %s
+*/
+ MSG_RE17 = 0x564,
+/*20080408 to latest
+불법프로그램이 실행, 바이러스 감염, 또는 해킹툴이 설치되어 있을 가능성이 있습니다. 정상 클라이언트를 실행하여 주시기 바랍니다. 함께 만드는 밝은 라그나로크가 될 수 있도록 노력하고 있습니다.
+The possibility of exposure to illegal program, PC virus infection or Hacking Tool has been detected. Please execute licensed client. Our team is trying to make a best environment for Ro players.
+*/
+ MSG_RE18 = 0x565,
+#endif
+#if PACKETVER >= 20080415
+/*20080415 to latest
+당신은 지금 건강한 게임 시간 대에 있습니다, 즐거운 게임이 되시길 바랍니다
+You are currently playing in the best game environment. Please enjoy the Ragnarok.
+*/
+ MSG_WARNING_MSG3 = 0x566,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.5배로 증가합니다.
+*/
+ MSG_PLUSONLYJOBEXP = 0x567,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.25배로 증가합니다.
+*/
+ MSG_PLUSEXP14532 = 0x568,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 2배로 증가합니다.
+EXP points from hunting monsters are increased by 100%% for 30 minutes.
+*/
+ MSG_PLUSEXP14533 = 0x569,
+/*20080415 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 60분간 1.5배로 증가합니다.
+EXP points from hunting monsters are increased by 50% for 60 minutes.
+*/
+ MSG_PLUSEXP12312 = 0x56a,
+#endif
+#if PACKETVER >= 20080527
+/*20080527 to latest
+이 맵에서는 파티를 결성할 수 없습니다.
+Unable to organize a party in this map.
+*/
+ MSG_NOPARTY = 0x56b,
+/*20080527 to latest
+(%s)님은 파티에 참여할 수 없는 맵에 있습니다.
+(%s) are currently in restricted map to join a party.
+*/
+ MSG_NOPARTY2 = 0x56c,
+/*20080527 to 20080603
+간편아이템샵.
+20080610 to latest
+간편아이템샵
+Simple Item Shop
+*/
+ MSG_SIMPLE_CASH_SHOP = 0x56d,
+/*20080527 to latest
+소지 한코인 : %d 한코인
+Han Coin: %d Han Coin
+*/
+ MSG_SIMPLE_POINT_SHOP_NHN = 0x56e,
+/*20080527 to latest
+소지 캐시 : %d 캐시
+RoK Point: %d RoK Point
+*/
+ MSG_SIMPLE_POINT_SHOP = 0x56f,
+/*20080527 to latest
+무료 캐시 : %d 캐시
+Free Cash: %d Cash
+*/
+ MSG_SIMPLE_POINT_SHOP2 = 0x570,
+#endif
+#if PACKETVER >= 20080715
+/*20080715 to latest
+본서버 유저는 프리서버에 접속할수 없습니다.
+An user of this server cannot connect to free server
+*/
+ MSG_MAIN_USER_CANONT_LOGIN_FREE_SERVER = 0x571,
+/*20080715 to latest
+유효기간이 지난 비밀번호 입니다. 다시 로그인하여주십시오.
+Your password has expired. Please log in again
+*/
+ MSG_INVALID_ONETIMELIMIT = 0x572,
+#endif
+#if PACKETVER >= 20080903
+/*20080903 to latest
+3차직업
+3rd
+*/
+ MSG_3TABNAME_SKILLWND = 0x573,
+#endif
+#if PACKETVER >= 20080917
+/*20080917 to latest
+이 스킬을 사용할 수 없는 대상입니다.
+This skill can't be used on that target.
+*/
+ MSG_USESKILL_FAIL_TOTARGET = 0x574,
+/*20080917 to latest
+안실라 소유 개수가 초과하여 스킬을 사용할 수 없습니다.
+You can't use skill because you have exceeded the number Ancilla possession limit
+*/
+ MSG_USESKILL_FAIL_ANCILLA_NUMOVER = 0x575,
+/*20080917 to latest
+성수가 필요합니다.
+Unable to use the skill to exceed the number of Ancilla.
+*/
+ MSG_USESKILL_FAIL_HOLYWATER = 0x576,
+/*20080917 to latest
+안실라가 필요합니다.
+Holy water is required.
+*/
+ MSG_USESKILL_FAIL_ANCILLA = 0x577,
+/*20080917 to latest
+일정거리 내에 중복될 수 없습니다.
+Ancilla is required.
+*/
+ MSG_USESKILL_FAIL_DUPLICATE_RANGEIN = 0x578,
+/*20080917 to latest
+이 스킬을 사용하기 위해서는 다른 스킬이 필요합니다.
+Cannot be duplicated within a certain distance.
+*/
+ MSG_USESKILL_FAIL_NEED_OTHER_SKILL = 0x579,
+#endif
+#if PACKETVER >= 20080924
+/*20080924 to latest
+이 맵에서는 채팅을 할 수 없습니다.
+This skill requires other skills to be used.
+*/
+ MSG_NO_CHATTING = 0x57a,
+#endif
+#if PACKETVER >= 20081001
+/*20081001 to latest
+3시간이 지났습니다.
+Chat is not allowed in this map
+*/
+ MSG_VET_3HOUR = 0x57b,
+/*20081001 to latest
+5시간이 지났습니다.
+3 hours have passed.
+*/
+ MSG_VET_5HOUR = 0x57c,
+#endif
+#if PACKETVER >= 20081008
+/*20081008 to latest
+게임가드 초기화 에러 또는 구버전의 게임가드 파일입니다. 게임가드 셋업파일을 다시 설치하고 게임을 실행해 보시기 바랍니다.
+5 hours have passed.
+*/
+ MSG_NPGAMEMON_ERROR_GAMEGUARD = 0x57d,
+/*20081008 to latest
+ini 파일이 없거나 변조되었습니다. 게임가드 셋업파일을 설치하면 해결 할 수 있습니다.
+Game guard initialization error or previous version game guard file is installed. Please re-install the setup file and try again
+*/
+ MSG_NPGMUP_ERROR_PARAM = 0x57e,
+/*20081008 to latest
+게임가드와 충돌 프로그램이 발견되었습니다.
+Either ini file is missing or altered. Install game guard setup file to fix the problem
+*/
+ MSG_NPGG_ERROR_COLLISION = 0x57f,
+#endif
+#if PACKETVER >= 20081112
+/*20081112 to latest
+잘못된 클라이언트입니다. 정상적인 클라이언트를 실행하여 주십시요.
+There is a program found that conflicts with game guard
+*/
+ MSG_PROOF_ERROR = 0x580,
+#endif
+#if PACKETVER >= 20081203
+/*20081203 to latest
+모바일 인증을 받아주시기 바랍니다.
+Incorrect client. Please run a normal client
+*/
+ MSG_MOBILE_LOCKSERVER = 0x581,
+#endif
+#if PACKETVER >= 20081210
+/*20081210 to latest
+모바일 인증에 실패하였습니다.
+Thank you to accept mobile authentication.
+*/
+ MSG_FAILED_MOBILE_LOCKSERVER = 0x582,
+#endif
+#if PACKETVER >= 20081217
+/*20081217 to latest
+이스킬은 혼자서 사용할수 없습니다.
+This skill can't be used alone
+*/
+ MSG_USESKILL_FAIL_NEED_HELPER = 0x583,
+/*20081217 to latest
+이스킬은 특정방향으로만 사용할수 있습니다.
+This skill can be used to certain direction only
+*/
+ MSG_USESKILL_FAIL_INVALID_DIR = 0x584,
+/*20081217 to latest
+더이상 소환할수 없습니다.
+Cannot summon spheres anymore.
+*/
+ MSG_USESKILL_FAIL_SUMMON = 0x585,
+/*20081217 to latest
+소환된 구체가 존재하지 않습니다.
+*/
+ MSG_USESKILL_FAIL_SUMMON_NONE = 0x586,
+/*20081217 to latest
+사용가능한 모방스킬이 존재하지 않습니다.
+There is no imitation skills available.
+*/
+ MSG_USESKILL_FAIL_IMITATION_SKILL_NONE = 0x587,
+/*20081217 to latest
+이 스킬은 중복해서 사용할수 없습니다.
+You can't reuse this skill
+*/
+ MSG_USESKILL_FAIL_DUPLICATE = 0x588,
+/*20081217 to latest
+스킬을 사용할수 없는 상태입니다.
+Skill can't be used in this state
+*/
+ MSG_USESKILL_FAIL_CONDITION = 0x589,
+/*20081217 to latest
+아이템별 최대 소지량을 초과하여 가질 수 없습니다.
+You have exceeded the maximum amount of possession of another item.
+*/
+ MSG_PICKUP_MAXCOUNT_LIMIT = 0x58a,
+#endif
+#if PACKETVER >= 20090204
+/*20090204 to latest
+관리자 권한이 없습니다. 프로그램 최초 실행은 관리자 권한으로 실행하셔야 합니다.
+No administrative privileges. Must first run the program with administrator privileges.
+*/
+ MSG_NPK_ERROR_NOTADMIN = 0x58b,
+/*20090204 to latest
+nProtect KeyCrypt 드라이버 버전이 맞지 않습니다. 시스템 재 부팅 후에 새로 실행 시켜 주십시오.
+nProtect KeyCrypt not the same. Please restart the program and the computer first.
+*/
+ MSG_NPK_ERROR_DRIVERVERSION = 0x58c,
+/*20090204 to latest
+WindowXP 호환성 모드를 사용하고 계십니다. 현재 프로그램에서 호환성 모드를 제거하였습니다. 프로그램을 새로 시작해 주십시오.
+Currently wearing WindowXP Compatibility Mode. The program now removes Compatibility Mode. Please restart the program.
+*/
+ MSG_NPK_ERROR_VERIFYVERSION = 0x58d,
+/*20090204 to latest
+PS/2 키로거가 존재합니다.
+PS/2 keyloggers exist.
+*/
+ MSG_DETECT_PS2KEYLOGGER = 0x58e,
+/*20090204 to latest
+USB 키보드 드라이버 해킹 시도가 탐지되었습니다.
+USB Keylogging attempt was detected.
+*/
+ MSG_DETECT_USBKEYLOGGER = 0x58f,
+/*20090204 to latest
+HHD 모니터링 툴이 탐지되었습니다.
+HHD monitoring tool has been detected.
+*/
+ MSG_DETECT_HHDUSBH = 0x590,
+/*20090204 to latest
+페인트붓이 필요합니다.
+Paintbrush is required.
+*/
+ MSG_USESKILL_FAIL_PAINTBRUSH = 0x591,
+/*20090204 to 20090401
+그림물감이 필요합니다.
+20090408 to latest
+서페이스페인트가 필요합니다.
+Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_SURFACE_PAINTS = 0x592,
+/*20090204 to latest
+지정한 위치에 스킬을 사용할수 없습니다.
+Use the skills that are not at the specified location.
+*/
+ MSG_USESKILL_FAIL_POS = 0x593,
+/*20090204 to latest
+도우미의 SP가 부족합니다.
+Not enough SP.
+*/
+ MSG_USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 0x594,
+#endif
+#if PACKETVER >= 20090211
+/*20090211 to 20090218
+생성 가능 캐릭터 수는 9개입니다!!(임시)
+20090225 to latest
+캐릭터 선택창의 캐릭터가 %d개를 초과하면 게임에 접속할 수 없습니다. 불필요한 캐릭터를 삭제해주십시오.
+Character %d is character selection window cannot connect to the game that exceeds the total. Please remove unwanted characters.
+*/
+ MSG_BAN_OVER_CHARACTER_LIST = 0x595,
+#endif
+#if PACKETVER >= 20090225
+/*20090225 to latest
+목캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_NECK_CANDY = 0x596,
+/*20090225 to latest
+안타까운눈물이 필요합니다.
+Painful Tears is required.
+*/
+ MSG_USESKILL_FAIL_II_MISERABLE_TEAR = 0x597,
+/*20090225 to latest
+목 보호 캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_PROTECT_NECK_CANDY = 0x598,
+/*20090225 to latest
+웨폰 블로킹의 연계로만 사용가능합니다.
+Cooperation is only available with Weapon Blocking.
+*/
+ MSG_USESKILL_FAIL_GC_WEAPONBLOCKING = 0x599,
+/*20090225 to latest
+길로틴크로스의 독을 바른 무기가 필요합니다.
+Poisoned weapons is required.
+*/
+ MSG_USESKILL_FAIL_GC_POISONINGWEAPON = 0x59a,
+#endif
+#if PACKETVER >= 20090304
+/*20090304 to latest
+마도기어 탑승시에만 사용가능합니다.
+Item can only be used when Mado Gear is mounted.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR = 0x59b,
+/*20090304 to latest
+발칸블릿이 필요합니다.
+Vulcan Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_VULCANBULLET = 0x59c,
+/*20090304 to latest
+마도기어 연료가 필요합니다.
+Mado Gear Fuel is required.
+*/
+ MSG_USESKILL_FAIL_II_FUELGAS = 0x59d,
+/*20090304 to latest
+액체냉각탄이 필요합니다.
+Liquid Cold Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_COLDSLOWERBULLET = 0x59e,
+/*20090304 to latest
+캐논볼을 장전 하세요.
+Please load a Cannon Ball.
+*/
+ MSG_USESKILL_FAIL_CANONBALL = 0x59f,
+/*20090304 to latest
+미도기어 가속장치를 착용하세요.
+Please equipped with a Mado Gear Accelerator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 0x5a0,
+/*20090304 to latest
+호버링부스터를 착용하세요.
+Please equipped with a Hovering Booster.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 0x5a1,
+/*20090304 to latest
+[톡신] 독 효과가 무기에 적용되었습니다.
+[Toxin] Poison effect was applied to the weapon.
+*/
+ MSG_TOXIN = 0x5a2,
+/*20090304 to latest
+[패럴라이즈] 독 효과가 무기에 적용되었습니다.
+[Paralysis] Poison effect was applied to the weapon.
+*/
+ MSG_PARALYZE = 0x5a3,
+/*20090304 to latest
+[베놈블리드] 독 효과가 무기에 적용되었습니다.
+[Fatigue] Poison effect was applied to the weapon.
+*/
+ MSG_VENOMBLEED = 0x5a4,
+/*20090304 to latest
+[매직 머쉬룸] 독 효과가 무기에 적용되었습니다.
+[Laughing] Poison effect was applied to the weapon.
+*/
+ MSG_MAGICMUSHROOM = 0x5a5,
+/*20090304 to latest
+[데스 허트] 독 효과가 무기에 적용되었습니다.
+[Disheart] Poison effect was applied to the weapon.
+*/
+ MSG_DEATHHURT = 0x5a6,
+/*20090304 to latest
+[파이렉시아] 독 효과가 무기에 적용되었습니다.
+[Pyrexia] Poison effect was applied to the weapon.
+*/
+ MSG_PHYREXIA = 0x5a7,
+/*20090304 to latest
+[오블리비언 커즈] 독 효과가 무기에 적용되었습니다.
+[Oblivion] Poison effect was applied to the weapon.
+*/
+ MSG_OBLIANCURSE = 0x5a8,
+/*20090304 to latest
+[리치 엔드] 독 효과가 무기에 적용되었습니다.
+[Leech] Poison effect was applied to the weapon.
+*/
+ MSG_RICHEND = 0x5a9,
+#endif
+#if PACKETVER >= 20090311
+/*20090311 to latest
+호버링상태에서만 사용가능합니다.
+Can only be used in Hovering state.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_HOVERING = 0x5aa,
+/*20090311 to latest
+자폭장치를 장착하세요.
+Please equip a Self-Destruct Mechanism.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 0x5ab,
+/*20090311 to latest
+셰이프쉬프터를 장착하세요.
+Please equip a Shape Shift.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 0x5ac,
+/*20090311 to latest
+길로틴독이 필요합니다.
+Guillotine Cross Poison is required.
+*/
+ MSG_USESKILL_FAIL_GUILLONTINE_POISON = 0x5ad,
+/*20090311 to latest
+냉각장치를 장착하세요.
+Please equipped with a Cooling System.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 0x5ae,
+/*20090311 to latest
+자기장필드생성기를 착용하세요.
+Please equipped with a Magnetic Field Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 0x5af,
+/*20090311 to latest
+베리어생성기를 착용하세요.
+Please equipped with a Barrier Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 0x5b0,
+/*20090311 to latest
+광학미채발생기를 착용하세요.
+Please equipped with a Optical Camouflage Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 0x5b1,
+/*20090311 to latest
+리페어키트를 착용하세요.
+Please equipped with a Repair Kit.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 0x5b2,
+/*20090311 to latest
+몽키 스패너가 필요합니다.
+Monkey Wrench is required.
+*/
+ MSG_USESKILL_FAIL_II_MONKEY_SPANNER = 0x5b3,
+#endif
+#if PACKETVER >= 20090318
+/*20090318 to latest
+[%s] 스킬을 시전 할 수 없습니다.
+[%s] Cannot use the skills due to cooldown delay.
+*/
+ MSG_SKILLINTERVAL2 = 0x5b4,
+/*20090318 to latest
+%d레벨 이상은 삭제가 불가능합니다.
+Deletion is impossible for over level %d
+*/
+ MSG_LEMIT_DELETE_LEVEL = 0x5b5,
+/*20090318 to latest
+마도기어 탑승시에는 사용할수 없습니다.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_RIDE = 0x5b6,
+#endif
+#if PACKETVER >= 20090320
+/*20090320 to latest
+드래곤 내리기
+Dismount Dragon
+*/
+ MSG_DRAGONOFF = 0x5b7,
+/*20090320 to latest
+마도기어 내리기
+Dismount Magic Gear
+*/
+ MSG_MADOOFF = 0x5b8,
+#endif
+#if PACKETVER >= 20090330
+/*20090330 to latest
+소비
+I
+*/
+ MSG_STORE_TABNAME_0 = 0x5b9,
+/*20090330 to latest
+캐쉬
+Cash
+*/
+ MSG_STORE_TABNAME_1 = 0x5ba,
+/*20090330 to latest
+방어구
+Armors
+*/
+ MSG_STORE_TABNAME_2 = 0x5bb,
+/*20090330 to latest
+무기
+Weapons
+*/
+ MSG_STORE_TABNAME_3 = 0x5bc,
+/*20090330 to latest
+투사체
+Ammo
+*/
+ MSG_STORE_TABNAME_4 = 0x5bd,
+/*20090330 to latest
+카드
+Card
+*/
+ MSG_STORE_TABNAME_5 = 0x5be,
+/*20090330 to latest
+기타
+Other
+*/
+ MSG_STORE_TABNAME_6 = 0x5bf,
+#endif
+#if PACKETVER >= 20090401
+/*20090401 to latest
+클라이언트 응답시간이 초과되어 연결이 끊어집니다.
+Client response time has passed so connection is terminated
+*/
+ MSG_ERROR_HS_TIMEOUT = 0x5c0,
+/*20090401 to latest
+핵쉴드 파일의 버전이 맞지 않습니다. 클라이언트를 재설치 해주십시오.
+Incorrect version of hack shield file. Please reinstall the client
+*/
+ MSG_ERROR_DIFF_CLIENT = 0x5c1,
+#endif
+#if PACKETVER >= 20090408
+/*20090408 to latest
+마법서가 필요합니다.
+[Magic Book] is required.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK = 0x5c2,
+/*20090408 to latest
+마법서가 너무 어려워서 졸음이 몰려온다.
+Feel sleepy since Magic Book is too difficult to understand.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 0x5c3,
+/*20090408 to latest
+보존포인트가 부족합니다.
+Not enough saved point.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 0x5c4,
+/*20090408 to latest
+더이상 마법서를 읽을수 없습니다.
+Can't read a Magic Book anymore.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_READING = 0x5c5,
+/*20090408 to latest
+페이스페인트가 필요합니다.
+Face Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_FACE_PAINTS = 0x5c6,
+/*20090408 to latest
+분장용붓이 필요합니다.
+Brush is required.
+*/
+ MSG_USESKILL_FAIL_II_MAKEUP_BRUSH = 0x5c7,
+/*20090408 to latest
+대기 시간이 초과하였습니다. 다시 로그인 해주십시오.
+Waiting time has passed. Please log in again
+*/
+ MSG_MOBILE_TIMEOVER = 0x5c8,
+/*20090408 to latest
+위험! 이미 동일한 계정이 로그인 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is already logged in. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_ANOTHER_LOGIN = 0x5c9,
+/*20090408 to latest
+위험! 현재 동일한 계정이 모바일 인증 대기 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is waiting for mobile verification. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_WAITING_STATE = 0x5ca,
+#endif
+#if PACKETVER >= 20090506
+/*20090506 to latest
+게임 옵션창
+Game setting window
+*/
+ MSG_ESC_OPTIONWND = 0x5cb,
+/*20090506 to latest
+그래픽 설정
+Graphics Settings
+*/
+ MSG_GRAPHIC_OPTIONWND = 0x5cc,
+/*20090506 to latest
+사운드 설정
+Sound Settings
+*/
+ MSG_SOUND_OPTIONWND = 0x5cd,
+#endif
+#if PACKETVER >= 20090514
+/*20090514 to latest
+변경 할 단축키를 누르거나, 'ESC'키를 눌러 삭제 해 주세요.
+Press a key to assign. Pressing 'ESC' will remove the assigned key.
+*/
+ MSG_HOTKEYWND_NOTICE1 = 0x5ce,
+/*20090514 to latest
+단일 키로 지정 할 수 없는 키입니다.
+Unable to specify a single key.
+*/
+ MSG_HOTKEYWND_NOTICE2 = 0x5cf,
+/*20090514 to latest
+지정 할 수 없는 키입니다.
+Unable to specify the key assigned.
+*/
+ MSG_HOTKEYWND_NOTICE3 = 0x5d0,
+/*20090514 to latest
+'%s'에 사용된 단축키와 중복됩니다. 바꾸시겠습니까?
+Duplicated with ['%s']. Do you still want to change?
+*/
+ MSG_HOTKEYWND_NOTICE4 = 0x5d1,
+/*20090514 to latest
+저장된 단축키 조합이 초기화 됩니다. 초기화 하시겠습니까?
+Initialization is stored in the shortcut key settings. Do you want to initialized?
+*/
+ MSG_HOTKEYWND_NOTICE5 = 0x5d2,
+/*20090514 to latest
+스킬바
+Skill Bar
+*/
+ MSG_HOTKEYWND_TAB1 = 0x5d3,
+/*20090514 to latest
+인터페이스
+Interface
+*/
+ MSG_HOTKEYWND_TAB2 = 0x5d4,
+/*20090514 to latest
+이모션
+Macros
+*/
+ MSG_HOTKEYWND_TAB3 = 0x5d5,
+/*20090514 to latest
+단축키 설정 창
+Shortcut Settings
+*/
+ MSG_HOTKEYWND_TITLE = 0x5d6,
+#endif
+#if PACKETVER >= 20090520
+/*20090520 to latest
+배경음
+BGM
+*/
+ MSG_BGM = 0x5d7,
+/*20090520 to latest
+효과음
+Effect
+*/
+ MSG_SOUND = 0x5d8,
+/*20090520 to latest
+스킨
+Skin
+*/
+ MSG_SKIN = 0x5d9,
+/*20090520 to latest
+채팅방 입장음만 소리남 On
+Chat room entrance sound on
+*/
+ MSG_TINGONLY_ON = 0x5da,
+/*20090520 to latest
+채팅방 입장음만 소리남 Off
+Chat room entrance sound off
+*/
+ MSG_TINGONLY_OFF = 0x5db,
+/*20090520 to latest
+/tingonly : 채팅방 입장음만 들을수있게됩니다
+/tingonly: you can hear only sound like a chat room entry.
+*/
+ MSG_EXPLAIN_TINGONLY = 0x5dc,
+/*20090520 to latest
+/주먹
+/rock
+*/
+ MSG_EMOTION_ROCK = 0x5dd,
+/*20090520 to latest
+/가위
+/scissors
+*/
+ MSG_EMOTION_SCISSOR = 0x5de,
+/*20090520 to latest
+/보
+/paper
+*/
+ MSG_EMOTION_WRAP = 0x5df,
+/*20090520 to latest
+/러브
+/love
+*/
+ MSG_EMOTION_LUV = 0x5e0,
+/*20090520 to latest
+/mobile
+*/
+ MSG_EMOTION_MOBILE = 0x5e1,
+/*20090520 to latest
+/mail
+*/
+ MSG_EMOTION_MAIL = 0x5e2,
+/*20090520 to latest
+/antenna0
+*/
+ MSG_EMOTION_ANTENNA0 = 0x5e3,
+/*20090520 to latest
+/antenna1
+*/
+ MSG_EMOTION_ANTENNA1 = 0x5e4,
+/*20090520 to latest
+/antenna2
+*/
+ MSG_EMOTION_ANTENNA2 = 0x5e5,
+/*20090520 to latest
+/antenna3
+*/
+ MSG_EMOTION_ANTENNA3 = 0x5e6,
+/*20090520 to latest
+/hum
+*/
+ MSG_EMOTION_HUM2 = 0x5e7,
+/*20090520 to latest
+/abs
+*/
+ MSG_EMOTION_ABS = 0x5e8,
+/*20090520 to latest
+/oops
+*/
+ MSG_EMOTION_OOPS = 0x5e9,
+/*20090520 to latest
+/spit
+*/
+ MSG_EMOTION_SPIT = 0x5ea,
+/*20090520 to latest
+/ene
+*/
+ MSG_EMOTION_ENE = 0x5eb,
+/*20090520 to latest
+/panic
+*/
+ MSG_EMOTION_PANIC = 0x5ec,
+/*20090520 to latest
+/whisp
+*/
+ MSG_EMOTION_WHISP = 0x5ed,
+#endif
+#if PACKETVER >= 20090527
+/*20090527 to latest
+지정안함
+Not Assigned
+*/
+ MSG_HOTKEY_NOTHING = 0x5ee,
+#endif
+#if PACKETVER >= 20090603
+/*20090603 to latest
+카트장착시에만 사용가능합니다.
+Only available when cart is mounted.
+*/
+ MSG_USESKILL_FAIL_CART = 0x5ef,
+/*20090603 to latest
+[가시나무 씨앗]이 필요합니다.
+[Thorny Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_THORNS_SEED = 0x5f0,
+/*20090603 to latest
+[흡혈 식물 씨앗]이 필요합니다.
+[Bloodsucker Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 0x5f1,
+/*20090603 to latest
+더이상 시전할수 없습니다.
+Cannot be used anymore.
+*/
+ MSG_USESKILL_FAIL_NO_MORE_SPELL = 0x5f2,
+/*20090603 to latest
+[폭탄버섯포자]가 필요합니다.
+[Bomb Mushroom Spore] is required.
+*/
+ MSG_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 0x5f3,
+/*20090603 to latest
+[화염병]이 필요합니다.
+[Fire Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_GASOLINE_BOOMB = 0x5f4,
+/*20090603 to latest
+[기름병]이 필요합니다.
+[Oil Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_OIL_BOTTLE = 0x5f5,
+/*20090603 to latest
+[폭발가루]가 필요합니다.
+[Explosive Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_EXPLOSION_POWDER = 0x5f6,
+/*20090603 to latest
+[연막가루]가 필요합니다.
+[Smokescreen Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_SMOKE_POWDER = 0x5f7,
+/*20090603 to latest
+[최루가스]가 필요합니다.
+[Tear Gas] is required.
+*/
+ MSG_USESKILL_FAIL_II_TEAR_GAS = 0x5f8,
+/*20090603 to latest
+[염산병]이 필요합니다.
+[Acid Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 0x5f9,
+/*20090603 to latest
+[식인식물병]이 필요합니다.
+[Bottom Man-Eating Plant] is required.
+*/
+ MSG_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 0x5fa,
+/*20090603 to latest
+[만드라고라의 화분]이 필요합니다.
+[Pot of Mandragora] is required.
+*/
+ MSG_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 0x5fb,
+/*20090603 to latest
+파티장 위임
+Party delegation
+*/
+ MSG_YIELD_PARTYMASTER = 0x5fc,
+/*20090603 to latest
+정말 파티장을 위임하시겠습니까?
+Do you want to delegate the real party?
+*/
+ MSG_DO_YOU_REALLY_WANT_YIELD_PARTYMASTER = 0x5fd,
+/*20090603 to latest
+파티장을 위임 할 수 없습니다.
+Party cannot be delegated.
+*/
+ MSG_CANNOT_YIELD_PARTYMASTER = 0x5fe,
+/*20090603 to latest
+변경불가
+Immutable
+*/
+ MSG_FAILED_CHANGE = 0x5ff,
+#endif
+#if PACKETVER >= 20090610
+/*20090610 to latest
+[%s]가 %d개 필요합니다.
+[%s] required '%d' amount.
+*/
+ MSG_USESKILL_FAIL_NEED_ITEM = 0x600,
+/*20090610 to latest
+제련 수치가 하향 조정 되었습니다.
+Is now refining the value lowered.
+*/
+ MSG_ITEM_REFINING_DOWNGRADE = 0x601,
+/*20090610 to latest
+[%s]를 장비하고 있어야 사용할 수 있습니다
+Need to put on [%s] in order to use.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT = 0x602,
+#endif
+#if PACKETVER >= 20090617
+/*20090617 to latest
+전장 리스트
+*/
+ MSG_BATTLEFIELD_LIST = 0x603,
+/*20090617 to latest
+전장 - [%s] 신청 하시겠습니까?
+*/
+ MSG_CANNOT_JOINTO_BATTLEFIELD = 0x604,
+/*20090617 to latest
+전장 - [%s] 입장 신청이 완료되었습니다.
+*/
+ MSG_COMPLETED_JOINTO_BATTLEFIELD = 0x605,
+/*20090617 to latest
+전장 - [%s] 입장 하실 수 없습니다.
+*/
+ MSG_DIFFER_JOINTO_BATTLEFIELD = 0x606,
+/*20090617 to latest
+현재 입장 신청 상태입니다.
+*/
+ MSG_STATUS_JOINTO_BATTLEFIELD = 0x607,
+/*20090617 to latest
+입장 신청을 취소하시겠습니까?
+*/
+ MSG_REQ_CANCEL_JOINTO_BATTLEFIELD = 0x608,
+/*20090617 to latest
+전장 - [%s] 입장 신청이 취소되었습니다.
+*/
+ MSG_CANCEL_JOINTO_BATTLEFIELD = 0x609,
+/*20090617 to latest
+곧 전장으로 이동 합니다.
+*/
+ MSG_MOVETO_BATTLEFIELD = 0x60a,
+/*20090617 to latest
+전장 - [%s]
+*/
+ MSG_BATTLEFIELD_NAME = 0x60b,
+#endif
+
+};
+#endif /* MAP_MESSAGES_SAK_H */
diff --git a/src/map/messages_zero.h b/src/map/messages_zero.h
new file mode 100644
index 000000000..babe9384c
--- /dev/null
+++ b/src/map/messages_zero.h
@@ -0,0 +1,18706 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_MESSAGES_ZERO_H
+#define MAP_MESSAGES_ZERO_H
+
+/* This file is autogenerated, please do not commit manual changes
+
+Latest version: 20200304
+*/
+
+enum clif_messages {
+/*20171018 to latest
+동의 하십니까?
+Do you agree?
+*/
+ MSG_DO_YOU_AGREE = 0x0,
+/*20171018 to latest
+서버 연결 실패
+Failed to Connect to Server.
+*/
+ MSG_SERVER_CONNECTION_FAILED = 0x1,
+/*20171018 to latest
+서버와 연결이 끊어졌습니다.
+Disconnected from Server.
+*/
+ MSG_UNABLE_TO_CONNECT_SERVER = 0x2,
+/*20171018 to latest
+서버와 연결이 끊어졌습니다!
+Disconnected from Server!
+*/
+ MSG_BANNED = 0x3,
+/*20171018 to latest
+서버 종료됨
+Server Closed.
+*/
+ MSG_SERVER_OFF = 0x4,
+/*20171018 to latest
+같은 계정으로 다른 사용자가 로그인 하였습니다.
+Someone has Logged in with this ID.
+*/
+ MSG_DOUBLE_LOGIN_PROHIBITED = 0x5,
+/*20171018 to latest
+등록되지 않은 계정입니다. 다시 확인 바랍니다.
+Unregistered ID. Please make sure you have a registered account and you have correctly typed in the user ID.
+*/
+ MSG_INCORRECT_USERID = 0x6,
+/*20171018 to latest
+입력하신 비밀번호가 올바르지 않습니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_PASSWORD = 0x7,
+/*20171018 to latest
+본 ID 는 사용기간이 만료 되었습니다
+This ID is expired.
+*/
+ MSG_ID_EXPIRED = 0x8,
+/*20171018 to latest
+서버 접근 거부
+Rejected from Server.
+20171117 to 20171117
+2017년 11월 20일 11:00 부터 접속이 가능합니다.
+*/
+ MSG_ACCESS_DENIED = 0x9,
+/*20171018 to latest
+같은 캐릭터 이름이 있습니다.
+Character Name already exists.
+*/
+ MSG_CHARACTER_NAME_ALREADY_EXISTS = 0xa,
+/*20171018 to latest
+캐릭터 생성 거부됨
+Character Creation is denied.
+*/
+ MSG_CHARACTER_CREATION_DENIED = 0xb,
+/*20171018 to latest
+캐릭터 삭제 거부
+Character Deletion is denied.
+*/
+ MSG_CANNOT_DELETE_CHARACTER = 0xc,
+/*20171018 to latest
+방제목를 입력하세요.
+Please Enter Room Title.
+*/
+ MSG_ENTER_ROOM_TITLE = 0xd,
+/*20171018 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_SENTANGE = 0xe,
+/*20171018 to latest
+암호를 입력하세요.
+Please enter Password.
+*/
+ MSG_ENTER_PASSWORD = 0xf,
+/*20171018 to latest
+암호를 영문 4자 이상 입력하세요.
+Please enter Password. Passwords must be at least 4 characters long.
+*/
+ MSG_Enter_Password_more_than_4_char = 0x10,
+/*20171018 to latest
+종료 하시겠습니까?
+Are you sure that you want to quit?
+*/
+ MSG_DO_YOU_REALLY_WANT_TO_QUIT = 0x11,
+/*20171018 to latest
+4자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Passwords are at least 4 characters long. Please try again.
+*/
+ MSG_NAME_MUST_EXCEED_4_CHAR = 0x12,
+/*20171018 to latest
+한 번 삭제된 캐릭터 및 관련 정보는 다시 복구되지 않습니다. 캐릭터를 삭제하시겠습니까?
+Are you sure that you want to delete this character?
+*/
+ MSG_DELETE_CHARACTER = 0x13,
+/*20171018 to latest
+불량단어가 검출되었습니다.
+Foul Language Detected.
+*/
+ MSG_BAD_NAME = 0x14,
+/*20171018 to latest
+이름을 입력해 주세요.(한글 2자 영문 4자 이상)
+Character Name must be at least 4 characters long.
+*/
+ MSG_ENTER_NAME_MORE_THAN_4_CHAR = 0x15,
+/*20171018 to latest
+명령어 일람: /h
+Command List: /h | /help
+*/
+ MSG_LIST_COMMAND = 0x16,
+/*20171018 to latest
+이펙트 On
+Effects On
+*/
+ MSG_EFFECT_ON = 0x17,
+/*20171018 to latest
+이펙트 Off
+Effects Off
+*/
+ MSG_EFFECT_OFF = 0x18,
+/*20171018 to latest
+사운드 볼륨
+Sound Volume
+*/
+ MSG_VOLUME_OF_SOUND = 0x19,
+/*20171018 to latest
+배경음악 볼륨
+BGM Volume
+*/
+ MSG_VOLUME_OF_BGM = 0x1a,
+/*20171018 to latest
+효과음 On
+Sound Effects On
+*/
+ MSG_SOUND_ON = 0x1b,
+/*20171018 to latest
+효과음 Off
+Sound Effects Off
+*/
+ MSG_SOUND_OFF = 0x1c,
+/*20171018 to latest
+프레임스킵 On
+Frame Skip On
+*/
+ MSG_FRAME_SKIP_ON = 0x1d,
+/*20171018 to latest
+프레임스킵 Off
+Frame Skip Off
+*/
+ MSG_FRAME_SKIP_OFF = 0x1e,
+/*20171018 to latest
+배경음악 On
+BGM On
+*/
+ MSG_BGM_ON = 0x1f,
+/*20171018 to latest
+배경음악 Off
+BGM Off
+*/
+ MSG_BGM_OFF = 0x20,
+/*20171018 to latest
+/h or /help: 명령어 일람
+/h or /help: Shows this Command Help List
+*/
+ MSG_EXPLAIN_HELP = 0x21,
+/*20171018 to latest
+/w or /who or /접속자 or /누구: 현재 접속자수 보기
+/w or /who or /player or /who: wiew current the number of player
+*/
+ MSG_EXPLAIN_WHO = 0x22,
+/*20171018 to latest
+/음악 : 배경음악 On Off
+/music: Turns BGM On or Off
+*/
+ MSG_EXPLAIN_MUSIC = 0x23,
+/*20171018 to latest
+/효과음 : 효과음 On Off
+/sound: Turns Sound Effects On or Off
+*/
+ MSG_EXPLAIN_SOUND = 0x24,
+/*20171018 to latest
+/이펙트 : 이펙트 On Off
+/effect: Effects On or Off
+*/
+ MSG_EXPLAIN_EFFECT = 0x25,
+/*20171018 to latest
+/좌표 or /장소: 현재 위치 표시
+/where: Shows your present location
+*/
+ MSG_EXPLAIN_POS = 0x26,
+/*20171018 to latest
+/skip : 프래임스킵 On Off
+/skip: Turns Frame Skip On or Off
+*/
+ MSG_EXPLAIN_FRAMESKIP = 0x27,
+/*20171018 to latest
+/v (0~127): 효과음 볼륨조정
+/v (0~127): Controls the volume of the Sound Effects
+*/
+ MSG_EXPLAIN_SOUNDVOLUME = 0x28,
+/*20171018 to latest
+/bv (0~127): 배경음악 볼륨조정
+/bv (0~127): Controls the volume of the BGM
+*/
+ MSG_EXPLAIN_BGMVOLUME = 0x29,
+/*20171018 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당캐릭터에 대해 귓말차단
+/ex (Character Name): Blocks whispering from the Character
+*/
+ MSG_EXPLAIN_SAYISOLATION = 0x2a,
+/*20171018 to latest
+/ex or /차단 : 귓말차단 캐릭터 리스트
+/ex: View a list of Characters you have Blocked
+*/
+ MSG_EXPLAIN_LIST_SAYISOLATION_CHAR = 0x2b,
+/*20171018 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당캐릭터에 대해 귓말허용
+/in (Character Name): Allows whispering from the Character
+*/
+ MSG_EXPLAIN_SAY_PERMIT = 0x2c,
+/*20171018 to latest
+/inall or /해제전부 : 모두에게 귓말허용
+/inall: Allows whispers from anyone
+*/
+ MSG_EXPLAIN_SAY_PERMITALL = 0x2d,
+/*20171018 to latest
+/exall or /차단전부 : 모두에게 귓말차단
+/exall: Blocks whispers from everyone
+*/
+ MSG_EXPLAIN_SAY_ISOLATEALL = 0x2e,
+/*20171018 to latest
+다른유저 캐릭터를 마우스 오른버튼을 누르고 있는 상태에서 왼버튼으로 클릭하면 그캐릭터이름이 귓말콤보박스에 저장됩니다.
+Right click on a character and select [Register as a Friend] to add a person to your Friend List.
+*/
+ MSG_EXPLAIN_TIP1 = 0x2f,
+/*20171018 to latest
+단축아이탬창(F12) 소비장비 아이템을 드래그한후 사용하세요. 사용키(F1F2F3F4F5F6F7F8F9)
+F12 Brings up a Hotkey Window which allows you to drag and drop Recovery Items, Equipment and Skills into it for faster access.
+*/
+ MSG_EXPLAIN_TIP2 = 0x30,
+/*20171018 to latest
+같은말을 3번이상 연속해서 전송할 수 없습니다.
+You can't type the same word/phrase more than 3 times.
+*/
+ MSG_NO_SAME_SENTANCE = 0x31,
+/*20171018 to latest
+불량단어 검출로 전송이 중단 되었습니다.
+Chat Filter: Yeah, uh, I don't think so buddy...
+*/
+ MSG_NO_SEND_BECAUSE_INSULT = 0x32,
+/*20171018 to latest
+같은아이템은 한번만 올릴수 있습니다.
+You cannot overlap items on a window.
+*/
+ MSG_CAN_DRAG_ITEM_OLNY_ONETIME = 0x33,
+/*20171018 to latest
+무게가 초과하여 아이템을 가질 수 없습니다.
+You cannot carry more items because you are overweight.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_WEIGHT = 0x34,
+/*20171018 to latest
+아이템을 가질 수 없습니다.
+You cannot get the item.
+*/
+ MSG_CANT_GET_ITEM = 0x35,
+/*20171018 to latest
+거래가 잘 이루어졌습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SECCESS = 0x36,
+/*20171018 to latest
+돈이 부족합니다.
+You do not have enough zeny.
+*/
+ MSG_INSUFFICIENT_MONEY = 0x37,
+/*20171018 to latest
+무게가 초과 되었습니다.
+You are over your Weight Limit.
+*/
+ MSG_OVER_WEIGHT = 0x38,
+/*20171018 to latest
+거래가 실패 했습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAIL = 0x39,
+/*20171018 to latest
+모두에게 귓말거부상태로됨
+You've blocked whispers from everyone.
+*/
+ MSG_REFUSE_HEAR_ALL = 0x3a,
+/*20171018 to latest
+모두에게 귓말거부요청 실패함
+You've failed to block all whispers.
+*/
+ MSG_REQ_REFUSE_HEAR_ALL_FAIL = 0x3b,
+/*20171018 to latest
+모두에게 귓말가능상태가됨
+You've allowed whispers from everyone.
+*/
+ MSG_HEAR_ALL = 0x3c,
+/*20171018 to latest
+모두에게 귓말가능요청 실패함
+You've failed to allow all whispers.
+*/
+ MSG_REQ_HEAR_ALL_FAIL = 0x3d,
+/*20171018 to latest
+귓말 거부 리스트가 없습니다
+You have no Block List.
+*/
+ MSG_NO_REFUSE_HEAR_LIST = 0x3e,
+/*20171018 to latest
+-귓말 거부 리스트-
+[ Character Block List ]
+*/
+ MSG_REFUSE_HEAR_LIST = 0x3f,
+/*20171018 to latest
+방이 잘 만들어 졌습니다.
+Room has been successfully created.
+*/
+ MSG_ROOM_IS_MADE = 0x40,
+/*20171018 to latest
+방갯수가 허용갯수를 초과 하였습니다.
+Room Limit Exceeded.
+*/
+ MSG_TOO_MANY_ROOM = 0x41,
+/*20171018 to latest
+같은 방제목이 있습니다.
+Same Room exists.
+*/
+ MSG_SAME_ROOM_TITLE = 0x42,
+/*20171018 to latest
+인원초과로 방에 들어갈 수 없습니다.
+The Room is full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_ROOM = 0x43,
+/*20171018 to latest
+강제로 퇴장된 방입니다.
+You have been kicked out of this room.
+*/
+ MSG_YOU_HAVE_BANNED_FROM_THE_ROOM = 0x44,
+/*20171018 to latest
+교환요청을 거절 했습니다.
+The deal has been rejected.
+*/
+ MSG_REJECT_DEAL = 0x45,
+/*20171018 to latest
+교환가능거리를 벗어났습니다.
+You are too far away from the person to trade.
+*/
+ MSG_TOO_FAR_TO_DEAL = 0x46,
+/*20171018 to latest
+해당 캐릭터가 없습니다.
+The Character is not currently online or does not exist.
+*/
+ MSG_CHARACTER_IS_NOT_EXIST = 0x47,
+/*20171018 to latest
+다른캐릭터와 교환중입니다.
+The person is in another deal.
+*/
+ MSG_CHARACTER_IS_DEALING = 0x48,
+/*20171018 to latest
+상대 캐릭터 중량초과로 올려놓을 수 없습니다.
+You cannot trade because this character will exceed his weight limit.
+*/
+ MSG_CHARACTER_IS_OVER_WEIGHT = 0x49,
+/*20171018 to latest
+거래가 취소 되었습니다.
+The deal has been canceled.
+*/
+ MSG_DEAL_IS_CANCELED = 0x4a,
+/*20171018 to latest
+아이템 교환이 잘 되었습니다.
+The deal has successfully completed.
+*/
+ MSG_DEAL_SUCCESS = 0x4b,
+/*20171018 to latest
+아이템 교환이 실패 하였습니다.
+The deal has failed.
+*/
+ MSG_DEAL_FAILED = 0x4c,
+/*20171018 to latest
+파티가 만들어졌습니다.
+Party has successfully been organized.
+*/
+ MSG_PARTY_MAKE_SUCCEED = 0x4d,
+/*20171018 to latest
+같은 파티이름이 있습니다.
+That Party Name already exists.
+*/
+ MSG_SAME_PARTY_NAME = 0x4e,
+/*20171018 to latest
+이미 파티에 속해있습니다.
+The Character is already in a party.
+*/
+ MSG_YOU_ARE_ALREADY_IN_PARTY = 0x4f,
+/*20171018 to latest
+다른파티에 가입되어 있습니다.
+The Character already joined another party.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_PARTY = 0x50,
+/*20171018 to latest
+파티가입을 거부했습니다.
+Request for party rejected.
+*/
+ MSG_CHARACTER_REJECT_JOIN = 0x51,
+/*20171018 to latest
+파티가입을 수락했습니다.
+Request for party accepted.
+*/
+ MSG_CHARACTER_ACCEPT_JOIN = 0x52,
+/*20171018 to latest
+파티정원을 초과했습니다.
+Party Capacity exceeded.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_PARTY = 0x53,
+/*20171018 to latest
+파티에서 탈퇴하였습니다.
+You left the party.
+*/
+ MSG_YOU_LEAVE_FROM_PARTY = 0x54,
+/*20171018 to latest
+전체에게 보냄
+Send to All
+*/
+ MSG_SEND_TO_ALL = 0x55,
+/*20171018 to latest
+파티에게 보냄
+Send to Party
+*/
+ MSG_SEND_TO_PARTY = 0x56,
+/*20171018 to latest
+님과의 거래요청
+Request a deal with %s
+*/
+ MSG_REQ_DEAL_WITH = 0x57,
+/*20171018 to latest
+님 파티에 가입요청
+Ask %s to join your party
+*/
+ MSG_REQ_JOIN_PARTY = 0x58,
+/*20171018 to latest
+비공개 :
+Pri:
+*/
+ MSG_ROOM_PRIVATE = 0x59,
+/*20171018 to latest
+공개 :
+Pub:
+*/
+ MSG_ROOM_PUBLIC = 0x5a,
+/*20171018 to latest
+마지막 체크지점부터 시작하려면 '재시작'을 캐릭터 선택으로 돌아가려면 '종료'를 눌러주세요.
+Click ''Restart'' to go back to your save point or click ''Exit'' to select another character.
+*/
+ MSG_RESTART_MSG = 0x5b,
+/*20171018 to latest
+원하는 거래를 선택하세요.
+Please select a Deal Type.
+*/
+ MSG_SELECT_DEAL_TYPE = 0x5c,
+/*20171018 to latest
+님이 거래를 요청했습니다.
+ requests a deal.
+*/
+ MSG_SUGGEST_DEAL = 0x5d,
+/*20171018 to latest
+ 파티에서 초청 메시지가 왔습니다. 합류하겠습니까?
+ Party has sent you an invitation. Would you like to join?
+*/
+ MSG_SUGGEST_JOIN_PARTY = 0x5e,
+/*20171018 to latest
+명령이 틀렸습니다.
+Invalid Command
+*/
+ MSG_INVALID_COMMAND = 0x5f,
+/*20171018 to latest
+탈퇴하기
+Leave party
+*/
+ MSG_LEAVE_PARTY = 0x60,
+/*20171018 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL = 0x61,
+/*20171018 to latest
+쪽지보내기
+Send Message
+*/
+ MSG_MSG = 0x62,
+/*20171018 to latest
+1:1 대화
+1:1 Chat
+*/
+ MSG_1ON1 = 0x63,
+/*20171018 to latest
+정보
+Information
+*/
+ MSG_CHARACTER_INFO = 0x64,
+/*20171018 to latest
+파티설정
+Party Setup
+*/
+ MSG_PARTY_SETTING = 0x65,
+/*20171018 to latest
+친구
+Friend
+*/
+ MSG_FRIEND = 0x66,
+/*20171018 to latest
+파티
+Party
+*/
+ MSG_PARTY = 0x67,
+/*20171018 to latest
+장착아이템
+Equipment
+*/
+ MSG_EQUIPED_ITEM = 0x68,
+/*20171018 to latest
+스테이터스
+Status
+*/
+ MSG_STATUS_ = 0x69,
+/*20171018 to latest
+소지아이템
+Inventory
+*/
+ MSG_ITEM = 0x6a,
+/*20171018 to latest
+/결성 [파티이름] : 파티결성 /탈퇴 : 파티탈퇴
+/organize ''Party Name'' To organize a party. Type /leave To leave a Party.
+*/
+ MSG_EXPLAIN_PARTY = 0x6b,
+/*20171018 to latest
+자신이 파티리더일때 캐릭터를 오른버튼으로 클릭하면 파티에 가입요청하기 메뉴가 뜹니다.
+If you are the party master, you can invite someone into your party by right-clicking on a Character.
+*/
+ MSG_EXPLAIN_TIP3 = 0x6c,
+/*20171018 to latest
+회복
+Consumables
+*/
+ MSG_RESTORE = 0x6d,
+/*20171018 to latest
+공격
+Attack
+*/
+ MSG_ATTACK = 0x6e,
+/*20171018 to latest
+보조
+Support
+*/
+ MSG_SUPPORT = 0x6f,
+/*20171018 to latest
+전체
+All
+*/
+ MSG_ALL = 0x70,
+/*20171018 to latest
+무기
+Weapons
+*/
+ MSG_WEAPON = 0x71,
+/*20171018 to latest
+방어
+Defense
+*/
+ MSG_DEFENCE = 0x72,
+/*20171018 to latest
+수
+Water
+*/
+ MSG_WATER = 0x73,
+/*20171018 to latest
+지
+Earth
+*/
+ MSG_EARTH = 0x74,
+/*20171018 to latest
+화
+Fire
+*/
+ MSG_FIRE = 0x75,
+/*20171018 to latest
+풍
+Wind
+*/
+ MSG_WIND = 0x76,
+/*20171018 to 20191008
+같은종류의 장비아이템은 한번에 한개만 살 수 있습니다.
+Please avoid buying 2 of the same items at one time.
+20191023 to latest
+같은 종류의 장비 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_EQUIPITEM_OLNY_ONE = 0x77,
+/*20171018 to latest
+창모드에서 실행 할때는 16비트 컬러로 맞춰주세요.
+Please change your desktop Color Depth to 16-bit when running Ragnarok in windowed mode.
+*/
+ MSG_ONLY_16BIT_WHEN_WINDOWMODE = 0x78,
+/*20171018 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_PLEASE_BE_PATIENT = 0x79,
+/*20171018 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_WAITING_RESPONSE_FROM_SERVER = 0x7a,
+/*20171018 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_MAKING_CHARACTER = 0x7b,
+/*20171018 to latest
+잠시만 기다려 주세요.
+Please wait...
+*/
+ MSG_DELETING_CHARACTER = 0x7c,
+/*20171018 to latest
+방 만들기
+Make a Room
+*/
+ MSG_MAKING_ROOM = 0x7d,
+/*20171018 to latest
+방셋팅 바꾸기
+Room Setup
+*/
+ MSG_CHANGE_ROOM_SETTING = 0x7e,
+/*20171018 to latest
+강퇴시키기
+Kick Character Out
+*/
+ MSG_BAN = 0x7f,
+/*20171018 to latest
+방장권한 주기
+Give Master Authority
+*/
+ MSG_GIVE_GIVE_ROOM_POWER = 0x80,
+/*20171018 to latest
+정보보기
+View Information
+*/
+ MSG_SEE_INFORMATION_OF_CHARACTER = 0x81,
+/*20171018 to latest
+대화방
+Chat Room
+*/
+ MSG_CHAT_ROOM = 0x82,
+/*20171018 to latest
+명
+Ppl
+*/
+ MSG_COUNT_UNIT_OF_PEOPLE = 0x83,
+/*20171018 to latest
+/앉기 or /sit : 앉기. 앉아있을때 서기
+/sit: Sit command. If you are sitting, you will stand instead.
+*/
+ MSG_EXPLAIN_SIT = 0x84,
+/*20171018 to latest
+/서기 or /stand : 서기. 서있을때 앉기
+/stand: Stand command. If you are standing, you will sit instead.
+*/
+ MSG_EXPLAIN_STAND = 0x85,
+/*20171018 to latest
+/채팅방 or /chat : 채팅방 만들기창 띄우기
+/chat: Creates a Chat Room
+*/
+ MSG_EXPLAIN_MAKE_CHAT = 0x86,
+/*20171018 to latest
+/q : 채팅방 나가기.
+/q: Leaves a Chat Room
+*/
+ MSG_EXPLAIN_EXIT_CHAT_ROOM = 0x87,
+/*20171018 to latest
+/거래 [캐릭터이름] or /교환 [캐릭터이름] or /deal [캐릭터이름] : 해당 캐릭터와 거래요청
+/deal ''Character Name'' Requests a deal with a character
+*/
+ MSG_EXPLAIN_DEAL = 0x88,
+/*20171018 to latest
+/결성 [파티이름] or /organize [파티이름] : 파티결성
+/organize ''Party Name'' Organizes a party
+*/
+ MSG_EXPLAIN_ORGANIZE_PARTY = 0x89,
+/*20171018 to latest
+/탈퇴 or /leave : 파티 탈퇴
+/leave: Leaves a party
+*/
+ MSG_EXPLAIN_LEAVE_PARTY = 0x8a,
+/*20171018 to latest
+/제명 [캐릭터이름] or /expel [캐릭터이름] : 해당캐릭터를 파티에서 제명시킴
+/expel ''Character Name'' kicks a Character out of your party
+*/
+ MSG_EXPLAIN_EXPEL_PARTY_MEMBER = 0x8b,
+/*20171018 to latest
+[Alt] + [End] : 플레이어 hp/sp 게이지 On Off
+[Alt] + [End]: Turns HP/SP Bar On or Off
+*/
+ MSG_EXPLAIN_TIP4 = 0x8c,
+/*20171018 to latest
+[Alt] + [Home] : 지면 커서 표시 On Off
+[Alt] + [Home]: Turns Ground Cursor On or Off
+*/
+ MSG_EXPLAIN_TIP5 = 0x8d,
+/*20171018 to latest
+[Insert] : 앉기 서기
+[Insert]: Makes you sit or stand. (Hotkey to toggle between /sit and /stand)
+*/
+ MSG_EXPLAIN_TIP6 = 0x8e,
+/*20171018 to latest
+MVP가 되셨습니다!! MVP 아이템은
+Congratulations! You are the MVP! Your reward item is
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM = 0x8f,
+/*20171018 to latest
+ !!
+!
+*/
+ MSG_YOU_RECEIVE_MVP_ITEM2 = 0x90,
+/*20171018 to latest
+MVP가 되셨습니다!! 특별경험치
+Congratulations! You are the MVP! Your reward EXP Points are
+*/
+ MSG_YOU_RECEIVE_MVP_EXP = 0x91,
+/*20171018 to latest
+ 획득!!
+!!
+*/
+ MSG_YOU_RECEIVE_MVP_EXP2 = 0x92,
+/*20171018 to latest
+MVP가 되셨습니다만 무게초과로 MVP 아이템을 가질 수 없었습니다!!
+You are the MVP, but you can't take the reward because you are over your weight limit.
+*/
+ MSG_YOU_THROW_MVPITEM = 0x93,
+/*20171018 to latest
+ 없는 캐릭터 이름 입니다.
+There is no such character name or the user is offline.
+*/
+ MSG_NOT_EXIST_CHARACTER = 0x94,
+/*20171018 to latest
+ 수신 거부 상태입니다.
+ doesn't want to receive your messages.
+*/
+ MSG_NO_RECEIVE_MODE = 0x95,
+/*20171018 to latest
+ 모든 캐릭터에 대해 수신 거부 상태 입니다.
+ is not in the mood to talk with anyone.
+*/
+ MSG_NO_RECEIVE_MODE_FOR_ALL = 0x96,
+/*20171018 to latest
+캐릭터 접속끊기 성공.
+Killed/Disconnected User.
+*/
+ MSG_SUCCESS_DISCONNECT_CHARACTER = 0x97,
+/*20171018 to latest
+캐릭터 접속끊기 실패.
+Kill has failed.
+*/
+ MSG_FAIL_DISCONNECT_CHARACTER = 0x98,
+/*20171018 to latest
+%s %d 개 획득
+You got %s (%d).
+*/
+ MSG_GET_ITEM = 0x99,
+/*20171018 to latest
+[Alt] + [=] : 알파벳 간격이 넓어졌을때 되돌리기.
+[Alt] + [=]: Fix the interval error between letters.
+*/
+ MSG_EXPLAIN_TIP7 = 0x9a,
+/*20171018 to latest
+[F10] : 채팅창 크기조정 [Alt] + [F10] : 채팅창 On Off
+[F10]: To toggle Chat Window size; [Alt] + [F10]: Toggle Chat Window On or Off
+*/
+ MSG_EXPLAIN_TIP8 = 0x9b,
+/*20171018 to latest
+귓속말 하는법 : 채팅창 왼쪽 입력란에 캐릭터이름을 입력하고 오른쪽 입력란에 말을 입력하면 됩니다. TAB키로 두입력란 사이로 커서를 이동할 수 있습니다.
+How to Whisper: Enter a Character's Name on the left side of chat window and type your message on the right side. The Tab key helps you move between these boxes.
+*/
+ MSG_EXPLAIN_TIP9 = 0x9c,
+/*20171018 to latest
+/! /? /기쁨 /하트 /땀 /아하 /짜증 /화 /돈 /... /가위 /바위 /보 : Alt + (1~9) Ctrl + (-=\) 에 대응되는 명령어 입니다.
+/!,/?,/ho,/lv,/lv2,/swt,/ic,/an,/ag,/$,/….,/thx,/wah,/sry,/heh,/swt2,/hmm,/no1,/??,/omg,/oh,/X,/hp,/go,/sob,/gg,/kis,/kis2,/pif,/ok: Emotion icons corresponding to Alt + (1~9) Ctrl + (-=\\)
+*/
+ MSG_EXPLAIN_TIP10 = 0x9d,
+/*20171018 to latest
+파티원에게 말하는법 : 말의 제일앞에 '%'를 붙이면 파티원에게 말이 갑니다. (예: "%안녕")
+How to Speak to Party: Add % in front of every message.(Example: \%Hello\)
+*/
+ MSG_EXPLAIN_TIP11 = 0x9e,
+/*20171018 to latest
+스킬레벨이 부족합니다. 교환 불능.
+You haven't learned enough Basic Skills to Trade.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE1 = 0x9f,
+/*20171018 to latest
+스킬레벨이 부족합니다. 이모션 불능.
+You haven't learned enough Basic Skills to use Emotion icons.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE2 = 0xa0,
+/*20171018 to latest
+스킬레벨이 부족합니다. 앉기 불능.
+You haven't learned enough Basic Skills to Sit.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE3 = 0xa1,
+/*20171018 to latest
+스킬레벨이 부족합니다. 채팅방만들기 불능.
+You haven't learned enough Basic Skills to create a chat room.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE4 = 0xa2,
+/*20171018 to latest
+스킬레벨이 부족합니다. 파티만들기 불능
+You haven't learned enough Basic Skills to Party.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5 = 0xa3,
+/*20171018 to latest
+스킬레벨이 부족합니다. 외치기 불능
+You haven't learned enough skills to Shout.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE6 = 0xa4,
+/*20171018 to latest
+스킬레벨이 부족합니다. pk 불능
+You haven't learned enough skills for Pking.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE7 = 0xa5,
+/*20171018 to latest
+사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY = 0xa6,
+/*20171018 to latest
+아이템 상점
+Item Shop
+*/
+ MSG_ITEM_STORE = 0xa7,
+/*20171018 to latest
+팔고자하는 품목
+Selling Items
+*/
+ MSG_ITEMS_FOR_SELL = 0xa8,
+/*20171018 to latest
+보관아이템
+Storage
+*/
+ MSG_ITEMS_THAT_IS_STORED = 0xa9,
+/*20171018 to latest
+ 장비가 장착 되었습니다.
+ is put on.
+*/
+ MSG_ITEM_IS_EQUIPED = 0xaa,
+/*20171018 to latest
+ 장비가 해제 되었습니다.
+ is taken off.
+*/
+ MSG_ITEM_IS_REMOVED = 0xab,
+/*20171018 to latest
+귓말리스트에 이름넣기
+To add names on the Whispering List
+*/
+ MSG_ADD_TO_WHISPER_CHAR_LIST = 0xac,
+/*20171018 to latest
+스크린샷 찍는법 : [Print Screen]키나 [Scroll Lock]키를 누르면 됩니다.
+How to Take Screen Shots: Press [Print Screen] or [Scroll Lock]
+*/
+ MSG_EXPLAIN_TIP12 = 0xad,
+/*20171018 to latest
+오늘의 팁
+Tip of the Day
+*/
+ MSG_TIPOFTHEDAY = 0xae,
+/*20171018 to latest
+^3850a0알고 계셨습니까... ^000000 //^709fed
+^3850a0Did you know...?^709fed
+*/
+ MSG_DIDYOUKNOW = 0xaf,
+/*20171018 to latest
+시작할때 열기
+Display at startup
+*/
+ MSG_SHOWTIPSATSTARTUP = 0xb0,
+/*20171018 to latest
+/tip : 오늘의팁 열기
+/tip: Opens ''Tip of the Day''
+*/
+ MSG_EXPLAIN_OPENTIP = 0xb1,
+/*20171018 to latest
+현재 접속자 %d명
+There are %d Players Currently Connected.
+*/
+ MSG_NUMPEOPLE = 0xb2,
+/*20171018 to latest
+(%s)님이 입장 하였습니다.
+(%s) has entered.
+*/
+ MSG_USERGETINTHEROOM = 0xb3,
+/*20171018 to latest
+(%s)님이 퇴장 하였습니다.
+(%s) has left.
+*/
+ MSG_USERGETOUTOFTHEROOM = 0xb4,
+/*20171018 to latest
+(%s)님이 강제 퇴장 되었습니다.
+(%s) was kicked out.
+*/
+ MSG_USERGETOUTOFTHEROOMBYFORCE = 0xb5,
+/*20171018 to latest
+ %d 개
+%d ea.
+*/
+ MSG_EA = 0xb6,
+/*20171018 to latest
+%s : %d 개
+%s: %d ea.
+*/
+ MSG_EA2 = 0xb7,
+/*20171018 to latest
+%s %s : %d 개
+%s %s: %d
+*/
+ MSG_EA3 = 0xb8,
+/*20171018 to latest
+팔 수 있는 품목
+Available Items to sell
+*/
+ MSG_ITEMSYOUCANSELL = 0xb9,
+/*20171018 to latest
+상점에서 파는 품목
+Shop Items
+*/
+ MSG_SHOPITEMS = 0xba,
+/*20171018 to latest
+알 수 없는곳
+Unknown Area
+*/
+ MSG_NOWHERE = 0xbb,
+/*20171018 to latest
+서버와 언어가 맞지 않습니다.
+Your Client language doesn't match the Server language.
+*/
+ MSG_CLIENTTYPEMISMATCH = 0xbc,
+/*20171018 to latest
+아이템을 버릴려면 장비창을 닫으세요.
+Please move your equipment to the inventory. And close the equipment window.
+*/
+ MSG_CLOSEEQUIPWND = 0xbd,
+/*20171018 to latest
+영어만 됩니다.
+This server provides English Text Characters Only.
+*/
+ MSG_ENGLISHONLY = 0xbe,
+/*20171018 to latest
+지금은 지원되지 않습니다.
+This is not implemented yet.
+*/
+ MSG_NOTSUPPORTEDYET = 0xbf,
+/*20171018 to latest
+귓말 리스트가 없습니다.
+No Whisper List.
+*/
+ MSG_NOWHISPERLIST = 0xc0,
+/*20171018 to latest
+ 에게 귓말거부상태로됨
+: Whispering Blocked.
+*/
+ MSG_WHISPERIGNORESUCCESS = 0xc1,
+/*20171018 to latest
+ 에게 귓말거부 요청실패함
+: Whispering Block has failed.
+*/
+ MSG_WHISPERIGNOREFAILED1 = 0xc2,
+/*20171018 to latest
+ 에게 귓말거부 요청실패함 (인원초과)
+: Whispering Block has failed. Block List is full.
+*/
+ MSG_WHISPERIGNOREFAILED2 = 0xc3,
+/*20171018 to latest
+ 에게 귓말가능상태로됨
+: Whispering accepted.
+*/
+ MSG_WHISPERNOIGNORESUCCESS = 0xc4,
+/*20171018 to latest
+ 에게 귓말가능 요청실패함
+: Command has failed.
+*/
+ MSG_WHISPERNOIGNOREFAILED1 = 0xc5,
+/*20171018 to latest
+ 에게 귓말가능 요청실패함 (인원초과)
+: Command has failed. Block List is full.
+*/
+ MSG_WHISPERNOIGNOREFAILED2 = 0xc6,
+/*20171018 to latest
+이름의 처음과 마지막에는 공백문자를 사용할 수 없습니다.
+You cannot put a space at the beginning or end of a name.
+*/
+ MSG_NO_SPACE_IN_NAME = 0xc7,
+/*20171018 to latest
+비공개
+Private
+*/
+ MSG_ROOM_PRIVATE2 = 0xc8,
+/*20171018 to latest
+공개
+Public
+*/
+ MSG_ROOM_PUBLIC2 = 0xc9,
+/*20171018 to latest
+SP가 부족합니다.
+Not Enough SP
+*/
+ MSG_USESKILL_FAIL_SP_INSUFFICIENT = 0xca,
+/*20171018 to latest
+HP가 부족합니다.
+Not Enough HP
+*/
+ MSG_USESKILL_FAIL_HP_INSUFFICIENT = 0xcb,
+/*20171018 to latest
+스킬사용 실패.
+Skill has failed.
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE8 = 0xcc,
+/*20171018 to latest
+훔치기 실패.
+Steal has failed.
+*/
+ MSG_FAIL_STEAL = 0xcd,
+/*20171018 to latest
+교환창
+Trade
+*/
+ MSG_EXCHANGE = 0xce,
+/*20171018 to latest
+독걸기 실패.
+Envenom skill has failed.
+*/
+ MSG_FAIL_POISON = 0xcf,
+/*20171018 to latest
+이 아이디로는 이 서버에 접속할 수 없습니다.
+You cannot use this ID on this server.
+*/
+ MSG_ID_MISMATCH = 0xd0,
+/*20171018 to latest
+스피드가 향상되었습니다.
+Your Speed has increased.
+*/
+ MSG_SPEEDUP = 0xd1,
+/*20171018 to latest
+스피드가 감소되었습니다.
+Your Speed has decreased.
+*/
+ MSG_SPEEDDOWN = 0xd2,
+/*20171018 to latest
+/기억 : 워프할 장소 기억(워프 스킬이 있는경우)
+/memo: To memorize a place as Warp Point (If you are an Acolyte Class character)
+*/
+ MSG_EXPLAIN_TIP13 = 0xd3,
+/*20171018 to latest
+임의의 위치
+Random Area
+*/
+ MSG_RANDOM_POS = 0xd4,
+/*20171018 to latest
+워프 할 위치를 선택하세요.
+Select an Area to Warp
+*/
+ MSG_SELECTWHERETOWARP = 0xd5,
+/*20171018 to latest
+스킬레벨이 부족합니다.
+Skill Level is not high enough
+*/
+ MSG_NOTENOUGHSKILLLEVEL = 0xd6,
+/*20171018 to latest
+저장된 워프할 장소가 없습니다.
+There are no memorized locations (Memo Points).
+*/
+ MSG_NO_STORED_PLACE_TO_WARP = 0xd7,
+/*20171018 to latest
+워프 관련 스킬이 없습니다.
+You haven't learned Warp.
+*/
+ MSG_NOWARPSKILL = 0xd8,
+/*20171018 to latest
+워프 장소로 저장됨.
+Saved location as a Memo Point for Warp Skill.
+*/
+ MSG_WARPPOINTSTORED = 0xd9,
+/*20171018 to latest
+취소
+Cancel
+*/
+ MSG_CANCEL = 0xda,
+/*20171018 to latest
+스킬 사용후 시간이 충분히 지나지 않았습니다.
+There is a Delay after using a Skill.
+*/
+ MSG_SKILLINTERVAL = 0xdb,
+/*20171018 to latest
+한번에 가질 수 있는 아이템 종류수를 초과하여 아이템을 가질 수 없습니다.
+You can't have this item because you will exceed the weight limit.
+*/
+ MSG_CANT_GET_ITEM_BECAUSE_COUNT = 0xdc,
+/*20171018 to latest
+아이템 최대 종류수를 초과 하였습니다.
+Out of the maximum capacity
+*/
+ MSG_INSUFFICIENT_OVER_COUNT = 0xdd,
+/*20171018 to latest
+수레아이템
+Cart Items
+*/
+ MSG_MERCHANTITEM = 0xde,
+/*20171018 to latest
+수레 벗기
+Take off Cart
+*/
+ MSG_CARTOFF = 0xdf,
+/*20171018 to latest
+노점 개설
+Opening a stall
+*/
+ MSG_MERCHANTSHOPMAKER = 0xe0,
+/*20171018 to latest
+노점이름을 입력하세요.
+Please Name your Shop.
+*/
+ MSG_ENTER_SHOP_TITLE = 0xe1,
+/*20171018 to latest
+나의 노점
+My Shop
+*/
+ MSG_ITEM_MY_STORE = 0xe2,
+/*20171018 to latest
+상인 아이템 상점
+Merchant Shop
+*/
+ MSG_ITEM_MERCHANT_STORE = 0xe3,
+/*20171018 to latest
+상인에게 사고자하는 품목
+Buying Items
+*/
+ MSG_ITEMS_FOR_BUY_FROM_MERCHANT = 0xe4,
+/*20171018 to latest
+%s 구입 실패 %s
+%s Purchase Failed %s
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT = 0xe5,
+/*20171018 to latest
+재고 부족.
+Out of Stock
+*/
+ MSG_INSUFFICIENT_STOCK = 0xe6,
+/*20171018 to latest
+%s %d 개 팔림.
+%s %d sold.
+*/
+ MSG_ITEM_IS_SOLD = 0xe7,
+/*20171018 to latest
+노점에서 팔 수 있는 아이템
+Available Items for Vending
+*/
+ MSG_MERCHANTMIRRORITEM = 0xe8,
+/*20171018 to latest
+제니가 부족해서 스킬을 사용 할 수 없습니다.
+Skill has failed because you do not have enough zeny.
+*/
+ MSG_SKILL_FAIL_MONEY = 0xe9,
+/*20171018 to latest
+사용할 대상을 선택하세요
+Select a Target.
+*/
+ MSG_SELECTTARGET = 0xea,
+/*20171018 to latest
+/pk on : pk On /pk off : pk Off
+/pk on: Turns PK On. /pk off: Turns PK Off.
+*/
+ MSG_EXPLAIN_TIP14 = 0xeb,
+/*20171018 to latest
+노점
+Shop
+*/
+ MSG_STREETSHOP = 0xec,
+/*20171018 to latest
+수레 아이템 [Alt+W]
+Cart Items [Alt+W]
+*/
+ MSG_OPENCARTWINDOW = 0xed,
+/*20171018 to latest
+기본정보
+Basic Information
+*/
+ MSG_BASICINFOWND = 0xee,
+/*20171018 to 20191204
+이무기로는 이스킬을 사용할수 없습니다.
+The skill cannot be used with this weapon.
+20191211 to latest
+현재 무기로는 스킬을 사용할 수 없습니다.
+*/
+ MSG_USESKILL_FAIL_NOT_SUITABLE_WEAPON = 0xef,
+/*20171018 to latest
+%s 사기 실패 재고 부족 현재 재고 %d 개.
+Buying %s has been failed. Out of Stock. Current Stock %d.
+*/
+ MSG_FAIL_BUY_ITEM_FROM_MERCHANT_NO_STOCK = 0xf0,
+/*20171018 to latest
+서버와 동기화가 틀려 연결이 끊어졌습니다.
+You've been disconnected due to a time gap between you and the server.
+*/
+ MSG_SPEEDHACK = 0xf1,
+/*20171018 to latest
+화살을 장착하세요
+Please equip the proper ammunition first.
+*/
+ MSG_ERR_ATTACK_ARROW = 0xf2,
+/*20171018 to latest
+중량과다로 공격이나 스킬을 사용할 수 없습니다.
+You can't attack or use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_ATTACK_WEIGHT = 0xf3,
+/*20171018 to latest
+중량과다로 스킬을 사용할 수 없습니다.
+You can't use skills because you've exceeded the Weight Limit.
+*/
+ MSG_ERR_SKILL_WEIGHT = 0xf4,
+/*20171018 to latest
+화살이 장착되었습니다.
+Ammunition has been equipped.
+*/
+ MSG_MSG_ARROW_EQUIPMENT_SUCCESS = 0xf5,
+/*20171018 to latest
+레드젬스톤이 필요합니다.
+Red Gemstone required.
+*/
+ MSG_NEED_REDJAMSTONE = 0xf6,
+/*20171018 to latest
+블루젬스톤이 필요합니다.
+Blue Gemstone required.
+*/
+ MSG_NEED_BLUEJAMSTONE = 0xf7,
+/*20171018 to latest
+힘 파라메터
+Strength
+*/
+ MSG_DESC_STR = 0xf8,
+/*20171018 to latest
+민첩성 파라메터
+Agility
+*/
+ MSG_DESC_AGI = 0xf9,
+/*20171018 to latest
+체력 파라메터
+Vitality
+*/
+ MSG_DESC_VIT = 0xfa,
+/*20171018 to latest
+지력 파라메터
+Intelligence
+*/
+ MSG_DESC_INT = 0xfb,
+/*20171018 to latest
+손재주 파라메터
+Dexterity
+*/
+ MSG_DESC_DEX = 0xfc,
+/*20171018 to latest
+운 파라메터
+Luck
+*/
+ MSG_DESC_LUK = 0xfd,
+/*20171018 to latest
+공격력
+Hit Point
+*/
+ MSG_DESC_ATK = 0xfe,
+/*20171018 to latest
+방어력
+Defence Rate
+*/
+ MSG_DESC_DEF = 0xff,
+/*20171018 to latest
+명중률
+Accuracy
+*/
+ MSG_DESC_HIT = 0x100,
+/*20171018 to latest
+필살공격률
+Critical Attack
+*/
+ MSG_DESC_CRI = 0x101,
+/*20171018 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_DESC_GUILD = 0x102,
+/*20171018 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_DESC_POINT = 0x103,
+/*20171018 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_DESC_MATK = 0x104,
+/*20171018 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_DESC_MDEF = 0x105,
+/*20171018 to latest
+회피율
+Dodge
+*/
+ MSG_DESC_FLEE = 0x106,
+/*20171018 to latest
+공격스피드
+Attack Speed
+*/
+ MSG_DESC_ASPD = 0x107,
+/*20171018 to latest
+지역당 수용인원 초과로 접속할 수 없습니다.
+Server is jammed due to over population. Please try again shortly.
+*/
+ MSG_PC_OVERFLOW = 0x108,
+/*20171018 to latest
+옵션
+Option
+*/
+ MSG_OPTIONWND = 0x109,
+/*20171018 to latest
+E-MAIL 인증이 되지않았거나 블럭된 계정입니다.
+Account ID blocked by the Game Master Team.
+*/
+ MSG_ID_EMAIL_CONFIRM_NEEDED = 0x10a,
+/*20171018 to latest
+비밀번호가 틀립니다.
+Incorrect User ID or Password. Please try again.
+*/
+ MSG_INCORRECT_LOGIN_PASSWORD = 0x10b,
+/*20171018 to latest
+머리모양 선택
+Choose Hairstyle
+*/
+ MSG_SELECT_HAIR_STYLE = 0x10c,
+/*20171018 to latest
+공격력
+Hit Point
+*/
+ MSG_ATK = 0x10d,
+/*20171018 to latest
+방어력
+Defence Rate
+*/
+ MSG_DEF = 0x10e,
+/*20171018 to latest
+공격스냅 On
+Attack Snap On
+*/
+ MSG_ATTACK_SNAP_ON = 0x10f,
+/*20171018 to latest
+공격스냅 Off
+Attack Snap Off
+*/
+ MSG_ATTACK_SNAP_OFF = 0x110,
+/*20171018 to latest
+스킬스냅 On
+Skill Snap On
+*/
+ MSG_SKILL_SNAP_ON = 0x111,
+/*20171018 to latest
+스킬스냅 Off
+Skill Snap Off
+*/
+ MSG_SKILL_SNAP_OFF = 0x112,
+/*20171018 to latest
+/스냅 or /snap: 몬스터 공격시 스냅 On Off /스킬스냅 or /skillsnap: 스킬로 몬스터 공격시 스냅 On Off /아이템스냅 or /itemsnap: 아이템 주울때 스냅 On Off
+/snap: Turns snap On | Off for fights, /skillsnap: Turns snap On | Off for skills. /itemsnap: Turns snap On | Off for items on the grounds.
+*/
+ MSG_EXPLAIN_SNAP = 0x113,
+/*20171018 to latest
+아이템스냅 On
+Item Snap On
+*/
+ MSG_ITEM_SNAP_ON = 0x114,
+/*20171018 to latest
+아이템스냅 Off
+Item Snap Off
+*/
+ MSG_ITEM_SNAP_OFF = 0x115,
+/*20171018 to latest
+스냅
+Snap
+*/
+ MSG_SNAP = 0x116,
+/*20171018 to latest
+한가지 아이템을 3만개 이상 가질수 없습니다.
+You cannot carry more than 30,000 of one kind of item.
+*/
+ MSG_CANT_GET_ITEM_OVERCOUNT_ONEITEM = 0x117,
+/*20171018 to latest
+레벨 30이상의 캐릭터는 삭제할 수 없습니다. 삭제를 원하시면 관계자에게 문의 하세요.
+You cannot delete a Character with a level greater than 30. If you want to delete the character please contact a Game Master.
+*/
+ MSG_CANT_DELETE_CHARACTER_OVER_30_LEVEL = 0x118,
+/*20171018 to latest
+아이템 교환중에는 아이템을 사고 팔 수 없습니다.
+You cannot use an NPC shop while in a trade.
+*/
+ MSG_FAIL_BUY_ITEM_ITEM_EXCHANGING = 0x119,
+/*20171018 to latest
+상점명
+Shop Name
+*/
+ MSG_STALL_NAME = 0x11a,
+/*20171018 to latest
+스킬목록
+Skill Tree
+*/
+ MSG_SKILLLIST = 0x11b,
+/*20171018 to latest
+스킬포인트 : %d
+Skill Point: %d
+*/
+ MSG_SKILLPOINT = 0x11c,
+/*20171018 to latest
+스킬사용 실패
+Skill has failed.
+*/
+ MSG_USESKILL_FAIL = 0x11d,
+/*20171018 to latest
+패시브
+Passive
+*/
+ MSG_PASSIVE = 0x11e,
+/*20171018 to latest
+각자 취득
+Individual
+*/
+ MSG_EXPDIV1 = 0x11f,
+/*20171018 to latest
+균등하게 분배
+Shared
+*/
+ MSG_EXPDIV2 = 0x120,
+/*20171018 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMCOLLECT1 = 0x121,
+/*20171018 to latest
+파티 전체 공유
+Party Share
+*/
+ MSG_ITEMCOLLECT2 = 0x122,
+/*20171018 to latest
+파티 설정
+Party Setup
+*/
+ MSG_PARTYSETTING = 0x123,
+/*20171018 to latest
+경험치 분배방식
+How to share EXP
+*/
+ MSG_HOWEXPDIV = 0x124,
+/*20171018 to latest
+아이템 수집방식
+How to share Items
+*/
+ MSG_HOWITEMCOLLECT = 0x125,
+/*20171018 to latest
+파티 리더만 설정할 수 있습니다.
+Only the Party Leader can change this setting.
+*/
+ MSG_ONLY_PARTYMASTER = 0x126,
+/*20171018 to latest
+아이템 갯수 안물어보기
+Toggle Item Amount.
+*/
+ MSG_NOQUESTION_ITEMCOUNT = 0x127,
+/*20171018 to latest
+^ff0000%d^000000 초 후에 캐릭터가 지워집니다. 취소 하려면 취소 버튼을 누르세요.
+Character will be deleted after ^ff0000%d^000000 seconds. Press Cancel to quit.
+*/
+ MSG_CHARARATER_DELETE_COUNT = 0x128,
+/*20171018 to latest
+교환할 수 있는 최대 아이템 갯수는 10가지 입니다.
+You cannot trade more than 10 types of items per trade.
+*/
+ MSG_MAXEXCHANGE_IS_10_KIND = 0x129,
+/*20171018 to latest
+이서버를 이용할 수 없는 나이입니다.
+You are underaged.
+*/
+ MSG_LIMIT_AGE = 0x12a,
+/*20171018 to latest
+이메일 주소를 입력하세요.
+Please enter the deletion password.
+*/
+ MSG_ENTER_EMAIL = 0x12b,
+/*20171018 to latest
+이메일 주소 입력하기
+E-mail Address (Case Sensitive).
+*/
+ MSG_ENTER_EMAIL_TOOLTIP = 0x12c,
+/*20171018 to latest
+이메일 주소가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect e-mail address.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_EMAIL = 0x12d,
+/*20171018 to latest
+계정 비밀번호를 입력하세요.
+Enter Second Serial Cord of your Social Security number.
+*/
+ MSG_ENTER_PEOPLE_REG_NUMBER = 0x12e,
+/*20171018 to latest
+비밀번호가 틀려서 캐릭터가 삭제 되지 않았습니다.
+Character Deletion has failed because you have entered an incorrect SSN.
+*/
+ MSG_CANNOT_DELETE_CHARACTER_PEOPLE_REG_NUMBER = 0x12f,
+/*20171018 to latest
+한번에 15가지 이상의 아이템을 팔 수 없습니다.
+You can't sell more than 15 types of Items at one time.
+*/
+ MSG_CANT_SELL_OVER_15 = 0x130,
+/*20171018 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_UNDER_AGE = 0x131,
+/*20171018 to latest
+무게가 50 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+HP/SP will not be restored when your carried weight is over 50% of the Weight Limit.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT = 0x132,
+/*20171018 to latest
+무게가 90 퍼센트 이상일때는 공격과 스킬을 사용할 수 없습니다.
+You can't use Skills or Attack while your carried weight is over 90% of your Weight Limit.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT = 0x133,
+/*20171018 to latest
+HP SP가 자연적으로 회복이 가능한 상태가 되었습니다.
+Your HP/SP are now being restored naturally.
+*/
+ MSG_NO_RECOVER_OVERWEIGHT_RELEASED = 0x134,
+/*20171018 to latest
+공격과 스킬이 가능한 상태가 되었습니다.
+Attack and Skills are now available.
+*/
+ MSG_NO_ATTACK_OVERWEIGHT_RELEASED = 0x135,
+/*20171018 to latest
+서버 점검중입니다.
+Your Game's Exe File is not the latest version.
+*/
+ MSG_INVALID_VERSION = 0x136,
+/*20171018 to latest
+아이템이 모두 팔렸습니다.
+Items are sold out.
+*/
+ MSG_ITEM_IS_SOLD_OUT = 0x137,
+/*20171018 to latest
+채팅내용 파일로 저장하기
+Save Chat as Text File
+*/
+ MSG_WRITE_CHAT_TO_FILE = 0x138,
+/*20171018 to latest
+/갈무리 or /savechat : 채팅 내용 파일로 저장하기.
+/savechat: Save a Chat Log
+*/
+ MSG_EXPLAIN_SAVE_CHAT = 0x139,
+/*20171018 to latest
+계정 만들기
+Register
+*/
+ MSG_MAKEACCOUNT = 0x13a,
+/*20171018 to latest
+수신거부하기
+Reject Whispering
+*/
+ MSG_REQ_EX_LIST = 0x13b,
+/*20171018 to latest
+수신거부해제하기
+Allow Whispering
+*/
+ MSG_REQ_IN = 0x13c,
+/*20171018 to latest
+미스표시 On
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_ON = 0x13d,
+/*20171018 to latest
+미스표시 Off
+Shows ''Miss''
+*/
+ MSG_MISS_EFFECT_OFF = 0x13e,
+/*20171018 to latest
+카메라고정 On
+Camera Zooming On
+*/
+ MSG_FIXED_CAMERA_ON = 0x13f,
+/*20171018 to latest
+카메라고정 Off
+Camera Zooming Off
+*/
+ MSG_FIXED_CAMERA_OFF = 0x140,
+/*20171018 to latest
+/camera : 플레이어에게 카메라고정 On Off /miss : 미스이펙트 On Off
+/camera: Camera Zooming On or Off. /miss: Toggle ''Miss'' display
+*/
+ MSG_EXPLAIN_CAMERA_MISS = 0x141,
+/*20171018 to latest
+스킬정보보기
+View Skill Info
+*/
+ MSG_SEE_INFORMATION_OF_SKILL = 0x142,
+/*20171018 to latest
+스킬이름바꾸기
+Change Skill
+*/
+ MSG_CHANGE_SKILL_NAME = 0x143,
+/*20171018 to latest
+스프라이트 해상도
+Sprite Resolution
+*/
+ MSG_SPRITE_RESOLUTION = 0x144,
+/*20171018 to latest
+텍스쳐 해상도
+Texture Resolution
+*/
+ MSG_TEXTURE_RESOLUTION = 0x145,
+/*20171018 to latest
+디테일 조정
+Arrange Detail
+*/
+ MSG_DETAILLEVELWND = 0x146,
+/*20171018 to latest
+%s Zeny 획득
+You got %s Zeny
+*/
+ MSG_GET_ZENY = 0x147,
+/*20171018 to latest
+길드명
+Guild Name
+*/
+ MSG_GUILDNAME = 0x148,
+/*20171018 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILDLEVEL = 0x149,
+/*20171018 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_GUILD_MASTER_NAME = 0x14a,
+/*20171018 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_NUM_MEMBER = 0x14b,
+/*20171018 to latest
+조합원 평균레벨
+Avg.lvl of Guildsmen
+*/
+ MSG_GUILD_AVG_MEMBER_LEVEL = 0x14c,
+/*20171018 to latest
+관리영지
+Castles Owned
+*/
+ MSG_GUILD_MANAGE_LAND = 0x14d,
+/*20171018 to latest
+성향
+Tendency
+*/
+ MSG_GUILD_FAIR = 0x14e,
+/*20171018 to latest
+경험치
+EXP
+*/
+ MSG_GUILD_EXP = 0x14f,
+/*20171018 to latest
+길드엠블렘
+Emblem
+*/
+ MSG_GUILD_EMBLEM = 0x150,
+/*20171018 to latest
+길드상납포인트
+Tax Point
+*/
+ MSG_GUILD_POINT = 0x151,
+/*20171018 to latest
+동맹길드
+Alliances
+*/
+ MSG_ALLY_GUILD = 0x152,
+/*20171018 to latest
+적대길드
+Antagonists
+*/
+ MSG_HOSTILITY_GUILD = 0x153,
+/*20171018 to latest
+길드정보
+Guild Info
+*/
+ MSG_GUILDINFOMANAGE = 0x154,
+/*20171018 to latest
+조합원정보
+Guildsmen Info
+*/
+ MSG_GUILDMEMBERMANAGE = 0x155,
+/*20171018 to latest
+직위설정
+Position
+*/
+ MSG_GUILDPOSITIONMANAGE = 0x156,
+/*20171018 to latest
+길드스킬
+Guild Skill
+*/
+ MSG_GUILDSKILL = 0x157,
+/*20171018 to latest
+추방자 리스트
+Expel History
+*/
+ MSG_GUILDBANISHEDMEMBER = 0x158,
+/*20171018 to latest
+공지사항
+Guild Notice
+*/
+ MSG_GUILDNOTICE = 0x159,
+/*20171018 to latest
+전체길드 리스트
+Entire Guild List
+*/
+ MSG_GUILDTOTALINFO = 0x15a,
+/*20171018 to latest
+귓말 리스트
+Whispering List
+*/
+ MSG_WHISPERLISTWND = 0x15b,
+/*20171018 to latest
+귓말창 열기
+Open Whispering Window
+*/
+ MSG_OPENWHISPERLISTWND = 0x15c,
+/*20171018 to latest
+귓말 리스트 창 여는법 : [Alt] + [H] 를 누르면 귓말 리스트 창이 열립니다.
+How to Open Whispering List: Press [Alt] + [H]
+*/
+ MSG_EXPLAIN_WHISPER_LIST_WND = 0x15d,
+/*20171018 to latest
+자동으로 귓말창 열기
+Open Whispering List Automatically
+*/
+ MSG_AUTOOPENWHISPERLISTWND = 0x15e,
+/*20171018 to latest
+지우기
+Delete
+*/
+ MSG_DELETE = 0x15f,
+/*20171018 to latest
+다음부터 열리지 않음
+Close since next
+*/
+ MSG_DONTOPEN = 0x160,
+/*20171018 to latest
+마지막으로 접속한 시간
+Last Log-in Time
+*/
+ MSG_LAST_LOGIN_TIME = 0x161,
+/*20171018 to latest
+마지막으로 접속한 IP
+Last Log-in IP
+*/
+ MSG_LAST_LOGIN_IP = 0x162,
+/*20171018 to latest
+친구 설정
+Friend Setup
+*/
+ MSG_FRIEND_SETTING = 0x163,
+/*20171018 to latest
+정말 지우시겠습니까?
+Are you sure that you want to delete?
+*/
+ MSG_DO_YOU_REALLY_WANT_DELETE = 0x164,
+/*20171018 to latest
+정말 탈퇴하시겠습니까?
+Are you sure that you want to leave?
+*/
+ MSG_DO_YOU_REALLY_WANT_LEAVE = 0x165,
+/*20171018 to latest
+친구로 등록하기
+Register as a Friend
+*/
+ MSG_ADD_TO_FRIEND_CHAR_LIST = 0x166,
+/*20171018 to latest
+친구일때 자동으로 1:1창 열기
+Open 1:1 Chat between Friends
+*/
+ MSG_AUTOOPENWHISPERLISTWND_FRIEND = 0x167,
+/*20171018 to latest
+1:1창 열기
+Open 1:1 Chat
+*/
+ MSG_OPEN_1ON1_WINDOW = 0x168,
+/*20171018 to latest
+친구가 아닐때 자동으로 1:1창 열기
+Open 1:1 Chat between Strangers
+*/
+ MSG_AUTOOPEN_1ON1_WINDOW = 0x169,
+/*20171018 to latest
+1:1창 열릴때 소리로 알림
+Alarm when you recieve a 1:1 Chat
+*/
+ MSG_WHISPER_OPEN_SOUND = 0x16a,
+/*20171018 to latest
+정말 제명시키시겠습니까?
+Are you sure that you want to expel?
+*/
+ MSG_DO_YOU_REALLY_WANT_EXPEL = 0x16b,
+/*20171018 to latest
+%s 님이 길드를 탈퇴했습니다.
+%s has withdrawn from the guild.
+*/
+ MSG_USER_LEFT_GUILD = 0x16c,
+/*20171018 to latest
+탈퇴사유 : %s
+Secession Reason: %s
+*/
+ MSG_REASON_LEAVE_GUILD = 0x16d,
+/*20171018 to latest
+길드명이 일치하지 않습니다
+You have failed to disband the guild.
+*/
+ MSG_DISORGANIZE_GUILD_FAILURE = 0x16e,
+/*20171018 to latest
+길드해체사유 : %s
+Disband Reason: %s
+*/
+ MSG_DISORGANIZATION_REASON = 0x16f,
+/*20171018 to latest
+해당 계정은 삭제된 아이디 입니다.
+This ID has been removed.
+*/
+ MSG_DELETED_ACCOUNT = 0x170,
+/*20171018 to latest
+판매가 :
+Price:
+*/
+ MSG_SELLPRICE = 0x171,
+/*20171018 to latest
+%s 님이 길드에서 추방되었습니다.
+%s has been expelled from our guild.
+*/
+ MSG_BAN_GUILD = 0x172,
+/*20171018 to latest
+추방사유 : %s
+Expulsion Reason: %s
+*/
+ MSG_REASON_BAN_GUILD = 0x173,
+/*20171018 to latest
+아이템을 착용할 수 없습니다.
+You can't put this item on.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM = 0x174,
+/*20171018 to latest
+파티설정을 변경할 수 없습니다.
+You can't modify Party Setup.
+*/
+ MSG_PARTYSETTING_CHANGE_IMPOSSIBLE = 0x175,
+/*20171018 to latest
+길드가 만들어 졌습니다.
+Guild has been Created.
+*/
+ MSG_GUILD_MAKE_SUCCESS = 0x176,
+/*20171018 to latest
+이미 길드에 속해있습니다.
+You are already in a Guild.
+*/
+ MSG_GUILD_MAKE_ALREADY_MEMBER = 0x177,
+/*20171018 to latest
+같은이름의 길드가 존재합니다.
+That Guild Name already exists.
+*/
+ MSG_GUILD_MAKE_GUILD_EXIST = 0x178,
+/*20171018 to latest
+ 길드에서 초청 메시지가 왔습니다. 가입하겠습니까?
+ Guild has sent you an invitation. Would you like to join this Guild?
+*/
+ MSG_SUGGEST_JOIN_GUILD = 0x179,
+/*20171018 to latest
+다른길드에 가입되어 있습니다.
+He/She is already in a Guild.
+*/
+ MSG_CHARACTER_IS_ALREADY_IN_GUILD = 0x17a,
+/*20171018 to latest
+길드가입을 거절 했습니다.
+Offer Rejected
+*/
+ MSG_CHARACTER_REJECT_JOIN_GUILD = 0x17b,
+/*20171018 to latest
+길드가입을 수락했습니다.
+Offer Accepted
+*/
+ MSG_CHARACTER_ACCEPT_JOIN_GUILD = 0x17c,
+/*20171018 to latest
+길드정원을 초과했습니다.
+Your Guild is Full.
+*/
+ MSG_TOO_MANY_PEOPLE_IN_GUILD = 0x17d,
+/*20171018 to latest
+(%s)님 길드에 가입요청
+Send (%s) a Guild invitation
+*/
+ MSG_REQ_JOIN_GUILD = 0x17e,
+/*20171018 to latest
+스킬 레벨이 모자라서 매너포인트를 줄 수 없습니다.
+You haven't learned enough skills for aligning.
+*/
+ MSG_NOT_ENOUGH_FOR_MANNER_POINT = 0x17f,
+/*20171018 to latest
+매너 포인트 주기 성공
+Aligning completed.
+*/
+ MSG_GIVING_MANNER_POINT_SUCCESS = 0x180,
+/*20171018 to latest
+오늘 이미 사용했습니다.
+You already spent your point for today.
+*/
+ MSG_YOU_USE_TODAY_ALREADY = 0x181,
+/*20171018 to latest
+이캐릭터에게 지급한지 한달이 지나지 않았습니다.
+Hasn't been a month yet since you aligned this person.
+*/
+ MSG_ONE_MONTH_NOT_PASSED = 0x182,
+/*20171018 to latest
+%s 님으로부터 플러스 매너 포인트를 받았습니다.
+Remember, Spamming isn't nice.
+*/
+ MSG_RECEIVE_PLUS_MANNER_POINT = 0x183,
+/*20171018 to latest
+%s 님으로부터 마이너스 매너 포인트를 받았습니다.
+Please refrain from ill-mannered conduct, thank you.
+*/
+ MSG_RECEIVE_MINUS_MANNER_POINT = 0x184,
+/*20171018 to latest
+채팅 금지 시간 줄이기(풀기)
+Align with a Good Point
+*/
+ MSG_GIVE_PLUS_MANNER_POINT = 0x185,
+/*20171018 to latest
+채팅 금지 시간 늘이기(걸기)
+Align with a Bad Point
+*/
+ MSG_GIVE_MINUS_MANNER_POINT = 0x186,
+/*20171018 to latest
+(%s)님과의 거래요청
+Request a deal with (%s)
+*/
+ MSG_REQ_DEAL_WITH2 = 0x187,
+/*20171018 to latest
+(%s)님 파티에 가입요청
+Ask (%s) to join your party
+*/
+ MSG_REQ_JOIN_PARTY2 = 0x188,
+/*20171018 to latest
+ 길드에서 동맹요청 메시지가 왔습니다. 동맹하겠습니까?
+ Guild is asking you to agree to an Alliance with them. Do you accept?
+*/
+ MSG_SUGGEST_ALLY_GUILD = 0x189,
+/*20171018 to latest
+이미 동맹되어 있습니다.
+This Guild is already your Ally.
+*/
+ MSG_REQALLYGUILD_ALREADY_ALLIED = 0x18a,
+/*20171018 to latest
+동맹을 거절 했습니다.
+You reject the offer
+*/
+ MSG_REQALLYGUILD_REJECT = 0x18b,
+/*20171018 to latest
+동맹을 수락 했습니다.
+You accept the offer
+*/
+ MSG_REQALLYGUILD_ACCEPT = 0x18c,
+/*20171018 to latest
+상대길드의 동맹길드의 수가 초과 되었습니다.
+They have too many Alliances.
+*/
+ MSG_REQALLYGUILD_OVERSIZE = 0x18d,
+/*20171018 to latest
+길드의 동맹길드의 수가 초과 되었습니다.
+You have too many Alliances.
+*/
+ MSG_REQALLYMYGUILD_OVERSIZE = 0x18e,
+/*20171018 to latest
+길드 동맹 요청
+Set this guild as an Alliance
+*/
+ MSG_REQ_ALLY_GUILD = 0x18f,
+/*20171018 to latest
+길드가 성공적으로 해체 되었습니다.
+Guild was successfully disbanded.
+*/
+ MSG_DISORGANIZE_GUILD_SUCCESS = 0x190,
+/*20171018 to latest
+주민등록번호가 틀려서 길드가 해체되지 않았습니다.
+You have failed to disband the guild due to your incorrect SSN.
+*/
+ MSG_DISORGANIZE_GUILD_INVALIDKEY = 0x191,
+/*20171018 to latest
+길드맴버가 존재해서 길드가 해체되지 않았습니다.
+You have failed to disband the guild because there are guildsmen still present.
+*/
+ MSG_DISORGANIZE_GUILD_MEMBEREXIST = 0x192,
+/*20171018 to latest
+길드 적대 요청
+Set this guild as an Antagonist
+*/
+ MSG_REQ_HOSTILE_GUILD = 0x193,
+/*20171018 to latest
+머리색깔 선택
+Choose Hair Color
+*/
+ MSG_SELECT_HAIR_COLOR = 0x194,
+/*20171018 to latest
+길드결성시 필요한 아이템이 없습니다.
+You don't have necessary item to create a Guild.
+*/
+ MSG_GUILD_MAKE_GUILD_NONE_ITEM = 0x195,
+/*20171018 to latest
+몬스터 정보
+Monster Info
+*/
+ MSG_MONSTER_INFO_WINDOW = 0x196,
+/*20171018 to latest
+이름
+Name
+*/
+ MSG_NAME = 0x197,
+/*20171018 to latest
+레벨
+Level
+*/
+ MSG_LEVEL = 0x198,
+/*20171018 to latest
+HP
+*/
+ MSG_HP = 0x199,
+/*20171018 to latest
+크기
+Size
+*/
+ MSG_SIZE = 0x19a,
+/*20171018 to latest
+종족
+Type
+*/
+ MSG_RACETYPE = 0x19b,
+/*20171018 to latest
+MDEF
+*/
+ MSG_MDEFPOWER = 0x19c,
+/*20171018 to latest
+속성
+Attribute
+*/
+ MSG_PROPERTY = 0x19d,
+/*20171018 to latest
+無
+Neutral
+*/
+ MSG_PROPERTY_NEUTURAL = 0x19e,
+/*20171018 to latest
+水
+Water
+*/
+ MSG_PROPERTY_WATER = 0x19f,
+/*20171018 to latest
+地
+Earth
+*/
+ MSG_PROPERTY_EARTH = 0x1a0,
+/*20171018 to latest
+火
+Fire
+*/
+ MSG_PROPERTY_FIRE = 0x1a1,
+/*20171018 to latest
+風
+Wind
+*/
+ MSG_PROPERTY_WIND = 0x1a2,
+/*20171018 to latest
+毒
+Poison
+*/
+ MSG_PROPERTY_POISON = 0x1a3,
+/*20171018 to latest
+聖
+Holy
+*/
+ MSG_PROPERTY_SAINT = 0x1a4,
+/*20171018 to latest
+暗
+Shadow
+*/
+ MSG_PROPERTY_DARK = 0x1a5,
+/*20171018 to latest
+念
+Ghost
+*/
+ MSG_PROPERTY_MENTAL = 0x1a6,
+/*20171018 to latest
+死
+Undead
+*/
+ MSG_PROPERTY_UNDEAD = 0x1a7,
+/*20171018 to latest
+현재는 아이템을 만들 수 없습니다.
+You can't create items yet.
+*/
+ MSG_CANT_MAKE_ITEM = 0x1a8,
+/*20171018 to latest
+제조 목록
+Item List you can craft
+*/
+ MSG_MAKE_LIST = 0x1a9,
+/*20171018 to latest
+ 만들기
+ Create
+*/
+ MSG_MAKE_TARGET = 0x1aa,
+/*20171018 to latest
+ 에 필요한 재료:
+'s materials
+*/
+ MSG_REQUIRE_FOR_MAKE_TARGET = 0x1ab,
+/*20171018 to latest
+ 만들기 실패
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL = 0x1ac,
+/*20171018 to latest
+ 만들기 성공
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS = 0x1ad,
+/*20171018 to latest
+%s 만들기를 실패하였습니다.
+ item creation failed.
+*/
+ MSG_MAKE_TARGET_FAIL_MSG = 0x1ae,
+/*20171018 to latest
+%s 만들기를 성공했습니다.
+ item created successfully.
+*/
+ MSG_MAKE_TARGET_SUCCEESS_MSG = 0x1af,
+/*20171018 to latest
+레벨이 부족합니다.
+You are not the required lvl.
+*/
+ MSG_NOT_ENOUGH_LEVEL = 0x1b0,
+/*20171018 to latest
+레벨이 너무 높습니다.
+Too high lvl for this job.
+*/
+ MSG_TOO_HIGH_LEVEL = 0x1b1,
+/*20171018 to latest
+직업이 적합하지 않습니다.
+Not the suitable job for this type of work.
+*/
+ MSG_NOT_ACCEPTABLE_JOB = 0x1b2,
+/*20171018 to latest
+토키 박스 트랩 메세지
+Record a message in the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW = 0x1b3,
+/*20171018 to latest
+기록할 메세지를 입력하시기 바랍니다.
+Please type a message for the Talkie Box
+*/
+ MSG_TALKBOX_WINDOW_MSG = 0x1b4,
+/*20171018 to latest
+길드에게 보냄
+Send to Guild
+*/
+ MSG_SEND_TO_GUILD = 0x1b5,
+/*20171018 to latest
+결제된 계정이 아닙니다. 결제 페이지로 이동하시겠습니까?
+You didn't pay for this ID. Would you like to pay for it now?
+*/
+ MSG_NOT_SETTLED = 0x1b6,
+/*20171018 to latest
+서버가 혼잡한 관계로 잠시후 다시 시도해 주시기 바랍니다.
+Server is jammed due to overpopulation. Please try again after few minutes.
+*/
+ MSG_ACCOUNT_BUSY = 0x1b7,
+/*20171018 to latest
+지난 접속 정보가 남아 있습니다. 30초정도 지난뒤에 다시 시도해 주시기 바랍니다.
+Server still recognizes your last log-in. Please try again after a few minutes.
+*/
+ MSG_INFORMATION_REMAINED = 0x1b8,
+/*20171018 to latest
+매 풀어주기
+Release Falcon
+*/
+ MSG_BIRDOFF = 0x1b9,
+/*20171018 to latest
+페코페코 내리기
+Dismount
+*/
+ MSG_CHIKENOFF = 0x1ba,
+/*20171018 to latest
+小
+Small
+*/
+ MSG_SIZE_SMALL = 0x1bb,
+/*20171018 to latest
+中
+Med
+*/
+ MSG_SIZE_MIDDLE = 0x1bc,
+/*20171018 to latest
+大
+Big
+*/
+ MSG_SIZE_BIG = 0x1bd,
+/*20171018 to latest
+더블
+Double
+*/
+ MSG_DOUBLE = 0x1be,
+/*20171018 to latest
+트리플
+Triple
+*/
+ MSG_TRIPLE = 0x1bf,
+/*20171018 to latest
+쿼드로플
+Quadruple
+*/
+ MSG_QUADROPLE = 0x1c0,
+/*20171018 to latest
+%s 까지 로그인을 금지하고 있습니다.
+You are prohibited to log in until %s.
+*/
+ MSG_LOGIN_REFUSE_BLOCKED_UNTIL = 0x1c1,
+/*20171018 to latest
+의
+'s
+*/
+ MSG_MANUFACTURED_NORMAL_ITEM = 0x1c2,
+/*20171018 to latest
+의 파이어
+'s Fire
+*/
+ MSG_MANUFACTURED_FIRE_ITEM = 0x1c3,
+/*20171018 to latest
+의 아이스
+'s Ice
+*/
+ MSG_MANUFACTURED_ICE_ITEM = 0x1c4,
+/*20171018 to latest
+의 윈드
+'s Wind
+*/
+ MSG_MANUFACTURED_WIND_ITEM = 0x1c5,
+/*20171018 to latest
+의 어스
+'s Earth
+*/
+ MSG_MANUFACTURED_EARTH_ITEM = 0x1c6,
+/*20171018 to latest
+211.239.161.246
+38.144.194.2
+*/
+ MSG_ACCOUNT_ADDRESS = 0x1c7,
+/*20171018 to latest
+6900
+*/
+ MSG_ACCOUNT_PORT = 0x1c8,
+/*20171018 to 20171206
+http://www.ragnarok.co.kr
+20171208 to latest
+http://roz.gnjoy.com/
+http://www.ragnarok.co.kr
+*/
+ MSG_REGISTRATION_WEB_URL = 0x1c9,
+/*20171018 to latest
+%s 사용자 강제 종료
+Kill %s
+*/
+ MSG_BAN_USER = 0x1ca,
+/*20171018 to latest
+무지쎈
+Very Strong
+*/
+ MSG_ONE_STARPIECE = 0x1cb,
+/*20171018 to latest
+무지무지쎈
+Very Very Strong
+*/
+ MSG_TWO_STARPIECE = 0x1cc,
+/*20171018 to latest
+무무무쎈
+Very Very Very Strong
+*/
+ MSG_THREE_STARPIECE = 0x1cd,
+/*20171018 to latest
+길드 추방 사유
+The Reason of Expulsion
+*/
+ MSG_GUILD_KICK_REASON = 0x1ce,
+/*20171018 to latest
+ 공격 속도가 증가했습니다.
+Attack Speed is up.
+*/
+ MSG_INCATTACKSPEED = 0x1cf,
+/*20171018 to latest
+ 공격 속도가 감소했습니다.
+Attack Speed is down.
+*/
+ MSG_DECATTACKSPEED = 0x1d0,
+/*20171018 to latest
+ 무기의 공격력이 향상되었습니다.
+Weapon Damage is improved.
+*/
+ MSG_INCWEAPONATTACK = 0x1d1,
+/*20171018 to latest
+ 무기의 공격력이 감소되었습니다.
+Weapon Damage is reduced.
+*/
+ MSG_DECWEAPONATTACK = 0x1d2,
+/*20171018 to latest
+ 시전 딜레이가 줄었습니다.
+Cast Delay is reduced.
+*/
+ MSG_FASTPREDELAY = 0x1d3,
+/*20171018 to latest
+ 시전 딜레이가 정상으로 되었습니다.
+Cast Delay has returned to normal.
+*/
+ MSG_NORMALPREDELAY = 0x1d4,
+/*20171018 to latest
+ 무기에 독속성이 부여되었습니다.
+Weapon is temporarily enchanted with Poison.
+*/
+ MSG_WEAPONPROPERTYPOISON = 0x1d5,
+/*20171018 to latest
+ 무기에 성속성이 부여되었습니다.
+Weapon is temporarily enchanted with an elemental property.
+*/
+ MSG_WEAPONPROPERTYSAINT = 0x1d6,
+/*20171018 to latest
+ 무기의 원래속성이 적용되었습니다.
+Weapon has changed back to normal.
+*/
+ MSG_WEAPONPROPERTYORIGINAL = 0x1d7,
+/*20171018 to latest
+ 방어구에 성속성이 부여되었습니다.
+Armor has been enchanted with the Holy Ghost.
+*/
+ MSG_ARMORPROPERTYSAINT = 0x1d8,
+/*20171018 to latest
+ 방어구의 원래속성이 적용되었습니다.
+Armor has changed back to normal.
+*/
+ MSG_ARMORPROPERTYORIGINAL = 0x1d9,
+/*20171018 to latest
+ 배리어 상태가 되었습니다.
+Barrier Formed.
+*/
+ MSG_BARRIOR = 0x1da,
+/*20171018 to latest
+ 배리어 상태가 해제 되었습니다.
+Barrier Canceled.
+*/
+ MSG_DISAPPEARBARRIOR = 0x1db,
+/*20171018 to latest
+ 소형, 중형, 대형 몬스터에게 100% 공격력을 줍니다.
+Weapon Perfection Initiated.
+*/
+ MSG_PERFECTDAMAGE = 0x1dc,
+/*20171018 to latest
+ 웨폰퍼펙션 모드가 해제 되었습니다.
+Weapon perfection Canceled.
+*/
+ MSG_DISAPPEARPERFECTDAMAGE = 0x1dd,
+/*20171018 to latest
+ 무기가 파괴될 가능성이 높아진 대신 무기의 공격력이 증가하였습니다.
+Power-Thrust Initiated.
+*/
+ MSG_OVERTHRUSTING = 0x1de,
+/*20171018 to latest
+ 오버트러스트 상태가 해제 되었습니다.
+Power-Thrust Canceled.
+*/
+ MSG_DISAPPEAROVERTHRUSTING = 0x1df,
+/*20171018 to latest
+ 무기의 최대 성능을 끌어냅니다.
+Maximize-Power Initiated.
+*/
+ MSG_MAXIMIZE = 0x1e0,
+/*20171018 to latest
+ 맥시마이즈 상태가 해제 되었습니다.
+Maximize-Power Canceled.
+*/
+ MSG_DISAPPEARMAXIMIZE = 0x1e1,
+/*20171018 to latest
+[신서버]
+[New Server]
+*/
+ MSG_SERVER_PROPERTY_NEW = 0x1e2,
+/*20171018 to latest
+(%d 명)
+(%d players)
+*/
+ MSG_SERVER_USER_COUNT = 0x1e3,
+/*20171018 to latest
+(점검중)
+(On the maintenance)
+*/
+ MSG_SERVER_INSPECTING = 0x1e4,
+/*20171018 to latest
+길드멤버 %s님이 접속하셨습니다.
+Guild member %s has connected.
+*/
+ MSG_GUILD_MEMBER_STATUS_ONLINE = 0x1e5,
+/*20171018 to latest
+길드멤버 %s님이 종료하셨습니다.
+Guild member %s has disconnected.
+*/
+ MSG_GUILD_MEMBER_STATUS_OFFLINE = 0x1e6,
+/*20171018 to latest
+경험치 %d 얻음
+You got %d Base EXP.
+*/
+ MSG_GOT_EXPERIENCE_POINT = 0x1e7,
+/*20171018 to latest
+잡경험치 %d 얻음
+You got %d Job EXP.
+*/
+ MSG_GOT_JOB_EXPERIENCE_POINT = 0x1e8,
+/*20171018 to latest
+길드에서 탈퇴 했습니다.
+You left the guild.
+*/
+ MSG_LEFT_GUILD = 0x1e9,
+/*20171018 to latest
+길드에서 추방 당했습니다.
+You have been expelled from the Guild.
+*/
+ MSG_BAN_FROM_GUILD = 0x1ea,
+/*20171018 to latest
+아이템 감정 성공
+Item Appraisal has completed successfully.
+*/
+ MSG_ITEM_IDENTIFY_SUCCEESS = 0x1eb,
+/*20171018 to latest
+아이템 감정 실패
+Item appraisal has failed.
+*/
+ MSG_ITEM_IDENTIFY_FAIL = 0x1ec,
+/*20171018 to latest
+아이템 조합 성공
+Compounding has completed successfully.
+*/
+ MSG_ITEM_COMPOUNDING_SUCCEESS = 0x1ed,
+/*20171018 to latest
+아이템 조합 실패
+Compounding has failed.
+*/
+ MSG_ITEM_COMPOUNDING_FAIL = 0x1ee,
+/*20171018 to latest
+길드 적대 성공
+Antagonist has been set.
+*/
+ MSG_HOSTILE_GUILD_SUCCEESS = 0x1ef,
+/*20171018 to latest
+적대 길드수 초과로 길드 적대 실패
+Guild has too many Antagonists.
+*/
+ MSG_TOO_MANY_HOSTILE_GUILD = 0x1f0,
+/*20171018 to latest
+이미 적대 길드 입니다
+Already set as an Antagonist
+*/
+ MSG_ALREADY_REGISTERED_HOSTILE_GUILD = 0x1f1,
+/*20171018 to latest
+제련이 성공적으로 되었습니다.
+Upgrade has been completed successfully.
+*/
+ MSG_ITEM_REFINING_SUCCEESS = 0x1f2,
+/*20171018 to latest
+제련이 실패하였습니다.
+Upgrade has failed.
+*/
+ MSG_ITEM_REFINING_FAIL = 0x1f3,
+/*20171018 to latest
+이곳에서는 순간이동이 불가능합니다.
+Unavailable Area to Teleport
+*/
+ MSG_IMPOSSIBLE_TELEPORT_AREA = 0x1f4,
+/*20171018 to latest
+이 장소는 기억할 수 없습니다.
+Unable to memorize this place as Warp Point
+*/
+ MSG_POSSIBLE_TELEPORT_AREA = 0x1f5,
+/*20171018 to latest
+지금은 종료할 수 없습니다.
+Please wait 10 seconds before trying to log out.
+*/
+ MSG_CANT_EXIT_NOW = 0x1f6,
+/*20171018 to latest
+직위
+Position
+*/
+ MSG_POSITION = 0x1f7,
+/*20171018 to latest
+직업
+Job
+*/
+ MSG_JOB = 0x1f8,
+/*20171018 to latest
+메모
+Note
+*/
+ MSG_MEMO = 0x1f9,
+/*20171018 to latest
+기여
+Devotion
+*/
+ MSG_CONTRIBUTION = 0x1fa,
+/*20171018 to latest
+상납경험치
+Tax Point
+*/
+ MSG_EXP_CONTIRIBUTION = 0x1fb,
+/*20171018 to latest
+길드탈퇴
+Leave Guild
+*/
+ MSG_LEAVE_GUILD = 0x1fc,
+/*20171018 to latest
+제명시키기
+Expel
+*/
+ MSG_EXPEL_GUILD = 0x1fd,
+/*20171018 to latest
+서열
+Rank
+*/
+ MSG_GRADE = 0x1fe,
+/*20171018 to latest
+직위명
+Position Title
+*/
+ MSG_POSITION_NAME = 0x1ff,
+/*20171018 to latest
+가입권한
+Invitation
+*/
+ MSG_JOIN_AUTHORITY = 0x200,
+/*20171018 to latest
+처벌권한
+Punish
+*/
+ MSG_PENALTY_AUTORITY = 0x201,
+/*20171018 to latest
+상납%
+Tax %
+*/
+ MSG_CONTRIBUTION_PERCENT = 0x202,
+/*20171018 to latest
+제목
+Title
+*/
+ MSG_TITLE = 0x203,
+/*20171018 to latest
+내용
+For
+*/
+ MSG_CONTENTS = 0x204,
+/*20171018 to latest
+길드이름
+Guild Name
+*/
+ MSG_GUILD_NAME = 0x205,
+/*20171018 to latest
+길드레벨
+Guild lvl
+*/
+ MSG_GUILD_LEVEL = 0x206,
+/*20171018 to latest
+조합원수
+Number of Members
+*/
+ MSG_GUILD_PEOPLE_COUNT = 0x207,
+/*20171018 to latest
+랭킹
+Ranking
+*/
+ MSG_RANKING = 0x208,
+/*20171018 to latest
+아이템 감정
+Item Appraisal
+*/
+ MSG_ITEM_IDENTIFY = 0x209,
+/*20171018 to latest
+아이템 조합
+Insert Card
+*/
+ MSG_ITEM_COMPOUNDING = 0x20a,
+/*20171018 to latest
+탈퇴 사유를 입력해주세요.
+Please enter the reason of Secession.
+*/
+ MSG_PLEASE_INPUT_WHY_LEAVING = 0x20b,
+/*20171018 to latest
+추방 사유를 입력해주세요.
+Please enter the reason of Expulsion.
+*/
+ MSG_PELASE_INPUT_WHY_EXPEL = 0x20c,
+/*20171018 to latest
+상점을 닫으세요.
+Please close Shop.
+*/
+ MSG_PLEASE_CLOSE_STORE = 0x20d,
+/*20171018 to latest
+스킬 이름
+Skill
+*/
+ MSG_SKILL_NAME = 0x20e,
+/*20171018 to latest
+아이템 이름
+Item Name
+*/
+ MSG_ITEM_NAME = 0x20f,
+/*20171018 to latest
+https://payment.ragnarok.co.kr
+https://pay.ragnarok.co.kr (Billing Web)
+*/
+ MSG_SETTLE_WEB_URL = 0x210,
+/*20171018 to latest
+게임방에서 사용가능한 IP개수가 모두 사용중입니다. 개인 계정으로 결제 하시겠습니까?
+IP capacity of this Internet Cafe is full. Would you like to pay the personal base?
+*/
+ MSG_BAN_IP_OVERFLOW = 0x211,
+/*20171018 to latest
+결제시간이 다되어 게임을 종료합니다.
+You are out of available paid playing time. Game will be shut down automatically.
+*/
+ MSG_BAN_PAY_OUT = 0x212,
+/*20171018 to latest
+이름이 너무 깁니다. 한글 11자 영문 23자 이내로 써주십시오.
+Name is too long. Please enter a name no greater than 23 english characters.
+*/
+ MSG_NAMELENGTH_TOO_LONG = 0x213,
+/*20171018 to latest
+deleted
+Character will be deleted in %d seconds.
+*/
+ MSG_DELETE_AFTER_10_SECOND = 0x214,
+/*20171018 to latest
+귀하는 개인 정액제 사용자입니다.
+You paid with the personal regular base.
+*/
+ MSG_BILLING_100 = 0x215,
+/*20171018 to latest
+귀하는 개인정량제 사용자입니다.
+You paid with the personal regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_200 = 0x216,
+/*20171018 to latest
+귀하는 개인 무료 사용자입니다.
+You are free!
+*/
+ MSG_BILLING_300 = 0x217,
+/*20171018 to latest
+귀하는 개인 무료 허용기간 사용자입니다.
+You are free for the test, your available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_400 = 0x218,
+/*20171018 to latest
+귀하는 게임방 정액제 사용자입니다.
+You paid with the Internet Cafe regular base. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_500 = 0x219,
+/*20171018 to latest
+귀하는 게임방 정량제 사용자입니다.
+You paid with the Time Limit for Internet Cafe. Available time is xx hrs xx mins xx secs.
+*/
+ MSG_BILLING_501 = 0x21a,
+/*20171018 to latest
+귀하는 게임방 무료 허용기간 사용자입니다.
+You are free for the test of Internet Cafe version .
+*/
+ MSG_BILLING_600 = 0x21b,
+/*20171018 to latest
+귀하는 게임방 무료 사용자입니다.
+You are free for the Internet Cafe version.
+*/
+ MSG_BILLING_700 = 0x21c,
+/*20171018 to latest
+귀하는 종량제 사이트 이용자입니다.
+You paid on the Time Limit Website.
+*/
+ MSG_BILLING_800 = 0x21d,
+/*20171018 to latest
+이모션 목록
+Emotion icon List
+*/
+ MSG_EMOTION_LIST = 0x21e,
+/*20171018 to latest
+/이모션
+/emo
+*/
+ MSG_VIEW_EMOTION = 0x21f,
+/*20171018 to latest
+/!
+*/
+ MSG_EMOTION_SURPRISE = 0x220,
+/*20171018 to latest
+/?
+*/
+ MSG_EMOTION_QUESTION = 0x221,
+/*20171018 to latest
+/기쁨
+/ho
+*/
+ MSG_EMOTION_DELIGHT = 0x222,
+/*20171018 to latest
+/하트
+/lv
+*/
+ MSG_EMOTION_THROB = 0x223,
+/*20171018 to latest
+/왕하트
+/lv2
+*/
+ MSG_EMOTION_BIGTHROB = 0x224,
+/*20171018 to latest
+/땀
+/swt
+*/
+ MSG_EMOTION_SWEAT = 0x225,
+/*20171018 to latest
+/아하
+/ic
+*/
+ MSG_EMOTION_AHA = 0x226,
+/*20171018 to latest
+/짜증
+/an
+*/
+ MSG_EMOTION_FRET = 0x227,
+/*20171018 to latest
+/화
+/ag
+*/
+ MSG_EMOTION_ANGER = 0x228,
+/*20171018 to latest
+/돈
+/$
+*/
+ MSG_EMOTION_MONEY = 0x229,
+/*20171018 to latest
+/...
+*/
+ MSG_EMOTION_THINK = 0x22a,
+/*20171018 to latest
+/감사
+/thx
+*/
+ MSG_EMOTION_THANKS = 0x22b,
+/*20171018 to latest
+/꽥
+/wah
+*/
+ MSG_EMOTION_KEK = 0x22c,
+/*20171018 to latest
+/죄송
+/sry
+*/
+ MSG_EMOTION_SORRY = 0x22d,
+/*20171018 to latest
+/웃음
+/heh
+*/
+ MSG_EMOTION_SMILE = 0x22e,
+/*20171018 to latest
+/뻘뻘
+/swt2
+*/
+ MSG_EMOTION_PROFUSELY_SWEAT = 0x22f,
+/*20171018 to latest
+/긁적
+/hmm
+*/
+ MSG_EMOTION_SCRATCH = 0x230,
+/*20171018 to latest
+/최고
+/no1
+*/
+ MSG_EMOTION_BEST = 0x231,
+/*20171018 to latest
+/두리번
+/??
+*/
+ MSG_EMOTION_STARE_ABOUT = 0x232,
+/*20171018 to latest
+/헉
+/omg
+*/
+ MSG_EMOTION_HUK = 0x233,
+/*20171018 to latest
+/오
+/oh
+*/
+ MSG_EMOTION_O = 0x234,
+/*20171018 to latest
+/엑스
+/X
+*/
+ MSG_EMOTION_X = 0x235,
+/*20171018 to latest
+/헬프
+/hlp
+*/
+ MSG_EMOTION_HELP = 0x236,
+/*20171018 to latest
+/가
+/go
+*/
+ MSG_EMOTION_GO = 0x237,
+/*20171018 to latest
+/엉엉
+/sob
+*/
+ MSG_EMOTION_CRY = 0x238,
+/*20171018 to latest
+/킥킥
+/gg
+*/
+ MSG_EMOTION_KIK = 0x239,
+/*20171018 to latest
+/쪽
+/kis
+*/
+ MSG_EMOTION_CHUP = 0x23a,
+/*20171018 to latest
+/쪽쪽
+/kis2
+*/
+ MSG_EMOTION_CHUPCHUP = 0x23b,
+/*20171018 to latest
+/흥
+/pif
+*/
+ MSG_EMOTION_HNG = 0x23c,
+/*20171018 to latest
+/응
+/ok
+*/
+ MSG_EMOTION_OK = 0x23d,
+/*20171018 to latest
+단축키 목록
+Shortcut List
+*/
+ MSG_SHORTCUT_LIST = 0x23e,
+/*20171018 to latest
+귀하의 계정은 보류되었습니다.
+Your account is suspended.
+*/
+ MSG_BAN_PAY_SUSPEND = 0x23f,
+/*20171018 to latest
+과금 정책 변경으로 인해 일시 종료됩니다. 다시 접속하여 주시기 바랍니다.
+Your connection is terminated due to change in the billing policy. Please connect again.
+*/
+ MSG_BAN_PAY_CHANGE = 0x240,
+/*20171018 to latest
+어카운트 서버에 인증된 IP와 귀하의 IP가 달라 연결을 종료합니다.
+Your connection is terminated because your IP doesn't match the authorized IP from the account server.
+*/
+ MSG_BAN_PAY_WRONGIP = 0x241,
+/*20171018 to latest
+게임방 IP에서 개인 종량제 과금을 막기 위해 연결을 종료합니다. 개인 종량제 과금을 사용하기 위해서는 게임방IP로 등록이 되지 않은 IP를 사용해 주세요.
+Your connection is terminated to prevent charging from your account's play time.
+*/
+ MSG_BAN_PAY_PNGAMEROOM = 0x242,
+/*20171018 to latest
+귀하는 운영자에 의해 강제 종료 되었습니다.
+You have been forced to disconnect by the Game Master Team.
+*/
+ MSG_BAN_OP_FORCE = 0x243,
+/*20171018 to latest
+무게가 90%를 초과하여 스킬을 사용할 수 없습니다.
+You can't use this Skill because you are over your Weight Limit.
+*/
+ MSG_USESKILL_FAIL_WEIGHTOVER = 0x244,
+/*20171018 to latest
+무명
+Nameless
+*/
+ MSG_NAMELESS_USER = 0x245,
+/*20171018 to latest
+축하합니다. %s님의 현재 랭킹이 %d위로 상승하였습니다.
+Congratulations! %s ranking has gone up to %d.
+*/
+ MSG_RANK_IN_TEN = 0x246,
+/*20171018 to latest
+안타깝게도 %s님의 현재 랭킹이 %d위로 하락하였습니다.
+What a pity! %s ranking has gone down to %d.
+*/
+ MSG_RANK_OUT_TEN = 0x247,
+/*20171018 to latest
+Pet Info
+*/
+ MSG_PET_INFO = 0x248,
+/*20171018 to latest
+만복도
+Hunger
+*/
+ MSG_PET_HUNGRY = 0x249,
+/*20171018 to latest
+친밀도
+Intimacy
+*/
+ MSG_PET_FRIENDLY = 0x24a,
+/*20171018 to latest
+상점과 채팅방을 동시에 열수 없습니다.
+Please avoid opening a chatroom while vending.
+*/
+ MSG_CANT_OPEN_STORE_WHILE_CHAT = 0x24b,
+/*20171018 to latest
+개
+Total
+*/
+ MSG_EA4 = 0x24c,
+/*20171018 to latest
+%s 를 전투불능으로 만들었습니다.
+You have knocked down %s.
+*/
+ MSG_SLAIN = 0x24d,
+/*20171018 to latest
+%s 님에 의해 전투불능 상태가 되었습니다.
+You have been knocked down by %s.
+*/
+ MSG_SLAINBY = 0x24e,
+/*20171018 to latest
+먹이 - '%s' 아이템이 존재하지 않습니다..
+Feed - "%s" is not available.
+*/
+ MSG_NOT_EXIST_PET_FOOD = 0x24f,
+/*20171018 to latest
+먹이 주기
+Feed Pet
+*/
+ MSG_PET_FEEDING = 0x250,
+/*20171018 to latest
+퍼포먼스
+Performance
+*/
+ MSG_PET_PERFORMANCE = 0x251,
+/*20171018 to latest
+알로 되돌리기
+Return to Egg Shell
+*/
+ MSG_PET_RETURN_EGG = 0x252,
+/*20171018 to latest
+악세사리 해제
+Unequip Accessory
+*/
+ MSG_PET_ACC_OFF = 0x253,
+/*20171018 to latest
+Pet 상태 보기
+Check Pet Status
+*/
+ MSG_PET_SHOWINFO = 0x254,
+/*20171018 to latest
+악세사리
+Accessory
+*/
+ MSG_PET_ACCESSARY = 0x255,
+/*20171018 to latest
+장착됨
+Equipped
+*/
+ MSG_ITEM_EQUIPED = 0x256,
+/*20171018 to latest
+펫 리스트
+Pet List
+*/
+ MSG_PET_EGG_LIST = 0x257,
+/*20171018 to latest
+장착 안됨
+Unequipped
+*/
+ MSG_ITEM_UNEQUIPED = 0x258,
+/*20171018 to latest
+정말로 먹이를 주시겠습니까?
+Are you sure that you want to feed your pet?
+*/
+ MSG_SURE_TO_FEED_PET = 0x259,
+/*20171018 to latest
+가격을 쓰실땐 숫자(0~9)만 써주십시오.
+Only the numbers (0~9) are available.
+*/
+ MSG_CAN_INPUT_NUMBER_ONLY = 0x25a,
+/*20171018 to latest
+감정되지 않은 아이템은 판매할 수 없습니다.
+You cannot sell unidentified items.
+*/
+ MSG_CANT_SELL_UNIDENTIFIED_ITEM = 0x25b,
+/*20171018 to latest
+가격이 0 Zeny인 아이템이 존재합니다. 계속 하시겠습니까?
+Item at 0 Zeny exists. Do you wish to continue?
+*/
+ MSG_YOU_HAVE_FREE_ITEM_ON_SHOP = 0x25c,
+/*20171018 to latest
+[새로 추가된 이모션 리스트]
+[New Emotion List]
+*/
+ MSG_NEW_EMOTION_LIST = 0x25d,
+/*20171018 to latest
+일본쪽 베타 사용자들에게 전하는 메세지. -> 겅호에서 재가입 하세요.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE1 = 0x25e,
+/*20171018 to latest
+일본쪽 과금이 종료된 사용자들에게 전하는 메세지. -> 돈내라. 두 번내라.
+N/A
+*/
+ MSG_BAN_JAPAN_REFUSE2 = 0x25f,
+/*20171018 to latest
+같은 계정의 캐릭터가 이미 가입되어있습니다.
+Character in the same account already joined.
+*/
+ MSG_ALREADY_SAME_AID_JOINED = 0x260,
+/*20171018 to latest
+(%d 명) - 만18세이상
+(%d ppl) - over the age 18
+*/
+ MSG_SERVER_PROPERTY_ADULT = 0x261,
+/*20171018 to latest
+ 프로보크 상태가 되었습니다.
+Provoke initiated.
+*/
+ MSG_ENST_PROVOKE = 0x262,
+/*20171018 to latest
+ 프로보크 상태가 해제되었습니다.
+Provoke canceled.
+*/
+ MSG_DSST_PROVOKE = 0x263,
+/*20171018 to latest
+ 인듀어 상태가 되었습니다.
+Endure initiated.
+*/
+ MSG_ENST_ENDURE = 0x264,
+/*20171018 to latest
+ 인듀어 상태가 해제되었습니다.
+Endure canceled.
+*/
+ MSG_DSST_ENDURE = 0x265,
+/*20171018 to latest
+ 집중력 향상 상태가 되었습니다.
+Improve Concentration initiated.
+*/
+ MSG_ENST_CONCENTRATION = 0x266,
+/*20171018 to latest
+ 집중력 향상 상태가 해제되었습니다.
+Improve Concentration canceled.
+*/
+ MSG_DSST_CONCENTRATION = 0x267,
+/*20171018 to latest
+ 하이딩 상태가 되었습니다.
+Hiding Initiated.
+*/
+ MSG_ENST_HIDING = 0x268,
+/*20171018 to latest
+ 하이딩 상태가 해제되었습니다.
+Hiding Canceled.
+*/
+ MSG_DSST_HIDING = 0x269,
+/*20171018 to latest
+ 클로킹 상태가 되었습니다.
+Cloaking initiated.
+*/
+ MSG_ENST_CLOAKING = 0x26a,
+/*20171018 to latest
+ 클로킹 상태가 해제되었습니다.
+Cloaking canceled.
+*/
+ MSG_DSST_CLOAKING = 0x26b,
+/*20171018 to latest
+ 독을 반사 할 수 있는 상태가 되었습니다.
+Poison React initiated.
+*/
+ MSG_ENST_POISONREACT = 0x26c,
+/*20171018 to latest
+ 포이즌 리액트 상태가 해제되었습니다.
+Poison React canceled.
+*/
+ MSG_DSST_POISONREACT = 0x26d,
+/*20171018 to latest
+ 이동속도가 감소하였습니다.
+Speed reduced.
+*/
+ MSG_ENST_QUAGMIRE = 0x26e,
+/*20171018 to latest
+ 콰그마이어 상태가 해제되었습니다.
+Quagmire canceled.
+*/
+ MSG_DSST_QUAGMIRE = 0x26f,
+/*20171018 to latest
+ 방어력이 증가되었습니다.
+Defense increased.
+*/
+ MSG_ENST_ANGELUS = 0x270,
+/*20171018 to latest
+ 안젤루스 상태가 해제되었습니다.
+Angelus canceled.
+*/
+ MSG_DSST_ANGELUS = 0x271,
+/*20171018 to latest
+ 힘과 지능, 덱스가 증가하였습니다.
+Blessing aligned.
+*/
+ MSG_ENST_BLESSING = 0x272,
+/*20171018 to latest
+ 블레싱 상태가 해제되었습니다.
+Blessing canceled.
+*/
+ MSG_DSST_BLESSING = 0x273,
+/*20171018 to latest
+ 시그넘 크루시스를 사용하였습니다.
+Signum Crusis initiated.
+*/
+ MSG_ENST_CRUCIS = 0x274,
+/*20171018 to latest
+ 시그넘 크루시스 상태가 해제되었습니다.
+Signum Crusis canceled.
+*/
+ MSG_DSST_CRUCIS = 0x275,
+/*20171018 to latest
+ 독이 퍼지는 속도가 느려졌습니다.
+Slow Poison initiated.
+*/
+ MSG_ENST_SLOWPOISON = 0x276,
+/*20171018 to latest
+ 슬로우 포이즌 상태가 해제되었습니다.
+Slow Poison Canceled.
+*/
+ MSG_DSST_SLOWPOISON = 0x277,
+/*20171018 to latest
+ SP의 회복 속도가 향상 되었습니다.
+HP/SP recovery increased.
+*/
+ MSG_ENST_MAGNIFICAT = 0x278,
+/*20171018 to latest
+ 마니피캇 상태가 해제되었습니다.
+Magnificat canceled.
+*/
+ MSG_DSST_MAGNIFICAT = 0x279,
+/*20171018 to latest
+ 행운이 향상되었습니다.
+Luck increased.
+*/
+ MSG_ENST_GLORIA = 0x27a,
+/*20171018 to latest
+ 글로리아 상태가 해제되었습니다.
+Gloria canceled.
+*/
+ MSG_DSST_GLORIA = 0x27b,
+/*20171018 to latest
+ 1회 공격에 두 배 데미지를 받는 상태가 되었습니다.
+You will received double damage from all attacking opponents.
+*/
+ MSG_ENST_LEXAETERNA = 0x27c,
+/*20171018 to latest
+ 렉스에테르나 상태가 해제되었습니다.
+Lex Eterna canceled.
+*/
+ MSG_DSST_LEXAETERNA = 0x27d,
+/*20171018 to latest
+ 공격속도가 증가하였습니다.
+Attack Speed increased.
+*/
+ MSG_ENST_ADRENALINE = 0x27e,
+/*20171018 to latest
+ 공격속도가 감소하였습니다.
+Attack Speed reduced.
+*/
+ MSG_DSST_ADRENALINE = 0x27f,
+/*20171018 to latest
+ 페코에 올라 탔습니다.
+You've just been on a Peco Peco.
+*/
+ MSG_ENST_RIDING = 0x280,
+/*20171018 to latest
+ 페코에서 내렸습니다.
+You've just got off of a Peco Peco.
+*/
+ MSG_DSST_RIDING = 0x281,
+/*20171018 to latest
+ 팔콘을 장착하였습니다.
+You've just carried a Falcon with.
+*/
+ MSG_ENST_FALCON = 0x282,
+/*20171018 to latest
+ 팔콘을 풀어주었습니다.
+You've just released a Falcon.
+*/
+ MSG_DSST_FALCON = 0x283,
+/*20171018 to latest
+ 죽은척하기 상태가 되었습니다.
+Play Dead initiated.
+*/
+ MSG_ENST_TRICKDEAD = 0x284,
+/*20171018 to latest
+ 죽은척하기 상태가 해제되었습니다.
+Play Dead canceled.
+*/
+ MSG_DSST_TRICKDEAD = 0x285,
+/*20171018 to latest
+ 힘이 강해졌습니다.
+STR improved.
+*/
+ MSG_ENST_SHOUT = 0x286,
+/*20171018 to latest
+ 힘이 원래대로 돌아왔습니다.
+STR turned back to normal.
+*/
+ MSG_DSST_SHOUT = 0x287,
+/*20171018 to latest
+ 에너지코트 상태가 되었습니다.
+Energy Coat initiated.
+*/
+ MSG_ENST_ENERGYCOAT = 0x288,
+/*20171018 to latest
+ 에너지코트 상태가 해제되었습니다.
+Energy Coat canceled.
+*/
+ MSG_DSST_ENERGYCOAT = 0x289,
+/*20171018 to latest
+ 방어구가 파괴되었습니다.
+Armor destroyed.
+*/
+ MSG_ENST_BROKENAMOR = 0x28a,
+/*20171018 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENAMOR = 0x28b,
+/*20171018 to latest
+ 무기가 파괴되었니다.
+Weapon destroyed.
+*/
+ MSG_ENST_BROKENWEAPON = 0x28c,
+/*20171018 to latest
+ ...
+Weapon has just been released from destroyed status.
+*/
+ MSG_DSST_BROKENWEAPON = 0x28d,
+/*20171018 to latest
+ 환영상태가 되었습니다.
+Invisibility initiated.
+*/
+ MSG_ENST_ILLUSION = 0x28e,
+/*20171018 to latest
+ 환영상태가 해제되었습니다.
+Invisibility canceled.
+*/
+ MSG_DSST_ILLUSION = 0x28f,
+/*20171018 to latest
+과금 정보 처리가 늦어지고 있어 접속이 지연되고 있습니다. 잠시 후에 다시 시도해 주시기 바랍니다.
+Sorry. It is delayed due to the process of payment. Please re-connect in a minute.
+*/
+ MSG_REFUSE_BLOCK_TEMPORARY = 0x290,
+/*20171018 to latest
+장착된 화살/탄환/수리검 을 해제해야합니다.
+You must unequip ammunition first.
+*/
+ MSG_UNEQUIP_ARROW = 0x291,
+/*20171018 to latest
+화살 목록
+Arrow List
+*/
+ MSG_ARROW_LIST = 0x292,
+/*20171018 to latest
+카트 목록
+Cart List
+*/
+ MSG_CART_LIST = 0x293,
+/*20171018 to latest
+카트를 장착한 상태여야 합니다.
+You must have a Pushcart.
+*/
+ MSG_MUST_EQUIP_CART = 0x294,
+/*20171018 to latest
+채팅방을 개설 할 수 없습니다.
+You cannot open a Chat Window.
+*/
+ MSG_CANT_MAKE_CHAT_ROOM = 0x295,
+/*20171018 to latest
+라그나로크 홈페이지로 접속하여 계정을 만듭니다. 처음 계정을 만드시면 3일 동안은 무료로 이용하실 수 있습니다.
+Registering an account is the first step to accessing the game. Do you want to visit the registration page now?
+*/
+ MSG_3DAY_FREE = 0x296,
+/*20171018 to latest
+앉은 상태에서는 이 아이템을 사용할 수 없습니다.
+You cannot use this item while sitting.
+*/
+ MSG_CANT_USE_WHEN_SITDOWN = 0x297,
+/*20171018 to latest
+채팅, 스킬, 아이템 사용금지가 %d 분간 남아 있습니다.
+Your use of skills and chat will be blocked for the next %d minutes.
+*/
+ MSG_BAD_MANNER_REMAIN = 0x298,
+/*20171018 to latest
+채팅, 스킬, 아이템 사용금지가 해지 되었습니다.
+Your use of skills and chat have been reinstated.
+*/
+ MSG_BAD_MANNER_END = 0x299,
+/*20171018 to latest
+-[장착안됨]
+- [Not equipped]
+*/
+ MSG_REF_UNEQUIP = 0x29a,
+/*20171018 to latest
+배고픔
+Very Hungry
+*/
+ MSG_VERY_HUNGRY = 0x29b,
+/*20171018 to latest
+출출함
+Hungry
+*/
+ MSG_HUNGRY = 0x29c,
+/*20171018 to latest
+보통
+Normal
+*/
+ MSG_NORMAL = 0x29d,
+/*20171018 to latest
+배부름
+Satisfied
+*/
+ MSG_REPLETE = 0x29e,
+/*20171018 to latest
+아주 배부름
+Stuffed
+*/
+ MSG_VERY_REPLETE = 0x29f,
+/*20171018 to latest
+서먹서먹함
+Awkward
+*/
+ MSG_VERY_AWKWARD = 0x2a0,
+/*20171018 to latest
+어색함
+Shy
+*/
+ MSG_AWKWARD = 0x2a1,
+/*20171018 to latest
+친함
+Cordial
+*/
+ MSG_FRIENDLY = 0x2a2,
+/*20171018 to latest
+절친함
+Loyal
+*/
+ MSG_VERY_FRIENDLY = 0x2a3,
+/*20171018 to latest
+알수 없음
+Unknown
+*/
+ MSG_UNKNOWN = 0x2a4,
+/*20171018 to latest
+귀하는 앞으로 %일 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d day %d hour %d minute.
+*/
+ MSG_BILLING_DAY_HOUR_MINUTES = 0x2a5,
+/*20171018 to latest
+이 계정은 이미 다른 어카운트 서버로 접속한 상태입니다.
+Your account is already connected to account server.
+*/
+ MSG_BAN_INFORMATION_REMAINED_ANOTHER_ACCOUNT = 0x2a6,
+/*20171018 to latest
+귀하는 앞으로 %d시간 %d분 사용이 가능합니다.
+Your account has play time of %d hour %d minute.
+*/
+ MSG_BILLING_HOUR_MINUTES = 0x2a7,
+/*20171018 to latest
+귀하는 무료 사용자 입니다.
+Your account is a free account.
+*/
+ MSG_BILLING_FREE_USER = 0x2a8,
+/*20171018 to latest
+이 계정으로 사크라이에 접속할수 없습니다.
+This account can't connect the Sakray server.
+*/
+ MSG_REFUSE_NONSAKRAY_ID_BLOCKED = 0x2a9,
+/*20171018 to latest
+펫의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Your pet name must be 23 characters or less.
+*/
+ MSG_PETNAME_IN23 = 0x2aa,
+/*20171018 to latest
+이름은 단 한번만 바꿀수 있습니다. 펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You may change your pet's name only once. Your pet's name will be changed to ^0000ff^0000ff %s^000000^000000. Do you wish to continue?
+*/
+ MSG_PETNAME_CHANGE_ONLYONCE = 0x2ab,
+/*20171018 to latest
+/폰트
+/font
+*/
+ MSG_NAMEBALLOON_TYPE = 0x2ac,
+/*20171018 to latest
+길드에 남은 제니가 부족하여 작업이 실패하였습니다.
+Your guild lacks the funds to pay for this venture.
+*/
+ MSG_GUILDZENY_NOT_ENOUGH = 0x2ad,
+/*20171018 to latest
+길드가 소유할 수 있는 최대 금액을 초과하여 작업이 실패하였습니다.
+Your guild zeny limit prevents you from performing this action.
+*/
+ MSG_GUILDZENY_OVER = 0x2ae,
+/*20171018 to latest
+이펙트 간략화 On
+Simplified effects have been activated.
+*/
+ MSG_MINEFFECT_ON = 0x2af,
+/*20171018 to latest
+이펙트 간략화 Off
+Simplified effects have been deactivated.
+*/
+ MSG_MINEFFECT_OFF = 0x2b0,
+/*20171018 to latest
+자본금
+Required Fee
+*/
+ MSG_CAPITAL = 0x2b1,
+/*20171018 to latest
+아이템을 바닥에 버리려면, 아이템 창을 열어 주십시오.
+If you wish to drop an item, you must first open your Item Window (alt+e).
+*/
+ MSG_OPEN_ITEMWND_TO_THROW = 0x2b2,
+/*20171018 to latest
+PC방 요금이 종료하여 개인 요금제로 전환합니다. 개인 요금으로 게임을 계속 하시겠습니까?
+Internet Cafe Time Plan has been ended. Would you like to continue the game with your personal play time?
+*/
+ MSG_ASK_PNGAMEROOM = 0x2b3,
+/*20171018 to latest
+
+Current admission application state.
+*/
+ MSG_REPLY_REMAINTIME = 0x2b4,
+/*20171018 to latest
+
+Current admission application state.
+*/
+ MSG_INFO_REMAINTIME = 0x2b5,
+/*20171018 to latest
+돈이 모자라거나, 가질 수 있는 최대 금액을 초과하였습니다.
+Your lack of zeny or your zeny limit have prevented you from performing this action.
+*/
+ MSG_OVER_OR_LOW_MONEY = 0x2b6,
+/*20171018 to latest
+전투불능 상태가 되었습니다. esc키를 누르시면 선택창이 뜹니다.
+Your character has fainted. Push the ESC key to restart.
+*/
+ MSG_PRESS_ESC_TO_RESTART = 0x2b7,
+/*20171018 to latest
+ %d 개 획득
+- %d obtained.
+*/
+ MSG_EA_OBTAIN = 0x2b8,
+/*20171018 to latest
+스펠 리스트
+Spell List
+*/
+ MSG_SPELL_LIST = 0x2b9,
+/*20171018 to latest
+/최소화
+/minimize
+*/
+ MSG_MINEFFECT = 0x2ba,
+/*20171018 to latest
+이 아이템은 손상되어 있습니다..
+This item has been damaged.
+*/
+ MSG_DAMAGED_ITEM = 0x2bb,
+/*20171018 to latest
+/noshift : 쉬프트를 누르지않고 힐로 적을 공격할수있게됩니다 On Off
+/noshift: You may use your ''force heal'' ability without the Shift key. On | Off
+*/
+ MSG_EXPLAIN_NOSHIFT = 0x2bc,
+/*20171018 to latest
+시프트를 누르지 않고도 힐로 언데드를 공격할수 있습니다 [/ns ON]
+[no shift] option activated. [ON]
+*/
+ MSG_NOSHIFT_ON = 0x2bd,
+/*20171018 to latest
+시프트를 눌러야 힐로 언데드를 공격할수 있습니다 [/ns OFF]
+[no shift] option deactivated. [OFF]
+*/
+ MSG_NOSHIFT_OFF = 0x2be,
+/*20171018 to latest
+MSI_REFUSE_BAN_BY_DBA
+*/
+ MSG_REFUSE_BAN_BY_DBA = 0x2bf,
+/*20171018 to latest
+MSI_REFUSE_EMAIL_NOT_CONFIRMED
+*/
+ MSG_REFUSE_EMAIL_NOT_CONFIRMED = 0x2c0,
+/*20171018 to latest
+MSI_REFUSE_BAN_BY_GM
+*/
+ MSG_REFUSE_BAN_BY_GM = 0x2c1,
+/*20171018 to latest
+MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+*/
+ MSG_REFUSE_TEMP_BAN_FOR_DBWORK = 0x2c2,
+/*20171018 to latest
+MSI_REFUSE_SELF_LOCK
+*/
+ MSG_REFUSE_SELF_LOCK = 0x2c3,
+/*20171018 to latest
+MSI_REFUSE_NOT_PERMITTED_GROUP
+*/
+ MSG_REFUSE_NOT_PERMITTED_GROUP = 0x2c4,
+/*20171018 to latest
+MSI_REFUSE_WAIT_FOR_SAKRAY_ACTIVE
+*/
+ MSG_REFUSE_WAIT_FOR_SAKRAY_ACTIVE = 0x2c5,
+/*20171018 to latest
+/aura : 오오라를 간략화 시킬수있습니다 On Off
+/aura: Simplify Aura effect On | Off
+*/
+ MSG_EXPLAIN_AURA = 0x2c6,
+/*20171018 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_AURA_ON = 0x2c7,
+/*20171018 to latest
+오오라가 간략화되서 표시됩니다 [오오라 OFF]
+Simplify Aura enabled. [ON]
+*/
+ MSG_AURA_OFF = 0x2c8,
+/*20171018 to latest
+채팅금지 기록 %d 회
+Chat block record %d times
+*/
+ MSG_PROHIBIT_LOG = 0x2c9,
+/*20171018 to latest
+채팅 금지 리스트
+Chat block list
+*/
+ MSG_PROHIBIT_LIST = 0x2ca,
+/*20171018 to latest
+/이름표시 or /showname : 캐릭터의 이름 표시 방식을 변경합니다.
+/showname: Change the name font type.
+*/
+ MSG_EXPLAIN_SHOWNAMETYPE = 0x2cb,
+/*20171018 to latest
+/noctrl : 콘트롤을 누르지않아도 자동공격이 됩니다. On Off
+/noctrl | /nc: Auto attack without pressing ctrl key. On | Off
+*/
+ MSG_EXPLAIN_NOCTRL = 0x2cc,
+/*20171018 to latest
+콘트롤을 누르지 않아도 자동공격을 합니다 [/nc ON]
+Use auto attack without Ctrl. [Auto attack ON]
+*/
+ MSG_NOCTRL_ON = 0x2cd,
+/*20171018 to latest
+콘트롤을 눌러야 자동공격을 합니다 [/nc OFF]
+Use auto attack with Ctrl. [Auto attack OFF]
+*/
+ MSG_NOCTRL_OFF = 0x2ce,
+/*20171018 to latest
+채팅 금지 주기
+Mute this player.
+*/
+ MSG_APPEND_PROHIBIT = 0x2cf,
+/*20171018 to latest
+채팅 금지 완전 풀기 & 로그 삭제
+Unmute player & Erase mute time.
+*/
+ MSG_ERASE_PROHIBIT = 0x2d0,
+/*20171018 to latest
+채팅 금지 시간 줄이기(로그 삭제 안됨)
+Decrease Player Mute time.
+*/
+ MSG_REDUCE_PROHIBIT = 0x2d1,
+/*20171018 to latest
+폰트가 정상적으로 바뀌었습니다 [이름표시방식 1]
+Normal Font Displayed. [showname type 1]
+*/
+ MSG_SHOWNAME_ON = 0x2d2,
+/*20171018 to latest
+폰트가 가늘게 바뀌면서 파티명도 표시됩니다 [이름표시방식 2]
+Font will be thin and party name will be shown [showname type 2]
+*/
+ MSG_SHOWNAME_OFF = 0x2d3,
+/*20171018 to latest
+/doridori : 연속해서 이 명령어를 쳐주면 캐릭터가 도리도리 ^^;;
+/doridori: Shake head
+*/
+ MSG_EXPLAIN_DORIDORI = 0x2d4,
+/*20171018 to latest
+인터넷 카페에서 과금을 하고 있습니다.
+Internet room is paying now.
+*/
+ MSG_BILLING_INTERNET_CAFE = 0x2d5,
+/*20171018 to latest
+정액제 과금은 %d일 %d시간 %d분이 남았습니다.
+종량제 과금은 %d시간 %d분이 남았습니다.
+Prepaid voucher validate until %d days %d hours %d minutes later.
+Time limit voucher validate untill %d hours %d minutes later.
+*/
+ MSG_BILLING_BOTH = 0x2d6,
+/*20171018 to latest
+/bingbing : 연속해서 이 명령어를 쳐주면 캐릭터가 빙글빙글 ^^;;
+/bingbing: Rotates player counter clockwise.
+*/
+ MSG_EXPLAIN_BINGBING = 0x2d7,
+/*20171018 to latest
+/bangbang : 연속해서 이 명령어를 쳐주면 캐릭터가 뱅글뱅글 ^^;;
+/bangbang: Rotates player clockwise.
+*/
+ MSG_EXPLAIN_BANGBANG = 0x2d8,
+/*20171018 to latest
+/skillfail : 빨간색의 스킬사용 실패 메세지를 표시하지 않습니다 On Off
+/skillfail: Display red font message when skill fails. On | Off
+*/
+ MSG_EXPLAIN_SKILLFAIL = 0x2d9,
+/*20171018 to latest
+스킬사용 실패 메세지를 표시합니다 [/sf ON]
+Skill fail messages will be displayed. [Display On]
+*/
+ MSG_SKILLFAIL_ON = 0x2da,
+/*20171018 to latest
+스킬사용 실패 메세지를 표시하지 않습니다 [/sf OFF]
+Skill fail messages will not be displayed. [Display OFF]
+*/
+ MSG_SKILLFAIL_OFF = 0x2db,
+/*20171018 to latest
+/notalkmsg : 채팅내용을 채팅창에 표시하지 않습니다 On Off
+/notalkmsg: Chat will not be displayed in chat window. On | Off
+*/
+ MSG_EXPLAIN_NOTALKMSG = 0x2dc,
+/*20171018 to latest
+채팅내용을 채팅창에 표시합니다 [/nm ON]
+Chat content will be displayed in the chat window. [Display ON]
+*/
+ MSG_NOTALKMSG_ON = 0x2dd,
+/*20171018 to latest
+채팅내용을 채팅창에 표시하지않습니다 [/nm OFF]
+Chat content will not be displayed in the chat window. [Display OFF]
+*/
+ MSG_NOTALKMSG_OFF = 0x2de,
+/*20171018 to latest
+/set1 : /nc + /showname + /sf + /wi, /set2 : + /q3
+/set1: /noctrl + /showname + /skillfail
+*/
+ MSG_EXPLAIN_SET1 = 0x2df,
+/*20171018 to latest
+/fog : FOG이펙트를 키거나 끌수있습니다 On Off
+/fog: Fog effect. On | Off
+*/
+ MSG_EXPLAIN_FOG = 0x2e0,
+/*20171018 to latest
+ 청혼을 해왔습니다. 승낙하시겠습니까?
+You have received a marriage proposal. Do you accept?
+*/
+ MSG_SUGGEST_COUPLE = 0x2e1,
+/*20171018 to latest
+아이템 분배 방식
+Item sharing type
+*/
+ MSG_HOWITEMDIV = 0x2e2,
+/*20171018 to latest
+각자 취득
+Individual
+*/
+ MSG_ITEMDIV1 = 0x2e3,
+/*20171018 to latest
+균등하게 분배
+Shared
+*/
+ MSG_ITEMDIV2 = 0x2e4,
+/*20171018 to latest
+nProtect KeyCrypt
+*/
+ MSG_KEYCRYPT = 0x2e5,
+/*20171018 to latest
+Keyboard Driver가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+Keyboard Driver has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_INSTALL_KEYDRIVER = 0x2e6,
+/*20171018 to latest
+설치가 완료 되었습니다.
+
+시스템을 Reboot 합니다.
+Installation has been completed.
+
+System will be rebooted.
+*/
+ MSG_KEYCRYPT_REBOOT = 0x2e7,
+/*20171018 to latest
+설치 실패.
+Installation has been failed.
+*/
+ MSG_KEYCRYPT_INSTALLFAIL = 0x2e8,
+/*20171018 to latest
+키보드 보안을 적용하지 않고 계속합니다.
+Keyboard Security will be skipped.
+*/
+ MSG_KEYCRYPT_SKIPKEYCRYPT = 0x2e9,
+/*20171018 to latest
+키보드 보안에 필요한 파일이 존재하지 않습니다.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+Required file for Keyboard Security is not existing.
+
+(npkeyc.vxd, npkeyc.sys, npkeycs.sys)
+*/
+ MSG_KEYCRYPT_NOKEYCRYPTFILE = 0x2ea,
+/*20171018 to latest
+USB Keyboard가 검출되었습니다.
+
+키보드 보안 입력을 위해 추가기능을 설치하시겠습니까?
+
+(추가기능 설치후, 시스템 reboot 필수)
+USB Keyboard has been detected.
+
+Do you want to install a program for keyboard security?
+
+(After installation, System Reboot is required)
+*/
+ MSG_KEYCRYPT_USBKEYBOARD = 0x2eb,
+/*20171018 to latest
+ftp://ragnarok.nefficient.co.kr/pub/ragnarok/ragnarok0526.exe
+*/
+ MSG_FINDHACK_PATH = 0x2ec,
+/*20171018 to latest
+FindHack이 정상적으로 설치가 되어있지 않습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.(%d).
+FindHack is not installed correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.(%d).
+*/
+ MSG_FINDHACK_NOTINSTALLED = 0x2ed,
+/*20171018 to latest
+해킹툴이 존재하지만 치료가 정상적으로 되지 않았습니다. 라그나로크가 실행되지 않습니다.
+Hacking tool is existing but it hasn't been cleaned. Rangarok Online will not be executed.
+*/
+ MSG_FINDHACK_HACKTOOLEXIST = 0x2ee,
+/*20171018 to latest
+해킹툴 진단 프로그램이 정상적으로 다운로드 되지 않았습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+Hacking tool scan program has not been downloaded correctly. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_CANTDOWNLOAD = 0x2ef,
+/*20171018 to latest
+NPX.DLL 등록에러 이거나 FindHack 구동에 필요한 파일이 없습니다. ragnarok0226.exe 를 다운로드 하여 라그나로크가 설치된 폴더에 설치해 주시기 바랍니다.
+NPX.DLL register error or there is no necessary file to run FindHack. Please download ragnarok0226.exe and install it in RagnarokOnline directory.
+*/
+ MSG_FINDHACK_NOFILE = 0x2f0,
+/*20171018 to latest
+예외사항이 발생했습니다. (02-3281-0361)로 문의해주세요. 리턴값(%d)
+Exceptional Error. Please contact the customer support. Return Value: (%d)
+*/
+ MSG_FINDHACK_EXCEPTION = 0x2f1,
+/*20171018 to latest
+종료버튼을 클릭 하셨습니다.
+Exit button has been clicked.
+*/
+ MSG_FINDHACK_EXITPRESSED = 0x2f2,
+/*20171018 to latest
+Findhack 업데이트 서버접근 실패하였습니다. 잠시 후에 다시 시도해 주시거나 그라비티 운영팀으로 연락해주시기 바랍니다.
+Unable to connect Findhack Update Server. Please try again or contact the customer support.
+*/
+ MSG_FINDHACK_UPDATEFAILED = 0x2f3,
+/*20171018 to latest
+사랑받고있는
+Beloved
+*/
+ MSG_NAMED_PET = 0x2f4,
+/*20171018 to latest
+/report or /신고 : 신고용 갈무리 파일을 저장합니다.
+/report: Save a chat log file.
+*/
+ MSG_REPORTCOMMAND_EXPLANATION = 0x2f5,
+/*20171018 to latest
+이 파일은 (주)그라비티의 운영팀에서 게임내의 부정행위나 비매너 행위에 대한
+증거자료로 사용하게 됩니다.
+문서를 다른 문서 형식으로 저장하거나 내용을 변경하여 원본과 일치하지 않게
+ 될 경우 그 문서는 증거 효력을 상실하게 됩니다.
+Chat logs are not accepted as evidence for any ill-mannered violation on account of possible file modifications. However this feature is provided for players' personal reference.
+*/
+ MSG_REPORTTEXT_HEADER = 0x2f6,
+/*20171018 to latest
+당신을 사랑해요 ♡
+I love you.
+*/
+ MSG_LOVE_SKILL = 0x2f7,
+/*20171018 to latest
+화면 또는 이펙트가 밝아서 눈에 부담이 되시는분들은 모니터의 밝기를 조정해주시기바랍니다.
+Please adjust your monitor/video brightness if effects appear too bright.
+*/
+ MSG_EXPLAIN_BRIGHT = 0x2f8,
+/*20171018 to latest
+전체화면모드가 잘안되는 경우에 게임실행후 ALT+TAB으로 화면을 전환하면 잘되는 기종도 있습니다
+If full screen mode fails to work, it is suggested you alt+tab [or ctrl+esc] to inactivate and reactivate the Ragnarok Client.
+*/
+ MSG_EXPLAIN_ALTTAB = 0x2f9,
+/*20171018 to latest
+(%d 명) - 유료서버
+(%d players) - Pay to Play Server
+*/
+ MSG_SERVER_PROPERTY_PAY = 0x2fa,
+/*20171018 to latest
+(%d 명) - 무료서버
+(%d players) - Free Server
+*/
+ MSG_SERVER_PROPERTY_FREE = 0x2fb,
+/*20171018 to latest
+무료 회원은 유료 서버로 접속할 수 없습니다.
+Trial players can't connect Pay to Play Server.
+*/
+ MSG_CANT_CONNECT_TO_PAY_SERVER = 0x2fc,
+/*20171018 to latest
+마우스 우클릭으로 F9에 저장한 스킬을 쓸수있습니다 [/q1 ON]
+Right click menu skills for F9 are Enabled.[/q1 ON]
+*/
+ MSG_QUICKSPELL_ON = 0x2fd,
+/*20171018 to latest
+마우스 우클릭으로 스킬을 사용하지 못합니다 [/q1 OFF]
+Right click menu skills for F9 are Disabled.[/q1 OFF]
+*/
+ MSG_QUICKSPELL_OFF = 0x2fe,
+/*20171018 to latest
+/quickspell : 마우스 우클릭으로 F9에 저장한 스킬을 사용합니다 On Off
+/quickspell: Right-click menu enables you to use skills assigned to the F9 hotkey. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL = 0x2ff,
+/*20171018 to latest
+마우스의 WHEEL을 사용해서 F7 과 F8에 저장한 스킬을 사용합니다 [/q2 ON]
+Mouse wheel skills for F7 and F8 are Enabled.[/q2 ON]
+*/
+ MSG_QUICKSPELL2_ON = 0x300,
+/*20171018 to latest
+마우스 WHEEL로 스킬을 사용하지 못합니다 [/q2 OFF]
+Mouse wheel skills for F7 and F8 are Disabled.[/q2 OFF]
+*/
+ MSG_QUICKSPELL2_OFF = 0x301,
+/*20171018 to latest
+/quickspell2 : 마우스 WHEEL을 위,아래로 굴려서 F7과F8에 저장한 스킬을 사용합니다 On Off
+/quickspell2: By rolling the mouse wheel up and down, you are able to use skills registered on F7 and F8 hotkeys. On | Off
+*/
+ MSG_EXPLAIN_QUICKSPELL2 = 0x302,
+/*20171018 to latest
+/q3 : /quickspell (/q1) + /quickspell2 (/q2)
+*/
+ MSG_EXPLAIN_QUICKSPELL3 = 0x303,
+/*20171018 to latest
+/찌릿
+/bzz
+*/
+ MSG_EMOTION_STARE = 0x304,
+/*20171018 to latest
+/밥
+/rice
+*/
+ MSG_EMOTION_HUNGRY = 0x305,
+/*20171018 to latest
+/멋져
+/awsm
+*/
+ MSG_EMOTION_COOL = 0x306,
+/*20171018 to latest
+/메롱
+/meh
+*/
+ MSG_EMOTION_MERONG = 0x307,
+/*20171018 to latest
+/부끄
+/shy
+*/
+ MSG_EMOTION_SHY = 0x308,
+/*20171018 to latest
+/쓱쓱
+/pat
+*/
+ MSG_EMOTION_GOODBOY = 0x309,
+/*20171018 to latest
+/엠탐
+/mp
+*/
+ MSG_EMOTION_SPTIME = 0x30a,
+/*20171018 to latest
+/질질
+/slur
+*/
+ MSG_EMOTION_SEXY = 0x30b,
+/*20171018 to latest
+/컴온
+/com
+*/
+ MSG_EMOTION_COMEON = 0x30c,
+/*20171018 to latest
+/하품
+/yawn
+*/
+ MSG_EMOTION_SLEEPY = 0x30d,
+/*20171018 to latest
+/축하
+/grat
+*/
+ MSG_EMOTION_CONGRATULATION = 0x30e,
+/*20171018 to latest
+/피탐
+/hp
+*/
+ MSG_EMOTION_HPTIME = 0x30f,
+/*20171018 to latest
+/이모션 : 현재 사용가능한 이모션의 리스트를 보여줍니다.
+/emotion: views the emoticon list.
+*/
+ MSG_EXPLAIN_EMOTION = 0x310,
+/*20171018 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용합니다. [/bm ON]
+Skills assigned to shortcut windows 1, 2, 3 are Enabled. [/bm ON]
+*/
+ MSG_BATTLE_ON = 0x311,
+/*20171018 to latest
+키보드를 이용해서 스킬단축창 1,2,3의 스킬들을 사용하지못합니다. [/bm OFF]
+Skills assigned to shortcut windows 1, 2, 3 are Disabled. [/bm OFF]
+*/
+ MSG_BATTLE_OFF = 0x312,
+/*20171018 to latest
+/battlemode : Q ~ O 를 누르면 스킬단축창2의 스킬들이 사용됩니다.
+/battlemode: allows you to use skills assigned to Shortcut Window 2 by pressing Q ~ O keys.
+*/
+ MSG_EXPLAIN_BATTLE = 0x313,
+/*20171018 to latest
+ A ~ L 을 누르면 스킬단축창3의 스킬들이 사용됩니다.
+A ~ L keys allow you to use skills assigned to Shortcut Window 3.
+*/
+ MSG_EXPLAIN_BATTLE2 = 0x314,
+/*20171018 to latest
+라그나로크를 실행하실때 다른 프로그램을 띄우시면 게임이 느려질수도있습니다.
+Please remember, programs running in the background while playing may affect the game's performance.
+*/
+ MSG_EXPLAIN_LAG = 0x315,
+/*20171018 to latest
+천사님 제 목소리 들리세요? ^^;
+Dear angel, can you hear my voice?
+*/
+ MSG_SUPERNOVICE1 = 0x316,
+/*20171018 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_SUPERNOVICE2 = 0x317,
+/*20171018 to latest
+예요~
+Super Novice~
+*/
+ MSG_SUPERNOVICE3 = 0x318,
+/*20171018 to latest
+저 좀 도와주세요~ ㅠ_ㅠ
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE4 = 0x319,
+/*20171018 to latest
+님께서 당신을 입양시키고 싶어하십니다. 승낙하시겠습니까?
+ wishes to adopt you. Do you accept?
+*/
+ MSG_SUGGEST_BABY = 0x31a,
+/*20171018 to latest
+ Z ~ > 을 누르면 스킬단축창1의 스킬들이 사용됩니다. On Off
+Z ~ > keys allow you to use skills assigned on shortcut window 1. On | Off
+*/
+ MSG_EXPLAIN_BATTLE3 = 0x31b,
+/*20171018 to latest
+ Space를 한번 누른뒤에 글자를 입력하면 채팅을 할수있습니다.
+Press the space bar to Chat when in Battle mode [/battlemode | /bm].
+*/
+ MSG_EXPLAIN_BATTLE4 = 0x31c,
+/*20171018 to latest
+게임가드 파일이 없거나 변조되었습니다. 게임가드 셋업 파일을 설치해보시기 바랍니다.
+"Either there's no Game Guard installed on the program or Game Guard is cracked. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_AUTH_GAMEGUARD = 0x31d,
+/*20171018 to latest
+윈도우의 일부 시스템 파일이 손상되었습니다. 인터넷 익스플로러(IE)를 다시 설치해보시기 바랍니다.
+Some of Windows system files have been damaged. Please re-install your Internet Explorer.
+*/
+ MSG_NPGAMEMON_ERROR_CRYPTOAPI = 0x31e,
+/*20171018 to latest
+게임가드 실행에 실패했습니다. 게임가드 셋업 파일을 다시 설치해보시기 바랍니다.
+"Failed to run Game Guard. Please, try to reinstall Game Guard from its setup file."
+*/
+ MSG_NPGAMEMON_ERROR_EXECUTE = 0x31f,
+/*20171018 to latest
+불법 프로그램이 발견되었습니다. 불필요한 프로그램을 종료한 후 다시 실행해보시기 바랍니다.
+"At least one hazardous program has been detected. Please, terminate all the unnecessary programs before executing Game Guard."
+*/
+ MSG_NPGAMEMON_ERROR_ILLEGAL_PRG = 0x320,
+/*20171018 to latest
+게임가드 업데이트를 취소하셨습니다. 접속이 계속 되지 않을 경우 인터넷 및 방화벽 상태를 점검해보시기 바랍니다.
+"Game Guard update is canceled. If the disconnection continues, please, check your internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_ABORT = 0x321,
+/*20171018 to latest
+게임가드 업데이트 서버 접속에 실패하였습니다. 잠시 후 재시도 해보거나, 인터넷 및 방화벽 상태를 점검해 보시기 바랍니다.
+"Failed to connect to Game Guard update server. Try to connect again later, or try to check the internet or firewall settings."
+*/
+ MSG_NPGMUP_ERROR_CONNECT = 0x322,
+/*20171018 to latest
+게임가드 업데이트를 완료하지 못 했습니다. 바이러스 검사를 해보시거나, PC 관리 프로그램을 사용하시면 설정을 조정한 후 게임을 실행해 보시기 바랍니다.
+"Can't complete Game Guard update process. Please, try to execute a vaccine program to remove viruses. Or, please try to modify the settings of your PC managing tool if you are using any."
+*/
+ MSG_NPGMUP_ERROR_AUTH = 0x323,
+/*20171018 to latest
+/notrade : 거래신청을 자동으로 거절합니다 On Off
+/notrade: Declines trade offers automatically. On | Off
+*/
+ MSG_EXPLAIN_NOTRADE = 0x324,
+/*20171018 to latest
+거래신청과 친구등록요청을 자동으로 거절합니다 [/nt ON]
+Auto decline trade offers has been Enabled. [/nt ON]
+*/
+ MSG_NOTRADE_ON = 0x325,
+/*20171018 to latest
+거래신청과 친구등록요청을 정상적으로 받습니다 [/nt OFF]
+Auto decline trade offers has been Disabled. [/nt OFF]
+*/
+ MSG_NOTRADE_OFF = 0x326,
+/*20171018 to latest
+같은 아이템은 한번에 30000개 이상은 살수 없습니다.
+You cannot buy more than 30,000ea items at once.
+*/
+ MSG_LIMIT_BUY_ITEM = 0x327,
+/*20171018 to latest
+재료가 충분하지 않습니다.
+You do not have enough ingredients.
+*/
+ MSG_NOT_ENOUGH_SOURCE = 0x328,
+/*20171018 to latest
+%s에 계정정보가 남아있습니다.
+Login information remains at %s.
+*/
+ MSG_ALREADY_CONNECT = 0x329,
+/*20171018 to latest
+계정도용 조사를 위해 로그인이 금지되었습니다. 자세한 문의는 계정도용 관련 문의 메일로 해주시기 바랍니다.
+Account has been locked for a hacking investigation. Please contact the GM Team for more information.
+*/
+ MSG_HACKING_INVESTIGATION = 0x32a,
+/*20171018 to latest
+귀하는 버그관련 조사중이므로 일시적으로 접속을 금합니다
+This account has been temporarily prohibited from login due to a bug-related investigation.
+*/
+ MSG_BUG_INVESTIGATION = 0x32b,
+/*20171018 to latest
+수리가능한 아이템
+Repairable items
+*/
+ MSG_REPAIRITEMLIST = 0x32c,
+/*20171018 to latest
+아이템 수리 성공
+Item has been successfully repaired.
+*/
+ MSG_ITEM_REPAIR_SUCCEESS = 0x32d,
+/*20171018 to latest
+아이템 수리 실패 (재료 또는 상대와의 거리등을 확인해주십시요)
+You have failed to repair this item. Please check the distance between you and opponent.
+*/
+ MSG_ITEM_REPAIR_FAIL = 0x32e,
+/*20171018 to latest
+시스템 상황을 지속적으로 체크 합니다.[운영자모드] [/sc ON]
+System process enabled [GM mode] [/sc ON]
+*/
+ MSG_SYSTEM_CHECK_ON = 0x32f,
+/*20171018 to latest
+시스템 상황을 지속적으로 체크 하지 않습니다.[운영자모드] [/sc OFF]
+System process disabled [GM mode] [/sc OFF]
+*/
+ MSG_SYSTEM_CHECK_OFF = 0x330,
+/*20171018 to latest
+/systemcheck : 시스템 상황을 지속적으로 체크 합니다.[운영자모드]
+/systemcheck: Check the system process [GM mode] On | Off
+*/
+ MSG_EXPLAIN_SYSTEM_CHECK = 0x331,
+/*20171018 to latest
+(%s)님이 친구 신청을 하셨습니다. 친구가 되시겠습니까?
+(%s) wishes to be friends with you. Would you like to accept?
+*/
+ MSG_SUGGEST_JOIN_FRIEND = 0x332,
+/*20171018 to latest
+더 이상 친구 등록을 하실수 없습니다.
+Your Friend List is full.
+*/
+ MSG_FRIEND_ADD_ME_OVERSIZE = 0x333,
+/*20171018 to latest
+(%s)님이 더 이상 친구 등록을 하실수 없습니다.
+(%s)'s Friend List is full.
+*/
+ MSG_FRIEND_ADD_OTHER_OVERSIZE = 0x334,
+/*20171018 to latest
+(%s)님과 친구가 되셨습니다.
+You have become friends with (%s).
+*/
+ MSG_FRIEND_ADD_SUCCEED = 0x335,
+/*20171018 to latest
+(%s)님이 친구 되기를 원하지 않습니다.
+(%s) does not want to be friends with you.
+*/
+ MSG_FRIEND_ADD_FALSE = 0x336,
+/*20171018 to latest
+이 캐릭터는 %s 까지 블럭되어있습니다.
+This character will be blocked to use until %s.
+*/
+ MSG_BLOCKED = 0x337,
+/*20171018 to latest
+천만제니 이상 입력하셔도 가격은 천만제니로 판매됩니다.
+Price will be fixed at 10,000,000 zeny, even if you enter higher price.
+*/
+ MSG_OVERPRICE = 0x338,
+/*20171018 to latest
+(적음)
+(Very low)
+*/
+ MSG_LITTLEUSER = 0x339,
+/*20171018 to latest
+(약간 적음)
+(Low)
+*/
+ MSG_ALITTLEUSER = 0x33a,
+/*20171018 to latest
+(보통)
+(Normal)
+*/
+ MSG_NORMLEUSER = 0x33b,
+/*20171018 to latest
+(많음)
+(High)
+*/
+ MSG_MANYUSER = 0x33c,
+/*20171018 to latest
+(매우 많음)
+(Very high)
+*/
+ MSG_VERYMANYUSER = 0x33d,
+/*20171018 to latest
+비매너에 의해 운영자로부터 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d minutes by the GM Team.
+*/
+ MSG_GM_BAD_MANNER_START = 0x33e,
+/*20171018 to latest
+GM에 의한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_REMAIN = 0x33f,
+/*20171018 to latest
+GM에 의한 채팅금지가 해지 되었습니다.
+You have been released from the GM penalty.
+*/
+ MSG_GM_BAD_MANNER_END = 0x340,
+/*20171018 to latest
+도배 방지 시스템으로 인한 자동 채팅금지가 적용됩니다.
+You have been blocked from using chat and skills for %d as an automatic penalty.
+*/
+ MSG_AUTO_BAD_MANNER_START = 0x341,
+/*20171018 to latest
+도배 방지 시스템으로 인한 채팅금지가 %d 분 남아 있습니다.
+%d minutes remain until release from auto penalty.
+*/
+ MSG_AUTO_BAD_MANNER_REMAIN = 0x342,
+/*20171018 to latest
+도배 방지 시스템으로 인한 채팅금지가 해지되었습니다. 게임진행 시에는 도배에 대해서 주의하여 주시기 바랍니다.
+You have been released from the auto penalty. Please refrain from spamming in-game.
+*/
+ MSG_AUTO_BAD_MANNER_END = 0x343,
+/*20171018 to latest
+%s님과 %s님이 이혼하셨습니다.
+%s and %s have divorced from each other.
+*/
+ MSG_DIVORCE = 0x344,
+/*20171018 to latest
+拳聖 %s의 태양의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Space.
+*/
+ MSG_STARPLACE1 = 0x345,
+/*20171018 to latest
+拳聖 %s의 달의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Space.
+*/
+ MSG_STARPLACE2 = 0x346,
+/*20171018 to latest
+拳聖 %s의 별의 장소로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Space.
+*/
+ MSG_STARPLACE3 = 0x347,
+/*20171018 to latest
+拳聖 %s의 태양의 장소는 %s 입니다
+Gravity %s's Solar Space: %s
+*/
+ MSG_STARPLACE4 = 0x348,
+/*20171018 to latest
+拳聖 %s의 달의 장소는 %s 입니다
+Gravity %s's Luna Space: %s
+*/
+ MSG_STARPLACE5 = 0x349,
+/*20171018 to latest
+拳聖 %s의 별의 장소는 %s 입니다
+Gravity %s's Stellar Space: %s
+*/
+ MSG_STARPLACE6 = 0x34a,
+/*20171018 to latest
+拳聖 %s의 태양의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Solar Monster.
+*/
+ MSG_STARMONSTER1 = 0x34b,
+/*20171018 to latest
+拳聖 %s의 달의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Luna Monster.
+*/
+ MSG_STARMONSTER2 = 0x34c,
+/*20171018 to latest
+拳聖 %s의 별의 몬스터로 %s 가 지정됐습니다.
+%s has been designated as Gravity %s's Stellar Monster.
+*/
+ MSG_STARMONSTER3 = 0x34d,
+/*20171018 to latest
+拳聖 %s의 태양의 몬스터는 %s 입니다
+Gravity %s's Solar Monster: %s
+*/
+ MSG_STARMONSTER4 = 0x34e,
+/*20171018 to latest
+拳聖 %s의 달의 몬스터는 %s 입니다
+Gravity %s's Luna Monster: %s
+*/
+ MSG_STARMONSTER5 = 0x34f,
+/*20171018 to latest
+拳聖 %s의 별의 몬스터는 %s 입니다
+Gravity %s's Stellar Monster: %s
+*/
+ MSG_STARMONSTER6 = 0x350,
+/*20171018 to latest
+/window : 창 위치 이동시 다른 창과 달라붙는 속성이 들어갑니다 On Off
+/window: Display windows will snap/dock together. On | Off
+*/
+ MSG_EXPLAIN_WINDOW = 0x351,
+/*20171018 to latest
+창 위치 이동시 다른 창과 잘 붙습니다 [/wi ON]
+Display window docking enabled. [/wi ON]
+*/
+ MSG_WINDOW_ON = 0x352,
+/*20171018 to latest
+창 위치 이동시 다른 창과 붙으려는 속성을 가지지 않습니다 [/wi OFF]
+Display window docking disabled. [/wi OFF]
+*/
+ MSG_WINDOW_OFF = 0x353,
+/*20171018 to latest
+/pvpinfo : 자신의 PVP 승패와 PVP 포인트를 알 수 있습니다.
+/pvpinfo: shows your PVP result and PVP points.
+*/
+ MSG_EXPLAIN_PVP_INFO = 0x354,
+/*20171018 to latest
+현재 %d승, %d패, PVP포인트는 %d입니다.
+You have won %d times and have lost %d times in PVP. Current points %d.
+*/
+ MSG_PVP_INFO = 0x355,
+/*20171018 to latest
+매너 포인트를 성공적으로 보냈습니다.
+A manner point has been successfully aligned.
+*/
+ MSG_SEND_MANNER_POINT = 0x356,
+/*20171018 to latest
+현재 이곳은 PK 가능 지역입니다. 불의의 공격에 유의 하시기 바랍니다.
+You are in a PK area. Please beware of sudden attack.
+*/
+ MSG_PKZONE = 0x357,
+/*20171018 to latest
+게임가드 업데이트가 바이러스나 스파이웨어와의 충돌로 실패했습니다. 백신 프로그램/스파이웨어 제거 프로그램을 사용한 후 접속해 주십시기 바랍니다
+Game Guard update has been failed when either Virus or Spyware conflicted with. Please, Uninstall Spyware and Virus protection program before you log in.
+*/
+ MSG_NPGAMEMON_ERROR_100ERROR = 0x358,
+/*20171018 to latest
+윈도우 호환성 문제로 프로그램을 종료합니다. 게임을 다시 실행해 주시기 바랍니다
+Program has encountered an error related to Windows compatibility. Please start the game again.
+*/
+ MSG_NPGAMEMON_XP_COMPATIBILITY = 0x359,
+/*20171018 to latest
+채팅, 스킬, 아이템을 사용할수없게 되었습니다.
+You have been blocked from chatting, using skills and items.
+*/
+ MSG_PK_HONOR = 0x35a,
+/*20171018 to latest
+캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while this character is being deleted.
+*/
+ MSG_DELETING_CHAR = 0x35b,
+/*20171018 to latest
+결혼 상대자의 캐릭터 삭제 작업중이므로 접속이 일시적으로 제한됩니다.
+Login is temporarily unavailable while your spouse character is being deleted.
+*/
+ MSG_DELETING_SPOUSE_CHAR = 0x35c,
+/*20171018 to latest
+Novice
+*/
+ MSG_NOVICE = 0x35d,
+/*20171018 to latest
+Swordman
+*/
+ MSG_SWORDMAN = 0x35e,
+/*20171018 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN = 0x35f,
+/*20171018 to latest
+Archer
+*/
+ MSG_ARCHER = 0x360,
+/*20171018 to latest
+Acolyte
+*/
+ MSG_ACOLYTE = 0x361,
+/*20171018 to latest
+Merchant
+*/
+ MSG_MERCHANT = 0x362,
+/*20171018 to latest
+Thief
+*/
+ MSG_THIEF = 0x363,
+/*20171018 to latest
+Knight
+*/
+ MSG_KNIGHT = 0x364,
+/*20171018 to 20181128
+Prieset
+Priest
+20181212 to latest
+Priest
+*/
+ MSG_PRIEST = 0x365,
+/*20171018 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD = 0x366,
+/*20171018 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH = 0x367,
+/*20171018 to latest
+Hunter
+*/
+ MSG_HUNTER = 0x368,
+/*20171018 to latest
+Assassin
+*/
+ MSG_ASSASSIN = 0x369,
+/*20171018 to latest
+Novice
+*/
+ MSG_NOVICE_W = 0x36a,
+/*20171018 to latest
+Swordman
+*/
+ MSG_SWORDMAN_W = 0x36b,
+/*20171018 to latest
+Magician
+Mage
+*/
+ MSG_MAGICIAN_W = 0x36c,
+/*20171018 to latest
+Archer
+*/
+ MSG_ARCHER_W = 0x36d,
+/*20171018 to latest
+Acolyte
+*/
+ MSG_ACOLYTE_W = 0x36e,
+/*20171018 to latest
+Merchant
+*/
+ MSG_MERCHANT_W = 0x36f,
+/*20171018 to latest
+Thief
+*/
+ MSG_THIEF_W = 0x370,
+/*20171018 to latest
+Knight
+*/
+ MSG_KNIGHT_W = 0x371,
+/*20171018 to latest
+Prieset
+Priest
+*/
+ MSG_PRIEST_W = 0x372,
+/*20171018 to latest
+Wizerd
+Wizard
+*/
+ MSG_WIZARD_W = 0x373,
+/*20171018 to latest
+Blacksmith
+*/
+ MSG_BLACKSMITH_W = 0x374,
+/*20171018 to latest
+Hunter
+*/
+ MSG_HUNTER_W = 0x375,
+/*20171018 to latest
+Assassin
+*/
+ MSG_ASSASSIN_W = 0x376,
+/*20171018 to latest
+(%s)님을 아이로 입양신청
+Send an adoption request to %s
+*/
+ MSG_REQ_JOIN_BABY = 0x377,
+/*20171018 to latest
+아이가 되면 전승을 할수없고 스텟은 80이상 올릴수없게되며 HP와 SP가 줄어듭니다. 그래도 괜찮습니까?
+When you become a child, you will be unable to become a Transcendent Class character, all stats will be limited to a maximum of 80, and Max HP/SP will be reduced. Are you sure that you want to be adopted?
+*/
+ MSG_SUGGEST_BABY2 = 0x378,
+/*20171018 to latest
+모든 나쁜 상태이상이 제거 되었습니다.
+All abnormal status effects have been removed.
+*/
+ MSG_GOSPEL1 = 0x379,
+/*20171018 to latest
+1분간 모든 상태이상에 대해 면역이 됩니다.
+You will be immune to abnormal status effects for the next minute.
+*/
+ MSG_GOSPEL2 = 0x37a,
+/*20171018 to latest
+1분간 최대 생명력이 크게 늘어납니다.
+Your Max HP will stay increased for the next minute.
+*/
+ MSG_GOSPEL3 = 0x37b,
+/*20171018 to latest
+1분간 최대 마법력이 크게 늘어납니다.
+Your Max SP will stay increased for the next minute.
+*/
+ MSG_GOSPEL4 = 0x37c,
+/*20171018 to latest
+1분간 모든 능력이 크게 상승합니다.
+All of your Stats will stay increased for the next minute.
+*/
+ MSG_GOSPEL5 = 0x37d,
+/*20171018 to latest
+1분간 사용하는 무기에 성스러운 속성이 부여됩니다.
+Your weapon will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL6 = 0x37e,
+/*20171018 to latest
+1분간 사용하는 갑옷에 성스러운 속성이 부여됩니다.
+Your armor will remain blessed with Holy power for the next minute.
+*/
+ MSG_GOSPEL7 = 0x37f,
+/*20171018 to latest
+10초간 방어력이 크게 상승합니다.
+Your Defense will stay increased for the next 10 seconds.
+*/
+ MSG_GOSPEL8 = 0x380,
+/*20171018 to latest
+1분간 공격력이 크게 증가합니다.
+Your Attack strength will be increased for the next minute.
+*/
+ MSG_GOSPEL9 = 0x381,
+/*20171018 to latest
+1분간 명중률과 회피율이 크게 상승합니다.
+Your Accuracy and Flee Rate will be increased for the next minute.
+*/
+ MSG_GOSPEL10 = 0x382,
+/*20171018 to latest
+아이를 한번 입양했던 부부는 추가 입양이 불가능합니다.
+You cannot adopt more than 1 child.
+*/
+ MSG_BABY1 = 0x383,
+/*20171018 to latest
+부부가 둘다 레벨70이 넘어야 아이를 입양할수있습니다.
+You must be at least character level 70 in order to adopt someone.
+*/
+ MSG_BABY2 = 0x384,
+/*20171018 to latest
+[POINT] 블랙스미스 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Blacksmith rank points. Your point total is %d.
+*/
+ MSG_BLACKSMITH_POINT = 0x385,
+/*20171018 to latest
+[POINT] 알케미스트 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have been rewarded with %d Alchemist rank points. Your point total is %d.
+*/
+ MSG_ALCHEMIST_POINT = 0x386,
+/*20171018 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE11 = 0x387,
+/*20171018 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE12 = 0x388,
+/*20171018 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE13 = 0x389,
+/*20171018 to latest
+X
+Help me out~ Please~ T_T
+*/
+ MSG_SUPERNOVICE14 = 0x38a,
+/*20171018 to latest
+/notalkmsg2 : 채팅내용을 채팅창에 표시하지 않습니다 (길드말 포함) On Off
+/notalkmsg2: Hides chat messages(including guild chat). On Off
+*/
+ MSG_EXPLAIN_NOTALKMSG2 = 0x38b,
+/*20171018 to latest
+채팅내용을 채팅창에 표시합니다 [/nm2 ON]
+Show chat messages. [/nm2 ON]
+*/
+ MSG_NOTALKMSG2_ON = 0x38c,
+/*20171018 to latest
+채팅내용을 채팅창에 표시하지않습니다 (길드말 포함) [/nm2 OFF]
+Hide chat messages(including guild chat) [/nm2 OFF]
+*/
+ MSG_NOTALKMSG2_OFF = 0x38d,
+/*20171018 to latest
+제련가능한 아이템
+Upgradable Weapons
+*/
+ MSG_REFINEITEMLIST = 0x38e,
+/*20171018 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_SUCCEESS = 0x38f,
+/*20171018 to latest
+제련한 무기 : %s
+Weapons upgraded: %s
+*/
+ MSG_ITEM_REFINE_FAIL = 0x390,
+/*20171018 to latest
+무기제련스킬의 레벨이 부족해서 %s 제련을 할수없습니다.
+You cannot upgrade %s until you level up your Upgrade Weapon skill.
+*/
+ MSG_ITEM_REFINE_FAIL_LEVEL = 0x391,
+/*20171018 to latest
+제련에 필요한 아이템 (%s) 이 없으므로 제련할수없습니다.
+You lack a necessary item %s to upgrade this weapon.
+*/
+ MSG_ITEM_REFINE_FAIL_MATERIAL = 0x392,
+/*20171018 to latest
+완벽하게 코팅되어있어서 풀스트립이 통하지 않습니다.
+Full Divestment cannot pierce the target. The target is fully shielded.
+*/
+ MSG_FULLSTRIP = 0x393,
+/*20171018 to latest
+결혼한 캐릭터는 입양시킬수 없습니다.
+You cannot adopt a married person.
+*/
+ MSG_BABY3 = 0x394,
+/*20171018 to latest
+친구로 등록된 이름과 비슷하지만 등록된 이름이 아닙니다. 아는사람인지 확인하십시요.
+This name is not registered in your Friend List. Please check the name again.
+*/
+ MSG_ID_WARNING = 0x395,
+/*20171018 to latest
+/hi 또는 /hi 문장 : 친구로 등록된 캐릭터들에게 인사를 합니다.
+/hi or /hi message: Send greetings to people who are online and registered on your Friend List.
+*/
+ MSG_EXPLAIN_HI = 0x396,
+/*20171018 to latest
+길드원의 이름과 비슷하지만 길드원이 아닙니다. 길드원인지 확인하십시요.
+This character is not your guildsman. Please check the name again.
+*/
+ MSG_ID_WARNING_GUILD = 0x397,
+/*20171018 to latest
+9999만제니 이상 입력하셔도 가격은 9999만제니로 판매됩니다.
+Please be aware that the maximum selling price is fixed as 2 Billion. You cannot sell an item higher than that.
+*/
+ MSG_OVERPRICE9999 = 0x398,
+/*20171018 to latest
+친구의 귓속말은 [ Friend ] , 길드원은 [ Member ] 로 표시됩니다.
+Whispers from friends are displayed as [ Friend ], and ones from guildsmen are displayed as [ Member ].
+*/
+ MSG_EXPLAIN_SACHING1 = 0x399,
+/*20171018 to latest
+( From 캐릭터이름 : ) 이라고 표시 되는 귓속말은 친구나 길드원이 아닙니다.
+( From character name: ) is from an anonymous character who is neither your friend nor guildsman.
+*/
+ MSG_EXPLAIN_SACHING2 = 0x39a,
+/*20171018 to latest
+/blacksmith : 블랙스미스의 상위 10위권 랭킹을 보여줍니다.
+/blacksmith: Shows top 10 Blacksmiths in the server.
+*/
+ MSG_EXPLAIN_BLACKSMITH = 0x39b,
+/*20171018 to latest
+/alchemist : 알케미스트의 상위 10위권 랭킹을 보여줍니다.
+/alchemist: Shows top 10 Alchemists in the server.
+*/
+ MSG_EXPLAIN_ALCHEMIST = 0x39c,
+/*20171018 to latest
+ALT+Y : 여러가지 명령어를 쉽게 쓸수있는 윈도우가 열립니다.
+ALT+Y: Opens a window which allows you to use various commands with ease.
+*/
+ MSG_EXPLAIN_ALTY = 0x39d,
+/*20171018 to latest
+[POINT] 태권미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Tae-Kwon Mission rank points. Your point total is %d.
+*/
+ MSG_TAEKWON_POINT = 0x39e,
+/*20171018 to latest
+[태권미션] Target Monster : %s (%d%%)
+[Taekwon Mission] Target Monster: %s (%d%%)
+*/
+ MSG_TAEKWON_MISSION = 0x39f,
+/*20171018 to latest
+게임가드 초기화 에러 : %lu
+Error - Failed to initialize GameGuard: %lu
+*/
+ MSG_INIT_ERROR = 0x3a0,
+/*20171018 to latest
+스피드핵이 감지되었습니다.
+Speed Hack has been detected.
+*/
+ MSG_SPEEDHACK_DETECT = 0x3a1,
+/*20171018 to latest
+불법 프로그램 (%s) 가 발견되었습니다
+The illegal program, (%s) has been detected.
+*/
+ MSG_GAMEHACK_DETECT = 0x3a2,
+/*20171018 to latest
+게임이나 게임가드가 변조되었습니다.
+The Game or Gameguard has been cracked.
+*/
+ MSG_GAMEHACK_DOUBT = 0x3a3,
+/*20171018 to latest
+게임가드가 실행 중 입니다. 잠시 후에 다시 실행해보시기 바랍니다.
+GameGuard is currently running. Please wait for sometime and restart the game.
+*/
+ MSG_ERROR_EXIST = 0x3a4,
+/*20171018 to latest
+게임이 중복 실행되었거나 게임가드가 이미 실행 중 입니다. 게임 종료 후 다시 실행해보시기 바랍니다.
+The Game or GameGuard is already running. Please close the game and restart the game.
+*/
+ MSG_GAME_EXIST = 0x3a5,
+/*20171018 to latest
+게임가드 초기화 에러입니다. 재부팅 후 다시 실행해보거나 충돌할 수 있는 다른 프로그램들을 종료한 후 실행해 보시기 바랍니다.
+Failed to intialize GameGuard. Please try again after rebooting the system or closing other programs.
+*/
+ MSG_ERROR_INIT = 0x3a6,
+/*20171018 to latest
+바이러스 및 해킹툴 검사 모듈 로딩에 실패 했습니다. 메모리 부족이거나 바이러스에 의한 감염일 수 있습니다.
+Failed to load the scan module of virus and hacking tool. It's caused by lack of memory or PC virus infection.
+*/
+ MSG_ERROR_NPSCAN = 0x3a7,
+/*20171018 to latest
+호문클루스 정보
+Homunculus Info
+*/
+ MSG_HOMUN_INFO = 0x3a8,
+/*20171018 to latest
+호문클루스 스킬목록
+Homunculus Skill List
+*/
+ MSG_HOMUN_SKILLLIST = 0x3a9,
+/*20171018 to latest
+호문클루스의 이름은 영문 23, 한글 11자 이내로 정해 주세요.
+Please give your Homunculus a name no longer than 23 letters.
+*/
+ MSG_HOMUN_NAME_IN23 = 0x3aa,
+/*20171018 to latest
+이름은 단 한번만 바꿀수 있습니다. 호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+You can name a Homunculus only once. You have entered the name, ^0000ff%s^000000. Would you like to continue?
+*/
+ MSG_HOMUN_NAME_CHANGE_ONLYONCE = 0x3ab,
+/*20171018 to latest
+지금은 부재중~
+(Away)
+*/
+ MSG_AUTO_MSG = 0x3ac,
+/*20171018 to latest
+[자동응답]
+[Automated Message]
+*/
+ MSG_AUTO_MSG2 = 0x3ad,
+/*20171018 to latest
+부재시 타인의 귓말에 자동응답합니다.
+Send an automated message while you are away.
+*/
+ MSG_AUTO_MSG_ON = 0x3ae,
+/*20171018 to latest
+부재시 타인의 귓말에 자동응답하지 않습니다.
+Cancel automated away message.
+*/
+ MSG_AUTO_MSG_OFF = 0x3af,
+/*20171018 to latest
+자동 응답 메시지를 입력하세요.
+Please enter Away Message.
+*/
+ MSG_ENTER_AUTO_MSG = 0x3b0,
+/*20171018 to latest
+/번쩍
+/fsh
+*/
+ MSG_EMOTION_SPARK = 0x3b1,
+/*20171018 to latest
+/빙빙
+/spin
+*/
+ MSG_EMOTION_CONFUSE = 0x3b2,
+/*20171018 to latest
+/하아
+/sigh
+*/
+ MSG_EMOTION_OHNO = 0x3b3,
+/*20171018 to latest
+/덤덤
+/dum
+*/
+ MSG_EMOTION_HUM = 0x3b4,
+/*20171018 to latest
+/시끌
+/crwd
+*/
+ MSG_EMOTION_BLABLA = 0x3b5,
+/*20171018 to latest
+/좌절
+/desp
+*/
+ MSG_EMOTION_OTL = 0x3b6,
+/*20171018 to latest
+/주사위
+/dice
+*/
+ MSG_EMOTION_DICE = 0x3b7,
+/*20171018 to latest
+/pk : 학살자의 상위 10위권 랭킹을 보여줍니다.
+/pk: Shows top 10 Slayers in the server.
+*/
+ MSG_EXPLAIN_KILLER_RANK = 0x3b8,
+/*20171018 to latest
+[POINT] 학살자 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You have been rewarded with %d Slayer rank points. Your point total is %d.
+*/
+ MSG_KILLER_POINT = 0x3b9,
+/*20171018 to latest
+진화 가능
+Evolution Available
+*/
+ MSG_HOMUN_EVOLVE = 0x3ba,
+/*20171018 to latest
+^ff0000^ff0000호문클루스를 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+You have decided to delete this Homunculus ^ff0000^ff0000. When deleted, the homunculus and its history will be deleted and they cannot be restored in the future. Would you like to continue?
+*/
+ MSG_DELETE_HOMUN = 0x3bb,
+/*20171018 to latest
+호문의 상태를 파일에 저장합니다.
+Save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_ON = 0x3bc,
+/*20171018 to latest
+호문의 상태를 파일에 저장하지 않습니다.
+Do not save Homunculus status as a file.
+*/
+ MSG_TRACE_AI_OFF = 0x3bd,
+/*20171018 to latest
+Crusader
+*/
+ MSG_CRUSADER = 0x3be,
+/*20171018 to latest
+Monk
+*/
+ MSG_MONK = 0x3bf,
+/*20171018 to latest
+Sage
+*/
+ MSG_SAGE = 0x3c0,
+/*20171018 to latest
+Rouge
+Rogue
+*/
+ MSG_ROGUE = 0x3c1,
+/*20171018 to latest
+Alchemist
+*/
+ MSG_ALCHEMIST = 0x3c2,
+/*20171018 to latest
+Bard
+*/
+ MSG_BARD = 0x3c3,
+/*20171018 to latest
+Crusader_W
+Crusader
+*/
+ MSG_CRUSADER_W = 0x3c4,
+/*20171018 to latest
+Monk_W
+Monk
+*/
+ MSG_MONK_W = 0x3c5,
+/*20171018 to latest
+Sage_W
+Sage
+*/
+ MSG_SAGE_W = 0x3c6,
+/*20171018 to latest
+Rouge_W
+Rogue
+*/
+ MSG_ROGUE_W = 0x3c7,
+/*20171018 to latest
+Alchemist_W
+Alchemist
+*/
+ MSG_ALCHEMIST_W = 0x3c8,
+/*20171018 to latest
+Dancer
+*/
+ MSG_DANCER = 0x3c9,
+/*20171018 to latest
+Novice High
+High Novice
+*/
+ MSG_NOVICE_H = 0x3ca,
+/*20171018 to latest
+Swordman High
+High Swordman
+*/
+ MSG_SWORDMAN_H = 0x3cb,
+/*20171018 to latest
+Magician High
+High Mage
+*/
+ MSG_MAGICIAN_H = 0x3cc,
+/*20171018 to latest
+Archer High
+High Archer
+*/
+ MSG_ARCHER_H = 0x3cd,
+/*20171018 to latest
+Acolyte High
+High Acolyte
+*/
+ MSG_ACOLYTE_H = 0x3ce,
+/*20171018 to latest
+Merchant High
+High Merchant
+*/
+ MSG_MERCHANT_H = 0x3cf,
+/*20171018 to latest
+Thief High
+High Thief
+*/
+ MSG_THIEF_H = 0x3d0,
+/*20171018 to latest
+Novice High_W
+High Novice
+*/
+ MSG_NOVICE_H_W = 0x3d1,
+/*20171018 to latest
+Swordman High_W
+High Swordman
+*/
+ MSG_SWORDMAN_H_W = 0x3d2,
+/*20171018 to latest
+Magician High_W
+High Mage
+*/
+ MSG_MAGICIAN_H_W = 0x3d3,
+/*20171018 to latest
+Archer High_W
+High Archer
+*/
+ MSG_ARCHER_H_W = 0x3d4,
+/*20171018 to latest
+Acolyte High_W
+High Acolyte
+*/
+ MSG_ACOLYTE_H_W = 0x3d5,
+/*20171018 to latest
+Merchant High_W
+High Merchant
+*/
+ MSG_MERCHANT_H_W = 0x3d6,
+/*20171018 to latest
+Thief High_W
+High Thief
+*/
+ MSG_THIEF_H_W = 0x3d7,
+/*20171018 to latest
+Lord Knight
+*/
+ MSG_KNIGHT_H = 0x3d8,
+/*20171018 to latest
+High Priest
+*/
+ MSG_PRIEST_H = 0x3d9,
+/*20171018 to latest
+High Wizard
+*/
+ MSG_WIZARD_H = 0x3da,
+/*20171018 to latest
+White Smith
+MasterSmith
+*/
+ MSG_BLACKSMITH_H = 0x3db,
+/*20171018 to latest
+Sniper
+*/
+ MSG_HUNTER_H = 0x3dc,
+/*20171018 to 20181128
+Saaassin Cross
+Assassin Cross
+20181212 to latest
+Assassin Cross
+*/
+ MSG_ASSASSIN_H = 0x3dd,
+/*20171018 to latest
+Lord Knight_W
+Lord Knight
+*/
+ MSG_KNIGHT_H_W = 0x3de,
+/*20171018 to latest
+High Priest_W
+High Priest
+*/
+ MSG_PRIEST_H_W = 0x3df,
+/*20171018 to latest
+High Wizard_W
+High Wizard
+*/
+ MSG_WIZARD_H_W = 0x3e0,
+/*20171018 to latest
+White Smith_W
+WhiteSmith
+*/
+ MSG_BLACKSMITH_H_W = 0x3e1,
+/*20171018 to latest
+Sniper_W
+Sniper
+*/
+ MSG_HUNTER_H_W = 0x3e2,
+/*20171018 to 20181128
+Saaassin Cross_W
+Assassin Cross
+20181212 to latest
+Assassin Cross_W
+*/
+ MSG_ASSASSIN_H_W = 0x3e3,
+/*20171018 to latest
+Paladin
+*/
+ MSG_CRUSADER_H = 0x3e4,
+/*20171018 to latest
+Champion
+*/
+ MSG_MONK_H = 0x3e5,
+/*20171018 to latest
+Professor
+Scholar
+*/
+ MSG_SAGE_H = 0x3e6,
+/*20171018 to latest
+Stalker
+*/
+ MSG_ROGUE_H = 0x3e7,
+/*20171018 to latest
+Creator
+Biochemist
+*/
+ MSG_ALCHEMIST_H = 0x3e8,
+/*20171018 to latest
+Clown
+Minstrel
+*/
+ MSG_BARD_H = 0x3e9,
+/*20171018 to latest
+Paladin_W
+Paladin
+*/
+ MSG_CRUSADER_H_W = 0x3ea,
+/*20171018 to latest
+Champion_W
+Champion
+*/
+ MSG_MONK_H_W = 0x3eb,
+/*20171018 to latest
+Professor_W
+Professor
+*/
+ MSG_SAGE_H_W = 0x3ec,
+/*20171018 to latest
+Stalker_W
+Stalker
+*/
+ MSG_ROGUE_H_W = 0x3ed,
+/*20171018 to latest
+Creator_W
+Creator
+*/
+ MSG_ALCHEMIST_H_W = 0x3ee,
+/*20171018 to latest
+Gypsy
+*/
+ MSG_DANCER_H = 0x3ef,
+/*20171018 to latest
+비밀번호가 지정되어 있지 않습니다. 새로운 비밀번호를 지정하시겠습니까?
+You have not set a password yet. Would you like to create one now?
+*/
+ MSG_STORE_PASSWORD_REQ = 0x3f0,
+/*20171018 to latest
+비밀번호를 3회 틀려셨습니다. 나중에 다시 시도해 주세요.
+You have incorrectly entered the password 3 times. Please try again later.
+*/
+ MSG_STORE_PASSWORD_PENALTY = 0x3f1,
+/*20171018 to latest
+비밀번호 변경이 실패하였습니다.
+Password creation has failed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_NG = 0x3f2,
+/*20171018 to latest
+비밀번호는 4자리 이상 8자리이하여야만 합니다.
+Password must be 4~8 letters long.
+*/
+ MSG_STORE_PASSWORD_4_8 = 0x3f3,
+/*20171018 to latest
+비밀번호
+Password
+*/
+ MSG_STORE_PASSWORD = 0x3f4,
+/*20171018 to latest
+신규 비밀번호
+New Password
+*/
+ MSG_STORE_NEW_PASSWORD = 0x3f5,
+/*20171018 to latest
+확인 비밀번호
+Confirm Password
+*/
+ MSG_STORE_RENEW_PASSWORD = 0x3f6,
+/*20171018 to latest
+비밀번호 변경이 완료되었습니다.
+Password has been changed.
+*/
+ MSG_STORE_PASSWORD_CHANGE_OK = 0x3f7,
+/*20171018 to latest
+비밀번호가 서로 다릅니다.
+Password does not match.
+*/
+ MSG_STORE_PASSWORD_MISMATCH = 0x3f8,
+/*20171018 to latest
+비밀번호 입력
+Enter Password
+*/
+ MSG_STORE_PASSWORD_INPUT = 0x3f9,
+/*20171018 to latest
+호문이 아사 직전입니다! 먹이를 주지 않으면 가출하게됩니다.
+Your Homunculus is starving. Please feed it, otherwise it will leave you.
+*/
+ MSG_HOMUN_HUNGRY = 0x3fa,
+/*20171018 to latest
+경험치
+EXP
+*/
+ MSG_HOMUN_EXP = 0x3fb,
+/*20171018 to latest
+수령하지 않은 아이템이 존재합니다. 알베르타의 존다 기획사 직원을 찾아주세요. ^ff0000※ 아이템 수령 기간이 지나면 아이템이 소실 됩니다!^000000
+[EVENT] You have won an event prize. Please claim your prize in game.
+*/
+ MSG_EVENT_RESULT = 0x3fc,
+/*20171018 to latest
+싫어함
+Hate
+*/
+ MSG_HATE = 0x3fd,
+/*20171018 to latest
+매우싫어함
+Hate with a Passion
+*/
+ MSG_VERYHATE = 0x3fe,
+/*20171018 to latest
+호문클루스가 사용자 인공지능으로 동작합니다.
+Homunculus has been customized.
+*/
+ MSG_HOMUN_USERAI_ON = 0x3ff,
+/*20171018 to latest
+호문클루스가 기본 인공지능으로 동작합니다.
+Homunculus has been activated with the basic AI.
+*/
+ MSG_HOMUN_USERAI_OFF = 0x400,
+/*20171018 to latest
+편지목록
+Mail List
+*/
+ MSG_MAIL_LIST = 0x401,
+/*20171018 to latest
+편지쓰기
+Write Mail
+*/
+ MSG_MAIL_WRITE = 0x402,
+/*20171018 to latest
+편지읽기
+Read Mail
+*/
+ MSG_MAIL_READ = 0x403,
+/*20171018 to latest
+한번 지정하시면 변경이 불가능합니다! 이 맵으로 지정하시겠습니까?
+You cannot change a map's designation once it is designated. Are you sure that you want to designate this map?
+*/
+ MSG_STARPLACE_ACCEPT = 0x404,
+/*20171018 to latest
+메일 아이템을 수령했습니다.
+Item has been added in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_SUCCESS = 0x405,
+/*20171018 to latest
+메일 아이템을 수령하지 못했습니다.
+You have failed to add the item in the Item Window.
+*/
+ MSG_MAIL_ADD_ITEM_FAILURE = 0x406,
+/*20171018 to latest
+메일 보내기가 성공하였습니다.
+You have successfully mailed a message.
+*/
+ MSG_MAIL_SEND_SUCCESS = 0x407,
+/*20171018 to latest
+메일 보내기가 실패하였습니다. 받는 사람이 존재하지 않습니다.
+You have failed to mail a message. Recipient does not exist.
+*/
+ MSG_MAIL_USER_NOT_FOUND = 0x408,
+/*20171018 to latest
+[태양과 달과 별의 천사] 지정했던 장소들과 몬스터들이 초기화됐습니다!
+[Solar, Lunar and Stellar Angel] Designated places and monsters have been reset.
+*/
+ MSG_STAR_ANGEL = 0x409,
+/*20171018 to latest
+경매 등록이 실패했습니다.
+The minimum starting bid for auctions is 10,000,000 zeny.
+*/
+ MSG_AUCTION_ADD_FALSE = 0x40a,
+/*20171018 to latest
+경매 등록이 성공했습니다.
+You have successfully started a new auction.
+*/
+ MSG_AUCTION_ADD_TRUE = 0x40b,
+/*20171018 to latest
+해당 경매가 취소되었습니다.
+The auction has been canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL = 0x40c,
+/*20171018 to latest
+입찰자가 있는 경매는 취소할 수 없습니다.
+An auction with at least one bidder cannot be canceled.
+*/
+ MSG_AUCTION_ADD_CANCEL_FALSE = 0x40d,
+/*20171018 to latest
+메일 삭제가 성공하였습니다.
+Mail has been successfully deleted.
+*/
+ MSG_MAIL_DELETE_SUCCESS = 0x40e,
+/*20171018 to latest
+메일 삭제가 실패하였습니다.
+You have failed to delete the mail.
+*/
+ MSG_MAIL_DELETE_FAILURE = 0x40f,
+/*20171018 to latest
+던지는 단검이 장착되었습니다.
+You have equipped throwing daggers.
+*/
+ MSG_MSG_KNIFE_EQUIPMENT_SUCCESS = 0x410,
+/*20171018 to latest
+%s 님이 로그인했습니다.
+%s has logged in.
+*/
+ MSG_LOGIN_FRIEND = 0x411,
+/*20171018 to latest
+%s 님이 로그아웃했습니다.
+%s has logged out.
+*/
+ MSG_LOGOUT_FRIEND = 0x412,
+/*20171018 to latest
+/loginout : 길드원과 친구들의 접속관련 메세지를 보여줍니다. On Off
+/loginout: Shows guildsmen and friends online status. On Off
+*/
+ MSG_EXPLAIN_LOGINOUT = 0x413,
+/*20171018 to latest
+친구들의 접속관련 메세지를 대화창에 표시합니다. [/li ON]
+Display online status of friends in Chat Window. [/li ON]
+*/
+ MSG_LOGINOUT_ON = 0x414,
+/*20171018 to latest
+친구들의 접속관련 메세지를 대화창에 표시하지않습니다. [/li OFF]
+Do not display online status of friends in Chat Window. [/li OFF]
+*/
+ MSG_LOGINOUT_OFF = 0x415,
+/*20171018 to latest
+이미 실행중입니다.
+It is already running.
+*/
+ MSG_SGP_CODE_ALREADY_RUNNING = 0x416,
+/*20171018 to latest
+매크로 사용이 감지되었습니다.
+Use of Macro program has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MACRO = 0x417,
+/*20171018 to latest
+스피드해킹이 감지되었습니다.
+Use of Speed hack has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_SPEEDHACK = 0x418,
+/*20171018 to latest
+API 후킹이 감지되었습니다.
+API Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_APIHOOK = 0x419,
+/*20171018 to latest
+메시지 후킹이 감지되었습니다.
+Message Hooking has been detected.
+*/
+ MSG_SGP_CODE_DETECTED_MSGHOOK = 0x41a,
+/*20171018 to latest
+모듈이 변조 또는 손상되었거나 버전이 일치하지 않습니다.
+Module has been modified or damaged or its version does not match.
+*/
+ MSG_SGP_CODE_NOT_EQUALENCRYPTEDDATA = 0x41b,
+/*20171018 to latest
+(태국)귀하는 게임방 과금으로 로그인 하셨습니다.
+(Thailand) You have logged in game with PC cafe payment.
+*/
+ MSG_BILLING_PCB = 0x41c,
+/*20171018 to latest
+이전
+Prev
+*/
+ MSG_PREV_PAGE = 0x41d,
+/*20171018 to latest
+다음
+Next
+*/
+ MSG_NEXT_PAGE = 0x41e,
+/*20171018 to latest
+경매
+Auction
+*/
+ MSG_AUCTION = 0x41f,
+/*20171018 to latest
+물품보기
+Product List
+*/
+ MSG_AUCTION_VIEW = 0x420,
+/*20171018 to latest
+등록하기
+Register
+*/
+ MSG_AUCTION_ADD = 0x421,
+/*20171018 to latest
+판매 진행상태
+Sale Status
+*/
+ MSG_AUCTION_SELL = 0x422,
+/*20171018 to latest
+구매 진행상태
+Purchase Status
+*/
+ MSG_AUCTION_BUY = 0x423,
+/*20171018 to latest
+아이템
+Item
+*/
+ MSG_ITEM2 = 0x424,
+/*20171018 to latest
+아이템명
+Name
+*/
+ MSG_ITEM_NAME2 = 0x425,
+/*20171018 to latest
+가격 / 즉시구입가격
+Current Bid / Max Bid
+*/
+ MSG_ITEM_PRICE = 0x426,
+/*20171018 to latest
+판매자
+Seller
+*/
+ MSG_SELLER = 0x427,
+/*20171018 to latest
+구매자
+Buyer
+*/
+ MSG_BUYER = 0x428,
+/*20171018 to latest
+종료시간
+End Time
+*/
+ MSG_FINISH_TIME = 0x429,
+/*20171018 to latest
+%m월 %d일 %H시
+%m %d %H
+*/
+ MSG_TIME_TYPE = 0x42a,
+/*20171018 to latest
+시간설정
+Time (Hr)
+*/
+ MSG_SET_TIME = 0x42b,
+/*20171018 to latest
+수수료
+Fee
+*/
+ MSG_CHARGE = 0x42c,
+/*20171018 to latest
+검색된 아이템이 없습니다.
+No items found in search.
+*/
+ MSG_NOTHING_SEARCH_ITEM = 0x42d,
+/*20171018 to latest
+현재 판매중인 아이템이 없습니다.
+Your Sale List is empty.
+*/
+ MSG_NOTHING_SEARCH_SELL_ITEM = 0x42e,
+/*20171018 to latest
+현재 구매중인 아이템이 없습니다.
+Your Purchase List is empty.
+*/
+ MSG_NOTHING_SEARCH_BUY_ITEM = 0x42f,
+/*20171018 to latest
+경매정보가 정확하지 않습니다.
+Auction Information is incorrect or incomplete.
+*/
+ MSG_ERROR_AUCTION_ITEM_INFO = 0x430,
+/*20171018 to latest
+경매에 등록할 아이템 정보가 없습니다.
+You must drag and drop an item from your Inventory into the Register Window to begin a new auction.
+*/
+ MSG_NOTHING_AUCTION_ITEM_INFO = 0x431,
+/*20171018 to latest
+이미 등록된 경매입니다.
+The auction has already been registered.
+*/
+ MSG_ERROR_ADD_AUCTION = 0x432,
+/*20171018 to latest
+제시가격
+Starting Bid
+*/
+ MSG_PRICE = 0x433,
+/*20171018 to latest
+구입희망가격
+Current Bid
+*/
+ MSG_PRICE2 = 0x434,
+/*20171018 to latest
+즉시구입가격
+Buy Now Price
+*/
+ MSG_PRICE3 = 0x435,
+/*20171018 to latest
+현재소지제니
+Your Current Zeny
+*/
+ MSG_PRICE4 = 0x436,
+/*20171018 to latest
+현재최고가격
+Highest Bid
+*/
+ MSG_PRICE5 = 0x437,
+/*20171018 to latest
+이전입찰가격
+Previous Bid
+*/
+ MSG_PRICE6 = 0x438,
+/*20171018 to latest
+추가입찰가격
+Next Bid
+*/
+ MSG_PRICE7 = 0x439,
+/*20171018 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_BUY_ACTION_ITEM = 0x43a,
+/*20171018 to latest
+이 가격에 판매하시겠습니까?
+Would you like to sell this item?
+*/
+ MSG_SELL_ACTION_ITEM = 0x43b,
+/*20171018 to latest
+입찰하기
+Place Bid
+*/
+ MSG_BUY_AUCTION = 0x43c,
+/*20171018 to latest
+즉시구매하기
+Buy Now
+*/
+ MSG_BUY_AUCTION2 = 0x43d,
+/*20171018 to latest
+경매종료하기
+End the Auction
+*/
+ MSG_BUY_AUCTION3 = 0x43e,
+/*20171018 to latest
+재입찰하기
+Place another Bid
+*/
+ MSG_FINISH_AUCTION = 0x43f,
+/*20171018 to latest
+해당 경매에 대한 입찰이 성공했습니다.
+You have placed a bid.
+*/
+ MSG_RESULT_BUY_TRUE = 0x440,
+/*20171018 to latest
+해당 경매에 대한 입찰이 실패했습니다.
+You have failed to place a bid.
+*/
+ MSG_RESULT_BUY_FALSE = 0x441,
+/*20171018 to latest
+제니가 충분하지 않습니다.
+You do not have enough zeny.
+*/
+ MSG_RESULT_BUY_FALSE_MONEY = 0x442,
+/*20171018 to latest
+방어구
+Armors
+*/
+ MSG_EQUIP = 0x443,
+/*20171018 to latest
+카드
+Card
+*/
+ MSG_CARD = 0x444,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_ETC = 0x445,
+/*20171018 to latest
+경매번호
+Bid
+*/
+ MSG_AUCTION_NUM = 0x446,
+/*20171018 to latest
+검색
+Search
+*/
+ MSG_AUCTION_SEARCH = 0x447,
+/*20171018 to latest
+해당 경매를 종료했습니다.
+You have ended the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_TRUE = 0x448,
+/*20171018 to latest
+해당 경매를 종료 할 수 없습니다.
+You cannot end the auction.
+*/
+ MSG_RESULT_MY_SELL_STOP_FALSE = 0x449,
+/*20171018 to latest
+경매 번호가 정확하지 않습니다.
+Bid Number is incorrect.
+*/
+ MSG_RESULT_AUCTION_ID_FALSE = 0x44a,
+/*20171018 to latest
+받는이
+To
+*/
+ MSG_SENDER = 0x44b,
+/*20171018 to latest
+제 목
+Title
+*/
+ MSG_TITLE2 = 0x44c,
+/*20171018 to latest
+새 메일이 도착하였습니다.
+You have received a message in the mail.
+*/
+ MSG_NEW_MAIL = 0x44d,
+/*20171018 to latest
+검색중입니다.
+Searching...
+*/
+ MSG_SEARCHING_ITEM = 0x44e,
+/*20171018 to latest
+더 이상 경매 등록할 수 없습니다. 경매 등록은 최대 5개까지 가능합니다.
+You cannot register more than 5 items in an auction at a time.
+*/
+ MSG_AUCTION_ADD_OVER = 0x44f,
+/*20171018 to latest
+더 이상 경매 물품에 입찰할 수 없습니다. 경매 물품 입찰은 최대 5개까지 가능합니다.
+You cannot place more than 5 bids at a time.
+*/
+ MSG_RESULT_BUY_OVER = 0x450,
+/*20171018 to latest
+삭제하려는 메일에 수령하지 않은 아이템이 있습니다.
+Please accept all items from your mail before deleting.
+*/
+ MSG_MAIL_DELETE_ERROR = 0x451,
+/*20171018 to latest
+메일 제목을 입력하여 주십시오.
+Please enter a title.
+*/
+ MSG_MAIL_SEND_ERROR = 0x452,
+/*20171018 to latest
+/shopping : 클릭 한번으로 상점을 열고 상점이름 오른쪽 클릭으로 상점을 닫습니다 On Off
+/shopping: Enables you to open a shop with a single left-click and close your shop with a single right-click. On Off
+*/
+ MSG_EXPLAIN_SHOPPING = 0x453,
+/*20171018 to latest
+클릭 한번으로 상점을 열고 상점이름을 오른쪽 클릭해서 상점을 닫을수있습니다. [/sh ON]
+You can now open a shop with a single left-click and close your shop with a single right-click. [sh ON].
+*/
+ MSG_SHOPPING_ON = 0x454,
+/*20171018 to latest
+더블클릭 으로 상점을 열게됩니다. [/sh OFF]
+You can open a shop by double-clicking. [/sh OFF]
+*/
+ MSG_SHOPPING_OFF = 0x455,
+/*20171018 to latest
+메일을 보내려면, 제니 입력을 완료해야 합니다.
+Please enter zeny amount before sending mail.
+*/
+ MSG_MAIL_SEND_ERROR2 = 0x456,
+/*20171018 to latest
+경매 수수료가 부족합니다.
+You do not have enough zeny to pay the Auction Fee.
+*/
+ MSG_ADD_MONEY_FALSE = 0x457,
+/*20171018 to latest
+상태보기
+View Status
+*/
+ MSG_HOMUN_SHOWINFO = 0x458,
+/*20171018 to latest
+먹이주기
+Feed
+*/
+ MSG_HOMUN_FEEDING = 0x459,
+/*20171018 to latest
+대기
+Stand By
+*/
+ MSG_HOMUN_WAITING = 0x45a,
+/*20171018 to latest
+슈퍼노비스(남)
+Super Novice (Male)
+*/
+ MSG_JOB_SUPERNOVICE_M = 0x45b,
+/*20171018 to latest
+슈퍼노비스(여)
+Super Novice (Female)
+*/
+ MSG_JOB_SUPERNOVICE_F = 0x45c,
+/*20171018 to latest
+태권소년
+Taekwon Boy
+*/
+ MSG_JOB_TAEKWON_M = 0x45d,
+/*20171018 to latest
+태권소녀
+Taekwon Girl
+*/
+ MSG_JOB_TAEKWON_F = 0x45e,
+/*20171018 to latest
+권성(남)
+Taekwon Master (Male)
+*/
+ MSG_KWONSUNG_M = 0x45f,
+/*20171018 to latest
+권성(여)
+Taekwon Master (Female)
+*/
+ MSG_KWONSUNG_F = 0x460,
+/*20171018 to latest
+소울링커(남)
+Soul Linker (Male)
+*/
+ MSG_SOULLINGKER_M = 0x461,
+/*20171018 to latest
+소울링커(여)
+Soul Linker (Female)
+*/
+ MSG_SOULLINGKER_F = 0x462,
+/*20171018 to latest
+PC방요금제로 2개이상의 계정이 접속되고있습니다. 확인후 다시 사용하시기 바랍니다.
+Please check the connection, more than 2 accounts are connected with Internet Cafe Time Plan.
+*/
+ MSG_BAN_PC_IP_UNFAIR = 0x463,
+/*20171018 to latest
+귀하는 월정액 요금제 사용자 입니다. (남은기간 : %d일)
+Your account is using monthly payment. (Remaining day: %d day)
+*/
+ MSG_BILLING_1 = 0x464,
+/*20171018 to latest
+귀하는 정량 요금제 사용자 입니다. (남은시간 : %d시간 %분 %초)
+Your account is using time limited. (Remaining time: %d hour %d minute %d second)
+*/
+ MSG_BILLING_2 = 0x465,
+/*20171018 to latest
+해당 아이템은 메일에 첨부 할수 없는 아이템입니다.
+This item cannot be mailed.
+*/
+ MSG_MAIL_ITEM_ADD_FAILED = 0x466,
+/*20171018 to latest
+더이상 아이템을 가질수 없습니다. 아이템은 메일로 보관하겠습니다.
+You cannot accept any more items. Please try again later.
+*/
+ MSG_MAIL_ADD_ITEM_OVER_FAILURE = 0x467,
+/*20171018 to latest
+남성
+Male
+*/
+ MSG_PTSEX1 = 0x468,
+/*20171018 to latest
+여성
+Female
+*/
+ MSG_PTSEX2 = 0x469,
+/*20171018 to latest
+새로운 유저입니다
+New User.
+*/
+ MSG_PT_NEWUSER = 0x46a,
+/*20171018 to latest
+E-mail은 캐릭터를 지울때 필요합니다.
+E-mail address is required to delete a character.
+*/
+ MSG_PT_ACINFO = 0x46b,
+/*20171018 to latest
+정확한 형식으로 입력해 주세요.
+Please enter the correct information.
+*/
+ MSG_PT_ACINFO2 = 0x46c,
+/*20171018 to latest
+이 키를 사용하세요
+Please use this key.
+*/
+ MSG_PT_NEWKEYINFO = 0x46d,
+/*20171018 to latest
+정확한 카드 패스워드를 다시 입력해주세요
+Please enter the correct card password.
+*/
+ MSG_PT_FAIL_CARDPASS = 0x46e,
+/*20171018 to latest
+PT정보
+PT Info
+*/
+ MSG_PTID1 = 0x46f,
+/*20171018 to latest
+PT_ID는 %s
+PT_ID is %s
+*/
+ MSG_PTID2 = 0x470,
+/*20171018 to latest
+NUM_ID는 %s
+NUM_ID is %s
+*/
+ MSG_PTID3 = 0x471,
+/*20171018 to latest
+잊지않게 주의하세요
+Please don't forget this information.
+*/
+ MSG_PTID4 = 0x472,
+/*20171018 to latest
+1001
+*/
+ MSG_PT_ERROR_1001 = 0x473,
+/*20171018 to latest
+1002
+*/
+ MSG_PT_ERROR_1002 = 0x474,
+/*20171018 to latest
+1003
+*/
+ MSG_PT_ERROR_1003 = 0x475,
+/*20171018 to latest
+1004
+*/
+ MSG_PT_ERROR_1004 = 0x476,
+/*20171018 to latest
+1006
+*/
+ MSG_PT_ERROR_1006 = 0x477,
+/*20171018 to latest
+1007
+*/
+ MSG_PT_ERROR_1007 = 0x478,
+/*20171018 to latest
+1008
+*/
+ MSG_PT_ERROR_1008 = 0x479,
+/*20171018 to latest
+1009
+*/
+ MSG_PT_ERROR_1009 = 0x47a,
+/*20171018 to latest
+1012
+*/
+ MSG_PT_ERROR_1012 = 0x47b,
+/*20171018 to latest
+1013
+*/
+ MSG_PT_ERROR_1013 = 0x47c,
+/*20171018 to latest
+1014
+*/
+ MSG_PT_ERROR_1014 = 0x47d,
+/*20171018 to latest
+1015
+*/
+ MSG_PT_ERROR_1015 = 0x47e,
+/*20171018 to latest
+1019
+*/
+ MSG_PT_ERROR_1019 = 0x47f,
+/*20171018 to latest
+1020
+Navigation
+*/
+ MSG_PT_ERROR_1020 = 0x480,
+/*20171018 to latest
+1021
+*/
+ MSG_PT_ERROR_1021 = 0x481,
+/*20171018 to latest
+1023
+*/
+ MSG_PT_ERROR_1023 = 0x482,
+/*20171018 to latest
+1024
+*/
+ MSG_PT_ERROR_1024 = 0x483,
+/*20171018 to latest
+1025
+*/
+ MSG_PT_ERROR_1025 = 0x484,
+/*20171018 to latest
+1027
+*/
+ MSG_PT_ERROR_1027 = 0x485,
+/*20171018 to latest
+1028
+*/
+ MSG_PT_ERROR_1028 = 0x486,
+/*20171018 to latest
+10
+*/
+ MSG_PT_ERROR_10 = 0x487,
+/*20171018 to latest
+20
+*/
+ MSG_PT_ERROR_20 = 0x488,
+/*20171018 to latest
+40
+*/
+ MSG_PT_ERROR_40 = 0x489,
+/*20171018 to latest
+50
+*/
+ MSG_PT_ERROR_50 = 0x48a,
+/*20171018 to latest
+60
+*/
+ MSG_PT_ERROR_60 = 0x48b,
+/*20171018 to latest
+70
+*/
+ MSG_PT_ERROR_70 = 0x48c,
+/*20171018 to latest
+80
+*/
+ MSG_PT_ERROR_80 = 0x48d,
+/*20171018 to latest
+90
+*/
+ MSG_PT_ERROR_90 = 0x48e,
+/*20171018 to latest
+100
+*/
+ MSG_PT_ERROR_100 = 0x48f,
+/*20171018 to latest
+110
+*/
+ MSG_PT_ERROR_110 = 0x490,
+/*20171018 to latest
+30포인트를 받으시겠습니까?
+Do you want to receive 30 points?
+*/
+ MSG_PT_POINT1 = 0x491,
+/*20171018 to latest
+30포인트(5시간)이 충전되었습니다
+30 points (5 hours) have been added.
+*/
+ MSG_PT_POINT2 = 0x492,
+/*20171018 to latest
+감정되지 않은 아이템은 경매에 등록할 수 없습니다.
+You cannot register Unidentified Items in auctions.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE = 0x493,
+/*20171018 to latest
+소비 아이템은 경매에 등록할 수 없습니다.
+You cannot register this Consumable Item in an auction.
+*/
+ MSG_AUCTION_ADD_ITEM_FAILURE2 = 0x494,
+/*20171018 to latest
+메일창을 열려면 카트창을 닫아 주십시요.
+Please close the Cart Window to open the Mail Window.
+*/
+ MSG_CLOSE_MERCHANTITEMWND = 0x495,
+/*20171018 to latest
+카트창을 열려면 메일창을 닫아 주십시요.
+Please close the Mail Window to open the Cart Window.
+*/
+ MSG_CLOSE_MAILWND = 0x496,
+/*20171018 to latest
+탄환이 장착되었습니다.
+Bullets have been equipped.
+*/
+ MSG_MSG_BULLET_EQUIPMENT_SUCCESS = 0x497,
+/*20171018 to latest
+메일이 반송되었습니다.
+The mail has been returned to sender.
+*/
+ MSG_MAIL_RETURN_SUCCESS = 0x498,
+/*20171018 to latest
+메일이 존재하지 않습니다.
+The mail no longer exists.
+*/
+ MSG_MAIL_RETURN_FAILURE = 0x499,
+/*20171018 to latest
+한시간 동안, 동일한 IP로 접속한 유저가 30건 이상입니다. 확인후 다시 사용하시기 바랍니다.
+More than 30 players sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT_ALL = 0x49a,
+/*20171018 to latest
+한시간 동안, 동일한 IP로 10번 이상 접속되었습니다. 확인후 다시 사용하시기 바랍니다.
+More than 10 connections sharing the same IP have logged into the game for an hour. Please check this matter.
+*/
+ MSG_BAN_PC_IP_COUNT = 0x49b,
+/*20171018 to latest
+게임을 재시작 하십시오
+Please restart the game.
+*/
+ MSG_GAMEGUARD_RESTART = 0x49c,
+/*20171018 to latest
+용병정보 - 아쳐타입
+Mercenary: Archer
+*/
+ MSG_MER_INFO_TYPE_ARCHER = 0x49d,
+/*20171018 to latest
+용병정보 - 검사타입
+Mercenary: Swordman
+*/
+ MSG_MER_INFO_TYPE_SWORDMAN = 0x49e,
+/*20171018 to latest
+용병정보 - 창병타입
+Mercenary: Spearman
+*/
+ MSG_MER_INFO_TYPE_LANCER = 0x49f,
+/*20171018 to latest
+삭제시간
+Expiration
+*/
+ MSG_LEFT_TIME = 0x4a0,
+/*20171018 to latest
+신뢰도
+Loyalty
+*/
+ MSG_MER_FRIENDLY = 0x4a1,
+/*20171018 to latest
+소환횟수
+Summons
+*/
+ MSG_MER_CALLCOUNT = 0x4a2,
+/*20171018 to latest
+Kill
+*/
+ MSG_MER_KILL = 0x4a3,
+/*20171018 to latest
+펫이 배가 고파서 당신을 원망하고 있다는 느낌이 든다.
+You can feel hatred from your pet for neglecting to feed it.
+*/
+ MSG_PET_STARVING = 0x4a4,
+/*20171018 to latest
+[POINT] 테이밍미션 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[POINT] You earned %d Taming Mission Ranking Points, giving you a total of %d points.
+*/
+ MSG_GANGSI_POINT = 0x4a5,
+/*20171018 to latest
+[테이밍미션] Target Monster : %s
+[Taming Mission] Target Monster: %s
+*/
+ MSG_GANGSI_MISSION = 0x4a6,
+/*20171018 to latest
+/hunting : 사냥 목록을 보여줍니다.
+/hunting: You can check the your hunting list.
+*/
+ MSG_EXPLAIN_HUNTING = 0x4a7,
+/*20171018 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s는 몇 스킬 찍으셨나요?
+[Angel's Question] Please tell me, how many %s skills do you have?
+*/
+ MSG_DEATH_Q01 = 0x4a8,
+/*20171018 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 소지하시고있는 제니를 십만으로 나누면 얼마가 되시나요?
+[Angel's Question] Please tell me, how much zeny you'll have if you divide it by 100,000?
+*/
+ MSG_DEATH_Q02 = 0x4a9,
+/*20171018 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. 오늘이 몇일이신지 아시나요?
+[Angel's Question] Please tell me, what is today's date?
+*/
+ MSG_DEATH_Q03 = 0x4aa,
+/*20171018 to latest
+[천사의질문] 소녀에게 가르쳐주시어요. %s은 지금 몇이신가요?
+[Angel's Question] Please tell me, how many %s do you have?
+*/
+ MSG_DEATH_Q04 = 0x4ab,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 슈노, 태권계열, 무낙계열을 담당하고있는 SiYeon씨의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in SiYeon's name?
+*/
+ MSG_DEATH_Q05 = 0x4ac,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 귀엽고 어여쁜 라그나로크의 히로인 Munak의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Munak's name?
+*/
+ MSG_DEATH_Q06 = 0x4ad,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 제가 어여뻐하는 Bongun의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in Bongun's name?
+*/
+ MSG_DEATH_Q07 = 0x4ae,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 저희가 존재하는 온라인세계 Ragnarok의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, Ragnarok?
+*/
+ MSG_DEATH_Q08 = 0x4af,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 언제나 Online상태인 천사동료들은 큰힘이 되어주죠. Online의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, online?
+*/
+ MSG_DEATH_Q09 = 0x4b0,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 죽음도 두려워하지않는 기사들을 상징하는 단어인 Death의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, death?
+*/
+ MSG_DEATH_Q10 = 0x4b1,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 기사들은 너무 멋진다고 생각해요. Knight의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, knight?
+*/
+ MSG_DEATH_Q11 = 0x4b2,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 중력을 뜻하는 단어인 Gravity의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, gravity?
+*/
+ MSG_DEATH_Q12 = 0x4b3,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 어둠속에서도 밝게 사는게 중요하지요. Dark의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, dark?
+*/
+ MSG_DEATH_Q13 = 0x4b4,
+/*20171018 to latest
+[천사의질문] A는 1이고 Z는 26이어요. 뭐든지 수집하는 Collector의 알파벳을 더하면 몇이 되나요?
+[Angel's Question] If A is 1, B is 2, and so on, and if Z is 26, what number do you get if you add the letters in the word, collecter?
+*/
+ MSG_DEATH_Q14 = 0x4b5,
+/*20171018 to latest
+[천사의대답] 소녀에게 정확한 사실을 가르쳐주셔서 감사하옵니다.
+[Angel's Answer] Thank you for letting me know~
+*/
+ MSG_DEATH_R01 = 0x4b6,
+/*20171018 to latest
+[천사의대답] 사랑스러우신 분이시군요. 소녀 감탄했사옵니다.
+[Angel's Answer] I'm very pleased with your answer. You are a splendid adventurer.
+*/
+ MSG_DEATH_R02 = 0x4b7,
+/*20171018 to latest
+[천사의대답] 소녀 실망했사옵니다.
+[Angel's Answer] You've disappointed me...
+*/
+ MSG_DEATH_R05 = 0x4b8,
+/*20171018 to latest
+[POINT] 랭킹포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You earned %d Ranking Points, giving you a total of %d Ranking Points.
+*/
+ MSG_DEATH_POINT = 0x4b9,
+/*20171018 to latest
+[%s]의 소지 캐시 : %d 캐시
+[%s]'s Points: %d Points
+*/
+ MSG_POINT_SHOP = 0x4ba,
+/*20171018 to latest
+선택하지 않은 캐릭터는 삭제 됩니다. 완료하시겠습니까?
+Unselected Characters will be deleted. Continue?
+*/
+ MSG_CONFIRM_SELECT_CHARACTERS = 0x4bb,
+/*20171018 to latest
+9개 이상 선택하실 수 없습니다.
+You cannot select more than 8.
+*/
+ MSG_ERROR_SELECT_CHARACTERS = 0x4bc,
+/*20171018 to latest
+캐릭터명을 '%s' (으)로 변경하시겠습니까?
+Do you want to change your name to '%s'?
+*/
+ MSG_CONFIRM_TO_CHANGE_NAME = 0x4bd,
+/*20171018 to latest
+캐릭터명이 성공적으로 변경되었습니다.
+Character Name has been changed successfully.
+*/
+ MSG_CHANGE_NAME_SUCCESS = 0x4be,
+/*20171018 to latest
+캐릭터명 변경이 실패하였습니다.
+You have failed to change this character's name.
+*/
+ MSG_CHANGE_NAME_FAILURE = 0x4bf,
+/*20171018 to latest
+한 번에 한 종류의 아이템만 구매할 수 있습니다.
+You can purchase only one kind of item at a time.
+*/
+ MSG_CAN_BUY_ONLY_ONEITEM = 0x4c0,
+/*20171018 to latest
+캐릭터가 한개도 선택되지 않았습니다. 반드시 한개 이상의 캐릭터를 선택하여야 합니다.
+No characters were selected. You must select at least one character.
+*/
+ MSG_NO_SELECT_CHARACTERS = 0x4c1,
+/*20171018 to latest
+이미 캐릭터명을 변경한 적이 있습니다. 더 이상 변경 할 수 없습니다.
+This character's name has already been changed. You cannot change a character's name more than once.
+*/
+ MSG_ALREADY_CHANGED_NAME = 0x4c2,
+/*20171018 to latest
+사용자 정보가 정확하지 않습니다.
+User Information is not correct.
+*/
+ MSG_NOTREGISTED_USER = 0x4c3,
+/*20171018 to latest
+다른 사용자가 같은 캐릭터 명을 먼저 사용하였습니다. 다른 캐릭터명을 사용하여 주십시요.
+Another user is using this character name, so please select another one.
+*/
+ MSG_DUPLICATED_CHAR_NAME = 0x4c4,
+/*20171018 to latest
+파티장 권한이 없어 파티원을 소환하지 못했습니다.
+The party member was not summoned because you are not the party leader.
+*/
+ MSG_CANNOT_PARTYCALL = 0x4c5,
+/*20171018 to latest
+현재 맵에는 소환될 파티원이 존재하지 않습니다.
+There is no party member to summon in the current map.
+*/
+ MSG_NO_PARTYMEM_ON_THISMAP = 0x4c6,
+/*20171018 to latest
+이 지역에선 보스몬스터의 흔적을 찾을 수가 없습니다.
+You cannot find any trace of a Boss Monster in this area.
+*/
+ MSG_NOTFIND_BOSSMON = 0x4c7,
+/*20171018 to latest
+보스 몬스터 '%s'(이)가 %d시간 %d분 후에 등장합니다.
+Boss Monster, '%s' will appear in %02d hour(s) and %02d minute(s).
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON = 0x4c8,
+/*20171018 to latest
+보스 몬스터 '%s'의 위치가 미니맵에 표시됩니다.
+The location of Boss Monster, '%s', will be displayed on your Mini-Map.
+*/
+ MSG_SHOW_POSITION_OF_BOSSMON = 0x4c9,
+/*20171018 to latest
+'%s'를 개봉 하시겠습니까? ^ff0000상자를 개봉하시면 청약 철회 대상에서 제외 됩니다.^000000 한번 개봉 된 아이템은 창고 저장 외의 다른 이동은 불가하며 임대 아이템은 창고 저장도 불가합니다. 한정 아이템은 거래 및 이동이 가능 합니다. 동일한 아이템을 중복 사용하더라도 효과가 중첩되지 않습니다.
+Do you want to open '%s'? Once opened, the contents cannot be moved to other locations aside from the Kafra Storage. The item effect isn't doubled, even if the same items are used more than once.
+*/
+ MSG_CONFIRM_TO_OPEN_CASH_ITEM = 0x4ca,
+/*20171018 to latest
+NPC가 존재하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the NPC does not exist.
+*/
+ MSG_BUY_CASH_FAIL_NPC = 0x4cb,
+/*20171018 to latest
+부분 유료화 시스템이 정상 작동하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Kafra Shop System is not working correctly.
+*/
+ MSG_BUY_CASH_FAIL_SYSTEM = 0x4cc,
+/*20171018 to latest
+교환중에는 아이템을 구매 할 수 없습니다.
+You cannot purchase items while you are in a trade.
+*/
+ MSG_BUY_CASH_FAIL_EXCHANGE = 0x4cd,
+/*20171018 to latest
+아이템 정보가 정확하지 않아 구매가 실패하였습니다.
+The Purchase has failed because the Item Information was incorrect.
+*/
+ MSG_BUY_CASH_FAIL_ITEM_ID = 0x4ce,
+/*20171018 to latest
+ STR이 향상되었습니다.
+STR has increased.
+*/
+ MSG_ENST_STR = 0x4cf,
+/*20171018 to latest
+ STR이 원래대로 돌아왔습니다.
+STR has returned to normal.
+*/
+ MSG_DSST_STR = 0x4d0,
+/*20171018 to latest
+ AGI이 향상되었습니다.
+AGI has increased.
+*/
+ MSG_ENST_AGI = 0x4d1,
+/*20171018 to latest
+ AGI이 원래대로 돌아왔습니다.
+AGI has returned to normal.
+*/
+ MSG_DSST_AGI = 0x4d2,
+/*20171018 to latest
+ VIT이 향상되었습니다.
+VIT has increased.
+*/
+ MSG_ENST_VIT = 0x4d3,
+/*20171018 to latest
+ VIT이 원래대로 돌아왔습니다.
+VIT has returned to normal.
+*/
+ MSG_DSST_VIT = 0x4d4,
+/*20171018 to latest
+ INT이 향상되었습니다.
+INT has increased.
+*/
+ MSG_ENST_INT = 0x4d5,
+/*20171018 to latest
+ INT이 원래대로 돌아왔습니다.
+INT has returned to normal.
+*/
+ MSG_DSST_INT = 0x4d6,
+/*20171018 to latest
+ DEX이 향상되었습니다.
+DEX has increased.
+*/
+ MSG_ENST_DEX = 0x4d7,
+/*20171018 to latest
+ DEX이 원래대로 돌아왔습니다.
+DEX has returned to normal.
+*/
+ MSG_DSST_DEX = 0x4d8,
+/*20171018 to latest
+ LUK이 향상되었습니다.
+LUK has increased.
+*/
+ MSG_ENST_LUK = 0x4d9,
+/*20171018 to latest
+ LUK이 원래대로 돌아왔습니다.
+LUK has returned to normal.
+*/
+ MSG_DSST_LUK = 0x4da,
+/*20171018 to latest
+ 회피율이 향상되었습니다.
+Flee Rate (Flee) has increased.
+*/
+ MSG_ENST_AVOIDANCE = 0x4db,
+/*20171018 to latest
+ 회피율이 원래대로 돌아왔습니다.
+Flee Rate has returned to normal.
+*/
+ MSG_DSST_AVOIDANCE = 0x4dc,
+/*20171018 to latest
+ 명중률이 향상되었습니다.
+Accuracy Rate (Hit) has increased.
+*/
+ MSG_ENST_HIT = 0x4dd,
+/*20171018 to latest
+ 명중률이 원래대로 돌아왔습니다.
+Accuracy Rate has returned to normal.
+*/
+ MSG_DSST_HIT = 0x4de,
+/*20171018 to latest
+ 크리티컬 확률이 향상되었습니다.
+Critical Attack (Critical) has increased.
+*/
+ MSG_ENST_CRITICALSUCCESSVALUE = 0x4df,
+/*20171018 to latest
+ 크리티컬 확률이 원래대로 돌아왔습니다.
+Critical Attack has returned to normal.
+*/
+ MSG_DSST_CRITICALSUCCESSVALUE = 0x4e0,
+/*20171018 to latest
+ 30분간 얻을 수 있는 경험치가 50%% 증가합니다.
+You will receive 1.5 times more EXP from hunting monsters for the next 30 minutes.
+*/
+ MSG_PLUSEXP = 0x4e1,
+/*20171018 to latest
+ 30분내 사망시 1회에 한해 경험치 감소가 일어나지 않습니다.
+This character will not receive any EXP penalty if killed within the next 30 minutes.
+*/
+ MSG_DDEATHPENALTY = 0x4e2,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 30분간 2배로 증가합니다.
+Regular item drops from monsters will be doubled for the next 30 minutes.
+*/
+ MSG_RECEIVEITEM = 0x4e3,
+/*20171018 to latest
+ 10분간 맵 내에 출현 가능한 보스 몬스터에 대한 정보를 안내해 드립니다.
+Boss Monster Map Information for the next 10 minutes.
+*/
+ MSG_BOSS_ALARM = 0x4e4,
+/*20171018 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+Do you really want to purchase this item? %d points will be deducted from your total Kafra Credit Points.
+*/
+ MSG_BUY_RECONFIRM = 0x4e5,
+/*20171018 to latest
+ 캐시가 부족합니다.
+ You do not have enough Kafra Credit Points.
+*/
+ MSG_BUY_CASH_FAIL_MONEY = 0x4e6,
+/*20171018 to latest
+ ^ff0000파기일시: %s^000000
+ ^ff0000Expiration Date: %s^000000
+*/
+ MSG_NOTICE_TO_DELETE_TIME = 0x4e7,
+/*20171018 to latest
+ '%s'아이템의 사용시간이 %d분 남았습니다.
+ The '%s' item will disappear in %d minutes.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e8,
+/*20171018 to latest
+ 1분 후, '%s'아이템이 인벤토리에서 삭제됩니다.
+ '%s' item will be deleted from the Inventory in 1 minute.
+*/
+ MSG_LAST_NOTICE_TO_REMAIN_ITEMUSINGTIME = 0x4e9,
+/*20171018 to latest
+ '%s'아이템이 인벤토리에서 삭제되었습니다.
+ '%s' item has been deleted from the Inventory.
+*/
+ MSG_NOTICE_TO_DELETE_ITEM = 0x4ea,
+/*20171018 to latest
+Input Number
+*/
+ MSG_INPUT_NUMBER = 0x4eb,
+/*20171018 to latest
+%m월 %d일 %H시 %M분
+%m/%d %H:%M
+*/
+ MSG_TIME_TYPE2 = 0x4ec,
+/*20171018 to latest
+보스 몬스터 '%s'(이)가 잠시 후에 등장합니다.
+Boss Monster '%s' will appear within 1 minute.
+*/
+ MSG_APPEARANCE_TIME_OF_BOSSMON2 = 0x4ed,
+/*20171018 to latest
+용병 스킬목록
+Mercenary Soldier Skill List
+*/
+ MSG_MER_SKILLLIST = 0x4ee,
+/*20171018 to latest
+블랙젬스톤 1개와 백만제니를 소모하는 마법의 실행에 동의합니까?
+Do you agree to cast the magic spell that consumes 1 Black Gemstone and 1,000,000 Zeny?
+*/
+ MSG_DA_EXP_ACCEPT = 0x4ef,
+/*20171018 to latest
+[POINT] 콜렉터랭킹 포인트가 %d 상승해서 %d 포인트가 되었습니다.
+[Point] You have gained %d Collector Rank Points; you now have a total of %d Collector Rank Points.
+*/
+ MSG_COLLECTOR_POINT = 0x4f0,
+/*20171018 to latest
+[콜렉터랭킹] Target Item : %s
+[Collector Rank] Target Item: %s
+*/
+ MSG_COLLECTOR_MISSION = 0x4f1,
+/*20171018 to latest
+용병 사용시간이 만료되었습니다.
+The mercenary contract has expired.
+*/
+ MSG_MER_FINISH = 0x4f2,
+/*20171018 to latest
+용병이 사망하였습니다.
+The mercenary has died.
+*/
+ MSG_MER_DIE = 0x4f3,
+/*20171018 to latest
+용병이 해고되었습니다.
+You have released the mercenary.
+*/
+ MSG_MER_RETIRE = 0x4f4,
+/*20171018 to latest
+용병이 도망갔습니다.
+The mercenary has run away.
+*/
+ MSG_MER_RUNAWAY = 0x4f5,
+/*20171018 to latest
+ '%s'아이템의 사용시간이 %d초 남았습니다.
+ The '%s' item will disappear in %d seconds.
+*/
+ MSG_NOTICE_TO_REMAIN_ITEMUSINGTIME2 = 0x4f6,
+/*20171018 to latest
+PC방 프리미엄 서비스 : 경험치 %d%% 증가, 사망 페널티 %d%% 감소, 드롭율 %d%% 증가
+IP Bonus: EXP/JEXP %d%%, Death Penalty %d%%, Item Drop %d%%
+*/
+ MSG_PCBANG_EVENT = 0x4f7,
+/*20171018 to latest
+24시간 이후에 시도하세요
+Symbols in Character Names are forbidden.
+*/
+ MSG_LIMIT_CHAR_DELETE = 0x4f8,
+/*20171018 to latest
+용병이 사용자 인공지능으로 동작합니다.
+Mercenary will follow custom AI.
+*/
+ MSG_MER_USERAI_ON = 0x4f9,
+/*20171018 to latest
+용병이 기본 인공지능으로 동작합니다.
+Mercenary will follow basic AI.
+*/
+ MSG_MER_USERAI_OFF = 0x4fa,
+/*20171018 to latest
+ %s님의
+ %s's
+*/
+ MSG_CHARACTER_NAME = 0x4fb,
+/*20171018 to latest
+%s님이 %s 아이템을 획득하셨습니다.
+%s has acquired %s.
+*/
+ MSG_ITEM_PICKUP_PARTY = 0x4fc,
+/*20171018 to latest
+공개 채팅 메시지 표시
+Public Chat Display
+*/
+ MSG_VIEW_CHAT_MSG = 0x4fd,
+/*20171018 to latest
+귓속말 채팅 메시지 표시
+Whisper Display
+*/
+ MSG_VIEW_WHISPER_MSG = 0x4fe,
+/*20171018 to latest
+파티 채팅 메시지 표시
+Party Chat Display
+*/
+ MSG_VIEW_PARTY_MSG = 0x4ff,
+/*20171018 to latest
+길드 채팅 메시지 표시
+Guild Chat Display
+*/
+ MSG_VIEW_GUILD_MSG = 0x500,
+/*20171018 to latest
+아이템 획득/드롭 메시지 표시
+Item Get/Drop Message Display
+*/
+ MSG_VIEW_GET_ITEM_MSG = 0x501,
+/*20171018 to latest
+장비 장착/해제 메시지 표시
+Equipment On/Off Message Display
+*/
+ MSG_VIEW_EQUIP_MSG = 0x502,
+/*20171018 to latest
+상태이상 메시지 표시
+Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_MSG = 0x503,
+/*20171018 to latest
+파티원의 주요 아이템 획득 메시지 표시
+Party Member's Obtained Item Message Display
+*/
+ MSG_VIEW_GET_ITEM_PARTY_MSG = 0x504,
+/*20171018 to latest
+파티원의 상태이상 메시지 표시
+Party Member's Abnormal Status Message Display
+*/
+ MSG_VIEW_CHANGE_STATUS_PARTY_MSG = 0x505,
+/*20171018 to latest
+스킬 사용 실패 메시지 표시
+Skill Failure Message Display
+*/
+ MSG_VIEW_FAIL_SKILL_MSG = 0x506,
+/*20171018 to latest
+파티 설정 메시지 표시
+Party Configuration Message Display
+*/
+ MSG_VIEW_PARTY_SETUP_MSG = 0x507,
+/*20171018 to latest
+장비 손상 메시지 표시
+Damaged Equipment Message Display
+*/
+ MSG_VIEW_DAMAGED_EQUIP_MSG = 0x508,
+/*20171018 to latest
+배틀 메시지 창 표시 정보
+Battle Message Window Display
+*/
+ MSG_BATTLE_CHAT_WND_OPTION = 0x509,
+/*20171018 to latest
+[%s]의 소지 한코인 : %d 한코인
+[%s]'s Han Coin: %d Han Coin
+*/
+ MSG_POINT_SHOP_NHN = 0x50a,
+/*20171018 to latest
+일반 메시지
+Public Log
+*/
+ MSG_ST_CHAT = 0x50b,
+/*20171018 to latest
+배틀 메시지
+Battle Log
+*/
+ MSG_BT_CHAT = 0x50c,
+/*20171018 to latest
+휴대폰 인증.
+Mobile Authentication
+*/
+ MSG_PHONE_CONFIRM = 0x50d,
+/*20171018 to latest
+읽기
+Read
+*/
+ MSG_BOOK_READ = 0x50e,
+/*20171018 to latest
+자동낭독
+Auto Read
+*/
+ MSG_BOOK_AUTOREAD = 0x50f,
+/*20171018 to latest
+책갈피
+Bookmark
+*/
+ MSG_BOOK_KEEP = 0x510,
+/*20171018 to latest
+이전페이지
+Previous
+*/
+ MSG_BOOK_PREV = 0x511,
+/*20171018 to latest
+다음페이지
+Next
+*/
+ MSG_BOOK_NEXT = 0x512,
+/*20171018 to latest
+닫기
+Close
+*/
+ MSG_BOOK_CLOSE = 0x513,
+/*20171018 to latest
+%s 장비가 손상되었습니다.
+%s's Equipment has been damaged.
+*/
+ MSG_DAMAGED_EQUIP = 0x514,
+/*20171018 to latest
+%s님의 %s 손상되었습니다.
+%s's %s was damaged.
+*/
+ MSG_DAMAGED_EQUIP_PARTY = 0x515,
+/*20171018 to latest
+무기가
+Weapon
+*/
+ MSG_DAMAGED_WEAPON = 0x516,
+/*20171018 to latest
+갑옷이
+Armor
+*/
+ MSG_DAMAGED_BODY = 0x517,
+/*20171018 to latest
+스킬레벨이 부족합니다. 파티가입 불능
+Insufficient Skill Level for joining a Party
+*/
+ MSG_NOT_ENOUGH_SKILLLEVE5_2 = 0x518,
+/*20171018 to latest
+[%s]의 무료 캐시 : %d 캐시
+[%s]'s Free Cash: %d Cash
+*/
+ MSG_POINT_SHOP2 = 0x519,
+/*20171018 to latest
+무료 캐시 사용 :
+Use Free Cash:
+*/
+ MSG_USE_FREE_POINT = 0x51a,
+/*20171018 to latest
+캐시
+Cash
+*/
+ MSG_CASH = 0x51b,
+/*20171018 to latest
+http://payment.ro.hangame.com/index.asp
+*/
+ MSG_SETTLE_WEB_URL_HANGAME = 0x51c,
+/*20171018 to latest
+그라비티 회원 정보동의를 하셔야 사용할 수 있습니다.
+You need to accept the Privacy Policy from Gravity in order to use the service.
+*/
+ MSG_BAN_GRAVITY_MEM_AGREE = 0x51d,
+/*20171018 to latest
+이용약관에 동의를 하셔야 본 서비스를 이용하실 수 있습니다.
+You need to accept the User Agreement in order to use the service.
+*/
+ MSG_BAN_GAME_MEM_AGREE = 0x51e,
+/*20171018 to latest
+입력하신 아이디와 비밀번호가 등록된 정보와 일치하지 않습니다.
+Incorrect or nonexistent ID.
+*/
+ MSG_BAN_HAN_VALID = 0x51f,
+/*20171018 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+Do you really want to purchase these items? You will spend %d Regular Cash Points and %d Free Cash Points.
+*/
+ MSG_BUY_RECONFIRM2 = 0x520,
+/*20171018 to latest
+%d시간이 경과하였습니다.
+%d hour(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME1 = 0x521,
+/*20171018 to latest
+%d시간 %d분이 경과하였습니다.
+%d hour(s) %d minute(s) has passed.
+*/
+ MSG_NOTIFY_PLAYTIME2 = 0x522,
+/*20171018 to latest
+게임을 종료하세요, 경험치 및 모든게 50%로 조정됩니다
+Please stop playing the game, and take a break. Exp and other features will be reduced to 50%.
+*/
+ MSG_WARNING_MSG1 = 0x523,
+/*20171018 to latest
+불건전 시간대에 접어들었습니다. 게임을 종료하세요, 경험치 및 모든게 0%로 조정됩니다
+Please stop playing the game since you'll need to rest. Exp and other features will be fixed to 0%.
+*/
+ MSG_WARNING_MSG2 = 0x524,
+/*20171018 to latest
+퀘스트 목록
+Quest List
+*/
+ MSG_QUESTWIN = 0x525,
+/*20171018 to latest
+RO SHOP
+*/
+ MSG_RO_SHOP = 0x526,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약이 알수없는 이유로 실패 하였습니다.
+Memorial Dungeon, '%s' is booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN = 0x527,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약이 예약중복으로 실패 하였습니다.
+Failed to book Memorial Dungeon, '%s'.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE = 0x528,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약이 권한문제로 실패 하였습니다.
+Memorial Dungeon, '%s' is already booked.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT = 0x529,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약이 중복생성요청으로 실패하였습니다.
+Memorial Dungeon, '%s' is created.
+ Please enter in 5 minutes.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST = 0x52a,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약취소가 실패 하였습니다.
+Failed to create Memorial Dungeon, '%s'.
+ Please try again.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_FAIL = 0x52b,
+/*20171018 to latest
+상대방이 파티 초대 거부 상태입니다.
+The character blocked the party invitation.
+*/
+ MSG_JOINMSG_REFUSE = 0x52c,
+/*20171018 to latest
+모든 파티 초대를 거부합니다.
+Block all party invitations.
+*/
+ MSG_INVITE_PARTY_REFUSE = 0x52d,
+/*20171018 to latest
+모든 파티 초대를 수락합니다.
+Allow all party invitations.
+*/
+ MSG_INVITE_PARTY_ACCEPT = 0x52e,
+/*20171018 to latest
+착용하시면 이 아이템은 영구 귀속됩니다. 착용하시겠습니까?
+This item will be permanently bound to this character once it is equipped. Do you really want to equip this item?
+*/
+ MSG_YOURITEM_EQUIP = 0x52f,
+/*20171018 to latest
+%s 아이템이 귀속되었습니다.
+%s is now permanently bound to this character.
+*/
+ MSG_YOURITEM_EQUIPED = 0x530,
+/*20171018 to latest
+캐시가 부족합니다. 무료 캐시 포인트를 입력해 주시기 바랍니다.
+You do not have enough Kafra Credit Points. Please enter whether you have free credit points.
+*/
+ MSG_BUY_TO_FREE_POINT = 0x531,
+/*20171018 to latest
+파티 가입요청
+Request to Join Party
+*/
+ MSG_REQ_JOIN_PARTY3 = 0x532,
+/*20171018 to latest
+공성 정보 메시지 표시
+Display WOE Info
+*/
+ MSG_VIEW_SIEGE_INFO_MSG = 0x533,
+/*20171018 to latest
+메모리얼던젼 '%s'의 예약이 취소 되었습니다.
+Memorial Dungeon %s's reservation has been canceled.
+*/
+ MSG_MDUNGEON_SUBSCRIPTION_CANCEL_SUCCESS = 0x534,
+/*20171018 to latest
+메모리얼던젼 '%s' 생성에 실패하였습니다. 다시 시도 하세요.
+Failed to create Memorial Dungeon %s. Please try again.
+*/
+ MSG_MDUNGEON_CREATE_FAIL = 0x535,
+/*20171018 to latest
+이 장소에서는 사용할 수 없는 스킬입니다.
+This skill cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_SKILL_AREA = 0x536,
+/*20171018 to latest
+이 장소에서는 사용할 수 없는 아이템입니다.
+This item cannot be used within this area.
+*/
+ MSG_IMPOSSIBLE_USEITEM_AREA = 0x537,
+/*20171018 to latest
+메모리얼 던전
+Memorial Dungeon
+*/
+ MSG_MEMORIAL_DUN = 0x538,
+/*20171018 to latest
+%s 대기중
+%s in Standby
+*/
+ MSG_MEMORIAL_DUN_WAITING = 0x539,
+/*20171018 to latest
+%s 입장 가능
+%s Available
+*/
+ MSG_MEMORIAL_DUN_READY = 0x53a,
+/*20171018 to latest
+%s 진행중
+%s in Progress
+*/
+ MSG_MEMORIAL_DUN_IN = 0x53b,
+/*20171018 to latest
+시간 안에 입장하지 않아 메모리얼 던전이 사라졌습니다.
+No one entered the Memorial Dungeon within its duration; the dungeon has disappeared.
+*/
+ MSG_MEMORIAL_DUN_OUT1 = 0x53c,
+/*20171018 to latest
+이용하시려면 이용 신청을 처음부터 다시 해주시기 바랍니다.
+Please apply for dungeon entry again to play in this dungeon.
+*/
+ MSG_MEMORIAL_DUN_OUT2 = 0x53d,
+/*20171018 to latest
+대기 순위 : ^ff0000%d^000000
+Your Standby Priority: ^ff0000%d^000000
+*/
+ MSG_MEMORIAL_DUN_PRIORITY = 0x53e,
+/*20171018 to latest
+^ff0000%s^000000 내에 입장하지 않을 경우 신청하신 던전이 삭제 됩니다.
+The requested dungeon will be removed if you do not enter within ^ff0000%s^000000.
+*/
+ MSG_MEMORIAL_DUN_NOTIFY = 0x53f,
+/*20171018 to latest
+던전 미션 제한 시간 :
+Dungeon Mission Time Limit:
+*/
+ MSG_MEMORIAL_DUN_NOTIFY2 = 0x540,
+/*20171018 to latest
+메모리얼 던전 예약이 취소되었습니다.
+The Memorial Dungeon reservation has been canceled.
+*/
+ MSG_MEMORIAL_DUN_CANCEL = 0x541,
+/*20171018 to latest
+메모리얼 던전이 유지 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon duration expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_LIVE_TIME_OUT = 0x542,
+/*20171018 to latest
+메모리얼 던전이 입장 시간 제한에 의해 파괴되었습니다.
+The Memorial Dungeon's entry time limit expired; it has been destroyed.
+*/
+ MSG_MEMORIAL_DUN_ENTER_TIME_OUT = 0x543,
+/*20171018 to latest
+메모리얼 던전이 삭제 되었습니다.
+The Memorial Dungeon has been removed.
+*/
+ MSG_MEMORIAL_DUN_DESTROY_REQUEST = 0x544,
+/*20171018 to 20191224
+메모리얼 던전에 시스템 오류가 발생하였습니다. 정상적인 게임 진행을 위해 재접속을 해주십시오.
+A system error has occurred in the Memorial Dungeon. Please relog in to the game to continue playing.
+20200115 to latest
+메모리얼 던전에 통신 장애가 발생하였습니다. 정상적인 게임 진행을 위해 잠시 후, 재접속을 해주십시오.
+*/
+ MSG_MEMORIAL_DUN_ERROR = 0x545,
+/*20171018 to latest
+사용할 수 없는 슬롯입니다.
+This slot is not usable.
+*/
+ MSG_FR_INVALID_SLOT = 0x546,
+/*20171018 to latest
+Base Level이 15를 넘었습니다.
+Your Base Level is over 15.
+*/
+ MSG_FR_BASELVL = 0x547,
+/*20171018 to latest
+Job Level이 15를 넘었습니다.
+Your Job Level is over 15.
+*/
+ MSG_FR_INVALID_JOBLV = 0x548,
+/*20171018 to latest
+해당슬롯 캐릭터에 직업군의 상인이므로 게임을 할 수 없습니다.
+You cannot play the Merchant class character in this slot.
+*/
+ MSG_FR_JOB = 0x549,
+/*20171018 to latest
+추후 사용예정
+Not Yet Implemented
+*/
+ MSG_FR_MAP = 0x54a,
+/*20171018 to latest
+만들수 있는 케릭터 슬롯이 아닙니다.
+You are not eligible to open the Character Slot.
+*/
+ MSG_FR_ERR_MKCHAR_INVALID_SLOT = 0x54b,
+/*20171018 to latest
+삭제할 수 없는 케릭터 입니다.
+This character cannot be deleted.
+*/
+ MSG_FR_ERR_DELCHAR_INVALID_SLOT = 0x54c,
+/*20171018 to latest
+상대방의 장비창이 공개되어 있지 않습니다.
+This character's equipment information is not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSED = 0x54d,
+/*20171018 to latest
+장비창을 공개하지 않습니다.
+Equipment information not open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_REFUSE = 0x54e,
+/*20171018 to latest
+장비창을 공개합니다.
+Equipment information open to the public.
+*/
+ MSG_OPEN_EQUIPEDITEM_ACCEPT = 0x54f,
+/*20171018 to latest
+(%s)님 장비창 보기
+Check %s's Equipment Info
+*/
+ MSG_REQ_VIEW_OTHERUSER = 0x550,
+/*20171018 to latest
+%s의 장착아이템
+'%s's Equipment
+*/
+ MSG_OTHERUSER_EQUIPED_ITEM = 0x551,
+/*20171018 to latest
+장비창 공개
+Show Equip
+*/
+ MSG_OPEN_EQUIPED_ITEM = 0x552,
+/*20171018 to latest
+프리미엄 서비스를 이용해 주시기 바랍니다.
+This service is only available for premium users.
+*/
+ MSG_NEED_PREMIUM_SERVICE = 0x553,
+/*20171018 to latest
+무료 사용자는 최대 50000제니까지 소유할 수 있습니다.
+Free Trial users can only hold up to 50,000 zeny.
+*/
+ MSG_FR_INVALID_MONEY = 0x554,
+/*20171018 to latest
+전장채팅 상태가 되었습니다.
+Battlefield Chat has been activated.
+*/
+ MSG_BATTLECHAT_ON = 0x555,
+/*20171018 to latest
+전장채팅 상태가 해제되었습니다.
+Battlefield Chat has been deactivated.
+*/
+ MSG_BATTLECHAT_OFF = 0x556,
+/*20171018 to latest
+용병정보 - 몬스터타입
+Mercenary Info - Monster Type
+*/
+ MSG_MER_INFO_TYPE_MONSTER = 0x557,
+/*20171018 to latest
+전체 맵 보기
+World Map
+*/
+ MSG_RO_MAP = 0x558,
+/*20171018 to latest
+메모리얼던젼이 CLOSE 상태입니다.
+The Memorial Dungeon is now closed.
+*/
+ MSG_MEMORIAL_DUN_CLOSE = 0x559,
+/*20171018 to latest
+^ff0000^ff0000용병을 삭제합니다.^000000^000000 삭제하실 경우 지금까지 키운 내역이 모두 삭제됩니다. 계속하시겠습니까?
+^ff0000Deleting a Mercenary Soldier^000000 will also delete his growth history. Do you really want to proceed with the deletion?
+*/
+ MSG_DELETE_MER = 0x55a,
+/*20171018 to latest
+메모리얼던젼이 OPEN 상태입니다.
+The Memorial Dungeon is now open.
+*/
+ MSG_MEMORIAL_DUN_OPEN = 0x55b,
+/*20171018 to latest
+위의 계정은 아직 통신 안전 키에 연결되지 않았습니다. 먼저 안전 키를 해제하신 뒤 게임에 접속해 주십시오.
+This account has not been confirmed by connecting to the safe communication key. Please connect to the key first, and then log into the game.
+*/
+ MSG_PHONE_BLOCK = 0x55c,
+/*20171018 to latest
+한 아이피로 접속 가능한 유저수를 초과하였습니다.
+The number of accounts connected to this IP has exceeded the limit.
+*/
+ MSG_BAN_PC_IP_LIMIT_ACCESS = 0x55d,
+/*20171018 to latest
+새로운 퀘스트를 받았습니다
+You have received a new quest.
+*/
+ MSG_QUESTGET = 0x55e,
+/*20171018 to latest
+^777777습득조건 :
+^CC3399Requirement:
+*/
+ MSG_FINDTEXT_TO_SKILLDES = 0x55f,
+/*20171018 to latest
+스킬 설명 보기
+View Skill Info
+*/
+ MSG_VIEW_SKILL_DESCRIPT = 0x560,
+/*20171018 to latest
+사용된 스킬 포인트는 다시 되돌릴 수 없습니다. 적용하시겠습니까?
+Once used, skill points cannot be re-allocated. Would you like to use the skill points?
+*/
+ MSG_APPLY_SKILL_UP = 0x561,
+/*20171018 to latest
+노비스·1차직업
+1st
+*/
+ MSG_1TABNAME_SKILLWND = 0x562,
+/*20171018 to latest
+2차·전승직업
+2nd
+*/
+ MSG_2TABNAME_SKILLWND = 0x563,
+/*20171018 to latest
+불법프로그램을 사용하였거나 혹은 해킹을 시도한 계정입니다. 블럭종료시간 : %s
+This account has been used for illegal program or hacking program. Block Time: %s
+*/
+ MSG_RE17 = 0x564,
+/*20171018 to latest
+불법프로그램이 실행, 바이러스 감염, 또는 해킹툴이 설치되어 있을 가능성이 있습니다. 정상 클라이언트를 실행하여 주시기 바랍니다. 함께 만드는 밝은 라그나로크가 될 수 있도록 노력하고 있습니다.
+The possibility of exposure to illegal program, PC virus infection or Hacking Tool has been detected. Please execute licensed client. Our team is trying to make a best environment for Ro players.
+*/
+ MSG_RE18 = 0x565,
+/*20171018 to latest
+당신은 지금 건강한 게임 시간 대에 있습니다, 즐거운 게임이 되시길 바랍니다
+You are currently playing in the best game environment. Please enjoy the Ragnarok.
+*/
+ MSG_WARNING_MSG3 = 0x566,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 30분간 1.25배로 증가합니다.
+Job Exp points from hunting monsters are increased by 50% for 30 minutes.
+*/
+ MSG_PLUSONLYJOBEXP = 0x567,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 1.2배로 증가합니다.
+Exp points from hunting monsters are increased by 25% for 30 minutes.
+*/
+ MSG_PLUSEXP14532 = 0x568,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 30분간 2배로 증가합니다.
+EXP points from hunting monsters are increased by 100%% for 30 minutes.
+*/
+ MSG_PLUSEXP14533 = 0x569,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 경험치가 60분간 1.5배로 증가합니다.
+EXP points from hunting monsters are increased by 50% for 60 minutes.
+*/
+ MSG_PLUSEXP12312 = 0x56a,
+/*20171018 to latest
+이 맵에서는 파티를 결성할 수 없습니다.
+Unable to organize a party in this map.
+*/
+ MSG_NOPARTY = 0x56b,
+/*20171018 to latest
+(%s)님은 파티에 참여할 수 없는 맵에 있습니다.
+(%s) are currently in restricted map to join a party.
+*/
+ MSG_NOPARTY2 = 0x56c,
+/*20171018 to latest
+간편아이템샵
+Simple Item Shop
+*/
+ MSG_SIMPLE_CASH_SHOP = 0x56d,
+/*20171018 to latest
+소지 한코인 : %d 한코인
+Han Coin: %d Han Coin
+*/
+ MSG_SIMPLE_POINT_SHOP_NHN = 0x56e,
+/*20171018 to latest
+소지 캐시 : %d 캐시
+RoK Point: %d RoK Point
+*/
+ MSG_SIMPLE_POINT_SHOP = 0x56f,
+/*20171018 to latest
+무료 캐시 : %d 캐시
+Free Cash: %d Cash
+*/
+ MSG_SIMPLE_POINT_SHOP2 = 0x570,
+/*20171018 to latest
+본서버 유저는 프리서버에 접속할수 없습니다.
+An user of this server cannot connect to free server
+*/
+ MSG_MAIN_USER_CANONT_LOGIN_FREE_SERVER = 0x571,
+/*20171018 to latest
+유효기간이 지난 비밀번호 입니다. 다시 로그인하여주십시오.
+Your password has expired. Please log in again
+*/
+ MSG_INVALID_ONETIMELIMIT = 0x572,
+/*20171018 to latest
+3차직업
+3rd
+*/
+ MSG_3TABNAME_SKILLWND = 0x573,
+/*20171018 to latest
+이 스킬을 사용할 수 없는 대상입니다.
+This skill can't be used on that target.
+*/
+ MSG_USESKILL_FAIL_TOTARGET = 0x574,
+/*20171018 to latest
+안실라 소유 개수가 초과하여 스킬을 사용할 수 없습니다.
+You can't use skill because you have exceeded the number Ancilla possession limit
+*/
+ MSG_USESKILL_FAIL_ANCILLA_NUMOVER = 0x575,
+/*20171018 to latest
+성수가 필요합니다.
+Unable to use the skill to exceed the number of Ancilla.
+*/
+ MSG_USESKILL_FAIL_HOLYWATER = 0x576,
+/*20171018 to latest
+안실라가 필요합니다.
+Holy water is required.
+*/
+ MSG_USESKILL_FAIL_ANCILLA = 0x577,
+/*20171018 to latest
+일정거리 내에 중복될 수 없습니다.
+Ancilla is required.
+*/
+ MSG_USESKILL_FAIL_DUPLICATE_RANGEIN = 0x578,
+/*20171018 to latest
+이 스킬을 사용하기 위해서는 다른 스킬이 필요합니다.
+Cannot be duplicated within a certain distance.
+*/
+ MSG_USESKILL_FAIL_NEED_OTHER_SKILL = 0x579,
+/*20171018 to latest
+이 맵에서는 채팅을 할 수 없습니다.
+This skill requires other skills to be used.
+*/
+ MSG_NO_CHATTING = 0x57a,
+/*20171018 to latest
+3시간이 지났습니다.
+Chat is not allowed in this map
+*/
+ MSG_VET_3HOUR = 0x57b,
+/*20171018 to latest
+5시간이 지났습니다.
+3 hours have passed.
+*/
+ MSG_VET_5HOUR = 0x57c,
+/*20171018 to latest
+게임가드 초기화 에러 또는 구버전의 게임가드 파일입니다. 게임가드 셋업파일을 다시 설치하고 게임을 실행해 보시기 바랍니다.
+5 hours have passed.
+*/
+ MSG_NPGAMEMON_ERROR_GAMEGUARD = 0x57d,
+/*20171018 to latest
+ini 파일이 없거나 변조되었습니다. 게임가드 셋업파일을 설치하면 해결 할 수 있습니다.
+Game guard initialization error or previous version game guard file is installed. Please re-install the setup file and try again
+*/
+ MSG_NPGMUP_ERROR_PARAM = 0x57e,
+/*20171018 to latest
+게임가드와 충돌 프로그램이 발견되었습니다.
+Either ini file is missing or altered. Install game guard setup file to fix the problem
+*/
+ MSG_NPGG_ERROR_COLLISION = 0x57f,
+/*20171018 to latest
+잘못된 클라이언트입니다. 정상적인 클라이언트를 실행하여 주십시요.
+There is a program found that conflicts with game guard
+*/
+ MSG_PROOF_ERROR = 0x580,
+/*20171018 to latest
+모바일 인증을 받아주시기 바랍니다.
+Incorrect client. Please run a normal client
+*/
+ MSG_MOBILE_LOCKSERVER = 0x581,
+/*20171018 to latest
+모바일 인증에 실패하였습니다.
+Thank you to accept mobile authentication.
+*/
+ MSG_FAILED_MOBILE_LOCKSERVER = 0x582,
+/*20171018 to latest
+이스킬은 혼자서 사용할수 없습니다.
+This skill can't be used alone
+*/
+ MSG_USESKILL_FAIL_NEED_HELPER = 0x583,
+/*20171018 to latest
+이스킬은 특정방향으로만 사용할수 있습니다.
+This skill can be used to certain direction only
+*/
+ MSG_USESKILL_FAIL_INVALID_DIR = 0x584,
+/*20171018 to latest
+더이상 소환할수 없습니다.
+Cannot summon spheres anymore.
+*/
+ MSG_USESKILL_FAIL_SUMMON = 0x585,
+/*20171018 to latest
+소환된 구체가 존재하지 않거나 부족합니다.
+There is no summoned sphere or you do not have enough sphere.
+*/
+ MSG_USESKILL_FAIL_SUMMON_NONE = 0x586,
+/*20171018 to latest
+사용가능한 모방스킬이 존재하지 않습니다.
+There is no imitation skills available.
+*/
+ MSG_USESKILL_FAIL_IMITATION_SKILL_NONE = 0x587,
+/*20171018 to latest
+이 스킬은 중복해서 사용할수 없습니다.
+You can't reuse this skill
+*/
+ MSG_USESKILL_FAIL_DUPLICATE = 0x588,
+/*20171018 to latest
+스킬을 사용할수 없는 상태입니다.
+Skill can't be used in this state
+*/
+ MSG_USESKILL_FAIL_CONDITION = 0x589,
+/*20171018 to latest
+아이템별 최대 소지량을 초과하여 가질 수 없습니다.
+You have exceeded the maximum amount of possession of another item.
+*/
+ MSG_PICKUP_MAXCOUNT_LIMIT = 0x58a,
+/*20171018 to latest
+관리자 권한이 없습니다. 프로그램 최초 실행은 관리자 권한으로 실행하셔야 합니다.
+No administrative privileges. Must first run the program with administrator privileges.
+*/
+ MSG_NPK_ERROR_NOTADMIN = 0x58b,
+/*20171018 to latest
+nProtect KeyCrypt 드라이버 버전이 맞지 않습니다. 시스템 재 부팅 후에 새로 실행 시켜 주십시오.
+nProtect KeyCrypt not the same. Please restart the program and the computer first.
+*/
+ MSG_NPK_ERROR_DRIVERVERSION = 0x58c,
+/*20171018 to latest
+WindowXP 호환성 모드를 사용하고 계십니다. 현재 프로그램에서 호환성 모드를 제거하였습니다. 프로그램을 새로 시작해 주십시오.
+Currently wearing WindowXP Compatibility Mode. The program now removes Compatibility Mode. Please restart the program.
+*/
+ MSG_NPK_ERROR_VERIFYVERSION = 0x58d,
+/*20171018 to latest
+PS/2 키로거가 존재합니다.
+PS/2 keyloggers exist.
+*/
+ MSG_DETECT_PS2KEYLOGGER = 0x58e,
+/*20171018 to latest
+USB 키보드 드라이버 해킹 시도가 탐지되었습니다.
+USB Keylogging attempt was detected.
+*/
+ MSG_DETECT_USBKEYLOGGER = 0x58f,
+/*20171018 to latest
+HHD 모니터링 툴이 탐지되었습니다.
+HHD monitoring tool has been detected.
+*/
+ MSG_DETECT_HHDUSBH = 0x590,
+/*20171018 to latest
+페인트붓이 필요합니다.
+Paintbrush is required.
+*/
+ MSG_USESKILL_FAIL_PAINTBRUSH = 0x591,
+/*20171018 to latest
+서페이스페인트가 필요합니다.
+Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_SURFACE_PAINTS = 0x592,
+/*20171018 to latest
+지정한 위치에 스킬을 사용할수 없습니다.
+Use the skills that are not at the specified location.
+*/
+ MSG_USESKILL_FAIL_POS = 0x593,
+/*20171018 to latest
+도우미의 SP가 부족합니다.
+Not enough SP.
+*/
+ MSG_USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 0x594,
+/*20171018 to latest
+캐릭터 선택창의 캐릭터가 %d개를 초과하면 게임에 접속할 수 없습니다. 불필요한 캐릭터를 삭제해주십시오.
+Character %d is character selection window cannot connect to the game that exceeds the total. Please remove unwanted characters.
+*/
+ MSG_BAN_OVER_CHARACTER_LIST = 0x595,
+/*20171018 to latest
+목캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_NECK_CANDY = 0x596,
+/*20171018 to latest
+안타까운눈물이 필요합니다.
+Painful Tears is required.
+*/
+ MSG_USESKILL_FAIL_II_MISERABLE_TEAR = 0x597,
+/*20171018 to latest
+목 보호 캔디가 필요합니다.
+Throat Lozenge is required.
+*/
+ MSG_USESKILL_FAIL_II_PROTECT_NECK_CANDY = 0x598,
+/*20171018 to latest
+웨폰 블로킹의 연계로만 사용가능합니다.
+Cooperation is only available with Weapon Blocking.
+*/
+ MSG_USESKILL_FAIL_GC_WEAPONBLOCKING = 0x599,
+/*20171018 to latest
+길로틴크로스의 독을 바른 무기가 필요합니다.
+Poisoned weapons is required.
+*/
+ MSG_USESKILL_FAIL_GC_POISONINGWEAPON = 0x59a,
+/*20171018 to latest
+마도기어 탑승시에만 사용가능합니다.
+Item can only be used when Mado Gear is mounted.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR = 0x59b,
+/*20171018 to latest
+발칸블릿이 필요합니다.
+Vulcan Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_VULCANBULLET = 0x59c,
+/*20171018 to latest
+마도기어 연료가 필요합니다.
+Mado Gear Fuel is required.
+*/
+ MSG_USESKILL_FAIL_II_FUELGAS = 0x59d,
+/*20171018 to latest
+액체냉각탄이 필요합니다.
+Liquid Cold Bullet is required.
+*/
+ MSG_USESKILL_FAIL_II_COLDSLOWERBULLET = 0x59e,
+/*20171018 to latest
+캐논볼을 장전 하세요.
+Please load a Cannon Ball.
+*/
+ MSG_USESKILL_FAIL_CANONBALL = 0x59f,
+/*20171018 to latest
+미도기어 가속장치를 착용하세요.
+Please equipped with a Mado Gear Accelerator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 0x5a0,
+/*20171018 to latest
+호버링부스터를 착용하세요.
+Please equipped with a Hovering Booster.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 0x5a1,
+/*20171018 to latest
+[톡신] 독 효과가 무기에 적용되었습니다.
+[Toxin] Poison effect was applied to the weapon.
+*/
+ MSG_TOXIN = 0x5a2,
+/*20171018 to latest
+[패럴라이즈] 독 효과가 무기에 적용되었습니다.
+[Paralysis] Poison effect was applied to the weapon.
+*/
+ MSG_PARALYZE = 0x5a3,
+/*20171018 to latest
+[베놈블리드] 독 효과가 무기에 적용되었습니다.
+[Fatigue] Poison effect was applied to the weapon.
+*/
+ MSG_VENOMBLEED = 0x5a4,
+/*20171018 to latest
+[매직 머쉬룸] 독 효과가 무기에 적용되었습니다.
+[Laughing] Poison effect was applied to the weapon.
+*/
+ MSG_MAGICMUSHROOM = 0x5a5,
+/*20171018 to latest
+[데스 허트] 독 효과가 무기에 적용되었습니다.
+[Disheart] Poison effect was applied to the weapon.
+*/
+ MSG_DEATHHURT = 0x5a6,
+/*20171018 to latest
+[파이렉시아] 독 효과가 무기에 적용되었습니다.
+[Pyrexia] Poison effect was applied to the weapon.
+*/
+ MSG_PHYREXIA = 0x5a7,
+/*20171018 to latest
+[오블리비언 커즈] 독 효과가 무기에 적용되었습니다.
+[Oblivion] Poison effect was applied to the weapon.
+*/
+ MSG_OBLIANCURSE = 0x5a8,
+/*20171018 to latest
+[리치 엔드] 독 효과가 무기에 적용되었습니다.
+[Leech] Poison effect was applied to the weapon.
+*/
+ MSG_RICHEND = 0x5a9,
+/*20171018 to latest
+호버링상태에서만 사용가능합니다.
+Can only be used in Hovering state.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_HOVERING = 0x5aa,
+/*20171018 to latest
+자폭장치를 장착하세요.
+Please equip a Self-Destruct Mechanism.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 0x5ab,
+/*20171018 to latest
+셰이프쉬프터를 장착하세요.
+Please equip a Shape Shift.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 0x5ac,
+/*20171018 to latest
+길로틴독이 필요합니다.
+Guillotine Cross Poison is required.
+*/
+ MSG_USESKILL_FAIL_GUILLONTINE_POISON = 0x5ad,
+/*20171018 to latest
+냉각장치를 장착하세요.
+Please equipped with a Cooling System.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 0x5ae,
+/*20171018 to latest
+자기장필드생성기를 착용하세요.
+Please equipped with a Magnetic Field Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 0x5af,
+/*20171018 to latest
+베리어생성기를 착용하세요.
+Please equipped with a Barrier Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 0x5b0,
+/*20171018 to latest
+광학미채발생기를 착용하세요.
+Please equipped with a Optical Camouflage Generator.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 0x5b1,
+/*20171018 to latest
+리페어키트를 착용하세요.
+Please equipped with a Repair Kit.
+*/
+ MSG_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 0x5b2,
+/*20171018 to latest
+몽키 스패너가 필요합니다.
+Monkey Wrench is required.
+*/
+ MSG_USESKILL_FAIL_II_MONKEY_SPANNER = 0x5b3,
+/*20171018 to latest
+[%s] 스킬을 시전 할 수 없습니다.
+[%s] Cannot use the skills due to cooldown delay.
+*/
+ MSG_SKILLINTERVAL2 = 0x5b4,
+/*20171018 to latest
+%d레벨 이상은 삭제가 불가능합니다.
+Deletion is impossible for over level %d
+*/
+ MSG_LEMIT_DELETE_LEVEL = 0x5b5,
+/*20171018 to latest
+마도기어 탑승시에는 사용 할 수 없습니다.
+Can't be used while on Magic Gear.
+*/
+ MSG_USESKILL_FAIL_MADOGEAR_RIDE = 0x5b6,
+/*20171018 to latest
+드래곤 내리기
+Dismount Dragon
+*/
+ MSG_DRAGONOFF = 0x5b7,
+/*20171018 to latest
+마도기어 내리기
+Dismount Magic Gear
+*/
+ MSG_MADOOFF = 0x5b8,
+/*20171018 to latest
+소비
+I
+*/
+ MSG_STORE_TABNAME_0 = 0x5b9,
+/*20171018 to latest
+캐쉬
+Cash
+*/
+ MSG_STORE_TABNAME_1 = 0x5ba,
+/*20171018 to latest
+방어구
+Armors
+*/
+ MSG_STORE_TABNAME_2 = 0x5bb,
+/*20171018 to latest
+무기
+Weapons
+*/
+ MSG_STORE_TABNAME_3 = 0x5bc,
+/*20171018 to latest
+투사체
+Ammo
+*/
+ MSG_STORE_TABNAME_4 = 0x5bd,
+/*20171018 to latest
+카드
+Card
+*/
+ MSG_STORE_TABNAME_5 = 0x5be,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_STORE_TABNAME_6 = 0x5bf,
+/*20171018 to latest
+클라이언트 응답시간이 초과되어 연결이 끊어집니다.
+Client response time has passed so connection is terminated
+*/
+ MSG_ERROR_HS_TIMEOUT = 0x5c0,
+/*20171018 to latest
+핵쉴드 파일의 버전이 맞지 않습니다. 클라이언트를 재설치 해주십시오.
+Incorrect version of hack shield file. Please reinstall the client
+*/
+ MSG_ERROR_DIFF_CLIENT = 0x5c1,
+/*20171018 to latest
+마법서가 필요합니다.
+[Magic Book] is required.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK = 0x5c2,
+/*20171018 to latest
+마법서가 너무 어려워서 졸음이 몰려온다.
+Feel sleepy since Magic Book is too difficult to understand.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 0x5c3,
+/*20171018 to latest
+보존포인트가 부족합니다.
+Not enough saved point.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 0x5c4,
+/*20171018 to latest
+더이상 마법서를 읽을수 없습니다.
+Can't read a Magic Book anymore.
+*/
+ MSG_USESKILL_FAIL_SPELLBOOK_READING = 0x5c5,
+/*20171018 to latest
+페이스페인트가 필요합니다.
+Face Paint is required.
+*/
+ MSG_USESKILL_FAIL_II_FACE_PAINTS = 0x5c6,
+/*20171018 to latest
+분장용붓이 필요합니다.
+Brush is required.
+*/
+ MSG_USESKILL_FAIL_II_MAKEUP_BRUSH = 0x5c7,
+/*20171018 to latest
+대기 시간이 초과하였습니다. 다시 로그인 해주십시오.
+Waiting time has passed. Please log in again
+*/
+ MSG_MOBILE_TIMEOVER = 0x5c8,
+/*20171018 to latest
+위험! 이미 동일한 계정이 로그인 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is already logged in. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_ANOTHER_LOGIN = 0x5c9,
+/*20171018 to latest
+위험! 현재 동일한 계정이 모바일 인증 대기 중에 있습니다. 잠시 모바일 인증 진행을 멈추시고 비번을 수정한 뒤 재 로그인 해주십시오.
+Watch out! Same account is waiting for mobile verification. Stop mobile verification and log in again after changing your password
+*/
+ MSG_MOBILE_WAITING_STATE = 0x5ca,
+/*20171018 to latest
+게임 옵션창
+Game setting window
+*/
+ MSG_ESC_OPTIONWND = 0x5cb,
+/*20171018 to latest
+그래픽 설정
+Graphics Settings
+*/
+ MSG_GRAPHIC_OPTIONWND = 0x5cc,
+/*20171018 to latest
+사운드 설정
+Sound Settings
+*/
+ MSG_SOUND_OPTIONWND = 0x5cd,
+/*20171018 to latest
+변경 할 단축키를 누르거나, 'ESC'키를 눌러 삭제 해 주세요.
+Press a key to assign. Pressing 'ESC' will remove the assigned key.
+*/
+ MSG_HOTKEYWND_NOTICE1 = 0x5ce,
+/*20171018 to latest
+단일 키로 지정 할 수 없는 키입니다.
+Unable to specify a single key.
+*/
+ MSG_HOTKEYWND_NOTICE2 = 0x5cf,
+/*20171018 to latest
+지정 할 수 없는 키입니다.
+Unable to specify the key assigned.
+*/
+ MSG_HOTKEYWND_NOTICE3 = 0x5d0,
+/*20171018 to latest
+'%s'에 사용된 단축키와 중복됩니다. 바꾸시겠습니까?
+Duplicated with ['%s']. Do you still want to change?
+*/
+ MSG_HOTKEYWND_NOTICE4 = 0x5d1,
+/*20171018 to latest
+저장된 단축키 조합이 초기화 됩니다. 초기화 하시겠습니까?
+Initialization is stored in the shortcut key settings. Do you want to initialized?
+*/
+ MSG_HOTKEYWND_NOTICE5 = 0x5d2,
+/*20171018 to latest
+스킬바
+Skill Bar
+*/
+ MSG_HOTKEYWND_TAB1 = 0x5d3,
+/*20171018 to latest
+인터페이스
+Interface
+*/
+ MSG_HOTKEYWND_TAB2 = 0x5d4,
+/*20171018 to latest
+이모션
+Macros
+*/
+ MSG_HOTKEYWND_TAB3 = 0x5d5,
+/*20171018 to latest
+단축키 설정 창
+Shortcut Settings
+*/
+ MSG_HOTKEYWND_TITLE = 0x5d6,
+/*20171018 to latest
+배경음
+BGM
+*/
+ MSG_BGM = 0x5d7,
+/*20171018 to latest
+효과음
+Effect
+*/
+ MSG_SOUND = 0x5d8,
+/*20171018 to latest
+스킨
+Skin
+*/
+ MSG_SKIN = 0x5d9,
+/*20171018 to latest
+채팅방 입장음만 소리남 On
+Chat room entrance sound on
+*/
+ MSG_TINGONLY_ON = 0x5da,
+/*20171018 to latest
+채팅방 입장음만 소리남 Off
+Chat room entrance sound off
+*/
+ MSG_TINGONLY_OFF = 0x5db,
+/*20171018 to latest
+/tingonly : 채팅방 입장음만 들을수있게됩니다
+/tingonly: you can hear only sound like a chat room entry.
+*/
+ MSG_EXPLAIN_TINGONLY = 0x5dc,
+/*20171018 to latest
+/주먹
+/rock
+*/
+ MSG_EMOTION_ROCK = 0x5dd,
+/*20171018 to latest
+/가위
+/scissors
+*/
+ MSG_EMOTION_SCISSOR = 0x5de,
+/*20171018 to latest
+/보
+/paper
+*/
+ MSG_EMOTION_WRAP = 0x5df,
+/*20171018 to latest
+/러브
+/love
+*/
+ MSG_EMOTION_LUV = 0x5e0,
+/*20171018 to latest
+/mobile
+*/
+ MSG_EMOTION_MOBILE = 0x5e1,
+/*20171018 to latest
+/mail
+*/
+ MSG_EMOTION_MAIL = 0x5e2,
+/*20171018 to latest
+/antenna0
+*/
+ MSG_EMOTION_ANTENNA0 = 0x5e3,
+/*20171018 to latest
+/antenna1
+*/
+ MSG_EMOTION_ANTENNA1 = 0x5e4,
+/*20171018 to latest
+/antenna2
+*/
+ MSG_EMOTION_ANTENNA2 = 0x5e5,
+/*20171018 to latest
+/antenna3
+*/
+ MSG_EMOTION_ANTENNA3 = 0x5e6,
+/*20171018 to latest
+/hum
+*/
+ MSG_EMOTION_HUM2 = 0x5e7,
+/*20171018 to latest
+/abs
+*/
+ MSG_EMOTION_ABS = 0x5e8,
+/*20171018 to latest
+/oops
+*/
+ MSG_EMOTION_OOPS = 0x5e9,
+/*20171018 to latest
+/spit
+*/
+ MSG_EMOTION_SPIT = 0x5ea,
+/*20171018 to latest
+/ene
+*/
+ MSG_EMOTION_ENE = 0x5eb,
+/*20171018 to latest
+/panic
+*/
+ MSG_EMOTION_PANIC = 0x5ec,
+/*20171018 to latest
+/whisp
+*/
+ MSG_EMOTION_WHISP = 0x5ed,
+/*20171018 to latest
+지정안함
+Not Assigned
+*/
+ MSG_HOTKEY_NOTHING = 0x5ee,
+/*20171018 to latest
+카트장착시에만 사용가능합니다.
+Only available when cart is mounted.
+*/
+ MSG_USESKILL_FAIL_CART = 0x5ef,
+/*20171018 to latest
+[가시나무 씨앗]이 필요합니다.
+[Thorny Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_THORNS_SEED = 0x5f0,
+/*20171018 to latest
+[흡혈 식물 씨앗]이 필요합니다.
+[Bloodsucker Seed] is required.
+*/
+ MSG_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 0x5f1,
+/*20171018 to latest
+더이상 시전할수 없습니다.
+Cannot be used anymore.
+*/
+ MSG_USESKILL_FAIL_NO_MORE_SPELL = 0x5f2,
+/*20171018 to latest
+[폭탄버섯포자]가 필요합니다.
+[Bomb Mushroom Spore] is required.
+*/
+ MSG_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 0x5f3,
+/*20171018 to latest
+[화염병]이 필요합니다.
+[Fire Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_GASOLINE_BOOMB = 0x5f4,
+/*20171018 to latest
+[기름병]이 필요합니다.
+[Oil Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_OIL_BOTTLE = 0x5f5,
+/*20171018 to latest
+[폭발가루]가 필요합니다.
+[Explosive Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_EXPLOSION_POWDER = 0x5f6,
+/*20171018 to latest
+[연막가루]가 필요합니다.
+[Smokescreen Powder] is required.
+*/
+ MSG_USESKILL_FAIL_II_SMOKE_POWDER = 0x5f7,
+/*20171018 to latest
+[최루가스]가 필요합니다.
+[Tear Gas] is required.
+*/
+ MSG_USESKILL_FAIL_II_TEAR_GAS = 0x5f8,
+/*20171018 to latest
+[염산병]이 필요합니다.
+[Acid Bottle] is required.
+*/
+ MSG_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 0x5f9,
+/*20171018 to latest
+[식인식물병]이 필요합니다.
+[Bottom Man-Eating Plant] is required.
+*/
+ MSG_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 0x5fa,
+/*20171018 to latest
+[만드라고라의 화분]이 필요합니다.
+[Pot of Mandragora] is required.
+*/
+ MSG_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 0x5fb,
+/*20171018 to latest
+파티장 위임
+Party delegation
+*/
+ MSG_YIELD_PARTYMASTER = 0x5fc,
+/*20171018 to latest
+정말 파티장을 위임하시겠습니까?
+Do you want to delegate the real party?
+*/
+ MSG_DO_YOU_REALLY_WANT_YIELD_PARTYMASTER = 0x5fd,
+/*20171018 to latest
+파티장을 위임 할 수 없습니다.
+Party cannot be delegated.
+*/
+ MSG_CANNOT_YIELD_PARTYMASTER = 0x5fe,
+/*20171018 to latest
+변경불가
+Immutable
+*/
+ MSG_FAILED_CHANGE = 0x5ff,
+/*20171018 to latest
+[%s]가 %d개 필요합니다.
+[%s] required '%d' amount.
+*/
+ MSG_USESKILL_FAIL_NEED_ITEM = 0x600,
+/*20171018 to latest
+제련 수치가 하향 조정 되었습니다.
+Is now refining the value lowered.
+*/
+ MSG_ITEM_REFINING_DOWNGRADE = 0x601,
+/*20171018 to latest
+[%s]를 장비하고 있어야 사용할 수 있습니다
+Need to put on [%s] in order to use.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT = 0x602,
+/*20171018 to latest
+전장 입장 설정
+Battle field entrance setting
+*/
+ MSG_BATTLEFIELD_LIST = 0x603,
+/*20171018 to latest
+% 전장으로 이동 할 수 없는 상태가 되어 전장 신청이 취소 되었습니다.
+Battlefield - [%s] you sign up?
+*/
+ MSG_CANNOT_JOINTO_BATTLEFIELD = 0x604,
+/*20171018 to latest
+
+Current admission application state.
+*/
+ MSG_COMPLETED_JOINTO_BATTLEFIELD = 0x605,
+/*20171018 to latest
+% 전장 입장이 보류 되었습니다. 다른 플레이어를 기다립니다.
+It was unregistered and not be able to enter the state.
+*/
+ MSG_DIFFER_JOINTO_BATTLEFIELD = 0x606,
+/*20171018 to latest
+
+Current admission application state.
+*/
+ MSG_STATUS_JOINTO_BATTLEFIELD = 0x607,
+/*20171018 to latest
+확인 단추를 누르면 전장 신청이 취소됩니다. 아래 단추를 클릭해 주세요.
+Do you want to cancel the admission application?
+*/
+ MSG_REQ_CANCEL_JOINTO_BATTLEFIELD = 0x608,
+/*20171018 to latest
+%s 전장 입장 신청이 취소되었습니다.
+Admission request has been cancelled.
+*/
+ MSG_CANCEL_JOINTO_BATTLEFIELD = 0x609,
+/*20171018 to latest
+잠시후 %s 전장으로 이동 합니다. 공간 이동을 위한 안정적인 상태를 확보해 주시길 바랍니다. (거래 및 공간 이동 기능 일시 중지됨)
+Go to the battlefield quickly.
+*/
+ MSG_MOVETO_BATTLEFIELD = 0x60a,
+/*20171018 to latest
+전장 명칭
+Battlefield - [%s]
+*/
+ MSG_BATTLEFIELD_NAME = 0x60b,
+/*20171018 to latest
+정말 이동 하시겠습니까?
+Do you really want to go back to your savepoint?
+*/
+ MSG_MOVETO_SAVEPOINT = 0x60c,
+/*20171018 to latest
+파티원 찾기 메세지
+Search Message for Party Members
+*/
+ MSG_VIEW_SEEK_PARTY = 0x60d,
+/*20171018 to latest
+파티원 찾기 메세지 옵션이 꺼져있습니다.
+Message option is off the search party members.
+*/
+ MSG_UNVIEW_SEEK_PARTY = 0x60e,
+/*20171018 to latest
+10초간 파티 지원 딜레이가 걸려있습니다.
+10 seconds delay of party support is in effect
+*/
+ MSG_SEEK_PARTY_DEALY = 0x60f,
+/*20171018 to latest
+ 파티장은 '%s' 님 입니다.
+Party leader is '%s'.
+*/
+ MSG_NOTIFY_PARTY_ROLE_MASTER = 0x610,
+/*20171018 to latest
+시스템 오류로 입장 할 수 없습니다.
+Unable to enter due to system error.
+*/
+ MSG_ERROR_SYSTEM_ERROR_BATTLEFIELD = 0x611,
+/*20171018 to latest
+대기 인원 수 초과로 입장 할 수 없습니다.
+Cannot wait to enter the number of excess.
+*/
+ MSG_ERROR_FULL_ESROOM_BATTLEFIELD = 0x612,
+/*20171018 to latest
+이미 신청 되었습니다.
+Has already been applied.
+*/
+ MSG_ERROR_DOUBLE_OFFER_BATTLEFIELD = 0x613,
+/*20171018 to latest
+대기 시간이 초과되어 등록이 취소 되었습니다.
+Registration has been cancelled because of the excessive waiting time.
+*/
+ MSG_ERROR_WAIT_TIMEOUT_BATTLEFIELD = 0x614,
+/*20171018 to latest
+입장 조건이 맞지 않아, 등록이 취소 되었습니다.
+Unregistered because admission requirements are not matching.
+*/
+ MSG_ERROR_BATTLEFILD_ENTER_BATTLEFIELD = 0x615,
+/*20171018 to latest
+오류가 발생하여 등록이 취소 되었습니다.
+Was unregistered and error.
+*/
+ MSG_ERROR_DROP_ENTRANCESTATION_BATTLEFIELD = 0x616,
+/*20171018 to latest
+[%s]의 연계 스킬입니다.
+The skill need [%s].
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL = 0x617,
+/*20171018 to latest
+특정스킬 의 연계 스킬입니다.
+The skill need a particular skill.
+*/
+ MSG_USESKILL_FAIL_COMBOSKILL2 = 0x618,
+/*20171018 to latest
+기구체 %d 개가 필요합니다
+Requires %d mind bullets
+*/
+ MSG_USESKILL_FAIL_SPIRITS = 0x619,
+/*20171018 to latest
+기구체가 필요합니다
+Mind Bullet is required.
+*/
+ MSG_USESKILL_FAIL_SPIRITS2 = 0x61a,
+/*20171018 to latest
+최대 소지량 보다 많은 룬스톤을 제작할 수 없습니다.
+Cannot create rune stone more than the maximum amount.
+*/
+ MSG_RUNESTONE_MAKEERROR_OVERCOUNT = 0x61b,
+/*20171018 to latest
+전장 리스트를 받을 수 없는 상태입니다. 확인 후 다시 시도 해 주세요.
+Not able to receive battle field list. Please check and try again
+*/
+ MSG_ERROR_LIST_OPEN_BATTLEFIELD = 0x61c,
+/*20171018 to latest
+레벨이 부족하여 입장 할 수 없습니다.
+Level is not high enough to enter
+*/
+ MSG_ERROR_LEVEL_LIMIT_BATTLEFIELD = 0x61d,
+/*20171018 to latest
+ 1차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' points in your 1st Tab.
+*/
+ MSG_UPGRADESKILLERROR_MORE_FIRSTJOBSKILL = 0x61e,
+/*20171018 to latest
+ 1차 혹은 2차 직업 스킬 %d개를 더 올려 주십시오.
+You must consume all '%d' remaining points in your 2nd Tab. 1st Tab is already done.
+*/
+ MSG_UPGRADESKILLERROR_MORE_SECONDJOBSKILL = 0x61f,
+/*20171018 to latest
+변환 가능한 아이템
+Items available for conversion
+*/
+ MSG_ITEMSYOUCANCHANGE = 0x620,
+/*20171018 to latest
+변환할 아이템
+Insert items to convert
+*/
+ MSG_ITEMS_FOR_CHANGE = 0x621,
+/*20171018 to latest
+변환이 불가능한 조합 입니다.
+Inconvertible combination
+*/
+ MSG_SKILL_RECIPE_NOTEXIST = 0x622,
+/*20171018 to latest
+인벤토리의 무게가 너무 무겁습니다.
+Inventory weight is too much
+*/
+ MSG_SKILL_INVENTORY_WEIGHT_OVER = 0x623,
+/*20171018 to latest
+인벤토리를 공간을 확보해주세요.
+Please secure some room in the inventory
+*/
+ MSG_SKILL_INVENTORY_KINDCNT_OVER = 0x624,
+/*20171018 to latest
+재료가 존재하지 않습니다.
+Material doesn't exist
+*/
+ MSG_SKILL_MATERIAL_FAIL = 0x625,
+/*20171018 to latest
+성공하였습니다.
+Successful.
+*/
+ MSG_SKILL_SUCCESS = 0x626,
+/*20171018 to latest
+실패 하였습니다.
+Failed.
+*/
+ MSG_SKILL_FAIL = 0x627,
+/*20171018 to latest
+실패하여 모든 재료가 사라졌습니다.
+all materials are gone due to failure
+*/
+ MSG_SKILL_FAIL_MATERIAL_DESTROY = 0x628,
+/*20171018 to latest
+지정하신 탭 이름이 너무 길어 변경 할 수 없습니다.
+unable to change the name of the specified tab, because it's too long.
+*/
+ MSG_FAILED_CHANGE_TABNAME = 0x629,
+/*20171018 to latest
+더 이상 추가 할 수 없습니다.
+Cannot add more.
+*/
+ MSG_FAILED_ADD_TAB = 0x62a,
+/*20171018 to latest
+인증에 실패 했습니다.
+Authentication failed.
+*/
+ MSG_FAILED_LOCKSERVER = 0x62b,
+/*20171018 to latest
+자동 입력 방지
+Bot checks
+*/
+ MSG_BOT_CHECK = 0x62c,
+/*20171018 to latest
+감정이 않된 아이템은 재료로 사용할 수 없습니다.
+Items cannot be used in materials cannot be emotional.
+*/
+ MSG_SKILL_FAIL_MATERIAL_IDENTITY = 0x62d,
+/*20171018 to latest
+접속하신 IP는 라그나로크 온라인 이용이 불가능 합니다. 고객 지원 센터 또는 홈페이지로 문의 해 주십시오.
+It is impossible to connect using this IP in Ragnarok Online. Please contact the customer support center or home.
+*/
+ MSG_BAN_IP_BLOCK = 0x62e,
+/*20171018 to latest
+비밀번호가 6회 이상 잘못 입력되어 잠시 동안 접속이 제한됩니다. 고객님의 개인정보를 다시 한 번 확인해 주시길 바랍니다.
+You have entered a wrong password for more than six times, please check your personal information again.
+*/
+ MSG_BAN_INVALID_PWD_CNT = 0x62f,
+/*20171018 to latest
+합성에 사용한 아이템은 소모됩니다. 괜찮겠습니까?
+Consumption items are used in the synthesis. Are you sure?
+*/
+ MSG_MIX_ACCEPT = 0x630,
+/*20171018 to latest
+왼쪽에 보이는 글자 및 숫자조합을 입력해주세요.
+Please input the captcha code found at your left side.
+*/
+ MSG_BOT_CHECK_NOTIC = 0x631,
+/*20171018 to latest
+전장 설명 -
+Describes the battlefield --
+*/
+ MSG_DESCRIBE_BATTLEFIELD = 0x632,
+/*20171018 to latest
+입장 대기 상태 -
+Waiting for admission --
+*/
+ MSG_BATTLEFIELD_STATUS = 0x633,
+/*20171018 to latest
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_HELP = 0x634,
+/*20171018 to latest
+죄송합니다. 해당 직업의 캐릭터는 현재 테스트를 위해서 접속이 금지됩니다.
+Sorry the character you are trying to use is banned for testing connection.
+*/
+ MSG_BAN_NOT_ALLOWED_JOBCLASS = 0x635,
+/*20171018 to latest
+모든 장비 해제
+Remove all equipment
+*/
+ MSG_REMOVE_EQUIPEDITEM = 0x636,
+/*20171018 to latest
+미니 아이콘
+Mini Icon
+*/
+ MSG_MINI_ICON = 0x637,
+/*20171018 to latest
+진영 A : 진영 B
+Camp A: Camp B
+*/
+ MSG_BATTLEFIELD_TEAM = 0x638,
+/*20171018 to latest
+대기열
+Wait
+*/
+ MSG_WAIT_STATUS = 0x639,
+/*20171018 to latest
+전장 신청 취소 알림
+cancellation notice of Battlefield registration.
+*/
+ MSG_NOTIFY_BATTLEFIELD_CANCEL = 0x63a,
+/*20171018 to latest
+전장 필요 인원
+Required field for staff
+*/
+ MSG_BATTLEFIELD_COUNT = 0x63b,
+/*20171018 to latest
+전장 A 대기 인원
+Battlefield staff A is waiting.
+*/
+ MSG_BATTLEFIELD_ATEAM_COUNT = 0x63c,
+/*20171018 to latest
+전장 B 대기 인원
+Battlefield staff B is waiting.
+*/
+ MSG_BATTLEFIELD_BTEAM_COUNT = 0x63d,
+/*20171018 to latest
+내 대기 상황 : %d(진영 A)
+Waiting for my situation: %d (Camp A)
+*/
+ MSG_BATTLEFIELD_ATEAM_WAIT = 0x63e,
+/*20171018 to latest
+내 대기 상황 : %d(진영 B)
+Waiting for my situation: %d (Camp B)
+*/
+ MSG_BATTLEFIELD_BTEAM_WAIT = 0x63f,
+/*20171018 to latest
+전장 아이콘을 보여줍니다.
+Battlefield display icon.
+*/
+ MSG_SHOW_BATTLEFIELD_ICON = 0x640,
+/*20171018 to latest
+전장 아이콘을 보여주지 않습니다.
+Does not display the icon field.
+*/
+ MSG_DONT_SHOW_BATTLEFIELD_ICON = 0x641,
+/*20171018 to latest
+전장 이동 알림
+Field notification was moved.
+*/
+ MSG_NOTIFY_BATTLEFIELD_MOVE = 0x642,
+/*20171018 to latest
+전장 입장 보류 알림
+Admission pending notification of the battlefield
+*/
+ MSG_NOTIFY_BATTLEFIELD_DEFER = 0x643,
+/*20171018 to latest
+누군가
+Anyone
+*/
+ MSG_WHO_IS = 0x644,
+/*20171018 to latest
+ [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] deal '%d' damage on you.
+*/
+ MSG_I_RECEIVED_DAMAGE = 0x645,
+/*20171018 to latest
+ [%s]님이 [%s](으)로부터 '%d'의 데미지를 받았습니다.
+ [%s] received damage from [%s] with '%d' damage.
+*/
+ MSG_PARTY_RECEIVED_DAMAGE = 0x646,
+/*20171018 to latest
+ [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] received '%d' damage.
+*/
+ MSG_I_GAVE_DAMAGE = 0x647,
+/*20171018 to latest
+ [%s]님이 [%s]에게 '%d'의 데미지를 주었습니다.
+ [%s] deal damage to [%s] with '%d' damage.
+*/
+ MSG_PARTY_GAVE_DAMAGE = 0x648,
+/*20171018 to latest
+%s %d 개 드롭
+You dropped '%s' (%d).
+*/
+ MSG_DROP_ITEM = 0x649,
+/*20171018 to latest
+ [%s]퀘스트의 [%s]몬스터를 처치하였습니다. (%d/%d)
+[%s] Quest - defeated [%s] progress (%d/%d)
+*/
+ MSG_CLEAR_QUEST_MONSTER = 0x64a,
+/*20171018 to latest
+%s 퀘스트가 삭제 되었습니다.
+The Quest '%s' has been removed.
+*/
+ MSG_DELETE_QUEST = 0x64b,
+/*20171018 to latest
+[%s]님이
+[%s] has
+*/
+ MSG_NOTIFY_WHO = 0x64c,
+/*20171018 to latest
+'%d'의 경험치를
+You acquired '%d' Experience Points
+*/
+ MSG_NOTIFY_EXP = 0x64d,
+/*20171018 to latest
+'%d'의 잡경험치를
+You acquired '%d' Job Experience Points
+*/
+ MSG_NOTIFY_JOBEXP = 0x64e,
+/*20171018 to latest
+획득했습니다.
+ gained.
+*/
+ MSG_GET = 0x64f,
+/*20171018 to latest
+상실했습니다.
+ has lost.
+*/
+ MSG_LOSS = 0x650,
+/*20171018 to latest
+ [%s](으)로부터 '%d'의 코인을 스틸했습니다.
+From [%s], '%d' coins were stolen.
+*/
+ MSG_NOTIFY_STEAL_COIN = 0x651,
+/*20171018 to latest
+전투 메시지
+Battle Message
+*/
+ MSG_VIEW_COMBAT_MSG = 0x652,
+/*20171018 to latest
+파티원 전투 메시지
+Display Party Battle Message
+*/
+ MSG_VIEW_PARTY_COMBAT_MSG = 0x653,
+/*20171018 to latest
+획득 경험치
+Display Experience Message
+*/
+ MSG_VIEW_GETTING_EXP_MSG = 0x654,
+/*20171018 to latest
+파티원의 획득 경험치
+Display Party Experience Message
+*/
+ MSG_VIEW_PARTY_GETTING_EXP_MSG = 0x655,
+/*20171018 to latest
+퀘스트 정보 표시
+Display Quest Info Message
+*/
+ MSG_VIEW_QUEST_INFO_MSG = 0x656,
+/*20171018 to latest
+전장 정보 표시
+Display Battlefield Message
+*/
+ MSG_VIEW_BATTLEFIELD_INFO_MSG = 0x657,
+/*20171018 to latest
+[%s]에게
+[%s]
+*/
+ MSG_NOTIFY_TARGET_WHO = 0x658,
+/*20171018 to latest
+[%s] 스킬을 사용합니다.
+Casts [%s] skill.
+*/
+ MSG_NOTIFY_SKILL_TO_TARGET = 0x659,
+/*20171018 to latest
+기능제한상태
+Activate lock function
+*/
+ MSG_LOCK_MOUSE = 0x65a,
+/*20171018 to latest
+기능제한해제상태
+Deactivate lock function
+*/
+ MSG_UNLOCK_MOUSE = 0x65b,
+/*20171018 to latest
+[%s]님이 [%s](으)로부터 '%s' 를 획득 했습니다.
+Citizens of Midgard, Lady Luck shines upon [%s] !! [%s] has awarded the player with '%s' !!
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN = 0x65c,
+/*20171018 to latest
+소드맨
+Swordman
+*/
+ MSG_JOB_SWORDMAN = 0x65d,
+/*20171018 to latest
+매지션
+Magician
+*/
+ MSG_JOB_MAGICIAN = 0x65e,
+/*20171018 to latest
+아처
+Archer
+*/
+ MSG_JOB_ARCHER = 0x65f,
+/*20171018 to latest
+어콜라이트
+Acolyte
+*/
+ MSG_JOB_ACOLYTE = 0x660,
+/*20171018 to latest
+머첸트
+Merchant
+*/
+ MSG_JOB_MERCHANT = 0x661,
+/*20171018 to latest
+씨프
+Thief
+*/
+ MSG_JOB_THIEF = 0x662,
+/*20171018 to latest
+나이트
+Knight
+*/
+ MSG_JOB_KNIGHT = 0x663,
+/*20171018 to latest
+프리스트
+Priest
+*/
+ MSG_JOB_PRIEST = 0x664,
+/*20171018 to latest
+위저드
+Wizard
+*/
+ MSG_JOB_WIZARD = 0x665,
+/*20171018 to latest
+블랙스미스
+Black Smith
+*/
+ MSG_JOB_BLACKSMITH = 0x666,
+/*20171018 to latest
+헌터
+Hunter
+*/
+ MSG_JOB_HUNTER = 0x667,
+/*20171018 to latest
+어새신
+Assasin
+*/
+ MSG_JOB_ASSASSIN = 0x668,
+/*20171018 to latest
+크루세이더
+Crusader
+*/
+ MSG_JOB_CRUSADER = 0x669,
+/*20171018 to latest
+몽크
+Monk
+*/
+ MSG_JOB_MONK = 0x66a,
+/*20171018 to latest
+세이지
+Sage
+*/
+ MSG_JOB_SAGE = 0x66b,
+/*20171018 to latest
+로그
+Rogue
+*/
+ MSG_JOB_ROGUE = 0x66c,
+/*20171018 to latest
+알케미스트
+Alchemist
+*/
+ MSG_JOB_ALCHEMIST = 0x66d,
+/*20171018 to latest
+바드
+Bard
+*/
+ MSG_JOB_BARD = 0x66e,
+/*20171018 to latest
+댄서
+Dancer
+*/
+ MSG_JOB_DANCER = 0x66f,
+/*20171018 to latest
+룬 나이트
+Rune Knight
+*/
+ MSG_JOB_RUNE_KNIGHT = 0x670,
+/*20171018 to latest
+워록
+Warlock
+*/
+ MSG_JOB_WARLOCK = 0x671,
+/*20171018 to latest
+레인져
+Ranger
+*/
+ MSG_JOB_RANGER = 0x672,
+/*20171018 to latest
+아크 비숍
+Arc Bishop
+*/
+ MSG_JOB_ARCHBISHOP = 0x673,
+/*20171018 to latest
+미케닉
+Mechanic
+*/
+ MSG_JOB_MECHANIC = 0x674,
+/*20171018 to latest
+길로틴 크로스
+Guillotine Cross
+*/
+ MSG_JOB_GUILLOTINE_CROSS = 0x675,
+/*20171018 to latest
+로얄가드
+Royal Guard
+*/
+ MSG_JOB_ROYAL_GUARD = 0x676,
+/*20171018 to latest
+소서러
+Sorcerer
+*/
+ MSG_JOB_SORCERER = 0x677,
+/*20171018 to latest
+민스트럴
+Minstrel
+*/
+ MSG_JOB_MINSTREL = 0x678,
+/*20171018 to latest
+원더러
+Wanderer
+*/
+ MSG_JOB_WANDERER = 0x679,
+/*20171018 to latest
+수라
+Sura
+*/
+ MSG_JOB_SURA = 0x67a,
+/*20171018 to latest
+제네릭
+Genetic
+*/
+ MSG_JOB_GENETIC = 0x67b,
+/*20171018 to latest
+쉐도우 체이서
+Shadow Chaser
+*/
+ MSG_JOB_SHADOW_CHASER = 0x67c,
+/*20171018 to latest
+소드맨 하이
+High Swordman
+*/
+ MSG_JOB_SWORDMAN_H = 0x67d,
+/*20171018 to latest
+매지션 하이
+High Magician
+*/
+ MSG_JOB_MAGICIAN_H = 0x67e,
+/*20171018 to latest
+아처 하이
+High Archer
+*/
+ MSG_JOB_ARCHER_H = 0x67f,
+/*20171018 to latest
+어콜라이트 하이
+High Acolyte
+*/
+ MSG_JOB_ACOLYTE_H = 0x680,
+/*20171018 to latest
+머첸트 하이
+High Merchant
+*/
+ MSG_JOB_MERCHANT_H = 0x681,
+/*20171018 to latest
+씨프 하이
+High Thief
+*/
+ MSG_JOB_THIEF_H = 0x682,
+/*20171018 to latest
+로드나이트
+Lord Knight
+*/
+ MSG_JOB_KNIGHT_H = 0x683,
+/*20171018 to latest
+하이프리스트
+High Priest
+*/
+ MSG_JOB_PRIEST_H = 0x684,
+/*20171018 to latest
+하이위저드
+High Wizard
+*/
+ MSG_JOB_WIZARD_H = 0x685,
+/*20171018 to latest
+화이트스미스
+White Smith
+*/
+ MSG_JOB_BLACKSMITH_H = 0x686,
+/*20171018 to latest
+스나이퍼
+Sniper
+*/
+ MSG_JOB_HUNTER_H = 0x687,
+/*20171018 to latest
+어새신크로스
+Assasin Cross
+*/
+ MSG_JOB_ASSASSIN_H = 0x688,
+/*20171018 to latest
+팔라딘
+Paladin
+*/
+ MSG_JOB_CRUSADER_H = 0x689,
+/*20171018 to latest
+챔피온
+Champion
+*/
+ MSG_JOB_MONK_H = 0x68a,
+/*20171018 to latest
+프로페서
+Professor
+*/
+ MSG_JOB_SAGE_H = 0x68b,
+/*20171018 to latest
+스토커
+Stalker
+*/
+ MSG_JOB_ROGUE_H = 0x68c,
+/*20171018 to latest
+크리에이터
+Creator
+*/
+ MSG_JOB_ALCHEMIST_H = 0x68d,
+/*20171018 to latest
+클로운
+Clown
+*/
+ MSG_JOB_BARD_H = 0x68e,
+/*20171018 to latest
+집시
+Gypsy
+*/
+ MSG_JOB_DANCER_H = 0x68f,
+/*20171018 to latest
+노비스
+Wedding
+*/
+ MSG_JOB_NOVICE = 0x690,
+/*20171018 to latest
+하이노비스
+High Novice
+*/
+ MSG_JOB_NOVICE_H = 0x691,
+/*20171018 to latest
+슈퍼노비스
+Super Novice
+*/
+ MSG_JOB_SUPERNOVICE = 0x692,
+/*20171018 to latest
+건슬링거
+Gunslinger
+*/
+ MSG_JOB_GUNSLINGER = 0x693,
+/*20171018 to latest
+닌자
+Ninja
+*/
+ MSG_JOB_NINJA = 0x694,
+/*20171018 to latest
+태권소년/소녀
+Taekwon F/M
+*/
+ MSG_JOB_TAEKWON = 0x695,
+/*20171018 to latest
+권성
+Star Gladiator
+*/
+ MSG_JOB_STAR = 0x696,
+/*20171018 to latest
+소울링커
+Soul Linker
+*/
+ MSG_JOB_LINKER = 0x697,
+/*20171018 to latest
+파티모집
+Party Recruitment
+*/
+ MSG_SEEK_PARTY_MEMBER = 0x698,
+/*20171018 to latest
+파티 모집 리스트
+Party Booking List
+*/
+ MSG_SEEK_PARTY_LIST = 0x699,
+/*20171018 to latest
+파티 모집 중
+Recruiting Party
+*/
+ MSG_SEEK_PARTY_CHECK = 0x69a,
+/*20171018 to latest
+[활]을 장착한 상태여야 합니다.
+[Bow] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_BOW = 0x69b,
+/*20171018 to latest
+[악기/채찍]을 장착한 상태여야 합니다.
+[Musical Instrument/Whip] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_INSTRUMENT_WHIP = 0x69c,
+/*20171018 to latest
+영문과 숫자만 사용가능합니다.
+Only alphanumeric characters are allowed.
+*/
+ MSG_BAD_CHAR = 0x69d,
+/*20171018 to latest
+알림
+Notice
+*/
+ MSG_ALRAM = 0x69e,
+/*20171018 to latest
+상점 정보가 정확하지 않아 아이템 구매가 실패하였습니다.
+Item purchase failed due to incorrect shop information.
+*/
+ MSG_FAIL_BUY_ITEM_INVALID_MCSTORE = 0x69f,
+/*20171018 to latest
+소지 아이템 창에서 버릴 수 있습니다.
+Item cannot be discarded from the window.
+*/
+ MSG_CAN_DROP_ITEM_TO_ITEMWND = 0x6a0,
+/*20171018 to latest
+시간
+Time
+*/
+ MSG_TIME = 0x6a1,
+/*20171018 to latest
+맵
+Map
+*/
+ MSG_MAP = 0x6a2,
+/*20171018 to latest
+거래 상태에서는 아이템 사용 및 장비 착용/해제를 할 수 없습니다.
+You can't use, equip or disarm items when you're trading.
+*/
+ MSG_CANT_USE_WHEN_OPENED_EXCHANGEWND = 0x6a3,
+/*20171018 to latest
+미지정값
+Unspecified value
+*/
+ MSG_HOTKEY_UNKOWN = 0x6a4,
+/*20171018 to latest
+/stateinfo : 상태 아이콘에 대한 설명을 보여줍니다. On Off
+/stateinfo: Shows the description of status icons. On Off
+*/
+ MSG_EXPLAIN_STATEINFO = 0x6a5,
+/*20171018 to latest
+상태 정보 On : 상태 아이콘에 대한 설명이 표시됩니다.
+Status Information On: Status icon description is enabled.
+*/
+ MSG_SHOW_STATEINFO_ON = 0x6a6,
+/*20171018 to latest
+상태 정보 Off: 상태 아이콘에 대한 설명이 표시되지 않습니다.
+Status Information Off: Status icon description is disabled.
+*/
+ MSG_SHOW_STATEINFO_OFF = 0x6a7,
+/*20171018 to latest
+같은 아이템은 한번에 %d개 이상은 살 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_BUY_ITEM2 = 0x6a8,
+/*20171018 to latest
+같은 아이템은 한번에 %d개 이상은 팔 수 없습니다.
+It is not possible to purchase the same item more than %d pieces at a time
+*/
+ MSG_LIMIT_SELL_ITEM = 0x6a9,
+/*20171018 to latest
+해당 아이템의 총 구매 가능 개수는 %d개 입니다.
+Can purchase upto %d pieces of the same item at a time.
+*/
+ MSG_CAN_BUY_ITEM_NUM = 0x6aa,
+/*20171018 to latest
+설정한 내용은 정상 종료 시 [%s\%s]에 저장됩니다.
+User customized key is saved to [%s\%s]
+*/
+ MSG_SAVE_HOTKEY_TO_FILE = 0x6ab,
+/*20171018 to latest
+[%s] 님은 현재 교환 신청을 받을 수 없는 상태입니다.
+[%s] is currently on trade and cannot accept the request.
+*/
+ MSG_CHARACTER_IS_BUSY = 0x6ac,
+/*20171018 to latest
+RO_HELP
+RO_HELP.
+*/
+ MSG_RO_HELP = 0x6ad,
+/*20171018 to latest
+모루가 존재 하지 않습니다.
+Anvil does not exist.
+*/
+ MSG_HAVENOT_ANVIL = 0x6ae,
+/*20171018 to latest
+노비스 레벨 10 이하는 귓속말이 금지됩니다
+Novice below level 10 is not allowed to whisper.
+*/
+ MSG_WHISPER_BLOCK_NOVICE_LEVEL10 = 0x6af,
+/*20171018 to latest
+공격
+Attack
+*/
+ MSG_JOB_ATTACKER = 0x6b0,
+/*20171018 to latest
+방어
+Defense
+*/
+ MSG_JOB_TANKER = 0x6b1,
+/*20171018 to latest
+회복
+Consumables
+*/
+ MSG_JOB_HEALER = 0x6b2,
+/*20171018 to latest
+보조
+Support
+*/
+ MSG_JOB_ASSISTANCE = 0x6b3,
+/*20171018 to latest
+파티 모집 관련 명령어
+Party recruitment related command
+*/
+ MSG_DESCRIBE_PARTY_BOOKING = 0x6b4,
+/*20171018 to latest
+길드 동맹신청이 불가능합니다
+Guild alliance application is not possible.
+*/
+ MSG_GUILD_ALLY_REQUEST_DISABLE = 0x6b5,
+/*20171018 to latest
+길드 적대신청이 불가능합니다
+Guild hostility application is not possible.
+*/
+ MSG_GUILD_HOSTILE_REQUEST_DISABLE = 0x6b6,
+/*20171018 to latest
+아지트맵에서는 친구추가가 불가능합니다
+Adding friends is not possible in this map.
+*/
+ MSG_FRIEND_ADD_FALSE_AGIT = 0x6b7,
+/*20171018 to latest
+구매노점 개설
+Buying Store Window
+*/
+ MSG_BUYINGSTORE_MAKEWND_TITLE = 0x6b8,
+/*20171018 to latest
+구매가 :
+Price:
+*/
+ MSG_BUYINGSTORE_MAKEWND_PRICE = 0x6b9,
+/*20171018 to latest
+소지액 :
+Money:
+*/
+ MSG_BUYINGSTORE_MAKEWND_MYZENY = 0x6ba,
+/*20171018 to latest
+구매 한도액
+Purchase Zeny Limit
+*/
+ MSG_BUYINGSTORE_MAKEWND_LIMITZENY = 0x6bb,
+/*20171018 to latest
+구매할 아이템을 등록하지 않았습니다. 구매하실 아이템을 등록해 주세요
+Please register the item first that has to be purchased.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADDITEM = 0x6bc,
+/*20171018 to latest
+%s 아이템의 가격을 입력해 주세요.
+Enter the price for item %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTPRICE = 0x6bd,
+/*20171018 to latest
+%s 아이템의 가격을 9999만 Zeny이하로 입력해 주세요.
+Enter the price for item %s. It has to be below 99990000 Zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTPRICE = 0x6be,
+/*20171018 to latest
+%s 아이템의 구매수량을 입력해 주세요.
+Enter the item number for %s.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTNUM = 0x6bf,
+/*20171018 to latest
+%s 아이템의 소지수량과 구매수량의 합이 9999개 이상입니다. 9999개 이하의 수량을 입력해 주세요.
+The sum of purchasing and belonging items is over 9999. The sum has to be bellow 9999.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTNUM = 0x6c0,
+/*20171018 to latest
+중복된 아이템이 존재합니다.
+You have duplicate items in your purchase list.
+*/
+ MSG_BUYINGSTORE_MAKEWND_DUPLICATEITEM = 0x6c1,
+/*20171018 to latest
+제한 금액을 입력해 주세요
+Enter the limited price.
+*/
+ MSG_BUYINGSTORE_MAKEWND_INPUTLIMITZENY = 0x6c2,
+/*20171018 to latest
+입력한 제한금액이 소지금액을 초과합니다. 다시 설정해 주세요
+You have entered a greater amount of zeny than you have. Please check your zeny.
+*/
+ MSG_BUYINGSTORE_MAKEWND_REINPUTLIMITZENY = 0x6c3,
+/*20171018 to latest
+%s : %s Zeny => %s EA
+%s: %s Zeny => %s ea.
+*/
+ MSG_BUYINGSTORE_MAKEWND_ITEMLIST = 0x6c4,
+/*20171018 to latest
+구매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORBUYITEMLIST = 0x6c5,
+/*20171018 to latest
+나의 구매노점
+Purchase list:
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_TITLE = 0x6c6,
+/*20171018 to latest
+제한금액 : %s Zeny
+Price limit: %s Zeny
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_LIMITZENY = 0x6c7,
+/*20171018 to latest
+%s %s Zeny %d 개
+Buying %s for %s Zeny. Amount: %d.
+*/
+ MSG_BUYINGSTORE_MYSHOPWND_ITEMINFO = 0x6c8,
+/*20171018 to latest
+구매 노점
+Wanted items
+*/
+ MSG_BUYINGSTORE_SHOPWND_TITLE = 0x6c9,
+/*20171018 to latest
+판매 가능한 아이템 목록
+Available items:
+*/
+ MSG_BUYINGSTORE_MIRRORSELLWND_TITLE = 0x6ca,
+/*20171018 to latest
+해당 아이템의 총 판매 가능 개수는 %d개 입니다.
+The max. number of items you can sell is %d.
+*/
+ MSG_BUYINGSTORE_SELLWND_LIMITNUM = 0x6cb,
+/*20171018 to latest
+구매노점의 제한금액을 초과하여 판매할 수 없습니다.
+Buyer has insufficient money, lower the amount of items you're selling.
+*/
+ MSG_BUYINGSTORE_SELLWND_LACKBUYERZENY = 0x6cc,
+/*20171018 to latest
+구매상점 개설에 실패했습니다.
+Failed to open purchase shop.
+*/
+ MSG_BUYINGSTORE_OPEN_FAILED = 0x6cd,
+/*20171018 to latest
+아이템의 총 무게가 %d 만큼 소지 한계량을 초과합니다. 다시 설정해 주세요.
+You exceed the total amount of items.
+*/
+ MSG_BUYINGSTORE_OVERWEIGHT = 0x6ce,
+/*20171018 to latest
+제한금액만큼의 아이템을 모두 구매하였습니다.
+You have purchased all items within the limited price.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERLIMITZENY = 0x6cf,
+/*20171018 to latest
+아이템을 모두 구매했습니다.
+You purchased all items.
+*/
+ MSG_BUYINGSTORE_TRADE_BUYCOMPLETE = 0x6d0,
+/*20171018 to latest
+구매자의 잔액이 부족하여 거래가 실패하였습니다.
+Failed to deal because you have not enough Zeny.
+*/
+ MSG_BUYINGSTORE_TRADE_LACKBUYERZENY = 0x6d1,
+/*20171018 to latest
+%s %d개를 %dz에 판매하였습니다.
+You have sold %s. Amount: %d. Total Zeny: %dz
+*/
+ MSG_BUYINGSTORE_TRADE_SELLCOMPLETE = 0x6d2,
+/*20171018 to latest
+%s 아이템은 희망 구매갯수보다 수량이 많아 판매하지 못하였습니다
+%s item could not be sold because you do not have the wanted amount of items.
+*/
+ MSG_BUYINGSTORE_TRADE_OVERCOUNT = 0x6d3,
+/*20171018 to latest
+소환된 정령이 없습니다.
+You don't have any summoned spirits.
+*/
+ MSG_USESKILL_FAIL_EL_SUMMON = 0x6d4,
+/*20171018 to latest
+서버연합대전 제약사항 입니다.
+This is a restricted server.
+*/
+ MSG_AGAINSTSERVERSIEGEWARFARE_RESTRICTION = 0x6d5,
+/*20171018 to latest
+OTP 비밀번호는 6자리 입니다.
+OTP password is 6 digits long.
+*/
+ MSG_OTP_MUST_6_CHAR = 0x6d6,
+/*20171018 to latest
+OTP 정보가 없습니다. 관리자에게 문의하시기 바랍니다.
+OTP information is unavailable. Please contact your administrator.
+*/
+ MSG_DB_ERROR = 0x6d7,
+/*20171018 to latest
+OTP 인증에 실패 했습니다.
+OTP authentication failed.
+*/
+ MSG_OTP_FAILED = 0x6d8,
+/*20171018 to latest
+파티광고가 추가되었습니다
+Party ad has been added.
+*/
+ MSG_PARTY_BOOKING_NOTIFY = 0x6d9,
+/*20171018 to latest
+모집 중
+Recruit party members
+*/
+ MSG_PARTY_BOOKING_REQURT = 0x6da,
+/*20171018 to latest
+역할
+Roles
+*/
+ MSG_PARTY_BOOKING_TYPE = 0x6db,
+/*20171018 to latest
+1차 직업
+1st Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_1 = 0x6dc,
+/*20171018 to latest
+2차 직업
+2nd Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_2 = 0x6dd,
+/*20171018 to latest
+3-1차 직업
+3-1 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_3_1 = 0x6de,
+/*20171018 to latest
+3-2차 직업
+3-2 Classes
+*/
+ MSG_PARTY_BOOKING_TYPE_3_2 = 0x6df,
+/*20171018 to latest
+전승 1차 직업
+1st Job High
+*/
+ MSG_PARTY_BOOKING_TYPE_1PLUS = 0x6e0,
+/*20171018 to latest
+전승 2차 직업
+2nd Jobs High
+*/
+ MSG_PARTY_BOOKING_TYPE_2PLUS = 0x6e1,
+/*20171018 to latest
+기타 직업군
+Other Jobs
+*/
+ MSG_PARTY_BOOKING_TYPE_ETC = 0x6e2,
+/*20171018 to latest
+모집 하기
+Recruit
+*/
+ MSG_PARTY_BOOKING_REQURTING = 0x6e3,
+/*20171018 to latest
+파티원을 모집합니다.
+Open party recruitment window.
+*/
+ MSG_PARTY_BOOKING_REQURT_TIP = 0x6e4,
+/*20171018 to latest
+검색 중 -
+Searching -
+*/
+ MSG_PARTY_BOOKING_SEARCH = 0x6e5,
+/*20171018 to latest
+모두 선택
+Select All
+*/
+ MSG_PARTY_BOOKING_ALL_SELECT = 0x6e6,
+/*20171018 to latest
+최소한 하나의 직업이 모집 중이어야 합니다.
+Recruitment of at least one job must be running.
+*/
+ MSG_PARTY_BOOKING_ERR1 = 0x6e7,
+/*20171018 to latest
+최소 1개이상의 직업을 선택해 주셔야 합니다.
+You have to select atleast 1 or more jobs.
+*/
+ MSG_PARTY_BOOKING_ERR2 = 0x6e8,
+/*20171018 to latest
+선택된 직업은 %d개입니다. 최대 6개까지만 직업을 선택할 수 있습니다.
+You have selected %d Jobs. You can only select up to 6 different jobs.
+*/
+ MSG_PARTY_BOOKING_ERR3 = 0x6e9,
+/*20171018 to latest
+레벨에 숫자 이외의 문자는 들어갈 수 없습니다.
+Only numeric characters are allowed.
+*/
+ MSG_PARTY_BOOKING_ERR4 = 0x6ea,
+/*20171018 to latest
+레벨은 1~150 사이의 숫자를 입력해 주세요.
+Please enter levels between 1~150.
+*/
+ MSG_PARTY_BOOKING_ERR5 = 0x6eb,
+/*20171018 to latest
+ 해당 맵에서는 의상 장비가 보이지 않습니다.
+Nothing found in the selected map.
+*/
+ MSG_DISABLE_COSTUMEITEM_MAP = 0x6ec,
+/*20171018 to latest
+아이템을 착용할 수 있는 레벨이 아닙니다.
+You cannot equip this item with your current level.
+*/
+ MSG_CANNOT_EQUIP_ITEM_LEVEL = 0x6ed,
+/*20171018 to latest
+아이템을 사용할 수 있는 레벨이 아닙니다.
+You cannot use this item with your current level.
+*/
+ MSG_CANNOT_USE_ITEM_LEVEL = 0x6ee,
+/*20171018 to latest
+ 채팅모드 OnOff 활성화
+Enable Battlemode
+*/
+ MSG_CHATMODE_ONOFF = 0x6ef,
+/*20171018 to latest
+탭사이즈 크기가 초과되어 추가할 수 없습니다.
+Failed to add because you have reached the limit.
+*/
+ MSG_OVER_TABSIZE = 0x6f0,
+/*20171018 to latest
+ 창 표시 정보
+Window Sign Information
+*/
+ MSG_SET_CHATINFO = 0x6f1,
+/*20171018 to latest
+판매
+Sell
+*/
+ MSG_SELL = 0x6f2,
+/*20171018 to latest
+구매
+Purchase
+*/
+ MSG_BUY = 0x6f3,
+/*20171018 to latest
+노점 검색
+Search for Vends
+*/
+ MSG_SEARCH_STOREINFO = 0x6f4,
+/*20171018 to latest
+노점 이름
+Shop Name
+*/
+ MSG_STORE_NAME = 0x6f5,
+/*20171018 to latest
+수량
+Quantity
+*/
+ MSG_SEARCH_ITEM_COUNT = 0x6f6,
+/*20171018 to latest
+가격
+Cost
+*/
+ MSG_SEARCH_ITEM_PRICE = 0x6f7,
+/*20171018 to latest
+검색 결과가 너무 많습니다. 검색어를 자세히 입력 해 주세요.
+Too much results have been found. Please do a more precisely search.
+*/
+ MSG_SSI_FAILED_OVER_MAXCOUNT = 0x6f8,
+/*20171018 to latest
+해당 노점을 여시겠습니까?
+Do you want to open a street stall?
+*/
+ MSG_OPEN_SEARCH_STORE = 0x6f9,
+/*20171018 to latest
+SSO 인증에 실패하였습니다.
+Failed to recognize SSO.
+*/
+ MSG_SSO_FAILED = 0x6fa,
+/*20171018 to latest
+현재 해당지역으로 이동 할 수 없습니다
+Cannot move to the applied area.
+*/
+ MSG_ZONE_MOVE_FAIL = 0x6fb,
+/*20171018 to latest
+단어가 포함된 아이템 검색
+searching item including the word
+*/
+ MSG_SEARCH_INCLUDED = 0x6fc,
+/*20171018 to latest
+탈퇴한 유저입니다.
+User has been expelled.
+*/
+ MSG_WITHDREW_USERS = 0x6fd,
+/*20171018 to latest
+게임 이용에 동의하지 않았습니다.
+You have not accepted the user agreements yet.
+*/
+ MSG_DIDNOT_AGREE = 0x6fe,
+/*20171018 to latest
+존재 하지 않는 계정입니다.
+You will not be disconnect from the game.
+*/
+ MSG_ACCOUNT_DOESNOT_EXIST = 0x6ff,
+/*20171018 to latest
+본 게임은 12세 이용가입니다.
+It is available only for 12 hours.
+*/
+ MSG_AGE_RESTRICTIONS = 0x700,
+/*20171018 to latest
+계정도용 조사를 위한 블럭상태입니다.
+Your account is blocked due to illegal use of the game account.
+*/
+ MSG_ACCOUNT_BLOCK = 0x701,
+/*20171018 to latest
+버그조사를 위한 블럭상태입니다.
+Your account is blocked because there may exist a bug with your account.
+*/
+ MSG_BUG_BLOCK = 0x702,
+/*20171018 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 75% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 75% for 30 minutes.
+*/
+ MSG_PLUSEXP75 = 0x703,
+/*20171018 to latest
+몬스터 사냥을 통해 얻을 수 있는 Base, Job 경험치가 30분간 50% 증가합니다.
+Increases base exp and job exp gained by killing monsters up to 50% for 30 minutes.
+*/
+ MSG_PLUSEXP50 = 0x704,
+/*20171018 to latest
+판매(구매) 정보가 없습니다.
+No sales information.
+*/
+ MSG_FAIL_OPEN_STORE = 0x705,
+/*20171018 to latest
+더 이상 검색 할 수 없습니다.
+Failed to search any further.
+*/
+ MSG_SSI_FAILED_SEARCH_CNT = 0x706,
+/*20171018 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_SSI_FAILED_ITEM_DOES_NOT_EXIST = 0x707,
+/*20171018 to latest
+아직 검색 할 수 없습니다.
+Cannot search yet.
+*/
+ MSG_SSI_FAILED_LIMIT_SERACH_TIME = 0x708,
+/*20171018 to latest
+카드 이름 또는 접두사(접미사)를 입력하세요
+Enter the card name or prefix/suffix.
+*/
+ MSG_SSI_TOOLTIP_OF_SERACHING_THE_CARD = 0x709,
+/*20171018 to latest
+남은 검색 횟수 : %d
+Searches left: %d
+*/
+ MSG_SSI_REST_OF_NUMBER_OF_SEARCHES = 0x70a,
+/*20171018 to latest
+검색 된 노점이 없습니다.
+No result has been found.
+*/
+ MSG_SSI_FAILED_SEARCH_STORE = 0x70b,
+/*20171018 to latest
+아이템 가격 범위가 잘못되었습니다.
+The item price is too high.
+*/
+ MSG_SSI_FAILED_PRICE_ISNOT_VALID = 0x70c,
+/*20171018 to latest
+일반 장비
+Normal Gear
+*/
+ MSG_GENERAL_EQUIPMENT = 0x70d,
+/*20171018 to latest
+의상 장비
+Costume
+*/
+ MSG_COSTUME_EQUIPMENT = 0x70e,
+/*20171018 to latest
+분
+minute
+*/
+ MSG_MINUTE = 0x70f,
+/*20171018 to latest
+초
+second
+*/
+ MSG_SECOND = 0x710,
+/*20171018 to latest
+아이템 명을 입력해 주세요.
+Please enter the name of the item.
+*/
+ MSG_SSI_FAILED_ENTER_THE_NAME_OF_ITEM = 0x711,
+/*20171018 to latest
+해당 아이템 명은 존재하지 않습니다.
+The item you have entered does not exist.
+*/
+ MSG_SSI_FAILED_NAME_OF_ITEM_DOES_NOT_EXIST = 0x712,
+/*20171018 to latest
+진입가능한 맵이 존재하지 않습니다.
+The map is not available.
+*/
+ MSG_NOT_EXIST_ENTRYMAP = 0x713,
+/*20171018 to latest
+해당 카드 이름이나 접두사(접미사)는 존재하지 않습니다.
+The selected name or prefix/suffix does not exist.
+*/
+ MSG_SSI_FAILED_NAME_OF_CARD_DOES_NOT_EXIST = 0x714,
+/*20171018 to latest
+ 한번에 구매 가능 종류는 10개입니다.
+You can purchase up to 10 items.
+*/
+ MSG_CASH_FAILED_TOTAL_CNT = 0x715,
+/*20171018 to latest
+ 일부 아이템의 구매가 실패하였습니다.
+Some items could not be purchased.
+*/
+ MSG_CASH_FAILED_BUY_SOME = 0x716,
+/*20171018 to latest
+생년월일 6자리를 입력하세요.(예시:801122)
+Enter your 6-digit DOB(YYMMDD) (e.g: 801122)
+*/
+ MSG_ENTER_PEOPLE_BIRTH = 0x717,
+/*20171018 to latest
+알 수 없는 오류가 발생하였습니다.
+Now Logging Out.
+*/
+ MSG_RESULT_FAIL_UNKNOWN = 0x718,
+/*20171018 to latest
+데이타 베이스 오류가 발생하였습니다.
+A database error has occurred.
+*/
+ MSG_RESULT_FAIL_DATABASE = 0x719,
+/*20171018 to latest
+캐릭터를 삭제하기 위해서는 길드에서 탈퇴 해야 합니다.
+Please leave your guild first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_GUILD = 0x71a,
+/*20171018 to latest
+캐릭터를 삭제하기 위해서는 파티에서 탈퇴 해야 합니다.
+Please leave your party first in order to remove your character.
+*/
+ MSG_RESULT_FAIL_PARTY = 0x71b,
+/*20171018 to latest
+시스템 설정으로 인해 삭제할 수 없습니다.
+You cannot delete this character because the delete time has not expired yet.
+*/
+ MSG_RESULT_FAIL_CONFIGURATION = 0x71c,
+/*20171018 to latest
+아직 삭제 가능 시간이 아닙니다.
+You cannot delete this character at the moment.
+*/
+ MSG_RESULT_FAIL_DATE = 0x71d,
+/*20171018 to latest
+생년월일이 일치하지 않습니다.
+Your entered birthday does not match.
+*/
+ MSG_RESULT_FAIL_BIRTH = 0x71e,
+/*20171018 to latest
+친밀도가 부족합니다.
+You lack of familiarity.
+*/
+ MSG_USESKILL_FAIL_RELATIONGRADE = 0x71f,
+/*20171018 to latest
+스타일체인지 파이터 상태에서만 사용가능합니다.
+This is only available on style change for fighting classes.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 0x720,
+/*20171018 to latest
+스타일체인지 그래플러 상태에서만 사용가능합니다.
+This is only available on style change for novice.
+*/
+ MSG_USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 0x721,
+/*20171018 to latest
+파티등록실패
+Party Registration failed.
+*/
+ MSG_PARTY_REGISTRATION_FAILED = 0x722,
+/*20171018 to latest
+검색된 조건의 리스트가 없습니다.
+results have been found.
+*/
+ MSG_PARTY_SEARCH_FAILED = 0x723,
+/*20171018 to latest
+광고삭제에 실패했습니다.
+Failed to remove result.
+*/
+ MSG_PARTY_AD_DELETE_FAILED = 0x724,
+/*20171018 to latest
+조건에 맞는 광고가 없어 실패했습니다.
+No results have been found.
+*/
+ MSG_PARTY_NOT_EXIST_AD = 0x725,
+/*20171018 to latest
+결제 정보가 없습니다.
+No payment information has been found.
+*/
+ MSG_REFUSE_SSO_NOT_PAY_USER = 0x726,
+/*20171018 to latest
+교환 시 스크린샷 찍기
+Screenshot Trade
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE = 0x727,
+/*20171018 to latest
+[거래_%s]
+[Trade_%s]
+*/
+ MSG_SCREENSHOT_FOR_EXCHANGE_CHARNAME = 0x728,
+/*20171018 to 20180131
+사망으로 인해 신생명보험서가 자동 소비되었습니다
+20180207 to latest
+사망 시 소지한 아이템으로 경험치 손실을 막았습니다.
+Death due to the auto insurance young people are spending.
+*/
+ MSG_NOTIFY_NEO_INSURANCE_ITEM_USE = 0x729,
+/*20171018 to latest
+대화
+Chat Dialog
+*/
+ MSG_TALK = 0x72a,
+/*20171018 to latest
+중복사용이 불가능합니다.
+Redundant is not available.
+*/
+ MSG_MACRO_DUPLICATE = 0x72b,
+/*20171018 to latest
+사용제한이 걸려있습니다.
+Use the limit that has been set.
+*/
+ MSG_MACRO_POSTDELAY = 0x72c,
+/*20171018 to latest
+현재 사용제한이 걸려 있지 않습니다.
+No user restrictions are set.
+*/
+ MSG_MACRO_NOT_POSTDELAY = 0x72d,
+/*20171018 to latest
+예기치 못한 사유로 인해 접속이 실패하였습니다. 관리자에게 문의해 주시기 바랍니다.
+Connection has failed. Please contact your administrator.
+*/
+ MSG_SSO_ERROR_MSG = 0x72e,
+/*20171018 to latest
+접속 정보 인증 실패하였습니다.
+Failed to authenticate.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_TOKEN = 0x72f,
+/*20171018 to latest
+가입하지 않은 사용자입니다.
+User is offline.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_USER = 0x730,
+/*20171018 to latest
+나이제한 때문에 이계정으로 이서버에 접속할 수 없습니다.
+The age limit from commandment tables cannot connect to this server.
+*/
+ MSG_REFUSE_SSO_AUTH_INVALID_AGE = 0x731,
+/*20171018 to latest
+구매하기
+Buy
+*/
+ MSG_NC_BUY = 0x732,
+/*20171018 to latest
+장바구니 비우기
+Cancel.
+*/
+ MSG_NC_BLANK = 0x733,
+/*20171018 to latest
+첫 페이지
+First page
+*/
+ MSG_NC_FIRSTPAGE = 0x734,
+/*20171018 to latest
+마지막 페이지
+Last page
+*/
+ MSG_NC_LASTPAGE = 0x735,
+/*20171018 to latest
+신규
+New
+*/
+ MSG_NC_CAT1 = 0x736,
+/*20171018 to latest
+인기
+Headgears
+*/
+ MSG_NC_CAT2 = 0x737,
+/*20171018 to latest
+한정
+Limited
+*/
+ MSG_NC_CAT3 = 0x738,
+/*20171018 to latest
+임대장비
+Rental Items
+*/
+ MSG_NC_CAT4 = 0x739,
+/*20171018 to latest
+영구장비
+Equipments
+*/
+ MSG_NC_CAT5 = 0x73a,
+/*20171018 to latest
+버프
+Scrolls
+*/
+ MSG_NC_CAT6 = 0x73b,
+/*20171018 to latest
+회복
+Consumables
+*/
+ MSG_NC_CAT7 = 0x73c,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_NC_CAT8 = 0x73d,
+/*20171018 to latest
+가격
+Cost
+*/
+ MSG_NC_COST = 0x73e,
+/*20171018 to latest
+수량
+Quantity
+*/
+ MSG_NC_NUM = 0x73f,
+/*20171018 to latest
+개
+Total
+*/
+ MSG_NC_COUNT = 0x740,
+/*20171018 to latest
+무료 캐시 : %s C
+Free Cash: %s C
+*/
+ MSG_NC_FREECASH = 0x741,
+/*20171018 to latest
+소지 캐시 : %s C
+CashPoints: %s C
+*/
+ MSG_NC_CASH = 0x742,
+/*20171018 to latest
+이 지역에서는 몬스터 소환이 불가능합니다.
+You cannot summon a monster in this area.
+*/
+ MSG_CALLMONSTER_FAIL_AREA = 0x743,
+/*20171018 to latest
+무료캐시 사용량이 전체 금액을 초과하고있습니다
+Exceeded total free cash
+*/
+ MSG_BUY_CASH_FAIL2 = 0x744,
+/*20171018 to latest
+ 설정한 내용이 [SaveData_ExMacro%d]에 저장됩니다.
+%d seconds left until you can use
+*/
+ MSG_MACRO_SAVE_DATA = 0x745,
+/*20171018 to latest
+약 %d 초 후에 사용할 수 있습니다
+Content has been saved in [SaveData_ExMacro%d]
+*/
+ MSG_ITEM_REUSE_LIMIT_SECOND = 0x746,
+/*20171018 to latest
+[창]을 장착한 상태여야 합니다.
+~ [Windows] must be equipped with.
+*/
+ MSG_FAIL_NEED_EQUIPPED_SPEAR = 0x747,
+/*20171018 to latest
+드래곤 탑승시에만 사용가능합니다.
+Available only on the dragon.
+*/
+ MSG_USESKILL_FAIL_DRAGON = 0x748,
+/*20171018 to latest
+본 서버에 접속할 수 있는 정원이 초과되어 진입이 불가능 합니다.
+Unable to proceed due to exceeding capacity.
+*/
+ MSG_OVER_CONNECT_USER = 0x749,
+/*20171018 to latest
+실명 인증이 되지 않았습니다. 실명인증 사이트로 이동합니다
+Real name has not been verified. Go to name verification site.
+*/
+ MSG_AUTHENTICATE = 0x74a,
+/*20171018 to latest
+저장 할 슬롯을 선택 해 주세요
+Please select slot you are going to save.
+*/
+ MSG_SELECT_SAVESLOT = 0x74b,
+/*20171018 to latest
+%s, 축하드립니다. '%s' 를 얻으셨습니다!
+Congratulation %s, Acquired '%s' !
+*/
+ MSG_BROADCASTING_SPECIAL_ITEM_OBTAIN2 = 0x74c,
+/*20171018 to latest
+그루미상태에서는 사용할 수 없습니다
+Unable to use in gloomy state
+*/
+ MSG_NOTUSE_GROOMY = 0x74d,
+/*20171018 to latest
+구매물품의 합계금액이 케릭터가 소지할 수 있는 최대 금액을 초과하였습니다
+Purchased products has exceeded the total price.
+*/
+ MSG_BUYINGSTORE_OVERFLOW_MONEY = 0x74e,
+/*20171018 to latest
+현재 맵에서는 파티 가입이 불가능합니다.
+Cannot join a party in this map.
+*/
+ MSG_PREVENT_PARTY_JOIN = 0x74f,
+/*20171018 to latest
+현재 맵에서는 파티 탈퇴가 불가능합니다.
+Cannot leave a party in this map.
+*/
+ MSG_PREVENT_PARTY_LEAVE = 0x750,
+/*20171018 to latest
+현재 맵에서는 파티 추방이 불가능합니다.
+Cannot withdraw/break the party in this map.
+*/
+ MSG_PREVENT_PARTY_EXPEL = 0x751,
+/*20171018 to latest
+실제 성명
+Real Name
+*/
+ MSG_SDO_REALNAME = 0x752,
+/*20171018 to latest
+신분증 번호
+ID Number
+*/
+ MSG_SDO_ID_NUMBER = 0x753,
+/*20171018 to latest
+이메일
+E-mail
+*/
+ MSG_SDO_EMAIL = 0x754,
+/*20171018 to latest
+입력이 올바르지 않습니다
+Invalid input
+*/
+ MSG_SDO_WRONG_VALUE = 0x755,
+/*20171018 to latest
+상대 캐릭터가 최대 보유제니량을 초과하여 거래가 불가능합니다.
+Failed to send the zeny
+*/
+ MSG_MCSTORE_FAIL_SELLER_MONEY_GIVE = 0x756,
+/*20171018 to latest
+해당 직업이 아닙니다.
+This is not a relevant job
+*/
+ MSG_INVALID_CLASS = 0x757,
+/*20171018 to latest
+해당 성별이 아닙니다.
+This is not a relevant gender
+*/
+ MSG_INVALID_GENDER = 0x758,
+/*20171018 to latest
+유저님의 정보가 인증에 성공했습니다.
+User information identification was successful.
+*/
+ MSG_SUCCESS_AUTHENTICATE = 0x759,
+/*20171018 to latest
+이름이 일치하지 않습니다. 재작성 해주세요.
+Name does not match. Please retry.
+*/
+ MSG_INVALID_REALNAME = 0x75a,
+/*20171018 to latest
+신분증 번호가 일치하지 않습니다. 재작성 해주세요.
+ID number does not match. Please retry.
+*/
+ MSG_INVALID_IDNUMBER = 0x75b,
+/*20171018 to latest
+현재 서비스에 이상이 있으니 잠시 후 재시도 해주세요.
+Service is currently unavailable. Please try again later.
+*/
+ MSG_INVALID_AUTHENTICATE = 0x75c,
+/*20171018 to latest
+ 탑승 상태에서는 공격을 할 수 없습니다.
+Unable to attack while riding.
+*/
+ MSG_CANNOT_ATTACK_IN_RIDING_STATE = 0x75d,
+/*20171018 to latest
+ 탑승 상태에서는 스킬 시전을 할 수 없습니다.
+Unable to cast the skill while riding.
+*/
+ MSG_CANNOT_USE_SKILL_IN_RIDING_STATE = 0x75e,
+/*20171018 to latest
+비밀번호는 4자리이하여야만 합니다.
+Pin number should be 4~6 characters.
+*/
+ MSG_STORE_PASSWORD_4_6 = 0x75f,
+/*20171018 to latest
+보안 인증에 성공했습니다.
+Secured authentication is successful.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_SUCCESS = 0x760,
+/*20171018 to latest
+보안 패스워드의 생성에 성공했습니다.
+Succeeded in creating 2nd password.
+*/
+ MSG_SECOND_PASSWORD_MAKE_SUCCESS = 0x761,
+/*20171018 to latest
+보안 패스워드를 삭제했습니다.
+2nd password has been deleted.
+*/
+ MSG_SECOND_PASSWORD_DEL_SUCCESS = 0x762,
+/*20171018 to latest
+보안 패스워드를 수정했습니다.
+2nd password has been corrected.
+*/
+ MSG_SECOND_PASSWORD_EDIT_SUCCESS = 0x763,
+/*20171018 to latest
+잘못된 패스워드입니다.(%d회남음)
+Password is incorrect.
+*/
+ MSG_SECOND_PASSWORD_LOGIN_FAILED = 0x764,
+/*20171018 to latest
+보안 패스워드의 생성에 실패했습니다.
+Failed to create 2nd password.
+*/
+ MSG_SECOND_PASSWORD_MAKE_FAILED = 0x765,
+/*20171018 to latest
+보안 패스워드 삭제에 실패했습니다.
+Failed to delete 2nd password.
+*/
+ MSG_SECOND_PASSWORD_DEL_FAILED = 0x766,
+/*20171018 to latest
+보안 패스워드의 수정에 실패했습니다.
+Failed to correct 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_FAILED = 0x767,
+/*20171018 to latest
+입력하신패스워드는 사용하실수없습니다.
+Unable to use restricted number in 2nd password.
+*/
+ MSG_SECOND_PASSWORD_EDIT_RESTRICT_PW = 0x768,
+/*20171018 to latest
+주민등록번호는 사용할수없습니다.
+Unable to use your KSSN number.
+*/
+ MSG_SECOND_PASSWORD_EDIT_PERSONALNUM_PW = 0x769,
+/*20171018 to latest
+이미 패스워드가 존재합니다.
+~There is already a password.
+*/
+ MSG_SECOND_PASSWORD_MAKE_DUPLICATED_PW = 0x76a,
+/*20171018 to latest
+보안 패스워드
+Security Code
+*/
+ MSG_SECOND_PASSWORD = 0x76b,
+/*20171018 to latest
+계정보안을 위하여 추가적인 패스워드 설정을 권장합니다.
+Account for the additional password security settings are recommended.
+*/
+ MSG_SECOND_PASSWORD_INPUT = 0x76c,
+/*20171018 to latest
+보안 패스워드 사용을 하지 않습니다.
+Do not use secure password.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_SUCCESS = 0x76d,
+/*20171018 to latest
+보안 패스워드 사용설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWDRD_NOT_AVAILABLE_FAILED = 0x76e,
+/*20171018 to latest
+보안 패스워드를 사용합니다. 다음로그인부터 적용됩니다.
+Use secure passwords. Will be applied to your next login.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_SUCCESS = 0x76f,
+/*20171018 to latest
+보안 패스워드 사용 설정에 실패했습니다.
+Use the set security password failed.
+*/
+ MSG_SECOND_PASSWDRD_AVAILABLE_FAILED = 0x770,
+/*20171018 to latest
+계정보안을 위하여 추가적인 패스워드를 설정합니다.
+Added to the security of your account password is set.
+*/
+ MSG_SECOND_PASSWORD_INFO_1 = 0x771,
+/*20171018 to latest
+아래의 숫자버튼을 마우스를 이용하여 4자리를 클릭하세요.
+Use the mouse to enter the 4-digit password below.
+*/
+ MSG_SECOND_PASSWORD_INFO_2 = 0x772,
+/*20171018 to latest
+3회이상 잘못된패스워드 입력으로, 종료됩니다.
+Typing an incorrect password 3 times will shut down the client.
+*/
+ MSG_SECOND_PASSWORD_INFO_3 = 0x773,
+/*20171018 to latest
+ITEM
+*/
+ MSG_MACRO_ITEM = 0x774,
+/*20171018 to latest
+SKILL
+*/
+ MSG_MACRO_SKILL = 0x775,
+/*20171018 to latest
+TACTIC
+*/
+ MSG_MACRO_TACTIC = 0x776,
+/*20171018 to latest
+ETC
+*/
+ MSG_MACRO_ETC = 0x777,
+/*20171018 to latest
+COMBAT
+*/
+ MSG_MACRO_COMBAT = 0x778,
+/*20171018 to latest
+NON-COMBAT
+*/
+ MSG_MACRO_NON_COMBAT = 0x779,
+/*20171018 to latest
+BUFF
+*/
+ MSG_MACRO_BUFF = 0x77a,
+/*20171018 to latest
+AUTO EQUIPED
+*/
+ MSG_MACRO_AUTO_EQUIPED = 0x77b,
+/*20171018 to latest
+1st. ATTACK
+*/
+ MSG_MACRO_1ST_ATTACK = 0x77c,
+/*20171018 to latest
+ATTACK
+*/
+ MSG_MACRO_ATTACK = 0x77d,
+/*20171018 to latest
+Next attack time :
+*/
+ MSG_MACRO_NEXT_ATK_TIME = 0x77e,
+/*20171018 to latest
+When died
+*/
+ MSG_MACRO_WHEN_DIED = 0x77f,
+/*20171018 to latest
+When invited to a party
+When invited to the party
+*/
+ MSG_MACRO_WHEN_INVITED_PARTY = 0x780,
+/*20171018 to latest
+Pickup Item
+*/
+ MSG_MACRO_PICKUP_ITEM = 0x781,
+/*20171018 to latest
+Over 85% Weight
+*/
+ MSG_MACRO_OVERWEIGHT = 0x782,
+/*20171018 to latest
+진행중이던 작업(NPC대화,제조...)을 종료후에 다시 시도하세요.
+Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+*/
+ MSG_BUSY = 0x783,
+/*20171018 to latest
+ 몬스터 사냥을 통해 얻을 수 있는 Job경험치가 %d분간 %.2f배로 증가합니다.
+Monster Job hunting experience that you can get through the doubling of %d is %.2f minutes.
+*/
+ MSG_PLUSONLYJOBEXP2 = 0x784,
+/*20171018 to latest
+SaveData_ExMacro%d
+*/
+ MSG_MACRO_SAVE = 0x785,
+/*20171018 to latest
+ 설정한 내용이 [%s]에 저장됩니다.
+Settings for [%s] are stored in.
+*/
+ MSG_MACRO_SAVE_DATA2 = 0x786,
+/*20171018 to latest
+보안레벨
+Security level
+*/
+ MSG_SECOND_PASSWORD_LEVEL = 0x787,
+/*20171018 to latest
+현재 캐릭터는 파티 또는 길드에 가입되어 있어서 삭제가 불가능합니다.
+The current character is a party or join the guild can not be deleted.
+*/
+ MSG_RESULT_FAIL_CHAR_DELETE = 0x788,
+/*20171018 to latest
+벽이나 물체 근처에서만 사용 할 수 있습니다.
+Objects can be used only near the wall.
+*/
+ MSG_USESKILL_FAIL_NEER_WALL = 0x789,
+/*20171018 to latest
+%s : 레벨 %d %s 파티구합니다.
+%s: Level %d %s party to obtain level.
+*/
+ MSG_SEEK_PARTY_SET = 0x78a,
+/*20171018 to latest
+탑승 중인 상태에서는 고삐 아이템을 사용할 수 없습니다.
+While boarding reins is not available for items.
+*/
+ MSG_FAIELD_RIDING_OVERLAPPED = 0x78b,
+/*20171018 to latest
+이 스킬은 1%의 경험치가 필요합니다.
+This skill requires 1% experience.
+*/
+ MSG_USESKILL_FAIL_NEED_EXP_1PERCENT = 0x78c,
+/*20171018 to latest
+경 험 치 :
+Experience value:
+*/
+ MSG_EXP_MSG = 0x78d,
+/*20171018 to latest
+드 롭 율 :
+Drop rate:
+*/
+ MSG_DROP_MSG = 0x78e,
+/*20171018 to latest
+사망페널티 :
+Death Penalty:
+*/
+ MSG_DEATH_MSG = 0x78f,
+/*20171018 to latest
+%d%% (PC방 %d%% + TPLUS %d%% + 프리미엄 %d%% + %s서버 %d%%)
+%d%% (PCroom %d%% + TPLUS %d%% + Premium %d%% + %s Server %d%%)
+*/
+ MSG_BASIC_EXP_MSG = 0x790,
+/*20171018 to latest
+ 합창스킬을 시전할 파티원의 SP량이 부족합니다.
+Amount of party members to cast the skill Chorus SP is low.
+*/
+ MSG_USESKILL_FAIL_CHORUS_SP_INSUFFICIENT = 0x791,
+/*20171018 to latest
+상대 캐릭터의 소지 아이템 종류의 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the items can not trade because amount is exceeded.
+*/
+ MSG_CHARACTER_IS_OVER_COUNT = 0x792,
+/*20171018 to latest
+상대 캐릭터의 해당 아이템의 소지 한계량 초과로 거래가 불가능합니다.
+Relative character that has possession of the item amount which exceeds makes it impossible to trade.
+*/
+ MSG_CHARACTER_IS_EACHITEM_OVER_COUNT = 0x793,
+/*20171018 to latest
+해당 아이템의 소지 한계량 초과로 구입이 불가능합니다.
+Amounts are exceeded the possession of the item is not available for purchase.
+*/
+ MSG_PURCHASE_FAIL_EACHITEM_COUNT = 0x794,
+/*20171018 to latest
+광고 등록 대기중입니다.
+Advertising is pending registration.
+*/
+ MSG_PARTY_FAILED_TIMEOUT = 0x795,
+/*20171018 to latest
+아래의 파일과 텍스트내용을 함께
+라그나로크 공식홈페이지 -> 고객센터 -> 문의하기를
+이용하여 보내주시기 바랍니다.
+With the following files and text content Ragnarok Official Website -> Support -> Contact Us to submit your comments by:
+*/
+ MSG_UNEXCEPTION_MSG1ST = 0x796,
+/*20171018 to latest
+빌링시스템에 오류가 발생햇습니다(%d)
+Has caused an error in billing system(%d)
+*/
+ MSG_INGAMBA_BILLING_ZSVR_ERROR = 0x797,
+/*20171018 to latest
+룬 아이템 소유 개수가 초과 되어 구매가 실패 하였습니다.
+Failed purchase of runes, items exceed the maximum number that can be held.
+*/
+ MSG_CASH_FAILED_RUNE_OVERCOUNT = 0x798,
+/*20171018 to latest
+개별 아이템 개수가 초과 되어 구매가 실패 하였습니다.
+Exceeded the number of individual items, purchase failed.
+*/
+ MSG_CASH_FAILED_EACHITEM_OVERCOUNT = 0x799,
+/*20171018 to latest
+알 수 없는 오류가 발생하여 구매가 실패 하였습니다.
+Purchase failed due to an unknown error.
+*/
+ MSG_CASH_FAILED_UNKOWN = 0x79a,
+/*20171018 to latest
+잠시 후 다시 시도해 주십시오.
+Please try again later.
+*/
+ MSG_CASH_FAILED_BUSY = 0x79b,
+/*20171018 to latest
+ 쿠나이 아이템을 장착 한 상태에서만 사용 가능합니다.
+Kunai must be equipped to use this skill.
+*/
+ MSG_USESKILL_FAIL_NEED_EQUIPMENT_KUNAI = 0x79c,
+/*20171018 to latest
+모집할 최소레벨값을 입력해주세요.
+Please enter the value of the minimum level to be recruited.
+*/
+ MSG_SEEK_PARTY_LEVEL_HELP = 0x79d,
+/*20171018 to latest
+존다기획사NPC 에게 아이템이 수령이 불가능합니다. 소지창의 여유공간을 확보해주세요.
+Jonda agency receipt of the item to the NPC is not possible. Gaining possession of the free space of the window.
+*/
+ MSG_FAILED_GET_ITEM_FROM_ZONEDA = 0x79e,
+/*20171018 to latest
+이 스킬은 공성전에서만 사용 가능합니다.
+This skill is only available in the siege.
+*/
+ MSG_USESKILL_FAIL_SIZE = 0x79f,
+/*20171018 to latest
+이 스킬은 플레이어에게만 사용 가능합니다.
+This skill is available only to the player.
+*/
+ MSG_USESKILL_FAIL_TOTARGET_PLAYER = 0x7a0,
+/*20171018 to latest
+착용이 금지 된 상태로 착용 할 수 없습니다.
+Forbidden to wear the state can not be worn.
+*/
+ MSG_CAN_NOT_EQUIP_ITEM_FORBID = 0x7a1,
+/*20171018 to latest
+현재 위치에서는 상점 및 채팅방의 생성이 불가능합니다.
+Current location of the shop and chat room creation is disabled.
+*/
+ MSG_USESKILL_FAIL_THERE_ARE_NPC_AROUND = 0x7a2,
+/*20171018 to latest
+Elapsed time: %d:%d:%d / %d:%d:%d
+*/
+ MSG_REPLAY_ELAPSEDTIME = 0x7a3,
+/*20171018 to latest
+Speed : X 1/4
+*/
+ MSG_REPLAY_SPEED1_4 = 0x7a4,
+/*20171018 to latest
+Speed : X 1/2
+*/
+ MSG_REPLAY_SPEED1_2 = 0x7a5,
+/*20171018 to latest
+Speed : X 1
+*/
+ MSG_REPLAY_SPEED1 = 0x7a6,
+/*20171018 to latest
+Speed : X 2
+*/
+ MSG_REPLAY_SPEED2 = 0x7a7,
+/*20171018 to latest
+Speed : X 4
+*/
+ MSG_REPLAY_SPEED4 = 0x7a8,
+/*20171018 to latest
+Speed : X 8
+*/
+ MSG_REPLAY_SPEED8 = 0x7a9,
+/*20171018 to latest
+Speed : X 16
+*/
+ MSG_REPLAY_SPEED16 = 0x7aa,
+/*20171018 to latest
+Speed : 알수없음
+Speed: Unknown
+*/
+ MSG_REPLAY_SPEEDUNKNOWN = 0x7ab,
+/*20171018 to latest
+Service Info : %s
+*/
+ MSG_REPLAY_CHRVICEINFO = 0x7ac,
+/*20171018 to latest
+Character Name : %s
+*/
+ MSG_REPLAY_CHARACTERNAME = 0x7ad,
+/*20171018 to latest
+Map Name : %s
+*/
+ MSG_REPLAY_MAPNAME = 0x7ae,
+/*20171018 to latest
+Record Time: %d-%01d-%01d %d: %02d: %02d
+*/
+ MSG_REPLAY_RECORDTIME = 0x7af,
+/*20171018 to latest
+Play Time: %02d: %02d: %02d
+*/
+ MSG_REPLAY_PLAYTIME = 0x7b0,
+/*20171018 to latest
+No Replay File.
+*/
+ MSG_REPLAY_NOREPLAYFILE = 0x7b1,
+/*20171018 to latest
+Server No Matching
+*/
+ MSG_REPLAY_SERVERNOMATCH = 0x7b2,
+/*20171018 to latest
+Replay Option Setting
+*/
+ MSG_REPLAY_REPLAYOPTIONSETTING = 0x7b3,
+/*20171018 to latest
+파일 이름을 입력하세요.
+Enter File Name
+*/
+ MSG_REPLAY_ENTERTHEFILENAME = 0x7b4,
+/*20171018 to latest
+Set Replay Save Data
+*/
+ MSG_REPLAY_SETREPLAYSAVEDATA = 0x7b5,
+/*20171018 to latest
+Set Rec Option
+*/
+ MSG_REPLAY_SETRECOPTION = 0x7b6,
+/*20171018 to latest
+%.1f %% Pos☞:%d:%d:%d
+%.1f % Pos->:%d:%d:%d
+*/
+ MSG_REPLAY_GAGEPOS1 = 0x7b7,
+/*20171018 to latest
+%.1f %% Pos☞:이동불가
+%.1f % Pos->:cannot move
+*/
+ MSG_REPLAY_GAGEPOS2 = 0x7b8,
+/*20171018 to latest
+Start
+*/
+ MSG_REPLAY_START = 0x7b9,
+/*20171018 to latest
+Stop
+*/
+ MSG_REPLAY_STOP = 0x7ba,
+/*20171018 to latest
+Input FileName -> Start
+*/
+ MSG_REPLAY_START2 = 0x7bb,
+/*20171018 to latest
+Open Option
+Open Options
+*/
+ MSG_REPLAY_OPENOPTION = 0x7bc,
+/*20171018 to latest
+Close Option
+Close Options
+*/
+ MSG_REPLAY_CLOSEOPION = 0x7bd,
+/*20171018 to latest
+End
+*/
+ MSG_REPLAY_END = 0x7be,
+/*20171018 to latest
+Time
+*/
+ MSG_REPLAY_TIME = 0x7bf,
+/*20171018 to latest
+파티&친구
+Party & Friends
+*/
+ MSG_REPLAY_PARTYFRIEND = 0x7c0,
+/*20171018 to latest
+채팅
+Chat
+*/
+ MSG_REPLAY_CHAT = 0x7c1,
+/*20171018 to latest
+단축키
+Shortcuts
+*/
+ MSG_REPLAY_SHORTCUTS = 0x7c2,
+/*20171018 to latest
+자동 파일명 생성
+Automatic filename generation
+*/
+ MSG_REPLAY_AUTOMATICFILENAME = 0x7c3,
+/*20171018 to latest
+파일 중복 채크
+Checking for duplicate files
+*/
+ MSG_REPLAY_CHECKINGFILE = 0x7c4,
+/*20171018 to latest
+동일한 파일이 존재 합니다.
+The same file exists already.
+*/
+ MSG_REPLAY_THESAMEFILEEXISTS = 0x7c5,
+/*20171018 to latest
+Record Start
+*/
+ MSG_REPLAY_RECORDSTART = 0x7c6,
+/*20171018 to latest
+ is Saved.
+Recording saved
+*/
+ MSG_REPLAY_RECORDEND = 0x7c7,
+/*20171018 to latest
+Weight : %3d / %3d
+*/
+ MSG_WEIGHT = 0x7c8,
+/*20171018 to latest
+Total : %s C
+Total: %s EUR
+*/
+ MSG_TOTAL = 0x7c9,
+/*20171018 to latest
+[수리검]을 장착한 상태여야 합니다.
+[Shuriken] must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_SYURIKEN = 0x7ca,
+/*20171018 to latest
+Base Lv. %d
+*/
+ MSG__BASIC_MSG_BASE = 0x7cb,
+/*20171018 to latest
+Job Lv. %d
+*/
+ MSG__BASIC_MSG_JOB = 0x7cc,
+/*20171018 to latest
+Zeny : %s
+*/
+ MSG_BASIC_MSG_ZENY = 0x7cd,
+/*20171018 to latest
+Trilinear
+*/
+ MSG_GRAPHIC_MSG_TRILINEAR = 0x7ce,
+/*20171018 to latest
+attack
+*/
+ MSG_GRAPHIC_MSG_ATTACK = 0x7cf,
+/*20171018 to latest
+skill
+*/
+ MSG_GRAPHIC_MSG_SKILL = 0x7d0,
+/*20171018 to latest
+item
+*/
+ MSG_GRAPHIC_MSG_ITEM = 0x7d1,
+/*20171018 to latest
+NoCtrl
+Ctrl
+*/
+ MSG_GRAPHIC_MSG_NOCTRL = 0x7d2,
+/*20171018 to latest
+전장
+More
+*/
+ MSG_GRAPHIC_MSG_BATTLE = 0x7d3,
+/*20171018 to latest
+(Character/Total Slot)
+(Characters/Total slots)
+*/
+ MSG_CHARACTER_MSG_CHARACTERTOTALSLOT = 0x7d4,
+/*20171018 to latest
+Premium Service
+VIP Service
+*/
+ MSG_CHARACTER_MSG_PREMIUMSERVICE = 0x7d5,
+/*20171018 to latest
+Premium
+VIP
+*/
+ MSG_CHARACTER_MSG_PREMIUM = 0x7d6,
+/*20171018 to latest
+Service
+*/
+ MSG_CHARACTER_MSG_SERVICE = 0x7d7,
+/*20171018 to latest
+Billing Service
+VIP
+*/
+ MSG_CHARACTER_MSG_BILLINGSERVICE = 0x7d8,
+/*20171018 to latest
+Billing
+VIP
+*/
+ MSG_CHARACTER_MSG_BILLING = 0x7d9,
+/*20171018 to latest
+Command List
+*/
+ MSG_MSG_COMMANDLIST = 0x7da,
+/*20171018 to latest
+LEVEL
+*/
+ MSG_SEEK_PARTY_LEVEL = 0x7db,
+/*20171018 to latest
+MAP
+*/
+ MSG_SEEK_PARTY_MAP = 0x7dc,
+/*20171018 to latest
+JOB
+*/
+ MSG_SEEK_PARTY_JOB = 0x7dd,
+/*20171018 to latest
+Not Available
+*/
+ MSG_MSG_NOTAVAILABLE = 0x7de,
+/*20171018 to latest
+[수호 천사의 보호] 만렙일 경우 사용할 수 없습니다.
+[Protection of Guardian Angel] You can't use it when you reach the highest level.
+*/
+ MSG_MSG_SUPERNOVICE_CHOPOKGI_CAPPEDLEVEL = 0x7df,
+/*20171018 to latest
+정말 이동하시겠습니까?
+Do you really want to move?
+*/
+ MSG_CHANGE_CHARACTER_SLOT = 0x7e0,
+/*20171018 to latest
+캐릭터 슬롯 이동에 실패했습니다.
+Failed to move Char slot.
+*/
+ MSG_CHANGE_CHARACTER_SLOT_FAILED = 0x7e1,
+/*20171018 to latest
+캐릭터 이름이 잘못 되었습니다.
+Character name is invalid.
+*/
+ MSG_CHARACTERNAME_ERROR = 0x7e2,
+/*20171018 to latest
+퀘스트보기창
+Show Quest
+*/
+ MSG_QUEST_DISPLAY_ONOFF = 0x7e3,
+/*20171018 to latest
+ 청소년 보호법에 따라, 잠시 후 0시 부터 6시 까지 만 16세 미만 고객님들의 게임 이용이 제한됩니다.
+Depending on the protection of youth, and 0:00 to 6:00 while under the age of 16 of your game use is limited.
+*/
+ MSG_SHUTDOWN_ALERT_MSG = 0x7e4,
+/*20171018 to latest
+청소년 보호법에 따라, 0시 부터 6시 까지 ^ff0000만 16세 미만 고객님들의 게임 이용이 제한^000000되며, 게임을 종료합니다.
+Depending on the protection of youth, 0:00 to 6:00 ^ff0000 under the age of 16 ^000000 limit your use of the game and the game ends.
+*/
+ MSG_BAN_SHUTDOWN_TEENAGER = 0x7e5,
+/*20171018 to latest
+캐릭터 이름을 변경하기 위해서는 길드에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the guild.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_GUILD = 0x7e6,
+/*20171018 to latest
+캐릭터 이름을 변경하기 위해서는 파티에서 탈퇴 해야 합니다.
+In order to change the character name, you must leave the party.
+*/
+ MSG_FAILED_RENAME_BELONGS_TO_PARTY = 0x7e7,
+/*20171018 to latest
+알 수 없는 오류로 캐릭터 이름 변경이 실패 하였습니다.
+Character name change failed, due an unknown error.
+*/
+ MSG_FAILED_RENAME_UNKOWN = 0x7e8,
+/*20171018 to latest
+이미 캐릭터 슬롯변경이 가능한 상태입니다.(%d)
+Ready to change character slot in.(%d)
+*/
+ MSG_CHARSLOT_CHANGE_DUPLICATE = 0x7e9,
+/*20171018 to latest
+이미 캐릭터 이름변경이 가능한 상태입니다.(%d)
+Ready to change character name in.(%d)
+*/
+ MSG_CHARNAME_CHANGE_DUPLICATE = 0x7ea,
+/*20171018 to latest
+변경하려는 이름의 길이가 최대크기를 초과하여 캐릭터 이름 변경이 실패 하였습니다.
+Length exceeds the maximum size of the character name you want to change.
+*/
+ MSG_FAILED_RENAME_OVER_LENGTH = 0x7eb,
+/*20171018 to latest
+사용할 수 없는 단어가 포함되어 캐릭터 이름 변경이 실패 하였습니다.
+Name contains invalid characters. Character name change failed.
+*/
+ MSG_FAILED_RENAME_PREVENTNAM = 0x7ec,
+/*20171018 to latest
+이름 변경이 금지된 상태이므로 캐릭터 이름 변경이 실패 하였습니다.
+The name change is prohibited. Character name change failed.
+*/
+ MSG_FAILED_RENAME_FORBIDDEN = 0x7ed,
+/*20171018 to latest
+완료
+Complete
+*/
+ MSG_COMPLETE_HUNTING_QUEST = 0x7ee,
+/*20171018 to latest
+ %d분간 얻을 수 있는 경험치가 %d%% 증가합니다.
+During %d minutes your Exp will increase by %d%%.
+*/
+ MSG_PLUSEXP_VALUE = 0x7ef,
+/*20171018 to latest
+소환까지 %02d초남았습니다.
+%02d seconds left until summon.
+*/
+ MSG_PARTY_RECALL_TIME = 0x7f0,
+/*20171018 to latest
+파티장이 당신을 %s (%s) 로 소환합니다.소환시 %d zeny가 소모됩니다.
+Your party leader summons you to %s (%s). Warp costs %d Zeny.
+*/
+ MSG_PARTY_RECALL_INFO = 0x7f1,
+/*20171018 to latest
+소환대상
+Summon target
+*/
+ MSG_RECALL_TARGET = 0x7f2,
+/*20171018 to latest
+차단목록
+Block List
+*/
+ MSG_PARTY_BLACKLIST = 0x7f3,
+/*20171018 to latest
+파티 광고를 등록하기 위해 %d제니가 소모됩니다.
+%d Zeny will be spent for making party ad.
+*/
+ MSG_PARTY_CF_PAY = 0x7f4,
+/*20171018 to latest
+파티 광고를 하기 위한 제니가 부족합니다.
+Insufficient Zeny for making party ad.
+*/
+ MSG_PARTY_CF_PAY_SHORTAGE_COST = 0x7f5,
+/*20171018 to latest
+)님 파티 가입승인
+) party: accept invitation
+*/
+ MSG_PARTY_ADD_OK = 0x7f6,
+/*20171018 to latest
+)님 파티 가입거부
+) party: decline invitation
+*/
+ MSG_PARTY_ADD_REFUSES = 0x7f7,
+/*20171018 to latest
+)님 장비창보기
+) party: show equipment window
+*/
+ MSG_PARTY_ITEM_VIEW = 0x7f8,
+/*20171018 to latest
+한글18글자,영문36글자 입력가능
+Up to 36 english letters can be entered
+*/
+ MSG_SEEK_PARTY_MEMO_HELP = 0x7f9,
+/*20171018 to latest
+지원하기
+Enter
+*/
+ MSG_PARTY_REQUEST = 0x7fa,
+/*20171018 to latest
+1:1대화하기
+1:1 Chat
+*/
+ MSG_DIRECT_CHAT = 0x7fb,
+/*20171018 to latest
+차단하기
+Block
+*/
+ MSG_ADD_BLACKLIST = 0x7fc,
+/*20171018 to latest
+파티장에게 소환되기 위한 제니가 부족합니다.
+Insufficient Zeny for recall.
+*/
+ MSG_PARTY_RECRUIT_NOT_RECALL_PAY = 0x7fd,
+/*20171018 to latest
+메모란에 파티광고를 써주세요.
+Input your party ad.
+*/
+ MSG_PARTY_RECRUIT_MEMO_ERROR = 0x7fe,
+/*20171018 to latest
+파티장만이 파티광고를 등록할수있습니다.
+Only party leader can register party ad.
+*/
+ MSG_PARTY_RECRUIT_ERROR = 0x7ff,
+/*20171018 to latest
+이미 지원한 파티광고입니다.
+You have already accepted this ad.
+*/
+ MSG_PARTY_REFUSE_ERROR = 0x800,
+/*20171018 to latest
+내용
+For
+*/
+ MSG_PARTY_RECRUIT_INFO = 0x801,
+/*20171018 to latest
+장비
+E
+*/
+ MSG_INVENTORY_TABNAME_1 = 0x802,
+/*20171018 to latest
+개인
+F
+*/
+ MSG_INVENTORY_TABNAME_3 = 0x803,
+/*20171018 to latest
+ 아이템 버리기 잠금
+ Drop Lock: On/Off
+*/
+ MSG_ITEM_DROP_LOCK = 0x804,
+/*20171018 to latest
+파티원 찾기 알람
+Party Alarm
+*/
+ MSG_PARTY_RECRUIT_ALRAM = 0x805,
+/*20171018 to latest
+파티결성
+Create Party
+*/
+ MSG_CREATE_PARTY = 0x806,
+/*20171018 to latest
+파티탈퇴
+Leave Party
+*/
+ MSG_WITHDRAW_PARTY = 0x807,
+/*20171018 to latest
+파티초대
+Party Invitation
+*/
+ MSG_INVITE_PARTY = 0x808,
+/*20171018 to latest
+파티 이름 등록
+Party Name:
+*/
+ MSG_PUT_PARTY_NAME_IN = 0x809,
+/*20171018 to latest
+초대할 캐릭터 이름
+Player Name:
+*/
+ MSG_PUT_PLAYER_NAME_IN = 0x80a,
+/*20171018 to latest
+님께 파티가입 요청을 보냈습니다.
+ has recieved an invitation to join your party.
+*/
+ MSG_CHARACTER_PARTY_INVITATION_TO_JOIN = 0x80b,
+/*20171018 to latest
+님께서 파티가입을 거절했습니다.
+ rejected your party invitation.
+*/
+ MSG_CHARACTER_REJECT_PARTY_INVITATION = 0x80c,
+/*20171018 to latest
+님께서 파티가입을 수락했습니다.
+ accepted your party invitation.
+*/
+ MSG_CHARACTER_ACCEPT_PARTY_INVITATION = 0x80d,
+/*20171018 to latest
+이미 파티모집중입니다.
+Recruitment is already a party.
+*/
+ MSG_PARTY_RECRUIT_ERROR1 = 0x80e,
+/*20171018 to latest
+이전 검색과 같은 조건입니다.
+Same conditions such as the previous search.
+*/
+ MSG_PARTY_RECRUIT_ERROR2 = 0x80f,
+/*20171018 to latest
+길드 탈퇴 후 사용 가능합니다.
+Guild after withdrwal.
+*/
+ MSG_CHARNAME_CHANGE_FILED_GUILDMEMBER = 0x810,
+/*20171018 to latest
+파티 탈퇴 후 사용 가능합니다.
+Party after secession.
+*/
+ MSG_CHARNAME_CHANGE_FILED_PARTYMEMBER = 0x811,
+/*20171018 to latest
+소환 유저가 소환이 안되는 맵에 있습니다.
+The player can not be summoned to this map.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR1 = 0x812,
+/*20171018 to latest
+현재 파티장이 있는 맵에서는 소환이 안됩니다.
+Party Leader is on a map that is restricted to summon players.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR2 = 0x813,
+/*20171018 to latest
+소환거부되었습니다.
+Summon has been denied.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR3 = 0x814,
+/*20171018 to latest
+소환을 할 수 없습니다.
+Can not be summoned.
+*/
+ MSG_PARTY_RECRUIT_RECALL_ERR4 = 0x815,
+/*20171018 to latest
+파티초대는 파티장만 가능합니다.
+Only the leader can invite.
+*/
+ MSG_YOU_ARE_NOT_PARTYMASTER = 0x816,
+/*20171018 to latest
+검색할 아이템명 입력 :
+Search item:
+*/
+ MSG_NC_ITEM_SEARCH = 0x817,
+/*20171018 to latest
+캐릭터명을 입력하셔야 합니다.
+You must enter a character name.
+*/
+ MSG_PLEASE_PUT_CHARACTER_NAME_IN = 0x818,
+/*20171018 to latest
+파티이름을 입력하셔야 합니다.
+You must enter the name of the party.
+*/
+ MSG_PLEASE_PUT_PARTY_NAME_IN = 0x819,
+/*20171018 to latest
+길드 도우미
+Guild Creation Window
+*/
+ MSG_GUILD_HELPER = 0x81a,
+/*20171018 to latest
+가입되어 있는 길드가 없습니다.
+Join a guild or start your own!
+*/
+ MSG_NO_GUILD_CURRENTLY_PARTICIPATED_IN = 0x81b,
+/*20171018 to latest
+길드 결성
+Create Guild
+*/
+ MSG_CREATE_GUILD = 0x81c,
+/*20171018 to latest
+생성할 길드 이름
+Guild Name
+*/
+ MIS_PUT_GUILD_NAME_IN = 0x81d,
+/*20171018 to latest
+길드 결성 도움말
+Guild System
+*/
+ MIS_GUILD_TIP = 0x81e,
+/*20171018 to latest
+길드 시스템이란
+What is the guild system
+*/
+ MIS_GUILD_SYSTEM = 0x81f,
+/*20171018 to latest
+길드이름을 입력하셔야 합니다.
+You must enter the name of your guild.
+*/
+ MSG_PLEASE_PUT_GUILD_NAME_IN = 0x820,
+/*20171018 to latest
+지원한 파티에서 거부당했습니다.
+Supported at the party was rejected.
+*/
+ MSG_PARTY_RECRUIT_REFUSE_VOLUNTEER = 0x821,
+/*20171018 to latest
+서비스 선택.
+Select Service:
+*/
+ MSG_SERVICESELECT = 0x822,
+/*20171018 to latest
+탈출 가능한 지역.
+Possible escape area.
+*/
+ MSG_SHOW_MAPNAMETITLE = 0x823,
+/*20171018 to latest
+Replay File List
+*/
+ MSG_REPLAY_STR_REPLAYFILELIST = 0x824,
+/*20171018 to latest
+File info
+*/
+ MSG_REPLAY_STR_FILEINFO = 0x825,
+/*20171018 to latest
+File List
+*/
+ MSG_REPLAY_STR_FILELIST = 0x826,
+/*20171018 to latest
+%s 아이템은 거래가 불가능 합니다.
+%s Item deal not possible.
+*/
+ MSG_NOT_MOVEABLE_TRADE = 0x827,
+/*20171018 to latest
+길드해체
+Disband the Guild
+*/
+ MSG_GUILD_DISBAND = 0x828,
+/*20171018 to latest
+해체할 길드 이름
+Enter Guild Name
+*/
+ MSG_PUT_DISBAND_GUILDNAME = 0x829,
+/*20171018 to latest
+접속하지 않았거나 존재하지 않는 캐릭터입니다.
+The character is not online or does not exist.
+*/
+ MSG_JOINGUILD_NOTEXIST_USER = 0x82a,
+/*20171018 to latest
+팔콘 호출에 실패하였습니다.
+Failed to call Falcon.
+*/
+ MSG_FAILED_SET_EFFECT_BIRD = 0x82b,
+/*20171018 to latest
+%d%% ( 기본 100%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%%(default 100%%+ Premium%d%%+%s Server%d%%)
+*/
+ MSG_BASIC_EXP_MSG_BRZ = 0x82c,
+/*20171018 to latest
+해당 유저는 현재 공성전에 참가하고 있습니다.
+This user is currently participating in the siege.
+*/
+ MSG_JOINGUILD_TARGET_USER_IN_SIEGEMAP = 0x82d,
+/*20171018 to latest
+동일한 맵에서만 파티장 변경이 가능합니다.
+It is only possible to change the party leader while on the same map.
+*/
+ MSG_PARTY_MASTER_CHANGE_SAME_MAP = 0x82e,
+/*20171018 to latest
+현재 지역에서는 파티장 변경이 불가능합니다.
+In the current region it is not possible to change the party.
+*/
+ MSG_CANNOT_PARTY_MASTER_CHANGE_IN_MAP = 0x82f,
+/*20171018 to latest
+그리폰 내리기
+Gryphon making
+*/
+ MSG_ROYAL_CHIKENOFF = 0x830,
+/*20171018 to latest
+%d월 %d일 %d시 %d분 %d초
+Delete: %d/%d - %d:%d:%d
+*/
+ MSG_TIME_TYPE3 = 0x831,
+/*20171018 to latest
+현재 공성전에 참여 중이므로 길드초대를 하실 수 없습니다.
+You can't invite characters in WoE maps.
+*/
+ MSG_JOINGUILD_REQ_USER_IN_SIEGEMAP = 0x832,
+/*20171018 to latest
+전장에 입장 대기를 신청하셨습니다.
+You are now in the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_REQUEST_JOINWAIT = 0x833,
+/*20171018 to latest
+인원이 가득 찼습니다.
+Queuing has finished.
+*/
+ MSG_BATTLEFIELD_MSG_FULL = 0x834,
+/*20171018 to latest
+확인되지 않은 전장명입니다.
+Invalid name of the battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_NAME = 0x835,
+/*20171018 to latest
+확인되지 않은 신청타입입니다.
+Invalid type of application.
+*/
+ MSG_BATTLEFIELD_MSG_UNKNOWN_TYPE = 0x836,
+/*20171018 to latest
+최대 인원을 초과하였습니다.
+People count exceeded.
+*/
+ MSG_BATTLEFIELD_MSG_MAXOVER = 0x837,
+/*20171018 to latest
+입장 레벨이 맞지 않습니다.
+Your level doesn't fit this battlefield rules.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_NOTLEVEL = 0x838,
+/*20171018 to latest
+중복 신청하셨습니다.
+Duplicate application.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_OVERLAP = 0x839,
+/*20171018 to latest
+재접속후 다시 신청하여 주시기 바랍니다.
+After reconnecting, please re-apply.
+*/
+ MSG_BATTLEFIELD_MSG_RESTART = 0x83a,
+/*20171018 to latest
+직업이 맞지 않습니다.
+Your class can't participate in this battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_NOTJOB = 0x83b,
+/*20171018 to latest
+파티장이나 길드장만이 신청할 수 있습니다.
+Only party leader / guild master can apply.
+*/
+ MSG_BATTLEFIELD_MSG_JOIN_ONLYBOSS = 0x83c,
+/*20171018 to latest
+전장을 이용 중인 팀원이 있어 신청이 불가능 합니다.
+You can't apply while your team member is already on a battlefield.
+*/
+ MSG_BATTLEFIELD_MSG_BUSY_PARTYMEMBER = 0x83d,
+/*20171018 to latest
+전장 입장 대기가 취소되었습니다.
+You have left the battlefield queue.
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOINWAIT = 0x83e,
+/*20171018 to latest
+잘못된 전장명 입니다.
+Wrong battlefield name.
+*/
+ MSG_BATTLEFIELD_MSG_WRONG_NAME = 0x83f,
+/*20171018 to latest
+전장 입장 대기 순위에 없습니다.
+You are not in the battlefield queue list
+*/
+ MSG_BATTLEFIELD_MSG_NOTRANK = 0x840,
+/*20171018 to latest
+선택하신 전장은 현재 이용하실 수 없으므로 대기가 취소됩니다.
+The selected arena is unavailable; your application has been cancelled
+*/
+ MSG_BATTLEFIELD_MSG_FAIL_CHOICE = 0x841,
+/*20171018 to latest
+전장 입장을 취소하였습니다.
+You have left the queue
+*/
+ MSG_BATTLEFIELD_MSG_CANCEL_JOIN = 0x842,
+/*20171018 to latest
+전장에 입장하시겠습니까?
+Are you sure you want to join a battleground?
+*/
+ MSG_BATTLEFIELD_MSG_DOYOU_JOIN = 0x843,
+/*20171018 to latest
+전장 입장 신청 시스템
+[Battlefield application rules]
+*/
+ MSG_BATTLEFIELD_HELP1 = 0x844,
+/*20171018 to latest
+입장 신청 및 전장으로의 공간이동 불가 상황
+Application and position into the battlefield cannot be applied under this circumtances
+*/
+ MSG_BATTLEFIELD_HELP2 = 0x845,
+/*20171018 to latest
+1. 여러 종류의 전장을 동시에 신청할 수 없습니다.
+1. Different types of battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP3 = 0x846,
+/*20171018 to latest
+2. 개인 / 파티 / 길드 전장을 동시에 신청할 수 없습니다.
+2. Personal / party / guild battle can not be applied simultaneously.
+*/
+ MSG_BATTLEFIELD_HELP4 = 0x847,
+/*20171018 to latest
+3. 파티 전장 신청은 파티장만 신청할 수 있으며,
+3. Parties can only be applied by their party leaders.
+*/
+ MSG_BATTLEFIELD_HELP5 = 0x848,
+/*20171018 to latest
+오프라인중이거나 오프라인 된 파티원은 대기열에서 누락됩니다.
+Offline party members won't proceed to the queue.
+*/
+ MSG_BATTLEFIELD_HELP6 = 0x849,
+/*20171018 to latest
+4. 전장 신청은 전장 맵을 제외한 모든 곳에서 신청 가능하나,
+4. You can add request to enter the arena from any map except for those who don't allow teleport/warp.
+*/
+ MSG_BATTLEFIELD_HELP7 = 0x84a,
+/*20171018 to latest
+입장한 위치가 마을, 필드, 일반 던전이 아닐 경우 복귀 시 캐릭터 저장 좌표로 이동 됩니다.
+When the battle is finished your character will be returned to the current spot or (if it's not possible) to the save point.
+*/
+ MSG_BATTLEFIELD_HELP8 = 0x84b,
+/*20171018 to latest
+5. 전장의 보상 및 기타 서비스는 각 마을에 위치한 전장 모병관을 통해 전장 대기실에서 이용해 주십시오.
+5. You can view and choose rewards in the arena waiting room.
+*/
+ MSG_BATTLEFIELD_HELP9 = 0x84c,
+/*20171018 to latest
+전장 입장 신청 도움말
+Request help battle position
+*/
+ MSG_BATTLEFIELD_HELP10 = 0x84d,
+/*20171018 to latest
+%s 전장이 시작됩니다.
+%s battle begins.
+*/
+ MSG_BATTLEFIELD_START = 0x84e,
+/*20171018 to latest
+전장으로 이동하시겠습니까?
+Do you want to enter the arena?
+*/
+ MSG_BATTLEFIELD_DOYOU_MOVE = 0x84f,
+/*20171018 to latest
+[주의]
+[Note]
+*/
+ MSG_BATTLEFIELD_WARNINGMSG1 = 0x850,
+/*20171018 to latest
+현재 위치가 마을, 필드 혹은 일반던전이
+When the battle is finished your character will
+*/
+ MSG_BATTLEFIELD_WARNINGMSG2 = 0x851,
+/*20171018 to latest
+아닐 경우 전장 종료 후 저장된 위치로
+be returned to the current spot or (if it's not
+*/
+ MSG_BATTLEFIELD_WARNINGMSG3 = 0x852,
+/*20171018 to latest
+되돌아가게 됩니다.
+possible) to the save point.
+*/
+ MSG_BATTLEFIELD_WARNINGMSG4 = 0x853,
+/*20171018 to latest
+다른 이의 요청 결과를 기다리고 있습니다.
+Waiting for the opponents.
+*/
+ MSG_BATTLEFIELD_WAIT_PLAYER = 0x854,
+/*20171018 to latest
+전장 입장 요청
+Battlefield position request
+*/
+ MSG_BATTLEFIELD_REQUEST_JOIN = 0x855,
+/*20171018 to latest
+수락대기시간:%d초
+Accept standby time:%d seconds
+*/
+ MSG_BATTLEFIELD_WAITTIME_D = 0x856,
+/*20171018 to latest
+입장 대기 상태
+Standby position
+*/
+ MSG_BATTLEFIELD_STATE_JOINWAIT = 0x857,
+/*20171018 to latest
+전장 명칭: %s
+Battlefield name:%s
+*/
+ MSG_BATTLEFIELD_NAME_S = 0x858,
+/*20171018 to latest
+전장 필요 인원: %d
+Persons required:%d
+*/
+ MSG_BATTLEFIELD_MEMBER_D = 0x859,
+/*20171018 to latest
+내 대기순번: %d
+Your position:%d
+*/
+ MSG_BATTLEFIELD_MYRANK_D = 0x85a,
+/*20171018 to latest
+명칭 :
+Name:
+*/
+ MSG_BATTLEFIELD_DP_TITLE = 0x85b,
+/*20171018 to latest
+목표 :
+Goal:
+*/
+ MSG_BATTLEFIELD_DP_AIM = 0x85c,
+/*20171018 to latest
+전장의 인원 구성 :
+Format:
+*/
+ MSG_BATTLEFIELD_DP_MEMBER = 0x85d,
+/*20171018 to latest
+참여조건 :
+Level:
+*/
+ MSG_BATTLEFIELD_DP_REQUIRED = 0x85e,
+/*20171018 to latest
+보상(승) :
+Win:
+*/
+ MSG_BATTLEFIELD_DP_WIN = 0x85f,
+/*20171018 to latest
+보상(무) :
+Draw:
+*/
+ MSG_BATTLEFIELD_DP_DRAW = 0x860,
+/*20171018 to latest
+보상(패) :
+Loss:
+*/
+ MSG_BATTLEFIELD_DP_LOSS = 0x861,
+/*20171018 to latest
+전장을 개인으로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the individuals battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_SINGLE = 0x862,
+/*20171018 to latest
+전장을 파티로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the parties battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_PALTY = 0x863,
+/*20171018 to latest
+전장을 길드로 신청 하셨습니다. 맞습니까?
+Do you want to participate in the guilds battle?
+*/
+ MSG_BATTLEFIELD_DOYOU_GUILD = 0x864,
+/*20171018 to latest
+전장 목록
+Battleground List
+*/
+ MSG_BATTLEFIELD_LIST2 = 0x865,
+/*20171018 to latest
+%d VS %d
+*/
+ MSG_BATTLEFIELD_D_VS_D = 0x866,
+/*20171018 to latest
+Base LV %d 이하
+LV %d and lower
+*/
+ MSG_BATTLEFIELD_LEVELDOWN_D = 0x867,
+/*20171018 to latest
+Base LV %d 이상
+LV %d and higher
+*/
+ MSG_BATTLEFIELD_LEVELUP_D = 0x868,
+/*20171018 to latest
+Base LV %d ~ %d
+LV %d ~ %d
+*/
+ MSG_BATTLEFIELD_LEVEL_D_D = 0x869,
+/*20171018 to latest
+제한 없음
+No restrictions
+*/
+ MSG_BATTLEFIELD_LIMITLESS = 0x86a,
+/*20171018 to latest
+[해당 맵에서는 신청하실 수 없습니다.]
+[You can't apply on this map.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_JOINMAP = 0x86b,
+/*20171018 to latest
+[전장 재신청까지 약 1분의 대기시간을 필요로 합니다.]
+[You must wait about 1 minute to apply.]
+*/
+ MSG_BATTLEFIELD_MSG_WAIT_1MM = 0x86c,
+/*20171018 to latest
+[파티에 먼저 가입하셔야 합니다.]
+[You must be in a party.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_PALTYJOIN = 0x86d,
+/*20171018 to latest
+[파티장만 신청 가능합니다.]
+[Only party leader can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_PALTYBOSS = 0x86e,
+/*20171018 to latest
+[접속되어있는 파티인원수가 많습니다.]
+[Too many party members online.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_PARTYMEMBER = 0x86f,
+/*20171018 to latest
+[길드에 먼저 가입하셔야 합니다.]
+[You must be in a guild.]
+*/
+ MSG_BATTLEFIELD_MSG_PLZ_GUILDJOIN = 0x870,
+/*20171018 to latest
+[길드장만 신청 가능합니다.]
+[Only guild master can apply.]
+*/
+ MSG_BATTLEFIELD_MSG_NOT_GUILDBOSS = 0x871,
+/*20171018 to latest
+[접속되어있는 길드인원수가 많습니다.]
+[Too many guild members online.]
+*/
+ MSG_BATTLEFIELD_MSG_OVER_GUILDMEMBER = 0x872,
+/*20171018 to latest
+이동예약
+Moving Book
+*/
+ MSG_RESERVE_CHANGE_CHARACTER_SLOT = 0x873,
+/*20171018 to latest
+이동
+Move
+*/
+ MSG_CHARACTER_SLOT_CHANGE = 0x874,
+/*20171018 to latest
+이름변경
+Rename
+*/
+ MSG_CHANGE_CHARACTER_NAME = 0x875,
+/*20171018 to latest
+Make Character
+Create Character
+*/
+ MSG_MSG_MAKECHARCTER = 0x876,
+/*20171018 to latest
+http://ro.game.gnjoy.com/
+*/
+ MSG_UAE_URL = 0x877,
+/*20171018 to latest
+(%s) Server
+*/
+ MSG_UAE_SERVERSTR = 0x878,
+/*20171018 to latest
+아이템 병합(모두선택 Ctrl+클릭)
+Item Merge
+*/
+ MSG_MERGE_ITEM = 0x879,
+/*20171018 to latest
+같은 종류의 아이템을 2개 이상 선택해주세요.
+Two or more of the same type. Please select an item.
+*/
+ MSG_SELECT_ITEM_TO_MERGE = 0x87a,
+/*20171018 to latest
+아이템 합치기에 성공했습니다.
+Item merge is successful.
+*/
+ MSG_MERGE_ITEM_SUCCESS = 0x87b,
+/*20171018 to latest
+아이템 합치기는 한번에 1종류씩만 가능합니다.
+Combining items will be only one kind at a time.
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_MERGE = 0x87c,
+/*20171018 to latest
+아이템의 개수가 30000개 초과 했습니다.
+You cannot have more than 30,000 stacked items.
+*/
+ MSG_MERGE_ITEM_FAILED_MAX_COUNT = 0x87d,
+/*20171018 to latest
+좌로 회전
+Rotate left
+*/
+ MSG_CHARACTER_LEFT_ROLL = 0x87e,
+/*20171018 to latest
+우로 회전
+Rotate right
+*/
+ MSG_CHARACTER_RIGHT_ROLL = 0x87f,
+/*20171018 to latest
+(%s)님의 이전서버 정보보기
+(%s) to view the old server information
+*/
+ MSG_VIEW_BEFORE_WORLDINFO = 0x880,
+/*20171018 to latest
+기존 서버 정보
+Existing server information
+*/
+ MSG_VIEW_BEFORE_WORLDINFO_TITLE = 0x881,
+/*20171018 to latest
+^ff0000기존 서버 : ^0000ff
+^ff0000Existing server: ^0000ff
+*/
+ MSG_VIEW_BEFORE_SERVERINFO = 0x882,
+/*20171018 to latest
+^ff0000기존 캐릭명 : ^0000ff
+^ff0000Existing character: ^0000ff
+*/
+ MSG_VIEW_BEFORE_CHARNAME = 0x883,
+/*20171018 to latest
+공격한 몬스터의 HP가 표시됩니다.
+Show monster HP bar when attacking.
+*/
+ MSG_MONSTER_HP_ON = 0x884,
+/*20171018 to latest
+공격한 몬스터의 HP가 표시되지 않습니다.
+Hide monster HP bar when attacking.
+*/
+ MSG_MONSTER_HP_OFF = 0x885,
+/*20171018 to latest
+병합 가능한 아이템이 존재하지 않습니다
+Merge does not exist as an item
+*/
+ MSG_MERGE_ITEM_FAILED_NOT_EXIST = 0x886,
+/*20171018 to latest
+병합 가능한 아이템이 존재하지 않습니다.
+Merge items available does not exist.
+*/
+ MSG_NOT_EXIST_MERGE_ITEM = 0x887,
+/*20171018 to latest
+진행중
+Act
+*/
+ MSG_QUESTUI_TAB_PROCESS = 0x888,
+/*20171018 to latest
+보류중
+Pen
+*/
+ MSG_QUESTUI_TAB_HOLD = 0x889,
+/*20171018 to latest
+추천
+Rec
+*/
+ MSG_QUESTUI_TAB_BEST = 0x88a,
+/*20171018 to latest
+에피소드
+Episode
+*/
+ MSG_QUESTUI_TAB_EPISODE = 0x88b,
+/*20171018 to latest
+로컬
+Loc
+*/
+ MSG_QUESTUI_TAB_LOCAL = 0x88c,
+/*20171018 to latest
+이벤트
+Evt
+*/
+ MSG_QUESTUI_TAB_EVENT = 0x88d,
+/*20171018 to latest
+신규
+New
+*/
+ MSG_QUESTUI_TAB_NEW = 0x88e,
+/*20171018 to latest
+사냥몬스터
+Monsters to kill
+*/
+ MSG_QUESTUI_HUNTMONSTER = 0x88f,
+/*20171018 to latest
+보상아이템
+Rewards
+*/
+ MSG_QUESTUI_REWARDITEM = 0x890,
+/*20171018 to latest
+필요아이템
+Required Items
+*/
+ MSG_QUESTUI_NEEDITEM = 0x891,
+/*20171018 to latest
+제한시간
+Time Limit
+*/
+ MSG_QUESTUI_TIMELIMIT = 0x892,
+/*20171018 to latest
+마감시간
+Deadline
+*/
+ MSG_QUESTUI_CLOSINGTIME = 0x893,
+/*20171018 to latest
+검색
+Search
+*/
+ MSG_NAVIGATION_SEARCH = 0x894,
+/*20171018 to latest
+목표로 안내
+Navigation
+*/
+ MSG_NAVIGATION_TARGETGO = 0x895,
+/*20171018 to latest
+길 정보
+Back to Navigation
+*/
+ MSG_NAVIGATION_ROUTEINFO = 0x896,
+/*20171018 to latest
+검색 정보
+Find Information
+*/
+ MSG_NAVIGATION_SEARCHINFO = 0x897,
+/*20171018 to latest
+보기 모드 변경
+Toggle Minimap
+*/
+ MSG_NAVIGATION_VIEWCHANGE = 0x898,
+/*20171018 to latest
+외부 길정보 파일 읽기
+Read Information from External File
+*/
+ MSG_NAVIGATION_LIGHTCHANGE = 0x899,
+/*20171018 to latest
+종료
+Exit
+*/
+ MSG_NAVIGATION_END = 0x89a,
+/*20171018 to latest
+기본 UI로 변경
+Change the Default UI
+*/
+ MSG_NAVIGATION_BASE = 0x89b,
+/*20171018 to latest
+간편 UI로 변경
+Change to Default UI
+*/
+ MSG_NAVIGATION_MINI = 0x89c,
+/*20171018 to latest
+도움말
+Help
+*/
+ MSG_NAVIGATION_HELP = 0x89d,
+/*20171018 to latest
+ALL
+*/
+ MSG_NAVIGATION_ALL = 0x89e,
+/*20171018 to latest
+Map
+*/
+ MSG_NAVIGATION_MAP = 0x89f,
+/*20171018 to latest
+Npc
+*/
+ MSG_NAVIGATION_NPC = 0x8a0,
+/*20171018 to latest
+Mob
+*/
+ MSG_NAVIGATION_MOB = 0x8a1,
+/*20171018 to latest
+검색 단어 설정 (Ex: 단어 단어 ...
+Enter search string... (Ex: word word ...)
+*/
+ MSG_NAVIGATION_SETSTRING = 0x8a2,
+/*20171018 to latest
+Scroll
+*/
+ MSG_NAVIGATION_SCROLL = 0x8a3,
+/*20171018 to latest
+던전이동 스크롤 사용 적용
+Use Scroll?
+*/
+ MSG_NAVIGATION_USESCROLL = 0x8a4,
+/*20171018 to latest
+Service
+*/
+ MSG_NAVIGATION_SERVICE = 0x8a5,
+/*20171018 to latest
+위치 이동 서비스 허용
+Use Kafra Warp?
+*/
+ MSG_NAVIGATION_USESERVICE = 0x8a6,
+/*20171018 to latest
+Plane
+*/
+ MSG_NAVIGATION_PLANE = 0x8a7,
+/*20171018 to latest
+비공정 이동 적용
+Use Airship?
+*/
+ MSG_NAVIGATION_USEPLANE = 0x8a8,
+/*20171018 to latest
+>> 목표 정보를 읽지 못함!
+>> Failed to read the target information.
+*/
+ MSG_NAVIGATION_TARGETUNKNOWN = 0x8a9,
+/*20171018 to latest
+<< 안내중 >>
+>> Destination <<
+*/
+ MSG_NAVIGATION_GOING = 0x8aa,
+/*20171018 to latest
+<< 검색중... >>
+<< Goal >>
+*/
+ MSG_NAVIGATION_SEARCHING = 0x8ab,
+/*20171018 to latest
+-----------
+*/
+ MSG_NAVIGATION_UN = 0x8ac,
+/*20171018 to latest
+Navigation
+*/
+ MSG_NAVIGATION_NAVI = 0x8ad,
+/*20171018 to latest
+== 검색 결과(%d)==
+= Found (%d) ==
+*/
+ MSG_NAVIGATION_SEARCHRESULT_D = 0x8ae,
+/*20171018 to latest
+Npc)%s:%s
+*/
+ MSG_NAVIGATION_NPC_S_S = 0x8af,
+/*20171018 to latest
+Mob)%s:%s
+*/
+ MSG_NAVIGATION_MOB_S_S = 0x8b0,
+/*20171018 to latest
+Map)%s
+*/
+ MSG_NAVIGATION_MAP_S = 0x8b1,
+/*20171018 to latest
+======== 결과 정보 ==========
+======== Results ==========
+*/
+ MSG_NAVIGATION_RESULTINFO = 0x8b2,
+/*20171018 to latest
+거리 : %d Sell %d WarpMove
+Dist %d Cell %d WarpMove
+*/
+ MSG_NAVIGATION_LENGTH = 0x8b3,
+/*20171018 to latest
+목표맵: %s(%s)
+Coords %s(%s)
+*/
+ MSG_NAVIGATION_TARGETMAP_S_S = 0x8b4,
+/*20171018 to latest
+목표 : %s(%d, %d)
+Goal:%s (%d,%d)
+*/
+ MSG_NAVIGATION_TARGET_S_D_D = 0x8b5,
+/*20171018 to latest
+보스
+Boss
+*/
+ MSG_NAVIGATION_BOSS = 0x8b6,
+/*20171018 to latest
+일반
+General
+*/
+ MSG_NAVIGATION_NORMAL = 0x8b7,
+/*20171018 to latest
+목표 : %s(%s)
+Goal:
+*/
+ MSG_NAVIGATION_TARGET_S_S = 0x8b8,
+/*20171018 to latest
+목표: (%d, %d)
+Goal: (%d, %d)
+*/
+ MSG_NAVIGATION_TARGET_D_D = 0x8b9,
+/*20171018 to latest
+======= 길 안내 정보 =======
+======= Guidance =======
+*/
+ MSG_NAVIGATION_GOINFO = 0x8ba,
+/*20171018 to latest
+%2d) Item:%s => %s 사용!
+%2d) Item:%s => %s Use!
+*/
+ MSG_NAVIGATION_ITEM_S_S = 0x8bb,
+/*20171018 to latest
+%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_D_S_D_D_D_D = 0x8bc,
+/*20171018 to latest
+E%2d) %s(%d,%d)=>(%d,%d)
+*/
+ MSG_NAVIGATION_E_D_S_D_D_D_D = 0x8bd,
+/*20171018 to latest
+E%2d) %s
+*/
+ MSG_NAVIGATION_E_D_S = 0x8be,
+/*20171018 to latest
+안내중 입니다! 종료 하시겠습니까?
+Do you want to cancel navigation?
+*/
+ MSG_NAVIGATION_GOEXIT = 0x8bf,
+/*20171018 to latest
+내비게이션 도움말
+How to Use Navigation
+*/
+ MSG_NAVIGATION_HELPTITLE = 0x8c0,
+/*20171018 to latest
+------------------- 명령어 --------------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP1 = 0x8c1,
+/*20171018 to latest
+1. /navigation /navi
+1) /Navigation or /navi
+*/
+ MSG_NAVIGATION_HELP2 = 0x8c2,
+/*20171018 to latest
+ ex)/navi prontera 100/100 -> 맵이름, 100/100
+ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP3 = 0x8c3,
+/*20171018 to latest
+ 기본 명령어는 제니, 비공정 검색을 기본으로 합니다.
+2) /Navigation2 or /navi2
+*/
+ MSG_NAVIGATION_HELP4 = 0x8c4,
+/*20171018 to latest
+2. /navigation2 /navi2
+ex) /navi2 prontera 100 111
+*/
+ MSG_NAVIGATION_HELP5 = 0x8c5,
+/*20171018 to latest
+ ex) /navi2 prontera 100/100 1/1/1
+-> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP6 = 0x8c6,
+/*20171018 to latest
+-> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP7 = 0x8c7,
+/*20171018 to latest
+3. $$all 모든 항목 출력 (Type 구분 항목으로 출력 종류 구분 가능.)
+3) /$$ Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP8 = 0x8c8,
+/*20171018 to latest
+4. $$lv30 해당 레벨의 몬스터 출력
+4) /$$ Lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP9 = 0x8c9,
+/*20171018 to latest
+5. $$lv20~30 해당 레벨 범위의 몬스터 출력
+5) /$$ Lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_NAVIGATION_HELP10 = 0x8ca,
+/*20171018 to latest
+------------------- 설명 --------------------
+------------------- Description --------------------
+*/
+ MSG_NAVIGATION_HELP11 = 0x8cb,
+/*20171018 to latest
+1.검색 종류는 전체, 맵, Npc, 몬스터 으로 분류 된다.
+1) One can search for monsters, npcs, maps, or all at once
+*/
+ MSG_NAVIGATION_HELP12 = 0x8cc,
+/*20171018 to latest
+2.명령어로 검색한다. 규칙은 검색 하려는 문자열이 모두 포함된 정보를 출력 한다.
+2) You can press the search button to get results. It will out put the results depending on what rule you choose
+*/
+ MSG_NAVIGATION_HELP13 = 0x8cd,
+/*20171018 to latest
+ ex) 프론 카프 -> 검색 결과 프론테라의 카프라를 모두 출력 한다.
+ex) Drop down box -> Select "Npc", then type in the box "Kafra". Results will now be displayed
+*/
+ MSG_NAVIGATION_HELP14 = 0x8ce,
+/*20171018 to latest
+3.리스트에서 항목을 선택하면 정보가 출력된다.
+3) When you select an item from a list, information about it are displayed.
+*/
+ MSG_NAVIGATION_HELP15 = 0x8cf,
+/*20171018 to latest
+ 출력 되고 있는 목표가 있을때 안내 버튼을 클릭하면 해당 목표로 길을 안내 한다.
+-> When button is clicked, it will point you towards your destination if available
+*/
+ MSG_NAVIGATION_HELP16 = 0x8d0,
+/*20171018 to latest
+4.scrool/ zeny/ plane 상자를 원하는 만큼 체크하여 더 빠른 경로를 안내 받을 수 있다.
+4) Scroll | Zeny | Plane options can be checked to find a faster route
+*/
+ MSG_NAVIGATION_HELP17 = 0x8d1,
+/*20171018 to latest
+5.안내 버튼이 눌러지면 결과 리스트창은 길안내 리스트 장으로 변경 된다.
+5) Guide button is pressed, the result list window displays where routes can change direction
+*/
+ MSG_NAVIGATION_HELP18 = 0x8d2,
+/*20171018 to latest
+6.검색 리스트창 하단 버튼을 이용하여
+6) Using the button below, search results can be found
+*/
+ MSG_NAVIGATION_HELP19 = 0x8d3,
+/*20171018 to latest
+ [결과 리스트 창] <-> [길 안내 정보 창] 으로 보기 모드 변경 가능하다.
+-> [Results List Window] <-> [View Modes can be switched]
+*/
+ MSG_NAVIGATION_HELP20 = 0x8d4,
+/*20171018 to latest
+Level:%d (보스)
+Level:%d (Boss)
+*/
+ MSG_NAVIGATION_LEVEL_D_BOSS = 0x8d5,
+/*20171018 to latest
+Level:%d (일반)
+Level:%d (Mob)
+*/
+ MSG_NAVIGATION_LEVEL_D_NORMAL = 0x8d6,
+/*20171018 to latest
+수속성%d
+Water %d
+*/
+ MSG_NAVIGATION_PROPERTY1 = 0x8d7,
+/*20171018 to latest
+지속성%d
+Earth %d
+*/
+ MSG_NAVIGATION_PROPERTY2 = 0x8d8,
+/*20171018 to latest
+화속성%d
+Fire %d
+*/
+ MSG_NAVIGATION_PROPERTY3 = 0x8d9,
+/*20171018 to latest
+풍속성%d
+Wind %d
+*/
+ MSG_NAVIGATION_PROPERTY4 = 0x8da,
+/*20171018 to latest
+독속성%d
+Poison %d
+*/
+ MSG_NAVIGATION_PROPERTY5 = 0x8db,
+/*20171018 to latest
+성속성%d
+Holy %d
+*/
+ MSG_NAVIGATION_PROPERTY6 = 0x8dc,
+/*20171018 to latest
+암속성%d
+Shadow %d
+*/
+ MSG_NAVIGATION_PROPERTY7 = 0x8dd,
+/*20171018 to latest
+염속성%d
+Ghost %d
+*/
+ MSG_NAVIGATION_PROPERTY8 = 0x8de,
+/*20171018 to latest
+언데드%d
+Undead %d
+*/
+ MSG_NAVIGATION_PROPERTY9 = 0x8df,
+/*20171018 to latest
+무속성%d
+Neutral %d
+*/
+ MSG_NAVIGATION_PROPERTY0 = 0x8e0,
+/*20171018 to latest
+중형
+Medium
+*/
+ MSG_NAVIGATION_SCALE1 = 0x8e1,
+/*20171018 to latest
+대형
+Large
+*/
+ MSG_NAVIGATION_SCALE2 = 0x8e2,
+/*20171018 to latest
+소형
+Small
+*/
+ MSG_NAVIGATION_SCALE0 = 0x8e3,
+/*20171018 to latest
+불사형
+Undead
+*/
+ MSG_NAVIGATION_RACE1 = 0x8e4,
+/*20171018 to latest
+동물형
+Brute
+*/
+ MSG_NAVIGATION_RACE2 = 0x8e5,
+/*20171018 to latest
+식물형
+Plant
+*/
+ MSG_NAVIGATION_RACE3 = 0x8e6,
+/*20171018 to latest
+곤충형
+Insect
+*/
+ MSG_NAVIGATION_RACE4 = 0x8e7,
+/*20171018 to latest
+어패형
+Fish
+*/
+ MSG_NAVIGATION_RACE5 = 0x8e8,
+/*20171018 to latest
+악마형
+Demon
+*/
+ MSG_NAVIGATION_RACE6 = 0x8e9,
+/*20171018 to latest
+인간형
+Demi-Human
+*/
+ MSG_NAVIGATION_RACE7 = 0x8ea,
+/*20171018 to latest
+천사형
+Angel
+*/
+ MSG_NAVIGATION_RACE8 = 0x8eb,
+/*20171018 to latest
+용족
+Dragon
+*/
+ MSG_NAVIGATION_RACE9 = 0x8ec,
+/*20171018 to latest
+무형
+Formless
+*/
+ MSG_NAVIGATION_RACE0 = 0x8ed,
+/*20171018 to latest
+%s 이동 클릭
+Click to move %s
+*/
+ MSG_NAVIGATION_MOVECLICK = 0x8ee,
+/*20171018 to latest
+Npc 이동 서비스 이용
+Move to the Kafra Service Npc
+*/
+ MSG_NAVIGATION_NPCMOVE = 0x8ef,
+/*20171018 to latest
+NPC 클릭
+Click the NPC
+*/
+ MSG_NAVIGATION_NPCCLICK = 0x8f0,
+/*20171018 to latest
+%s 이동
+Move %s
+*/
+ MSG_NAVIGATION_S_MOVE = 0x8f1,
+/*20171018 to latest
+비공정 이동
+Move to the Airship Service
+*/
+ MSG_NAVIGATION_PLANEMOVE = 0x8f2,
+/*20171018 to latest
+워프 이용
+By Warp
+*/
+ MSG_NAVIGATION_WARPUSE = 0x8f3,
+/*20171018 to latest
+도착점 : ( %d %d )
+End Points: (%d %d)
+*/
+ MSG_NAVIGATION_TARGETPOINT_D_D = 0x8f4,
+/*20171018 to latest
+내비게이션이 지원 되지 않는 지역 입니다.
+That does not support the navigation area
+*/
+ MSG_NAVIGATION_UNKNOWNMAP = 0x8f5,
+/*20171018 to latest
+찾고자 하는 목적이 불분명 합니다.
+The purpose is unclear
+*/
+ MSG_NAVIGATION_RS_UNKNOWN = 0x8f6,
+/*20171018 to latest
+매칭이 맞지 않는 맵이다.
+Does not meet the map requirement
+*/
+ MSG_NAVIGATION_RS_NOTSAMEMAP = 0x8f7,
+/*20171018 to latest
+출발 지역에 대한 정보 설정 실패!
+Information Failure | Change settings
+*/
+ MSG_NAVIGATION_RS_FAILSTARTDATA = 0x8f8,
+/*20171018 to latest
+도착 지점에 대한 정보 설정 실패!
+Failed to set info for location!
+*/
+ MSG_NAVIGATION_RS_FAILTARGET = 0x8f9,
+/*20171018 to latest
+길 찾기 실패
+Failed to find a path
+*/
+ MSG_NAVIGATION_RS_FAILROUTE = 0x8fa,
+/*20171018 to latest
+플레이어 위치 찾기 실패
+Failed to find players
+*/
+ MSG_NAVIGATION_RS_FAILPLAYER = 0x8fb,
+/*20171018 to latest
+내비게이션에 정보가 없습니다.
+No Information
+*/
+ MSG_NAVIGATION_RS_NODATA = 0x8fc,
+/*20171018 to latest
+해당 맵은 길찾기가 지원 되지 않는 맵입니다.
+Map doesn't support directions
+*/
+ MSG_NAVIGATION_RS_MAPNOTNAVIGATION = 0x8fd,
+/*20171018 to latest
+목표를 지정 하시기 바랍니다.
+Please specify target goals.
+*/
+ MSG_NAVIGATION_RS_FAILTARGETROUTE = 0x8fe,
+/*20171018 to latest
+도착.
+Found
+*/
+ MSG_NAVIGATION_RS_SUCCESS = 0x8ff,
+/*20171018 to latest
+길 안내가 시작 되었습니다.
+Directions were started
+*/
+ MSG_NAVIGATION_RS_START = 0x900,
+/*20171018 to latest
+찾고자 하는 몬스터가 있는 맵 입니다.
+Is the map that your looking for mob
+*/
+ MSG_NAVIGATION_RS_MOBTARGETMAP = 0x901,
+/*20171018 to latest
+찾고자 하는 맵이 해당 맵 입니다.
+Map appears on the guide you are looking for
+*/
+ MSG_NAVIGATION_RS_TARGETMAP = 0x902,
+/*20171018 to latest
+아이템을 사용하여 이동하여 주시기 바랍니다.
+Please navigate using the item
+*/
+ MSG_NAVIGATION_RS_SCROLL = 0x903,
+/*20171018 to latest
+안내하는 위치로 이동하시기 바랍니다.
+Please follow the instruction to reach your destination.
+*/
+ MSG_NAVIGATION_RS_ROUTE_SUCCESS = 0x904,
+/*20171018 to latest
+목표 맵에 도착하였습니다.
+Arrived at the target map
+*/
+ MSG_NAVIGATION_RS_MAPTMAP_SUCCESS = 0x905,
+/*20171018 to latest
+찾고자 하는 Npc가 있는 맵에 도착 하였습니다. Npc로 이동하시기 바랍니다.
+Arrived on the map that has the Npc your looking for. Go to that NPC
+*/
+ MSG_NAVIGATION_RS_NPCTMAP_SUCCESS = 0x906,
+/*20171018 to latest
+찾고자 하는 Mob이 서식하는 맵에 도착 하였습니다.
+You have arrived at the mob you were looking for
+*/
+ MSG_NAVIGATION_RS_MOBTMAP_SUCCESS = 0x907,
+/*20171018 to latest
+이전과 동일한 목표 입니다.
+You have reached your goal
+*/
+ MSG_NAVIGATION_RS_POSTMAP_SUCCESS = 0x908,
+/*20171018 to latest
+가리키는 방향으로 가시기 바랍니다.
+Please go to indicated direction.
+*/
+ MSG_NAVIGATION_RS_SAMETARGET = 0x909,
+/*20171018 to latest
+목표가 여기 입니다.
+The goal has been reached
+*/
+ MSG_NAVIGATION_RS_HERE = 0x90a,
+/*20171018 to latest
+Navigation >: %s
+*/
+ MSG_NAVIGATION_PRINT_S = 0x90b,
+/*20171018 to latest
+Navigation >: 안내하는 %s(을)를 이용하여
+Navigation >: Talk to Guide "%s" (A)
+*/
+ MSG_NAVIGATION_PRINT_GO_S = 0x90c,
+/*20171018 to latest
+Navigation >: 맵(%s)으로 이동하시기 바랍니다
+Navigation >: Move to (%s) map
+*/
+ MSG_NAVIGATION_PRINT_MAP_S = 0x90d,
+/*20171018 to latest
+Navigation >: 맵(%s)을 선택하여 이동 하시기 바랍니다
+Navigation >: Choose (%s) Map from Kafra
+*/
+ MSG_NAVIGATION_PRINT_SELECTMAP_S = 0x90e,
+/*20171018 to latest
+Navigation >: 비공정으로 이동 하시기 바랍니다
+Navigation >: Please go to the AirShip
+*/
+ MSG_NAVIGATION_PRINT_PLANE = 0x90f,
+/*20171018 to latest
+Navigation >: 워프를 이용하여 다음 지역으로 이동하시기 바랍니다.
+Navigation >: Get to your destination by using WarpPortal
+*/
+ MSG_NAVIGATION_PRINT_WARP = 0x910,
+/*20171018 to latest
+Item:
+*/
+ MSG_NAVIGATION_PRINT_ITEM = 0x911,
+/*20171018 to latest
+$$
+*/
+ MSG_NAVIGATION_ZZ = 0x912,
+/*20171018 to latest
+$$lv
+*/
+ MSG_NAVIGATION_ZZLV = 0x913,
+/*20171018 to latest
+~
+*/
+ MSG_NAVIGATION_ZZLIMIT = 0x914,
+/*20171018 to latest
+$$all
+*/
+ MSG_NAVIGATION_ZZALL = 0x915,
+/*20171018 to latest
+구매 확인서
+Confirm Deal
+*/
+ MSG_SHOP_ITEM_BAY_TITLE = 0x916,
+/*20171018 to latest
+구입하려는 아이템들의 총가격은
+Below is the total cost:
+*/
+ MSG_SHOP_ITEM_BAY_MAG1 = 0x917,
+/*20171018 to latest
+Zeny 입니다.
+ Zeny to complete the transaction.
+*/
+ MSG_SHOP_ITEM_BAY_MAG2 = 0x918,
+/*20171018 to latest
+구입하시겠습니까?
+Press buy to confirm.
+*/
+ MSG_SHOP_ITEM_BAY_MAG3 = 0x919,
+/*20171018 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + 프리미엄 %.1f%% + %s서버 %.1f%%)
+%.1f% (PCRoom %.1f% + TPLUS %.1f% + Premium %.1f% + %sServer %.1f%)
+*/
+ MSG_BASIC_EXP_MSG2 = 0x91a,
+/*20171018 to latest
+카드 북
+Card Book
+*/
+ MSG_CARDWIN = 0x91b,
+/*20171018 to latest
+%d%% [ ( 기본 100%% + %s서버 %d%% ) * 활성 %.1f ]
+%d%% [ ( Basic 100%% + %sServer %d%% ) * Active %.1f ]
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN = 0x91c,
+/*20171018 to latest
+%d%% [ 기본 100%% + %s서버 %d%% ]
+%d%% [ Basic 100%% + %sServer %d%% ]
+*/
+ MSG_PERSONAL_INFORMATION_MSG_CHN_DEATH = 0x91d,
+/*20171018 to latest
+이곳은 PK 지역입니다. 미성년자는 자발적으로 떠나주시기 바랍니다.
+This is PK region. Minors,Please leave immediately.
+*/
+ MSG_CAUTION_PKZONE = 0x91e,
+/*20171018 to latest
+피로도
+Fatigue
+*/
+ MSG_FATIGUE = 0x91f,
+/*20171018 to latest
+건강상태 이며 게임수익은 100%입니다.
+Health and gaming revenue is 100%%.
+*/
+ MSG_FATIGUE_LEVEL_ZERO = 0x920,
+/*20171018 to latest
+지금은 피로상태이므로 손님의 게임수익은 50% 떨어집니다. 건강을 위하여 적당한 휴식 바랍니다.
+Fatigue because it is now a guest of the gaming revenue is down 50 percent.Hope for the proper health
+*/
+ MSG_FATIGUE_LEVEL_HALF = 0x921,
+/*20171018 to latest
+지금은 비건강상태이므로 손님의 건강을 위하여 게임오프라인을 원합니다. 계속 온라인상태에 있으면 건강에 손상을 주므로 게임 수익은 0%으로 떨어지며 게임 오프라인 5시간후에 다시 회복됩니다.
+Now because it is a non-health to the health of the guests want to offline games. If you still are online gaming revenue because the damage to the health of the game falls to 0% again after 5 hours will be restored offline.
+*/
+ MSG_FATIGUE_LEVEL_FULL = 0x922,
+/*20171018 to latest
+접속시간 %d 분이 되었습니다.
+Online since %d minutes
+*/
+ MSG_FATIGUE_MESSAGE0 = 0x923,
+/*20171018 to latest
+접속시간 %d 시간이 되었습니다.
+Online Time: %d
+*/
+ MSG_FATIGUE_MESSAGE1 = 0x924,
+/*20171018 to latest
+접속시간 %d 시간 %d 분이 되었습니다.
+Online since %d hours and %d minutes
+*/
+ MSG_FATIGUE_MESSAGE2 = 0x925,
+/*20171018 to latest
+/monsterhp : 공격한 몬스터의 HP정보를 표시합니다. On Off
+/monsterhp: Show the hp of attacked monster. On off
+*/
+ MSG_EXPLAIN_MONSTERHP = 0x926,
+/*20171018 to latest
+스킬포인트 :
+Skill Points:
+*/
+ MSG_SKILLPOINT2 = 0x927,
+/*20171018 to latest
+인증서버로 부터의 응답이 없습니다. 다시 시도해 주세요
+There is no response from the authentification server. Please try again
+*/
+ MSG_BAN_BILLING_SERVER_ERROR = 0x928,
+/*20171018 to latest
+암호를 변경하여 주시기 바랍니다.
+Please change your password
+*/
+ MSG_REFUSE_CHANGE_PASSWD_FORCE = 0x929,
+/*20171018 to latest
+http://www.ragnarok.co.kr
+*/
+ MSG_REFUSE_CHANGE_PASSWD_SITE = 0x92a,
+/*20171018 to latest
+고객님께서는 현재 접속금지 시간입니다.
+Guest access is prohibited
+*/
+ MSG_PLANNED_TIME_SHUTDOWN = 0x92b,
+/*20171018 to latest
+셧다운제도에 의해 고객님의 게임제한 시간은 %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d에 게임이 종료될 예정입니다.
+Your System is been Shutdown, %1.2d-%1.2d-%1.2d %1.2d:%1.2d:%1.2d is the end time.
+*/
+ MSG_SHOUTDOWN_TIME = 0x92c,
+/*20171018 to latest
+고객님의 계정은 선택적 셧다운이 적용된 계정이며, 잔여시간은 %1.2d시간 %1.2d분입니다. 게임 이용에 참고해주시기 바랍니다.
+Selected System Shutdown is activated in your account,Time Left: %1.2d hours %1.2d minutes.
+*/
+ MSG_PARTIAL_SHOUTDOWN_TIME = 0x92d,
+/*20171018 to latest
+리플레이
+Replay
+*/
+ MSG_MENU_REPLAYWND = 0x92e,
+/*20171018 to latest
+매크로
+Macro
+*/
+ MSG_MENU_MACROWND = 0x92f,
+/*20171018 to latest
+Webbrowser
+*/
+ MSG_MENU_WEBBROWSERWND = 0x930,
+/*20171018 to latest
+내비게이션
+Navigation
+*/
+ MSG_MENU_NAVIGATIONWND = 0x931,
+/*20171018 to latest
+UAEURL
+*/
+ MSG_MENU_UAEURLWND = 0x932,
+/*20171018 to latest
+ 클랜정보
+Clan Information
+*/
+ MSG_CLAN_INFOMANAGE = 0x933,
+/*20171018 to latest
+클랜레벨
+Clan Level
+*/
+ MSG_CLAN_LEVEL = 0x934,
+/*20171018 to latest
+클랜명
+Clan Name
+*/
+ MSG_CLAN_NAME = 0x935,
+/*20171018 to latest
+클랜마크
+Clan Mark
+*/
+ MSG_CLAN_MARK = 0x936,
+/*20171018 to latest
+동맹클랜
+Ally Clan
+*/
+ MSG_ALLY_CLAN = 0x937,
+/*20171018 to latest
+적대클랜
+Antagonist Clan
+*/
+ MSG_HOSTILITY_CLAN = 0x938,
+/*20171018 to latest
+클랜에게 보냄
+Send to Clan
+*/
+ MSG_SEND_TO_CLAN = 0x939,
+/*20171018 to latest
+마스터이름
+ClanMaster Name
+*/
+ MSG_CLAN_MASTER_NAME = 0x93a,
+/*20171018 to latest
+조합원수
+Number of Members
+*/
+ MSG_CLAN_NUM_MEMBER = 0x93b,
+/*20171018 to latest
+관리영지
+Castles Owned
+*/
+ MSG_CLAN_MANAGE_LAND = 0x93c,
+/*20171018 to latest
+클랜 채팅 메시지 표시
+Clan Chat Messages
+*/
+ MSG_VIEW_CLAN_MSG = 0x93d,
+/*20171018 to latest
+충전 페이지로 이동합니다.
+Go to Page Charged.
+*/
+ MSG_TWWAB_WARRING = 0x93e,
+/*20171018 to latest
+https://gfb.gameflier.com/Billing/ingame/index_new.asp?
+*/
+ MSG_TWWAB_URL = 0x93f,
+/*20171018 to latest
+캐릭터 만들기
+Create char
+*/
+ MSG_STR_MAKECHARACTER = 0x940,
+/*20171018 to latest
+캐릭명이 일치하지 않습니다.
+Name does not match
+*/
+ MSG_CHR_DELETE_RESERVED_FAIL_CHARNAME = 0x941,
+/*20171018 to latest
+캐릭터명을 입력하세요
+Enter the name of character
+*/
+ MSG_CHR_DELETE_RESERVED_INPUTCONFIRMSTR_WND_TITLE = 0x942,
+/*20171018 to latest
+성별 선택 창
+Sex Selection Window
+*/
+ MSG_SELECT_SEX = 0x943,
+/*20171018 to latest
+파일의 위변조가 감지 되었습니다.
+Editing of the File Detected
+*/
+ MSG_SPRITE_ALTER = 0x944,
+/*20171018 to latest
+해당 아이템을 개봉하여 획득되는 아이템들은 캐릭터 귀속 아이템 (창고이동 불가능) 입니다. 본 캐릭터에 사용하시는 것이 맞으신지 확인해주시기 바랍니다. 상자를 개봉하시겠습니까?
+Items obtained by opening the item is character bounded (can not move to storage). Do you want to open the box?
+*/
+ MSG_CONFIRM_TO_OPEN_EVENT_ITEM = 0x945,
+/*20171018 to latest
+게임 설정
+Game Settings
+*/
+ MSG_GAME_SETTING = 0x946,
+/*20171018 to latest
+게임 시스템
+Game System
+*/
+ MSG_SYSTEM_SETTING = 0x947,
+/*20171018 to latest
+게임 커맨드
+Game Commands
+*/
+ MSG_COMMAND_SETTING = 0x948,
+/*20171018 to latest
+게임 커맨드 ON/OFF
+Game Command ON/OFF
+*/
+ MSG_COMMAND_LIST = 0x949,
+/*20171018 to latest
+매크로
+Macro
+*/
+ MSG_MACRO_LIST = 0x94a,
+/*20171018 to latest
+이지역은 아이템교환이 금지 되어 있습니다
+Trading is prohibited in this Map
+*/
+ MSG_EXCHANGEITEM_DENY_MAP = 0x94b,
+/*20171018 to latest
+이지역은 카트이용이 금지 되어 있습니다
+Vending is prohibited in this Map
+*/
+ MSG_CART_USE_DENY_MAP = 0x94c,
+/*20171018 to latest
+이지역은 태양과달과별의 기적 효과가 발생하지 않습니다.
+In this Map,Effect of Mirace of Sun and Moon is nullified.
+*/
+ MSG_BLOCK_SUNMOONSTAR_MIRACLE = 0x94d,
+/*20171018 to latest
+랭킹 보드
+Ranking Board
+*/
+ MSG_RANKING_BOARD = 0x94e,
+/*20171018 to latest
+순위
+Rank
+*/
+ MSG_RANKING_NUMBER = 0x94f,
+/*20171018 to latest
+이름
+Name
+*/
+ MSG_RANKING_NAME = 0x950,
+/*20171018 to latest
+포인트
+Points
+*/
+ MSG_RANKING_POINT = 0x951,
+/*20171018 to latest
+BlackSmith
+*/
+ MSG_RANKING_BLACKSMITH = 0x952,
+/*20171018 to latest
+Alchemist
+*/
+ MSG_RANKING_ALCHEMIST = 0x953,
+/*20171018 to latest
+Taekwon
+*/
+ MSG_RANKING_TAEKWON = 0x954,
+/*20171018 to latest
+Killer
+*/
+ MSG_RANKING_KILLER = 0x955,
+/*20171018 to latest
+7 vs 7
+*/
+ MSG_RANKING_BATTLE_7VS7_ALL = 0x956,
+/*20171018 to latest
+RuneKnight
+*/
+ MSG_RANKING_RUNE_KNIGHT = 0x957,
+/*20171018 to latest
+Warlock
+*/
+ MSG_RANKING_WARLOCK = 0x958,
+/*20171018 to latest
+Ranger
+*/
+ MSG_RANKING_RANGER = 0x959,
+/*20171018 to latest
+Mechanic
+*/
+ MSG_RANKING_MECHANIC = 0x95a,
+/*20171018 to latest
+GuillotineCross
+*/
+ MSG_RANKING_GUILLOTINE_CROSS = 0x95b,
+/*20171018 to latest
+Archbishop
+*/
+ MSG_RANKING_ARCHBISHOP = 0x95c,
+/*20171018 to latest
+RoyalGuard
+*/
+ MSG_RANKING_ROYAL_GUARD = 0x95d,
+/*20171018 to latest
+Sorcerer
+*/
+ MSG_RANKING_SORCERER = 0x95e,
+/*20171018 to latest
+Minstrel
+*/
+ MSG_RANKING_MINSTREL = 0x95f,
+/*20171018 to latest
+Wanderer
+*/
+ MSG_RANKING_WANDERER = 0x960,
+/*20171018 to latest
+Genetic
+*/
+ MSG_RANKING_GENETIC = 0x961,
+/*20171018 to latest
+ShadowChaser
+*/
+ MSG_RANKING_SHADOW_CHASER = 0x962,
+/*20171018 to latest
+Sura
+*/
+ MSG_RANKING_SURA = 0x963,
+/*20171018 to latest
+Kagerou
+*/
+ MSG_RANKING_KAGEROU = 0x964,
+/*20171018 to latest
+Oboro
+*/
+ MSG_RANKING_OBORO = 0x965,
+/*20171018 to latest
+Select Ranking Type
+*/
+ MSG_RANKING_SELECT = 0x966,
+/*20171018 to latest
+Ranking Type
+*/
+ MSG_RANKING_TYPE = 0x967,
+/*20171018 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dSeconds
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_SEC = 0x968,
+/*20171018 to latest
+현재 접속 인원이 가득 찼습니다. ^0000ff현재 대기순위 : %d 예상 대기시간 : %d분 %d초
+Currently,Server is full. ^0000ffPeople Currently Waiting: %d Expected Waiting Time: %dMinutes %d Seconds
+*/
+ MSG_WAITING_FOR_ENTER_TO_CHARACTER_SEVER_IN_MIN = 0x969,
+/*20171018 to latest
+CBT 초청 유저가 아닙니다
+CBT is not an invited user
+*/
+ MSG_CBT_ACTIVE_USER_CHECK = 0x96a,
+/*20171018 to latest
+ -------------- Navigation 명령어 --------------
+------------------- Instruction --------------------
+*/
+ MSG_NAVIGATION_HELP_1 = 0x96b,
+/*20171018 to latest
+/navigation /navi : /navi yuno 100/100 ->> 맵이름, 위치(100/100)
+1) /Navigation or /navi ex) /navi prontera 100 100 -> /navi "MAPNAME", 100, 100
+*/
+ MSG_NAVIGATION_HELP_2 = 0x96c,
+/*20171018 to latest
+/navigation2 /navi2 : /navi2 yuno 100/100 1/1/1 ->> 맵이름, 위치(100/100), scrool/zeny/plane (1:사용함 0: 사용안함)
+2) /Navigation2 or /navi2 ex) /navi2 prontera 100 111 -> MAPNAME location (100 90), Scroll | Zeny | Plane (1: Enable or 0: Disable)
+*/
+ MSG_NAVIGATION_HELP_3 = 0x96d,
+/*20171018 to latest
+ -------------- Navigation 검색창 명령어 -------
+-> /navi2 goes with the case with location coordinates. They must be no less than 3 characters
+*/
+ MSG_NAVIGATION_HELP_4 = 0x96e,
+/*20171018 to latest
+$$all : 모든 항목 출력 (Type 구분자에서 출력 종류를 나눌수 있다.)
+3) $$all Output all the items (Can take a while...)
+*/
+ MSG_NAVIGATION_HELP_5 = 0x96f,
+/*20171018 to latest
+$$lv30 : 해당 레벨의 몬스터 출력 (숫자는 변경 가능)
+4) $$lv30 monsters are placed in the output
+*/
+ MSG_NAVIGATION_HELP_6 = 0x970,
+/*20171018 to latest
+$$lv20~30 : 해당 레벨 범위의 몬스터 출력 (숫자는 변경 가능)
+5) $$lv20~30 monsters in that level range are placed in the output
+*/
+ MSG_NAVIGATION_HELP_7 = 0x971,
+/*20171018 to latest
+1 vs 1
+*/
+ MSG_RANKING_BATTLE_1VS1_ALL = 0x972,
+/*20171018 to latest
+특수 장비
+Special Gear
+*/
+ MSG_SHADOW_EQUIPMENT = 0x973,
+/*20171018 to latest
+%d 번째 캐릭터의 직업 정보가 이상합니다. 고객센터로 문의 부탁 드립니다. ErrorCode(%d)
+%d First character of the profession is more than information. Please contact the Customer Care Center. ErrorCode(%d)
+*/
+ MSG_CHARACTERERROR_JOB = 0x974,
+/*20171018 to latest
+(%s) %d / %d
+*/
+ MSG_NAVIGATION_ALL_S = 0x975,
+/*20171018 to latest
+%s-%s(%d/%d)
+*/
+ MSG_NAVIGATION_ALL_SD = 0x976,
+/*20171018 to latest
+접속자 수 초과로 서버에 더이상 접속할 수 없습니다.
+Server Exceeded the maximum number of users,Cannot Connect anymore users.
+*/
+ MSG_REFUSE_OVER_USERLIMIT = 0x977,
+/*20171018 to latest
+서버접속 실패 (%d)
+Server Connection Failed (%d)
+*/
+ MSG_REFUSE_ERRORCODE = 0x978,
+/*20171018 to latest
+로그인 허용시간 초과
+Login Timeout Permitted
+*/
+ MSG_REFUSE_DISCONNECT_KEEP_TIME = 0x979,
+/*20171018 to latest
+로그인 중 인증서버로부터 인증이 실패하였습니다.
+Login Authentication Failed from Authentication Server.
+*/
+ MSG_REFUSE_WEB_AUTH_FAILED = 0x97a,
+/*20171018 to latest
+길드이름에 공백문자를 사용할 수 없습니다.
+Guild Cannot use Space in the name.
+*/
+ MSG_GUILDNAME_CHECK = 0x97b,
+/*20171018 to latest
+고객님 안녕하세요!
+Hey,Hello There
+*/
+ MSG_BILLING_CHN_1 = 0x97c,
+/*20171018 to latest
+고객님의 이용 시간은 %d년 %d 월 %d일 %d:%d 에 종료됩니다.
+Available Time will End on %d month %d hour %d:%d
+*/
+ MSG_BILLING_CHN_2 = 0x97d,
+/*20171018 to latest
+고객님의 이용 시간은 아직 많이 남았으니 안심하고 플레이하세요!
+You've lot of time,Play in Peace.
+*/
+ MSG_BILLING_CHN_3 = 0x97e,
+/*20171018 to latest
+고객님의 이용 시간은 이번 주 내로 종료 됩니다. 종료 전에 충전을 하시기 바랍니다.
+Your hours will be terminated within this week. Please Charge before termination.
+*/
+ MSG_BILLING_CHN_4 = 0x97f,
+/*20171018 to latest
+고객님의 이용 시간은 24시간 내에 종료됩니다. 빨리 충전하시기 바랍니다.
+Your hours will be terminated within 24 hours.Please Charge Quickly.
+*/
+ MSG_BILLING_CHN_5 = 0x980,
+/*20171018 to latest
+현재 고객님의 이용 시간은 %d시간 남았습니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d hours.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_6 = 0x981,
+/*20171018 to latest
+현재 고객님의 이용 시간은 %d분 남았습니다. 이용시간이 끝난 후 강제적으로 종료됩니다. 정상적인 게임 이용을 위해 충전을 하시기 바랍니다.
+Current Time Left:%d minutes.Charge the game for uninterrupted play.
+*/
+ MSG_BILLING_CHN_7 = 0x982,
+/*20171018 to latest
+고객님의 이용 시간은 %d시간 %d분 남았습니다.
+Time Left: %d hours %d minutes
+*/
+ MSG_BILLING_CHN_8 = 0x983,
+/*20171018 to latest
+%d%% ( 기본 100%% + PC방 %d%% + 프리미엄 %d%% + %s서버 %d%% )
+%d%% ( Basic 100%% + PCRoom %d%% + Premium %d%% + %sServer %d%% )
+*/
+ MSG_BASIC_EXP_MSG_THAI = 0x984,
+/*20171018 to latest
+고객님의 이용 시간은 %d시간 %d분 후에 종료됩니다.
+After %d hours %d minutes, your game will be terminated.
+*/
+ MSG_CHN_BILLING_EXPIRE_TIME = 0x985,
+/*20171018 to latest
+유저님의 계정은 영구 접속금지 되였습니다
+This Account is permanently Banned.
+*/
+ MSG_CHN_BLOCK_FOREVER = 0x986,
+/*20171018 to latest
+유저님의 계정은 접속금지 되였습니다
+ 해지 시간 : %04d-%02d-%02d %02d:%02d
+This Account is banned.
+Termination Time:%04d-%02d-%02d %02d:%02d
+*/
+ MSG_CHN_BLOCK = 0x987,
+/*20171018 to latest
+몬스터(Tab)
+Monster(Tab)
+*/
+ MSG_WORLDMAP_MSG1 = 0x988,
+/*20171018 to latest
+맵(Alt)
+Map(Alt)
+*/
+ MSG_WORLDMAP_MSG2 = 0x989,
+/*20171018 to latest
+안내 정보
+Product Information
+*/
+ MSG_WORLDMAP_MSG3 = 0x98a,
+/*20171018 to latest
+검색 정보
+Find Information
+*/
+ MSG_WORLDMAP_MSG4 = 0x98b,
+/*20171018 to latest
+비공정
+AirShip
+*/
+ MSG_WORLDMAP_MSG5 = 0x98c,
+/*20171018 to latest
+카프라
+Kafra
+*/
+ MSG_WORLDMAP_MSG6 = 0x98d,
+/*20171018 to latest
+(도착)
+(Arrival)
+*/
+ MSG_WORLDMAP_MSG7 = 0x98e,
+/*20171018 to latest
+Mob)%s:%s(%s)
+*/
+ MSG_NAVIGATION_MOB_S_S_S = 0x98f,
+/*20171018 to latest
+분포도:%s
+Distribution:%s
+*/
+ MSG_NAVIGATION_NUM = 0x990,
+/*20171018 to latest
+매우많음
+Very Plenty
+*/
+ MSG_NAVIGATION_NUM1 = 0x991,
+/*20171018 to latest
+많음
+Plenty
+*/
+ MSG_NAVIGATION_NUM2 = 0x992,
+/*20171018 to latest
+보통
+Normal
+*/
+ MSG_NAVIGATION_NUM3 = 0x993,
+/*20171018 to latest
+적음
+Low
+*/
+ MSG_NAVIGATION_NUM4 = 0x994,
+/*20171018 to latest
+매우적음
+Very Low
+*/
+ MSG_NAVIGATION_NUM5 = 0x995,
+/*20171018 to latest
+은행을 이용할 수 없습니다. 잠시 후 다시 시도하세요.
+The bank is not available. Please try again in a few minutes.
+*/
+ MSG_BANK_SYSTEM_ERROR = 0x996,
+/*20171018 to latest
+은행 잔고가 부족합니다.
+Bank balance is low.
+*/
+ MSG_BANK_WITHDRAW_NO_MONEY = 0x997,
+/*20171018 to latest
+보유한 Zeny 가 부족해서 입금할 수 없습니다.
+You don't have enough zeny
+*/
+ MSG_BANK_DEPOSIT_NO_MONEY = 0x998,
+/*20171018 to latest
+1 Zeny 이상 입금 가능합니다.
+Minimum Deposit Amount: 1 zeny
+*/
+ MSG_BANK_DEPOSIT_ZERO = 0x999,
+/*20171018 to latest
+1 Zeny 이상 출금 가능합니다.
+Minimum Withdrawal Amount: 1 zeny
+*/
+ MSG_BANK_WITHDRAW_ZERO = 0x99a,
+/*20171018 to latest
+보유 Zeny 는 2,147,483,647 Zeny를 넘을 수 없습니다.
+You cannot hold more than 2,147,483,647 Zeny
+*/
+ MSG_BANK_OVER_INT_MAX = 0x99b,
+/*20171018 to latest
+your account is lock by mobil otp
+your account is lock by mobile otp
+*/
+ MSG_REFUSE_MOTP_LOCK = 0x99c,
+/*20171018 to latest
+MOTP auth fail
+*/
+ MSG_REFUSE_MOTP_AUTH_FAIL = 0x99d,
+/*20171018 to latest
+%d분간 몬스터에게 얻을 수 있는 Job경험치가 %d%% 증가합니다.
+For %d minutes,Job Experience obtained from monster is increased by %d%%
+*/
+ MSG_JOBPLUSEXP_VALUE = 0x99e,
+/*20171018 to latest
+소지 Zeny : %s Zeny
+Current Zeny: %s Zeny
+*/
+ MSG_BANK_MY_ZENY = 0x99f,
+/*20171018 to latest
+Zeny
+*/
+ MSG_BANK_ZENY = 0x9a0,
+/*20171018 to latest
+최대 2,147,483,647 Zeny 까지만 보관이 가능합니다.
+The Maximum amount is 2,147,483,647 Zeny
+*/
+ MSG_BANK_WARNING = 0x9a1,
+/*20171018 to latest
+총알이 부족합니다.
+Insufficient bullet
+*/
+ MSG_NEED_MORE_BULLET = 0x9a2,
+/*20171018 to latest
+10억제니 이상 입력하셔도 가격은 10억 제니로 판매됩니다.
+You entered more than 1 Billion Zeny, the price will be set to 1 Billion Zeny.
+*/
+ MSG_OVERPRICE_MAX = 0x9a3,
+/*20171018 to latest
+AuthTicket is Not Vaild
+AuthTicket is Not Valid
+*/
+ MSG_NOT_VALID_AUTH_TICKET = 0x9a4,
+/*20171018 to latest
+ErrorCategory : %d, ErrorCode : %d (%d,%d,%d,%d)
+ErrorCode : %d, ErrorValue : %d
+*/
+ MSG_STEAMAGENCY_ERROR = 0x9a5,
+/*20171018 to latest
+%d%% ( Basic 100%% + Premium %d%% + PCCafe %d%% + %s Server %d%% )
+%d%% ( Basic 100%% + Premium %d%% + Internet cafe %d%% + %s Server %d%% )
+*/
+ MSG_BASIC_EXP_MSG_INDONESIA = 0x9a6,
+/*20171018 to latest
+ %d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE = 0x9a7,
+/*20171018 to latest
+ %d시 %.2d분간 몬스터 사냥을 통해 얻을 수 있는 기본 아이템의 드롭률이 %d%%로 증가합니다.
+Basic item drop rate from monster hunting is increased for %dhour %.2dmins by %dtimes.
+*/
+ MSG_RECEIVEITEM_VALUE_1 = 0x9a8,
+/*20171018 to latest
+%s 의 가격이
+The price of^0000FF %s^000000
+*/
+ MSG_WARNING_PRICE1 = 0x9a9,
+/*20171018 to latest
+100000000
+*/
+ MSG_WARNING_PRICE2 = 0x9aa,
+/*20171018 to latest
+ ^ff0000%d^0000ff억
+ is over ^FF0000%d^0000FF Billion^000000 Zeny and
+*/
+ MSG_WARNING_PRICE3 = 0x9ab,
+/*20171018 to latest
+10000000
+*/
+ MSG_WARNING_PRICE4 = 0x9ac,
+/*20171018 to latest
+ ^ff0000%d^0000ff천만
+ more than^FF0000 %d0^0000FF Million^000000 Zeny
+*/
+ MSG_WARNING_PRICE5 = 0x9ad,
+/*20171018 to latest
+^0000ffZeny 이상^000000입니다.
+입력금액이 맞습니까?
+. Is this correct?
+*/
+ MSG_WARNING_PRICE6 = 0x9ae,
+/*20171018 to latest
+천만Zeny이상 안전확인
+Safety check for more than 10m Zeny
+*/
+ MSG_WARNING_PRICE7 = 0x9af,
+/*20171018 to latest
+https://www.warpportal.com/account/login.aspx?ReturnUrl=%2faccount%2fpayment.aspx
+*/
+ MSG_AMERICA_CASHSHOP_URL = 0x9b0,
+/*20171018 to latest
+https://kepler.warpportal.com/ro1/purchase/?step=1&steamid=%lld&accountname=
+https://kepler.warpportal.com/ror/purchase/?step=1&steamid=%lld&accountname=
+*/
+ MSG_AMERICA_CASHSHOP_URL_STEAM = 0x9b1,
+/*20171018 to latest
+지상의 끝, 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 생겨난 거대한 균열, 그리고 근원을 알 수 없는 미궁숲.
+A giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim, and you do not know the source of the labyrinth forest.
+*/
+ MSG_QUEST_INFO_01 = 0x9b2,
+/*20171018 to latest
+이것은 여행의 끝을 알리는 표식인가, 새로운 세계를 여는 지표인가! 수호자는 노랫말 같은 유혹에 점차 넋을 잃어가고 있었다.
+This is a marker indicating the end of the trip, a new world is opening indicators! Guardian, such as the lyrics to the temptation was gradually losing the soul.
+*/
+ MSG_QUEST_INFO_02 = 0x9b3,
+/*20171018 to latest
+수천 년의 세월이 흐르는 동안, 그 스스로가 홀로 안간힘을 쓰며 지켜낸 것이 무엇이었는지, 봉인 되어 긴 시간을 갇혀버린 것은 오히려 자신이 아니었는지 혼란을 느끼고 있었다.
+For thousands of years, a mysterious melody has mesmerized the guardian. After a millennia of slumber, the guardian became confused about what he had been protecting all these years, and began to suspect that he might be the one who has been sealed and hidden away.
+*/
+ MSG_QUEST_INFO_03 = 0x9b4,
+/*20171018 to latest
+유혹의 노랫말이 최고조에 이르렀을 때, 지상의 끝 스플랑디드와 부유대륙 알프헤임을 잇는 다리, 비프로스트에 거대한 균열이 생겨났고, 그로 인해 두 세계간의 왕래가 끊기면서 사람들은 큰 불편을 겪게 되었다.
+When the melody reached its peak, a giant crevice appeared in Bifrost, the bridge between Splendide, the end of the world and the floating continent of Alfheim. As a result, the two worlds were cut off from each other, causing a big problem for the people.
+*/
+ MSG_QUEST_INFO_04 = 0x9b5,
+/*20171018 to latest
+비프로스트의 통로는 이제 미궁숲 뿐. 근원조차 알 수 없는 그곳을 무사히 통과 한 사람은 지금까지 아무도 없었다.
+Now, the only way to get to Bifrost is through the Labyrinth Forest. Nobody knows how the forest came to exist, and nobody has ever come out of it alive...
+*/
+ MSG_QUEST_INFO_05 = 0x9b6,
+/*20171018 to latest
+숱한 모험가들을 집어 삼킨 혼돈의 지옥, 미궁숲은 그 속을 방황하는 이름 모를 여인의 마음처럼 더욱 깊고 혼란스럽게 확장되고 있었다.
+Swallowed countless adventurers to put a hell of confusion, wandering in the forest labyrinth of nowhere, like the heart of a woman was being extend deeper confusion.
+*/
+ MSG_QUEST_INFO_06 = 0x9b7,
+/*20171018 to latest
+숫자만 입력 가능합니다.
+You can enter only numbers.
+*/
+ MSG_BANK_CHECK_NUM = 0x9b8,
+/*20171018 to latest
+교환창 또는 상점이 활성화 된 상태에서는 입출금을 하실수 없습니다.
+Exchange or store window is active and can not register the withdrawal.
+*/
+ MSG_BANK_PROHIBIT = 0x9b9,
+/*20171018 to latest
+바로가기
+Go to
+*/
+ MSG_QUEST_INFO_00 = 0x9ba,
+/*20171018 to latest
+아이템 비교
+Item Compare
+*/
+ MSG_ITEM_COMPARISON = 0x9bb,
+/*20171018 to latest
+현재 장착하려고 하는 총기가 장착하고 있는 탄환에 맞지 않습니다
+Now you are trying to mount the gun equipped with bullet does not meet
+*/
+ MSG_WRONG_GUN = 0x9bc,
+/*20171018 to latest
+현재 장착하려고 하는 탄환이 장착하고 있는 총기와 맞지 않습니다
+Now you are trying to mount the guns and bullets will not fit mounted
+*/
+ MSG_WRONG_BULLET = 0x9bd,
+/*20171018 to latest
+판매할 아이템을 등록하지 않았습니다. 판매하실 아이템을 등록해 주세요
+Has not registered to sell the item. Please register to sell the item
+*/
+ MSG_BUYINGSTORE_MAKEWND_ADD_GOODS = 0x9be,
+/*20171018 to latest
+ITEM
+*/
+ MSG_ITEM_IN_MAIL_SYSTEM = 0x9bf,
+/*20171018 to latest
+길드 창고를 이용할 수 없습니다.
+Guild storage is not available.
+*/
+ MSG_GUILD_STORAGE_OPEN_ERROR = 0x9c0,
+/*20171018 to latest
+길드에 가입되어 있지 않습니다. 가입 후 이용해주세요.
+Guild is not subscribed to. After signing up, please use
+*/
+ MSG_GUILD_STORAGE_OPEN_NO_JOIN_GUILD = 0x9c1,
+/*20171018 to latest
+다른 길드원이 사용중입니다. 잠시 후 이용해주세요.
+Two other guild members are in use. Please use it after a while.
+*/
+ MSG_GUILD_STORAGE_WARNING_USING_ANOTHER_MEMBER = 0x9c2,
+/*20171018 to latest
+창고권한
+Storage Permission
+*/
+ MSG_GUILD_STORAGE_PERMISSON = 0x9c3,
+/*20171018 to latest
+길드창고
+Guild Storage
+*/
+ MSG_GUILD_STORAGE_TITLE = 0x9c4,
+/*20171018 to latest
+길드창고의 사용 권한이 없습니다.
+You do not have permission to use guild storage.
+*/
+ MSG_GUILD_STORAGE_PERMISSON_WARNING_MSG = 0x9c5,
+/*20171018 to latest
+한정판매 등록창
+Limited Sale Registration Window
+*/
+ MSG_BARGAINSALE_TOOLWND_TITLE = 0x9c6,
+/*20171018 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NAME = 0x9c7,
+/*20171018 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_BARGAINSALE_TOOLWND_DB_NUMBER = 0x9c8,
+/*20171018 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_COUNT = 0x9c9,
+/*20171018 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_STARTTIME = 0x9ca,
+/*20171018 to latest
+판매할 시간
+Time to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_SELL_PERIODTIME = 0x9cb,
+/*20171018 to latest
+판매할 갯수를 입력해 주세요
+Please enter number you want to sell
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_COUNT_MSG = 0x9cc,
+/*20171018 to latest
+판매 시작시간을 입력해 주세요
+Enter start time of sale
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_STARTTIME_MSG = 0x9cd,
+/*20171018 to latest
+판매 시작시간의 범위가 맞지 않습니다
+Start time does not match the scope of sales.
+*/
+ MSG_BARGAINSALE_TOOLWND_WRONG_RANGE_MSG = 0x9ce,
+/*20171018 to latest
+판매할 시간을 입력해 주세요
+Please enter the time
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_PERIODTIME_MSG = 0x9cf,
+/*20171018 to latest
+Item DB Name을 입력해 주세요
+Please enter the Item DB Name
+*/
+ MSG_BARGAINSALE_TOOLWND_INPUT_ITEMDBNAME_MSG = 0x9d0,
+/*20171018 to latest
+Item ID 조회에 실패하였습니다. 확인 후 다시 시도해 주시기 바랍니다
+Item ID lookup failed. Please try again later
+*/
+ MSG_BARGAINSALE_TOOLWND_ITEMID_CHECK_FAILED_MSG = 0x9d1,
+/*20171018 to latest
+>> ItemName : %s / Price : %dc / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName: %s / Price: %dc / Quantity: %d / TimeOfSale: %dMonth:%dDay:%dMinute:%dSecond ~ %dMonth:%dDay:%dMinute:%dSecond
+*/
+ MSG_BARGAINSALE_TOOLWND_RESULT_FORMAT = 0x9d2,
+/*20171018 to latest
+등록에 성공하였습니다
+Registration successful
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_SUCCESS_MSG = 0x9d3,
+/*20171018 to latest
+등록에 실패하였습니다. 다시 시도해 주시기 바랍니다.
+Registration failure. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_APPLY_FAILED_MSG = 0x9d4,
+/*20171018 to latest
+이미 등록된 아이템이 있습니다. 다시 시도해 주시기 바랍니다.
+Item has already been registered. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_ALREADY_REGISTERED_MSG = 0x9d5,
+/*20171018 to latest
+아이템 삭제에 실패 하였습니다. 다시 시도해 주시기 바랍니다.
+Failed to delete the item. Please try again later.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_FAILED_MSG = 0x9d6,
+/*20171018 to latest
+%s 아이템이 삭제되었습니다.
+%s item has been deleted.
+*/
+ MSG_BARGAINSALE_TOOLWND_DELETE_SUCCESS_MSG = 0x9d7,
+/*20171018 to latest
+특가
+Special
+*/
+ MSG_BARGAINSALE_CASHSHOP_TAB_NAME = 0x9d8,
+/*20171018 to latest
+한정판매 아이템 판매수량 갱신
+Sales limited sale item update
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_BTN_TOOLTIP = 0x9d9,
+/*20171018 to latest
+판매종료
+Discontinued
+*/
+ MSG_BARGAINSALE_CASHSHOP_TIMER = 0x9da,
+/*20171018 to latest
+수량갱신이 필요합니다
+Quantity update is required
+*/
+ MSG_BARGAINSALE_CASHSHOP_REFRESH_MSG = 0x9db,
+/*20171018 to latest
+재고가 부족하여 %d 개 만큼만 구입합니다
+The %d is out of stock or to buy as much as
+*/
+ MSG_BARGAINSALE_CASHSHOP_CHECK_COUNT_MSG = 0x9dc,
+/*20171018 to latest
+%s 아이템의 특가판매가 시작되었습니다
+%s Items are on sale
+*/
+ MSG_BARGAINSALE_START_MSG = 0x9dd,
+/*20171018 to latest
+%s 아이템의 매진 또는 판매시간만료로 인해 한정판매가 종료되었습니다
+%s time-out or sale of the items sold has been shut down due to the limited sales
+*/
+ MSG_BARGAINSALE_CLOSE_MSG = 0x9de,
+/*20171018 to latest
+/한정판매
+/limitedsale
+*/
+ MSG_BARGAINSALE_TOOLWND_CALL = 0x9df,
+/*20171018 to latest
+http://www.ragnarokeurope.com/news/home-r70.html
+*/
+ MSG_FRANCE_CASHSHOP_URL = 0x9e0,
+/*20171018 to latest
+http://www.ragnarokeurope.com/index.php?rubrique=70&Steam
+*/
+ MSG_FRANCE_CASHSHOP_URL_STEAM = 0x9e1,
+/*20171018 to latest
+구입에 성공한 품목
+Item purchase successful
+*/
+ MSG_PARA_RESULT_TITLE = 0x9e2,
+/*20171018 to latest
+주문량이 재고량을 초과하였습니다.
+You do not have enough items.
+*/
+ MSG_PARA_WRONG_PURCHASE_COUNT_MSG = 0x9e3,
+/*20171018 to latest
+초대할수 없는 케릭터 이름입니다.
+Name of the character that cannot be invited.
+*/
+ MSG_PARTY_INVITE = 0x9e4,
+/*20171018 to latest
+길드초대할수 없는 케릭터 이름입니다.
+You cannot invite the character to the guild.
+*/
+ MSG_GUILD_INVITE = 0x9e5,
+/*20171018 to latest
+일부 품목은 이미 판매되어 구입에 실패하였습니다.
+Item already Sold,Purchase Failed.
+*/
+ MSG_PARA_PURCHASE_ITEM_FAIL = 0x9e6,
+/*20171018 to latest
+현재 위치에서 워프 장소를 기억 할 수 없습니다.
+The warp spot cannot be memorized in current position.
+*/
+ MSG_NOWARPSKILL2 = 0x9e7,
+/*20171018 to latest
+무게가 초과되어 아이템을 구매할 수 없습니다.
+Cannot purchase item, You exceeded the weight.
+*/
+ MSG_PARA_PURCHASE_ITEM_WEIGHT = 0x9e8,
+/*20171018 to latest
+No.
+*/
+ MSG_GUILD_STORAGE_NUMBER = 0x9e9,
+/*20171018 to latest
+아이템
+Item
+*/
+ MSG_GUILD_STORAGE_ITEM = 0x9ea,
+/*20171018 to latest
+개수
+Number
+*/
+ MSG_GUILD_STORAGE_ITEM_COUNT = 0x9eb,
+/*20171018 to latest
+이름
+Name
+*/
+ MSG_GUILD_STORAGE_USER_NAME = 0x9ec,
+/*20171018 to latest
+시간
+Time
+*/
+ MSG_GUILD_STORAGE_LOG_TIME = 0x9ed,
+/*20171018 to latest
+입/출
+Input/Output
+*/
+ MSG_GUILD_STORAGE_ITEM_IN_OUT = 0x9ee,
+/*20171018 to latest
+로그가 존재하지 않습니다.
+Log does not exist.
+*/
+ MSG_GUILD_STORAGE_LOG_FINISH = 0x9ef,
+/*20171018 to latest
+전 체
+Entire
+*/
+ MSG_GUILD_STORAGE_LOG_ALL = 0x9f0,
+/*20171018 to latest
+넣 기
+Insert Symbol
+*/
+ MSG_GUILD_STORAGE_LOG_IN = 0x9f1,
+/*20171018 to latest
+빼 기
+Remaining Time
+*/
+ MSG_GUILD_STORAGE_LOG_OUT = 0x9f2,
+/*20171018 to latest
+길드 창고 내역
+Guild Storage Logs
+*/
+ MSG_GUILD_STORAGE_LOG_WND_NAME = 0x9f3,
+/*20171018 to latest
+내역은 최근 100개만 표시됩니다.
+100 entries are displayed.
+*/
+ MSG_GUILD_STORAGE_LOG_CAUTION = 0x9f4,
+/*20171018 to latest
+길드창고의 사용 시간 2분이 경과되어 자동으로 종료됩니다.
+Guild Storage is open only for 2 minutes, and will close automatically.
+*/
+ MSG_GUILD_STORAGE_CLOSE_TIMEOUT = 0x9f5,
+/*20171018 to latest
+Incorrect GameSamba ID. Please Try Again.
+*/
+ MSG_INCORRECT_GAMESAMBEID = 0x9f6,
+/*20171018 to latest
+%s [%d옵션] : %d 개
+%s [%d Option]: %d Quantity
+*/
+ MSG_EA5 = 0x9f7,
+/*20171018 to latest
+코인이 필요합니다.
+Requires a Coin.
+*/
+ MSG_USESKILL_FAIL_COINTS = 0x9f8,
+/*20171018 to latest
+코인이 %d 개가 필요합니다.
+%d Coins are required.
+*/
+ MSG_USESKILL_FAIL_COINTS_NUM = 0x9f9,
+/*20171018 to latest
+개틀링건 계열의 총기류를 장착한 상태여야 합니다.
+Gatling Gun should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GATLING = 0x9fa,
+/*20171018 to latest
+샷건 계열의 총기류를 장착한 상태여야 합니다.
+Shotguns should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_SHOTGUN = 0x9fb,
+/*20171018 to latest
+라이플 계열의 총기류를 장착한 상태여야 합니다.
+Rifle should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_RIFLE = 0x9fc,
+/*20171018 to latest
+리볼버 계열의 총기류를 장착한 상태여야 합니다.
+Pair of Revolver should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_HANDGUN = 0x9fd,
+/*20171018 to latest
+성속성 블릿을 장착해야 합니다
+[Silver Bullet] weapon class must be equipped.
+*/
+ MSG_FAIL_NEED_EQUIPPED_PROPERTY_SAINT_BULLET = 0x9fe,
+/*20171018 to latest
+아이템 판매 내역
+Item Sell History
+*/
+ MSG_MERCHANT_SOLD_ITEM_LOG = 0x9ff,
+/*20171018 to latest
+아이템 구매 내역
+Item Purchase History
+*/
+ MSG_MERCHANT_ITEM_BUY_LOG = 0xa00,
+/*20171018 to latest
+그레네이드런쳐 계열의 총기류를 장착한 상태여야 합니다.
+Grenade Launcher should be equipped with bullets.
+*/
+ MSG_FAIL_NEED_EQUIPPED_GUN_GRANADE = 0xa01,
+/*20171018 to latest
+[히트배럴],[매드니스 캔슬러],[플래티넘 알터] 의 효과들은 중첩하여 사용할 수 없습니다.
+[Heat barrel],[Last Stand],[Platinum Alter] cannot be used while sitting.
+*/
+ MSG_FAIL_DUPLICATE_HEAT_BARREL_GS_MADNESSCANCEL_P_ALTER = 0xa02,
+/*20171018 to latest
+현재 맵에서는 사용할 수 없는 스킬입니다.
+Cannot use skill in this map.
+*/
+ MSG_USESKILL_FAIL_MAP = 0xa03,
+/*20171018 to latest
+길드 창고를 이용중인 경우 창고의 모든 아이템이 사라지게 됩니다.
+If you are using a guild storage, all items inside it will disappear.
+*/
+ MSG_GUILD_STORAGE_WARNING = 0xa04,
+/*20171018 to latest
+http://ragnarok.gamesamba.com/paytest.html
+http://ragnarok.gamesamba.com/
+*/
+ MSG_AMERICA_CASHSHOP_URL_GAMESAMBA = 0xa05,
+/*20171018 to latest
+로그인을 위해 패스워드를 입력해주세요.
+Please enter a password to login.
+*/
+ MSG_SECOND_PASSWORD_INFO_4 = 0xa06,
+/*20171018 to latest
+펫 진화
+Pet Evolution
+*/
+ MSG_PET_EVOLUTION = 0xa07,
+/*20171018 to latest
+진화 - %s
+Evolution - %s
+*/
+ MSG_PET_EVOLUTION_WITH_PET_NAME = 0xa08,
+/*20171018 to latest
+진화에는 다음의 재료가 필요합니다.
+Evolution requires the following ingredients:
+*/
+ MSG_PET_EVOLUTION_NEED_ITEM = 0xa09,
+/*20171018 to latest
+진화 하시겠습니까?
+Are you sure you want to evolve your pet?
+*/
+ MSG_DO_YOU_WANT_TO_EVOLVE_PET = 0xa0a,
+/*20171018 to latest
+알 수 없는 오류
+Unknown Error
+*/
+ MSG_PET_EVOLUTION_FAIL_UNKNOWN = 0xa0b,
+/*20171018 to latest
+소환된펫을 갖고 있지 않습니다.
+Pet Cannot be hatched.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOTEXIST_CALLPET = 0xa0c,
+/*20171018 to latest
+요청한 것이 펫알이 아닙니다.
+It is not requested petal.
+*/
+ MSG_PET_EVOLUTION_FAIL_NOT_PETEGG = 0xa0d,
+/*20171018 to latest
+진화 재료가 부족합니다.
+Evolution material is low.
+*/
+ MSG_PET_EVOLUTION_FAIL_RECIPE = 0xa0e,
+/*20171018 to latest
+진화에 필요한 재료가 부족합니다.
+Insufficient materials for evolution.
+*/
+ MSG_PET_EVOLUTION_FAIL_MATERIAL = 0xa0f,
+/*20171018 to latest
+친밀도가 절친인 상태에서만 진화가 가능합니다.
+Loyal Intimacy is required to evolve.
+*/
+ MSG_PET_EVOLUTION_FAIL_RG_FAMILIAR = 0xa10,
+/*20171018 to latest
+펫 자동 먹이 주기
+Automatic feeding
+*/
+ MSG_PET_AUTO_FEEDING = 0xa11,
+/*20171018 to latest
+펫에게 먹이를 주었습니다. '%s' 잔여량 %d개
+Feeding the pet. %d '%d' remaining
+*/
+ MSG_PET_AUTO_FEEDING_REST = 0xa12,
+/*20171018 to latest
+펫 자동 먹이 주기 활성화 On
+Automatic feeding turned On
+*/
+ MSG_PET_AUTO_FEEDING_ON = 0xa13,
+/*20171018 to latest
+펫 자동 먹이 주기 활성화 Off
+Automatic feeding turned Off
+*/
+ MSG_PET_AUTO_FEEDING_OFF = 0xa14,
+/*20171018 to latest
+갱신
+Update
+*/
+ MSG_REFRESH = 0xa15,
+/*20171018 to latest
+%d 분 전
+%d minutes ago
+*/
+ MSG_TIME_LINE_MINUTE = 0xa16,
+/*20171018 to latest
+%d 시간 전
+%d hours ago
+*/
+ MSG_TIME_LINE_HOUR = 0xa17,
+/*20171018 to latest
+%d 일 전
+%d days ago
+*/
+ MSG_TIME_LINE_DAY = 0xa18,
+/*20171018 to latest
+%d%% ( Premium %d%% + %s Server )
+%d%%% ( Premium %d%%% + %s Server )
+*/
+ MSG_BASIC_EXP_MSG_PH = 0xa19,
+/*20171018 to latest
+우편 발송
+Mailed
+*/
+ MSG_SEND_MAIL = 0xa1a,
+/*20171018 to latest
+메일이 전송되었습니다.
+Your mail has been sent.
+*/
+ MSG_MAIL_SENT = 0xa1b,
+/*20171018 to latest
+아이템이 인벤토리로 이동되었습니다.
+This item has been moved to the inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_SUCCEED = 0xa1c,
+/*20171018 to latest
+아이템 받기가 실패하였습니다.
+Failed to get items.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_FAILED = 0xa1d,
+/*20171018 to latest
+인벤토리를 비워주세요
+Please empty your inventory.
+*/
+ MSG_GET_ITEMS_FROM_MAIL_OVERWEIGHT = 0xa1e,
+/*20171018 to latest
+제니를 받았습니다.
+Zeny received.
+*/
+ MSG_GET_ZENY_FROM_MAIL_SUCCEED = 0xa1f,
+/*20171018 to latest
+제니 받기가 실패하였습니다.
+Failed to get zeny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_FAILED = 0xa20,
+/*20171018 to latest
+제니의 한계치를 넘었습니다.
+Exceeded the limits of zenny.
+*/
+ MSG_GET_ZENY_FROM_MAIL_OVERAMOUNT = 0xa21,
+/*20171018 to latest
+아이템 첨부 성공
+Items attached success
+*/
+ MSG_SET_ITEMS_TO_MAIL_SUCCEED = 0xa22,
+/*20171018 to latest
+받는 사람의 이름이 반드시 들어가야 합니다.
+The name of the recipient must be included.
+*/
+ MSG_INVALID_MAIL_RECIEVER_INFO = 0xa23,
+/*20171018 to latest
+제목의 길이는 한글 2자~25자, 영문 4자~50자 이어야 합니다.
+The length of the title must be 4 to 50 characters long.
+*/
+ MSG_INVALID_MAIL_TITLE_INFO = 0xa24,
+/*20171018 to latest
+메일 전송이 실패하였습니다.
+Mail delivery failed.
+*/
+ MSG_FAILED_SEND_MAIL = 0xa25,
+/*20171018 to latest
+적절하지 못한 아이템으로 전송 실패하였습니다.
+Transmission has failed to inappropriate items.
+*/
+ MSG_FAILED_SEND_MAIL_ITEM = 0xa26,
+/*20171018 to latest
+받는 사람의 정보가 존재하지 않습니다.
+Information of the recipient does not exist.
+*/
+ MSG_FAIELD_SEND_MAIL_TO = 0xa27,
+/*20171018 to latest
+%s [%d옵션]
+%s [%d Option]
+*/
+ MSG_EA6 = 0xa28,
+/*20171018 to latest
+레벨은 1~%d 사이의 숫자를 입력해 주세요.
+Level, enter a number between 1 and %d.
+*/
+ MSG_PARTY_BOOKING_ERR5R2 = 0xa29,
+/*20171018 to latest
+소지창의 여유공간을 확보해주세요.
+Please free the window possessing space.
+*/
+ MSG_ITEM_WND_OVERFULL = 0xa2a,
+/*20171018 to latest
+메일 보내기 횟수가 초과되었습니다.
+Sending mail count exceeded.
+*/
+ MSG_FAILED_MAIL_LIMIT_CNT = 0xa2b,
+/*20171018 to latest
+메일을 열 수 없습니다.
+You can not open the mail.
+*/
+ MSG_FAILED_TO_WRITE_MAIL = 0xa2c,
+/*20171018 to latest
+You are currently joined in CLan !!
+You currently belong to a clan.
+*/
+ MSG_JOINED_IN_CLAN = 0xa2d,
+/*20171018 to latest
+골드 PC방 마일리지 정보
+Gold PC rooms mileage information
+*/
+ MSG_GOLDPCCAFE_MILEAGE = 0xa2e,
+/*20171018 to latest
+펫 액세서리를 해제해야 진화가 가능합니다.
+Unequip pet accessories first to start evolution
+*/
+ MSG_PET_EVOLUTION_FAIL_PET_ACC_OFF = 0xa2f,
+/*20171018 to latest
+%d 분 후
+%d minutes later
+*/
+ MSG_TIME_LINE_MINUTE2 = 0xa30,
+/*20171018 to latest
+%d 시간 후
+%d hours later
+*/
+ MSG_TIME_LINE_HOUR2 = 0xa31,
+/*20171018 to latest
+%d 일 후
+%d days later
+*/
+ MSG_TIME_LINE_DAY2 = 0xa32,
+/*20171018 to latest
+확인 버튼을 눌러 C-CODE를 확인하세요.
+Press the OK button to confirm the C-CODE.
+*/
+ MSG_INVALID_CCODE_INFO = 0xa33,
+/*20171018 to latest
+첨부된 물품을 획득 후 삭제가 가능합니다.
+After obtaining the attached article can be deleted.
+*/
+ MSG_FAILED_DELETE_MAIL = 0xa34,
+/*20171018 to latest
+현재 보유 제니 보다 많은 제니를 보낼 수 없습니다.
+You can not send any more zeny.
+*/
+ MSG_FAILED_SEND_MAIL_ZENY = 0xa35,
+/*20171018 to latest
+수수료 : %s Zeny
+Fee: %s Zeny
+*/
+ MSG_SEND_MAIL_COMMISSION = 0xa36,
+/*20171018 to latest
+받는 사람의 이름이 존재하지 않습니다.
+The recipient's name does not exist.
+*/
+ MSG_FAILE_MAIL_RECIEVER_INFO = 0xa37,
+/*20171018 to latest
+E X P : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_EXPMSG = 0xa38,
+/*20171018 to latest
+DROP : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DROPMSG = 0xa39,
+/*20171018 to latest
+DEATH : %.1f%% ( basic %.1f%% premium %.1f%% + %s %.1f%%)
+*/
+ MSG_TAIWAN_PERSONALINFO_DEATHMSG = 0xa3a,
+/*20171018 to latest
+골드 PC방 마일리지는 최대 %d점까지 모을 수 있습니다.
+You can accumulate points of PC Gold-club up to %d points maximum.
+*/
+ MSG_MILEAGE_HELP = 0xa3b,
+/*20171018 to latest
+해당 서버에서 사용 할 수 없는 기능 입니다
+This function can not be used on the server.
+*/
+ MSG_RESTRAINT_OF_TRADE_1 = 0xa3c,
+/*20171018 to latest
+수래 이용이 불 가능한 서버 입니다.
+Imposible to use in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_2 = 0xa3d,
+/*20171018 to latest
+옥션 이용이 불 가능한 서버 입니다.
+The auction is not available in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_3 = 0xa3e,
+/*20171018 to latest
+거래가 불 가능한 서버 입니다.
+The deal is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_4 = 0xa3f,
+/*20171018 to latest
+아이템 버리기가 불 가능한 서버 입니다.
+Items discard is imposible in server.
+*/
+ MSG_RESTRAINT_OF_TRADE_5 = 0xa40,
+/*20171018 to latest
+상점 판매 기능을 사용할수 없습니다.
+Stores selling features are not available.
+*/
+ MSG_RESTRAINT_OF_TRADE_6 = 0xa41,
+/*20171018 to latest
+소환물의 SP가 부족합니다.
+The SP's summoned enough.
+*/
+ MSG_USESKILL_FAIL_SUMMON_SP_INSUFFICIENT = 0xa42,
+/*20171018 to latest
+%s/%s
+*/
+ MSG_SEND_MAIL_WEIGHT = 0xa43,
+/*20171018 to latest
+메일 내용의 최대 길이는 1K 이하 입니다.
+The maximum length of the message content is 1K.
+*/
+ MSG_INVALID_MAIL_CONTENTS_INFO = 0xa44,
+/*20171018 to latest
+아이템 첨부 실패
+Failed to attach an item.
+*/
+ MSG_SET_ITEMS_TO_MAIL_FAILED = 0xa45,
+/*20171018 to latest
+메일에 첨부할수 있는 아이템의 무게가 초과되었습니다.
+The weight of the items that can be attached to mail has been exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVER_WEIGHT = 0xa46,
+/*20171018 to latest
+이미 서비스 중입니다. 잠시 후 다시 시도해 주세요.
+Is already in service. Please try again in a few minutes.
+*/
+ MSG_DYNAMICNPC_FAIL_DUPLICATENAME = 0xa47,
+/*20171018 to latest
+행운의 룰렛창을 열 수 없습니다.
+Unable to open the window of Lucky Roulette.
+*/
+ MSG_FAILED_OPEN_ROULLETTE = 0xa48,
+/*20171018 to latest
+행운의 룰렛창을 닫을 수 없습니다.
+Unable to close the window of the Lucky Roulette.
+*/
+ MSG_FAILED_CLOSE_ROULLETTE = 0xa49,
+/*20171018 to latest
+행운의 룰렛을 시작 할 수 없습니다.
+You can not start a roulette wheel of fortune.
+*/
+ MSG_FAILED_GENERATE_ROULLETTE = 0xa4a,
+/*20171018 to latest
+행운의 룰렛을 시작하기 위해서는 포인트가 필요합니다.
+Points is required to play Lucky Roulette.
+*/
+ MSG_NOT_ENOUGH_ROULLETTE_POINT = 0xa4b,
+/*20171018 to latest
+당첨된 아이템을 수령할 수 없습니다.
+You can not receive a winning items.
+*/
+ MSG_FAILED_RECV_ITEM = 0xa4c,
+/*20171018 to latest
+인벤토리에 아이템 개수가 초과되었습니다.
+The number of items in the inventory has been exceeded.
+*/
+ MSG_FAILED_RECV_ITEM_OVERCOUNT = 0xa4d,
+/*20171018 to latest
+무게가 초과하였습니다. 소지창의 여유공간을 확보해주세요.
+The weight has been exceeded. Please free up the possesion window.
+*/
+ MSG_FAILED_RECV_ITEM_OVERWEIGHT = 0xa4e,
+/*20171018 to latest
+노점 개설 실패.
+Failed to open stalls.
+*/
+ MSG_MERCHANTSHOP_MAKING_FAIL = 0xa4f,
+/*20171018 to latest
+룰렛이 돌고 있습니다. 경품을 확인 후에 다시 시도해주세요.
+The roulette wheel is spinning. Please try again after checking with prizes.
+*/
+ MSG_FAILED_CLOSE_ROULLETTEWND = 0xa50,
+/*20171018 to latest
+행운의 룰렛
+Lucky Roulette
+*/
+ MSG_ROULLETTE_WND = 0xa51,
+/*20171018 to latest
+아이템 판매 시 소리로 알림
+Notify when item sell out
+*/
+ MSG_SOUNDEFFECT_ITEMSELLWND = 0xa52,
+/*20171018 to latest
+수수료를 확인해주세요.
+Please check the fees.
+*/
+ MSG_FAILED_SEND_MAIL_ITEMS = 0xa53,
+/*20171018 to latest
+유저이름 확인
+Verify user name
+*/
+ MSG_CHECK_USER_NAME = 0xa54,
+/*20171018 to latest
+삭제 예정
+Schedule deletion
+*/
+ MSG_DELETE_DUE_DATE = 0xa55,
+/*20171018 to latest
+달성과제
+Achievable challenge
+*/
+ MSG_ACHIEVEMENT_SYSTEM = 0xa56,
+/*20171018 to latest
+달성총점
+Achieve overall
+*/
+ MSG_ACHIEVEMENT_TOTAL_SCORE = 0xa57,
+/*20171018 to latest
+달성등급
+Achieve rank
+*/
+ MSG_ACHIEVEMENT_GRADE = 0xa58,
+/*20171018 to latest
+다음 달성등급까지 [%5d]점
+The following compensation box until [% 5d] point
+*/
+ MSG_ACHIEVEMENT_SCORE_REQUIRED_TO_REWARD = 0xa59,
+/*20171018 to latest
+진척상황
+Progress
+*/
+ MSG_ACHIEVEMENT_SUMMARY_TITLE = 0xa5a,
+/*20171018 to latest
+최근 달성 업적
+Recent Achievements
+*/
+ MSG_ACHIEVEMENT_RECENT_ACHIEVEMENT = 0xa5b,
+/*20171018 to latest
+仙貝 품목
+Cracker Item
+*/
+ MSG_CASH_GEDARE1 = 0xa5c,
+/*20171018 to latest
+仙貝 : %d / %d
+Cracker : %d / %d
+*/
+ MSG_CASH_GEDARE2 = 0xa5d,
+/*20171018 to latest
+仙貝가 부족합니다.
+Cracker is low.
+*/
+ MSG_CASH_GEDARE_FAIL_MONEY = 0xa5e,
+/*20171018 to latest
+%s
+*/
+ MSG_CASH_GEDARE_MONEY = 0xa5f,
+/*20171018 to latest
+개요
+Overview
+*/
+ MSG_ACHIEVEMENT_TAB_SUMMARY = 0xa60,
+/*20171018 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL = 0xa61,
+/*20171018 to latest
+캐릭터
+Role
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_CHARACTER = 0xa62,
+/*20171018 to latest
+행동
+Action
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_ACTION = 0xa63,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_GENERAL_REST = 0xa64,
+/*20171018 to latest
+모험
+Adventure
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE = 0xa65,
+/*20171018 to latest
+룬미드가츠
+Rune Midgarts
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_RUNEMIDGARTS = 0xa66,
+/*20171018 to latest
+슈발츠발드
+Schwartzvald
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_SCHWARZWALD = 0xa67,
+/*20171018 to latest
+아루나펠츠
+Arunafeltz
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ARUNAFELTZ = 0xa68,
+/*20171018 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_ANOTHERWORLD = 0xa69,
+/*20171018 to latest
+로컬라이징
+Localizing
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_LOCALIZING = 0xa6a,
+/*20171018 to latest
+던전
+Dungeon
+*/
+ MSG_ACHIEVEMENT_TAB_ADVENTURE_DUNGEON = 0xa6b,
+/*20171018 to latest
+전투
+Battle
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE = 0xa6c,
+/*20171018 to latest
+결투
+Duel
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_PVP = 0xa6d,
+/*20171018 to latest
+수련
+Lily
+*/
+ MSG_ACHIEVEMENT_TAB_BATTLE_TRAINING = 0xa6e,
+/*20171018 to latest
+퀘스트
+Quest
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST = 0xa6f,
+/*20171018 to latest
+에피소드
+Episode
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_EPISODE = 0xa70,
+/*20171018 to latest
+일반
+General
+*/
+ MSG_ACHIEVEMENT_TAB_QUEST_GENERAL = 0xa71,
+/*20171018 to latest
+메모리얼
+Memorial
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL = 0xa72,
+/*20171018 to latest
+미드가르드
+Midgard
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_MIDGARD = 0xa73,
+/*20171018 to latest
+이계
+Commandment
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_ANOTHERWORLD = 0xa74,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_ACHIEVEMENT_TAB_MEMORIAL_REST = 0xa75,
+/*20171018 to latest
+위업
+Feat
+*/
+ MSG_ACHIEVEMENT_TAB_ACHIEVEMENT = 0xa76,
+/*20171018 to latest
+달성한 과제
+Achieved challenge
+*/
+ MSG_ACHIEVEMENT_TAB_TOTAL = 0xa77,
+/*20171018 to latest
+더 이상 추가할 수 없습니다.
+You cannot add anymore.
+*/
+ MSG_FAIL_ADD_ACHIEVEMENT_TRACING = 0xa78,
+/*20171018 to latest
+< %s > 달성하였습니다.
+< %S > achieved.
+*/
+ MSG_NOTICE_COMPLETE_ACHIEVEMENT = 0xa79,
+/*20171018 to latest
+only otp user login allow
+Only OTP users are allowed
+*/
+ MSG_OTPUSER_ONLY = 0xa7a,
+/*20171018 to latest
+이 버튼을 누를 시, 지정된 상품을 받게되며 룰렛은 초기화 됩니다.
+When this button pressed, you will receive a specified initialized roulette item.
+*/
+ MSG_GET_ROULLETE_PRIZE = 0xa7b,
+/*20171018 to latest
+이 버튼을 누를 시, 깜빡이는 화살표의 라인부터 룰렛을 시작 합니다.
+When this button pressed, the flashing arrows from the lines of the roulette wheel begins.
+*/
+ MSG_NOTICE_NEXT_ROULLETE_STAGE = 0xa7c,
+/*20171018 to latest
+칭호
+Style
+*/
+ MSG_TITLE_EQUIPMENT = 0xa7d,
+/*20171018 to latest
+칭호 해제
+Title release
+*/
+ MSG_TAKEOFF_TITLE = 0xa7e,
+/*20171018 to latest
+길드 생성을 할 수 없는 지역입니다.
+Can't create a Guild in this area.
+*/
+ MSG_GUILD_MAKE_GUILD_NOT_PERMITTED_MAP = 0xa7f,
+/*20171018 to latest
+길드 해체를 할 수 없는 지역입니다.
+Can't disband a Guild in this area.
+*/
+ MSG_GUILD_DISORGANIZE_GUILD_NOT_PERMITTED_MAP = 0xa80,
+/*20171018 to latest
+길드 가입을 할 수 없는 지역입니다.
+Can't join a Guild in this area.
+*/
+ MSG_GUILD_JOIN_GUILD_NOT_PERMITTED_MAP = 0xa81,
+/*20171018 to latest
+길드 탈퇴를 할 수 없는 지역입니다.
+Can't leave a Guild in this area.
+*/
+ MSG_GUILD_LEAVE_GUILD_NOT_PERMITTED_MAP = 0xa82,
+/*20171018 to latest
+길드원 추방을 할 수 없는 지역입니다.
+Can't deport a Guild in this area.
+*/
+ MSG_GUILD_EXPEL_GUILD_NOT_PERMITTED_MAP = 0xa83,
+/*20171018 to latest
+길드직위 변경을 할 수 없는 지역입니다.
+Can't change a Guild title in this area
+*/
+ MSG_GUILD_POSITION_CHANGE_NOT_PERMITTED_MAP = 0xa84,
+/*20171018 to latest
+아이템 소지량을 5칸이상 비워주세요
+Please empty at least 5 amount of possession in item window.
+*/
+ MSG_NOT_ENOUGH_SPACE_IN_ITEM_BODY = 0xa85,
+/*20171018 to latest
+E X P : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_EXPMSG = 0xa86,
+/*20171018 to latest
+DROP : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DROPMSG = 0xa87,
+/*20171018 to latest
+DEATH : %.1f%% ( basic 100.0%% pccafe %.1f%% + %s %.1f%%)
+*/
+ MSG_JPN_PERSONALINFO_DEATHMSG = 0xa88,
+/*20171018 to latest
+첨부할 수 있는 아이템의 갯수가 초과되었습니다.
+The number of items that can be attached is exceeded.
+*/
+ MSG_SET_ITEMS_TO_MAIL_OVERCOUNT = 0xa89,
+/*20171018 to latest
+아이템 구매 시 소리로 알림
+Notify when item purchased
+*/
+ MSG_SOUNDEFFECT_ITEMBUYWND = 0xa8a,
+/*20171018 to latest
+첨부할 수 없는 아이템입니다.
+Unable to attach the items.
+*/
+ MSG_ID_A8B = 0xa8b,
+/*20171018 to latest
+꽝에 당첨되었으므로 다음 상위 단계의 룰렛을 돌리실 수 없습니다.
+Because you can not win a slam room and turn the roulette of the next higher step.
+*/
+ MSG_ID_A8C = 0xa8c,
+/*20171018 to latest
+답장쓰기
+Replying
+*/
+ MSG_ID_A8D = 0xa8d,
+/*20171018 to latest
+내용읽기
+Read more
+*/
+ MSG_ID_A8E = 0xa8e,
+/*20171018 to latest
+메일삭제
+Delete message
+*/
+ MSG_ID_A8F = 0xa8f,
+/*20171018 to latest
+仙貝 : %d
+Crackers : %d
+*/
+ MSG_ID_A90 = 0xa90,
+/*20171018 to latest
+%s %s 仙貝
+%s %s crackers
+*/
+ MSG_ID_A91 = 0xa91,
+/*20171018 to latest
+仙貝
+Crackers
+*/
+ MSG_ID_A92 = 0xa92,
+/*20171018 to latest
+Total : %d 仙貝
+Total : %d Crackers
+*/
+ MSG_ID_A93 = 0xa93,
+/*20171018 to latest
+%d -> %s 仙貝
+%d -> %s Crackers
+*/
+ MSG_ID_A94 = 0xa94,
+/*20171018 to latest
+%s 仙貝
+%s Crackers
+*/
+ MSG_ID_A95 = 0xa95,
+/*20171018 to latest
+ Current 仙貝 : %s
+ Current Crackers : %s
+*/
+ MSG_ID_A96 = 0xa96,
+/*20171018 to latest
+ %s : %s 仙貝
+ %s : %s Crackers
+*/
+ MSG_ID_A97 = 0xa97,
+/*20171018 to latest
+%10s 仙貝
+%10s Crackers
+*/
+ MSG_ID_A98 = 0xa98,
+/*20171018 to latest
+Total : %s 仙貝
+Total : %s Crackers
+*/
+ MSG_ID_A99 = 0xa99,
+/*20171018 to latest
+※수수료 3% / 최소 1仙貝의 수수료 차감
+* Commission 3% / Minimum 1 Crackers comission deducted
+*/
+ MSG_ID_A9A = 0xa9a,
+/*20171018 to latest
+仙貝 입니다.
+The Crackers.
+*/
+ MSG_ID_A9B = 0xa9b,
+/*20171018 to latest
+^0000ff仙貝 이상^000000입니다.
+입력금액이 맞습니까?
+^0000ff more than crackers^000000Did you enter the correct amount?
+*/
+ MSG_ID_A9C = 0xa9c,
+/*20171018 to latest
+10억仙貝이상 안전 확인
+Over than 10billions secure check
+*/
+ MSG_ID_A9D = 0xa9d,
+/*20171018 to latest
+10억 仙貝 이상 입력하셔도 가격은 10억 仙貝로 판매됩니다.
+If you fill over 1 billion, the price will be automatically set as 10 billion Xianbei.
+*/
+ MSG_ID_A9E = 0xa9e,
+/*20171018 to latest
+9,999仙貝 이상 입력하셔도 가격은 9,999仙貝로 판매됩니다.
+If you fill over 9,999 Xianbei, the price will automatically set as 9,999 Xianbei.
+*/
+ MSG_ID_A9F = 0xa9f,
+/*20171018 to latest
+가격이 0 仙貝인 아이템이 존재 합니다. 상점을 열수 없습니다!
+There are items priced 0 Xianbei. You cannot open vending.
+*/
+ MSG_ID_AA0 = 0xaa0,
+/*20171018 to latest
+상대 캐릭터가 최대 보유 仙貝량을 초과하여 거래가 불가능 합니다.
+The opponent is over the Xianbei limit. Trade failed.
+*/
+ MSG_ID_AA1 = 0xaa1,
+/*20171018 to latest
+%s 아이템의 가격을 10억仙貝 이하로 입력해 주세요.
+Please fill out %s item price less than 1 billion Xianbei.
+*/
+ MSG_ID_AA2 = 0xaa2,
+/*20171018 to latest
+%s : %s 仙貝 => %s EA
+%s: %s Xianbei => %s ea
+*/
+ MSG_ID_AA3 = 0xaa3,
+/*20171018 to latest
+제한 금액 : %s 仙貝
+Limited price: %s Xianbei
+*/
+ MSG_ID_AA4 = 0xaa4,
+/*20171018 to latest
+%s %s 仙貝 %d 개
+%s %s %d Xianbei
+*/
+ MSG_ID_AA5 = 0xaa5,
+/*20171018 to latest
+%s %d개를 %d 仙貝에 판매 하였습니다. 수수료는 3%% 입니다.
+%d %s are sold. In total %d Xianbei. 3%% charge will be imposed.
+*/
+ MSG_ID_AA6 = 0xaa6,
+/*20171018 to latest
+RODEX
+*/
+ MSG_ID_AA7 = 0xaa7,
+/*20171018 to latest
+SEND
+*/
+ MSG_ID_AA8 = 0xaa8,
+/*20171018 to latest
+RECEIVE
+*/
+ MSG_ID_AA9 = 0xaa9,
+/*20171018 to latest
+메일 작성창을 닫아주세요.
+Please close the mail compose window.
+*/
+ MSG_ID_AAA = 0xaaa,
+/*20171018 to latest
+서버접근거부(A)
+Server access denied(A)
+*/
+ MSG_ID_AAB = 0xaab,
+/*20171018 to latest
+서버접근거부(B)
+Server access denied(B)
+*/
+ MSG_ID_AAC = 0xaac,
+/*20171018 to latest
+장착된 화살/탄환 을 해제해야합니다.
+Unequipped Arrow/Ammunition.
+*/
+ MSG_ID_AAD = 0xaad,
+/*20171018 to latest
+인벤토리의 아이템이 소모되어 로덱스 쓰기창을 닫습니다.
+Consuming item in inventory will close mail compose window.
+*/
+ MSG_ID_AAE = 0xaae,
+/*20171018 to latest
+소지하신 돋보기가 없습니다.
+Do not have Magnifier.
+*/
+ MSG_ID_AAF = 0xaaf,
+/*20171018 to latest
+아이템을 버릴려면 메일 쓰기창을 닫아주세요.
+Close email window if you want to discard item.
+*/
+ MSG_ID_AB0 = 0xab0,
+/*20171018 to latest
+상대방이 친구 요청중입니다
+The opponent has already requested you to be a friend.
+*/
+ MSG_ID_AB1 = 0xab1,
+/*20171018 to latest
+SCRIPT ERROR AID
+*/
+ MSG_ID_AB2 = 0xab2,
+/*20171018 to latest
+
+Errorfile : %s
+ErrorLine : %d 줄
+ErrorContent:
+*이전 줄 : %s
+*Errorline : %s
+*다음 줄:
+ %s
+
+Errorfile : %s
+ErrorLine : %d item
+ErrorContext: %s
+*/
+ MSG_ID_AB3 = 0xab3,
+/*20171018 to latest
+ ^ff0000해당 아이템을 구매 하시겠습니까? %d포인트 및 %d 仙貝가 차감 됩니다.
+^ff0000Are you sure want to purchase the item? after confirmation will consume %d point and %d crackers.
+*/
+ MSG_ID_AB4 = 0xab4,
+/*20171018 to latest
+닫기
+Close
+*/
+ MSG_ID_AB5 = 0xab5,
+/*20171018 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_AB6 = 0xab6,
+/*20171018 to latest
+퀘스트 아이콘 보기
+View Quest icon
+*/
+ MSG_ID_AB7 = 0xab7,
+/*20171018 to latest
+편의시설
+Facility
+*/
+ MSG_ID_AB8 = 0xab8,
+/*20171018 to latest
+편의시설 아이콘 보기
+View Facility icon
+*/
+ MSG_ID_AB9 = 0xab9,
+/*20171018 to latest
+길드원/파티원
+Guild/Party
+*/
+ MSG_ID_ABA = 0xaba,
+/*20171018 to latest
+길드원/파티원 보기
+Show Guild/Party
+*/
+ MSG_ID_ABB = 0xabb,
+/*20171018 to latest
+기록하기
+Record
+*/
+ MSG_ID_ABC = 0xabc,
+/*20171018 to latest
+보스몬스터
+Boss Monster
+*/
+ MSG_ID_ABD = 0xabd,
+/*20171018 to latest
+나
+I
+*/
+ MSG_ID_ABE = 0xabe,
+/*20171018 to latest
+삭제 하시겠습니까?
+Are you sure want to delete it?
+*/
+ MSG_ID_ABF = 0xabf,
+/*20171018 to latest
+퀘스트 NPC
+Quest NPC
+*/
+ MSG_ID_AC0 = 0xac0,
+/*20171018 to latest
+메모할 내용을 기록합니다
+Record content
+*/
+ MSG_ID_AC1 = 0xac1,
+/*20171018 to latest
+저장하기
+Store
+*/
+ MSG_ID_AC2 = 0xac2,
+/*20171018 to latest
+메모하기
+Record
+*/
+ MSG_ID_AC3 = 0xac3,
+/*20171018 to latest
+%s [%d옵션] %d개
+%s [%d Property] %d ea
+*/
+ MSG_ID_AC4 = 0xac4,
+/*20171018 to latest
+%s [%d옵션] %s Zeny
+%s [%d Property] %s Zeny
+*/
+ MSG_ID_AC5 = 0xac5,
+/*20171018 to latest
+%s [%d옵션] %d %s %d -> %s %s
+%s [%d Property] %d %s %d -> %s %s
+*/
+ MSG_ID_AC6 = 0xac6,
+/*20171018 to latest
+%s [%d옵션] %d %s %s %s
+%s [%d Property] %d %s %s %s
+*/
+ MSG_ID_AC7 = 0xac7,
+/*20171018 to latest
+%s [%d옵션] %d -> %s %s
+%s [%d Property] %d -> %s %s
+*/
+ MSG_ID_AC8 = 0xac8,
+/*20171018 to latest
+%s [%d옵션] %s %s
+%s [%d Property] %s %s
+*/
+ MSG_ID_AC9 = 0xac9,
+/*20171018 to latest
+최소 거래 단위 100 仙貝 이상으로 설정 하셔야 합니다.
+The minimum trading unit must be 100 crackers or more.
+*/
+ MSG_ID_ACA = 0xaca,
+/*20171018 to latest
+머리 색
+Hair color
+*/
+ MSG_ID_ACB = 0xacb,
+/*20171018 to latest
+머리 모양
+Hair style
+*/
+ MSG_ID_ACC = 0xacc,
+/*20171018 to latest
+옷 색
+Cloth color
+*/
+ MSG_ID_ACD = 0xacd,
+/*20171018 to latest
+옷 모양
+Cloth pattern
+*/
+ MSG_ID_ACE = 0xace,
+/*20171018 to latest
+지원되지 않는 맵 입니다.
+Unsupported Map.
+*/
+ MSG_ID_ACF = 0xacf,
+/*20171018 to latest
+2,147,483,647 Zeny 이하로 입력 하십시오.
+Enter Zeny Below 2,147,483,647.
+*/
+ MSG_ID_AD0 = 0xad0,
+/*20171018 to latest
+1 Zeny 이상 입력 하십시오.
+Please Enter atleast 1 zeny.
+*/
+ MSG_ID_AD1 = 0xad1,
+/*20171018 to latest
+보유한 Zeny 가 없습니다.
+You do not hold any zeny.
+*/
+ MSG_ID_AD2 = 0xad2,
+/*20171018 to latest
+제니 창고
+Zeny Storage
+*/
+ MSG_ID_AD3 = 0xad3,
+/*20171018 to latest
+창고보유액
+in Bank
+*/
+ MSG_ID_AD4 = 0xad4,
+/*20171018 to latest
+소지금
+on hand
+*/
+ MSG_ID_AD5 = 0xad5,
+/*20171018 to latest
+입금
+Deposit
+*/
+ MSG_ID_AD6 = 0xad6,
+/*20171018 to latest
+출금
+Withdraw
+*/
+ MSG_ID_AD7 = 0xad7,
+/*20171018 to latest
+1 z UP
+*/
+ MSG_ID_AD8 = 0xad8,
+/*20171018 to latest
+1 z Down
+*/
+ MSG_ID_AD9 = 0xad9,
+/*20171018 to latest
+Max
+*/
+ MSG_ID_ADA = 0xada,
+/*20171018 to latest
+입력값이 없습니다
+There is no Input value
+*/
+ MSG_ID_ADB = 0xadb,
+/*20171018 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_ADC = 0xadc,
+/*20171018 to latest
+입력값 필요
+Input Required
+*/
+ MSG_ID_ADD = 0xadd,
+/*20171018 to latest
+문자 입력 불가
+Numbers only
+*/
+ MSG_ID_ADE = 0xade,
+/*20171018 to latest
+최대 입력 초과
+Exceeded max input
+*/
+ MSG_ID_ADF = 0xadf,
+/*20171018 to latest
+최소 입력 미만
+Below Minimum Input
+*/
+ MSG_ID_AE0 = 0xae0,
+/*20171018 to latest
+보유 Zeny 부족
+Not enough zeny
+*/
+ MSG_ID_AE1 = 0xae1,
+/*20171018 to latest
+은행 잔고 부족
+Insufficient funds
+*/
+ MSG_ID_AE2 = 0xae2,
+/*20171018 to latest
+최대 보유 Zeny 초과
+Exceeded max zeny
+*/
+ MSG_ID_AE3 = 0xae3,
+/*20171018 to latest
+드롭 X
+Drop X
+*/
+ MSG_ID_AE4 = 0xae4,
+/*20171018 to latest
+창고 X
+Storage X
+*/
+ MSG_ID_AE5 = 0xae5,
+/*20171018 to latest
+카트 X
+Cart X
+*/
+ MSG_ID_AE6 = 0xae6,
+/*20171018 to latest
+메일 X
+Mail X
+*/
+ MSG_ID_AE7 = 0xae7,
+/*20171018 to latest
+교환창 X
+Trade X
+*/
+ MSG_ID_AE8 = 0xae8,
+/*20171018 to latest
+경매장 X
+Auction X
+*/
+ MSG_ID_AE9 = 0xae9,
+/*20171018 to latest
+길드창고 X
+Guild Storage X
+*/
+ MSG_ID_AEA = 0xaea,
+/*20171018 to latest
+NPC에게 판매 X
+Sell to NPC X
+*/
+ MSG_ID_AEB = 0xaeb,
+/*20171018 to latest
+이동제한이 있는 아이템입니다.
+Item moves restriction.
+*/
+ MSG_ID_AEC = 0xaec,
+/*20171018 to latest
+캐릭터를 생성해주세요!
+Please Create a Character!
+*/
+ MSG_ID_AED = 0xaed,
+/*20171018 to latest
+장착된 투사체 아이템을 해제해야 합니다.
+You need to disarm the equipped projectiles.
+*/
+ MSG_ID_AEE = 0xaee,
+/*20171018 to latest
+인원 초과로 메모리얼 던전에 입장 할 수 없습니다
+You cannot enter Memorial Dungeon with excess members
+*/
+ MSG_ID_AEF = 0xaef,
+/*20171018 to latest
+인원수 초과로 인해 메모리얼 던전 입장이 거부되었습니다
+Memorial Dungeon Access was denied due to exceeding number of players
+*/
+ MSG_ID_AF0 = 0xaf0,
+/*20171018 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF1 = 0xaf1,
+/*20171018 to latest
+%.1f%% ( %s Server: %.1f%% + Premium:%.1f%% )
+*/
+ MSG_ID_AF2 = 0xaf2,
+/*20171018 to latest
+중복된 아이템이 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to multiple same item.
+*/
+ MSG_ID_AF3 = 0xaf3,
+/*20171018 to latest
+중복된 효과가 존재하여 사용이 불가능 합니다.
+Consuming Item denied due to effect of same consumed item.
+*/
+ MSG_ID_AF4 = 0xaf4,
+/*20171018 to latest
+화면 흔들림 효과 ON
+Flicker Effect ON
+*/
+ MSG_ID_AF5 = 0xaf5,
+/*20171018 to latest
+화면 흔들림 효과 OFF
+Flicker Effect OFF
+*/
+ MSG_ID_AF6 = 0xaf6,
+/*20171018 to latest
+불법 프로그램 발견되었습니다
+Illegal Programs has been detected
+*/
+ MSG_ID_AF7 = 0xaf7,
+/*20171018 to latest
+메일 보내기
+Send Mail
+*/
+ MSG_ID_AF8 = 0xaf8,
+/*20171018 to latest
+E X P : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AF9 = 0xaf9,
+/*20171018 to latest
+DROP : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFA = 0xafa,
+/*20171018 to latest
+DEATH : %.1f%% ( basic 100.0%% VIP Bonus %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_AFB = 0xafb,
+/*20171018 to 20180928
+ 해당 태그는 이름으로 사용하실 수 없습니다.
+Name with this tag cannot be used.
+20181010 to latest
+ 해당 내용은 이름으로 사용하실 수 없습니다.
+You cannot use the tag as a name.
+*/
+ MSG_ID_AFC = 0xafc,
+/*20171018 to latest
+???? bdbac5b8c0cfb8b52098de
+Style Shop
+*/
+ MSG_ID_AFD = 0xafd,
+/*20171018 to latest
+쿠폰 없음. Cash Shop에서 아이템을 구매해 주세요.
+No serial number, Please visit the store to buy.
+*/
+ MSG_ID_AFE = 0xafe,
+/*20171018 to latest
+인벤토리에서 아이템 쿠폰 상자를 열어주세요.
+Please turn on Serial item number window box.
+*/
+ MSG_ID_AFF = 0xaff,
+/*20171018 to latest
+해당 스타일 정보를 삭제하시겠습니까?
+Bank
+*/
+ MSG_ID_B00 = 0xb00,
+/*20171018 to latest
+슬롯이 꽉 찼습니다. 내 스타일에서 캐릭터 삭제 후 사용해 주십시오.
+Slot is full, please delete a character.
+*/
+ MSG_ID_B01 = 0xb01,
+/*20171018 to latest
+비용을 지불하고 현재 스타일을 적용하시겠습니까?
+(※ 비용은 반환되지 않습니다.)
+Item cannot be restored, are you sure want to apply it?
+*/
+ MSG_ID_B02 = 0xb02,
+/*20171018 to latest
+현재 스타일을 저장하였습니다.
+Registered as the following style.
+*/
+ MSG_ID_B03 = 0xb03,
+/*20171018 to latest
+보유 Zeny 부족. 은행에 충분한 Zeny가 있습니다.
+There are plenty of golds in the bank, Please go to the bank now.
+*/
+ MSG_ID_B04 = 0xb04,
+/*20171018 to latest
+으로 이동합니다.
+moving...
+*/
+ MSG_ID_B05 = 0xb05,
+/*20171018 to latest
+해당 국가의 영공통과에 대한 허가가 나지 않았습니다.
+You are not allowed to fly over the sovereign airspace of the country.
+*/
+ MSG_ID_B06 = 0xb06,
+/*20171018 to latest
+마나로 대기불안정이 계속되어 비공정 운행이 불가능합니다.
+Airship flight is temporarily unavailable due to atmospheric instability caused by magic.
+*/
+ MSG_ID_B07 = 0xb07,
+/*20171018 to latest
+개인 비공정
+Private airship
+*/
+ MSG_ID_B08 = 0xb08,
+/*20171018 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_B09 = 0xb09,
+/*20171018 to latest
+개인 비공정 이용에 필요한 제니가 부족합니다.
+Not enough Zeny to use the private airship.
+*/
+ MSG_ID_B0A = 0xb0a,
+/*20171018 to latest
+개인 비공정 이용에 필요한 아이템이 부족합니다.
+Not enough Cans to use the private airship.
+*/
+ MSG_ID_B0B = 0xb0b,
+/*20171018 to latest
+개인 비공정을 이용할 수 있는 레벨이 아닙니다.
+You cannot meet the level to use the private airship.
+*/
+ MSG_ID_B0C = 0xb0c,
+/*20171018 to latest
+선택한 지점으론 개인비공정이 이동할 수 없습니다.
+You cannot move to the selected point by the private airship.
+*/
+ MSG_ID_B0D = 0xb0d,
+/*20171018 to latest
+현 지점에선 개인비공정을 이용할 수 없습니다.
+You cannot use the private airship where you are now.
+*/
+ MSG_ID_B0E = 0xb0e,
+/*20171018 to latest
+액세서리
+Accessory
+*/
+ MSG_ID_B0F = 0xb0f,
+/*20171018 to latest
+세컨드코스튬
+Second costume
+*/
+ MSG_ID_B10 = 0xb10,
+/*20171018 to latest
+내 스타일
+Wardrobe
+*/
+ MSG_ID_B11 = 0xb11,
+/*20171018 to latest
+염색할 수 없는 헤어스타일입니다.
+This hairstyle cannot be dyed.
+*/
+ MSG_ID_B12 = 0xb12,
+/*20171018 to latest
+화살표를 눌러 마음에 드는 스타일을 선택해 보세요.
+Press an arrow to choose the style you want.
+*/
+ MSG_ID_B13 = 0xb13,
+/*20171018 to latest
+새로운 스타일을 확인해 보세요.
+(※ 액세서리 구매 시 RODEX로 발송됩니다.)
+Come and see the new styles.
+(Purchased accessories will be sent via RODEX.)
+*/
+ MSG_ID_B14 = 0xb14,
+/*20171018 to latest
+기본 스타일
+Basic style
+*/
+ MSG_ID_B15 = 0xb15,
+/*20171018 to latest
+ 해당 스킬은 BaseLv %d 이상부터 스킬 포인트 투자가 가능합니다.
+You can level up the skill from the base Lv. %d.
+*/
+ MSG_ID_B16 = 0xb16,
+/*20171018 to latest
+해당 특수기호는 이름에 사용하실 수 없습니다.
+Special symbol can't be used in name
+*/
+ MSG_ID_B17 = 0xb17,
+/*20171018 to latest
+MHP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxHP is to low to use this skill
+*/
+ MSG_ID_B18 = 0xb18,
+/*20171018 to latest
+MSP가 너무 낮아, 해당 스킬을 사용할 수 없습니다
+MaxSP is to low to use this skill
+*/
+ MSG_ID_B19 = 0xb19,
+/*20171018 to latest
+아이템 비교하기
+Compare items
+*/
+ MSG_ID_B1A = 0xb1a,
+/*20171018 to latest
+아이템 버리기 잠금
+Drop lock
+*/
+ MSG_ID_B1B = 0xb1b,
+/*20171018 to latest
+스크린샷 파일이 첨부 되지 않았습니다.
+Screenshots are not attached
+*/
+ MSG_ID_B1C = 0xb1c,
+/*20171018 to latest
+Twitter
+*/
+ MSG_ID_B1D = 0xb1d,
+/*20171018 to latest
+일반
+General
+*/
+ MSG_ID_B1E = 0xb1e,
+/*20171018 to latest
+공지
+Notice
+*/
+ MSG_ID_B1F = 0xb1f,
+/*20171018 to latest
+반송
+Clear
+*/
+ MSG_ID_B20 = 0xb20,
+/*20171018 to latest
+새로고침
+Refresh
+*/
+ MSG_ID_B21 = 0xb21,
+/*20171018 to latest
+%d분
+%d minute
+*/
+ MSG_ID_B22 = 0xb22,
+/*20171018 to latest
+%d시간
+%d hour
+*/
+ MSG_ID_B23 = 0xb23,
+/*20171018 to latest
+%d일
+%d day
+*/
+ MSG_ID_B24 = 0xb24,
+/*20171018 to latest
+반송됨
+Returned
+*/
+ MSG_ID_B25 = 0xb25,
+/*20171018 to latest
+선택한 메일을 삭제하시겠습니까?
+Do you want to delete the message?
+*/
+ MSG_ID_B26 = 0xb26,
+/*20171018 to latest
+위치표시
+Show information
+*/
+ MSG_ID_B27 = 0xb27,
+/*20171018 to latest
+확대
+Zoom In
+*/
+ MSG_ID_B28 = 0xb28,
+/*20171018 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_B29 = 0xb29,
+/*20171018 to latest
+맵보기
+Maximize
+*/
+ MSG_ID_B2A = 0xb2a,
+/*20171018 to latest
+월드보기
+Show world map
+*/
+ MSG_ID_B2B = 0xb2b,
+/*20171018 to latest
+아이템 소지 종류수
+Total possession item type
+*/
+ MSG_ID_B2C = 0xb2c,
+/*20171018 to latest
+/minimap
+*/
+ MSG_ID_B2D = 0xb2d,
+/*20171018 to latest
+미니맵 버튼을 표시합니다
+Show minimap buttons
+*/
+ MSG_ID_B2E = 0xb2e,
+/*20171018 to latest
+미니맵 버튼을 표시하지 않습니다
+Hide minimap buttons
+*/
+ MSG_ID_B2F = 0xb2f,
+/*20171018 to latest
+길드 접속자 정렬
+Show guild member login status
+*/
+ MSG_ID_B30 = 0xb30,
+/*20171018 to latest
+친밀도 : %s
+Intimacy: %s
+*/
+ MSG_ID_B31 = 0xb31,
+/*20171018 to latest
+확인 전
+Confirmation
+*/
+ MSG_ID_B32 = 0xb32,
+/*20171018 to latest
+파티 이름
+Team name
+*/
+ MSG_ID_B33 = 0xb33,
+/*20171018 to latest
+파티장
+Leader
+*/
+ MSG_ID_B34 = 0xb34,
+/*20171018 to latest
+제한 시간 초과. 클라이언트를 종료합니다.
+Time limit exceeded. Closing the client
+*/
+ MSG_ID_B35 = 0xb35,
+/*20171018 to latest
+잘못된 입력입니다. 클라이언트를 종료합니다.
+Input error. Closing the client
+*/
+ MSG_ID_B36 = 0xb36,
+/*20171018 to latest
+정답 입니다. 보상으로 소정의 버프가 주어집니다.
+Incorrect input. A small buff has given to you
+*/
+ MSG_ID_B37 = 0xb37,
+/*20171018 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_B38 = 0xb38,
+/*20171018 to latest
+입력한 답이 [%s]가 맞습니까?
+Your entered answer is [%s]. Is it right?
+*/
+ MSG_ID_B39 = 0xb39,
+/*20171018 to latest
+선택된 이미지가 없습니다.
+Icon is unchecked
+*/
+ MSG_ID_B3A = 0xb3a,
+/*20171018 to latest
+잘못된 입력입니다. (남은 기회 %d번)
+Incorrect input (Remaining chance: %d)
+*/
+ MSG_ID_B3B = 0xb3b,
+/*20171018 to latest
+총 %d명의 유저를 신고하시겠습니까?
+Do you want to announce %d to player?
+*/
+ MSG_ID_B3C = 0xb3c,
+/*20171018 to latest
+유저에게 메시지를 보냈습니다.
+Message has been sent to player
+*/
+ MSG_ID_B3D = 0xb3d,
+/*20171018 to latest
+불법 프로그램 단속에 필요한 데이터가 미등록 상태입니다.
+Needed Data for Query illegal software are not signed.
+*/
+ MSG_ID_B3E = 0xb3e,
+/*20171018 to latest
+이미 매크로 감시중인 유저입니다.
+The player is being monitored.
+*/
+ MSG_ID_B3F = 0xb3f,
+/*20171018 to latest
+매크로가 등록되었습니다..
+Already signed in investigation system.
+*/
+ MSG_ID_B40 = 0xb40,
+/*20171018 to latest
+이미지 등록에 실패하였습니다.
+Failed to store icon.
+*/
+ MSG_ID_B41 = 0xb41,
+/*20171018 to latest
+정답 등록에 실패하였습니다.
+Failed to store replied answer.
+*/
+ MSG_ID_B42 = 0xb42,
+/*20171018 to latest
+안녕하세요. 불법프로그램 단속중입니다.
+Hello, illegal software is being monitored.
+*/
+ MSG_ID_B43 = 0xb43,
+/*20171018 to latest
+지정된 시간내에 아래의 문자를 입력해주세요.
+Please enter the text below within the specified time.
+*/
+ MSG_ID_B44 = 0xb44,
+/*20171018 to latest
+3회 오류시 운영정책에 의거하여 영구블록됩니다.
+According to game regulation, when you enter the wrong text three times, you will get banned.
+*/
+ MSG_ID_B45 = 0xb45,
+/*20171018 to latest
+남은 횟수 : %d
+Remaining chance : %d
+*/
+ MSG_ID_B46 = 0xb46,
+/*20171018 to latest
+캐릭터
+Role
+*/
+ MSG_ID_B47 = 0xb47,
+/*20171018 to latest
+범위
+Range
+*/
+ MSG_ID_B48 = 0xb48,
+/*20171018 to latest
+캐릭터 선택은 좌클릭으로 합니다.
+You use the left mouse button to specify the role
+*/
+ MSG_ID_B49 = 0xb49,
+/*20171018 to latest
+범위 선택은 우클릭으로 합니다.
+You use the left mouse button to specify the range
+*/
+ MSG_ID_B4A = 0xb4a,
+/*20171018 to latest
+범위 크기를 지정하기 위해서는 엔터를 입력해주세요
+Not a valid range, please press Enter
+*/
+ MSG_ID_B4B = 0xb4b,
+/*20171018 to latest
+E X P : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4C = 0xb4c,
+/*20171018 to latest
+DROP : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4D = 0xb4d,
+/*20171018 to latest
+DEATH : %.1f%% ( basic %.1f%% %s %.1f%%)
+*/
+ MSG_ID_B4E = 0xb4e,
+/*20171018 to latest
+변경된 캐릭명으로 발송했습니다. 변경된 캐릭명 : %s
+The role name will be sent: %s
+*/
+ MSG_ID_B4F = 0xb4f,
+/*20171018 to latest
+합성에 필요한 재료
+Synthesis of the required materials
+*/
+ MSG_ID_B50 = 0xb50,
+/*20171018 to latest
+조합 재료가 부족해서 조합할 수 없습니다.
+Insufficient synthesis materials
+*/
+ MSG_ID_B51 = 0xb51,
+/*20171018 to latest
+해당 재료는 %d개가 필요합니다.
+Required material %d ea.
+*/
+ MSG_ID_B52 = 0xb52,
+/*20171018 to latest
+제련도가 낮아서 조합할 수 없습니다.
+Refine value is to low for synthesis
+*/
+ MSG_ID_B53 = 0xb53,
+/*20171018 to latest
+모험가중개소에 등록 하시겠습니까?
+Do you want to sign in to the adventurers?
+*/
+ MSG_ID_B54 = 0xb54,
+/*20171018 to latest
+자유롭게 코멘트를 남겨보세요.
+Please leave a message
+*/
+ MSG_ID_B55 = 0xb55,
+/*20171018 to latest
+그림에 보이는 문자를 입력해주세요.
+Please enter the text on the graph
+*/
+ MSG_ID_B56 = 0xb56,
+/*20171018 to latest
+%d초 남았습니다
+%d second left
+*/
+ MSG_ID_B57 = 0xb57,
+/*20171018 to latest
+OTP 인증번호 6자리를 입력해 주세요
+Please enter your 6 identification number.
+*/
+ MSG_ID_B58 = 0xb58,
+/*20171018 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_B59 = 0xb59,
+/*20171018 to latest
+6자리의 숫자가 아닙니다. 다시 확인해 주세요
+It's not a 6 identification number. Please try again
+*/
+ MSG_ID_B5A = 0xb5a,
+/*20171018 to latest
+이미 삭제된 메일입니다.
+The message has been deleted
+*/
+ MSG_ID_B5B = 0xb5b,
+/*20171018 to latest
+개인 비공정으로 이동할 지역을 선택해주세요.
+Please select the area where the private airship will move
+*/
+ MSG_ID_B5C = 0xb5c,
+/*20171018 to latest
+E X P : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5D = 0xb5d,
+/*20171018 to latest
+DROP : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5E = 0xb5e,
+/*20171018 to latest
+DEATH : %d%% ( basic 100.0%% %s %d%%)
+*/
+ MSG_ID_B5F = 0xb5f,
+/*20171018 to latest
+목적지로 이동중입니다.
+Move to the destination
+*/
+ MSG_ID_B60 = 0xb60,
+/*20171018 to latest
+[%s] 파일이 존재하지 않아 default AI 로 동작합니다
+The [%s] is not present, the default AI will be used instead.
+*/
+ MSG_ID_B61 = 0xb61,
+/*20171018 to latest
+ %.1f%% ( Basic 100.0%% + Premium %.1f%% + %s %.1f%%)
+*/
+ MSG_ID_B62 = 0xb62,
+/*20171018 to latest
+이 자리에 노점을 세우시겠습니까?
+Would you like to open a shop at this location?
+*/
+ MSG_ID_B63 = 0xb63,
+/*20171018 to latest
+도람족은 해당 의상을 입을 수 없습니다.
+Doram race can't wear this clothes
+*/
+ MSG_ID_B64 = 0xb64,
+/*20171018 to latest
+판매 노점에서 거래한 아이템이 로덱스로 배송되었습니다.
+Props open-air store sales will be traded in RODEX
+*/
+ MSG_ID_B65 = 0xb65,
+/*20171018 to latest
+30,000 z
+*/
+ MSG_ID_B66 = 0xb66,
+/*20171018 to latest
+말랑도 특산 통조림 100개
+Malangdo Special Can 100 pc
+*/
+ MSG_ID_B67 = 0xb67,
+/*20171018 to latest
+무게가 80%를 초과하여 진행할 수 없습니다.
+Cannot carry anymore because weight limit over 80%
+*/
+ MSG_ID_B68 = 0xb68,
+/*20171018 to latest
+판매되지 못한 상품이 로덱스로 배송되었습니다.
+Unsold items are sent to RODEX
+*/
+ MSG_ID_B69 = 0xb69,
+/*20171018 to latest
+장착 모습
+Preview
+*/
+ MSG_ID_B6A = 0xb6a,
+/*20171018 to latest
+길드마스터 위임
+Assign Guild Leader
+*/
+ MSG_ID_B6B = 0xb6b,
+/*20171018 to latest
+정말로 %s님께 길드마스터를 위임하시겠습니까? 위임 후 당신의 지위는 %s님과 지위가 바뀌게 됩니다.
+Are sure want to assign %s as guild leader? After assigned your position will become %s
+*/
+ MSG_ID_B6C = 0xb6c,
+/*20171018 to latest
+철회
+Cancel
+*/
+ MSG_ID_B6D = 0xb6d,
+/*20171018 to latest
+노점을 철수하시겠습니까?
+Do you want to close the shop?
+*/
+ MSG_ID_B6E = 0xb6e,
+/*20171018 to latest
+%02d일 %02d시간 %02d분 %02d초
+%02d day %02d hour %02d minute %02d second
+*/
+ MSG_ID_B6F = 0xb6f,
+/*20171018 to latest
+접속불가
+Unable to sign in
+*/
+ MSG_ID_B70 = 0xb70,
+/*20171018 to latest
+접속가능인원을 초과하여 접속이 불가능 합니다.
+Unable to sign in because the maximum number of sign-in is exceeded
+*/
+ MSG_ID_B71 = 0xb71,
+/*20171018 to latest
+노점을 설치할 위치를 선택해주세요.
+Please select a location for your shop
+*/
+ MSG_ID_B72 = 0xb72,
+/*20171018 to latest
+펫 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+Pet name will be changed to ^0000ff^0000ff %s^000000^000000, do you want to continue?
+*/
+ MSG_ID_B73 = 0xb73,
+/*20171018 to latest
+거래 일시 :
+Trade date :
+*/
+ MSG_ID_B74 = 0xb74,
+/*20171018 to latest
+거래 아이템 :
+Trade item :
+*/
+ MSG_ID_B75 = 0xb75,
+/*20171018 to latest
+거래 수량 :
+Trade quantity :
+*/
+ MSG_ID_B76 = 0xb76,
+/*20171018 to latest
+거래 단가 :
+Trade price :
+*/
+ MSG_ID_B77 = 0xb77,
+/*20171018 to latest
+거래 금액 :
+Total trade :
+*/
+ MSG_ID_B78 = 0xb78,
+/*20171018 to latest
+노점 판매 아이템
+Open vending sales agent
+*/
+ MSG_ID_B79 = 0xb79,
+/*20171018 to latest
+노점 구매 아이템
+Open vending purchase agent
+*/
+ MSG_ID_B7A = 0xb7a,
+/*20171018 to latest
+판매 노점 아르바이트 종료
+Close vending sales agent
+*/
+ MSG_ID_B7B = 0xb7b,
+/*20171018 to latest
+구매 노점 아르바이트 종료
+Close vending purchase agent
+*/
+ MSG_ID_B7C = 0xb7c,
+/*20171018 to latest
+남은 금액:
+Balance:
+*/
+ MSG_ID_B7D = 0xb7d,
+/*20171018 to latest
+아이템 리스트:
+Item list:
+*/
+ MSG_ID_B7E = 0xb7e,
+/*20171018 to latest
+노점 아르바이트생
+Vending agent
+*/
+ MSG_ID_B7F = 0xb7f,
+/*20171018 to latest
+반환 아이템:
+Returned item:
+*/
+ MSG_ID_B80 = 0xb80,
+/*20171018 to latest
+반환 수량:
+Returned quantity:
+*/
+ MSG_ID_B81 = 0xb81,
+/*20171018 to latest
+반환 일시:
+Returned date:
+*/
+ MSG_ID_B82 = 0xb82,
+/*20171018 to latest
+구매 노점에서 거래한 금액이 로덱스로 배송되었습니다
+Total trade will be sent to RODEX
+*/
+ MSG_ID_B83 = 0xb83,
+/*20171018 to latest
+사용할 수 없는 이름입니다.
+Name isn't available
+*/
+ MSG_ID_B84 = 0xb84,
+/*20171018 to latest
+상품이 도착했습니다.
+Item has been delivered
+*/
+ MSG_ID_B85 = 0xb85,
+/*20171018 to latest
+구입해주셔서 감사합니다.
+Thank you for purchasing
+*/
+ MSG_ID_B86 = 0xb86,
+/*20171018 to latest
+NPC에게 아이템을 판매하지 않습니다.
+Press again to unlock
+*/
+ MSG_ID_B87 = 0xb87,
+/*20171018 to latest
+아이템 판매 잠금
+Lock from NPC selling
+*/
+ MSG_ID_B88 = 0xb88,
+/*20171018 to latest
+근처에서 소환가능 위치를 찾을수 없습니다.
+There is no callable location nearby
+*/
+ MSG_ID_B89 = 0xb89,
+/*20171018 to latest
+전체 화면 캡쳐
+Capture full screens
+*/
+ MSG_ID_B8A = 0xb8a,
+/*20171018 to latest
+부분 화면 캡쳐
+Capture part of screen
+*/
+ MSG_ID_B8B = 0xb8b,
+/*20171018 to latest
+보내기
+Send
+*/
+ MSG_ID_B8C = 0xb8c,
+/*20171018 to latest
+가족 분과 담당자
+Family Affairs agent
+*/
+ MSG_ID_B8D = 0xb8d,
+/*20171018 to latest
+가족 사항 변동 안내
+Acknowledgement of family member registrations.
+*/
+ MSG_ID_B8E = 0xb8e,
+/*20171018 to latest
+안녕하십니까.
+
+금일 "%s"님과 "%s"님의 자녀인 "%s"님이 독립하여 단독 세대를 구성하였습니다.
+
+이에 서면으로 안내를 드립니다.
+
+가족 관계 확인을 원하시는 분은 프론테라 동사무소의 담당 직원에게 문의하시기 바랍니다.
+
+감사합니다.
+Dear whom it may concern.
+
+ Today, \"%s\" and \"%s\" 's son/daughter \"%s\" has fully separated and independent from your member of family.
+
+Hereat, we inform you in writing.
+
+Please contact to Prontera Family Affairs if you have any enquiries.
+
+Thank you.
+*/
+ MSG_ID_B8F = 0xb8f,
+/*20171018 to latest
+장착
+Equip
+*/
+ MSG_ID_B90 = 0xb90,
+/*20171018 to latest
+이미지 없음
+No image
+*/
+ MSG_ID_B91 = 0xb91,
+/*20171018 to latest
+[%s]은(는) 현재 호출을 차단한 상태입니다.
+[%s] is blocking Call Massage.
+*/
+ MSG_ID_B92 = 0xb92,
+/*20171018 to latest
+현재 공성전이 진행중이므로, 길드마스터를 위임 할 수 없습니다.
+Currently in WoE hours, unable to delegate Guild leader
+*/
+ MSG_ID_B93 = 0xb93,
+/*20171018 to latest
+현재 길드장 위임을 받은지 만 하루가 지나지 않아, 길드장을 위임할 수 없습니다.
+You have to wait for one day before delegating a new Guild leader
+*/
+ MSG_ID_B94 = 0xb94,
+/*20171018 to latest
+아이가 되면 전승을 할 수 없고 스텟의 제한이 있으며 HP와 SP가 줄어듭니다.
+그래도 괜찮습니까?
+When adopted, character will not able to transcend, maximum stats will be limited, MaxHP and MaxSP will be reduced.
+Are you sure you want to continue?
+*/
+ MSG_ID_B95 = 0xb95,
+/*20171018 to latest
+제련
+Refining
+*/
+ MSG_ID_B96 = 0xb96,
+/*20171018 to latest
+대장장이의 축복을 사용중입니다.
+Use Blacksmith's Blessing
+*/
+ MSG_ID_B97 = 0xb97,
+/*20171018 to latest
+제니가 부족합니다.
+Insufficient zeny
+*/
+ MSG_ID_B98 = 0xb98,
+/*20171018 to latest
+대장장이의 축복 개수가 부족합니다.
+Not enough Blacksmith's Blessing
+*/
+ MSG_ID_B99 = 0xb99,
+/*20171018 to latest
+해당 장비는 제련이 불가능합니다.
+This equipment can not be refined
+*/
+ MSG_ID_B9A = 0xb9a,
+/*20171018 to latest
+제련 성공
+Upgrade success!
+*/
+ MSG_ID_B9B = 0xb9b,
+/*20171018 to latest
+제련 실패
+Upgrade failed!
+*/
+ MSG_ID_B9C = 0xb9c,
+/*20171018 to latest
+돌아가기
+Back
+*/
+ MSG_ID_B9D = 0xb9d,
+/*20171018 to latest
+성공
+Success
+*/
+ MSG_ID_B9E = 0xb9e,
+/*20171018 to latest
+원래대로
+Return
+*/
+ MSG_ID_B9F = 0xb9f,
+/*20171018 to latest
+씨와의
+With Mr/Miss
+*/
+ MSG_ID_BA0 = 0xba0,
+/*20171018 to latest
+호문클루스의 이름을 ^0000ff^0000ff %s^000000^000000 로 수정합니다. 계속 하시겠습니까?
+The Homunculus's name will be changed to^0000ff^0000ff %s^000000^000000, Are you sure?
+*/
+ MSG_ID_BA1 = 0xba1,
+/*20171018 to latest
+호출이 허용된 상태입니다. (호출 기능 ON)
+Call function is ON
+*/
+ MSG_ID_BA2 = 0xba2,
+/*20171018 to latest
+호출이 차단된 상태입니다. (호출 기능 OFF)
+Call function is OFF
+*/
+ MSG_ID_BA3 = 0xba3,
+/*20171018 to latest
+호출 메시지 표시
+Display Call messages
+*/
+ MSG_ID_BA4 = 0xba4,
+/*20171018 to latest
+해당 캐릭터가 현재 노점 아이템을 사용 중이므로 삭제할 수 없습니다.
+This character is currently opening a shop and can't be deleted
+*/
+ MSG_ID_BA5 = 0xba5,
+/*20171018 to latest
+이미 동일한 노점 NPC가 설치 중입니다.
+The same vend shop NPC has been set up
+*/
+ MSG_ID_BA6 = 0xba6,
+/*20171018 to latest
+노점을 설치할 수 없는 위치입니다.
+Opening shop is not allowed on this location
+*/
+ MSG_ID_BA7 = 0xba7,
+/*20171018 to latest
+다른 캐릭터가 있는 위치에는 노점을 설치할 수 없습니다.
+Opening shop is not allowed when there is other character
+*/
+ MSG_ID_BA8 = 0xba8,
+/*20171018 to latest
+펫 먹이주기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+Failed to feed pet, please close RODEX window
+*/
+ MSG_ID_BA9 = 0xba9,
+/*20171018 to latest
+장비 세트 설정
+Set item setting
+*/
+ MSG_ID_BAA = 0xbaa,
+/*20171018 to latest
+장착 하기
+Equip
+*/
+ MSG_ID_BAB = 0xbab,
+/*20171018 to latest
+제련 실패시 장비가 사라집니다.
+Equipment will dissapear when refine fails
+*/
+ MSG_ID_BAC = 0xbac,
+/*20171018 to latest
+제련 실패시 장비의 제련도가 내려갑니다.
+Equipment's refine level will decreased when refine fails
+*/
+ MSG_ID_BAD = 0xbad,
+/*20171018 to latest
+제련 실패시 장비의 제련도가 내려가거나 사라질 수 있습니다.
+Equipment will dissapear or refine level will decreased when refine fails
+*/
+ MSG_ID_BAE = 0xbae,
+/*20171018 to latest
+제련 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+You cannot use RODEX while refining. RODEX has closed.
+*/
+ MSG_ID_BAF = 0xbaf,
+/*20171018 to latest
+제련 중에는 로덱스를 사용할 수 없습니다.
+You cannot use RODEX while refining.
+*/
+ MSG_ID_BB0 = 0xbb0,
+/*20171018 to latest
+제련을 진행하려면 다른 창을 닫아주세요.
+Please close other windows to continue.
+*/
+ MSG_ID_BB1 = 0xbb1,
+/*20171018 to latest
+오오라가 정상적으로 표시됩니다 [오오라 ON]
+Turn On Aura [Aura ON]
+*/
+ MSG_ID_BB2 = 0xbb2,
+/*20171018 to latest
+오오라가 표시되지 않습니다 [오오라 OFF]
+Turn Off Aura [Auta OFF]
+*/
+ MSG_ID_BB3 = 0xbb3,
+/*20171018 to latest
+오오라가 Off 상태입니다. Off 를 해제하고 시도해 주세요
+Aura is turned off. Please turn it on and try again
+*/
+ MSG_ID_BB4 = 0xbb4,
+/*20171018 to latest
+스킬 발동시 최소 %d개의 탄알이 필요합니다.
+You need %d bullet(s) to activate the skill.
+*/
+ MSG_ID_BB5 = 0xbb5,
+/*20171018 to latest
+장비 세트를 변경하시겠습니까?
+Do you want to change the equipment set?
+*/
+ MSG_ID_BB6 = 0xbb6,
+/*20171018 to latest
+죽은 상태에서는 할 수 없습니다
+You can not do it while you are dead.
+*/
+ MSG_ID_BB7 = 0xbb7,
+/*20171018 to latest
+캐스팅 도중에는 할 수 없습니다
+You can not do it while casting
+*/
+ MSG_ID_BB8 = 0xbb8,
+/*20171018 to latest
+거래 도중에는 할 수 없습니다
+You can not do it while trading
+*/
+ MSG_ID_BB9 = 0xbb9,
+/*20171018 to latest
+노점 개설 도중에는 할 수 없습니다
+You can not do it while opening vendor
+*/
+ MSG_ID_BBA = 0xbba,
+/*20171018 to latest
+NPC 이용중에는 할 수 없습니다
+You can not do it while using NPC
+*/
+ MSG_ID_BBB = 0xbbb,
+/*20171018 to latest
+채팅방 이용중에는 할 수 없습니다
+You can not do it while using chatting room
+*/
+ MSG_ID_BBC = 0xbbc,
+/*20171018 to latest
+파티원 전원이 접속 상태가 아닙니다.
+Party members are not connected.
+*/
+ MSG_ID_BBD = 0xbbd,
+/*20171018 to latest
+스킬 발동시 최소 %d개의 화살이 필요합니다.
+You need %d arrow(s) to activate the skill.
+*/
+ MSG_ID_BBE = 0xbbe,
+/*20171018 to latest
+아이템 정렬
+Align items
+*/
+ MSG_ID_BBF = 0xbbf,
+/*20171018 to latest
+아이템을 버리려면 장비 설정 창을 닫아주세요.
+Please close item setting window to dump item.
+*/
+ MSG_ID_BC0 = 0xbc0,
+/*20171018 to latest
+교체 할 수 있는 아이템이 없습니다.
+There is no item to replace.
+*/
+ MSG_ID_BC1 = 0xbc1,
+/*20171018 to latest
+삭제된 캐릭터
+Deleted character
+*/
+ MSG_ID_BC2 = 0xbc2,
+/*20171018 to latest
+%Y.%m.%d
+*/
+ MSG_ID_BC3 = 0xbc3,
+/*20171018 to latest
+접속일: %s
+Access date: %s
+*/
+ MSG_ID_BC4 = 0xbc4,
+/*20171018 to latest
+제련 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+You can not use bank while refining. Bank has closed.
+*/
+ MSG_ID_BC5 = 0xbc5,
+/*20171018 to latest
+제련 중에는 은행을 사용할 수 없습니다.
+You can not use bank while refining.
+*/
+ MSG_ID_BC6 = 0xbc6,
+/*20171018 to latest
+장비 세트 설정 중인 아이템입니다.
+The item has bind to set equipment.
+*/
+ MSG_ID_BC7 = 0xbc7,
+/*20171018 to latest
+인간
+Human
+*/
+ MSG_ID_BC8 = 0xbc8,
+/*20171018 to latest
+검사, 법사, 상인, 복사, 도둑, 궁수
+Swordman, Mage, Merchant, Acolyte, Thief, Archer
+*/
+ MSG_ID_BC9 = 0xbc9,
+/*20171018 to latest
+도람
+Doram
+*/
+ MSG_ID_BCA = 0xbca,
+/*20171018 to latest
+소환사
+Summoner
+*/
+ MSG_ID_BCB = 0xbcb,
+/*20171018 to latest
+미드가르드 대륙의 대표 종족. 무한한 잠재력과 뛰어난 적응력으로 문제 해결에 탁월한 것이 특징이다.
+Delegate race of Midgard. Very talented race to solve a problem with inifite potential and great adaptability.
+*/
+ MSG_ID_BCC = 0xbcc,
+/*20171018 to latest
+파-스타 대륙의 대표적인 종족 중 하나로, 선천적으로 호기심이 강하고 발랄한 성격을 지녔다.
+One of delegate race of Far-star continent with natural born curiosity and sparky character.
+*/
+ MSG_ID_BCD = 0xbcd,
+/*20171018 to latest
+소지 한계량이 70%를 초과하거나, 인벤토리에 10칸 이상의 여유 공간이 부족한 상태입니다.
+Weight limit has reached toover 70%. Or less then 10 invenrory space.
+*/
+ MSG_ID_BCE = 0xbce,
+/*20171018 to latest
+C
+EUR
+*/
+ MSG_ID_BCF = 0xbcf,
+/*20171018 to latest
+C
+EUR
+*/
+ MSG_ID_BD0 = 0xbd0,
+/*20171018 to latest
+다른 일을 하는 중입니다.
+Doing in other activity.
+*/
+ MSG_ID_BD1 = 0xbd1,
+/*20171018 to latest
+오버히트 리미트 : %d
+Overheat limit : %d
+*/
+ MSG_ID_BD2 = 0xbd2,
+/*20171018 to latest
+메모리얼 던전 이용 중엔 초대 및 탈퇴가 되지 않습니다.
+You cannot invite or withdraw while in memorial dungeon.
+*/
+ MSG_ID_BD3 = 0xbd3,
+/*20171018 to latest
+비속어가 포함되어있습니다.
+다시 한번 확인해주세요.
+Expletive has detected.
+Please check again.
+*/
+ MSG_ID_BD4 = 0xbd4,
+/*20171018 to latest
+아이디는 %d자 이상 입력해주세요. 사용자 계정이 없으신분들은 왼쪽 하단의 [신청] 버튼을 눌러 계정을 만드시기 바랍니다.
+Please enter over %d characters. If you don't have user account, please click [Register] button on the bottom left.
+*/
+ MSG_ID_BD5 = 0xbd5,
+/*20171018 to latest
+비밀번호는 %d자 이상 입력해주세요.
+Please enter the password over %d characters.
+*/
+ MSG_ID_BD6 = 0xbd6,
+/*20171018 to latest
+진행중이던 작업을 종료후 다시 시도하세요.
+Please finish your current work and try it again.
+*/
+ MSG_ID_BD7 = 0xbd7,
+/*20171018 to latest
+%.1f%% (PC방 %.1f%% + TPLUS %.1f%% + %s서버 %.1f%%)
+%.1f%% (Internet-Cafe %.1f%% + TPLUS %.1f%% + %sServer %.1f%%)
+*/
+ MSG_ID_BD8 = 0xbd8,
+/*20171018 to latest
+아이템을 등록할 수 없습니다
+The item cannot be registered.
+*/
+ MSG_ID_BD9 = 0xbd9,
+/*20171018 to latest
+/100
+/300
+*/
+ MSG_ID_BDA = 0xbda,
+/*20171018 to latest
+/2000
+/4000
+*/
+ MSG_ID_BDB = 0xbdb,
+/*20171018 to latest
+https://member.gnjoy.com.tw/mRO_SecPwd.aspx
+*/
+ MSG_ID_BDC = 0xbdc,
+/*20171018 to latest
+등록할 emblem이 존재하지 않습니다. emblem 폴더에 파일을 넣고 시도해 주세요
+The emblem you want to register does not exist. Insert it in the emblem file and try again
+*/
+ MSG_ID_BDD = 0xbdd,
+/*20171018 to latest
+라그나로크
+Ragnarok Ragnarok
+*/
+ MSG_ID_BDE = 0xbde,
+/*20171018 to latest
+스크린샷에 자신 이외의 캐릭터명이 표시되는 경우나 채팅창에 자신 이외의 캐릭터 대화가 표시되는 경우, 해당 사용자에게 반드시 양해를 구한 후 사용 해 주시기 바랍니다.
+If your screenshot or chat box includes other users besides yourself, first ask permission from the other users before using it.
+*/
+ MSG_ID_BDF = 0xbdf,
+/*20171018 to latest
+현재 상태에선 장비를 교체할 수 없습니다
+You cannot change equipment in current condition
+*/
+ MSG_ID_BE0 = 0xbe0,
+/*20171018 to latest
+해당 유저의 이름을 가져오고 있습니다
+Getting the user's name
+*/
+ MSG_ID_BE1 = 0xbe1,
+/*20171018 to latest
+해당 메시지는 사용 할 수 없는 내용을 포함하고 있습니다.
+This message includes contents you are not able to use.
+*/
+ MSG_ID_BE2 = 0xbe2,
+/*20171018 to latest
+아이템 구입에 실패하였습니다.
+Failed to purchase item.
+*/
+ MSG_ID_BE3 = 0xbe3,
+/*20171018 to latest
+신분증번호 하위 7자리가 일치하지 않습니다.
+The lower numbers of the identification number does not match.
+*/
+ MSG_ID_BE4 = 0xbe4,
+/*20171018 to latest
+닫기
+Close
+*/
+ MSG_ID_BE5 = 0xbe5,
+/*20171018 to latest
+규칙
+Rule
+*/
+ MSG_ID_BE6 = 0xbe6,
+/*20171018 to latest
+1회 구매
+Purchase 1x
+*/
+ MSG_ID_BE7 = 0xbe7,
+/*20171018 to latest
+10회 구매
+Purchase 10x
+*/
+ MSG_ID_BE8 = 0xbe8,
+/*20171018 to latest
+100회 구매
+Purchase 100x
+*/
+ MSG_ID_BE9 = 0xbe9,
+/*20171018 to latest
+1등 당첨
+Win 1st prize
+*/
+ MSG_ID_BEA = 0xbea,
+/*20171018 to latest
+2등 당첨
+Win 2nd prize
+*/
+ MSG_ID_BEB = 0xbeb,
+/*20171018 to latest
+3등 당첨
+Win 3rd prize
+*/
+ MSG_ID_BEC = 0xbec,
+/*20171018 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BED = 0xbed,
+/*20171018 to latest
+현재 사용하지 않음
+Currently not in use
+*/
+ MSG_ID_BEE = 0xbee,
+/*20171018 to latest
+제니 로또 당첨자
+Zeny Lottery winner
+*/
+ MSG_ID_BEF = 0xbef,
+/*20171018 to latest
+복권 구매 금액
+Lottery purchase amount
+*/
+ MSG_ID_BF0 = 0xbf0,
+/*20171018 to latest
+참여 캐릭터
+Participating character
+*/
+ MSG_ID_BF1 = 0xbf1,
+/*20171018 to latest
+1등
+1st Price
+*/
+ MSG_ID_BF2 = 0xbf2,
+/*20171018 to latest
+2등
+2nd Price
+*/
+ MSG_ID_BF3 = 0xbf3,
+/*20171018 to latest
+3등
+3rd Price
+*/
+ MSG_ID_BF4 = 0xbf4,
+/*20171018 to latest
+구매 보상 아이템
+Purchase Reward Item
+*/
+ MSG_ID_BF5 = 0xbf5,
+/*20171018 to latest
+^1a1a1a복권 ^b%d개^/b를
+^4435b2%dZeny^1a1a1a로
+구매하시겠습니까?
+^1a1a1a Do you want to purchase ^b%d lottery tickets for
+^4435b2%dZeny^1a1a1a?
+*/
+ MSG_ID_BF6 = 0xbf6,
+/*20171018 to latest
+복권을 성공적으로 구매하였습니다.
+You have successfully purchased the lottery ticket.
+*/
+ MSG_ID_BF7 = 0xbf7,
+/*20171018 to latest
+소지 제니가 부족하여 복권을 구매 할 수 없습니다.
+Not enough Zeny to purchase lottey ticket.
+*/
+ MSG_ID_BF8 = 0xbf8,
+/*20171018 to latest
+최대 복권 구매 횟수는 1000회를 초과 할 수 없습니다.
+You are only able to purchase the tickets upto 1000 times.
+*/
+ MSG_ID_BF9 = 0xbf9,
+/*20171018 to latest
+예
+Yes
+*/
+ MSG_ID_BFA = 0xbfa,
+/*20171018 to latest
+아니요
+No
+*/
+ MSG_ID_BFB = 0xbfb,
+/*20171018 to latest
+HP
+*/
+ MSG_ID_BFC = 0xbfc,
+/*20171018 to latest
+SP
+*/
+ MSG_ID_BFD = 0xbfd,
+/*20171018 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFE = 0xbfe,
+/*20171018 to latest
+Lv
+Lv.
+*/
+ MSG_ID_BFF = 0xbff,
+/*20171018 to latest
+Exp
+*/
+ MSG_ID_C00 = 0xc00,
+/*20171018 to latest
+ all on
+*/
+ MSG_ID_C01 = 0xc01,
+/*20171018 to latest
+Play Replay Flie
+Start replay
+*/
+ MSG_ID_C02 = 0xc02,
+/*20171018 to latest
+P
+*/
+ MSG_ID_C03 = 0xc03,
+/*20171018 to latest
+Total
+*/
+ MSG_ID_C04 = 0xc04,
+/*20171018 to latest
+Basicinfo
+*/
+ MSG_ID_C05 = 0xc05,
+/*20171018 to latest
+Equip
+Equipment
+*/
+ MSG_ID_C06 = 0xc06,
+/*20171018 to latest
+Item
+Items
+*/
+ MSG_ID_C07 = 0xc07,
+/*20171018 to latest
+Skill
+Skills
+*/
+ MSG_ID_C08 = 0xc08,
+/*20171018 to latest
+Guild
+*/
+ MSG_ID_C09 = 0xc09,
+/*20171018 to latest
+Party
+*/
+ MSG_ID_C0A = 0xc0a,
+/*20171018 to latest
+Chatting
+Chat
+*/
+ MSG_ID_C0B = 0xc0b,
+/*20171018 to latest
+Shortcut
+Hotkeys
+*/
+ MSG_ID_C0C = 0xc0c,
+/*20171018 to latest
+Status
+*/
+ MSG_ID_C0D = 0xc0d,
+/*20171018 to latest
+ALL
+*/
+ MSG_ID_C0E = 0xc0e,
+/*20171018 to latest
+User Defined File Name
+Custom file name
+*/
+ MSG_ID_C0F = 0xc0f,
+/*20171018 to latest
+Repeated File Check
+Check file
+*/
+ MSG_ID_C10 = 0xc10,
+/*20171018 to latest
+on
+*/
+ MSG_ID_C11 = 0xc11,
+/*20171018 to latest
+<Basic Skin>
+<Basic>
+*/
+ MSG_ID_C12 = 0xc12,
+/*20171018 to latest
+Select Skin
+Choose skin
+*/
+ MSG_ID_C13 = 0xc13,
+/*20171018 to latest
+현재 복권에 참여 중이라 삭제할 수 없습니다
+You cannot delete it because you are currently participating in the lottery
+*/
+ MSG_ID_C14 = 0xc14,
+/*20171018 to latest
+/achievement
+*/
+ MSG_ID_C15 = 0xc15,
+/*20171018 to latest
+제니 복권
+Zeny Lottery ticket
+*/
+ MSG_ID_C16 = 0xc16,
+/*20171018 to latest
+제니 복권 %d등 당첨 보상
+Zenyy Lottery %dprize reward
+*/
+ MSG_ID_C17 = 0xc17,
+/*20171018 to latest
+%d등 당첨 보상: %s
+%dprize reward: %s
+*/
+ MSG_ID_C18 = 0xc18,
+/*20171018 to latest
+제니 복권 누적 구매 보상
+Zeny Lottery Cumulative purchase reward
+*/
+ MSG_ID_C19 = 0xc19,
+/*20171018 to latest
+누적 %d회 보상: %s
+Cumulative %d times reward: %s
+*/
+ MSG_ID_C1A = 0xc1a,
+/*20171018 to latest
+제니 복권 구매 환불
+Zeny Lottery Refund
+*/
+ MSG_ID_C1B = 0xc1b,
+/*20171018 to latest
+환불 금액: %d Zeny
+환불 사유: 서버 내 복권 추첨 달성 실패
+Refund amount: %d Zeny
+Reason for Refund: Failed to draw lottery in the server
+*/
+ MSG_ID_C1C = 0xc1c,
+/*20171018 to latest
+미니 파티창 추가
+Add Mini Party Chat
+*/
+ MSG_ID_C1D = 0xc1d,
+/*20171018 to latest
+미니 파티창 삭제
+Delete Mini Party Chat
+*/
+ MSG_ID_C1E = 0xc1e,
+/*20171018 to latest
+복권 추첨이 모두 종료 되었습니다! 당첨자를 확인해주세요
+The lottery draw had ended! Check the winner!
+*/
+ MSG_ID_C1F = 0xc1f,
+/*20171018 to latest
+%d월 %d일
+%dMonth %dDay
+*/
+ MSG_ID_C20 = 0xc20,
+/*20171018 to latest
+다음 등급까지
+Till the next grade
+*/
+ MSG_ID_C21 = 0xc21,
+/*20171018 to latest
+전체
+All
+*/
+ MSG_ID_C22 = 0xc22,
+/*20171018 to latest
+미완료
+Incomplete
+*/
+ MSG_ID_C23 = 0xc23,
+/*20171018 to latest
+(달성!)
+(Accomplished!)
+*/
+ MSG_ID_C24 = 0xc24,
+/*20171018 to latest
+(미달성)
+(Not Accomplished)
+*/
+ MSG_ID_C25 = 0xc25,
+/*20171018 to latest
+장비 교체
+Change equipment
+*/
+ MSG_ID_C26 = 0xc26,
+/*20171018 to latest
+CHANGE
+*/
+ MSG_ID_C27 = 0xc27,
+/*20171018 to latest
+힘 파라메터
+ ^cc0000근접 물리 공격력^ffffff, 소지무게
+Power Parameter
+ ^cc0000Melee PhysicalAttack^ffffff, Carrying Weight
+*/
+ MSG_ID_C28 = 0xc28,
+/*20171018 to latest
+민첩성 파라메터
+^cc0000공격 속도^ffffff, 회피율, 물리 방어력
+Agility Parameter
+^cc0000Attack Speed^ffffff, Dodge, Physical Defense
+*/
+ MSG_ID_C29 = 0xc29,
+/*20171018 to latest
+체력 파라메터
+^cc0000최대 체력^ffffff, 물리 방어력, 마법 방어력
+HP Parameter
+^cc0000Max HP^ffffff, Physical Defense, Magic Defense
+*/
+ MSG_ID_C2A = 0xc2a,
+/*20171018 to latest
+지력 파라메터
+^cc0000마법 공격력^ffffff, 캐스팅 시간, 마법 방어력
+Intellect Parameter
+^cc0000Magic Attack^ffffff, Casting Time, Magic Defense
+*/
+ MSG_ID_C2B = 0xc2b,
+/*20171018 to latest
+손재주 파라메터
+^cc0000원거리 물리 공격력^ffffff, 명중률, 캐스팅 시간, 마법 공격력
+Handcraft Parameter
+^cc0000Long Range Physical Attack^ffffff, Accuracy, Casting Time, Magic Attack
+*/
+ MSG_ID_C2C = 0xc2c,
+/*20171018 to latest
+운 파라메터
+^cc0000치명타율^ffffff, 명중률, 물리공격력, 마법공격력, 회피율
+Moon Parameter
+^cc0000Critical Rate^ffffff, Accuracy, Physical Attack, Magic Attack, Dodge
+*/
+ MSG_ID_C2D = 0xc2d,
+/*20171018 to latest
+물리 공격력
+Physical Attack
+*/
+ MSG_ID_C2E = 0xc2e,
+/*20171018 to latest
+물리 방어력
+Physical Defense
+*/
+ MSG_ID_C2F = 0xc2f,
+/*20171018 to latest
+명중률
+Accuracy
+*/
+ MSG_ID_C30 = 0xc30,
+/*20171018 to latest
+치명타율
+Critical Rate
+*/
+ MSG_ID_C31 = 0xc31,
+/*20171018 to latest
+소속길드
+Affiliated Guild
+*/
+ MSG_ID_C32 = 0xc32,
+/*20171018 to latest
+각 파라메터 레벨업에 사용되는 포인트
+Points to level up each Parameter
+*/
+ MSG_ID_C33 = 0xc33,
+/*20171018 to latest
+마법공격력
+Magic Attack
+*/
+ MSG_ID_C34 = 0xc34,
+/*20171018 to latest
+마법방어력
+Magic Defense
+*/
+ MSG_ID_C35 = 0xc35,
+/*20171018 to latest
+회피율
+Dodge
+*/
+ MSG_ID_C36 = 0xc36,
+/*20171018 to latest
+공격 속도
+Attack Speed
+*/
+ MSG_ID_C37 = 0xc37,
+/*20171018 to latest
+단축키 안내
+Shortcut
+*/
+ MSG_ID_C38 = 0xc38,
+/*20171018 to latest
+옵션
+Option
+*/
+ MSG_ID_C39 = 0xc39,
+/*20171018 to latest
+스킬 단축키 (F1 ~ F9)
+Skill Shortcut Key (F1 ~ F9)
+*/
+ MSG_ID_C3A = 0xc3a,
+/*20171018 to latest
+이미지 캡쳐
+Capture Image
+*/
+ MSG_ID_C3B = 0xc3b,
+/*20171018 to latest
+확대
+Zoom In
+*/
+ MSG_ID_C3C = 0xc3c,
+/*20171018 to latest
+축소
+Zoom Out
+*/
+ MSG_ID_C3D = 0xc3d,
+/*20171018 to latest
+길드
+Guild
+*/
+ MSG_ID_C3E = 0xc3e,
+/*20171018 to latest
+은행
+Bank
+*/
+ MSG_ID_C3F = 0xc3f,
+/*20171018 to latest
+우편
+Mail
+*/
+ MSG_ID_C40 = 0xc40,
+/*20171018 to latest
+캐시 상점
+Cash Shop
+*/
+ MSG_ID_C41 = 0xc41,
+/*20171018 to latest
+앉기
+Sit
+*/
+ MSG_ID_C42 = 0xc42,
+/*20171018 to latest
+이동
+Move
+*/
+ MSG_ID_C43 = 0xc43,
+/*20171018 to latest
+회전
+Rotate
+*/
+ MSG_ID_C44 = 0xc44,
+/*20171018 to latest
+파티장은 파티장을 다른 파티원에게 위임 후 탈퇴 가능합니다.
+The Party Leader can be dropped out only after another party member becomes a Party Leader.
+*/
+ MSG_ID_C45 = 0xc45,
+/*20171018 to latest
+이 동영상을 그만 보시겠습니까?
+Do you want to stop viewing this video?
+*/
+ MSG_ID_C46 = 0xc46,
+/*20171018 to latest
+ 장비가 장비 교체 창에 장착 되었습니다.
+ gear has been equipped in the gear equipment pop-up.
+*/
+ MSG_ID_C47 = 0xc47,
+/*20171018 to latest
+ 장비가 장비 교체 창에서 해제 되었습니다.
+ gear has been removed in the gear equipment pop-up.
+*/
+ MSG_ID_C48 = 0xc48,
+/*20171018 to latest
+현재가 마지막 라인입니다.
+This is the last line.
+*/
+ MSG_ID_C49 = 0xc49,
+/*20171018 to latest
+%.1f%% ( 기본 100%% + 프리미엄 %.1f%%+ %s서버 %.1f%% )
+%.1f%% ( Base 100%% + Premium %.1f%%+ %sServer %.1f%% )
+*/
+ MSG_ID_C4A = 0xc4a,
+/*20171018 to latest
+한자
+Chinese character
+*/
+ MSG_ID_C4B = 0xc4b,
+/*20171018 to latest
+단축키 설정
+Shortcut Settings
+*/
+ MSG_ID_C4C = 0xc4c,
+/*20171018 to latest
+당신의 정액제 기간은 %s에 종료됩니다.
+Your subscription will be ended on%s.
+*/
+ MSG_ID_C4D = 0xc4d,
+/*20171018 to latest
+리플레이 파일을 찾지 못하였습니다.
+Cannot find the replay file.
+*/
+ MSG_ID_C4E = 0xc4e,
+/*20171018 to latest
+의상
+Shoes
+*/
+ MSG_ID_C4F = 0xc4f,
+/*20171018 to latest
+신발
+Head
+*/
+ MSG_ID_C50 = 0xc50,
+/*20171018 to latest
+갑옷
+Armor
+*/
+ MSG_ID_C51 = 0xc51,
+/*20171018 to latest
+어깨
+Shoulders
+*/
+ MSG_ID_C52 = 0xc52,
+/*20171018 to latest
+악세
+Accessory
+*/
+ MSG_ID_C53 = 0xc53,
+/*20171018 to latest
+머리
+Costume
+*/
+ MSG_ID_C54 = 0xc54,
+/*20171018 to latest
+차순정렬
+Sort Order
+*/
+ MSG_ID_C55 = 0xc55,
+/*20171018 to latest
+일반 장비
+Normal Gear
+*/
+ MSG_ID_C56 = 0xc56,
+/*20171018 to latest
+특수 장비
+Special Gear
+*/
+ MSG_ID_C57 = 0xc57,
+/*20171018 to latest
+칭호
+Style
+*/
+ MSG_ID_C58 = 0xc58,
+/*20171018 to latest
+/quake : 화면 흔들림 효과 On/Off
+/quake : Screen Shaking Effect On/Off
+*/
+ MSG_ID_C59 = 0xc59,
+/*20171018 to latest
+/aura2 : 오오라를 완전히 Off 시킬 수 있습니다 On Off
+/aura2 : You can completely turn off the aurora On/Off
+*/
+ MSG_ID_C5A = 0xc5a,
+/*20171018 to latest
+기본 설정
+Default Settings
+*/
+ MSG_ID_C5B = 0xc5b,
+/*20171018 to latest
+고급 설정
+Advanced Settings
+*/
+ MSG_ID_C5C = 0xc5c,
+/*20171018 to latest
+기본설정값이 적용됩니다.
+The Default Settings will be applied.
+*/
+ MSG_ID_C5D = 0xc5d,
+/*20171018 to latest
+기본 설정값이 적용됩니다. 동의하십니까?
+The Default Settings will be applied. Do you agree?
+*/
+ MSG_ID_C5E = 0xc5e,
+/*20171018 to latest
+설정값이 적용됩니다. 동의하십니까?
+The settings will be applied. Do you agree?
+*/
+ MSG_ID_C5F = 0xc5f,
+/*20171018 to latest
+설정값을 적용하려면 재시작이 필요합니다. 동의하십니까?
+Need to restart to apply the settings. Do you agree?
+*/
+ MSG_ID_C60 = 0xc60,
+/*20171018 to latest
+안개
+Fog
+*/
+ MSG_ID_C61 = 0xc61,
+/*20171018 to latest
+오오라 간략화
+Simplified aurora
+*/
+ MSG_ID_C62 = 0xc62,
+/*20171018 to latest
+오오라켜기
+Turn on aurora
+*/
+ MSG_ID_C63 = 0xc63,
+/*20171018 to latest
+이펙트 표시
+Show Effect
+*/
+ MSG_ID_C64 = 0xc64,
+/*20171018 to latest
+음영 표시
+Show Shadows
+*/
+ MSG_ID_C65 = 0xc65,
+/*20171018 to latest
+No Shift
+*/
+ MSG_ID_C66 = 0xc66,
+/*20171018 to latest
+하드웨어 T&L 가속기능을 선택합니다
+Select Hardware T&L Acceleration Function
+*/
+ MSG_ID_C67 = 0xc67,
+/*20171018 to latest
+게임의 해상도를 선택합니다
+Select Game Resolution
+*/
+ MSG_ID_C68 = 0xc68,
+/*20171018 to latest
+전체화면 사용
+Use full screen
+*/
+ MSG_ID_C69 = 0xc69,
+/*20171018 to latest
+마우스 고정
+Fix mouse
+*/
+ MSG_ID_C6A = 0xc6a,
+/*20171018 to latest
+이펙트 설정
+Effect Settings
+*/
+ MSG_ID_C6B = 0xc6b,
+/*20171018 to latest
+Control 설정
+Control Settings
+*/
+ MSG_ID_C6C = 0xc6c,
+/*20171018 to latest
+그래픽 장치 설정
+Graphic Device Settings
+*/
+ MSG_ID_C6D = 0xc6d,
+/*20171018 to latest
+그래픽 해상도 설정
+Graphic Resolution Settings
+*/
+ MSG_ID_C6E = 0xc6e,
+/*20171018 to latest
+전체 화면 유무 설정
+Full Screen Settings
+*/
+ MSG_ID_C6F = 0xc6f,
+/*20171018 to latest
+마우스 고정 여부 설정
+Fix mouse Settings
+*/
+ MSG_ID_C70 = 0xc70,
+/*20171018 to latest
+수수료 :
+Commission :
+*/
+ MSG_ID_C71 = 0xc71,
+/*20171018 to latest
+수수료 총액 :
+Total commission amount :
+*/
+ MSG_ID_C72 = 0xc72,
+/*20171018 to latest
+수신인 설정
+Select receiver
+*/
+ MSG_ID_C73 = 0xc73,
+/*20171018 to latest
+수신그룹 설정
+Select receiving group
+*/
+ MSG_ID_C74 = 0xc74,
+/*20171018 to latest
+크기 변경(F10)
+Change size(F10)
+*/
+ MSG_ID_C75 = 0xc75,
+/*20171018 to latest
+메일함을 불러오는 중 입니다.
+불필요한 메일은 ^c92114삭제^000000해 주세요~!!
+Loading the mailbox.
+^c92114Delete^000000unnecessary emails!!
+*/
+ MSG_ID_C76 = 0xc76,
+/*20171018 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_C77 = 0xc77,
+/*20171018 to latest
+제목
+Title
+*/
+ MSG_ID_C78 = 0xc78,
+/*20171018 to latest
+보낸이
+Sender
+*/
+ MSG_ID_C79 = 0xc79,
+/*20171018 to latest
+라그나로크 클라이언트와 동시에 실행이 불가능 합니다. setup을 종료합니다
+*/
+ MSG_ID_C7A = 0xc7a,
+/*20171018 to latest
+추가 기능 설정
+*/
+ MSG_ID_C7B = 0xc7b,
+/*20171018 to latest
+This account does not exist.
+*/
+ MSG_ID_C7C = 0xc7c,
+/*20171018 to latest
+Passwords do not match.
+*/
+ MSG_ID_C7D = 0xc7d,
+/*20171018 to latest
+Failed to pass IP authentication
+*/
+ MSG_ID_C7E = 0xc7e,
+/*20171018 to latest
+No identification number, supplement your registration information
+*/
+ MSG_ID_C7F = 0xc7f,
+/*20171018 to latest
+Account block
+*/
+ MSG_ID_C80 = 0xc80,
+/*20171018 to latest
+System error
+*/
+ MSG_ID_C81 = 0xc81,
+/*20171018 to latest
+unknown error found.
+*/
+ MSG_ID_C82 = 0xc82,
+/*20171018 to latest
+길안내 아이콘 설정
+*/
+ MSG_ID_C83 = 0xc83,
+/*20171018 to latest
+길 안내 정보 UI
+*/
+ MSG_ID_C84 = 0xc84,
+/*20171018 to latest
+길 안내 정보 열기
+*/
+ MSG_ID_C85 = 0xc85,
+/*20171018 to latest
+현재 위치 공유
+*/
+ MSG_ID_C86 = 0xc86,
+/*20171018 to latest
+검색결과[0]
+*/
+ MSG_ID_C87 = 0xc87,
+/*20171018 to latest
+검색&안내
+*/
+ MSG_ID_C88 = 0xc88,
+/*20171018 to latest
+위치가 올바르지 않습니다.
+*/
+ MSG_ID_C89 = 0xc89,
+/*20171018 to latest
+검색결과[%d]
+*/
+ MSG_ID_C8A = 0xc8a,
+/*20171018 to latest
+길안내 표시를 위한 아이콘 설정
+*/
+ MSG_ID_C8B = 0xc8b,
+/*20171018 to latest
+길 찾기에 zeny 허용
+*/
+ MSG_ID_C8C = 0xc8c,
+/*20171018 to latest
+내비게이션 도킹 해제
+*/
+ MSG_ID_C8D = 0xc8d,
+/*20171018 to latest
+활성화 하지 않은 계정입니다.
+*/
+ MSG_ID_C8E = 0xc8e,
+/*20171018 to latest
+클릭한 위치가 채팅창에 공유 됩니다.
+*/
+ MSG_ID_C8F = 0xc8f,
+/*20171018 to latest
+4. Service 항목을 선택하면 Zeny&비공정 이용을 고려하여 안내 한다.
+*/
+ MSG_ID_C90 = 0xc90,
+/*20171018 to latest
+5. [<-] 버튼 : 길안내 모드 <-> 검색 모드를 바꾸거나
+*/
+ MSG_ID_C91 = 0xc91,
+/*20171018 to latest
+공유하기 모드 -> 서치 모드로 돌아갈때 사용 된다.
+*/
+ MSG_ID_C92 = 0xc92,
+/*20171018 to latest
+경험치 %lld 얻음
+*/
+ MSG_ID_C93 = 0xc93,
+/*20171018 to latest
+'%lld'의 경험치를
+*/
+ MSG_ID_C94 = 0xc94,
+/*20171018 to latest
+^b- 노점 수수료 안내^/b
+노점 설정 가격에 따라 일정 비율의 수수료가 부가됩니다.
+
+ ^b> 수수료 비율^/b
+각 금액에 따른 수수료의 비율은 아래와 같습니다.
+
+0 z ~ 10,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,001 z ~ 100,000 z
+ = 수수료율 : ^1567fe0%^000000
+100,001 z ~ 1,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+1,000,001 z ~ 10,000,000 z
+ = 수수료율 : ^1567fe0%^000000
+10,000,001 z ~ 100,000,000 z
+ = 수수료율 : ^1567fe5%^000000
+100,000,001 z 이상
+ = 수수료율 : ^1567fe5%^000000
+*/
+ MSG_ID_C95 = 0xc95,
+/*20171018 to latest
+실거래가 :
+*/
+ MSG_ID_C96 = 0xc96,
+/*20171018 to latest
+※ 아이템 판매시, 실거래가만큼 제니를 획득합니다.
+*/
+ MSG_ID_C97 = 0xc97,
+/*20171018 to latest
+※ 아이템 구매시, 실거래가만큼 제니가 차감됩니다.
+*/
+ MSG_ID_C98 = 0xc98,
+/*20171018 to latest
+채팅방 개설
+*/
+ MSG_ID_C99 = 0xc99,
+/*20171018 to latest
+해당 캐릭터는 파티가입이 가능하지 않은 레벨입니다.
+*/
+ MSG_ID_C9A = 0xc9a,
+/*20171018 to latest
+'%lld'의 잡경험치를
+*/
+ MSG_ID_C9B = 0xc9b,
+/*20171018 to latest
+잡경험치 %lld 얻음
+*/
+ MSG_ID_C9C = 0xc9c,
+/*20171018 to latest
+현재위치(대로)에는 노점을 개설할 수 없습니다.
+*/
+ MSG_ID_C9D = 0xc9d,
+/*20171018 to latest
+초 후 가능합니다.
+*/
+ MSG_ID_C9E = 0xc9e,
+/*20171018 to latest
+파티원
+*/
+ MSG_ID_C9F = 0xc9f,
+/*20171018 to latest
+SNS 전송실패(%d)
+*/
+ MSG_ID_CA0 = 0xca0,
+/*20171018 to latest
+SNS 서버 연결실패
+*/
+ MSG_ID_CA1 = 0xca1,
+/*20171018 to latest
+SNS 로그인 후 사용 가능합니다.
+*/
+ MSG_ID_CA2 = 0xca2,
+/*20171018 to latest
+접속 할 수 있는 주소가 존재하지 않습니다.
+*/
+ MSG_ID_CA3 = 0xca3,
+/*20171018 to latest
+미니파티창이 겹쳐져 있어 사용하실 수 없습니다.
+*/
+ MSG_ID_CA4 = 0xca4,
+/*20171018 to latest
+나의 판매노점
+*/
+ MSG_ID_CA5 = 0xca5,
+/*20171018 to latest
+BOX
+*/
+ MSG_ID_CA6 = 0xca6,
+/*20171018 to latest
+팁박스
+*/
+ MSG_ID_CA7 = 0xca7,
+/*20171018 to latest
+트윗을 성공했습니다.
+*/
+ MSG_ID_CA8 = 0xca8,
+/*20171018 to latest
+다시하기
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CA9 = 0xca9,
+/*20171018 to latest
+다시하기가 비활성화되었습니다. 제련 재료를 다시 선택해주세요.
+*/
+ MSG_ID_CAA = 0xcaa,
+/*20171018 to latest
+제련석이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAB = 0xcab,
+/*20171018 to latest
+제니가 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAC = 0xcac,
+/*20171018 to latest
+대장장이의 축복이 부족하여 다시하기가 비활성화 되었습니다.
+*/
+ MSG_ID_CAD = 0xcad,
+/*20171018 to latest
+아이템이 파괴되었습니다.
+*/
+ MSG_ID_CAE = 0xcae,
+/*20171018 to latest
+모든 스테이터스가 감소되었습니다.
+*/
+ MSG_ID_CAF = 0xcaf,
+/*20171018 to latest
+모든 스테이터스 감소 효과가 해제되었습니다.
+*/
+ MSG_ID_CB0 = 0xcb0,
+/*20171018 to latest
+OTP 비밀번호는 8자리 입니다.
+*/
+ MSG_ID_CB1 = 0xcb1,
+/*20171018 to latest
+통합계정
+*/
+ MSG_ID_CB2 = 0xcb2,
+/*20171018 to latest
+라그나로크
+*/
+ MSG_ID_CB3 = 0xcb3,
+/*20171018 to latest
+서비스 점검 중입니다.
+*/
+ MSG_ID_CB4 = 0xcb4,
+/*20171018 to latest
+검색어를 입력해주세요
+*/
+ MSG_ID_CB5 = 0xcb5,
+/*20171018 to latest
+MOTP
+*/
+ MSG_ID_CB6 = 0xcb6,
+/*20171018 to latest
+인증번호
+Identification number.
+*/
+ MSG_ID_CB7 = 0xcb7,
+/*20171018 to latest
+휴대폰에 다운받은 GNJOY MOTP를 실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_CB8 = 0xcb8,
+/*20171018 to latest
+파티장을 위임할 파티원이 존재하지 않습니다. 파티를 해산하시겠습니까?
+*/
+ MSG_ID_CB9 = 0xcb9,
+/*20171018 to latest
+ - 만18세이상
+*/
+ MSG_ID_CBA = 0xcba,
+/*20171018 to latest
+ - 유료서버
+*/
+ MSG_ID_CBB = 0xcbb,
+/*20171018 to latest
+ - 무료서버
+*/
+ MSG_ID_CBC = 0xcbc,
+/*20171018 to latest
+쾌적
+*/
+ MSG_ID_CBD = 0xcbd,
+/*20171018 to latest
+보통
+Normal
+*/
+ MSG_ID_CBE = 0xcbe,
+/*20171018 to latest
+혼잡
+*/
+ MSG_ID_CBF = 0xcbf,
+/*20171018 to latest
+포화
+*/
+ MSG_ID_CC0 = 0xcc0,
+/*20171018 to latest
+map
+*/
+ MSG_ID_CC1 = 0xcc1,
+/*20171018 to latest
+월드창고는 인벤토리 아이템만 입출고 할 수 있습니다.
+*/
+ MSG_ID_CC2 = 0xcc2,
+/*20171018 to latest
+월드창고에는 펫알을 입고할 수 없습니다.
+*/
+ MSG_ID_CC3 = 0xcc3,
+/*20171018 to latest
+월드창고에는 제작아이템을 입고할 수 없습니다.
+*/
+ MSG_ID_CC4 = 0xcc4,
+/*20171018 to latest
+%s 에서는 출고 할 수 없는 아이템입니다.
+*/
+ MSG_ID_CC5 = 0xcc5,
+/*20171018 to latest
+던전 파괴
+*/
+ MSG_ID_CC6 = 0xcc6,
+/*20171018 to latest
+[%s] 님이 제련을 성공하여, [+%d %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_CC7 = 0xcc7,
+/*20171018 to latest
+[%s] 님이 [+%d %s] 아이템의 제련에 실패하였습니다.
+*/
+ MSG_ID_CC8 = 0xcc8,
+/*20171018 to latest
+파티장을 위임한 이후에 탈퇴할 수 있습니다.
+*/
+ MSG_ID_CC9 = 0xcc9,
+/*20171018 to latest
+오름
+*/
+ MSG_ID_CCA = 0xcca,
+/*20171018 to latest
+내림
+*/
+ MSG_ID_CCB = 0xccb,
+/*20171018 to latest
+기본
+*/
+ MSG_ID_CCC = 0xccc,
+/*20171018 to latest
+변조된 파일이 발견되었습니다. 게임을 다시 실행시켜주세요.
+File abusing detected. Please restart the client with clean files.
+*/
+ MSG_ID_CCD = 0xccd,
+/*20171018 to latest
+%s 은(는) 이맵에서 이동이 제한된 아이템입니다.
+*/
+ MSG_ID_CCE = 0xcce,
+/*20171018 to latest
+스스로
+먹이먹기
+*/
+ MSG_ID_CCF = 0xccf,
+/*20171018 to latest
+로덱스 작성창이 열려있는 동안 호문클루스가 먹이를 먹지 못합니다.
+*/
+ MSG_ID_CD0 = 0xcd0,
+/*20171018 to latest
+호문클루스가 먹이를 먹었습니다. '%s' 잔여량 %d개
+*/
+ MSG_ID_CD1 = 0xcd1,
+/*20171018 to latest
+호문클루스 스스로 먹이 먹기 활성화 On
+*/
+ MSG_ID_CD2 = 0xcd2,
+/*20171018 to latest
+호문클루스 스스로 먹이 먹기 활성화 Off
+*/
+ MSG_ID_CD3 = 0xcd3,
+/*20171018 to latest
+호문클루스는 주인이 획득하는 경험치의
+10%만큼을 자신의 경험치로 분배 받습니다.
+*/
+ MSG_ID_CD4 = 0xcd4,
+/*20171018 to latest
+확률 : %d%%
+*/
+ MSG_ID_CD5 = 0xcd5,
+/*20171018 to latest
+해당 대상은 호문의 공격대상이 아닙니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD6 = 0xcd6,
+/*20171018 to latest
+호문의 공격대상이 존재하지 않습니다. 'Alt + 우클릭'을 통해 호문클루스의 공격대상을 지정해주세요.
+*/
+ MSG_ID_CD7 = 0xcd7,
+/*20171018 to latest
+판매 리스트
+*/
+ MSG_ID_CD8 = 0xcd8,
+/*20171018 to latest
+구입 리스트
+*/
+ MSG_ID_CD9 = 0xcd9,
+/*20171018 to latest
+신규
+New
+*/
+ MSG_ID_CDA = 0xcda,
+/*20171018 to latest
+인기
+Headgears
+*/
+ MSG_ID_CDB = 0xcdb,
+/*20171018 to latest
+한정
+Limited
+*/
+ MSG_ID_CDC = 0xcdc,
+/*20171018 to latest
+임대장비
+Rental Items
+*/
+ MSG_ID_CDD = 0xcdd,
+/*20171018 to latest
+영구장비
+Equipments
+*/
+ MSG_ID_CDE = 0xcde,
+/*20171018 to latest
+버프
+Scrolls
+*/
+ MSG_ID_CDF = 0xcdf,
+/*20171018 to latest
+회복
+Consumables
+*/
+ MSG_ID_CE0 = 0xce0,
+/*20171018 to latest
+기타
+Other
+*/
+ MSG_ID_CE1 = 0xce1,
+/*20171018 to latest
+특가
+Special
+*/
+ MSG_ID_CE2 = 0xce2,
+/*20171018 to latest
+충전하기
+*/
+ MSG_ID_CE3 = 0xce3,
+/*20171018 to latest
+구입하기
+*/
+ MSG_ID_CE4 = 0xce4,
+/*20171018 to 20171206
+https://payment.gnjoy.com/bill/login.grv
+20171206 to latest
+http://member.gnjoy.com/user/pay/chargelist.asp
+*/
+ MSG_ID_CE5 = 0xce5,
+/*20171018 to latest
+아이템 검색
+*/
+ MSG_ID_CE6 = 0xce6,
+/*20171018 to latest
+무료캐시
+*/
+ MSG_ID_CE7 = 0xce7,
+/*20171018 to latest
+무료캐시 사용
+*/
+ MSG_ID_CE8 = 0xce8,
+/*20171018 to latest
+소지캐시
+*/
+ MSG_ID_CE9 = 0xce9,
+/*20171018 to latest
+수량갱신
+*/
+ MSG_ID_CEA = 0xcea,
+/*20171018 to latest
+성제(여)
+*/
+ MSG_ID_CEB = 0xceb,
+/*20171018 to latest
+소울리퍼(여)
+*/
+ MSG_ID_CEC = 0xcec,
+/*20171018 to latest
+성제(남)
+*/
+ MSG_ID_CED = 0xced,
+/*20171018 to latest
+소울리퍼(남)
+*/
+ MSG_ID_CEE = 0xcee,
+/*20171018 to latest
+무게가 %d 퍼센트 이상일때는 HP SP가 자연적으로 회복이 되지 않습니다.
+*/
+ MSG_ID_CEF = 0xcef,
+/*20171018 to latest
+한 번에 구입 가능한 아이템의 가짓수는 8개입니다.
+*/
+ MSG_ID_CF0 = 0xcf0,
+/*20171018 to 20190227
+http://gift.zhaouc.com/#/index
+http://gift.zhaouc.com/
+20190313 to latest
+http://gift.zhaouc.com/
+*/
+ MSG_ID_CF1 = 0xcf1,
+/*20171018 to latest
+UNKNOWN ERROR:%d
+*/
+ MSG_ID_CF2 = 0xcf2,
+/*20171018 to latest
+NOT USER
+*/
+ MSG_ID_CF3 = 0xcf3,
+/*20171018 to latest
+THIS ACCOUNT ID IS BLOCKED
+*/
+ MSG_ID_CF4 = 0xcf4,
+/*20171018 to latest
+COUNTRY REJECT (OR NOT AVALIABLE USER )
+*/
+ MSG_ID_CF5 = 0xcf5,
+/*20171018 to latest
+NOT MATCH PASSWORD
+*/
+ MSG_ID_CF6 = 0xcf6,
+/*20171018 to latest
+NOT EMAIL CERT
+*/
+ MSG_ID_CF7 = 0xcf7,
+/*20171018 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CF8 = 0xcf8,
+/*20171018 to latest
+COUNTRY REJECT
+*/
+ MSG_ID_CF9 = 0xcf9,
+/*20171018 to latest
+PAYPAL BLOCK
+*/
+ MSG_ID_CFA = 0xcfa,
+/*20171018 to latest
+WEB BLOCK
+*/
+ MSG_ID_CFB = 0xcfb,
+/*20171018 to latest
+AGE LIMIT USER
+*/
+ MSG_ID_CFC = 0xcfc,
+/*20171018 to latest
+PASSWORD HAS NOT BEEN CHANGED FOR MORE THAN 90DAYS
+*/
+ MSG_ID_CFD = 0xcfd,
+/*20171018 to latest
+INPUT DATA ERROR
+*/
+ MSG_ID_CFE = 0xcfe,
+/*20171018 to latest
+ERROR DATABASE
+*/
+ MSG_ID_CFF = 0xcff,
+/*20171018 to latest
+ERROR SYSTEM
+*/
+ MSG_ID_D00 = 0xd00,
+/*20171018 to 20171027
+%s 지불
+20171030 to latest
+%s 소모
+*/
+ MSG_ID_D01 = 0xd01,
+/*20171018 to latest
+비용지불
+*/
+ MSG_ID_D02 = 0xd02,
+/*20171018 to latest
+출발 가능한 맵이 아닙니다.
+*/
+ MSG_ID_D03 = 0xd03,
+/*20171018 to latest
+이동 불가능한 맵입니다
+*/
+ MSG_ID_D04 = 0xd04,
+/*20171018 to latest
+아이템이 부족합니다.
+*/
+ MSG_ID_D05 = 0xd05,
+/*20171018 to latest
+줄 바꿈 없이 한 줄로 입력해주세요.
+*/
+ MSG_ID_D06 = 0xd06,
+/*20171018 to latest
+불량 단어가 포함된 이름은 등록할 수 없습니다.
+*/
+ MSG_ID_D07 = 0xd07,
+/*20171018 to latest
+회원 가입을 위해 공식 홈페이지로 이동됩니다.
+*/
+ MSG_ID_D08 = 0xd08,
+#if PACKETVER >= 20171019
+/*20171019 to latest
+TokenAgency 서버 연결 실패
+*/
+ MSG_ID_D09 = 0xd09,
+#endif
+#if PACKETVER >= 20171023
+/*20171023 to latest
+과금정보
+*/
+ MSG_ID_D0A = 0xd0a,
+/*20171023 to latest
+삭제예약
+*/
+ MSG_ID_D0B = 0xd0b,
+/*20171023 to latest
+예약취소
+*/
+ MSG_ID_D0C = 0xd0c,
+/*20171023 to latest
+게임시작
+*/
+ MSG_ID_D0D = 0xd0d,
+/*20171023 to latest
+삭제
+Delete
+*/
+ MSG_ID_D0E = 0xd0e,
+/*20171023 to latest
+Character List
+*/
+ MSG_ID_D0F = 0xd0f,
+/*20171023 to latest
+공지
+Notice
+*/
+ MSG_ID_D10 = 0xd10,
+/*20171023 to latest
+생성
+*/
+ MSG_ID_D11 = 0xd11,
+/*20171023 to latest
+Hair Style
+*/
+ MSG_ID_D12 = 0xd12,
+/*20171023 to latest
+Hair Color
+*/
+ MSG_ID_D13 = 0xd13,
+/*20171023 to latest
+중복확인
+*/
+ MSG_ID_D14 = 0xd14,
+/*20171023 to latest
+%d시 %d분 %d초
+*/
+ MSG_ID_D15 = 0xd15,
+/*20171023 to latest
+MOTP 입력 시간이 초과되었습니다. 처음부터 다시 로그인해주십시오.
+*/
+ MSG_ID_D16 = 0xd16,
+/*20171023 to latest
+뒤로가기
+*/
+ MSG_ID_D17 = 0xd17,
+#endif
+#if PACKETVER >= 20171024
+/*20171024 to latest
+아이템을 사용할 수 없습니다.
+*/
+ MSG_ID_D18 = 0xd18,
+/*20171024 to latest
+동일한 맵으로 이동할 수 없습니다.
+*/
+ MSG_ID_D19 = 0xd19,
+/*20171024 to latest
+사망시 이동이 불가능합니다.
+*/
+ MSG_ID_D1A = 0xd1a,
+#endif
+#if PACKETVER >= 20171030
+/*20171030 to latest
+캐릭터 생성
+*/
+ MSG_ID_D1B = 0xd1b,
+#endif
+#if PACKETVER >= 20171031
+/*20171031 to latest
+모험가 중개소 등록
+*/
+ MSG_ID_D1C = 0xd1c,
+/*20171031 to 20191113
+모집 중단
+20191127 to latest
+모험가 중개소 등록하기
+*/
+ MSG_ID_D1D = 0xd1d,
+/*20171031 to 20191113
+모험가 중개소 설정
+20191127 to latest
+모집 중단
+*/
+ MSG_ID_D1E = 0xd1e,
+/*20171031 to 20191113
+전 지역
+20191127 to latest
+메모
+Note
+*/
+ MSG_ID_D1F = 0xd1f,
+/*20171031 to 20191113
+직접기재
+20191127 to latest
+퀘스트
+Quest
+*/
+ MSG_ID_D20 = 0xd20,
+/*20171031 to 20191113
+검사계열
+20191127 to latest
+필드
+*/
+ MSG_ID_D21 = 0xd21,
+/*20171031 to 20191113
+법사계열
+20191127 to latest
+던전
+Dungeon
+*/
+ MSG_ID_D22 = 0xd22,
+/*20171031 to 20191113
+궁수계열
+20191127 to latest
+MD
+*/
+ MSG_ID_D23 = 0xd23,
+/*20171031 to 20191113
+복사계열
+20191127 to latest
+낙원단
+*/
+ MSG_ID_D24 = 0xd24,
+/*20171031 to 20191113
+상인계열
+20191127 to latest
+기타
+Other
+*/
+ MSG_ID_D25 = 0xd25,
+/*20171031 to 20191113
+도둑계열
+20191127 to latest
+검색
+Search
+*/
+ MSG_ID_D26 = 0xd26,
+/*20171031 to 20191113
+태권계열
+20191127 to latest
+초기화
+*/
+ MSG_ID_D27 = 0xd27,
+/*20171031 to 20191113
+닌자계열
+20191127 to latest
+파티가입신청
+*/
+ MSG_ID_D28 = 0xd28,
+/*20171031 to 20191113
+건슬링거계열
+20191127 to latest
+목적
+*/
+ MSG_ID_D29 = 0xd29,
+/*20171031 to 20191113
+도람족계열
+20191127 to latest
+※욕설, 현거래등 운영 규칙에 위배되는 목적으로 사용 시 처벌 받을 수 있습니다.
+*/
+ MSG_ID_D2A = 0xd2a,
+/*20171031 to 20191113
+지역명
+20191127 to latest
+등록하기
+Register
+*/
+ MSG_ID_D2B = 0xd2b,
+/*20171031 to 20191113
+지역명 검색
+20191127 to latest
+사용할 수 없는 단어가 포함되어 있습니다.
+*/
+ MSG_ID_D2C = 0xd2c,
+/*20171031 to 20191113
+가입 요청하기
+20191127 to latest
+파티가입
+*/
+ MSG_ID_D2D = 0xd2d,
+/*20171031 to 20191113
+신고하기
+20191127 to latest
+1:1대화
+*/
+ MSG_ID_D2E = 0xd2e,
+/*20171031 to 20191113
+파티 모집 중단
+20191127 to latest
+모집 중지
+*/
+ MSG_ID_D2F = 0xd2f,
+/*20171031 to 20191113
+지역명을 입력해주세요.
+20191127 to latest
+수정하기
+*/
+ MSG_ID_D30 = 0xd30,
+/*20171031 to 20191113
+지역
+20191127 to latest
+전체
+All
+*/
+ MSG_ID_D31 = 0xd31,
+/*20171031 to 20191113
+전 직업
+20191127 to latest
+[%s] 님이 파티가입을 신청했습니다.
+*/
+ MSG_ID_D32 = 0xd32,
+#endif
+#if PACKETVER >= 20171109
+/*20171109 to latest
+로그인
+*/
+ MSG_ID_D33 = 0xd33,
+/*20171109 to latest
+계정
+*/
+ MSG_ID_D34 = 0xd34,
+/*20171109 to latest
+종료
+Exit
+*/
+ MSG_ID_D35 = 0xd35,
+/*20171109 to latest
+신청
+*/
+ MSG_ID_D36 = 0xd36,
+/*20171109 to latest
+접속
+*/
+ MSG_ID_D37 = 0xd37,
+/*20171109 to latest
+확인
+*/
+ MSG_ID_D38 = 0xd38,
+/*20171109 to latest
+휴대폰에 다운받은 GNJOY MOTP를
+*/
+ MSG_ID_D39 = 0xd39,
+/*20171109 to latest
+실행하여 인증번호를 입력해 주세요.
+*/
+ MSG_ID_D3A = 0xd3a,
+/*20171109 to latest
+NPC가 있는 맵의 랜덤 좌표로 이동 됩니다.
+*/
+ MSG_ID_D3B = 0xd3b,
+/*20171109 to latest
+태권
+Taekwon
+*/
+ MSG_ID_D3C = 0xd3c,
+/*20171109 to 20171117
+ 님이 차단 상태로 설정되었습니다.
+20171121 to latest
+ 에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D3D = 0xd3d,
+/*20171109 to 20171117
+ 님을 차단 상태로 설정하는데 실패하였습니다.
+20171121 to latest
+ 에게 전체채팅 및 귓말 거부 요청 실패
+*/
+ MSG_ID_D3E = 0xd3e,
+/*20171109 to 20171117
+ 님을 차단 상태로 설정하는데 실패하였습니다.(인원 초과)
+20171121 to latest
+ 에게 전체채팅 및 귓말 거부 요청실패 (인원초과)
+*/
+ MSG_ID_D3F = 0xd3f,
+/*20171109 to 20171117
+ 님이 차단 해제 되었습니다.
+20171121 to latest
+ 에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D40 = 0xd40,
+/*20171109 to 20171117
+ 님을 차단 해제하는데 실패하였습니다.
+20171121 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패
+*/
+ MSG_ID_D41 = 0xd41,
+/*20171109 to 20171117
+ 님을 차단 해제하는데 실패하였습니다.(인원 초과)
+20171121 to latest
+ 에게 전체채팅 및 귓말 가능 요청실패 (인원초과)
+*/
+ MSG_ID_D42 = 0xd42,
+/*20171109 to latest
+차단 리스트가 없습니다
+Ignore-list is empty
+*/
+ MSG_ID_D43 = 0xd43,
+/*20171109 to latest
+-차단 리스트-
+Characters in ignore-list:
+*/
+ MSG_ID_D44 = 0xd44,
+#endif
+#if PACKETVER >= 20171113
+/*20171113 to latest
+진행중
+Act
+*/
+ MSG_ID_D45 = 0xd45,
+/*20171113 to latest
+추천
+Rec
+*/
+ MSG_ID_D46 = 0xd46,
+/*20171113 to latest
+보류중
+Pen
+*/
+ MSG_ID_D47 = 0xd47,
+/*20171113 to latest
+QUEST
+*/
+ MSG_ID_D48 = 0xd48,
+/*20171113 to latest
+내용
+For
+*/
+ MSG_ID_D49 = 0xd49,
+/*20171113 to latest
+몬스터
+*/
+ MSG_ID_D4A = 0xd4a,
+/*20171113 to latest
+보상
+*/
+ MSG_ID_D4B = 0xd4b,
+/*20171113 to latest
+EXP
+*/
+ MSG_ID_D4C = 0xd4c,
+/*20171113 to latest
+JEXP
+*/
+ MSG_ID_D4D = 0xd4d,
+/*20171113 to latest
+아이템
+Item
+*/
+ MSG_ID_D4E = 0xd4e,
+/*20171113 to latest
+진행/보류
+*/
+ MSG_ID_D4F = 0xd4f,
+/*20171113 to latest
+하단으로 이동
+*/
+ MSG_ID_D50 = 0xd50,
+/*20171113 to latest
+간편 퀘스트창에 표시
+*/
+ MSG_ID_D51 = 0xd51,
+#endif
+#if PACKETVER >= 20171115
+/*20171115 to latest
+입력시간
+*/
+ MSG_ID_D52 = 0xd52,
+/*20171115 to latest
+아이디 저장
+*/
+ MSG_ID_D53 = 0xd53,
+/*20171115 to latest
+비밀번호
+Password
+*/
+ MSG_ID_D54 = 0xd54,
+/*20171115 to latest
+아이디
+*/
+ MSG_ID_D55 = 0xd55,
+/*20171115 to latest
+회원가입
+*/
+ MSG_ID_D56 = 0xd56,
+/*20171115 to 20191113
+노비스계열
+20191127 to latest
+파티장
+Leader
+*/
+ MSG_ID_D57 = 0xd57,
+/*20171115 to 20191113
+슈퍼노비스계열
+20191127 to latest
+파티에 가입할 수 있는 레벨이 아닙니다.
+*/
+ MSG_ID_D58 = 0xd58,
+/*20171115 to latest
+모험가 중개소 등록에 실패했습니다.
+*/
+ MSG_ID_D59 = 0xd59,
+/*20171115 to latest
+모험가 중개소에 등록되었습니다.
+*/
+ MSG_ID_D5A = 0xd5a,
+/*20171115 to 20180321
+직업을 한 개 이상 선택해주세요.
+20180328 to 20191113
+모집을 희망하는 파티원의 직업을 한 개 이상 선택해 주세요.
+20191127 to latest
+검색내용입력
+*/
+ MSG_ID_D5B = 0xd5b,
+/*20171115 to 20191127
+지역명을 두 글자 이상 입력해주세요.
+20191204 to latest
+탱커
+*/
+ MSG_ID_D5C = 0xd5c,
+/*20171115 to latest
+%.1f%% (+ %s서버 %.1f%%)
+*/
+ MSG_ID_D5D = 0xd5d,
+#endif
+#if PACKETVER >= 20171121
+/*20171121 to latest
+/ex (캐릭터이름) or /차단 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D5E = 0xd5e,
+/*20171121 to latest
+/in (캐릭터이름) or /해제 (캐릭터이름) : 해당 캐릭터에 대해 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D5F = 0xd5f,
+/*20171121 to latest
+/ex or /차단 : 전체채팅 및 귓말 차단 캐릭터 리스트
+*/
+ MSG_ID_D60 = 0xd60,
+/*20171121 to latest
+/exall or /차단전부 : 모두에게 전체채팅 및 귓말 차단
+*/
+ MSG_ID_D61 = 0xd61,
+/*20171121 to latest
+/inall or /해제전부 : 모두에게 전체채팅 및 귓말 허용
+*/
+ MSG_ID_D62 = 0xd62,
+/*20171121 to latest
+모두에게 전체채팅 및 귓말 거부상태
+*/
+ MSG_ID_D63 = 0xd63,
+/*20171121 to latest
+모두에게 전체채팅 및 귓말 거부요청 실패
+*/
+ MSG_ID_D64 = 0xd64,
+/*20171121 to latest
+모두에게 전체채팅 및 귓말 가능상태
+*/
+ MSG_ID_D65 = 0xd65,
+/*20171121 to latest
+모두에게 전체채팅 및 귓말 가능요청 실패
+*/
+ MSG_ID_D66 = 0xd66,
+#endif
+#if PACKETVER >= 20171123
+/*20171123 to latest
+오프닝
+*/
+ MSG_ID_D67 = 0xd67,
+#endif
+#if PACKETVER >= 20171127
+/*20171127 to latest
+로그인 화면으로 돌아가시겠습니까?
+*/
+ MSG_ID_D68 = 0xd68,
+#endif
+#if PACKETVER >= 20171204
+/*20171204 to latest
+힘과 공격력이 강해졌습니다.
+*/
+ MSG_ID_D69 = 0xd69,
+/*20171204 to latest
+힘, 지능, 손재주 및 명중률이 증가하였습니다.
+*/
+ MSG_ID_D6A = 0xd6a,
+/*20171204 to latest
+방어력 및 HP가 증가되었습니다.
+*/
+ MSG_ID_D6B = 0xd6b,
+/*20171204 to latest
+젤스타
+*/
+ MSG_ID_D6C = 0xd6c,
+/*20171204 to latest
+계정버프
+*/
+ MSG_ID_D6D = 0xd6d,
+/*20171204 to latest
+정액서비스
+*/
+ MSG_ID_D6E = 0xd6e,
+#endif
+#if PACKETVER >= 20171208
+/*20171208 to latest
+현재 접속이 지연되고 있습니다. 순차적으로 접속이 가능하니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D6F = 0xd6f,
+/*20171208 to latest
+현재 접속이 지연되고 있으니 잠시 후 재접속 부탁드립니다.
+*/
+ MSG_ID_D70 = 0xd70,
+#endif
+#if PACKETVER >= 20171213
+/*20171213 to latest
+불량 단어가 포함된 이름은 검색할 수 없습니다.
+*/
+ MSG_ID_D71 = 0xd71,
+/*20171213 to 20191127
+파티 마스터가 요청을 받을 수 없는 맵에 있습니다.
+20191204 to latest
+파티 마스터가 요청을 받을 수 없는 상태입니다.
+*/
+ MSG_ID_D72 = 0xd72,
+/*20171213 to latest
+파티를 찾을 수 없습니다.
+*/
+ MSG_ID_D73 = 0xd73,
+/*20171213 to 20180321
+님의 파티요청입니다.
+20180328 to 20191127
+님의 파티 가입 요청입니다.
+20191204 to latest
+딜러
+*/
+ MSG_ID_D74 = 0xd74,
+/*20171213 to latest
+http://ro.gnjoy.com
+*/
+ MSG_ID_D75 = 0xd75,
+#endif
+#if PACKETVER >= 20171214
+/*20171214 to latest
+▲
+*/
+ MSG_ID_D76 = 0xd76,
+/*20171214 to latest
+▼
+*/
+ MSG_ID_D77 = 0xd77,
+#endif
+#if PACKETVER >= 20171227
+/*20171227 to latest
+이미 친구입니다
+*/
+ MSG_ID_D78 = 0xd78,
+/*20171227 to latest
+상대방을 찾을 수 없습니다
+*/
+ MSG_ID_D79 = 0xd79,
+/*20171227 to latest
+이미 다른 캐릭터가 친구 신청 중입니다.
+*/
+ MSG_ID_D7A = 0xd7a,
+/*20171227 to latest
+혼구슬 표시 ON
+*/
+ MSG_ID_D7B = 0xd7b,
+/*20171227 to latest
+혼구슬 표시 OFF
+*/
+ MSG_ID_D7C = 0xd7c,
+#endif
+#if PACKETVER >= 20180117
+/*20180117 to latest
+해당 계정은 2차 비밀번호 오입력으로 인해 게임내 접속이 제한된 상태입니다.
+ %02d시간 %02d분 후에 접속제한이 해제되며, 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7D = 0xd7d,
+/*20180117 to latest
+보안패스워드를 3회이상 틀리셨습니다. 계정 보안을 위해 24시간동안 게임내 접속이 제한됩니다.
+ 접속제한의 해제는 홈페이지 -> 개인정보변경 -> 2차 비밀번호 에서 본인인증 후 진행해주시기 바랍니다.
+*/
+ MSG_ID_D7E = 0xd7e,
+/*20180117 to latest
+운영진
+*/
+ MSG_ID_D7F = 0xd7f,
+/*20180117 to latest
+%d일차 출석 보상이 지급되었습니다.
+*/
+ MSG_ID_D80 = 0xd80,
+/*20180117 to 20180117
+계정설정정보 받아오는데 실패 했습니다.( 재시도를 위해서는 재시작 해야 합니다. )
+20180131 to latest
+계정 설정 데이터를 불러오는 중에 오류가 발생했습니다. ( 재시도를 위해서는 재시작 해야 합니다. )
+*/
+ MSG_ID_D81 = 0xd81,
+/*20180117 to latest
+해당 스킬은 파티 상태에서 사용 가능합니다.
+*/
+ MSG_ID_D82 = 0xd82,
+#endif
+#if PACKETVER >= 20180131
+/*20180131 to latest
+파티 모집을 중단하였습니다.
+*/
+ MSG_ID_D83 = 0xd83,
+/*20180131 to latest
+길드 상납 경험치는 최대 %d%%까지 가능합니다.
+*/
+ MSG_ID_D84 = 0xd84,
+/*20180131 to latest
+길드 레벨이 최대여서 더 이상 경험치를 상납할 수 없습니다.
+*/
+ MSG_ID_D85 = 0xd85,
+/*20180131 to latest
+계정보안을 위하여 MOTP미사용자는 홈페이지 로그인만 가능합니다.
+홈페이지로 로그인을 시도해주시기 바랍니다.
+*/
+ MSG_ID_D86 = 0xd86,
+/*20180131 to latest
+물리 공격력과 마법 공격력이 향상되었습니다.
+*/
+ MSG_ID_D87 = 0xd87,
+/*20180131 to latest
+물리 공격력과 마법 공격력이 감소되었습니다.
+*/
+ MSG_ID_D88 = 0xd88,
+#endif
+#if PACKETVER >= 20180207
+/*20180207 to latest
+%s 출석체크 보상
+%s Attendance Check Reward
+*/
+ MSG_ID_D89 = 0xd89,
+/*20180207 to 20180511
+이벤트 기간 : %02d월 %02d일 ~ %2d월 %2d일 24:00까지
+Event period : From %02d/%02d ~ Until %2d/%2d (Month/Day) 24:00
+20180523 to latest
+이벤트 기간 : %02d월 %02d일 ~ %02d월 %02d일 24:00까지
+*/
+ MSG_ID_D8A = 0xd8a,
+/*20180207 to latest
+%d일차
+%d Day
+*/
+ MSG_ID_D8B = 0xd8b,
+/*20180207 to latest
+%d일차 출석체크
+클릭해주세요~!
+%d Day attendance check
+Please click~!
+*/
+ MSG_ID_D8C = 0xd8c,
+/*20180207 to latest
+%d일차 출석 성공!
+%d Day attendance success!
+*/
+ MSG_ID_D8D = 0xd8d,
+/*20180207 to latest
+D-day
+*/
+ MSG_ID_D8E = 0xd8e,
+/*20180207 to latest
+일
+Day
+*/
+ MSG_ID_D8F = 0xd8f,
+/*20180207 to latest
+출석체크에 실패하였습니다. 다시 실행해주세요.
+Attendance Check failed. Please run again.
+*/
+ MSG_ID_D90 = 0xd90,
+/*20180207 to latest
+출석체크
+Attendance Check
+*/
+ MSG_ID_D91 = 0xd91,
+/*20180207 to latest
+현재 출석체크 이벤트 기간이 아닙니다
+This is not the current attendance check event
+*/
+ MSG_ATTENDANCE_UNAVAILABLE = 0xd92,
+/*20180207 to 20180321
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다
+20180328 to latest
+길드 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+*/
+ MSG_ID_D93 = 0xd93,
+/*20180207 to latest
+개인 상납 경험치가 max에 도달하여, 더 이상 길드 경험치를 누적할 수 없습니다.
+
+*/
+ MSG_ID_D94 = 0xd94,
+#endif
+#if PACKETVER >= 20180213
+/*20180213 to latest
+메시지
+*/
+ MSG_ID_D95 = 0xd95,
+/*20180213 to latest
+트위터에 메세지 전송을 실패 했습니다.
+*/
+ MSG_ID_D96 = 0xd96,
+/*20180213 to latest
+영문 4자, 한글 2자 이상으로 입력해야 합니다.
+Enter 4 english words and 2 chinese words
+*/
+ MSG_ID_D97 = 0xd97,
+#endif
+#if PACKETVER >= 20180314
+/*20180314 to latest
+몬스터의 테이밍이 불가능한 지역입니다.
+*/
+ MSG_ID_D98 = 0xd98,
+#endif
+#if PACKETVER >= 20180328
+/*20180328 to latest
+순위를 가져오고 있습니다...
+*/
+ MSG_ID_D99 = 0xd99,
+/*20180328 to latest
+해당 스킬은 파티장일때만 사용 가능합니다.
+*/
+ MSG_ID_D9A = 0xd9a,
+/*20180328 to latest
+파트너의 SP가 부족하거나, 스킬 사용 불가 상태입니다.
+*/
+ MSG_ID_D9B = 0xd9b,
+/*20180328 to latest
+아르바이트 노점 강제 종료 알림메일
+*/
+ MSG_ID_D9C = 0xd9c,
+/*20180328 to latest
+안녕하세요. 운영팀입니다.
+해당 아르바이트 노점은 운영정책 위배되는 사항이 확인되어 강제 종료되었습니다.
+자세한 확인을 원하시는 경우에는 1:1 문의를 접수해 주시기 바랍니다.
+감사합니다
+*/
+ MSG_ID_D9D = 0xd9d,
+/*20180328 to latest
+50% 이상의 값을 입력할 수 없습니다.
+The guild tax rate can't be set to more than 50%.
+*/
+ MSG_ID_D9E = 0xd9e,
+/*20180328 to 20191204
+파티 가입 요청을 보냈습니다.
+20191211 to latest
+파티가 모험가 중개소에 등록되어, 파티장을 변경 할 수 없습니다.
+*/
+ MSG_ID_D9F = 0xd9f,
+/*20180328 to latest
+모험가 중개소에 파티를 등록할 수 없습니다
+*/
+ MSG_ID_DA0 = 0xda0,
+/*20180328 to latest
+수락
+*/
+ MSG_ID_DA1 = 0xda1,
+/*20180328 to latest
+거절
+*/
+ MSG_ID_DA2 = 0xda2,
+/*20180328 to 20191127
+설정 권한은 파티장에게 있습니다.
+20191204 to latest
+힐러
+*/
+ MSG_ID_DA3 = 0xda3,
+/*20180328 to latest
+해당 캐릭터를 찾을 수 없습니다.
+*/
+ MSG_ID_DA4 = 0xda4,
+/*20180328 to latest
+노점 강제 철거
+*/
+ MSG_ID_DA5 = 0xda5,
+/*20180328 to latest
+해당 파티의 파티장을 찾을 수 없습니다.
+*/
+ MSG_ID_DA6 = 0xda6,
+/*20180328 to latest
+잡레벨이 낮아 파티에 가입 할 수 없습니다.
+*/
+ MSG_ID_DA7 = 0xda7,
+/*20180328 to latest
+현재 요청자가 파티가입이 불가능한 지역에 있습니다.
+*/
+ MSG_ID_DA8 = 0xda8,
+/*20180328 to latest
+파티 인원수가 초과되었습니다.
+*/
+ MSG_ID_DA9 = 0xda9,
+/*20180328 to latest
+%s 파티의 파티장이 파티 가입을 승인했습니다.
+*/
+ MSG_ID_DAA = 0xdaa,
+/*20180328 to latest
+%s 파티의 파티장이 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAB = 0xdab,
+/*20180328 to latest
+%s 님이 이미 파티에 가입 중입니다.
+*/
+ MSG_ID_DAC = 0xdac,
+/*20180328 to latest
+%s 님의 파티 가입을 수락했습니다.
+*/
+ MSG_ID_DAD = 0xdad,
+/*20180328 to latest
+%s 님의 파티 가입을 거부했습니다.
+*/
+ MSG_ID_DAE = 0xdae,
+/*20180328 to latest
+파티 요청을 받을 수 없는 상태여서 %s님의 신청이 거절되었습니다.
+*/
+ MSG_ID_DAF = 0xdaf,
+#endif
+#if PACKETVER >= 20180411
+/*20180411 to latest
+모험가 중개소 리스트
+*/
+ MSG_ID_DB0 = 0xdb0,
+/*20180411 to latest
+파티 가입 요청
+*/
+ MSG_ID_DB1 = 0xdb1,
+/*20180411 to 20191113
+파티장이 아닌 경우, 모험가 중개소에 파티를 등록할 수 없습니다.
+20191127 to latest
+파티장이 아닌 경우 모험가 중개소에 파티를 등록할 수 없습니다.
+*/
+ MSG_ID_DB2 = 0xdb2,
+/*20180411 to latest
+파티 모집을 중단할 수 없습니다.
+*/
+ MSG_ID_DB3 = 0xdb3,
+/*20180411 to 20191127
+존재하지 않는 파티 글입니다.
+20191204 to latest
+보조
+Support
+*/
+ MSG_ID_DB4 = 0xdb4,
+#endif
+#if PACKETVER >= 20180425
+/*20180425 to latest
+Zoom Out
+*/
+ MSG_ID_DB5 = 0xdb5,
+/*20180425 to latest
+%s : Zoom Out을 켜거나 끌수 있습니다 On Off
+*/
+ MSG_ID_DB6 = 0xdb6,
+/*20180425 to latest
+Zoom Out 기능을 켭니다 (On)
+*/
+ MSG_ID_DB7 = 0xdb7,
+/*20180425 to latest
+Zoom Out 기능을 해제합니다 (Off)
+*/
+ MSG_ID_DB8 = 0xdb8,
+/*20180425 to latest
+/zoom
+*/
+ MSG_ID_DB9 = 0xdb9,
+/*20180425 to latest
+모험가 중개소
+*/
+ MSG_ID_DBA = 0xdba,
+/*20180425 to latest
+파티장인 경우, 가입 요청을 할 수 없습니다.
+*/
+ MSG_ID_DBB = 0xdbb,
+/*20180425 to 20191211
+모험가 중개소에 등록 중입니다. 잠시만 기다려 주세요.
+20191224 to latest
+파티 가입 최대 레벨은 최소 레벨 설정보다 높아야 합니다.
+*/
+ MSG_ID_DBC = 0xdbc,
+/*20180425 to latest
+더 이상 직업을 선택할 수 없습니다.
+*/
+ MSG_ID_DBD = 0xdbd,
+/*20180425 to 20191113
+게임 중 해당 유저의 가입 요청을 받지 않습니다.
+20191127 to latest
+게임 중 해당 유저의 가입 요청을 받지 않습니다.(클라이언트 종료 전까지 유효)
+*/
+ MSG_ID_DBE = 0xdbe,
+/*20180425 to latest
+잠시 후 다시 열어주시기 바랍니다.
+*/
+ MSG_ID_DBF = 0xdbf,
+/*20180425 to latest
+공성시작 전 %d분 동안은 해당 기능을 이용하실 수 없습니다.
+*/
+ MSG_ID_DC0 = 0xdc0,
+#endif
+#if PACKETVER >= 20180509
+/*20180509 to latest
+/viewclear
+*/
+ MSG_ID_DC1 = 0xdc1,
+/*20180509 to latest
+건물 반 투명화 ON
+*/
+ MSG_ID_DC2 = 0xdc2,
+/*20180509 to latest
+건물 반 투명화 OFF
+*/
+ MSG_ID_DC3 = 0xdc3,
+/*20180509 to latest
+건물 투명화
+*/
+ MSG_ID_DC4 = 0xdc4,
+/*20180509 to latest
+알로 되돌리기가 실패했습니다. 로덱스 작성창을 닫아주세요.
+*/
+ MSG_ID_DC5 = 0xdc5,
+#endif
+#if PACKETVER >= 20180523
+/*20180523 to latest
+Emblem Frame
+*/
+ MSG_ID_DC6 = 0xdc6,
+/*20180523 to latest
+Emblem 테두리를 그려줍니다
+*/
+ MSG_ID_DC7 = 0xdc7,
+/*20180523 to latest
+Emblem 테두리를 그려주지 않습니다
+*/
+ MSG_ID_DC8 = 0xdc8,
+#endif
+#if PACKETVER >= 20180605
+/*20180605 to latest
+장착된 무기가 없습니다.
+*/
+ MSG_ID_DC9 = 0xdc9,
+/*20180605 to latest
+에너지 구체가 부족합니다.
+*/
+ MSG_ID_DCA = 0xdca,
+/*20180605 to latest
+배울 수 없는 스킬(%s)이 포함되어있습니다.
+*/
+ MSG_ID_DCB = 0xdcb,
+/*20180605 to latest
+/frame
+*/
+ MSG_ID_DCC = 0xdcc,
+#endif
+#if PACKETVER >= 20180627
+/*20180627 to latest
+웨폰 블로킹 발동후 제한시간 내에 사용가능한 스킬입니다.
+*/
+ MSG_ID_DCD = 0xdcd,
+/*20180627 to latest
+아이디혹은 패스워드가 잘못되었읍니다.
+*/
+ MSG_ID_DCE = 0xdce,
+#endif
+#if PACKETVER >= 20180711
+/*20180711 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DCF = 0xdcf,
+/*20180711 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD0 = 0xdd0,
+/*20180711 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_DD1 = 0xdd1,
+#endif
+#if PACKETVER >= 20180725
+/*20180725 to 20180801
+'
+20180808 to latest
+영문이나 러시아어 단독으로만 사용이 가능합니다.
+Forbidden symbols in character name.
+*/
+ MSG_ID_DD2 = 0xdd2,
+/*20180725 to 20180801
+;
+20180822 to latest
+you must have an AccessTicket to login
+*/
+ MSG_ID_DD3 = 0xdd3,
+/*20180725 to 20180801
+--
+20180905 to latest
+창고를 불러오는 중입니다.
+Loading....
+*/
+ MSG_ID_DD4 = 0xdd4,
+#endif
+#if PACKETVER >= 20180905
+/*20180905 to latest
+NOW LOADING..
+Loading...
+*/
+ MSG_ID_DD5 = 0xdd5,
+#endif
+#if PACKETVER >= 20180919
+/*20180919 to latest
+삭제
+Delete
+*/
+ MSG_ID_DD6 = 0xdd6,
+/*20180919 to latest
+답장
+Reply
+*/
+ MSG_ID_DD7 = 0xdd7,
+/*20180919 to latest
+전송
+Send
+*/
+ MSG_ID_DD8 = 0xdd8,
+/*20180919 to latest
+이름확인
+Name Check
+*/
+ MSG_ID_DD9 = 0xdd9,
+/*20180919 to latest
+공지
+Notice
+*/
+ MSG_ID_DDA = 0xdda,
+/*20180919 to latest
+일반
+General
+*/
+ MSG_ID_DDB = 0xddb,
+/*20180919 to latest
+반송
+Clear
+*/
+ MSG_ID_DDC = 0xddc,
+/*20180919 to latest
+검색
+Search
+*/
+ MSG_ID_DDD = 0xddd,
+#endif
+#if PACKETVER >= 20181024
+/*20181024 to latest
+펫 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDE = 0xdde,
+/*20181024 to latest
+호문 먹이주기에 실패했습니다. 먹이를 줄 수 없는 상태입니다.
+*/
+ MSG_ID_DDF = 0xddf,
+/*20181024 to latest
+화폐
+*/
+ MSG_ID_DE0 = 0xde0,
+/*20181024 to latest
+%s %d개
+*/
+ MSG_ID_DE1 = 0xde1,
+/*20181024 to latest
+교환에 실패하였습니다.
+*/
+ MSG_ID_DE2 = 0xde2,
+/*20181024 to latest
+교환이 잘 이루어졌습니다.
+*/
+ MSG_ID_DE3 = 0xde3,
+/*20181024 to latest
+교환에 필요한 재화가 부족합니다.
+*/
+ MSG_ID_DE4 = 0xde4,
+/*20181024 to latest
+해당 아이템은 이미 판매되어 재고가 부족합니다.
+*/
+ MSG_ID_DE5 = 0xde5,
+/*20181024 to latest
+사망
+*/
+ MSG_ID_DE6 = 0xde6,
+/*20181024 to latest
+PvP
+*/
+ MSG_ID_DE7 = 0xde7,
+#endif
+#if PACKETVER >= 20181114
+/*20181114 to latest
+아이템 소지 확장
+*/
+ MSG_ID_DE8 = 0xde8,
+/*20181114 to latest
+^0000ff%s^000000을 소모하여, 아이템 최대 소지 종류수를 확장하시겠습니까?
+(^0000ff%d^000000)에서 (^0000ff%d^000000)로 확장됩니다.
+^ff0000※ 소모된 아이템 및 확장된 최대 소지 종류수는 되돌릴 수 없습니다.^000000
+*/
+ MSG_ID_DE9 = 0xde9,
+/*20181114 to latest
+아이템 최대 소지 종류수 확장에 실패하였습니다.
+*/
+ MSG_ID_DEA = 0xdea,
+/*20181114 to latest
+아이템 최대 소지 종류수 확장을 위해, 다른 작업을 종료하여 주시기 바랍니다.
+*/
+ MSG_ID_DEB = 0xdeb,
+/*20181114 to latest
+아이템 최대 소지 종류수 확장에 필요한 아이템을 소지하고 있지 않습니다.
+*/
+ MSG_ID_DEC = 0xdec,
+/*20181114 to latest
+더 이상 아이템 최대 소지 종류수를 확장 할 수 없습니다.
+*/
+ MSG_ID_DED = 0xded,
+/*20181114 to latest
+아이템 최대 소지 종류수 확장에 성공하였습니다.
+*/
+ MSG_ID_DEE = 0xdee,
+/*20181114 to latest
+같은 아이템을 %d개 이상 가질 수 없습니다.
+*/
+ MSG_ID_DEF = 0xdef,
+/*20181114 to latest
+소지 한계량 초과로 구입이 불가능합니다.
+*/
+ MSG_ID_DF0 = 0xdf0,
+/*20181114 to latest
+해당 아이템은 한 번에 한 개만 살 수 있습니다.
+*/
+ MSG_ID_DF1 = 0xdf1,
+#endif
+#if PACKETVER >= 20181212
+/*20181212 to latest
+성제
+*/
+ MSG_ID_DF2 = 0xdf2,
+/*20181212 to latest
+소울리퍼
+*/
+ MSG_ID_DF3 = 0xdf3,
+/*20181212 to latest
+설정한 내용은 정상 종료 시 서버에 저장됩니다.
+*/
+ MSG_ID_DF4 = 0xdf4,
+#endif
+#if PACKETVER >= 20181226
+/*20181226 to latest
+Capture Monster
+Taming monster
+*/
+ MSG_ID_DF5 = 0xdf5,
+/*20181226 to latest
+message
+*/
+ MSG_ID_DF6 = 0xdf6,
+#endif
+#if PACKETVER >= 20190116
+/*20190116 to latest
+TITLE
+Header
+*/
+ MSG_ID_DF7 = 0xdf7,
+/*20190116 to latest
+데미지 표기 확장
+*/
+ MSG_ID_DF8 = 0xdf8,
+#endif
+#if PACKETVER >= 20190130
+/*20190130 to latest
+맵 이름 표기
+*/
+ MSG_ID_DF9 = 0xdf9,
+#endif
+#if PACKETVER >= 20190213
+/*20190213 to latest
+시스템 메세지 : 현재 노점보기 기능이 %s 상태입니다. (/노점보기)
+*/
+ MSG_ID_DFA = 0xdfa,
+/*20190213 to latest
+수직 동기
+*/
+ MSG_ID_DFB = 0xdfb,
+/*20190213 to latest
+자료
+*/
+ MSG_ID_DFC = 0xdfc,
+/*20190213 to 20190227
+http://rodata.zhaouc.com/renwu.html#container
+20190313 to latest
+http://rodata.zhaouc.com/renwu.html
+*/
+ MSG_ID_DFD = 0xdfd,
+/*20190213 to latest
+작위
+*/
+ MSG_ID_DFE = 0xdfe,
+/*20190213 to latest
+프레임 제한
+*/
+ MSG_ID_DFF = 0xdff,
+#endif
+#if PACKETVER >= 20190220
+/*20190220 to latest
+%d개를 초과할 경우 더 이상 설치 할 수 없습니다.
+*/
+ MSG_ID_E00 = 0xe00,
+/*20190220 to latest
+목적지
+*/
+ MSG_ID_E01 = 0xe01,
+#endif
+#if PACKETVER >= 20190313
+/*20190313 to latest
+잠시 후 다시 시도해주세요.
+Please try again in a moment.
+*/
+ MSG_ID_E02 = 0xe02,
+/*20190313 to latest
+등록할 수 없는 파일입니다.
+*/
+ MSG_ID_E03 = 0xe03,
+#endif
+#if PACKETVER >= 20190327
+/*20190327 to latest
+선택 삭제
+*/
+ MSG_ID_E04 = 0xe04,
+/*20190327 to latest
+모두 삭제
+*/
+ MSG_ID_E05 = 0xe05,
+/*20190327 to latest
+[%s]편지함의 모든 메일을 삭제하시겠습니까?
+*/
+ MSG_ID_E06 = 0xe06,
+/*20190327 to latest
+선택 받기
+*/
+ MSG_ID_E07 = 0xe07,
+/*20190327 to latest
+모두 받기
+*/
+ MSG_ID_E08 = 0xe08,
+/*20190327 to latest
+선택한 메일의 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E09 = 0xe09,
+/*20190327 to latest
+[%s]편지함의 모든 첨부 물품을 받으시겠습니까?
+*/
+ MSG_ID_E0A = 0xe0a,
+/*20190327 to latest
+스킬바2
+*/
+ MSG_ID_E0B = 0xe0b,
+/*20190327 to latest
+스킬바 교체
+*/
+ MSG_ID_E0C = 0xe0c,
+#endif
+#if PACKETVER >= 20190403
+/*20190403 to latest
+←
+*/
+ MSG_ID_E0D = 0xe0d,
+/*20190403 to latest
+↑
+*/
+ MSG_ID_E0E = 0xe0e,
+/*20190403 to latest
+→
+*/
+ MSG_ID_E0F = 0xe0f,
+/*20190403 to latest
+↓
+*/
+ MSG_ID_E10 = 0xe10,
+/*20190403 to latest
+▤
+*/
+ MSG_ID_E11 = 0xe11,
+/*20190403 to latest
+←
+*/
+ MSG_ID_E12 = 0xe12,
+/*20190403 to latest
+로딩중에는 창을 닫을 수 없습니다.
+*/
+ MSG_ID_E13 = 0xe13,
+#endif
+#if PACKETVER >= 20190424
+/*20190424 to latest
+리딩 스펠북으로 저장된 마법이 없습니다.
+*/
+ MSG_ID_E14 = 0xe14,
+/*20190424 to latest
+이동 시 사용한 아이템은 재교환이 불가능합니다.
+*/
+ MSG_ID_E15 = 0xe15,
+/*20190424 to latest
+자유이동권을 구매 하였습니다
+*/
+ MSG_ID_E16 = 0xe16,
+/*20190424 to latest
+자유이동권 사용 중, 관련 아이템을 소모하지 않습니다.
+*/
+ MSG_ID_E17 = 0xe17,
+/*20190424 to latest
+적용
+*/
+ MSG_ID_E18 = 0xe18,
+/*20190424 to latest
+중지
+*/
+ MSG_ID_E19 = 0xe19,
+/*20190424 to latest
+자유이동권
+*/
+ MSG_ID_E1A = 0xe1a,
+/*20190424 to latest
+%d시간 이용, %s %d개
+*/
+ MSG_ID_E1B = 0xe1b,
+/*20190424 to latest
+자유이용권 사용중
+*/
+ MSG_ID_E1C = 0xe1c,
+/*20190424 to latest
+특성 스테이터스
+*/
+ MSG_ID_E1D = 0xe1d,
+/*20190424 to latest
+파워 파라메터
+^cc0000물리 공격력, 특성 공격력^ffffff 증가
+*/
+ MSG_ID_E1E = 0xe1e,
+/*20190424 to latest
+스테미나 파라메터
+^cc0000물리 저항력^ffffff 증가
+*/
+ MSG_ID_E1F = 0xe1f,
+/*20190424 to latest
+위즈덤 파라메터
+^cc0000마법 저항력^ffffff 증가
+*/
+ MSG_ID_E20 = 0xe20,
+/*20190424 to latest
+스펠 파라메터
+^cc0000마법 공격력, 마법 공격력^ffffff 증가
+*/
+ MSG_ID_E21 = 0xe21,
+/*20190424 to latest
+컨센트레이션 파라메터
+^cc0000명중률, 회피율, 특성 물리/마법 공격력^ffffff 증가
+*/
+ MSG_ID_E22 = 0xe22,
+/*20190424 to latest
+크리에이티브 파라메터
+^cc0000특성 힐 회복량, 크리티컬 데미지 비율^ffffff 증가
+*/
+ MSG_ID_E23 = 0xe23,
+/*20190424 to latest
+특성 물리 공격력
+*/
+ MSG_ID_E24 = 0xe24,
+/*20190424 to latest
+특성 마법 공격력
+*/
+ MSG_ID_E25 = 0xe25,
+/*20190424 to latest
+물리 저항력
+*/
+ MSG_ID_E26 = 0xe26,
+/*20190424 to latest
+마법 저항력
+*/
+ MSG_ID_E27 = 0xe27,
+/*20190424 to latest
+특성 힐 회복량
+*/
+ MSG_ID_E28 = 0xe28,
+/*20190424 to latest
+크리티컬 데미지 비율
+*/
+ MSG_ID_E29 = 0xe29,
+/*20190424 to latest
+특성 파라메터 레벨업에 사용되는 포인트
+*/
+ MSG_ID_E2A = 0xe2a,
+#endif
+#if PACKETVER >= 20190502
+/*20190502 to latest
+J.Lv
+*/
+ MSG_ID_E2B = 0xe2b,
+/*20190502 to latest
+AP
+*/
+ MSG_ID_E2C = 0xe2c,
+#endif
+#if PACKETVER >= 20190515
+/*20190515 to latest
+영지로 이동
+*/
+ MSG_ID_E2D = 0xe2d,
+/*20190515 to latest
+상업도/방어도 확인
+*/
+ MSG_ID_E2E = 0xe2e,
+/*20190515 to 20190605
+관리영지 "%s"(으)로 이동하시겠습니까?
+(1회 이동 시 마다 1,000제니가 소모됩니다.
+공성전 시간에는 제니의 소모가 100배로 증가합니다.)
+20190626 to latest
+관리영지 "%s"(으)로 이동하시겠습니까?
+이동 시 마다 %d제니가 소모됩니다.
+(공성전 시간에는 %d제니가 소모됩니다.)
+*/
+ MSG_ID_E2F = 0xe2f,
+/*20190515 to latest
+
+관리영지 "%s"
+
+방어도: %d / %d
+상업도: %d / %d
+*/
+ MSG_ID_E30 = 0xe30,
+/*20190515 to 20190717
+공성 영지 내에서는 다른 공성 영지로 이동 할 수 없습니다.
+20190724 to latest
+공성 영지에서는 사용할 수 없는 기능입니다.
+*/
+ MSG_ID_E31 = 0xe31,
+#endif
+#if PACKETVER >= 20190626
+/*20190626 to latest
+기본 기능 스킬을 습득하지 않은 캐릭터입니다.
+*/
+ MSG_ID_E32 = 0xe32,
+/*20190626 to latest
+접속하신 IP는 라그나로크 제로 이용이 불가능합니다.
+고객센터 또는 홈페이지로 문의해 주십시오.
+*/
+ MSG_ID_E33 = 0xe33,
+#endif
+#if PACKETVER >= 20190709
+/*20190709 to latest
+탑승/장착 해제
+*/
+ MSG_ID_E34 = 0xe34,
+/*20190709 to latest
+가져오기
+*/
+ MSG_ID_E35 = 0xe35,
+/*20190709 to latest
+직전 노점에 등록된 아이템 정보를 가져옵니다.
+*/
+ MSG_ID_E36 = 0xe36,
+/*20190709 to latest
+서버 이슈로 인해 로그인이 제한되고 있습니다.
+*/
+ MSG_ID_E37 = 0xe37,
+/*20190709 to latest
+메시지
+*/
+ MSG_ID_E38 = 0xe38,
+/*20190709 to latest
++18 이상만 플레이가 가능합니다.
+*/
+ MSG_ID_E39 = 0xe39,
+/*20190709 to latest
+3시간 이상의 게임 플레이를 권장하지 않습니다.
+*/
+ MSG_ID_E3A = 0xe3a,
+/*20190709 to latest
+AP가 부족합니다.
+*/
+ MSG_ID_E3B = 0xe3b,
+#endif
+#if PACKETVER >= 20190724
+/*20190724 to latest
+제련도가 높아서 조합할 수 없습니다.
+*/
+ MSG_ID_E3C = 0xe3c,
+/*20190724 to latest
+제련도가 조합에 필요한 요구치보다 높습니다.
+*/
+ MSG_ID_E3D = 0xe3d,
+/*20190724 to 20191106
+'카드가 끼워져있거나 인챈트 되어 있습니다.
+20191113 to latest
+카드가 끼워져있거나 인챈트 되어 있습니다.
+*/
+ MSG_ID_E3E = 0xe3e,
+#endif
+#if PACKETVER >= 20190814
+/*20190814 to latest
+∞
+?
+*/
+ MSG_ID_E3F = 0xe3f,
+/*20190814 to latest
+Z
+*/
+ MSG_ID_E40 = 0xe40,
+/*20190814 to latest
+Total : %s Zeny
+*/
+ MSG_ID_E41 = 0xe41,
+/*20190814 to latest
+계정한정판매 등록창
+Limited Account Registration Window
+*/
+ MSG_ID_E42 = 0xe42,
+/*20190814 to latest
+아이템 DB명
+Item DB Name
+*/
+ MSG_ID_E43 = 0xe43,
+/*20190814 to latest
+아이템 DB번호
+Item DB Number
+*/
+ MSG_ID_E44 = 0xe44,
+/*20190814 to latest
+판매 갯수
+Number of Sale
+*/
+ MSG_ID_E45 = 0xe45,
+/*20190814 to latest
+판매 시작시간
+Sale Start Time
+*/
+ MSG_ID_E46 = 0xe46,
+/*20190814 to latest
+판매 종료시간
+Sale end time
+*/
+ MSG_ID_E47 = 0xe47,
+/*20190814 to latest
+계정 한정
+Account only
+*/
+ MSG_ID_E48 = 0xe48,
+/*20190814 to 20190814
+판매기간 : %d월 %d일 ~ %d월 %d일
+20190828 to latest
+판매기간 : %d월 %d일 %d시 %d분
+Sale period:% d month% d day% d hours% d
+*/
+ MSG_ID_E49 = 0xe49,
+/*20190814 to 20190925
+구입가능 %d개
+% D available
+20191008 to latest
+계정당 구매가능
+*/
+ MSG_ID_E4A = 0xe4a,
+/*20190814 to latest
+%d개 한정
+limited to% d
+*/
+ MSG_ID_E4B = 0xe4b,
+/*20190814 to latest
+>> ItemName : %s / 수량 : %d / 판매기간 : %d월:%d일:%d시:%d분 ~ %d월:%d일:%d시:%d분
+>> ItemName:% s / Quantity:% d / Sales Period:% d Month:% d Day:% d Hour:% d Minute ~% d Month:% d Day:% d Hour:% d Minute
+*/
+ MSG_ID_E4C = 0xe4c,
+/*20190814 to latest
+Sold Out
+*/
+ MSG_ID_E4D = 0xe4d,
+/*20190814 to latest
+[%s]은(는) 현재 소환할 수 없는 지역에 있습니다.
+% s] is currently in a region that cannot be summoned.
+*/
+ MSG_ID_E4E = 0xe4e,
+#endif
+#if PACKETVER >= 20190828
+/*20190828 to latest
+~ %d월 %d일 %d시 %d분
+% d min% d days% d days
+*/
+ MSG_ID_E4F = 0xe4f,
+/*20190828 to latest
+상품을 더이상 추가할 수 없습니다
+Can't add any more items
+*/
+ MSG_ID_E50 = 0xe50,
+/*20190828 to latest
+장착 중인 아이템은 교환할 수 없습니다. 장착을 해제한 뒤 시도해 주시길 바랍니다.
+The item being mounted cannot be exchanged. Please unmount it and try again.
+*/
+ MSG_ID_E51 = 0xe51,
+#endif
+#if PACKETVER >= 20190911
+/*20190911 to latest
+길드 창고 이용 중엔 캐릭터 선택창으로 이동 할 수 없습니다.
+You can not move to the character selection window while using the Guild Warehouse.
+*/
+ MSG_ID_E52 = 0xe52,
+/*20190911 to latest
+아이템 태그가 포함되어 있어 사용할 수 없습니다.
+Item tag is included and cannot be used.
+*/
+ MSG_ID_E53 = 0xe53,
+/*20190911 to latest
+Monster
+*/
+ MSG_ID_E54 = 0xe54,
+/*20190911 to latest
+Unknown
+*/
+ MSG_ID_E55 = 0xe55,
+/*20190911 to latest
+Undead
+*/
+ MSG_ID_E56 = 0xe56,
+/*20190911 to latest
+Animal
+*/
+ MSG_ID_E57 = 0xe57,
+/*20190911 to latest
+Plant
+*/
+ MSG_ID_E58 = 0xe58,
+/*20190911 to latest
+Insect
+*/
+ MSG_ID_E59 = 0xe59,
+/*20190911 to latest
+Marine
+*/
+ MSG_ID_E5A = 0xe5a,
+/*20190911 to latest
+Devil
+*/
+ MSG_ID_E5B = 0xe5b,
+/*20190911 to latest
+Human
+*/
+ MSG_ID_E5C = 0xe5c,
+/*20190911 to latest
+Angel
+*/
+ MSG_ID_E5D = 0xe5d,
+/*20190911 to latest
+Dragon
+*/
+ MSG_ID_E5E = 0xe5e,
+/*20190911 to latest
+Balance: %s %c
+*/
+ MSG_ID_E5F = 0xe5f,
+/*20190911 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money will be deducted from your total balance.
+*/
+ MSG_ID_E60 = 0xe60,
+/*20190911 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %s캐시, 무료 %s캐시가 차감됩니다.
+Do you really want to purchase this item? %s Money and %s Free Points will be deducted from your total balance.
+*/
+ MSG_ID_E61 = 0xe61,
+/*20190911 to latest
+호출이 거부되었습니다.
+20190918 to 20190918
+[%s]의 호출이 거부되었습니다.
+*/
+ MSG_ID_E62 = 0xe62,
+#endif
+#if PACKETVER >= 20190918
+/*20190918 to latest
+구매 한도액은 소지액을 초과할 수 없습니다.
+*/
+ MSG_ID_E63 = 0xe63,
+/*20190918 to latest
+노점을 여는데 실패하였습니다. 구매노점 개설을 닫아주시기 바랍니다.
+*/
+ MSG_ID_E64 = 0xe64,
+#endif
+#if PACKETVER >= 20190925
+/*20190925 to latest
+판매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E65 = 0xe65,
+/*20190925 to latest
+구매 노점 아이템 리스트가 저장되었습니다.
+*/
+ MSG_ID_E66 = 0xe66,
+#endif
+#if PACKETVER >= 20191008
+/*20191008 to latest
+VTC 인증에 실패하였습니다.
+*/
+ MSG_ID_E67 = 0xe67,
+/*20191008 to latest
+물물교환 중에는 장비를 착용할 수 없습니다.
+*/
+ MSG_ID_E68 = 0xe68,
+/*20191008 to latest
+교환하려는 품목
+*/
+ MSG_ID_E69 = 0xe69,
+/*20191008 to latest
+ 1차, 2차, 3차 직업 스킬 %d개를 더 올려 주십시오.
+*/
+ MSG_ID_E6A = 0xe6a,
+#endif
+#if PACKETVER >= 20191023
+/*20191023 to latest
+같은 아이템은 %d개까지 소유할 수 있습니다.
+*/
+ MSG_ID_E6B = 0xe6b,
+/*20191023 to latest
+같은 아이템은 한 번에 %d개까지 교환할 수 있습니다.
+*/
+ MSG_ID_E6C = 0xe6c,
+/*20191023 to latest
+해당 로덱스는 "%s"서버에서 열 수 있습니다.
+*/
+ MSG_ID_E6D = 0xe6d,
+/*20191023 to latest
+[공지]편지함의 모든 메일을 삭제하시겠습니까 ?
+(해당 "%s"서버의 메일만 삭제됩니다.)
+*/
+ MSG_ID_E6E = 0xe6e,
+/*20191023 to latest
+[공지]편지함의 모든 첨부 물품을 받으시겠습니까?
+(해당 "%s"서버의 메일의 물품만 받으실 수 있습니다.)
+*/
+ MSG_ID_E6F = 0xe6f,
+/*20191023 to latest
+해당 메일은 "%s"서버에서만 삭제 가능합니다.
+*/
+ MSG_ID_E70 = 0xe70,
+/*20191023 to latest
+해당 메일은 "%s"서버에서만 물품 받기가 가능합니다.
+*/
+ MSG_ID_E71 = 0xe71,
+/*20191023 to latest
+해당 메일은 "%s"서버에서만 내용읽기가 가능합니다.
+*/
+ MSG_ID_E72 = 0xe72,
+#endif
+#if PACKETVER >= 20191106
+/*20191106 to latest
+합계 : %d z
+*/
+ MSG_ID_E73 = 0xe73,
+/*20191106 to latest
+메세지
+*/
+ MSG_ID_E74 = 0xe74,
+/*20191106 to latest
+구매상점 개설 중에는 개인상점의 물건을 구입할 수 없습니다.
+*/
+ MSG_ID_E75 = 0xe75,
+#endif
+#if PACKETVER >= 20191113
+/*20191113 to latest
+등급강화가 성공적으로 되었습니다.
+*/
+ MSG_ID_E76 = 0xe76,
+/*20191113 to latest
+등급강화가 실패하였습니다.
+*/
+ MSG_ID_E77 = 0xe77,
+/*20191113 to latest
+등급 수치가 하향 조정 되었습니다.
+*/
+ MSG_ID_E78 = 0xe78,
+/*20191113 to latest
+장비가 파괴되었습니다.
+*/
+ MSG_ID_E79 = 0xe79,
+/*20191113 to latest
+장비가 보호되었습니다.
+*/
+ MSG_ID_E7A = 0xe7a,
+/*20191113 to latest
+재료가 선택되지 않았습니다.
+*/
+ MSG_ID_E7B = 0xe7b,
+/*20191113 to latest
+재료가 부족합니다.
+*/
+ MSG_ID_E7C = 0xe7c,
+/*20191113 to latest
+소지 금액이 부족합니다.
+*/
+ MSG_ID_E7D = 0xe7d,
+/*20191113 to latest
+아이템 공간이 부족합니다.
+*/
+ MSG_ID_E7E = 0xe7e,
+/*20191113 to latest
+장비가 보호되고 있습니다.
+*/
+ MSG_ID_E7F = 0xe7f,
+/*20191113 to latest
+장비가 파괴될 수 있습니다.
+*/
+ MSG_ID_E80 = 0xe80,
+/*20191113 to latest
+등급강화 실패 시 등급이 내려갑니다.
+*/
+ MSG_ID_E81 = 0xe81,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다. 로덱스를 강제 종료하였습니다.
+*/
+ MSG_ID_E82 = 0xe82,
+/*20191113 to latest
+등급강화 중에는 로덱스를 사용할 수 없습니다.
+*/
+ MSG_ID_E83 = 0xe83,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다. 은행을 강제 종료하였습니다.
+*/
+ MSG_ID_E84 = 0xe84,
+/*20191113 to latest
+등급강화 중에는 은행을 사용할 수 없습니다.
+*/
+ MSG_ID_E85 = 0xe85,
+/*20191113 to latest
+[%s] 님이 등급강화를 성공하여, [%s등급 %s] 아이템을 획득하였습니다.
+*/
+ MSG_ID_E86 = 0xe86,
+/*20191113 to latest
+[%s] 님이 [%s등급 %s] 아이템의 등급강화에 실패하였습니다.
+*/
+ MSG_ID_E87 = 0xe87,
+/*20191113 to latest
+등급 강화가 불가능한 장비입니다.
+*/
+ MSG_ID_E88 = 0xe88,
+/*20191113 to latest
+체인지 메테리얼
+*/
+ MSG_ID_E89 = 0xe89,
+/*20191113 to latest
+가나다 정렬
+*/
+ MSG_ID_E8A = 0xe8a,
+/*20191113 to 20191224
+기본 결과물은 %s %d개 이나, 낮은 확률로 최대 %d개까지 생성될 수 있습니다.
+20200115 to latest
+※[%s] %d~%d개 제작
+*/
+ MSG_ID_E8B = 0xe8b,
+/*20191113 to latest
+성공 %d%%
+*/
+ MSG_ID_E8C = 0xe8c,
+/*20191113 to latest
+아이템 태그는 소지한 아이템만 태그할 수 있습니다.
+*/
+ MSG_ID_E8D = 0xe8d,
+#endif
+#if PACKETVER >= 20191127
+/*20191127 to latest
+공격력 및 특성 공격력이 증가되었습니다.
+*/
+ MSG_ID_E8E = 0xe8e,
+/*20191127 to latest
+강인한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E8F = 0xe8f,
+/*20191127 to latest
+HP 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_E90 = 0xe90,
+/*20191127 to latest
+굳건한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E91 = 0xe91,
+/*20191127 to latest
+공격 속도 및 유도 공격 확률이 증가되었습니다.
+*/
+ MSG_ID_E92 = 0xe92,
+/*20191127 to latest
+신실한 신념 효과가 해제되었습니다.
+*/
+ MSG_ID_E93 = 0xe93,
+/*20191127 to latest
+POW, CRT 및 CON 이 증가되었습니다.
+*/
+ MSG_ID_E94 = 0xe94,
+/*20191127 to latest
+베네딕툼 효과가 해제되었습니다.
+*/
+ MSG_ID_E95 = 0xe95,
+/*20191127 to latest
+SPL, WIS 및 CRT 가 증가되었습니다.
+*/
+ MSG_ID_E96 = 0xe96,
+/*20191127 to latest
+렐리지오 효과가 해제되었습니다.
+*/
+ MSG_ID_E97 = 0xe97,
+/*20191127 to latest
+특성 공격력 및 특성 마법 공격력이 증가되었습니다.
+*/
+ MSG_ID_E98 = 0xe98,
+/*20191127 to latest
+콤페텐티아 효과가 해제되었습니다.
+*/
+ MSG_ID_E99 = 0xe99,
+/*20191127 to latest
+크리티컬 데미지 비율이 증가되었습니다.
+*/
+ MSG_ID_E9A = 0xe9a,
+/*20191127 to latest
+프레센스 아치에스 효과가 해제되었습니다.
+*/
+ MSG_ID_E9B = 0xe9b,
+/*20191127 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9C = 0xe9c,
+/*20191127 to latest
+아르구투스 텔룸 효과가 해제되었습니다.
+*/
+ MSG_ID_E9D = 0xe9d,
+/*20191127 to latest
+마법 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_E9E = 0xe9e,
+/*20191127 to latest
+아르구투스 비타 효과가 해제되었습니다.
+*/
+ MSG_ID_E9F = 0xe9f,
+/*20191127 to latest
+Num: %d/%d Weight: %d/%d
+*/
+ MSG_ID_EA0 = 0xea0,
+#endif
+#if PACKETVER >= 20191204
+/*20191204 to latest
+서번트 웨폰 효과가 해제되었습니다.
+*/
+ MSG_ID_EA1 = 0xea1,
+/*20191204 to latest
+챠징 피어스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA2 = 0xea2,
+/*20191204 to latest
+비고르 효과가 해제되었습니다.
+*/
+ MSG_ID_EA3 = 0xea3,
+/*20191204 to latest
+공격력이 증가하고, 방어력이 감소되었습니다.
+*/
+ MSG_ID_EA4 = 0xea4,
+/*20191204 to latest
+어택 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA5 = 0xea5,
+/*20191204 to latest
+방어력이 증가하고, 공격력이 감소되었습니다.
+*/
+ MSG_ID_EA6 = 0xea6,
+/*20191204 to latest
+가드 스탠스 효과가 해제되었습니다.
+*/
+ MSG_ID_EA7 = 0xea7,
+/*20191204 to latest
+배리어가 부여되었습니다.
+*/
+ MSG_ID_EA8 = 0xea8,
+/*20191204 to latest
+가디언 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EA9 = 0xea9,
+/*20191204 to latest
+헌신 효과로 받는 데미지가 감소되었습니다.
+*/
+ MSG_ID_EAA = 0xeaa,
+/*20191204 to latest
+리바운드 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAB = 0xeab,
+/*20191204 to latest
+성속성 마법 데미지와 암/불사속성 내성이 증가되었습니다.
+*/
+ MSG_ID_EAC = 0xeac,
+/*20191204 to latest
+홀리 쉴드 효과가 해제되었습니다.
+*/
+ MSG_ID_EAD = 0xead,
+/*20191204 to latest
+즉시 부활 효과가 부여되었습니다.
+*/
+ MSG_ID_EAE = 0xeae,
+/*20191204 to latest
+얼티메이트 세크리파이스 효과가 해제되었습니다.
+*/
+ MSG_ID_EAF = 0xeaf,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB0 = 0xeb0,
+/*20191204 to latest
+클라이막스 효과가 해제되었습니다.
+*/
+ MSG_ID_EB1 = 0xeb1,
+/*20191204 to latest
+특정 스킬의 효능이 변경되었습니다.
+*/
+ MSG_ID_EB2 = 0xeb2,
+/*20191204 to latest
+쉐도우 익시드 효과가 해제되었습니다.
+*/
+ MSG_ID_EB3 = 0xeb3,
+/*20191204 to latest
+물리 저항력 무시 효과가 부여되었습니다.
+*/
+ MSG_ID_EB4 = 0xeb4,
+/*20191204 to latest
+포텐트 베넘 효과가 해제되었습니다.
+*/
+ MSG_ID_EB5 = 0xeb5,
+/*20191204 to latest
+매 공격 시, 일정 확률로 대상이 받는 데미지를 증가시킵니다.
+*/
+ MSG_ID_EB6 = 0xeb6,
+/*20191204 to latest
+인챈팅 쉐도우 효과가 해제되었습니다.
+*/
+ MSG_ID_EB7 = 0xeb7,
+/*20191204 to latest
+토벌 카운트 On
+*/
+ MSG_ID_EB8 = 0xeb8,
+/*20191204 to latest
+토벌 카운트 Off
+*/
+ MSG_ID_EB9 = 0xeb9,
+#endif
+#if PACKETVER >= 20191211
+/*20191211 to latest
+대상의 AP가 최대치입니다
+*/
+ MSG_ID_EBA = 0xeba,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBB = 0xebb,
+/*20191211 to latest
+ ^ff0000본 아이템을 구매 후 7일 이내에는 청약 철회가 가능합니다. 다만, 7일이 지났거나 아이템을 개봉하시면 청약 철회 대상에서 제외 됩니다.또한 구매시 사용된 무료캐시는 청약철회시 반환되지 않습니다.일부(이벤트) 아이템의 경우 이벤트 종료 시 삭제될 수 있으며, 아이템 설명 내 기재된 삭제기간을 확인해 주시기 바랍니다.^000000 정말로 아이템을 구매하시겠습니까? 구매하실 경우 일반 %d캐시, 무료 %d캐시가 차감됩니다.
+*/
+ MSG_ID_EBC = 0xebc,
+#endif
+#if PACKETVER >= 20191224
+/*20191224 to latest
+서번트 웨폰 %d개가 필요합니다.
+*/
+ MSG_ID_EBD = 0xebd,
+/*20191224 to latest
+https://member.gnjoy.com.tw/billing.aspx
+*/
+ MSG_ID_EBE = 0xebe,
+#endif
+#if PACKETVER >= 20200115
+/*20200115 to latest
+역순 정렬
+*/
+ MSG_ID_EBF = 0xebf,
+/*20200115 to latest
+검색 내용 입력
+*/
+ MSG_ID_EC0 = 0xec0,
+/*20200115 to latest
+검색
+Search
+*/
+ MSG_ID_EC1 = 0xec1,
+/*20200115 to latest
+리서치 리포트 상태가 됩니다.
+*/
+ MSG_ID_EC2 = 0xec2,
+/*20200115 to latest
+리서치 리포트 상태가 해제됩니다.
+*/
+ MSG_ID_EC3 = 0xec3,
+/*20200115 to latest
+제조에 성공 했습니다.
+*/
+ MSG_ID_EC4 = 0xec4,
+/*20200115 to latest
+제조에 실패 했습니다.
+*/
+ MSG_ID_EC5 = 0xec5,
+/*20200115 to latest
+쉐도우 장비가 파괴 및 해제에서 보호됩니다.
+*/
+ MSG_ID_EC6 = 0xec6,
+/*20200115 to latest
+풀 쉐도우 프로텍션이 해제됩니다.
+*/
+ MSG_ID_EC7 = 0xec7,
+/*20200115 to latest
+식물형, 무형 몬스터에게 주는 데미지가 증가합니다.
+*/
+ MSG_ID_EC8 = 0xec8,
+/*20200115 to latest
+지옥 나무의 가루효과가 사라집니다.
+*/
+ MSG_ID_EC9 = 0xec9,
+#endif
+#if PACKETVER >= 20200129
+/*20200129 to latest
+공격 장치가 활성화되었습니다.
+*/
+ MSG_ID_ECA = 0xeca,
+/*20200129 to latest
+공격 장치가 해제되었습니다.
+*/
+ MSG_ID_ECB = 0xecb,
+/*20200129 to latest
+물리 방어력 및 물리 저항력이 증가되었습니다.
+*/
+ MSG_ID_ECC = 0xecc,
+/*20200129 to latest
+방어 장치가 해제되었습니다.
+*/
+ MSG_ID_ECD = 0xecd,
+#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+검색
+Search
+*/
+ MSG_ID_ECE = 0xece,
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
+
+};
+#endif /* MAP_MESSAGES_ZERO_H */
diff --git a/src/map/mob.c b/src/map/mob.c
index c765e7d63..dcbdccedd 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,6 +44,7 @@
#include "map/script.h"
#include "map/skill.h"
#include "map/status.h"
+#include "map/achievement.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
@@ -64,7 +65,7 @@
#include <stdlib.h>
#include <string.h>
-struct mob_interface mob_s;
+static struct mob_interface mob_s;
struct mob_interface *mob;
#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
@@ -77,6 +78,7 @@ struct mob_interface *mob;
// Move probability for mobs away from players (rate of 1000 minute)
// in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
#define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0)
+#define MOB_MAX_CASTTIME (10 * 60 * 1000) // Maximum cast time for monster skills. (10 minutes)
#define MOB_MAX_DELAY (24*3600*1000)
#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
@@ -88,6 +90,7 @@ struct item_drop_ratio {
int mob_id[MAX_ITEMRATIO_MOBS];
};
static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB];
+static struct DBMap *item_drop_ratio_other_db = NULL;
static struct eri *item_drop_ers; //For loot drops delay structures.
static struct eri *item_drop_list_ers;
@@ -97,12 +100,14 @@ static struct {
int class_[350];
} summon[MAX_RANDOMMONSTER];
-struct mob_db *mob_db(int index) {
+static struct mob_db *mob_db(int index)
+{
if (index < 0 || index > MAX_MOB_DB || mob->db_data[index] == NULL)
return mob->dummy;
return mob->db_data[index];
}
-struct mob_chat *mob_chat(short id) {
+static struct mob_chat *mob_chat(short id)
+{
if(id <= 0 || id > MAX_MOB_CHAT || mob->chat_db[id] == NULL)
return NULL;
return mob->chat_db[id];
@@ -111,7 +116,7 @@ struct mob_chat *mob_chat(short id) {
/*==========================================
* Mob is searched with a name.
*------------------------------------------*/
-int mobdb_searchname(const char *str)
+static int mobdb_searchname(const char *str)
{
int i;
@@ -130,7 +135,8 @@ int mobdb_searchname(const char *str)
return 0;
}
-int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag) {
+static int mobdb_searchname_array_sub(struct mob_db *monster, const char *str, int flag)
+{
nullpo_ret(monster);
if (monster == mob->dummy)
@@ -157,7 +163,45 @@ int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag
/*==========================================
* MvP Tomb [GreenBox]
*------------------------------------------*/
-void mvptomb_create(struct mob_data *md, char *killer, time_t time)
+ /// Creates a timer to spawn a tomb
+ /// @param nd : The tomb
+static void mvptomb_spawn_delayed(struct npc_data *nd)
+{
+ nullpo_retv(nd);
+
+ if (nd->u.tomb.spawn_timer != INVALID_TIMER)
+ timer->delete(nd->u.tomb.spawn_timer, mob->mvptomb_delayspawn);
+
+ nd->u.tomb.spawn_timer = timer->add(timer->gettick() + battle_config.mvp_tomb_spawn_delay, mob->mvptomb_delayspawn, nd->bl.id, 0);
+}
+
+/// Spawns a tomb after the delay has ended
+/// @param tid : Timer id
+/// @param tick : current tick
+/// @param id : NPC Id
+/// @param data : 0
+static int mvptomb_delayspawn(int tid, int64 tick, int id, intptr_t data)
+{
+ struct npc_data *nd = map->id2nd(id);
+
+ if (nd == NULL)
+ return 0;
+
+ if (nd->u.tomb.spawn_timer != tid) {
+ ShowError("mvptomb_delay_spawn: Timer mismatch: %d != %d\n", tid, nd->u.tomb.spawn_timer);
+ return 0;
+ }
+
+ nd->u.tomb.spawn_timer = INVALID_TIMER;
+
+ // Sets view data to make the tomb visible and notifies client
+ status->set_viewdata(&nd->bl, nd->class_);
+ clif->spawn(&(nd->bl));
+
+ return 0;
+}
+
+static void mvptomb_create(struct mob_data *md, char *killer, time_t time)
{
struct npc_data *nd;
@@ -172,6 +216,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
nd->u.tomb.md = md;
nd->u.tomb.kill_time = time;
+ nd->u.tomb.spawn_timer = INVALID_TIMER;
if (killer)
safestrncpy(nd->u.tomb.killer_name, killer, NAME_LENGTH);
@@ -180,11 +225,13 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
map->addnpc(nd->bl.m, nd);
map->addblock(&nd->bl);
- status->set_viewdata(&nd->bl, nd->class_);
- clif->spawn(&nd->bl);
+
+ // Tomb npc is created but not yet visible, we set view data and spawn it after some time
+ mob->mvptomb_spawn_delayed(nd);
}
-void mvptomb_destroy(struct mob_data *md) {
+static void mvptomb_destroy(struct mob_data *md)
+{
struct npc_data *nd;
nullpo_retv(md);
@@ -193,6 +240,14 @@ void mvptomb_destroy(struct mob_data *md) {
m = nd->bl.m;
+ struct s_mapiterator *iter = mapit_geteachpc();
+ for (struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (sd->npc_id == nd->bl.id) {
+ sd->state.npc_unloaded = 1;
+ }
+ }
+ mapit->free(iter);
+
clif->clearunit_area(&nd->bl,CLR_OUTSIGHT);
map->delblock(&nd->bl);
@@ -204,6 +259,9 @@ void mvptomb_destroy(struct mob_data *md) {
map->list[m].npc[map->list[m].npc_num] = NULL;
}
+ if (nd->u.tomb.spawn_timer != INVALID_TIMER)
+ timer->delete(nd->u.tomb.spawn_timer, mob->mvptomb_delayspawn);
+
map->deliddb(&nd->bl);
aFree(nd);
@@ -215,7 +273,7 @@ void mvptomb_destroy(struct mob_data *md) {
/*==========================================
* Founds up to N matches. Returns number of matches [Skotlex]
*------------------------------------------*/
-int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int flag)
+static int mobdb_searchname_array(struct mob_db **data, int size, const char *str, int flag)
{
int count = 0, i;
struct mob_db* monster;
@@ -236,7 +294,7 @@ int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int
/*==========================================
* Id Mob is checked.
*------------------------------------------*/
-int mobdb_checkid(const int id)
+static int mobdb_checkid(const int id)
{
if (mob->db(id) == mob->dummy)
return 0;
@@ -248,7 +306,7 @@ int mobdb_checkid(const int id)
/*==========================================
* Returns the view data associated to this mob class.
*------------------------------------------*/
-struct view_data * mob_get_viewdata(int class_)
+static struct view_data *mob_get_viewdata(int class_)
{
if (mob->db(class_) == mob->dummy)
return 0;
@@ -257,7 +315,7 @@ struct view_data * mob_get_viewdata(int class_)
/*==========================================
* Cleans up mob-spawn data to make it "valid"
*------------------------------------------*/
-int mob_parse_dataset(struct spawn_data *data)
+static int mob_parse_dataset(struct spawn_data *data)
{
size_t len;
@@ -273,21 +331,30 @@ int mob_parse_dataset(struct spawn_data *data)
memmove(data->eventname, data->eventname+1, len-1);
}
- if(strcmp(data->name,"--en--")==0)
+ if (strcmp(data->name, DEFAULT_MOB_NAME) == 0)
safestrncpy(data->name, mob->db(data->class_)->name, sizeof(data->name));
- else if(strcmp(data->name,"--ja--")==0)
+ else if (strcmp(data->name, DEFAULT_MOB_JNAME) == 0)
safestrncpy(data->name, mob->db(data->class_)->jname, sizeof(data->name));
return 1;
}
-/*==========================================
- * Generates the basic mob data using the spawn_data provided.
- *------------------------------------------*/
-struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
- struct mob_data *md = NULL;
+
+/**
+ * Generates basic mob data by using the passed spawn data.
+ *
+ * @param data The mobs spawn data.
+ * @param npc_id If spawned by NPC script, this holds the ID of the invoking NPC.
+ * @return The generated mob data, later used to spawn the mob.
+ *
+ **/
+static struct mob_data *mob_spawn_dataset(struct spawn_data *data, int npc_id)
+{
nullpo_retr(NULL, data);
- CREATE(md, struct mob_data, 1);
- md->bl.id= npc->get_new_npc_id();
+
+ struct mob_data *md = (struct mob_data *)aCalloc(1, sizeof(struct mob_data));
+
+ memcpy(md->name, data->name, NAME_LENGTH);
+ md->bl.id = npc->get_new_npc_id();
md->bl.type = BL_MOB;
md->bl.m = data->m;
md->bl.x = data->x;
@@ -295,24 +362,29 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
md->class_ = data->class_;
md->state.boss = data->state.boss;
md->db = mob->db(md->class_);
+ md->npc_id = npc_id;
+ md->spawn_timer = INVALID_TIMER;
+ md->deletetimer = INVALID_TIMER;
+ md->skill_idx = -1;
+
if (data->level > 0 && data->level <= MAX_LEVEL)
md->level = data->level;
- memcpy(md->name, data->name, NAME_LENGTH);
- if (data->state.ai)
+
+ if (data->state.ai > 0)
md->special_state.ai = data->state.ai;
- if (data->state.size)
+
+ if (data->state.size > 0)
md->special_state.size = data->state.size;
- if (data->eventname[0] && strlen(data->eventname) >= 4)
+
+ if (data->eventname[0] != '\0' && strlen(data->eventname) >= 4)
memcpy(md->npc_event, data->eventname, 50);
- if(md->db->status.mode&MD_LOOTER)
- md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
- md->spawn_timer = INVALID_TIMER;
- md->deletetimer = INVALID_TIMER;
- md->skill_idx = -1;
+
+ if ((md->db->status.mode & MD_LOOTER) == MD_LOOTER)
+ md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE, sizeof(struct item));
+
status->set_viewdata(&md->bl, md->class_);
status->change_init(&md->bl);
unit->dataset(&md->bl);
-
map->addiddb(&md->bl);
return md;
}
@@ -330,7 +402,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
* &8: Selected monster must have normal spawn.
* lv: Mob level to check against
*------------------------------------------*/
-int mob_get_random_id(int type, int flag, int lv)
+static int mob_get_random_id(int type, int flag, int lv)
{
struct mob_db *monster;
int i=0, class_;
@@ -361,7 +433,8 @@ int mob_get_random_id(int type, int flag, int lv)
/*==========================================
* Kill Steal Protection [Zephyrus]
*------------------------------------------*/
-bool mob_ksprotected(struct block_list *src, struct block_list *target) {
+static bool mob_ksprotected(struct block_list *src, struct block_list *target)
+{
struct block_list *s_bl, *t_bl;
struct map_session_data
*sd, // Source
@@ -374,6 +447,9 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
if( !battle_config.ksprotection )
return false; // KS Protection Disabled
+ if (status->isdead(target) != 0)
+ return false; // Target is dead.
+
if( !(md = BL_CAST(BL_MOB,target)) )
return false; // Target is not MOB
@@ -420,8 +496,8 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
// Message to KS
if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 )
{
- sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name);
- clif_disp_onlyself(sd, output, strlen(output));
+ sprintf(output, msg_sd(sd, 890), pl_sd->status.name); // [KS Warning!! - Owner : %s]
+ clif_disp_onlyself(sd, output);
sd->ks_floodprotect_tick = tick + 2000;
}
@@ -429,8 +505,8 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
// Message to Owner
if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 )
{
- sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name);
- clif_disp_onlyself(pl_sd, output, strlen(output));
+ sprintf(output, msg_sd(pl_sd, 891), sd->status.name); // [Watch out! %s is trying to KS you!]
+ clif_disp_onlyself(pl_sd, output);
pl_sd->ks_floodprotect_tick = tick + 2000;
}
@@ -444,7 +520,24 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
return false;
}
-struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai)
+/**
+ * Prepares a mob's spawn data.
+ *
+ * @param bl The invoking character's block list.
+ * @param m The ID of the map where the mob should be spawned.
+ * @param x The x coordinate where the mob should be spawned.
+ * @param y The y coordinate where the mob should be spawned.
+ * @param mobname The mob's display name.
+ * @param class_ The mob's ID in database.
+ * @param event The name of the event which should be executed when the mob is killed.
+ * @param size The mob's size.
+ * @param ai The mob's AI.
+ * @param npc_id If spawned by NPC script, this holds the ID of the invoking NPC.
+ * @return The mob data generated by mob->spawn_dataset().
+ *
+ **/
+static struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_,
+ const char *event, unsigned int size, unsigned int ai, int npc_id)
{
struct spawn_data data;
@@ -455,89 +548,113 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int
data.state.size = size;
data.state.ai = ai;
- if (mobname)
+ if (mobname != NULL)
safestrncpy(data.name, mobname, sizeof(data.name));
+ else if (battle_config.override_mob_names == 1)
+ strcpy(data.name, DEFAULT_MOB_NAME);
else
- if (battle_config.override_mob_names == 1)
- strcpy(data.name, "--en--");
- else
- strcpy(data.name, "--ja--");
+ strcpy(data.name, DEFAULT_MOB_JNAME);
- if (event)
+ if (event != NULL)
safestrncpy(data.eventname, event, sizeof(data.eventname));
- // Locate spot next to player.
- if (bl && (x < 0 || y < 0))
+ /** Locate spot next to player. **/
+ if (bl != NULL && (x < 0 || y < 0))
map->search_freecell(bl, m, &x, &y, 1, 1, 0);
- // if none found, pick random position on map
+ /** If none found, pick random position on map. **/
if (x <= 0 || x >= map->list[m].xs || y <= 0 || y >= map->list[m].ys)
map->search_freecell(NULL, m, &x, &y, -1, -1, 1);
data.x = x;
data.y = y;
- if (!mob->parse_dataset(&data))
+ if (mob->parse_dataset(&data) == 0)
return NULL;
- return mob->spawn_dataset(&data);
+ return mob->spawn_dataset(&data, npc_id);
}
-/*==========================================
- * Spawn a single mob on the specified coordinates.
- *------------------------------------------*/
-int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) {
- struct mob_data* md = NULL;
- int count, lv;
+/**
+ * Spawns a given amount of mobs.
+ *
+ * @param sd The invoking character.
+ * @param m The ID of the map where the mob should be spawned.
+ * @param x The x coordinate where the mob should be spawned.
+ * @param y The y coordinate where the mob should be spawned.
+ * @param mobname The mob's display name.
+ * @param class_ The mob's ID in database.
+ * @param amount The amount of mobs to spawn.
+ * @param event The name of the event which should be executed when the mob is killed.
+ * @param size The mob's size.
+ * @param ai The mob's AI.
+ * @return The last spawned mob's GID, or 0 if spawning failed.
+ *
+ **/
+static int mob_once_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *mobname, int class_,
+ int amount, const char *event, unsigned int size, unsigned int ai)
+{
bool no_guardian_data = false;
- if( ai && ai&0x200 ) {
+ if (ai > 0 && (ai & 0x200) == 0x200) {
no_guardian_data = true;
- ai &=~ 0x200;
+ ai &= ~0x200;
}
if (m < 0 || amount <= 0)
- return 0; // invalid input
+ return 0;
- lv = (sd) ? sd->status.base_level : 255;
+ struct mob_data *md = NULL;
- for (count = 0; count < amount; count++) {
- int c = (class_ >= 0) ? class_ : mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv);
- md = mob->once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai);
+ for (int i = 0; i < amount; i++) {
+ int mob_id = class_;
- if (!md)
+ if (mob_id < 0) {
+ mob_id = mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv == 1) ? 3 : 1,
+ (sd != NULL) ? sd->status.base_level : 255);
+ }
+
+ md = mob->once_spawn_sub((sd != NULL) ? &sd->bl : NULL, m, x, y, mobname, mob_id, event, size, ai,
+ (sd != NULL) ? sd->npc_id : 0);
+
+ if (md == NULL)
continue;
if (class_ == MOBID_EMPELIUM && !no_guardian_data) {
- struct guild_castle* gc = guild->mapindex2gc(map_id2index(m));
- struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL;
- if( gc ) {
+ struct guild_castle *gc = guild->mapindex2gc(map_id2index(m));
+
+ if (gc != NULL) {
+ struct guild *g = guild->search(gc->guild_id);
+
md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
md->guardian_data->castle = gc;
md->guardian_data->number = MAX_GUARDIANS;
- if( g )
+
+ if (g != NULL)
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);
+ else if (gc->guild_id > 0) /// Guild not yet available, retry in 5s.
+ timer->add(timer->gettick() + 5000, mob->spawn_guardian_sub, md->bl.id,
+ gc->guild_id);
}
- } // end addition [Valaris]
+ }
mob->spawn(md);
- if (class_ < 0 && battle_config.dead_branch_active) {
- //Behold Aegis's masterful decisions yet again...
- //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3
- sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000);
+ if (class_ < 0 && battle_config.dead_branch_active == 1) {
+ /// Behold Aegis' masterful decisions yet again...
+ /// "I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" [Poki]
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY,
+ 0, 60000);
}
}
- return (md) ? md->bl.id : 0; // id of last spawned mob
+ return (md != NULL) ? md->bl.id : 0; /// ID of last spawned mob.
}
/*==========================================
* Spawn mobs in the specified area.
*------------------------------------------*/
-int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai)
+static int mob_once_spawn_area(struct map_session_data *sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai)
{
int i, max, id = 0;
int lx = -1, ly = -1;
@@ -590,195 +707,236 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0
}
/**
- * Sets a guardian's guild data and liberates castle if couldn't retrieve guild data
- * @param data (int)guild_id
- * @retval Always 0
+ * Sets a guardian's guild data and liberates castle if couldn't retrieve guild data.
+ * Required because the guild data may not be available at guardian spawn time.
+ *
+ * @param tid Required parameter for timer functions. Unused inside the function.
+ * @param tick Required parameter for timer functions. Unused inside the function.
+ * @param id The guardian mob's GID.
+ * @param data The guild ID.
+ * @return 1 on success, 0 on failure.
+ *
* @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.
- struct block_list* bl = map->id2bl(id);
- struct mob_data* md;
- struct guild* g;
+static int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data)
+{
+ struct block_list *bl = map->id2bl(id);
- if( bl == NULL ) //It is possible mob was already removed from map when the castle has no owner. [Skotlex]
+ if (bl == NULL || bl->type != BL_MOB) /// It is possible mob was already removed from map when the castle has no owner. [Skotlex]
return 0;
- Assert_ret(bl->type == BL_MOB);
- md = BL_UCAST(BL_MOB, bl);
+ struct mob_data *md = BL_UCAST(BL_MOB, bl);
+
+ if (md->guardian_data == NULL)
+ return 0;
- nullpo_ret(md->guardian_data);
- g = guild->search((int)data);
+ struct guild *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);
- //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
- if (md->class_ == MOBID_EMPELIUM && md->guardian_data) {
+
+ /// Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
+ if (md->class_ == MOBID_EMPELIUM) {
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);
+
+ if (md->guardian_data->castle->guild_id > 0) { /// Free castle up.
+ ShowNotice("mob_spawn_guardian_sub: 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 )
- guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
+ if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS &&
+ md->guardian_data->castle->guardian[md->guardian_data->number].visible == 1)
+ 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;
}
- if( guild->checkskill(g,GD_GUARDUP) )
- status_calc_mob(md, SCO_NONE); // Give bonuses.
+ if (guild->checkskill(g, GD_GUARDUP) > 0)
+ status_calc_mob(md, SCO_NONE); /// Give bonuses.
- return 0;
+ return 1;
}
-/*==========================================
- * Summoning Guardians [Valaris]
- *------------------------------------------*/
-int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index)
+/**
+ * Summons a castle guardian mob.
+ *
+ * @param mapname The name of the map where the guardian should be spawned.
+ * @param x The x coordinate where the guardian should be spawned.
+ * @param y The y coordinate where the guardian should be spawned.
+ * @param mobname The guardian's display name.
+ * @param class_ The guardian's mob ID in database.
+ * @param event The name of the event which should be executed when the guardian is killed.
+ * @param guardian The guardian's index.
+ * @param has_index If false, the guardian will be temporarily.
+ * @param npc_id If spawned by NPC script, this holds the ID of the invoking NPC.
+ * @return The spawned guardian's GID, or 0 if spawning failed.
+ *
+ * @author Valaris
+ *
+ **/
+static int mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event,
+ int guardian, bool has_index, int npc_id)
{
- struct mob_data *md=NULL;
- struct spawn_data data;
- struct guild *g=NULL;
- struct guild_castle *gc;
- int16 m;
-
nullpo_ret(mapname);
nullpo_ret(mobname);
nullpo_ret(event);
- memset(&data, 0, sizeof(struct spawn_data));
- data.num = 1;
-
- m=map->mapname2mapid(mapname);
+ const int map_id = map->mapname2mapid(mapname);
- if(m<0)
- {
+ if (map_id == INDEX_NOT_FOUND) {
ShowWarning("mob_spawn_guardian: Map [%s] not found.\n", mapname);
return 0;
}
- data.m = m;
- data.num = 1;
- if(class_<=0) {
- class_ = mob->get_random_id(-class_-1, 1, 99);
- if (!class_) return 0;
+
+ if ((x <= 0 || y <= 0) && map->search_freecell(NULL, map_id, &x, &y, -1, -1, 1) == 0) {
+ ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) on castle map %s.\n",
+ class_, guardian, mapname);
+ return 0;
}
- data.class_ = class_;
+ if (class_ <= 0 && (class_ = mob->get_random_id(-class_ - 1, 1, 99)) == 0)
+ return 0;
- if( !has_index ) {
+ if (!has_index) {
guardian = -1;
- } else if( guardian < 0 || guardian >= MAX_GUARDIANS ) {
- ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map->list[m].name);
+ } else if (guardian < 0 || guardian >= MAX_GUARDIANS) {
+ ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d on castle map %s.\n",
+ guardian, class_, mapname);
return 0;
}
- if((x<=0 || y<=0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1)) {
- ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map->list[m].name);
- return 0;
- }
+ struct spawn_data data;
+
+ memset(&data, 0, sizeof(struct spawn_data));
+ data.num = 1;
+ data.m = map_id;
+ data.class_ = class_;
data.x = x;
data.y = y;
safestrncpy(data.name, mobname, sizeof(data.name));
safestrncpy(data.eventname, event, sizeof(data.eventname));
- if (!mob->parse_dataset(&data))
+
+ if (mob->parse_dataset(&data) == 0)
return 0;
- gc=guild->mapname2gc(map->list[m].name);
+ struct guild_castle *gc = guild->mapname2gc(mapname);
+
if (gc == NULL) {
- ShowError("mob_spawn_guardian: No castle set at map %s\n", map->list[m].name);
+ ShowError("mob_spawn_guardian: No castle set on map %s.\n", mapname);
return 0;
}
- if (!gc->guild_id)
- ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map->list[m].name);
+
+ struct guild *g = NULL;
+
+ if (gc->guild_id == 0)
+ ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle map %s with no guild.\n",
+ class_, mapname);
else
g = guild->search(gc->guild_id);
- if( has_index && gc->guardian[guardian].id ) {
- //Check if guardian already exists, refuse to spawn if so.
- struct block_list *bl2 = map->id2bl(gc->guardian[guardian].id); // TODO: Why does this not use map->id2md?
- struct mob_data *md2 = BL_CAST(BL_MOB, bl2);
- if (md2 != NULL && md2->guardian_data != NULL && md2->guardian_data->number == guardian) {
- ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map->list[m].name);
+ if (has_index && gc->guardian[guardian].id != 0) { /// Check if guardian already exists, refuse to spawn if so.
+ struct mob_data *md = map->id2md(gc->guardian[guardian].id);
+
+ if (md != NULL && md->guardian_data != NULL && md->guardian_data->number == guardian) {
+ ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian on castle map %s.\n",
+ guardian, mapname);
return 0;
}
}
- md = mob->spawn_dataset(&data);
+ struct mob_data *md = mob->spawn_dataset(&data, npc_id);
+
md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
md->guardian_data->number = guardian;
md->guardian_data->castle = gc;
- if( has_index )
- {// permanent guardian
+
+ if (has_index) { /// Permanent guardian.
gc->guardian[guardian].id = md->bl.id;
- }
- else
- {// temporary guardian
+ } else { /// Temporary guardian.
int i;
+
ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == 0);
- if( i == gc->temp_guardians_max )
- {
+
+ if (i == gc->temp_guardians_max) {
++(gc->temp_guardians_max);
RECREATE(gc->temp_guardians, int, gc->temp_guardians_max);
}
+
gc->temp_guardians[i] = md->bl.id;
}
- if( g )
+
+ if (g != NULL)
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);
+ else if (gc->guild_id > 0)
+ timer->add(timer->gettick() + 5000, mob->spawn_guardian_sub, md->bl.id, gc->guild_id);
+ mob->spawn(md);
return md->bl.id;
}
-/*==========================================
- * Summoning BattleGround [Zephyrus]
- *------------------------------------------*/
-int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, unsigned int bg_id)
+/**
+ * Spawn a mob with allegiance to the given battle group.
+ *
+ * @param mapname The name of the map where the mob should be spawned.
+ * @param x The x coordinate where the mob should be spawned.
+ * @param y The y coordinate where the mob should be spawned.
+ * @param mobname The mob's display name.
+ * @param class_ The mob's mob ID in database.
+ * @param event The name of the event which should be executed when the mob is killed.
+ * @param bg_id The battle group ID.
+ * @param npc_id If spawned by NPC script, this holds the ID of the invoking NPC.
+ * @return The spawned mob's GID, or 0 if spawning failed.
+ *
+ * @author Zephyrus
+ *
+ **/
+static int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event,
+ unsigned int bg_id, int npc_id)
{
- struct mob_data *md = NULL;
- struct spawn_data data;
- int16 m;
-
nullpo_ret(mapname);
nullpo_ret(mobname);
nullpo_ret(event);
- if( (m = map->mapname2mapid(mapname)) < 0 ) {
+ const int map_id = map->mapname2mapid(mapname);
+
+ if (map_id == INDEX_NOT_FOUND) {
ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname);
return 0;
}
- memset(&data, 0, sizeof(struct spawn_data));
- data.m = m;
- data.num = 1;
- if( class_ <= 0 )
- {
- class_ = mob->get_random_id(-class_-1,1,99);
- if( !class_ ) return 0;
+ if ((x <= 0 || y <= 0) && map->search_freecell(NULL, map_id, &x, &y, -1, -1, 1) == 0) {
+ ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %u) on map %s.\n", class_, bg_id, mapname);
+ return 0;
}
- data.class_ = class_;
- if( (x <= 0 || y <= 0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1) ) {
- ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %u) at map %s\n", class_, bg_id, map->list[m].name);
+ if (class_ <= 0 && (class_ = mob->get_random_id(-class_ - 1, 1, 99)) == 0)
return 0;
- }
+ struct spawn_data data;
+
+ memset(&data, 0, sizeof(struct spawn_data));
+ data.num = 1;
+ data.m = map_id;
+ data.class_ = class_;
data.x = x;
data.y = y;
safestrncpy(data.name, mobname, sizeof(data.name));
safestrncpy(data.eventname, event, sizeof(data.eventname));
- if( !mob->parse_dataset(&data) )
+
+ if (mob->parse_dataset(&data) == 0)
return 0;
- md = mob->spawn_dataset(&data);
- mob->spawn(md);
- md->bg_id = bg_id; // BG Team ID
+ struct mob_data *md = mob->spawn_dataset(&data, npc_id);
+ mob->spawn(md);
+ md->bg_id = bg_id;
return md->bl.id;
}
@@ -789,7 +947,7 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int
* - MSS_RUSH: Chasing attacking player, path is complex
* - MSS_FOLLOW: Initiative/support seek, path is complex
*------------------------------------------*/
-int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state)
+static int mob_can_reach(struct mob_data *md, struct block_list *bl, int range, int state)
{
int easy = 0;
@@ -811,7 +969,7 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state
/*==========================================
* Links nearby mobs (supportive mobs)
*------------------------------------------*/
-int mob_linksearch(struct block_list *bl,va_list ap)
+static int mob_linksearch(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
int class_ = va_arg(ap, int);
@@ -840,7 +998,8 @@ int mob_linksearch(struct block_list *bl,va_list ap)
/*==========================================
* mob spawn with delay (timer function)
*------------------------------------------*/
-int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) {
+static int mob_delayspawn(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list* bl = map->id2bl(id); // TODO: Why does this not use map->bl2md?
struct mob_data* md = BL_CAST(BL_MOB, bl);
@@ -860,7 +1019,7 @@ int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* spawn timing calculation
*------------------------------------------*/
-int mob_setdelayspawn(struct mob_data *md)
+static int mob_setdelayspawn(struct mob_data *md)
{
unsigned int spawntime;
uint32 mode;
@@ -904,7 +1063,8 @@ int mob_setdelayspawn(struct mob_data *md)
return 0;
}
-int mob_count_sub(struct block_list *bl, va_list ap) {
+static int mob_count_sub(struct block_list *bl, va_list ap)
+{
int mobid[10] = { 0 }, i;
ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0
if (mobid[0]) { //if there one let's check it otherwise go backward
@@ -919,7 +1079,7 @@ int mob_count_sub(struct block_list *bl, va_list ap) {
/*==========================================
* Mob spawning. Initialization is also variously here.
*------------------------------------------*/
-int mob_spawn (struct mob_data *md)
+static int mob_spawn(struct mob_data *md)
{
int i=0;
int64 tick = timer->gettick();
@@ -1013,7 +1173,7 @@ int mob_spawn (struct mob_data *md)
/*==========================================
* Determines if the mob can change target. [Skotlex]
*------------------------------------------*/
-int mob_can_changetarget(const struct mob_data *md, const struct block_list *target, uint32 mode)
+static int mob_can_changetarget(const struct mob_data *md, const struct block_list *target, uint32 mode)
{
nullpo_ret(md);
nullpo_ret(target);
@@ -1047,7 +1207,7 @@ int mob_can_changetarget(const struct mob_data *md, const struct block_list *tar
/*==========================================
* Determination for an attack of a monster
*------------------------------------------*/
-int mob_target(struct mob_data *md,struct block_list *bl,int dist)
+static int mob_target(struct mob_data *md, struct block_list *bl, int dist)
{
nullpo_ret(md);
nullpo_ret(bl);
@@ -1071,7 +1231,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
/*==========================================
* The ?? routine of an active monster
*------------------------------------------*/
-int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
+static int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
{
struct mob_data *md;
struct block_list **target;
@@ -1099,6 +1259,7 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
case BL_PC:
if (BL_UCCAST(BL_PC, bl)->state.gangsterparadise && !(status_get_mode(&md->bl)&MD_BOSS))
return 0; //Gangster paradise protection.
+ FALLTHROUGH
default:
if (battle_config.hom_setting&0x4 &&
(*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
@@ -1110,13 +1271,15 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
battle->check_range(&md->bl,bl,md->db->range2)
) { //Pick closest target?
#ifdef ACTIVEPATHSEARCH
- struct walkpath_data wpd;
- if (!path->search(&wpd, &md->bl, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells
- return 0;
- //Standing monsters use range2, walking monsters use range3
- if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2)
- || (md->ud.walktimer != INVALID_TIMER && wpd.path_len > md->db->range3))
- return 0;
+ struct walkpath_data wpd;
+ bool is_standing = (md->ud.walktimer == INVALID_TIMER);
+ if (!path->search(&wpd, &md->bl, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS) // Count walk path cells
+ || (is_standing && wpd.path_len > md->db->range2) //Standing monsters use range2, walking monsters use range3
+ || (!is_standing && wpd.path_len > md->db->range3)) {
+ if (!check_distance_bl(&md->bl, bl, md->status.rhw.range)
+ || !path->search_long(NULL, &md->bl, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, CELL_CHKWALL))
+ return 0;
+ }
#endif
(*target) = bl;
md->target_id=bl->id;
@@ -1133,7 +1296,8 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
/*==========================================
* chase target-change routine.
*------------------------------------------*/
-int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) {
+static int mob_ai_sub_hard_changechase(struct block_list *bl, va_list ap)
+{
struct mob_data *md;
struct block_list **target;
@@ -1161,7 +1325,8 @@ int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) {
/*==========================================
* finds nearby bg ally for guardians looking for users to follow.
*------------------------------------------*/
-int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
+static int mob_ai_sub_hard_bg_ally(struct block_list *bl, va_list ap)
+{
struct mob_data *md;
struct block_list **target;
@@ -1180,7 +1345,7 @@ int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
/*==========================================
* loot monster item search
*------------------------------------------*/
-int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
+static int mob_ai_sub_hard_lootsearch(struct block_list *bl, va_list ap)
{
struct mob_data* md;
struct block_list **target;
@@ -1202,7 +1367,8 @@ int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
return 0;
}
-int mob_warpchase_sub(struct block_list *bl,va_list ap) {
+static int mob_warpchase_sub(struct block_list *bl, va_list ap)
+{
int cur_distance;
struct block_list *target = va_arg(ap, struct block_list *);
struct npc_data **target_nd = va_arg(ap, struct npc_data **);
@@ -1231,10 +1397,32 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) {
}
return 0;
}
+
+/**
+ * Checks if a monster is currently involved in battle,
+ * may it be due to aggression or being attacked.
+ * @param bl: monster's bl
+ * @return true if in battle, false otherwise
+ */
+static bool mob_is_in_battle_state(const struct mob_data *md)
+{
+ nullpo_retr(false, md);
+ switch (md->state.skillstate) {
+ case MSS_BERSERK:
+ case MSS_ANGRY:
+ case MSS_RUSH:
+ case MSS_FOLLOW:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*==========================================
* Processing of slave monsters
*------------------------------------------*/
-int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
+static int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick)
+{
struct block_list *bl;
nullpo_ret(md);
@@ -1274,8 +1462,11 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
) {
short x = bl->x, y = bl->y;
mob_stop_attack(md);
- if(map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
- && unit->walktoxy(&md->bl, x, y, 0))
+ const struct mob_data *m_md = BL_CCAST(BL_MOB, bl); // Can be NULL due to master being BL_PC
+ // If master is BL_MOB and in battle, lock & chase to master's target instead, unless configured not to.
+ if ((battle_config.slave_chase_masters_chasetarget == 0 || (m_md != NULL && !mob->is_in_battle_state(m_md)))
+ && map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
+ && unit->walk_toxy(&md->bl, x, y, 0) == 0)
return 1;
}
} else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) {
@@ -1286,26 +1477,28 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
//Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex]
if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) {
- struct unit_data *ud = unit->bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
+ struct mob_data *m_md = BL_CAST(BL_MOB, bl); // Can be NULL due to master being BL_PC
+ nullpo_retr(0, ud);
md->last_linktime = tick;
-
- if (ud) {
- struct block_list *tbl=NULL;
- if (ud->target && ud->state.attack_continue)
- tbl=map->id2bl(ud->target);
- else if (ud->skilltarget) {
- tbl = map->id2bl(ud->skilltarget);
- //Required check as skilltarget is not always an enemy. [Skotlex]
- if (tbl && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0)
- tbl = NULL;
- }
- if (tbl && status->check_skilluse(&md->bl, tbl, 0, 0)) {
- md->target_id=tbl->id;
- md->min_chase=md->db->range3+distance_bl(&md->bl, tbl);
- if(md->min_chase>MAX_MINCHASE)
- md->min_chase=MAX_MINCHASE;
- return 1;
- }
+ struct block_list *tbl = NULL;
+
+ if (battle_config.slave_chase_masters_chasetarget == 1 && m_md != NULL && m_md->target_id != 0) { // possibly chasing something
+ tbl = map->id2bl(m_md->target_id);
+ } else if (ud->target != 0 && ud->state.attack_continue != 0) {
+ tbl = map->id2bl(ud->target);
+ } else if (ud->skilltarget != 0) {
+ tbl = map->id2bl(ud->skilltarget);
+ //Required check as skilltarget is not always an enemy. [Skotlex]
+ if (tbl != NULL && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0)
+ tbl = NULL;
+ }
+ if (tbl != NULL && status->check_skilluse(&md->bl, tbl, 0, 0) != 0) {
+ md->target_id = tbl->id;
+ md->min_chase = md->db->range3 + distance_bl(&md->bl, tbl);
+ if (md->min_chase > MAX_MINCHASE)
+ md->min_chase = MAX_MINCHASE;
+ return 1;
}
}
return 0;
@@ -1317,7 +1510,8 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
* when trying to pick new targets when the current chosen target is
* unreachable.
*------------------------------------------*/
-int mob_unlocktarget(struct mob_data *md, int64 tick) {
+static int mob_unlocktarget(struct mob_data *md, int64 tick)
+{
nullpo_ret(md);
switch (md->state.skillstate) {
@@ -1326,9 +1520,10 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) {
break;
//Because it is not unset when the mob finishes walking.
md->state.skillstate = MSS_IDLE;
+ FALLTHROUGH
case MSS_IDLE:
// Idle skill.
- if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1))
+ if ((++md->ud.walk_count % IDLE_SKILL_INTERVAL) == 0 && mob->skill_use(md, tick, -1) == 0)
break;
//Random walk.
if (!md->master_id &&
@@ -1352,8 +1547,8 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) {
md->ud.target_to = 0;
unit->set_target(&md->ud, 0);
}
- if(battle_config.official_cell_stack_limit && map->count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
- unit->walktoxy(&md->bl, md->bl.x, md->bl.y, 8);
+ if(battle_config.official_cell_stack_limit && map->count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR|BL_NPC, 0x1 | 0x2) > battle_config.official_cell_stack_limit) {
+ unit->walk_toxy(&md->bl, md->bl.x, md->bl.y, 8);
}
return 0;
@@ -1361,7 +1556,8 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) {
/*==========================================
* Random walk
*------------------------------------------*/
-int mob_randomwalk(struct mob_data *md, int64 tick) {
+static int mob_randomwalk(struct mob_data *md, int64 tick)
+{
const int retrycount=20;
int i,c,d;
int speed;
@@ -1384,9 +1580,9 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
x+=md->bl.x;
y+=md->bl.y;
- if (((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&md->bl, x, y, 8)) {
+ if ((x != md->bl.x || y != md->bl.y) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) != 0
+ && unit->walk_toxy(&md->bl, x, y, 8) == 0)
break;
- }
}
if(i==retrycount){
md->move_fail_count++;
@@ -1411,7 +1607,7 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
return 1;
}
-int mob_warpchase(struct mob_data *md, struct block_list *target)
+static int mob_warpchase(struct mob_data *md, struct block_list *target)
{
struct npc_data *warp = NULL;
int distance = AREA_SIZE;
@@ -1438,7 +1634,8 @@ int mob_warpchase(struct mob_data *md, struct block_list *target)
/*==========================================
* AI of MOB whose is near a Player
*------------------------------------------*/
-bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
+static bool mob_ai_sub_hard(struct mob_data *md, int64 tick)
+{
struct block_list *tbl = NULL, *abl = NULL;
uint32 mode;
int view_range, can_move;
@@ -1506,7 +1703,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
|| !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
)
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
+ && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 // If can't rude Attack
&& can_move && unit->escape(&md->bl, tbl, rnd()%10 +1) // Attempt escape
) {
//Escaped
@@ -1534,7 +1731,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
) {
// Rude attacked
if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
+ && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 && can_move != 0
&& !tbl && unit->escape(&md->bl, abl, rnd()%10 +1)
) {
//Escaped.
@@ -1650,7 +1847,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0]));
memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0]));
}
- if (pc->db_checkid(md->vd->class_)) {
+ if (pc->db_checkid(md->vd->class)) {
//Give them walk act/delay to properly mimic players. [Skotlex]
clif->takeitem(&md->bl,tbl);
md->ud.canact_tick = tick + md->status.amotion;
@@ -1718,7 +1915,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
return true;
}
-int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap)
+static int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
int64 tick = va_arg(ap, int64);
@@ -1739,7 +1936,8 @@ int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap)
/*==========================================
* Serious processing for mob in PC field of view (foreachclient)
*------------------------------------------*/
-int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
+static int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap)
+{
int64 tick;
nullpo_ret(sd);
tick=va_arg(ap, int64);
@@ -1751,7 +1949,8 @@ int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
/*==========================================
* Negligent mode MOB AI (PC is not in near)
*------------------------------------------*/
-int mob_ai_sub_lazy(struct mob_data *md, va_list args) {
+static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
+{
int64 tick;
nullpo_ret(md);
@@ -1815,7 +2014,8 @@ int mob_ai_sub_lazy(struct mob_data *md, va_list args) {
/*==========================================
* Negligent processing for mob outside PC field of view (interval timer function)
*------------------------------------------*/
-int mob_ai_lazy(int tid, int64 tick, int id, intptr_t data) {
+static int mob_ai_lazy(int tid, int64 tick, int id, intptr_t data)
+{
map->foreachmob(mob->ai_sub_lazy,tick);
return 0;
}
@@ -1823,7 +2023,8 @@ int mob_ai_lazy(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Serious processing for mob in PC field of view (interval timer function)
*------------------------------------------*/
-int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) {
+static int mob_ai_hard(int tid, int64 tick, int id, intptr_t data)
+{
if (battle_config.mob_ai&0x20)
map->foreachmob(mob->ai_sub_lazy,tick);
@@ -1833,14 +2034,54 @@ int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
+/**
+ * Adds random options of a given options drop group into item.
+ *
+ * @param item : item receiving random options
+ * @param options : Random Option Drop Group to be used
+ */
+static void mob_setdropitem_options(struct item *item, struct optdrop_group *options)
+{
+ nullpo_retv(item);
+ nullpo_retv(options);
+
+ for (int i = 0; i < options->optslot_count; i++) {
+ if (rnd() % 10000 >= options->optslot_rate[i])
+ continue;
+
+ // count avoids a too long loop that would cause lag.
+ // if after option_drop_max_loop full iterations (running through all possibilities)
+ // it still fails to pick one, it'll stop at one random index in the next iteration
+ int count = battle_config.option_drop_max_loop * options->optslot[i].option_count + (rnd() % options->optslot[i].option_count);
+ int idx = 0;
+ while (count > 0 && rnd() % 10000 >= options->optslot[i].options[idx].rate) {
+ idx = (idx + 1) % options->optslot[i].option_count;
+ --count;
+ }
+
+ item->option[i].index = options->optslot[i].options[idx].id;
+
+ int min = options->optslot[i].options[idx].min;
+ int max = options->optslot[i].options[idx].max;
+ item->option[i].value = min + (rnd() % (max - min + 1));
+ }
+}
+
/*==========================================
* Initializes the delay drop structure for mob-dropped items.
*------------------------------------------*/
-struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) {
+static struct item_drop *mob_setdropitem(int nameid, struct optdrop_group *options, int qty, struct item_data *data)
+{
struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
drop->item_data.nameid = nameid;
drop->item_data.amount = qty;
drop->item_data.identify = data ? itemdb->isidentified2(data) : itemdb->isidentified(nameid);
+
+ // Set item options [KirieZ]
+ if (options != NULL)
+ mob->setdropitem_options(&drop->item_data, options);
+
+ drop->showdropeffect = true;
drop->next = NULL;
return drop;
}
@@ -1848,13 +2089,14 @@ struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) {
/*==========================================
* Initializes the delay drop structure for mob-looted items.
*------------------------------------------*/
-struct item_drop* mob_setlootitem(struct item* item)
+static struct item_drop *mob_setlootitem(struct item *item)
{
struct item_drop *drop ;
nullpo_retr(NULL, item);
drop = ers_alloc(item_drop_ers, struct item_drop);
memcpy(&drop->item_data, item, sizeof(struct item));
+ drop->showdropeffect = false;
drop->next = NULL;
return drop;
}
@@ -1862,7 +2104,8 @@ struct item_drop* mob_setlootitem(struct item* item)
/*==========================================
* item drop with delay (timer function)
*------------------------------------------*/
-int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
+static int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data)
+{
struct item_drop_list *list;
struct item_drop *ditem;
list=(struct item_drop_list *)data;
@@ -1870,8 +2113,9 @@ int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
while (ditem) {
struct item_drop *ditem_prev;
map->addflooritem(NULL, &ditem->item_data,ditem->item_data.amount,
- list->m,list->x,list->y,
- list->first_charid,list->second_charid,list->third_charid,0);
+ list->m,list->x,list->y,
+ list->first_charid,list->second_charid,list->third_charid,0,
+ ditem->showdropeffect);
ditem_prev = ditem;
ditem = ditem->next;
ers_free(item_drop_ers, ditem_prev);
@@ -1886,7 +2130,7 @@ int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
* rate is the drop-rate of the item, required for autoloot.
* flag : Killed only by homunculus?
*------------------------------------------*/
-void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag)
+static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag)
{
struct map_session_data *sd = NULL;
@@ -1902,6 +2146,7 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite
if( sd
&& (drop_rate <= sd->state.autoloot || pc->isautolooting(sd, ditem->item_data.nameid))
+ && (!map->list[sd->bl.m].flag.noautoloot)
&& (battle_config.idle_no_autoloot == 0 || DIFF_TICK(sockt->last_tick, sd->idletime) < battle_config.idle_no_autoloot)
&& (battle_config.homunculus_autoloot?1:!flag)
#ifdef AUTOLOOT_DISTANCE
@@ -1921,7 +2166,8 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite
dlist->item = ditem;
}
-int mob_timer_delete(int tid, int64 tick, int id, intptr_t data) {
+static int mob_timer_delete(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list* bl = map->id2bl(id); // TODO: Why does this not use map->id2md?
struct mob_data* md = BL_CAST(BL_MOB, bl);
@@ -1942,7 +2188,7 @@ int mob_timer_delete(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
*
*------------------------------------------*/
-int mob_deleteslave_sub(struct block_list *bl,va_list ap)
+static int mob_deleteslave_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
int id = va_arg(ap, int);
@@ -1959,14 +2205,16 @@ int mob_deleteslave_sub(struct block_list *bl,va_list ap)
/*==========================================
*
*------------------------------------------*/
-int mob_deleteslave(struct mob_data *md) {
+static int mob_deleteslave(struct mob_data *md)
+{
nullpo_ret(md);
map->foreachinmap(mob->deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
return 0;
}
// Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
-int mob_respawn(int tid, int64 tick, int id, intptr_t data) {
+static int mob_respawn(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl = map->id2bl(id);
if(!bl) return 0;
@@ -1974,7 +2222,7 @@ int mob_respawn(int tid, int64 tick, int id, intptr_t data) {
return 1;
}
-void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
+static void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
{
int char_id = 0, flag = MDLF_NORMAL;
@@ -2086,11 +2334,20 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
md->dmglog[minpos].flag= flag;
md->dmglog[minpos].dmg = damage;
}
+#if (PACKETVER >= 20120404 && PACKETVER < 20131223)
+ // Show HP bar to all chars who hit the mob (fixes TF_STEAL not showing HP bar right away but only when target leaves/re-enters sight range)
+ if (battle_config.show_monster_hp_bar != 0 && (md->status.mode & MD_BOSS) == 0) {
+ struct map_session_data *sd = map->charid2sd(char_id);
+ if (sd != NULL && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE)) // check if in range
+ clif->monster_hp_bar(md, sd);
+ }
+#endif
}
return;
}
//Call when a mob has received damage.
-void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
+static void mob_damage(struct mob_data *md, struct block_list *src, int damage)
+{
nullpo_retv(md);
if (damage > 0) { //Store total damage...
if (UINT_MAX - (unsigned int)damage > md->tdmg)
@@ -2112,10 +2369,14 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
if (src)
mob->log_damage(md, src, damage);
md->dmgtick = timer->gettick();
+
+ // Achievements [Smokexyz/Hercules]
+ if (src != NULL && src->type == BL_PC)
+ achievement->validate_mob_damage(BL_UCAST(BL_PC, src), damage, false);
}
if (battle_config.show_mob_info&3)
- clif->charnameack (0, &md->bl);
+ clif->blname_ack(0, &md->bl);
#if PACKETVER >= 20131223
// Resend ZC_NOTIFY_MOVEENTRY to Update the HP
@@ -2144,11 +2405,13 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
* Signals death of mob.
* type&1 -> no drops, type&2 -> no exp
*------------------------------------------*/
-int mob_dead(struct mob_data *md, struct block_list *src, int type) {
+static int mob_dead(struct mob_data *md, struct block_list *src, int type)
+{
struct status_data *mstatus;
struct map_session_data *sd = BL_CAST(BL_PC, src);
struct map_session_data *tmpsd[DAMAGELOG_SIZE] = { NULL };
struct map_session_data *mvp_sd = sd, *second_sd = NULL, *third_sd = NULL;
+ struct item_data *id = NULL;
struct {
struct party_data *p;
@@ -2337,16 +2600,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if(flag) {
if(base_exp || job_exp) {
if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
-#ifdef RENEWAL_EXP
- int rate = pc->level_penalty_mod(md->level - (tmpsd[i])->status.base_level, md->status.race, md->status.mode, 1);
- base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX);
- job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX);
-#endif
pc->gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false);
}
}
if(zeny) // zeny from mobs [Valaris]
pc->getzeny(tmpsd[i], zeny, LOG_TYPE_PICKDROP_MONSTER, NULL);
+
+ if (!md->special_state.clone && !mob->is_clone(md->class_))
+ achievement->validate_mob_kill(tmpsd[i], md->db->mob_id); // Achievements [Smokexyz/Hercules]
}
}
@@ -2410,7 +2671,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
drop_rate += (int)(0.5+drop_rate*status_get_luk(src)*battle_config.drops_by_luk2/10000.);
}
if (sd && battle_config.pk_mode &&
- (int)(md->level - sd->status.base_level) >= 20)
+ md->level - sd->status.base_level >= 20)
drop_rate = (int)(drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris]
// Increase drop rate if user has SC_CASH_RECEIVEITEM
@@ -2440,34 +2701,24 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
continue;
}
- ditem = mob->setdropitem(md->db->dropitem[i].nameid, 1, it);
+ ditem = mob->setdropitem(md->db->dropitem[i].nameid, md->db->dropitem[i].options, 1, it);
- //A Rare Drop Global Announce by Lupus
- if( mvp_sd && drop_rate <= battle_config.rare_drop_announce ) {
- char message[128];
- sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100);
- //MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
+ // Official Drop Announce [Jedzkie]
+ if (mvp_sd != NULL) {
+ if ((id = itemdb->search(it->nameid)) != NULL && id->flag.drop_announce) {
+ clif->item_drop_announce(mvp_sd, it->nameid, md->name);
+ }
}
- /* heres the thing we got the feature set up however we're still discussing how to best define the ids,
- * so while we discuss, for a small period of time, the list is hardcoded (yes officially only those 2 use it,
- * thus why we're unsure on how to best place the setting) */
- /* temp, will not be hardcoded for long thudu. */
- // TODO: This should be a field in the item db.
- if (mvp_sd != NULL
- && (it->nameid == ITEMID_GOLD_KEY77 || it->nameid == ITEMID_SILVER_KEY77)) /* for when not hardcoded: add a check on mvp bonus drop as well */
- clif->item_drop_announce(mvp_sd, it->nameid, md->name);
-
// Announce first, or else ditem will be freed. [Lance]
// By popular demand, use base drop rate for autoloot code. [Skotlex]
- mob->item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, homkillonly);
+ mob->item_drop(md, dlist, ditem, 0, battle_config.autoloot_adjust ? drop_rate : md->db->dropitem[i].p, homkillonly);
}
// Ore Discovery [Celest]
if (sd == mvp_sd && pc->checkskill(sd,BS_FINDINGORE) > 0) {
if( (temp = itemdb->chain_item(itemdb->chain_cache[ECC_ORE],&i)) ) {
- ditem = mob->setdropitem(temp, 1, NULL);
+ ditem = mob->setdropitem(temp, NULL, 1, NULL);
mob->item_drop(md, dlist, ditem, 0, i, homkillonly);
}
}
@@ -2475,7 +2726,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if(sd) {
// process script-granted extra drop bonuses
int itemid = 0;
- for (i = 0; i < ARRAYLENGTH(sd->add_drop) && (sd->add_drop[i].id || sd->add_drop[i].group); i++)
+ for (i = 0; i < ARRAYLENGTH(sd->add_drop) && (sd->add_drop[i].id != 0 || sd->add_drop[i].is_group); i++)
{
if ( sd->add_drop[i].race == -md->class_ ||
( sd->add_drop[i].race > 0 && (
@@ -2497,9 +2748,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if (rnd()%10000 >= drop_rate)
continue;
- itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb->chain_item(sd->add_drop[i].group,&drop_rate);
+ itemid = (!sd->add_drop[i].is_group) ? sd->add_drop[i].id : itemdb->chain_item(sd->add_drop[i].id, &drop_rate);
if( itemid )
- mob->item_drop(md, dlist, mob->setdropitem(itemid,1,NULL), 0, drop_rate, homkillonly);
+ mob->item_drop(md, dlist, mob->setdropitem(itemid, NULL, 1, NULL), 0, drop_rate, homkillonly);
}
}
@@ -2556,60 +2807,54 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
pc->gainexp(mvp_sd, &md->bl, mexp,0, false);
log_mvp[1] = mexp;
- if( !(map->list[m].flag.nomvploot || type&1) ) {
+ if (!(map->list[m].flag.nomvploot || type&1)) {
/* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */
- int mdrop_id[MAX_MVP_DROP];
- int mdrop_p[MAX_MVP_DROP];
- struct item item;
-
- memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int));
-
- for(i = 0; i < MAX_MVP_DROP; i++) {
- while( 1 ) {
- int va = rnd()%MAX_MVP_DROP;
- if( !mdrop_id[va] || !md->db->mvpitem[i].nameid ) {
- mdrop_id[va] = md->db->mvpitem[i].nameid;
- mdrop_p[va] = md->db->mvpitem[i].p;
- break;
- }
- }
- }
+ struct mob_drop mdrop[MAX_MVP_DROP] = { { 0 } };
- for(i = 0; i < MAX_MVP_DROP; i++) {
- struct item_data *data;
- if(mdrop_id[i] <= 0)
- continue;
- if(! (data = itemdb->exists(mdrop_id[i])) )
+ for (i = 0; i < MAX_MVP_DROP; i++) {
+ int rpos;
+ if (md->db->mvpitem[i].nameid == 0)
continue;
+ do {
+ rpos = rnd()%MAX_MVP_DROP;
+ } while (mdrop[rpos].nameid != 0);
+
+ mdrop[rpos].nameid = md->db->mvpitem[i].nameid;
+ mdrop[rpos].p = md->db->mvpitem[i].p;
+ mdrop[rpos].options = md->db->mvpitem[i].options;
+ }
+
+ for (i = 0; i < MAX_MVP_DROP; i++) {
+ struct item_data *data = NULL;
+ int rate = 0;
- temp = mdrop_p[i];
- if(temp <= 0 && !battle_config.drop_rate0item)
- temp = 1;
- if(temp <= rnd()%10000+1) //if ==0, then it doesn't drop
+ if (mdrop[i].nameid <= 0)
+ continue;
+ if ((data = itemdb->exists(mdrop[i].nameid)) == NULL)
continue;
- memset(&item,0,sizeof(item));
- item.nameid=mdrop_id[i];
- item.identify= itemdb->isidentified2(data);
- clif->mvp_item(mvp_sd,item.nameid);
- log_mvp[0] = item.nameid;
-
- //A Rare MVP Drop Global Announce by Lupus
- if(temp<=battle_config.rare_drop_announce) {
- char message[128];
- sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, temp/100.);
- //MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
- }
+ rate = mdrop[i].p;
+ if (rate <= 0 && !battle_config.drop_rate0item)
+ rate = 1;
+ if (rate > rnd()%10000) {
+ struct item item = { 0 };
+
+ item.nameid = mdrop[i].nameid;
+ item.identify = itemdb->isidentified2(data);
+ if (mdrop[i].options != NULL)
+ mob->setdropitem_options(&item, mdrop[i].options);
+ clif->mvp_item(mvp_sd, item.nameid);
+ log_mvp[0] = item.nameid;
+
+ if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
+ clif->additem(mvp_sd,0,0,temp);
+ map->addflooritem(&md->bl, &item, 1, mvp_sd->bl.m, mvp_sd->bl.x, mvp_sd->bl.y, mvp_sd->status.char_id, (second_sd?second_sd->status.char_id : 0), (third_sd ? third_sd->status.char_id : 0), 1, true);
+ }
- if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
- clif->additem(mvp_sd,0,0,temp);
- map->addflooritem(&md->bl, &item, 1, mvp_sd->bl.m, mvp_sd->bl.x, mvp_sd->bl.y, mvp_sd->status.char_id, (second_sd?second_sd->status.char_id : 0), (third_sd ? third_sd->status.char_id : 0), 1);
+ //Logs items, MVP prizes [Lupus]
+ logs->pick_mob(md, LOG_TYPE_MVP, -1, &item, data);
+ break;
}
-
- //Logs items, MVP prizes [Lupus]
- logs->pick_mob(md, LOG_TYPE_MVP, -1, &item, data);
- break;
}
}
@@ -2636,13 +2881,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if( sd ) {
if( sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex]
if (++sd->mission_count >= 100 && (temp = mob->get_random_id(0, 0xE, sd->status.base_level)) != 0) {
- pc->addfame(sd, 1);
+ pc->addfame(sd, RANKTYPE_TAEKWON, 1);
sd->mission_mobid = temp;
- pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), temp);
+ pc_setglobalreg(sd,script->add_variable("TK_MISSION_ID"), temp);
sd->mission_count = 0;
clif->mission_info(sd, temp, 0);
}
- pc_setglobalreg(sd,script->add_str("TK_MISSION_COUNT"), sd->mission_count);
+ pc_setglobalreg(sd,script->add_variable("TK_MISSION_COUNT"), sd->mission_count);
}
if( sd->status.party_id )
@@ -2685,7 +2930,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if( !rebirth ) {
- if( pc->db_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client.
+ if (pc->db_checkid(md->vd->class)) {
+ // Player mobs are not removed automatically by the client.
/* 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);
@@ -2702,7 +2948,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
return 5; // Note: Actually, it's 4. Oh well...
// MvP tomb [GreenBox]
- if (battle_config.mvp_tomb_enabled && md->spawn->state.boss && map->list[md->bl.m].flag.notomb != 1)
+ if (battle_config.mvp_tomb_enabled && md->spawn->state.boss == BTYPE_MVP && map->list[md->bl.m].flag.notomb != 1)
mob->mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL));
if( !rebirth ) {
@@ -2712,7 +2958,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
return 3; //Remove from map.
}
-void mob_revive(struct mob_data *md, unsigned int hp)
+static void mob_revive(struct mob_data *md, unsigned int hp)
{
int64 tick = timer->gettick();
@@ -2730,10 +2976,10 @@ void mob_revive(struct mob_data *md, unsigned int hp)
skill->unit_move(&md->bl,tick,1);
mob->skill_use(md, tick, MSC_SPAWN);
if (battle_config.show_mob_info&3)
- clif->charnameack (0, &md->bl);
+ clif->blname_ack(0, &md->bl);
}
-int mob_guardian_guildchange(struct mob_data *md)
+static int mob_guardian_guildchange(struct mob_data *md)
{
struct guild *g;
nullpo_ret(md);
@@ -2772,7 +3018,7 @@ int mob_guardian_guildchange(struct mob_data *md)
/*==========================================
* Pick a random class for the mob
*------------------------------------------*/
-int mob_random_class (int *value, size_t count)
+static int mob_random_class(int *value, size_t count)
{
nullpo_ret(value);
@@ -2794,7 +3040,8 @@ int mob_random_class (int *value, size_t count)
/*==========================================
* Change mob base class
*------------------------------------------*/
-int mob_class_change (struct mob_data *md, int class_) {
+static int mob_class_change(struct mob_data *md, int class_)
+{
int64 tick = timer->gettick(), c = 0;
int i, hp_rate;
@@ -2832,7 +3079,7 @@ int mob_class_change (struct mob_data *md, int class_) {
mob_stop_walking(md, STOPWALKING_FLAG_NONE);
unit->skillcastcancel(&md->bl, 0);
status->set_viewdata(&md->bl, class_);
- clif->class_change(&md->bl, md->vd->class_, 1);
+ clif->class_change(&md->bl, md->vd->class, 1, NULL);
status_calc_mob(md, SCO_FIRST);
md->ud.state.speed_changed = 1; //Speed change update.
@@ -2854,7 +3101,7 @@ int mob_class_change (struct mob_data *md, int class_) {
md->target_id = md->attacked_id = 0;
//Need to update name display.
- clif->charnameack(0, &md->bl);
+ clif->blname_ack(0, &md->bl);
status_change_end(&md->bl,SC_KEEPING,INVALID_TIMER);
return 0;
}
@@ -2862,11 +3109,11 @@ int mob_class_change (struct mob_data *md, int class_) {
/*==========================================
* mob heal, update display hp info of mob for players
*------------------------------------------*/
-void mob_heal(struct mob_data *md, unsigned int heal)
+static void mob_heal(struct mob_data *md, unsigned int heal)
{
nullpo_retv(md);
if (battle_config.show_mob_info&3)
- clif->charnameack (0, &md->bl);
+ clif->blname_ack(0, &md->bl);
#if PACKETVER >= 20131223
// Resend ZC_NOTIFY_MOVEENTRY to Update the HP
if (battle_config.show_monster_hp_bar)
@@ -2890,7 +3137,7 @@ void mob_heal(struct mob_data *md, unsigned int heal)
/*==========================================
* Added by RoVeRT
*------------------------------------------*/
-int mob_warpslave_sub(struct block_list *bl, va_list ap)
+static int mob_warpslave_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
struct block_list *master;
@@ -2916,7 +3163,8 @@ int mob_warpslave_sub(struct block_list *bl, va_list ap)
* Warps slaves. Range is the area around the master that they can
* appear in randomly.
*------------------------------------------*/
-int mob_warpslave(struct block_list *bl, int range) {
+static int mob_warpslave(struct block_list *bl, int range)
+{
nullpo_ret(bl);
if (range < 1)
range = 1; //Min range needed to avoid crashes and stuff. [Skotlex]
@@ -2927,7 +3175,7 @@ int mob_warpslave(struct block_list *bl, int range) {
/*==========================================
* Counts slave sub, currently checking if mob master is the given ID.
*------------------------------------------*/
-int mob_countslave_sub(struct block_list *bl, va_list ap)
+static int mob_countslave_sub(struct block_list *bl, va_list ap)
{
int id = va_arg(ap, int);
struct mob_data *md = NULL;
@@ -2944,23 +3192,31 @@ int mob_countslave_sub(struct block_list *bl, va_list ap)
/*==========================================
* Counts the number of slaves a mob has on the map.
*------------------------------------------*/
-int mob_countslave(struct block_list *bl) {
+static int mob_countslave(struct block_list *bl)
+{
nullpo_ret(bl);
return map->foreachinmap(mob->countslave_sub, bl->m, BL_MOB,bl->id);
}
-/*==========================================
- * Summons amount slaves contained in the value[5] array using round-robin. [adapted by Skotlex]
- *------------------------------------------*/
-int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
+/**
+ * Summons amount slaves contained in the value[5] array using round-robin.
+ *
+ * @param md2 The mob which summons the slaves.
+ * @param value Array with slave mob IDs.
+ * @param amount The amount of slaves to spawn.
+ * @param skill_id The Id of the skill which summons the slaves.
+ * @return 1 on success, 0 on failure.
+ *
+ * @author Skotlex
+ *
+ **/
+static int mob_summonslave(struct mob_data *md2, int *value, int amount, uint16 skill_id)
{
- struct mob_data *md;
- struct spawn_data data;
- int count = 0,k=0,hp_rate=0;
-
nullpo_ret(md2);
nullpo_ret(value);
+ struct spawn_data data;
+
memset(&data, 0, sizeof(struct spawn_data));
data.m = md2->bl.m;
data.x = md2->bl.x;
@@ -2969,31 +3225,42 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
data.state.size = md2->special_state.size;
data.state.ai = md2->special_state.ai;
- if(mob->db_checkid(value[0]) == 0)
+ if (mob->db_checkid(value[0]) == 0)
return 0;
- /**
- * Flags this monster is able to summon; saves a worth amount of memory upon deletion
- **/
- md2->can_summon = 1;
- while(count < 5 && mob->db_checkid(value[count])) count++;
- if(count < 1) return 0;
- if (amount > 0 && amount < count) { //Do not start on 0, pick some random sub subset [Skotlex]
- k = rnd()%count;
- amount+=k; //Increase final value by same amount to preserve total number to summon.
+ md2->can_summon = 1; /// Flags this monster is able to summon; saves a worth amount of memory upon deletion.
+
+ int count = 0;
+
+ while (count < 5 && mob->db_checkid(value[count]) != 0)
+ count++;
+
+ if (count < 1)
+ return 0;
+
+ int k = 0;
+
+ if (amount > 0 && amount < count) { /// Do not start on 0, pick some random sub subset. [Skotlex]
+ k = rnd() % count;
+ amount += k; /// Increase final value by same amount to preserve total number to summon.
}
- if (!battle_config.monster_class_change_recover &&
- (skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS))
+ int hp_rate = 0;
+
+ if ((skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS) &&
+ battle_config.monster_class_change_recover == 0)
hp_rate = get_percentage(md2->status.hp, md2->status.max_hp);
- for(;k<amount;k++) {
- short x,y;
- data.class_ = value[k%count]; //Summon slaves in round-robin fashion. [Skotlex]
+ for (; k < amount; k++) {
+ data.class_ = value[k % count]; /// Summon slaves in round-robin fashion. [Skotlex]
+
if (mob->db_checkid(data.class_) == 0)
continue;
- if (map->search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0)) {
+ short x;
+ short y;
+
+ if (map->search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0) != 0) {
data.x = x;
data.y = y;
} else {
@@ -3001,56 +3268,59 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
data.y = md2->bl.y;
}
- //These two need to be loaded from the db for each slave.
- if(battle_config.override_mob_names==1)
- strcpy(data.name,"--en--");
+ if (battle_config.override_mob_names == 1)
+ strcpy(data.name, DEFAULT_MOB_NAME);
else
- strcpy(data.name,"--ja--");
+ strcpy(data.name, DEFAULT_MOB_JNAME);
- if (!mob->parse_dataset(&data))
+ if (mob->parse_dataset(&data) == 0)
continue;
- md= mob->spawn_dataset(&data);
- if(skill_id == NPC_SUMMONSLAVE){
- md->master_id=md2->bl.id;
+ struct mob_data *md = mob->spawn_dataset(&data, 0);
+
+ if (skill_id == NPC_SUMMONSLAVE) {
+ md->master_id = md2->bl.id;
md->special_state.ai = md2->special_state.ai;
}
+
mob->spawn(md);
- if (hp_rate) //Scale HP
- md->status.hp = md->status.max_hp*hp_rate/100;
+ if (hp_rate > 0) /// Scale HP.
+ md->status.hp = md->status.max_hp * hp_rate / 100;
- //Inherit the aggressive mode of the master.
- if (battle_config.slaves_inherit_mode && md->master_id) {
+ /** Inherit the aggressive mode of the master. **/
+ if (battle_config.slaves_inherit_mode > 0 && md->master_id > 0) {
switch (battle_config.slaves_inherit_mode) {
- case 1: //Always aggressive
- if (!(md->status.mode&MD_AGGRESSIVE))
- sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
+ case 1: /// Always aggressive.
+ if ((md->status.mode & MD_AGGRESSIVE) == 0)
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 0);
+
break;
- case 2: //Always passive
- if (md->status.mode&MD_AGGRESSIVE)
- sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
+ case 2: /// Always passive.
+ if ((md->status.mode & MD_AGGRESSIVE) == MD_AGGRESSIVE)
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, 0, MD_AGGRESSIVE, 0);
+
break;
- default: //Copy master.
- if (md2->status.mode&MD_AGGRESSIVE)
- sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
+ default: /// Copy master.
+ if ((md2->status.mode & MD_AGGRESSIVE) == MD_AGGRESSIVE)
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 0);
else
- sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, 0, MD_AGGRESSIVE, 0);
break;
}
}
- clif->skill_nodamage(&md->bl,&md->bl,skill_id,amount,1);
+ clif->skill_nodamage(&md->bl, &md->bl, skill_id, amount, 1);
}
- return 0;
+ return 1;
}
/*==========================================
* MOBskill lookup (get skillindex through skill_id)
* Returns INDEX_NOT_FOUND if not found.
*------------------------------------------*/
-int mob_skill_id2skill_idx(int class_,uint16 skill_id)
+static int mob_skill_id2skill_idx(int class_, uint16 skill_id)
{
int i, max = mob->db(class_)->maxskill;
struct mob_skill *ms=mob->db(class_)->skill;
@@ -3067,7 +3337,7 @@ int mob_skill_id2skill_idx(int class_,uint16 skill_id)
/*==========================================
* Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
*------------------------------------------*/
-int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
+static int mob_getfriendhprate_sub(struct block_list *bl, va_list ap)
{
int min_rate, max_rate,rate;
struct block_list **fr;
@@ -3095,7 +3365,8 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
(*fr) = bl;
return 1;
}
-struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate) {
+static struct block_list *mob_getfriendhprate(struct mob_data *md, int min_rate, int max_rate)
+{
struct block_list *fr=NULL;
int type = BL_MOB;
@@ -3110,7 +3381,8 @@ struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_
/*==========================================
* Check hp rate of its master
*------------------------------------------*/
-struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate) {
+static struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md, int rate)
+{
if( md && md->master_id > 0 ) {
struct block_list *bl = map->id2bl(md->master_id);
if( bl && get_percentage(status_get_hp(bl), status_get_max_hp(bl)) < rate )
@@ -3119,277 +3391,355 @@ struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate) {
return NULL;
}
-/*==========================================
- * What a status state suits by nearby MOB is looked for.
- *------------------------------------------*/
-int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
-{
- int cond1,cond2;
- struct mob_data **fr = NULL, *md = NULL, *mmd = NULL;
- int flag=0;
+/**
+ * Checks if the passed monster/character meets the passed status change requirements
+ * and returns it by reference parameter on success.
+ *
+ * @param bl The monster/character to check.
+ * @param ap List of arguments. (Source monster, MSC_* flag, SC_* flag, reference bl.)
+ * @return Always 0.
+ *
+ **/
+static int mob_getfriendstatus_sub(struct block_list *bl, va_list ap)
+{
nullpo_ret(bl);
- Assert_ret(bl->type == BL_MOB);
- md = BL_UCAST(BL_MOB, bl);
- nullpo_ret(mmd=va_arg(ap,struct mob_data *));
- if( mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10) )
+ struct mob_data *md = va_arg(ap, struct mob_data *);
+
+ nullpo_ret(md);
+
+ if (md->bl.id == bl->id && (battle_config.mob_ai & 0x10) == 0)
return 0;
- if (battle->check_target(&mmd->bl,bl,BCT_ENEMY)>0)
+ if (battle->check_target(&md->bl, bl, BCT_ENEMY) > 0)
+ return 0;
+
+ int cond1 = va_arg(ap, int);
+ int cond2 = va_arg(ap, int);
+ struct block_list **fr = va_arg(ap, struct block_list **);
+
+ if ((*fr) != NULL) // A friend was already found.
return 0;
- cond1=va_arg(ap,int);
- cond2=va_arg(ap,int);
- fr=va_arg(ap,struct mob_data **);
- if( cond2==-1 ){
- int j;
- for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){
- if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex]
+
+ int flag = 0;
+ struct status_change *sc = status->get_sc(bl);
+
+ if (cond2 == -1) { // Check for any of the common status alignments.
+ for (int i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) {
+ if ((flag = (sc->data[i] != NULL)) != 0) // Once an effect was found, break out. [Skotlex]
break;
}
- }else
- flag=( md->sc.data[cond2] != NULL );
- if( flag^( cond1==MSC_FRIENDSTATUSOFF ) )
- (*fr)=md;
+ } else {
+ flag = (sc->data[cond2] != NULL);
+ }
+
+ if ((flag ^ (cond1 == MSC_FRIENDSTATUSOFF)) != 0)
+ (*fr) = bl;
return 0;
}
-struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) {
- struct mob_data* fr = NULL;
+/**
+ * Gets a random monster/character within a range of 8 cells around md.
+ * If md is summoned (no monster slave!) a character is picker, otherwise a monster.
+ *
+ * @param md The monster which tries to cast a skill.
+ * @param cond1 Whether to check for active or inactive status change. (MSC_FRIENDSTATUSON/MSC_FRIENDSTATUSOFF)
+ * @param cond2 The status change (SC_* flag) to check.
+ * @return A randomly picked monster/character within range.
+ *
+ **/
+static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2)
+{
nullpo_ret(md);
- map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr);
+ int type = (md->special_state.ai != AI_NONE) ? BL_PC : BL_MOB;
+ struct block_list *fr = NULL;
+
+ map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8, type, md, cond1, cond2, &fr);
+
return fr;
}
-/*==========================================
- * Skill use judging
- *------------------------------------------*/
-int mobskill_use(struct mob_data *md, int64 tick, int event) {
- struct mob_skill *ms;
- struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
- struct block_list *bl;
- struct mob_data *fmd = NULL;
- int i,j,n;
-
+/**
+ * Checks if skill cast condition in fulfilled and executes the skill in case of success.
+ *
+ * @param md The monster which tries to cast a skill.
+ * @param tick The timestamp of skill execution.
+ * @param event The MSC_* flag which triggered the skill execution. (-1 for non-event skill conditions.)
+ * @return 0 on success, 1 on failure.
+ *
+ **/
+static int mob_skill_use(struct mob_data *md, int64 tick, int event)
+{
nullpo_ret(md);
- nullpo_ret(ms = md->db->skill);
- if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill)
- return 0;
+ struct mob_skill *ms = md->db->skill;
+
+ nullpo_ret(ms);
+
+ if (battle_config.mob_skill_rate == 0 || md->ud.skilltimer != INVALID_TIMER || md->db->maxskill == 0)
+ return 1;
if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0)
- return 0; //Skill act delay only affects non-event skills.
+ return 1; // Skill act delay only affects non-event skill conditions.
- //Pick a starting position and loop from that.
- i = (battle_config.mob_ai&0x100) ? rnd()%md->db->maxskill : 0;
- for (n = 0; n < md->db->maxskill; i++, n++) {
- int c2, flag = 0;
+ // Pick a starting position and loop from that.
+ int skill_idx = ((battle_config.mob_ai & 0x100) != 0) ? rnd() % md->db->maxskill : 0;
- if (i == md->db->maxskill)
- i = 0;
+ for (int i = 0; i < md->db->maxskill; skill_idx++, i++) {
+ if (skill_idx == md->db->maxskill)
+ skill_idx = 0;
- if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay)
+ if (DIFF_TICK(tick, md->skilldelay[skill_idx]) < ms[skill_idx].delay)
continue;
- c2 = ms[i].cond2;
+ enum MobSkillState state = ms[skill_idx].state;
- if (ms[i].state != md->state.skillstate) {
- if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY ||
- (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT)
- )) //ANYTARGET works with any state as long as there's a target. [Skotlex]
- ;
- else
+ if (state != md->state.skillstate) {
+ bool state_dead = (md->state.skillstate == MSS_DEAD);
+ bool any_target = (state == MSS_ANYTARGET && md->target_id != 0 && md->state.skillstate != MSS_LOOT);
+
+ // MSS_ANYTARGET works with any state as long as there's a target. [Skotlex]
+ if (state_dead || (state != MSS_ANY && !any_target))
continue;
}
- if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000)
+
+ if (rnd() % 10000 > ms[skill_idx].permillage)
continue;
- if (ms[i].cond1 == event)
- flag = 1; //Trigger skill.
- else if (ms[i].cond1 == MSC_SKILLUSED)
- flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0));
- else if(event == -1){
- //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle.
- switch (ms[i].cond1)
- {
- case MSC_ALWAYS:
- flag = 1; break;
- case MSC_MYHPLTMAXRATE: // HP< maxhp%
- flag = get_percentage(md->status.hp, md->status.max_hp);
- flag = (flag <= c2);
- break;
- case MSC_MYHPINRATE:
- flag = get_percentage(md->status.hp, md->status.max_hp);
- flag = (flag >= c2 && flag <= ms[i].val[0]);
- break;
- case MSC_MYSTATUSON: // status[num] on
- case MSC_MYSTATUSOFF: // status[num] off
- if (!md->sc.count) {
- flag = 0;
- } else if (ms[i].cond2 == -1) {
- for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++)
- if ((flag = (md->sc.data[j]!=NULL)) != 0)
- break;
- } else {
- flag = (md->sc.data[ms[i].cond2]!=NULL);
+ int cast_cond = ms[skill_idx].cond1;
+ int cond_data = ms[skill_idx].cond2;
+ int flag = 0;
+ struct block_list *fbl = NULL; // Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
+
+ if (cast_cond == event) {
+ flag = 1; // Trigger skill.
+ } else if (cast_cond == MSC_SKILLUSED) {
+ flag = ((event & 0xFFFF) == MSC_SKILLUSED && ((event >> 16) == cond_data || cond_data == 0));
+ } else if (event == -1) {
+ // Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle.
+ switch (cast_cond) {
+ case MSC_ALWAYS:
+ flag = 1;
+ break;
+ case MSC_MYHPLTMAXRATE: // HP <= x%
+ flag = get_percentage(md->status.hp, md->status.max_hp);
+ flag = (flag <= cond_data);
+ break;
+ case MSC_MYHPINRATE: // HP >= x% && HP <= y%
+ flag = get_percentage(md->status.hp, md->status.max_hp);
+ flag = (flag >= cond_data && flag <= ms[skill_idx].val[0]);
+ break;
+ case MSC_MYSTATUSON: // Status change x is active.
+ case MSC_MYSTATUSOFF: // Status change x is inactive.
+ if (cond_data == -1) { // Check for any of the common status alignments.
+ for (int j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) {
+ if ((flag = (md->sc.data[j] != NULL)) != 0)
+ break;
}
- flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
- case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
- flag = ((fbl = mob->getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
- case MSC_FRIENDHPINRATE:
- flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
- case MSC_FRIENDSTATUSON: // friend status[num] on
- case MSC_FRIENDSTATUSOFF: // friend status[num] off
- flag = ((fmd = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
- case MSC_SLAVELT: // slave < num
- flag = (mob->countslave(&md->bl) < c2 ); break;
- case MSC_ATTACKPCGT: // attack pc > num
- flag = (unit->counttargeted(&md->bl) > c2); break;
- case MSC_SLAVELE: // slave <= num
- flag = (mob->countslave(&md->bl) <= c2 ); break;
- case MSC_ATTACKPCGE: // attack pc >= num
- flag = (unit->counttargeted(&md->bl) >= c2); break;
- case MSC_AFTERSKILL:
- flag = (md->ud.skill_id == c2); break;
- case MSC_RUDEATTACKED:
- flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT);
- if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
- break;
- case MSC_MASTERHPLTMAXRATE:
- flag = ((fbl = mob->getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
- case MSC_MASTERATTACKED:
- flag = (md->master_id > 0 && (fbl=map->id2bl(md->master_id)) != NULL && unit->counttargeted(fbl) > 0);
- break;
- case MSC_ALCHEMIST:
- flag = (md->state.alchemist);
- break;
+ } else {
+ flag = (md->sc.data[cond_data] != NULL);
+ }
+
+ flag ^= (cast_cond == MSC_MYSTATUSOFF);
+ break;
+ case MSC_FRIENDHPLTMAXRATE: // FriendHP <= x%
+ flag = ((fbl = mob->getfriendhprate(md, 0, cond_data)) != NULL);
+ break;
+ case MSC_FRIENDHPINRATE: // FriendHP >= x% && FriendHP <= y%
+ flag = ((fbl = mob->getfriendhprate(md, cond_data, ms[skill_idx].val[0])) != NULL);
+ break;
+ case MSC_FRIENDSTATUSON: // Friend's status change x is active.
+ case MSC_FRIENDSTATUSOFF: // Friend's status change x is inactive.
+ flag = ((fbl = mob->getfriendstatus(md, cast_cond, cond_data)) != NULL);
+ break;
+ case MSC_SLAVELT: // Monster has less than x active slaves.
+ flag = (mob->countslave(&md->bl) < cond_data);
+ break;
+ case MSC_ATTACKPCGT: // Monster is attacked by more than x units.
+ flag = (unit->counttargeted(&md->bl) > cond_data);
+ break;
+ case MSC_SLAVELE: // Monster has x or less active slaves.
+ flag = (mob->countslave(&md->bl) <= cond_data);
+ break;
+ case MSC_ATTACKPCGE: // Monster is attacked by x or more units.
+ flag = (unit->counttargeted(&md->bl) >= cond_data);
+ break;
+ case MSC_AFTERSKILL: // Monster used skill x, or any skill if x is 0.
+ flag = (md->ud.skill_id == cond_data || cond_data == 0);
+ break;
+ case MSC_RUDEATTACKED: // Monster was rude attacked RUDE_ATTACKED_COUNT or more times.
+ flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT);
+
+ // Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
+ if (flag)
+ md->state.attacked_count = 0;
+
+ break;
+ case MSC_MASTERHPLTMAXRATE: // MasterHP < x%
+ flag = ((fbl = mob->getmasterhpltmaxrate(md, cond_data)) != NULL);
+ break;
+ case MSC_MASTERATTACKED: // Monster's master is under attack.
+ flag = (md->master_id > 0 && (fbl = map->id2bl(md->master_id)) != NULL);
+ flag = (fbl != NULL && unit->counttargeted(fbl) > 0);
+ break;
+ case MSC_ALCHEMIST: // Monster was summoned by an Alchemist.
+ flag = (md->state.alchemist != 0);
+ break;
}
}
- if (!flag)
- continue; //Skill requisite failed to be fulfilled.
+ if (flag == 0) // Skill cast condition not fulfilled.
+ continue;
- //Execute skill
- if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill.
- short x, y;
- switch (ms[i].target) {
- case MST_RANDOM: //Pick a random enemy within skill range.
- bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
- skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
- break;
- case MST_TARGET:
- case MST_AROUND5:
- case MST_AROUND6:
- case MST_AROUND7:
- case MST_AROUND8:
- bl = map->id2bl(md->target_id);
- break;
- case MST_MASTER:
- bl = &md->bl;
- if (md->master_id)
- bl = map->id2bl(md->master_id);
- if (bl) //Otherwise, fall through.
- break;
- case MST_FRIEND:
- bl = fbl?fbl:(fmd?&fmd->bl:&md->bl);
- break;
- default:
- bl = &md->bl;
+ // Execute skill.
+ if (skill->get_casttype(ms[skill_idx].skill_id) == CAST_GROUND) { // Ground skill.
+ int target_type = ms[skill_idx].target;
+ int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv);
+ struct block_list *bl;
+
+ switch (target_type) {
+ case MST_RANDOM: // Pick a random enemy within skill range. Skill center is monster position.
+ bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range);
+ break;
+ case MST_TARGET: // Monster's current target is within skill range. Skill center is monster position.
+ case MST_AROUND5: // Monster's current target is within skill range. Skill center is a random cell within a range of 1.
+ case MST_AROUND6: // Monster's current target is within skill range. Skill center is a random cell within a range of 2.
+ case MST_AROUND7: // Monster's current target is within skill range. Skill center is a random cell within a range of 3.
+ case MST_AROUND8: // Monster's current target is within skill range. Skill center is a random cell within a range of 4.
+ bl = map->id2bl(md->target_id);
+ break;
+ case MST_MASTER: // Monster's master is within skill range. Skill center is monster position.
+ // If monster has no master, use the monster as target,
+ bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl;
+
+ if (bl != NULL)
break;
+
+ // If monster has a master but master wasn't found, try a friend.
+ FALLTHROUGH
+ case MST_FRIEND: // Monster's friend is within skill range. Skill center is monster position.
+ bl = (fbl != NULL) ? fbl : &md->bl;
+ break;
+ default: // Monster is within skill range. Skill center is monster position.
+ bl = &md->bl;
+ break;
}
- if (!bl) continue;
-
- x = bl->x;
- y = bl->y;
- // Look for an area to cast the spell around...
- if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) {
- j = ms[i].target >= MST_AROUND1?
- (ms[i].target-MST_AROUND1) +1:
- (ms[i].target-MST_AROUND5) +1;
- map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3);
+
+ if (bl == NULL) // No target found.
+ continue;
+
+ short x = bl->x;
+ short y = bl->y;
+
+ // Find a target cell.
+ if (target_type >= MST_AROUND5 && target_type <= MST_AROUND) {
+ int range = target_type - ((target_type >= MST_AROUND1) ? MST_AROUND1 : MST_AROUND5) + 1;
+ map->search_freecell(&md->bl, md->bl.m, &x, &y, range, range, 3);
}
- md->skill_idx = i;
+
+ md->skill_idx = skill_idx;
map->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
- || !unit->skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
- ) {
+
+ uint16 sk_id = ms[skill_idx].skill_id;
+ uint16 sk_lv = ms[skill_idx].skill_lv;
+ int casttime = ms[skill_idx].casttime;
+ short cancel = ms[skill_idx].cancel;
+
+ if (!battle->check_range(&md->bl, bl, skill_range)
+ || unit->skilluse_pos2(&md->bl, x, y, sk_id, sk_lv, casttime, cancel) == 0) {
map->freeblock_unlock();
continue;
}
- } else {
- //Targeted skill
- switch (ms[i].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));
- break;
- case MST_TARGET:
- bl = map->id2bl(md->target_id);
- break;
- case MST_MASTER:
- bl = &md->bl;
- if (md->master_id)
- bl = map->id2bl(md->master_id);
- if (bl) //Otherwise, fall through.
- break;
- case MST_FRIEND:
- if (fbl) {
- bl = fbl;
- break;
- } else if (fmd) {
- bl = &fmd->bl;
- break;
- } // else fall through
- default:
- bl = &md->bl;
+ } else { // Targeted skill.
+ int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv);
+ struct block_list *bl;
+
+ switch (ms[skill_idx].target) {
+ case MST_RANDOM: // Pick a random enemy within skill range.
+ bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range);
+ break;
+ case MST_TARGET: // Monster's current target is within skill range.
+ bl = map->id2bl(md->target_id);
+ break;
+ case MST_MASTER: // Monster's master is within skill range.
+ // If monster has no master, use the monster as target,
+ bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl;
+
+ if (bl != NULL)
break;
+
+ // If monster has a master but master wasn't found, try a friend.
+ FALLTHROUGH
+ case MST_FRIEND: // Monster's friend is within skill range.
+ bl = (fbl != NULL) ? fbl : &md->bl;
+ break;
+ default: // Monster is within skill range.
+ bl = &md->bl;
+ break;
}
- if (!bl) continue;
- md->skill_idx = i;
+ if (bl == NULL) // No target found.
+ continue;
+
+ md->skill_idx = skill_idx;
map->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
- || !unit->skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
- ) {
+
+ uint16 sk_id = ms[skill_idx].skill_id;
+ uint16 sk_lv = ms[skill_idx].skill_lv;
+ int casttime = ms[skill_idx].casttime;
+ short cancel = ms[skill_idx].cancel;
+
+ if (!battle->check_range(&md->bl, bl, skill_range)
+ || unit->skilluse_id2(&md->bl, bl->id, sk_id, sk_lv, casttime, cancel) == 0) {
map->freeblock_unlock();
continue;
}
}
- //Skill used. Post-setups...
- if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak]
- struct mob_chat *mc = mob->chat(ms[i].msg_id);
+
+ // Skill used.
+ if (ms[skill_idx].msg_id != 0) { // Display color message. [SnakeDrak]
char temp[CHAT_SIZE_MAX];
char name[NAME_LENGTH];
- snprintf(name, sizeof name,"%s", md->name);
- strtok(name, "#"); // discard extra name identifier if present [Daegaladh]
- snprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
+ struct mob_chat *mc = mob->chat(ms[skill_idx].msg_id);
+
+ snprintf(name, sizeof(name), "%s", md->name);
+ strtok(name, "#"); // Discard extra name identifier if present. [Daegaladh]
+ safesnprintf(temp, sizeof(temp), "%s : %s", name, mc->msg);
clif->messagecolor(&md->bl, mc->color, temp);
}
- if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill.
- for (j = 0; j < md->db->maxskill; j++)
- if (md->db->skill[j].skill_id == ms[i].skill_id)
- md->skilldelay[j]=tick;
- } else
- md->skilldelay[i]=tick;
+
+ if ((battle_config.mob_ai & 0x200) == 0) { // Pass on delay to same skill.
+ for (int j = 0; j < md->db->maxskill; j++) {
+ if (md->db->skill[j].skill_id == ms[skill_idx].skill_id)
+ md->skilldelay[j] = tick;
+ }
+ } else {
+ md->skilldelay[skill_idx] = tick;
+ }
+
map->freeblock_unlock();
- return 1;
+ return 0;
}
- //No skill was used.
+
+ // No skill was used.
md->skill_idx = -1;
- return 0;
+ return 1;
}
+
/*==========================================
* Skill use event processing
*------------------------------------------*/
-int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag) {
+static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag)
+{
int target_id, res = 0;
nullpo_ret(md);
nullpo_ret(src);
if(md->bl.prev == NULL || md->status.hp <= 0)
- return 0;
+ return 1;
if (md->special_state.ai == AI_SPHERE) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
md->state.alchemist = 1;
@@ -3409,7 +3759,7 @@ int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int
else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic.
res = mob->skill_use(md, tick, MSC_LONGRANGEATTACKED);
- if (!res)
+ if (res != 0)
//Restore previous target only if skill condition failed to trigger. [Skotlex]
md->target_id = target_id;
//Otherwise check if the target is an enemy, and unlock if needed.
@@ -3420,7 +3770,7 @@ int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int
}
// Player cloned mobs. [Valaris]
-int mob_is_clone(int class_)
+static int mob_is_clone(int class_)
{
if(class_ < MOB_CLONE_START || class_ > MOB_CLONE_END)
return 0;
@@ -3429,215 +3779,243 @@ int mob_is_clone(int class_)
return class_;
}
-//Flag values:
-//&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.
-int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, uint32 mode, int flag, unsigned int duration)
+/**
+ * Spawns a mob which is a clone of another character.
+ *
+ * @param sd The character which should be cloned.
+ * @param m The ID of the map where the clone should be spawned.
+ * @param x The x coordinate where the clone should be spawned.
+ * @param y The y coordinate where the clone should be spawned.
+ * @param event The name of the event which should be executed when the clone is killed.
+ * @param master_id If passed, the clone will be attached to this account ID.
+ * @param mode The clone's mob mode(s). (Defaults to MD_CANMOVE|MD_AGGRESSIVE|MD_ASSIST|MD_CANATTACK.)
+ * @param flag 0 - target characters; 1 - target mobs.
+ * @param duration How long the clone will live before it is auto-removed. (ms)
+ * @return The spawned clone's GID, or 0 if spawning failed.
+ *
+ **/
+static int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id,
+ uint32 mode, int flag, unsigned int duration)
{
- int class_;
- int i,j,h,inf, fd;
- struct mob_data *md;
- struct mob_skill *ms;
- struct mob_db* db;
- struct status_data *mstatus;
-
nullpo_ret(sd);
- if(pc_isdead(sd) && master_id && flag&1)
+ if (pc_isdead(sd) && master_id != 0 && flag == 1)
return 0;
- ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL );
- if(class_ < 0 || class_ >= MOB_CLONE_END)
+ int class_;
+
+ ARR_FIND(MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL);
+
+ if (class_ < 0 || class_ >= MOB_CLONE_END)
return 0;
- db = mob->db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
- mstatus = &db->status;
- strcpy(db->sprite,sd->status.name);
- strcpy(db->name,sd->status.name);
- strcpy(db->jname,sd->status.name);
- db->lv=status->get_lv(&sd->bl);
+ mob->db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db));
+
+ struct mob_db *db = mob->db_data[class_];
+ struct status_data *mstatus = &db->status;
+
+ strcpy(db->sprite, sd->status.name);
+ strcpy(db->name, sd->status.name);
+ strcpy(db->jname, sd->status.name);
+ db->lv = status->get_lv(&sd->bl);
+ db->dmg_taken_rate = 100;
memcpy(mstatus, &sd->base_status, sizeof(struct status_data));
- mstatus->rhw.atk2= mstatus->dex + mstatus->rhw.atk + mstatus->rhw.atk2; //Max ATK
- mstatus->rhw.atk = mstatus->dex; //Min ATK
- if (mstatus->lhw.atk) {
- mstatus->lhw.atk2= mstatus->dex + mstatus->lhw.atk + mstatus->lhw.atk2; //Max ATK
- mstatus->lhw.atk = mstatus->dex; //Min ATK
+ mstatus->rhw.atk2 = mstatus->dex + mstatus->rhw.atk + mstatus->rhw.atk2; /// Max ATK.
+ mstatus->rhw.atk = mstatus->dex; /// Min ATK.
+
+ if (mstatus->lhw.atk > 0) {
+ mstatus->lhw.atk2 = mstatus->dex + mstatus->lhw.atk + mstatus->lhw.atk2; /// Max ATK.
+ mstatus->lhw.atk = mstatus->dex; /// Min ATK.
}
- if (mode != MD_NONE) //User provided mode.
+
+ if (mode != MD_NONE) /// User provided mode.
mstatus->mode = mode;
- else if (flag&1) //Friendly Character, remove looting.
+ else if (flag == 1) /// Friendly Character, remove looting.
mstatus->mode &= ~MD_LOOTER;
+
mstatus->hp = mstatus->max_hp;
mstatus->sp = mstatus->max_sp;
memcpy(&db->vd, &sd->vd, sizeof(struct view_data));
- db->base_exp=1;
- db->job_exp=1;
- db->range2=AREA_SIZE; //Let them have the same view-range as players.
- db->range3=AREA_SIZE; //Min chase of a screen.
- db->option=sd->sc.option;
+ db->base_exp = 1;
+ db->job_exp = 1;
+ db->range2 = AREA_SIZE; /// Let them have the same view-range as players.
+ db->range3 = AREA_SIZE; /// Min chase of a screen.
+ db->option = sd->sc.option;
- //Skill copy [Skotlex]
- ms = &db->skill[0];
+ const int fd = sd->fd;
- /**
- * We temporarily disable sd's fd so it doesn't receive the messages from skill_check_condition_castbegin
- **/
- fd = sd->fd;
- sd->fd = 0;
-
- //Go Backwards to give better priority to advanced skills.
- for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
- int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][j].idx;
- int skill_id = pc->skill_tree[pc->class2idx(sd->status.class_)][j].id;
- if (!skill_id || sd->status.skill[idx].lv < 1 ||
- (skill->dbs->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
- )
+ sd->fd = 0; /// Temporarily disable sd's fd so it doesn't receive the messages from skill_check_condition_castbegin.
+
+ struct mob_skill *mob_skills = &db->skill[0];
+
+ /// Go Backwards to give better priority to advanced skills.
+ for (int i = 0, j = MAX_SKILL_TREE - 1; j >= 0 && i < MAX_MOBSKILL; j--) {
+ const int idx = pc->skill_tree[pc->class2idx(sd->status.class)][j].idx;
+ const int skill_id = pc->skill_tree[pc->class2idx(sd->status.class)][j].id;
+
+ if (skill_id == 0 || sd->status.skill[idx].lv < 1 ||
+ (skill->dbs->db[idx].inf2 & (INF2_WEDDING_SKILL | INF2_GUILD_SKILL)) > 0)
continue;
- for(h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) {
- if( skill_id == map->list[sd->bl.m].zone->disabled_skills[h]->nameid && map->list[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE ) {
+
+ int h;
+
+ for (h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) {
+ if (skill_id == map->list[sd->bl.m].zone->disabled_skills[h]->nameid &&
+ map->list[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE)
break;
- }
}
- if( h < map->list[sd->bl.m].zone->disabled_skills_count )
+
+ if (h < map->list[sd->bl.m].zone->disabled_skills_count)
continue;
- //Normal aggressive mob, disable skills that cannot help them fight
- //against players (those with flags UF_NOMOB and UF_NOPC are specific
- //to always aid players!) [Skotlex]
- if (!(flag&1) &&
- skill->get_unit_id(skill_id, 0) &&
- skill->get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC))
+
+ /// Normal aggressive mob. Disable skills that cannot help fighting against players. (Those with flags UF_NOMOB and UF_NOPC are specific to always aid players!) [Skotlex]
+ if (flag == 0 && skill->get_unit_id(skill_id, 0) != 0 &&
+ (skill->get_unit_flag(skill_id) & (UF_NOMOB | UF_NOPC)) > 0)
continue;
- /**
- * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
- **/
- if( !skill->check_condition_castbegin(sd,skill_id,sd->status.skill[idx].lv) )
+
+ /// The clone should be able to cast the skill. (E.g. have the required weapon.) [bugreport:5299]
+ if (skill->check_condition_castbegin(sd, skill_id, sd->status.skill[idx].lv) == 0)
continue;
- memset (&ms[i], 0, sizeof(struct mob_skill));
- ms[i].skill_id = skill_id;
- ms[i].skill_lv = sd->status.skill[idx].lv;
- ms[i].state = MSS_ANY;
- ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5%
- ms[i].emotion = -1;
- ms[i].cancel = 0;
- ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv);
- ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv);
-
- inf = skill->dbs->db[idx].inf;
- if (inf&INF_ATTACK_SKILL) {
- ms[i].target = MST_TARGET;
- ms[i].cond1 = MSC_ALWAYS;
- if (skill->get_range(skill_id, ms[i].skill_lv) > 3)
- ms[i].state = MSS_ANYTARGET;
+ memset(&mob_skills[i], 0, sizeof(struct mob_skill));
+ mob_skills[i].skill_id = skill_id;
+ mob_skills[i].skill_lv = sd->status.skill[idx].lv;
+ mob_skills[i].state = MSS_ANY;
+ mob_skills[i].permillage = 500 * battle_config.mob_skill_rate / 100; /// Default chance of all skills: 5%
+ mob_skills[i].emotion = -1;
+ mob_skills[i].cancel = 0;
+ mob_skills[i].casttime = skill->cast_fix(&sd->bl, skill_id, mob_skills[i].skill_lv);
+ mob_skills[i].delay = 5000 + skill->delay_fix(&sd->bl, skill_id, mob_skills[i].skill_lv);
+
+ const int inf = skill->dbs->db[idx].inf;
+
+ if ((inf & INF_ATTACK_SKILL) == INF_ATTACK_SKILL) {
+ mob_skills[i].target = MST_TARGET;
+ mob_skills[i].cond1 = MSC_ALWAYS;
+
+ if (skill->get_range(skill_id, mob_skills[i].skill_lv) > 3)
+ mob_skills[i].state = MSS_ANYTARGET;
else
- ms[i].state = MSS_BERSERK;
- } else if(inf&INF_GROUND_SKILL) {
- if (skill->get_inf2(skill_id)&INF2_TRAP) { //Traps!
- ms[i].state = MSS_IDLE;
- ms[i].target = MST_AROUND2;
- ms[i].delay = 60000;
- } else if (skill->get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy
- ms[i].state = MSS_ANYTARGET;
- ms[i].target = MST_TARGET;
- ms[i].cond1 = MSC_ALWAYS;
- } else { //Target allies
- ms[i].target = MST_FRIEND;
- ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
- ms[i].cond2 = 95;
+ mob_skills[i].state = MSS_BERSERK;
+ } else if ((inf & INF_GROUND_SKILL) == INF_GROUND_SKILL) {
+ if ((skill->get_inf2(skill_id) & INF2_TRAP) == INF2_TRAP) { /// Traps!
+ mob_skills[i].state = MSS_IDLE;
+ mob_skills[i].target = MST_AROUND2;
+ mob_skills[i].delay = 60000;
+ } else if (skill->get_unit_target(skill_id) == BCT_ENEMY) { /// Target Enemy.
+ mob_skills[i].state = MSS_ANYTARGET;
+ mob_skills[i].target = MST_TARGET;
+ mob_skills[i].cond1 = MSC_ALWAYS;
+ } else { /// Target allies.
+ mob_skills[i].target = MST_FRIEND;
+ mob_skills[i].cond1 = MSC_FRIENDHPLTMAXRATE;
+ mob_skills[i].cond2 = 95;
}
- } else if (inf&INF_SELF_SKILL) {
- if (skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill.
- ms[i].target = MST_TARGET;
- ms[i].cond1 = MSC_ALWAYS;
- if (skill->get_range(skill_id, ms[i].skill_lv) > 3) {
- ms[i].state = MSS_ANYTARGET;
- } else {
- ms[i].state = MSS_BERSERK;
- }
- } else { //Self skill
- ms[i].target = MST_SELF;
- ms[i].cond1 = MSC_MYHPLTMAXRATE;
- ms[i].cond2 = 90;
- ms[i].permillage = 2000;
- //Delay: Remove the stock 5 secs and add half of the support time.
- ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2;
- if (ms[i].delay < 5000)
- ms[i].delay = 5000; //With a minimum of 5 secs.
+ } else if ((inf & INF_SELF_SKILL) == INF_SELF_SKILL) {
+ if ((skill->get_inf2(skill_id) & INF2_NO_TARGET_SELF) == INF2_NO_TARGET_SELF) { /// Auto-select target skill.
+ mob_skills[i].target = MST_TARGET;
+ mob_skills[i].cond1 = MSC_ALWAYS;
+
+ if (skill->get_range(skill_id, mob_skills[i].skill_lv) > 3)
+ mob_skills[i].state = MSS_ANYTARGET;
+ else
+ mob_skills[i].state = MSS_BERSERK;
+ } else { /// Self skill.
+ mob_skills[i].target = MST_SELF;
+ mob_skills[i].cond1 = MSC_MYHPLTMAXRATE;
+ mob_skills[i].cond2 = 90;
+ mob_skills[i].permillage = 2000;
+
+ const int time1 = skill->get_time(skill_id, mob_skills[i].skill_lv);
+ const int time2 = skill->get_time2(skill_id, mob_skills[i].skill_lv);
+
+ /** Delay: Remove the stock 5 secs and add half of the support time. **/
+ mob_skills[i].delay += -5000 + (time1 + time2) / 2;
+
+ if (mob_skills[i].delay < 5000)
+ mob_skills[i].delay = 5000; /// With a minimum of 5 seconds.
}
- } else if (inf&INF_SUPPORT_SKILL) {
- ms[i].target = MST_FRIEND;
- ms[i].cond1 = MSC_FRIENDHPLTMAXRATE;
- ms[i].cond2 = 90;
+ } else if ((inf & INF_SUPPORT_SKILL) == INF_SUPPORT_SKILL) {
+ mob_skills[i].target = MST_FRIEND;
+ mob_skills[i].cond1 = MSC_FRIENDHPLTMAXRATE;
+ mob_skills[i].cond2 = 90;
+
if (skill_id == AL_HEAL)
- ms[i].permillage = 5000; //Higher skill rate usage for heal.
+ mob_skills[i].permillage = 5000; /// Higher skill rate usage for heal.
else if (skill_id == ALL_RESURRECTION)
- ms[i].cond2 = 1;
- //Delay: Remove the stock 5 secs and add half of the support time.
- ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2;
- if (ms[i].delay < 2000)
- ms[i].delay = 2000; //With a minimum of 2 secs.
-
- if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self.
- memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill));
+ mob_skills[i].cond2 = 1;
+
+ const int time1 = skill->get_time(skill_id, mob_skills[i].skill_lv);
+ const int time2 = skill->get_time2(skill_id, mob_skills[i].skill_lv);
+
+ /** Delay: Remove the stock 5 secs and add half of the support time. **/
+ mob_skills[i].delay += -5000 + (time1 + time2) / 2;
+
+ if (mob_skills[i].delay < 2000)
+ mob_skills[i].delay = 2000; /// With a minimum of 2 seconds.
+
+ if (i + 1 < MAX_MOBSKILL) { /// Duplicate this so it also triggers on self.
+ memcpy(&mob_skills[i + 1], &mob_skills[i], sizeof(struct mob_skill));
db->maxskill = ++i;
- ms[i].target = MST_SELF;
- ms[i].cond1 = MSC_MYHPLTMAXRATE;
+ mob_skills[i].target = MST_SELF;
+ mob_skills[i].cond1 = MSC_MYHPLTMAXRATE;
}
} else {
- switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered.
- case MO_TRIPLEATTACK:
- case TF_DOUBLE:
- case GS_CHAINACTION:
- ms[i].state = MSS_BERSERK;
- ms[i].target = MST_TARGET;
- ms[i].cond1 = MSC_ALWAYS;
- ms[i].permillage = skill_id==MO_TRIPLEATTACK?(3000-ms[i].skill_lv*100):(ms[i].skill_lv*500);
- ms[i].delay -= 5000; //Remove the added delay as these could trigger on "all hits".
- break;
- default: //Untreated Skill
- continue;
+ switch (skill_id) { /// Certain special skills that are passive, and thus, never triggered.
+ case MO_TRIPLEATTACK:
+ FALLTHROUGH
+ case TF_DOUBLE:
+ FALLTHROUGH
+ case GS_CHAINACTION:
+ mob_skills[i].state = MSS_BERSERK;
+ mob_skills[i].target = MST_TARGET;
+ mob_skills[i].cond1 = MSC_ALWAYS;
+
+ if (skill_id == MO_TRIPLEATTACK)
+ mob_skills[i].permillage = 3000 - mob_skills[i].skill_lv * 100;
+ else
+ mob_skills[i].permillage = mob_skills[i].skill_lv * 500;
+
+ mob_skills[i].delay -= 5000; /// Remove the added delay as these could trigger on "all hits".
+ break;
+ default: /// Untreated skill.
+ continue;
}
}
- if (battle_config.mob_skill_rate!= 100)
- ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100;
- if (battle_config.mob_skill_delay != 100)
- ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100;
+ mob_skills[i].permillage = mob_skills[i].permillage * battle_config.mob_skill_rate / 100;
+ mob_skills[i].delay = mob_skills[i].delay * battle_config.mob_skill_delay / 100;
db->maxskill = ++i;
}
- /**
- * We grant the session it's fd value back.
- **/
- sd->fd = fd;
+ sd->fd = fd; /// We grant the session it's fd value back.
- //Finally, spawn it.
- md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE);
- if (!md) return 0; //Failed?
+ /// Finally spawn it.
+ struct mob_data *md = mob->once_spawn_sub(&sd->bl, m, x, y, DEFAULT_MOB_NAME, class_, event, SZ_SMALL, AI_NONE, 0);
+
+ if (md == NULL)
+ return 0; /// Failed?
md->special_state.clone = 1;
- if (master_id || flag || duration) { //Further manipulate crafted char.
- if (flag&1) //Friendly Character
- md->special_state.ai = AI_ATTACK;
- if (master_id) //Attach to Master
- md->master_id = master_id;
- if (duration) //Auto Delete after a while.
- {
- if( md->deletetimer != INVALID_TIMER )
- timer->delete(md->deletetimer, mob->timer_delete);
- md->deletetimer = timer->add(timer->gettick() + duration, mob->timer_delete, md->bl.id, 0);
- }
+ if (flag == 1) /// Friendly character.
+ md->special_state.ai = AI_ATTACK;
+
+ if (master_id != 0) /// Attach to master.
+ md->master_id = master_id;
+
+ if (duration > 0) { /// Auto delete after a while.
+ if (md->deletetimer != INVALID_TIMER)
+ timer->delete(md->deletetimer, mob->timer_delete);
+
+ md->deletetimer = timer->add(timer->gettick() + duration, mob->timer_delete, md->bl.id, 0);
}
mob->spawn(md);
-
return md->bl.id;
}
-int mob_clone_delete(struct mob_data *md)
+static int mob_clone_delete(struct mob_data *md)
{
int class_;
@@ -3660,7 +4038,7 @@ int mob_clone_delete(struct mob_data *md)
/*==========================================
* Since un-setting [ mob ] up was used, it is an initial provisional value setup.
*------------------------------------------*/
-int mob_makedummymobdb(int class_)
+static int mob_makedummymobdb(int class_)
{
if (mob->dummy != NULL)
{
@@ -3702,7 +4080,7 @@ int mob_makedummymobdb(int class_)
}
//Adjusts the drop rate of item according to the criteria given. [Skotlex]
-unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max)
+static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max)
{
int64 rate = baserate;
@@ -3723,6 +4101,28 @@ unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_
return (unsigned int)cap_value(rate,rate_min,rate_max);
}
+static struct item_drop_ratio *mob_get_item_drop_ratio(int nameid)
+{
+ Assert_retr(NULL, nameid > 0);
+ if (nameid < ARRAYLENGTH(item_drop_ratio_db)) {
+ return item_drop_ratio_db[nameid];
+ } else {
+ return (struct item_drop_ratio *)idb_get(item_drop_ratio_other_db, nameid);
+ }
+}
+
+static void mob_set_item_drop_ratio(int nameid, struct item_drop_ratio *ratio)
+{
+ Assert_retv(nameid > 0);
+ if (nameid < ARRAYLENGTH(item_drop_ratio_db)) {
+ Assert_retv(item_drop_ratio_db[nameid] == NULL);
+ item_drop_ratio_db[nameid] = ratio;
+ } else {
+ Assert_retv(idb_get(item_drop_ratio_other_db, nameid) == NULL);
+ idb_put(item_drop_ratio_other_db, nameid, ratio);
+ }
+}
+
/**
* Check if global item drop rate is overridden for given item
* in db/mob_item_ratio.txt
@@ -3730,23 +4130,27 @@ unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_
* @param mob_id ID of the monster
* @param rate_adjust pointer to store ratio if found
*/
-void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
+static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
{
+ struct item_drop_ratio *dropRatio;
nullpo_retv(rate_adjust);
- if( item_drop_ratio_db[nameid] ) {
- if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs
+
+ dropRatio = mob->get_item_drop_ratio(nameid);
+ if (dropRatio) {
+ if (dropRatio->mob_id[0] ) { // only for listed mobs
int i;
- ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id);
- if(i < MAX_ITEMRATIO_MOBS) // found
- *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
+ ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, dropRatio->mob_id[i] == mob_id);
+ if (i < MAX_ITEMRATIO_MOBS) // found
+ *rate_adjust = dropRatio->drop_ratio;
}
else // for all mobs
- *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
+ *rate_adjust = dropRatio->drop_ratio;
}
}
/* (mob_parse_dbrow)_cap_value */
-static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int value) {
+static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int value)
+{
if( value > max ) {
ShowError("mob_parse_dbrow_cap_value: for class '%d', field value '%d' is higher than the maximum '%d'! capping...\n", class_, value, max);
return max;
@@ -3758,13 +4162,217 @@ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int va
}
/**
+ * Reads one possible option for a option slot in a option drop group
+ * @param option : Libconfig entry
+ * @param entry : memory db entry for current slot
+ * @param idx : index of entry where this option should be inserted at
+ * @param calc_rate : if rates should be recalculated after reading all entries
+ * @param slot : option group slot being read (for messages)
+ * @param group : option group being read (for messages)
+ * @return true if it successfully read the entry, false otherwise
+ */
+static bool mob_read_optdrops_option(struct config_setting_t *option, struct optdrop_group_optslot *entry, int *idx, bool *calc_rate, int slot, const char *group)
+{
+ nullpo_retr(false, option);
+ nullpo_retr(false, entry);
+ nullpo_retr(false, idx);
+ nullpo_retr(false, calc_rate);
+ nullpo_retr(false, group);
+
+ const char *name = config_setting_name(option);
+ int opt_id;
+
+ if (strncmp(name, "Rate", 4) == 0)
+ return true;
+
+ if (script->get_constant(name, &opt_id) == false) {
+ ShowWarning("mob_read_optdrops_option: Invalid option \"%s\" for option slot %d of %s group, skipping.\n", name, slot, group);
+ return false;
+ }
+
+ int min = 0, max = 0, opt_rate = 0;
+ if (config_setting_is_number(option)) {
+ // OptionName: value
+ min = libconfig->setting_get_int(option);
+ } else if (config_setting_is_array(option)) {
+ // OptionName: [min, max]
+ // OptionName: [min, max, rate]
+ int slen = libconfig->setting_length(option);
+
+ if (slen >= 2) {
+ // [min, max,...]
+ min = libconfig->setting_get_int_elem(option, 0);
+ max = libconfig->setting_get_int_elem(option, 1);
+ }
+
+ if (slen == 3) {
+ // [min, max, rate]
+ opt_rate = libconfig->setting_get_int_elem(option, 2);
+ }
+ } else {
+ ShowWarning("mob_read_optdrops_option: Invalid value \"%s\" for option slot %d of %s group, skipping.\n", name, slot, group);
+ return false;
+ }
+
+ if (max < min)
+ max = min;
+
+ entry->options[*idx].id = opt_id;
+ entry->options[*idx].min = min;
+ entry->options[*idx].max = max;
+ entry->options[*idx].rate = opt_rate;
+
+ if (entry->options[*idx].rate == 0)
+ *calc_rate = true;
+
+ (*idx)++;
+
+ return true;
+}
+
+/**
+ * Reads the settings for one random option slot of a random option drop group.
+ * @param optslot : The slot entry from config file
+ * @param n : slot index
+ * @param group_id : Group index
+ * @param group : group name (used in messages)
+ * @return true if it succesfully read, false otherwise
+ */
+static bool mob_read_optdrops_optslot(struct config_setting_t *optslot, int n, int group_id, const char *group)
+{
+ nullpo_retr(false, optslot);
+ nullpo_retr(false, group);
+ Assert_retr(false, group_id >= 0 && group_id < mob->opt_drop_groups_count);
+ Assert_retr(false, n >= 0 && n < MAX_ITEM_OPTIONS);
+
+ // Structure:
+ // {
+ // Rate: chance of option 1 (int)
+ // OptionName1: value
+ // OptionName2: [min, max]
+ // OptionName3: [min, max, rate]
+ // ....
+ // }
+
+ int drop_rate; // The rate for this option to be dropped (Rate field)
+ if (libconfig->setting_lookup_int(optslot, "Rate", &drop_rate) == CONFIG_FALSE) {
+ ShowWarning("mob_read_optdrops_optslot: Missing option %d rate in group %s, skipping.\n", n, group);
+ return false;
+ }
+
+ int count = libconfig->setting_length(optslot);
+ if (count <= 1) { // 1 = Rate
+ ShowWarning("mob_read_optdrops_optslot: Option %d of %s group doesn't contain any possible options, skipping.\n", n, group);
+ return false;
+ }
+
+ struct optdrop_group_optslot *entry = &(mob->opt_drop_groups[group_id].optslot[n]);
+ entry->options = aCalloc(sizeof(struct optdrop_group_option), count);
+
+ int idx = 0;
+ int i = 0;
+ struct config_setting_t *opt = NULL;
+ bool calc_rate = false;
+ while (i < count && (opt = libconfig->setting_get_elem(optslot, i)) != NULL) {
+ ++i;
+ mob->read_optdrops_option(opt, entry, &idx, &calc_rate, n, group);
+ }
+ entry->option_count = idx;
+ mob->opt_drop_groups[group_id].optslot_count++;
+ mob->opt_drop_groups[group_id].optslot_rate[n] = drop_rate;
+
+ // If there're empty rates, calculate them
+ if (calc_rate == true) {
+ for (int j = 0; j < idx; ++j) {
+ if (entry->options[j].rate == 0)
+ entry->options[j].rate = 10000 / idx;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Reads one random option drop group.
+ * @param group : Drop Group entry from config file
+ * @param n : group index
+ * @return true if it successfuly read, false otherwise
+ */
+static bool mob_read_optdrops_group(struct config_setting_t *group, int n)
+{
+ /* Structure:
+ <Group Name>: (
+ { <Option 1 drop data> },
+ { <Option 2 drop data> },
+ ... // Up to MAX_ITEM_OPTIONS
+ )
+ */
+ nullpo_retr(false, group);
+
+ const char *group_name = config_setting_name(group);
+
+ if (group_name == NULL || *group_name == '\0') {
+ ShowWarning("mob_read_optdrops_group: Invalid name for random option drop group, skipping group %d...\n", n);
+ return false;
+ }
+
+ script->set_constant2(group_name, n, false, false);
+
+ int i = 0;
+ struct config_setting_t *drop_data = NULL;
+ while (i < MAX_ITEM_OPTIONS && (drop_data = libconfig->setting_get_elem(group, i)) != NULL) {
+ mob->read_optdrops_optslot(drop_data, i, n, group_name);
+ i++;
+ }
+
+ return true;
+}
+
+/**
+ * Reads random option drop groups database.
+ */
+static bool mob_read_optdrops_db(void)
+{
+ char filepath[256];
+ libconfig->format_db_path("option_drop_groups.conf", filepath, sizeof(filepath));
+
+ struct config_t option_groups;
+ if (libconfig->load_file(&option_groups, filepath) == CONFIG_FALSE) {
+ ShowError("Failed to load option drop groups\n");
+ return false;
+ }
+
+ struct config_setting_t *its = libconfig->lookup(&option_groups, "option_drop_group_db");
+ struct config_setting_t *groups = NULL;
+
+ int i = 0;
+ if (its != NULL && (groups = libconfig->setting_get_elem(its, 0)) != NULL) {
+ int count = libconfig->setting_length(groups);
+ mob->opt_drop_groups = aCalloc(sizeof(struct optdrop_group), count);
+ mob->opt_drop_groups_count = count; // maximum size (used by assertions)
+
+ struct config_setting_t *group = NULL;
+ while ((group = libconfig->setting_get_elem(groups, i)) != NULL) {
+ mob->read_optdrops_group(group, i);
+ i++;
+ }
+ mob->opt_drop_groups_count = i; // number of entries used (should be the same amount)
+ }
+
+ libconfig->destroy(&option_groups);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, filepath);
+ return true;
+}
+
+/**
* Processes the stats for a mob database entry.
*
* @param[in,out] entry The destination mob_db entry, already initialized
* (mob_id is expected to be already set).
* @param[in] t The libconfig entry.
*/
-void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t)
+static void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t)
{
int i32;
nullpo_retv(entry);
@@ -3789,6 +4397,54 @@ void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t)
}
/**
+ * Processes the view data for a mob_db entry.
+ *
+ * @param[in,out] entry The destination mob_db entry, already initialized
+ * (mob_id, status.mode are expected to be already set).
+ * @param[in] t The libconfig entry.
+ */
+static void mob_read_db_viewdata_sub(struct mob_db *entry, struct config_setting_t *t)
+{
+ nullpo_retv(entry);
+ nullpo_retv(t);
+
+ struct config_setting_t *it;
+ int i32;
+
+ if ((it = libconfig->setting_get_member(t, "SpriteId")) != NULL)
+ entry->vd.class = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "WeaponId")) != NULL)
+ entry->vd.weapon = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "ShieldId")) != NULL)
+ entry->vd.shield = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "RobeId")) != NULL)
+ entry->vd.robe = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "HeadTopId")) != NULL)
+ entry->vd.head_top = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "HeadMidId")) != NULL)
+ entry->vd.head_mid = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "HeadLowId")) != NULL)
+ entry->vd.head_bottom = libconfig->setting_get_int(it);
+
+ if ((it = libconfig->setting_get_member(t, "HairStyleId")) != NULL)
+ entry->vd.hair_style = libconfig->setting_get_int(it);
+ else
+ entry->vd.hair_style = 1;
+
+ if ((it = libconfig->setting_get_member(t, "BodyStyleId")) != NULL)
+ entry->vd.body_style = libconfig->setting_get_int(it);
+ if ((it = libconfig->setting_get_member(t, "HairColorId")) != NULL)
+ entry->vd.hair_color = libconfig->setting_get_uint16(it);
+ if ((it = libconfig->setting_get_member(t, "BodyColorId")) != NULL)
+ entry->vd.cloth_color = libconfig->setting_get_uint16(it);
+ if (mob->lookup_const(t, "Gender", &i32) && i32 >= 0) {
+ entry->vd.sex = (char)i32;
+ }
+ if ((it = libconfig->setting_get_member(t, "Options")) != NULL)
+ entry->option = libconfig->setting_get_int(it) &~ (OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE);
+}
+
+/**
* Processes the mode for a mob_db entry.
*
* @param[in] entry The destination mob_db entry, already initialized.
@@ -3796,7 +4452,7 @@ void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t)
*
* @return The parsed mode.
*/
-uint32 mob_read_db_mode_sub(struct mob_db *entry, struct config_setting_t *t)
+static uint32 mob_read_db_mode_sub(struct mob_db *entry, struct config_setting_t *t)
{
uint32 mode = 0;
struct config_setting_t *t2;
@@ -3838,13 +4494,58 @@ uint32 mob_read_db_mode_sub(struct mob_db *entry, struct config_setting_t *t)
}
/**
+ * Process an entry of mob/mvp drops that contains a random option drop group.
+ *
+ * @param entry : mob db entry being read (used in error messages)
+ * @param item_name : AegisName of the item in this entry (used in error messages)
+ * @param drop : drop data entry
+ * @param drop_rate : used to return the entry drop_rate
+ * @returns a reference to the opt_drop_group to be used when creating this item drop
+ */
+static struct optdrop_group *mob_read_db_drops_option(struct mob_db *entry, const char *item_name, struct config_setting_t *drop, int *drop_rate)
+{
+ nullpo_retr(NULL, entry);
+ nullpo_retr(NULL, item_name);
+ nullpo_retr(NULL, drop);
+ nullpo_retr(NULL, drop_rate);
+
+ // (Drop Rate, "Option Group")
+ if (!config_setting_is_list(drop) || config_setting_length(drop) != 2) {
+ ShowError("mob_read_db_optdrops: Invalid format for option drop group on item \"%s\" in monster %d, skipping.\n", item_name, entry->mob_id);
+ return NULL;
+ }
+
+ int i32;
+ if (mob->get_const(libconfig->setting_get_elem(drop, 0), &i32) && i32 >= 0)
+ *drop_rate = i32;
+
+ const char *group_name = libconfig->setting_get_string_elem(drop, 1);
+ if (group_name == NULL || *group_name == '\0') {
+ ShowError("mob_read_db_optdrops: Missing option drop group name on item \"%s\" in monster %d, skipping.\n", item_name, entry->mob_id);
+ return NULL;
+ }
+
+ int opt_id;
+ if (script->get_constant(group_name, &opt_id) == false) {
+ ShowError("mob_read_db_optdrops: Invalid option drop group \"%s\" on item \"%s\" in monster %d, does this group really exists? Skipping...\n", group_name, item_name, entry->mob_id);
+ return NULL;
+ }
+ if (opt_id < 0 || opt_id >= mob->opt_drop_groups_count) {
+ ShowError("mob_read_db_optdrops: Invalid option drop group \"%s\" index \"%d\" on item \"%s\" in monster %d, does this group really exists? Skipping...\n", group_name, opt_id, item_name, entry->mob_id);
+ return NULL;
+ }
+
+ return &mob->opt_drop_groups[opt_id];
+}
+
+/**
* Processes the MVP drops for a mob_db entry.
*
* @param[in,out] entry The destination mob_db entry, already initialized
* (mob_id is expected to be already set).
* @param[in] t The libconfig entry.
*/
-void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
+static void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
{
struct config_setting_t *drop;
int i = 0;
@@ -3862,9 +4563,18 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
i++;
continue;
}
- if (mob->get_const(drop, &i32) && i32 >= 0) {
- value = i32;
+
+ struct optdrop_group *drop_option = NULL;
+ if (config_setting_is_number(drop)) {
+ // Setting is a number, item doesn't contain options
+ if (mob->get_const(drop, &i32) && i32 >= 0) {
+ value = i32;
+ }
+ } else {
+ // (Drop Rate, "Opt Drop Group")
+ drop_option = mob->read_db_drops_option(entry, name, drop, &value);
}
+
if (value <= 0) {
ShowWarning("mob_read_db: wrong drop chance %d for mvp drop item %s in monster %d\n", value, name, entry->mob_id);
i++;
@@ -3878,6 +4588,7 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
}
mob->item_dropratio_adjust(entry->mvpitem[idx].nameid, entry->mob_id, &rate_adjust);
entry->mvpitem[idx].p = mob->drop_adjust(value, rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max);
+ entry->mvpitem[idx].options = drop_option;
//calculate and store Max available drop chance of the MVP item
if (entry->mvpitem[idx].p) {
@@ -3901,7 +4612,7 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
* (mob_id, status.mode are expected to be already set).
* @param[in] t The libconfig entry.
*/
-void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
+static void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
{
struct config_setting_t *drop;
int i = 0;
@@ -3921,9 +4632,18 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
i++;
continue;
}
- if (mob->get_const(drop, &i32) && i32 >= 0) {
- value = i32;
+
+ struct optdrop_group *drop_option = NULL;
+ if (config_setting_is_number(drop)) {
+ // Setting is a number, item doesn't contain options
+ if (mob->get_const(drop, &i32) && i32 >= 0) {
+ value = i32;
+ }
+ } else {
+ // (Drop Rate, "Opt Drop Group")
+ drop_option = mob->read_db_drops_option(entry, name, drop, &value);
}
+
if (value <= 0) {
ShowWarning("mob_read_db: wrong drop chance %d for drop item %s in monster %d\n", value, name, entry->mob_id);
i++;
@@ -3931,6 +4651,7 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
}
entry->dropitem[idx].nameid = id->nameid;
+ entry->dropitem[idx].options = drop_option;
if (!entry->dropitem[idx].nameid) {
entry->dropitem[idx].p = 0; //No drop.
i++;
@@ -4027,7 +4748,7 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
* (i.e. mob_db2 inheritance), as it will make sure not to free any data still
* in use by the new entry.
*/
-int mob_db_validate_entry(struct mob_db *entry, int n, const char *source)
+static int mob_db_validate_entry(struct mob_db *entry, int n, const char *source)
{
struct mob_data data;
@@ -4130,7 +4851,7 @@ int mob_db_validate_entry(struct mob_db *entry, int n, const char *source)
* validation errors.
* @return Mob ID of the validated entry, or 0 in case of failure.
*/
-int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
+static int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
{
struct mob_db md = { 0 };
struct config_setting_t *t = NULL;
@@ -4192,14 +4913,33 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
* AttackMotion: attack motion
* DamageMotion: damage motion
* MvpExp: mvp experience
+ * DamageTakenRate: damage taken rate
* MvpDrops: {
* AegisName: chance
* ...
* }
* Drops: {
* AegisName: chance
+ * // or
+ * AegisName: (chance, "Option Drop Group")
* ...
* }
+ * DamageTakenRate: damage taken rate
+ * ViewData: {
+ * SpriteId: sprite id
+ * WeaponId: weapon id
+ * ShieldId: shield id
+ * RobeId: garment id
+ * HeadTopId: top headgear id
+ * HeadMidId: middle headgear id
+ * HeadLowId: lower headgear id
+ * HairStyleId: hair style id
+ * BodyStyleId: clothes id
+ * HairColorId: hair color id
+ * BodyColorId: clothes color id
+ * Gender: gender
+ * Options: options
+ * }
*/
if (!libconfig->setting_lookup_int(mobt, "Id", &i32)) {
@@ -4207,7 +4947,7 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
return 0;
}
md.mob_id = i32;
- md.vd.class_ = md.mob_id;
+ md.vd.class = md.mob_id;
if ((t = libconfig->setting_get_member(mobt, "Inherit")) && (inherit = libconfig->setting_get_bool(t))) {
if (!mob->db_data[md.mob_id]) {
@@ -4278,7 +5018,7 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
if (mob->lookup_const(mobt, "AttackRange", &i32) && i32 >= 0) {
md.status.rhw.range = i32;
- } else {
+ } else if (!inherit) {
md.status.rhw.range = 1;
}
@@ -4348,12 +5088,10 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
md.status.def_ele = i32;
md.status.ele_lv = value;
} else if (!inherit) {
- ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id);
md.status.def_ele = ELE_NEUTRAL;
md.status.ele_lv = 1;
}
} else if (!inherit) {
- ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id);
md.status.def_ele = ELE_NEUTRAL;
md.status.ele_lv = 1;
}
@@ -4423,6 +5161,18 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
}
}
+ if (mob->lookup_const(mobt, "DamageTakenRate", &i32) && i32 >= 0) {
+ md.dmg_taken_rate = cap_value(i32, 1, INT_MAX);
+ } else if (!inherit) {
+ md.dmg_taken_rate = 100;
+ }
+
+ if ((t = libconfig->setting_get_member(mobt, "ViewData"))) {
+ if (config_setting_is_group(t)) {
+ mob->read_db_viewdata_sub(&md, t);
+ }
+ }
+
mob->read_db_additional_fields(&md, mobt, n, source);
return mob->db_validate_entry(&md, n, source);
@@ -4439,12 +5189,12 @@ int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source)
* @param[in] source Source of the entry (file name), to be displayed in
* case of validation errors.
*/
-void mob_read_db_additional_fields(struct mob_db *entry, struct config_setting_t *t, int n, const char *source)
+static void mob_read_db_additional_fields(struct mob_db *entry, struct config_setting_t *t, int n, const char *source)
{
// do nothing. plugins can do own work
}
-bool mob_lookup_const(const struct config_setting_t *it, const char *name, int *value)
+static bool mob_lookup_const(const struct config_setting_t *it, const char *name, int *value)
{
if (libconfig->setting_lookup_int(it, name, value))
{
@@ -4462,7 +5212,7 @@ bool mob_lookup_const(const struct config_setting_t *it, const char *name, int *
return false;
}
-bool mob_get_const(const struct config_setting_t *it, int *value)
+static bool mob_get_const(const struct config_setting_t *it, int *value)
{
const char *str = config_setting_get_string(it);
@@ -4477,7 +5227,8 @@ bool mob_get_const(const struct config_setting_t *it, int *value)
/*==========================================
* mob_db.txt reading
*------------------------------------------*/
-void mob_readdb(void) {
+static void mob_readdb(void)
+{
const char* filename[] = {
DBPATH"mob_db.conf",
"mob_db2.conf" };
@@ -4498,7 +5249,7 @@ void mob_readdb(void) {
* @param ignore_missing Whether to ignore errors caused by a missing db file.
* @return the number of found entries.
*/
-int mob_read_libconfig(const char *filename, bool ignore_missing)
+static int mob_read_libconfig(const char *filename, bool ignore_missing)
{
bool duplicate[MAX_MOB_DB] = { 0 };
struct config_t mob_db_conf;
@@ -4508,7 +5259,7 @@ int mob_read_libconfig(const char *filename, bool ignore_missing)
int i = 0, count = 0;
nullpo_ret(filename);
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (ignore_missing && !exists(filepath))
return 0;
@@ -4537,12 +5288,13 @@ int mob_read_libconfig(const char *filename, bool ignore_missing)
}
}
libconfig->destroy(&mob_db_conf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
return count;
}
-void mob_name_constants(void) {
+static void mob_name_constants(void)
+{
int i;
#ifdef ENABLE_CASE_CHECK
script->parser_current_file = "Mob Database (Likely an invalid or conflicting SpriteName)";
@@ -4556,52 +5308,21 @@ void mob_name_constants(void) {
#endif // ENABLE_CASE_CHECK
}
-/*==========================================
- * MOB display graphic change data reading
- *------------------------------------------*/
-bool mob_readdb_mobavail(char* str[], int columns, int current)
+static void mob_mobavail_removal_notice(void)
{
- int class_, k;
-
- nullpo_retr(false, str);
- class_=atoi(str[0]);
-
- if(mob->db(class_) == mob->dummy) {
- // invalid class (probably undefined in db)
- ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", class_);
- return false;
- }
-
- k=atoi(str[1]);
+ char filepath[256];
- memset(&mob->db_data[class_]->vd, 0, sizeof(struct view_data));
- mob->db_data[class_]->vd.class_=k;
+ safesnprintf(filepath, sizeof(filepath), "%s/mob_avail.txt", map->db_path);
- //Player sprites
- if(pc->db_checkid(k) && columns==12) {
- mob->db_data[class_]->vd.sex=atoi(str[2]);
- mob->db_data[class_]->vd.hair_style=atoi(str[3]);
- mob->db_data[class_]->vd.hair_color=atoi(str[4]);
- mob->db_data[class_]->vd.weapon=atoi(str[5]);
- mob->db_data[class_]->vd.shield=atoi(str[6]);
- mob->db_data[class_]->vd.head_top=atoi(str[7]);
- mob->db_data[class_]->vd.head_mid=atoi(str[8]);
- mob->db_data[class_]->vd.head_bottom=atoi(str[9]);
- mob->db_data[class_]->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE);
- mob->db_data[class_]->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris
+ if (exists(filepath)) {
+ ShowError("mob_mobavail_removal_notice: the usage of mob_avail.txt is no longer supported, move your data using tools/mobavailconverter.py and delete the database file to suspend this message.\n");
}
- else if(columns==3)
- mob->db_data[class_]->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris]
- else if( columns != 2 )
- return false;
-
- return true;
}
/*==========================================
* Reading of random monster data
*------------------------------------------*/
-int mob_read_randommonster(void)
+static int mob_read_randommonster(void)
{
char line[1024];
char *str[10],*p;
@@ -4659,7 +5380,7 @@ int mob_read_randommonster(void)
summon[i].qty = 1;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,mobfile[i]);
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s/%s"CL_RESET"'.\n",count, map->db_path, mobfile[i]);
}
return 0;
}
@@ -4668,7 +5389,7 @@ int mob_read_randommonster(void)
* processes one mob_chat_db entry [SnakeDrak]
* @param last_msg_id ensures that only one error message per mob id is printed
*------------------------------------------*/
-bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_msg_id)
+static bool mob_parse_row_chatdb(char **str, const char *source, int line, int *last_msg_id)
{
char* msg;
struct mob_chat *ms;
@@ -4728,13 +5449,14 @@ bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_ms
/*==========================================
* mob_chat_db.txt reading [SnakeDrak]
*-------------------------------------------------------------------------*/
-void mob_readchatdb(void) {
+static void mob_readchatdb(void)
+{
char arc[]="mob_chat_db.txt";
uint32 lines=0, count=0;
char line[1024], filepath[256];
int i, tmp=0;
FILE *fp;
- sprintf(filepath, "%s/%s", map->db_path, arc);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, arc);
fp=fopen(filepath, "r");
if(fp == NULL) {
ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", filepath);
@@ -4775,270 +5497,266 @@ void mob_readchatdb(void) {
count++;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, arc);
+ ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
}
/*==========================================
* processes one mob_skill_db entry
*------------------------------------------*/
-bool mob_parse_row_mobskilldb(char** str, int columns, int current)
+static bool mob_skill_db_libconfig(const char *filename, bool ignore_missing)
{
- static const struct {
- char str[32];
- enum MobSkillState id;
- } state[] = {
- { "any", MSS_ANY }, //All states except Dead
- { "idle", MSS_IDLE },
- { "walk", MSS_WALK },
- { "loot", MSS_LOOT },
- { "dead", MSS_DEAD },
- { "attack", MSS_BERSERK }, //Retaliating attack
- { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs)
- { "chase", MSS_RUSH }, //Chase escaping target
- { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs)
- { "anytarget", MSS_ANYTARGET }, //Berserk+Angry+Rush+Follow
- };
- static const struct {
- char str[32];
- int id;
- } cond1[] = {
- { "always", MSC_ALWAYS },
- { "myhpltmaxrate", MSC_MYHPLTMAXRATE },
- { "myhpinrate", MSC_MYHPINRATE },
- { "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE },
- { "friendhpinrate", MSC_FRIENDHPINRATE },
- { "mystatuson", MSC_MYSTATUSON },
- { "mystatusoff", MSC_MYSTATUSOFF },
- { "friendstatuson", MSC_FRIENDSTATUSON },
- { "friendstatusoff", MSC_FRIENDSTATUSOFF },
- { "attackpcgt", MSC_ATTACKPCGT },
- { "attackpcge", MSC_ATTACKPCGE },
- { "slavelt", MSC_SLAVELT },
- { "slavele", MSC_SLAVELE },
- { "closedattacked", MSC_CLOSEDATTACKED },
- { "longrangeattacked", MSC_LONGRANGEATTACKED },
- { "skillused", MSC_SKILLUSED },
- { "afterskill", MSC_AFTERSKILL },
- { "casttargeted", MSC_CASTTARGETED },
- { "rudeattacked", MSC_RUDEATTACKED },
- { "masterhpltmaxrate", MSC_MASTERHPLTMAXRATE },
- { "masterattacked", MSC_MASTERATTACKED },
- { "alchemist", MSC_ALCHEMIST },
- { "onspawn", MSC_SPAWN },
- }, cond2[] ={
- { "anybad", -1 },
- { "stone", SC_STONE },
- { "freeze", SC_FREEZE },
- { "stun", SC_STUN },
- { "sleep", SC_SLEEP },
- { "poison", SC_POISON },
- { "curse", SC_CURSE },
- { "silence", SC_SILENCE },
- { "confusion", SC_CONFUSION },
- { "blind", SC_BLIND },
- { "hiding", SC_HIDING },
- { "sight", SC_SIGHT },
- }, target[] = {
- { "target", MST_TARGET },
- { "randomtarget", MST_RANDOM },
- { "self", MST_SELF },
- { "friend", MST_FRIEND },
- { "master", MST_MASTER },
- { "around5", MST_AROUND5 },
- { "around6", MST_AROUND6 },
- { "around7", MST_AROUND7 },
- { "around8", MST_AROUND8 },
- { "around1", MST_AROUND1 },
- { "around2", MST_AROUND2 },
- { "around3", MST_AROUND3 },
- { "around4", MST_AROUND4 },
- { "around", MST_AROUND },
- };
- static int last_mob_id = 0; // ensures that only one error message per mob id is printed
+ struct config_t mob_skill_conf;
+ struct config_setting_t *it = NULL, *its = NULL, *mob_skill = NULL;
+ char filepath[256];
+ int i = 0;
- struct mob_skill *ms, gms;
- int mob_id;
- int i =0, j, tmp;
- uint16 sidx = 0;
+ nullpo_retr(false, filename);
- nullpo_retr(false, str);
- mob_id = atoi(str[0]);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
- if (mob_id > 0 && mob->db(mob_id) == mob->dummy)
- {
- if (mob_id != last_mob_id) {
- ShowError("mob_parse_row_mobskilldb: Non existant Mob id %d\n", mob_id);
- last_mob_id = mob_id;
+ if (!exists(filepath)) {
+ if (!ignore_missing) {
+ ShowError("mob_skill_db_libconfig: can't find file %s\n", filepath);
}
+ return 0;
+ }
+
+ if (!libconfig->load_file(&mob_skill_conf, filepath))
+ return false;
+
+ its = libconfig->lookup(&mob_skill_conf, "mob_skill_db");
+
+ if (its != NULL && (mob_skill = libconfig->setting_get_elem(its, 0)) != NULL) {
+ while ((it = libconfig->setting_get_elem(mob_skill, i++))) {
+ mob->skill_db_libconfig_sub(it, i);
+ }
+ }
+
+ libconfig->destroy(&mob_skill_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, filepath);
+ return true;
+}
+
+static bool mob_skill_db_libconfig_sub(struct config_setting_t *it, int n)
+{
+ int i = 0;
+ int mob_id;
+ struct config_setting_t *its;
+ const char *name = config_setting_name(it);
+
+ nullpo_retr(false, it);
+
+ if (!*name) {
+ ShowWarning("mob_skill_db_libconfig_sub: Invalid value for monster name, entry #%d, skipping.\n", n);
+ return false;
+ }
+ if (!script->get_constant(name, &mob_id)) {
+ ShowWarning("mob_skill_db_libconfig_sub: Invalid monster '%s', entry #%d, skipping.\n", name, n);
+ return false;
+ }
+ if (mob_id > 0 && mob->db(mob_id) == mob->dummy) {
+ ShowWarning("mob_skill_db_libconfig_sub: Non existant monster id %d, skipping.\n", mob_id);
+ return false;
+ }
+
+ while ((its = libconfig->setting_get_elem(it, i++))) {
+ mob->skill_db_libconfig_sub_skill(its, i, mob_id);
+ }
+ return true;
+}
+
+/**
+ * Reads a single monster skill from DB.
+ *
+ * @param it The libconfig settings block, which contains the skill data.
+ * @param n The skill data block's index within the parent monster block.
+ * @param mob_id The monster's ID.
+ * @return true on success, false on failure.
+ *
+ **/
+static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, int mob_id)
+{
+ nullpo_retr(false, it);
+ Assert_retr(false, mob_id <= 0 || mob->db(mob_id) != mob->dummy);
+
+ int skill_id = 0;
+ const char *name = config_setting_name(it);
+ const char *mob_str = (mob_id < 0) ? "global ID" : "monster";
+
+ if ((skill_id = skill->name2id(name)) == 0) {
+ ShowWarning("%s: Non existant skill %d in %s %d, skipping.\n", __func__, skill_id, mob_str, mob_id);
return false;
}
- if( strcmp(str[1],"clear")==0 ){
- if (mob_id < 0)
+
+ const char *skill_name = skill->get_name(skill_id);
+ bool clearskills = false;
+
+ // If ClearSkills flag is enabled clear all the previous skills.
+ if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) == CONFIG_TRUE && clearskills) {
+ if (mob_id < 0) {
+ ShowError("%s: Global skill clearing is not supported, skipping. (Global ID %d, skill %d (%s).)\n",
+ __func__, mob_id, skill_id, skill_name);
return false;
- memset(mob->db_data[mob_id]->skill,0,sizeof(struct mob_skill) * MAX_MOBSKILL);
- mob->db_data[mob_id]->maxskill=0;
+ }
+
+ memset(mob->db_data[mob_id]->skill, 0, sizeof(struct mob_skill) * MAX_MOBSKILL);
+ mob->db_data[mob_id]->maxskill = 0;
return true;
}
- if (mob_id < 0) {
- //Prepare global skill. [Skotlex]
+ struct mob_skill *ms;
+
+ if (mob_id < 0) { // Prepare global skill. [Skotlex]
+ struct mob_skill gms;
memset(&gms, 0, sizeof (struct mob_skill));
ms = &gms;
} else {
- ARR_FIND( 0, MAX_MOBSKILL, i, (ms = &mob->db_data[mob_id]->skill[i])->skill_id == 0 );
- if( i == MAX_MOBSKILL )
- {
- if (mob_id != last_mob_id) {
- ShowError("mob_parse_row_mobskilldb: Too many skills for monster %d[%s]\n", mob_id, mob->db_data[mob_id]->sprite);
- last_mob_id = mob_id;
- }
+ int idx = 0;
+
+ ARR_FIND(0, MAX_MOBSKILL, idx, (ms = &mob->db_data[mob_id]->skill[idx])->skill_id == 0);
+
+ if (idx == MAX_MOBSKILL) {
+ ShowError("%s: Too many skills for monster %d, skipping.\n", __func__, mob_id);
return false;
}
- }
- //State
- ARR_FIND( 0, ARRAYLENGTH(state), j, strcmp(str[2],state[j].str) == 0 );
- if( j < ARRAYLENGTH(state) )
- ms->state = state[j].id;
- else {
- ShowWarning("mob_parse_row_mobskilldb: Unrecognized state %s\n", str[2]);
- ms->state = MSS_ANY;
+ mob->db_data[mob_id]->maxskill = idx + 1;
}
- //Skill ID
- j=atoi(str[3]);
- if ( !(sidx = skill->get_index(j) ) ) {
- if (mob_id < 0)
- ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j);
- else
- ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob->db_data[mob_id]->sprite);
- return false;
+ ms->skill_id = skill_id;
+
+ int i32 = MSS_ANY;
+ if (mob->lookup_const(it, "SkillState", &i32) && (i32 < MSS_ANY || i32 > MSS_ANYTARGET)) {
+ ShowWarning("%s: Invalid skill state %d for skill %d (%s) in %s %d, defaulting to MSS_ANY.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ i32 = MSS_ANY;
}
- ms->skill_id=j;
+ ms->state = i32;
+
+ int res = libconfig->setting_lookup_int(it, "SkillLevel", &i32);
+ ms->skill_lv = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, battle_config.mob_max_skilllvl);
- //Skill lvl
- j= atoi(str[4])<=0 ? 1 : atoi(str[4]);
- ms->skill_lv= j>battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : j; //we strip max skill level
+ res = libconfig->setting_lookup_int(it, "Rate", &i32);
+ ms->permillage = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, 10000);
- //Apply battle_config modifiers to rate (permillage) and delay [Skotlex]
- tmp = atoi(str[5]);
+ // Apply battle_config modifier to rate (permillage).
if (battle_config.mob_skill_rate != 100)
- tmp = tmp*battle_config.mob_skill_rate/100;
- if (tmp > 10000)
- ms->permillage= 10000;
- else if (!tmp && battle_config.mob_skill_rate)
- ms->permillage= 1;
- else
- ms->permillage= tmp;
- ms->casttime=atoi(str[6]);
- ms->delay=atoi(str[7]);
+ ms->permillage = ms->permillage * battle_config.mob_skill_rate / 100;
+
+ if (ms->permillage > 10000)
+ ms->permillage = 10000;
+ else if (ms->permillage == 0 && battle_config.mob_skill_rate != 0)
+ ms->permillage = 1;
+
+ res = libconfig->setting_lookup_int(it, "CastTime", &i32);
+ ms->casttime = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_CASTTIME);
+
+ res = libconfig->setting_lookup_int(it, "Delay", &i32);
+ ms->delay = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_DELAY);
+
+ // Apply battle_config modifier to delay.
if (battle_config.mob_skill_delay != 100)
- ms->delay = ms->delay*battle_config.mob_skill_delay/100;
- if (ms->delay < 0 || ms->delay > MOB_MAX_DELAY) //time overflow?
- ms->delay = MOB_MAX_DELAY;
- ms->cancel=atoi(str[8]);
- if( strcmp(str[8],"yes")==0 ) ms->cancel=1;
-
- //Target
- ARR_FIND( 0, ARRAYLENGTH(target), j, strcmp(str[9],target[j].str) == 0 );
- if( j < ARRAYLENGTH(target) )
- ms->target = target[j].id;
- else {
- ShowWarning("mob_parse_row_mobskilldb: Unrecognized target %s for %d\n", str[9], mob_id);
- ms->target = MST_TARGET;
+ ms->delay = ms->delay * battle_config.mob_skill_delay / 100;
+
+ ms->delay = min(ms->delay, MOB_MAX_DELAY);
+
+ res = libconfig->setting_lookup_bool(it, "Cancelable", &i32);
+ ms->cancel = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, 1);
+
+ i32 = MST_TARGET;
+ if (mob->lookup_const(it, "SkillTarget", &i32) && (i32 < MST_TARGET || i32 > MST_AROUND)) {
+ ShowWarning("%s: Invalid skill target %d for skill %d (%s) in %s %d, defaulting to MST_TARGET.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ i32 = MST_TARGET;
}
+ ms->target = i32;
- //Check that the target condition is right for the skill type. [Skotlex]
- if ( skill->get_casttype2(sidx) == CAST_GROUND) {//Ground skill.
- if (ms->target > MST_AROUND) {
- ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->dbs->db[sidx].name,
- mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite);
- ms->target = MST_TARGET;
- }
- } else if (ms->target > MST_MASTER) {
- ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->dbs->db[sidx].name,
- mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite);
+ // Check the target condition for non-ground skills. (Ground skills can use every target.)
+ if (skill->get_casttype2(skill->get_index(skill_id)) != CAST_GROUND && ms->target > MST_MASTER) {
+ ShowWarning("%s: Wrong skill target %d for non-ground skill %d (%s) in %s %d, defaulting to MST_TARGET.\n",
+ __func__, ms->target, skill_id, skill_name, mob_str, mob_id);
ms->target = MST_TARGET;
}
- //Cond1
- ARR_FIND( 0, ARRAYLENGTH(cond1), j, strcmp(str[10],cond1[j].str) == 0 );
- if( j < ARRAYLENGTH(cond1) )
- ms->cond1 = cond1[j].id;
- else {
- ShowWarning("mob_parse_row_mobskilldb: Unrecognized condition 1 %s for %d\n", str[10], mob_id);
- ms->cond1 = -1;
+ i32 = MSC_ALWAYS;
+ if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_SPAWN)) {
+ ShowWarning("%s: Invalid skill condition %d for skill id %d (%s) in %s %d, defaulting to MSC_ALWAYS.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ i32 = MSC_ALWAYS;
}
+ ms->cond1 = i32;
+
+ ms->cond2 = !mob->lookup_const(it, "ConditionData", &i32) ? 0 : cap_value(i32, SHRT_MIN, SHRT_MAX);
- //Cond2
- // numeric value
- ms->cond2 = atoi(str[11]);
- // or special constant
- ARR_FIND( 0, ARRAYLENGTH(cond2), j, strcmp(str[11],cond2[j].str) == 0 );
- if( j < ARRAYLENGTH(cond2) )
- ms->cond2 = cond2[j].id;
+ for (int i = 0; i < 5; i++) {
+ char valname[16];
+ sprintf(valname, "val%1d", i);
- ms->val[0]=(int)strtol(str[12],NULL,0);
- ms->val[1]=(int)strtol(str[13],NULL,0);
- ms->val[2]=(int)strtol(str[14],NULL,0);
- ms->val[3]=(int)strtol(str[15],NULL,0);
- ms->val[4]=(int)strtol(str[16],NULL,0);
+ if (libconfig->setting_lookup_int(it, valname, &i32) == CONFIG_TRUE)
+ ms->val[i] = i32;
+ }
if (ms->skill_id == NPC_EMOTION) {
ms->val[1] &= MD_MASK;
ms->val[2] &= MD_MASK;
ms->val[3] &= MD_MASK;
+
+ if (mob_id > 0 && (uint32)ms->val[1] == mob->db(mob_id)->status.mode) {
+ ms->val[1] = MD_NONE;
+ ms->val[4] = 1; // Request to return mode to normal.
+ }
}
- if (ms->skill_id == NPC_EMOTION && mob_id > 0
- && (uint32)ms->val[1] == mob->db(mob_id)->status.mode) {
- ms->val[1] = MD_NONE;
- ms->val[4] = 1; //request to return mode to normal.
- }
- if (ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1] != MD_NONE) {
- //Adds a mode to the mob.
- //Remove aggressive mode when the new mob type is passive.
- if (!(ms->val[1]&MD_AGGRESSIVE))
+
+ if (ms->skill_id == NPC_EMOTION_ON && mob_id > 0 && ms->val[1] != MD_NONE) {
+ // Add a mode to the mob and remove aggressive mode if the new mode is passive.
+ if ((ms->val[1] & MD_AGGRESSIVE) == 0)
ms->val[3] |= MD_AGGRESSIVE;
- ms->val[2] |= (uint32)ms->val[1]; //Add the new mode.
- ms->val[1] = MD_NONE; //Do not "set" it.
+
+ ms->val[2] |= (uint32)ms->val[1]; // Add the new mode.
+ ms->val[1] = MD_NONE; // Do not "set" it.
}
- if(*str[17])
- ms->emotion=atoi(str[17]);
- else
- ms->emotion=-1;
+ res = libconfig->setting_lookup_int(it, "Emotion", &i32);
+ ms->emotion = (res == CONFIG_FALSE) ? -1 : cap_value(i32, -1, SHRT_MAX);
- if(str[18]!=NULL && mob->chat_db[atoi(str[18])]!=NULL)
- ms->msg_id=atoi(str[18]);
- else
- ms->msg_id=0;
+ if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) == CONFIG_TRUE) {
+ if (i32 <= 0 || i32 > MAX_MOB_CHAT || mob->chat_db[i32] == NULL) {
+ ShowWarning("%s: Invalid message ID %d for skill %d (%s) in %s %d, ignoring.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ } else {
+ ms->msg_id = i32;
+ }
+ }
- if (mob_id < 0) {
- //Set this skill to ALL mobs. [Skotlex]
- mob_id *= -1;
- for (i = 1; i < MAX_MOB_DB; i++)
- {
+ if (mob_id < 0) { // Global skill assignment.
+ mob_id = -mob_id;
+
+ for (int i = 1; i < MAX_MOB_DB; i++) {
if (mob->db_data[i] == NULL)
continue;
- if (mob->db_data[i]->status.mode&MD_BOSS)
- {
- if (!(mob_id&2)) //Skill not for bosses
+
+ if ((mob->db_data[i]->status.mode & MD_BOSS) != 0) {
+ if ((mob_id & 2) == 0) // Skill not for boss monsters.
continue;
- } else
- if (!(mob_id&1)) //Skill not for normal enemies.
+ } else {
+ if ((mob_id & 1) == 0) // Skill not for normal monsters.
continue;
+ }
+
+ int idx;
- ARR_FIND( 0, MAX_MOBSKILL, j, mob->db_data[i]->skill[j].skill_id == 0 );
- if(j==MAX_MOBSKILL)
+ ARR_FIND(0, MAX_MOBSKILL, idx, mob->db_data[i]->skill[idx].skill_id == 0);
+
+ if (idx == MAX_MOBSKILL) {
+ ShowError("%s: Too many skills for monster %d in global ID %d, skipping.\n",
+ __func__, i, -mob_id);
continue;
+ }
- memcpy (&mob->db_data[i]->skill[j], ms, sizeof(struct mob_skill));
- mob->db_data[i]->maxskill=j+1;
+ memcpy(&mob->db_data[i]->skill[idx], ms, sizeof(struct mob_skill));
+ mob->db_data[i]->maxskill = idx + 1;
}
- } else //Skill set on a single mob.
- mob->db_data[mob_id]->maxskill=i+1;
+ }
return true;
}
@@ -5046,34 +5764,29 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
/*==========================================
* mob_skill_db.txt reading
*------------------------------------------*/
-void mob_readskilldb(void) {
- const char* filename[] = {
- DBPATH"mob_skill_db.txt",
- "mob_skill_db2.txt" };
- int fi;
+static void mob_readskilldb(void)
+{
+
+ const char *filename[] = {
+ DBPATH"mob_skill_db.conf",
+ "mob_skill_db2.conf"
+ };
+ int i;
- if( battle_config.mob_skill_rate == 0 ) {
+ if (battle_config.mob_skill_rate == 0) {
ShowStatus("Mob skill use disabled. Not reading mob skills.\n");
return;
}
- for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
- if(fi > 0) {
- char filepath[256];
- sprintf(filepath, "%s/%s", map->db_path, filename[fi]);
- if(!exists(filepath)) {
- continue;
- }
- }
-
- sv->readdb(map->db_path, filename[fi], ',', 19, 19, -1, mob->parse_row_mobskilldb);
+ for (i = 0; i < ARRAYLENGTH(filename); ++i) {
+ mob->skill_db_libconfig(filename[i], i > 0 ? true : false);
}
}
/*==========================================
* mob_race2_db.txt reading
*------------------------------------------*/
-bool mob_readdb_race2(char* fields[], int columns, int current)
+static bool mob_readdb_race2(char *fields[], int columns, int current)
{
int race, i;
@@ -5099,9 +5812,10 @@ bool mob_readdb_race2(char* fields[], int columns, int current)
/**
* Read mob_item_ratio.txt
*/
-bool mob_readdb_itemratio(char* str[], int columns, int current)
+static bool mob_readdb_itemratio(char *str[], int columns, int current)
{
int nameid, ratio, i;
+ struct item_drop_ratio *dropRatio;
nullpo_retr(false, str);
nameid = atoi(str[0]);
@@ -5114,12 +5828,15 @@ bool mob_readdb_itemratio(char* str[], int columns, int current)
ratio = atoi(str[1]);
- if(item_drop_ratio_db[nameid] == NULL)
- item_drop_ratio_db[nameid] = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio));
+ dropRatio = mob->get_item_drop_ratio(nameid);
+ if (dropRatio == NULL) {
+ dropRatio = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio));
+ mob->set_item_drop_ratio(nameid, dropRatio);
+ }
- item_drop_ratio_db[nameid]->drop_ratio = ratio;
- for(i = 0; i < columns-2; i++)
- item_drop_ratio_db[nameid]->mob_id[i] = atoi(str[i+2]);
+ dropRatio->drop_ratio = ratio;
+ for (i = 0; i < columns - 2; i++)
+ dropRatio->mob_id[i] = atoi(str[i + 2]);
return true;
}
@@ -5127,22 +5844,62 @@ bool mob_readdb_itemratio(char* str[], int columns, int current)
/**
* read all mob-related databases
*/
-void mob_load(bool minimal) {
+static void mob_load(bool minimal)
+{
if (minimal) {
- // Only read the mob db in minimal mode
+ // Only read the mob db and option drops in minimal mode
+ mob->read_optdrops_db();
mob->readdb();
return;
}
sv->readdb(map->db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, mob->readdb_itemratio); // must be read before mobdb
+ mob->read_optdrops_db();
mob->readchatdb();
mob->readdb();
mob->readskilldb();
- sv->readdb(map->db_path, "mob_avail.txt", ',', 2, 12, -1, mob->readdb_mobavail);
+ mob->mobavail_removal_notice();
mob->read_randommonster();
sv->readdb(map->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, mob->readdb_race2);
}
-void mob_reload(void) {
+/**
+ * @see DBApply
+ */
+static int mob_final_ratio_sub(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct item_drop_ratio *ratio = DB->data2ptr(data);
+
+ if (ratio)
+ aFree(ratio);
+
+ return 0;
+}
+
+static int mob_reload_sub_mob(struct mob_data *md, va_list args)
+{
+ nullpo_ret(md);
+ md->db = mob_db(md->class_);
+
+ status_calc_mob(md, SCO_FIRST);
+
+ // If the view data was not overwritten manually
+ if (md->vd != NULL) {
+ // Get the new view data from the mob database
+ md->vd = mob_get_viewdata(md->class_);
+
+ // If they are spawned right now
+ if (md->bl.prev != NULL) {
+ // Respawn all mobs on client side so that they are displayed correctly(if their view id changed)
+ clif->clearunit_area(&md->bl, CLR_OUTSIGHT);
+ clif->spawn(&md->bl);
+ }
+ }
+
+ return 0;
+}
+
+static void mob_reload(void)
+{
int i;
//Mob skills need to be cleared before re-reading them. [Skotlex]
@@ -5159,14 +5916,18 @@ void mob_reload(void) {
item_drop_ratio_db[i] = NULL;
}
}
+ mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub);
+
+ mob->destroy_drop_groups();
mob->load(false);
+ map->foreachmob(mob->reload_sub_mob);
}
/**
* Clears spawn related information for a script reload.
*/
-void mob_clear_spawninfo(void)
+static void mob_clear_spawninfo(void)
{
int i;
for (i = 0; i < MAX_MOB_DB; i++)
@@ -5177,7 +5938,8 @@ void mob_clear_spawninfo(void)
/*==========================================
* Circumference initialization of mob
*------------------------------------------*/
-int do_init_mob(bool minimal) {
+static int do_init_mob(bool minimal)
+{
// Initialize the mob database
memset(mob->db_data,0,sizeof(mob->db_data)); //Clear the array
mob->db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
@@ -5197,13 +5959,14 @@ int do_init_mob(bool minimal) {
timer->add_func_list(mob->timer_delete,"mob_timer_delete");
timer->add_func_list(mob->spawn_guardian_sub,"mob_spawn_guardian_sub");
timer->add_func_list(mob->respawn,"mob_respawn");
+ timer->add_func_list(mob->mvptomb_delayspawn, "mvptomb_delayspawn");
timer->add_interval(timer->gettick()+MIN_MOBTHINKTIME,mob->ai_hard,0,0,MIN_MOBTHINKTIME);
timer->add_interval(timer->gettick()+MIN_MOBTHINKTIME*10,mob->ai_lazy,0,0,MIN_MOBTHINKTIME*10);
return 0;
}
-void mob_destroy_mob_db(int index)
+static void mob_destroy_mob_db(int index)
{
struct mob_db *data;
Assert_retv(index >= 0 && index <= MAX_MOB_DB);
@@ -5213,10 +5976,26 @@ void mob_destroy_mob_db(int index)
mob->db_data[index] = NULL;
}
+/**
+ * Unloads option drop group database
+ */
+static void mob_destroy_drop_groups(void)
+{
+ for (int i = 0; i < mob->opt_drop_groups_count; i++) {
+ struct optdrop_group *group = &mob->opt_drop_groups[i];
+
+ for (int j = 0; j < group->optslot_count; j++) {
+ aFree(group->optslot[j].options);
+ }
+ }
+
+ aFree(mob->opt_drop_groups);
+}
+
/*==========================================
* Clean memory usage.
*------------------------------------------*/
-int do_final_mob(void)
+static int do_final_mob(void)
{
int i;
if (mob->dummy)
@@ -5231,6 +6010,7 @@ int do_final_mob(void)
mob->destroy_mob_db(i);
}
}
+ mob->destroy_drop_groups();
for (i = 0; i <= MAX_MOB_CHAT; i++)
{
if (mob->chat_db[i] != NULL)
@@ -5247,12 +6027,15 @@ int do_final_mob(void)
item_drop_ratio_db[i] = NULL;
}
}
+ mob->item_drop_ratio_other_db->clear(mob->item_drop_ratio_other_db, mob->final_ratio_sub);
+ db_destroy(mob->item_drop_ratio_other_db);
ers_destroy(item_drop_ers);
ers_destroy(item_drop_list_ers);
return 0;
}
-void mob_defaults(void) {
+void mob_defaults(void)
+{
// Defines the Manuk/Splendide/Mora mob groups for the status reductions [Epoque & Frost]
const int mob_manuk[8] = {
MOBID_TATACHO,
@@ -5289,8 +6072,13 @@ void mob_defaults(void) {
memcpy(mob->splendide, mob_splendide, sizeof(mob->splendide));
memcpy(mob->mora, mob_mora, sizeof(mob->mora));
+ item_drop_ratio_other_db = idb_alloc(DB_OPT_BASE);
+ mob->item_drop_ratio_db = item_drop_ratio_db;
+ mob->item_drop_ratio_other_db = item_drop_ratio_other_db;
+
/* */
mob->reload = mob_reload;
+ mob->reload_sub_mob = mob_reload_sub_mob;
mob->init = do_init_mob;
mob->final = do_final_mob;
/* */
@@ -5303,6 +6091,8 @@ void mob_defaults(void) {
mob->db_searchname_array_sub = mobdb_searchname_array_sub;
mob->mvptomb_create = mvptomb_create;
mob->mvptomb_destroy = mvptomb_destroy;
+ mob->mvptomb_spawn_delayed = mvptomb_spawn_delayed;
+ mob->mvptomb_delayspawn = mvptomb_delayspawn;
mob->db_searchname_array = mobdb_searchname_array;
mob->db_checkid = mobdb_checkid;
mob->get_viewdata = mob_get_viewdata;
@@ -5328,6 +6118,7 @@ void mob_defaults(void) {
mob->ai_sub_hard_bg_ally = mob_ai_sub_hard_bg_ally;
mob->ai_sub_hard_lootsearch = mob_ai_sub_hard_lootsearch;
mob->warpchase_sub = mob_warpchase_sub;
+ mob->is_in_battle_state = mob_is_in_battle_state;
mob->ai_sub_hard_slavemob = mob_ai_sub_hard_slavemob;
mob->unlocktarget = mob_unlocktarget;
mob->randomwalk = mob_randomwalk;
@@ -5338,6 +6129,7 @@ void mob_defaults(void) {
mob->ai_sub_lazy = mob_ai_sub_lazy;
mob->ai_lazy = mob_ai_lazy;
mob->ai_hard = mob_ai_hard;
+ mob->setdropitem_options = mob_setdropitem_options;
mob->setdropitem = mob_setdropitem;
mob->setlootitem = mob_setlootitem;
mob->delay_item_drop = mob_delay_item_drop;
@@ -5364,13 +6156,17 @@ void mob_defaults(void) {
mob->getmasterhpltmaxrate = mob_getmasterhpltmaxrate;
mob->getfriendstatus_sub = mob_getfriendstatus_sub;
mob->getfriendstatus = mob_getfriendstatus;
- mob->skill_use = mobskill_use;
+ mob->skill_use = mob_skill_use;
mob->skill_event = mobskill_event;
mob->is_clone = mob_is_clone;
mob->clone_spawn = mob_clone_spawn;
mob->clone_delete = mob_clone_delete;
mob->drop_adjust = mob_drop_adjust;
mob->item_dropratio_adjust = item_dropratio_adjust;
+ mob->read_optdrops_option = mob_read_optdrops_option;
+ mob->read_optdrops_optslot = mob_read_optdrops_optslot;
+ mob->read_optdrops_group = mob_read_optdrops_group;
+ mob->read_optdrops_db = mob_read_optdrops_db;
mob->lookup_const = mob_lookup_const;
mob->get_const = mob_get_const;
mob->db_validate_entry = mob_db_validate_entry;
@@ -5381,17 +6177,25 @@ void mob_defaults(void) {
mob->read_db_drops_sub = mob_read_db_drops_sub;
mob->read_db_mvpdrops_sub = mob_read_db_mvpdrops_sub;
mob->read_db_mode_sub = mob_read_db_mode_sub;
+ mob->read_db_drops_option = mob_read_db_drops_option;
mob->read_db_stats_sub = mob_read_db_stats_sub;
+ mob->read_db_viewdata_sub = mob_read_db_viewdata_sub;
mob->name_constants = mob_name_constants;
- mob->readdb_mobavail = mob_readdb_mobavail;
+ mob->mobavail_removal_notice = mob_mobavail_removal_notice;
mob->read_randommonster = mob_read_randommonster;
mob->parse_row_chatdb = mob_parse_row_chatdb;
mob->readchatdb = mob_readchatdb;
- mob->parse_row_mobskilldb = mob_parse_row_mobskilldb;
mob->readskilldb = mob_readskilldb;
mob->readdb_race2 = mob_readdb_race2;
mob->readdb_itemratio = mob_readdb_itemratio;
mob->load = mob_load;
+ mob->get_item_drop_ratio = mob_get_item_drop_ratio;
+ mob->set_item_drop_ratio = mob_set_item_drop_ratio;
+ mob->final_ratio_sub = mob_final_ratio_sub;
mob->clear_spawninfo = mob_clear_spawninfo;
mob->destroy_mob_db = mob_destroy_mob_db;
+ mob->destroy_drop_groups = mob_destroy_drop_groups;
+ mob->skill_db_libconfig = mob_skill_db_libconfig;
+ mob->skill_db_libconfig_sub = mob_skill_db_libconfig_sub;
+ mob->skill_db_libconfig_sub_skill = mob_skill_db_libconfig_sub_skill;
}
diff --git a/src/map/mob.h b/src/map/mob.h
index 60bc4b869..6ad1ce705 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include "map/status.h" // struct status_data, struct status_change
#include "map/unit.h" // struct unit_data, view_data
#include "common/hercules.h"
+#include "common/db.h"
#include "common/mmo.h" // struct item
struct hplugin_data_store;
@@ -34,12 +35,11 @@ struct hplugin_data_store;
// 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 5000
+#define MAX_MOB_DB 22000
//The number of drops all mobs have and the max drop-slot that the steal skill will attempt to steal from.
#define MAX_MOB_DROP 10
#define MAX_MVP_DROP 3
-#define MAX_STEAL_DROP 7
//Min time between AI executions
#define MIN_MOBTHINKTIME 100
@@ -60,6 +60,9 @@ struct hplugin_data_store;
#define MAX_MOB_CHAT 250 //Max Skill's messages
+#define DEFAULT_MOB_NAME "--en--"
+#define DEFAULT_MOB_JNAME "--ja--"
+
// On official servers, monsters will only seek targets that are closer to walk to than their
// search range. The search range is affected depending on if the monster is walking or not.
// On some maps there can be a quite long path for just walking two cells in a direction and
@@ -69,6 +72,14 @@ struct hplugin_data_store;
// Disable this to make monsters not do any path search when looking for a target (old behavior).
#define ACTIVEPATHSEARCH
+struct item_drop_ratio;
+
+enum e_bosstype {
+ BTYPE_NONE = 0,
+ BTYPE_BOSS = 1,
+ BTYPE_MVP = 2,
+};
+
//Mob skill states.
enum MobSkillState {
MSS_ANY = -1,
@@ -140,6 +151,45 @@ struct spawn_info {
unsigned short qty;
};
+/**
+ * Information of one possible option that will fill
+ * an option slot (see optdrop_group_optslot)
+ */
+struct optdrop_group_option {
+ int id; //< Option ID
+ int min; //< Minimun value when this option drops
+ int max; //< Maximun value when this option drops
+ int rate; //< Chance of dropping this option
+};
+
+/**
+ * Information of possible options that will fill
+ * one option slot
+ */
+struct optdrop_group_optslot {
+ int option_count; //< Number of options in *options
+ struct optdrop_group_option *options; //< Array of possible options
+};
+
+/**
+ * A group of options to be random picked when
+ * dropping an item
+ */
+struct optdrop_group {
+ int optslot_count; //< How many option slots are configured by this group
+ int optslot_rate[MAX_ITEM_OPTIONS]; //< The rate to fill each of the configured slots
+ struct optdrop_group_optslot optslot[MAX_ITEM_OPTIONS]; //< Details of the options that will go in each slot
+};
+
+/**
+ * Stores data related to a monster drop (normal or mvp drop)
+ */
+struct mob_drop {
+ int nameid; //< Item ID
+ int p; //< Drop chance
+ struct optdrop_group *options; //< Option Drop Group associated with this drop (NULL if none)
+};
+
struct mob_db {
int mob_id;
char sprite[NAME_LENGTH],name[NAME_LENGTH],jname[NAME_LENGTH];
@@ -148,13 +198,14 @@ struct mob_db {
short range2,range3;
short race2; // celest
unsigned short lv;
- struct { int nameid,p; } dropitem[MAX_MOB_DROP];
- struct { int nameid,p; } mvpitem[MAX_MVP_DROP];
+ struct mob_drop dropitem[MAX_MOB_DROP];
+ struct mob_drop mvpitem[MAX_MVP_DROP];
struct status_data status;
struct view_data vd;
unsigned int option;
int summonper[MAX_RANDOMMONSTER];
int maxskill;
+ int dmg_taken_rate;
struct mob_skill skill[MAX_MOBSKILL];
struct spawn_info spawn[10];
struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
@@ -181,10 +232,10 @@ struct mob_data {
unsigned int spotted: 1;
unsigned int npc_killmonster: 1; //for new killmonster behavior
unsigned int rebirth: 1; // NPC_Rebirth used
- unsigned int boss : 1;
enum MobSkillState skillstate;
unsigned char steal_flag; //number of steal tries (to prevent steal exploit on mobs with few items) [Lupus]
unsigned char attacked_count; //For rude attacked.
+ uint8 boss;
int provoke_flag; // Celest
} state;
struct guardian_data* guardian_data;
@@ -193,15 +244,18 @@ struct mob_data {
unsigned int dmg;
unsigned int flag : 2; //0: Normal. 1: Homunc exp. 2: Pet exp
} dmglog[DAMAGELOG_SIZE];
+ int dmg_taken_rate;
struct spawn_data *spawn; //Spawn data.
int spawn_timer; //Required for Convex Mirror
struct item *lootitem;
- short class_;
+ int class_;
unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex]
int level;
int target_id,attacked_id;
int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
unsigned int bg_id; // BattleGround System
+ int clan_id; // Clan System
+ int npc_id; // NPC ID if spawned with monster/areamonster/guardian/bg_monster/atcommand("@monster xy") (Used to kill mob on NPC unload.)
int64 next_walktime, last_thinktime, last_linktime, last_pcneartime, dmgtick;
short move_fail_count;
@@ -269,6 +323,13 @@ enum {
MSC_SPAWN,
};
+/** Special monster(-name) constants used to assign skills to a group of monsters. **/
+enum mob_group {
+ ALL_MOBS_NONBOSS = -1,
+ ALL_MOBS_BOSS = -2,
+ ALL_MOBS = -3,
+};
+
/**
* Mob IDs
*/
@@ -400,6 +461,7 @@ enum mob_id {
// The data structures for storing delayed item drops
struct item_drop {
struct item item_data;
+ bool showdropeffect;
struct item_drop* next;
};
struct item_drop_list {
@@ -422,14 +484,20 @@ struct mob_interface {
struct mob_db *dummy; //Dummy mob to be returned when a non-existant one is requested.
// Dynamic mob chat database
struct mob_chat *chat_db[MAX_MOB_CHAT + 1];
+ // Random Option Drop groups
+ struct optdrop_group *opt_drop_groups;
+ int opt_drop_groups_count;
// Defines the Manuk/Splendide/Mora mob groups for the status reductions [Epoque & Frost]
int manuk[8];
int splendide[5];
int mora[5];
+ struct item_drop_ratio **item_drop_ratio_db;
+ struct DBMap *item_drop_ratio_other_db;
/* */
int (*init) (bool mimimal);
int (*final) (void);
void (*reload) (void);
+ int (*reload_sub_mob) (struct mob_data *md, va_list args);
/* */
struct mob_db* (*db) (int index);
struct mob_chat* (*chat) (short id);
@@ -439,20 +507,22 @@ struct mob_interface {
int (*db_searchname) (const char *str);
int (*db_searchname_array_sub) (struct mob_db *monster, const char *str, int flag);
// MvP Tomb System
+ void (*mvptomb_spawn_delayed) (struct npc_data *nd);
+ int (*mvptomb_delayspawn) (int tid, int64 tick, int id, intptr_t data);
void (*mvptomb_create) (struct mob_data *md, char *killer, time_t time);
void (*mvptomb_destroy) (struct mob_data *md);
int (*db_searchname_array) (struct mob_db **data, int size, const char *str, int flag);
int (*db_checkid) (const int id);
struct view_data* (*get_viewdata) (int class_);
int (*parse_dataset) (struct spawn_data *data);
- struct mob_data* (*spawn_dataset) (struct spawn_data *data);
+ struct mob_data* (*spawn_dataset) (struct spawn_data *data, int npc_id);
int (*get_random_id) (int type, int flag, int lv);
bool (*ksprotected) (struct block_list *src, struct block_list *target);
- struct mob_data* (*once_spawn_sub) (struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai);
+ struct mob_data* (*once_spawn_sub) (struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai, int npc_id);
int (*once_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai);
int (*once_spawn_area) (struct map_session_data *sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai);
- int (*spawn_guardian) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index);
- int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id);
+ int (*spawn_guardian) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index, int npc_id);
+ int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id, int npc_id);
int (*can_reach) (struct mob_data *md, struct block_list *bl, int range, int state);
int (*linksearch) (struct block_list *bl, va_list ap);
int (*delayspawn) (int tid, int64 tick, int id, intptr_t data);
@@ -466,6 +536,7 @@ struct mob_interface {
int (*ai_sub_hard_bg_ally) (struct block_list *bl, va_list ap);
int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap);
int (*warpchase_sub) (struct block_list *bl, va_list ap);
+ bool (*is_in_battle_state) (const struct mob_data *md);
int (*ai_sub_hard_slavemob) (struct mob_data *md, int64 tick);
int (*unlocktarget) (struct mob_data *md, int64 tick);
int (*randomwalk) (struct mob_data *md, int64 tick);
@@ -476,7 +547,8 @@ struct mob_interface {
int (*ai_sub_lazy) (struct mob_data *md, va_list args);
int (*ai_lazy) (int tid, int64 tick, int id, intptr_t data);
int (*ai_hard) (int tid, int64 tick, int id, intptr_t data);
- struct item_drop* (*setdropitem) (int nameid, int qty, struct item_data *data);
+ void (*setdropitem_options) (struct item *item, struct optdrop_group *options);
+ struct item_drop* (*setdropitem) (int nameid, struct optdrop_group *options, int qty, struct item_data *data);
struct item_drop* (*setlootitem) (struct item *item);
int (*delay_item_drop) (int tid, int64 tick, int id, intptr_t data);
void (*item_drop) (struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag);
@@ -501,7 +573,7 @@ struct mob_interface {
struct block_list* (*getfriendhprate) (struct mob_data *md, int min_rate, int max_rate);
struct block_list* (*getmasterhpltmaxrate) (struct mob_data *md, int rate);
int (*getfriendstatus_sub) (struct block_list *bl, va_list ap);
- struct mob_data* (*getfriendstatus) (struct mob_data *md, int cond1, int cond2);
+ struct block_list *(*getfriendstatus) (struct mob_data *md, int cond1, int cond2);
int (*skill_use) (struct mob_data *md, int64 tick, int event);
int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag);
int (*is_clone) (int class_);
@@ -509,6 +581,10 @@ struct mob_interface {
int (*clone_delete) (struct mob_data *md);
unsigned int (*drop_adjust) (int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max);
void (*item_dropratio_adjust) (int nameid, int mob_id, int *rate_adjust);
+ bool (*read_optdrops_option) (struct config_setting_t *option, struct optdrop_group_optslot *entry, int *idx, bool *calc_rate, int slot, const char *group);
+ bool (*read_optdrops_optslot) (struct config_setting_t *optslot, int n, int group_id, const char *group);
+ bool (*read_optdrops_group) (struct config_setting_t *group, int n);
+ bool (*read_optdrops_db) (void);
void (*readdb) (void);
bool (*lookup_const) (const struct config_setting_t *it, const char *name, int *value);
bool (*get_const) (const struct config_setting_t *it, int *value);
@@ -519,19 +595,27 @@ struct mob_interface {
void (*read_db_drops_sub) (struct mob_db *entry, struct config_setting_t *t);
void (*read_db_mvpdrops_sub) (struct mob_db *entry, struct config_setting_t *t);
uint32 (*read_db_mode_sub) (struct mob_db *entry, struct config_setting_t *t);
+ struct optdrop_group *(*read_db_drops_option) (struct mob_db *entry, const char *item_name, struct config_setting_t *drop, int *drop_rate);
void (*read_db_stats_sub) (struct mob_db *entry, struct config_setting_t *t);
+ void (*read_db_viewdata_sub) (struct mob_db *entry, struct config_setting_t *t);
void (*name_constants) (void);
- bool (*readdb_mobavail) (char *str[], int columns, int current);
+ void (*mobavail_removal_notice) (void);
int (*read_randommonster) (void);
bool (*parse_row_chatdb) (char **str, const char *source, int line, int *last_msg_id);
void (*readchatdb) (void);
- bool (*parse_row_mobskilldb) (char **str, int columns, int current);
void (*readskilldb) (void);
bool (*readdb_race2) (char *fields[], int columns, int current);
bool (*readdb_itemratio) (char *str[], int columns, int current);
void (*load) (bool minimal);
void (*clear_spawninfo) (void);
+ struct item_drop_ratio *(*get_item_drop_ratio) (int nameid);
+ void (*set_item_drop_ratio) (int nameid, struct item_drop_ratio *ratio);
+ int (*final_ratio_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*destroy_mob_db) (int index);
+ void (*destroy_drop_groups) (void);
+ bool (*skill_db_libconfig) (const char *filename, bool ignore_missing);
+ bool (*skill_db_libconfig_sub) (struct config_setting_t *it, int n);
+ bool (*skill_db_libconfig_sub_skill) (struct config_setting_t *it, int n, int mob_id);
};
#ifdef HERCULES_CORE
diff --git a/src/map/npc.c b/src/map/npc.c
index 1b784b0c8..40ec380ee 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include "map/battle.h"
#include "map/chat.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/guild.h"
#include "map/instance.h"
@@ -35,10 +36,12 @@
#include "map/mob.h"
#include "map/pc.h"
#include "map/pet.h"
+#include "map/quest.h"
#include "map/script.h"
#include "map/skill.h"
#include "map/status.h"
#include "map/unit.h"
+#include "map/achievement.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/db.h"
@@ -59,27 +62,16 @@
#include <string.h>
#include <time.h>
-struct npc_interface npc_s;
+static struct npc_interface npc_s;
struct npc_interface *npc;
-static int npc_id=START_NPC_NUM;
-static int npc_warp=0;
-static int npc_shop=0;
-static int npc_script=0;
-static int npc_mob=0;
-static int npc_delay_mob=0;
-static int npc_cache_mob=0;
-
-static const char *npc_last_path;
-static const char *npc_last_ref;
-struct npc_path_data *npc_last_npd;
//For holding the view data of npc classes. [Skotlex]
static struct view_data npc_viewdb[MAX_NPC_CLASS];
static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START];
/* for speedup */
-unsigned int npc_market_qty[MAX_INVENTORY];
+static unsigned int npc_market_qty[MAX_INVENTORY];
static struct script_event_s {
//Holds pointers to the commonly executed scripts for speedup. [Skotlex]
@@ -93,7 +85,7 @@ static struct script_event_s {
* @param class_ The NPC class ID.
* @return The viewdata, or NULL if the ID is invalid.
*/
-struct view_data *npc_get_viewdata(int class_)
+static struct view_data *npc_get_viewdata(int class_)
{
if (class_ == INVISIBLE_CLASS)
return &npc_viewdb[0];
@@ -115,7 +107,7 @@ struct view_data *npc_get_viewdata(int class_)
* @param id The NPC ID to validate.
* @return Whether the value is a valid ID.
*/
-bool npc_db_checkid(int id)
+static bool npc_db_checkid(int id)
{
if (id >= WARP_CLASS && id <= 125) // First subrange
return true;
@@ -125,22 +117,25 @@ bool npc_db_checkid(int id)
return true;
if (id >= MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END) // Second range
return true;
+ if (pc->db_checkid(id))
+ return true;
// Anything else is invalid
return false;
}
/// Returns a new npc id that isn't being used in id_db.
/// Fatal error if nothing is available.
-int npc_get_new_npc_id(void) {
- if( npc_id >= START_NPC_NUM && !map->blid_exists(npc_id) )
- return npc_id++;// available
+static int npc_get_new_npc_id(void)
+{
+ if (npc->npc_id >= START_NPC_NUM && !map->blid_exists(npc->npc_id))
+ return npc->npc_id++;// available
else {// find next id
- int base_id = npc_id;
- while( base_id != ++npc_id ) {
- if( npc_id < START_NPC_NUM )
- npc_id = START_NPC_NUM;
- if( !map->blid_exists(npc_id) )
- return npc_id++;// available
+ int base_id = npc->npc_id;
+ while (base_id != ++npc->npc_id) {
+ if (npc->npc_id < START_NPC_NUM)
+ npc->npc_id = START_NPC_NUM;
+ if (!map->blid_exists(npc->npc_id))
+ return npc->npc_id++;// available
}
// full loop, nothing available
ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting...");
@@ -148,7 +143,7 @@ int npc_get_new_npc_id(void) {
}
}
-int npc_isnear_sub(struct block_list *bl, va_list args)
+static int npc_isnear_sub(struct block_list *bl, va_list args)
{
const struct npc_data *nd = NULL;
@@ -165,7 +160,8 @@ int npc_isnear_sub(struct block_list *bl, va_list args)
return 1;
}
-bool npc_isnear(struct block_list * bl) {
+static bool npc_isnear(struct block_list *bl)
+{
if( battle_config.min_npc_vendchat_distance > 0
&& map->foreachinrange(npc->isnear_sub,bl, battle_config.min_npc_vendchat_distance, BL_NPC) )
return true;
@@ -173,7 +169,7 @@ bool npc_isnear(struct block_list * bl) {
return false;
}
-int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
+static int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
@@ -188,7 +184,7 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
return npc->event(sd,name,1);
}
-int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
+static int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
@@ -201,7 +197,7 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
return npc->event(sd, name, 2);
}
-int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd)
+static int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
@@ -217,7 +213,7 @@ int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd)
/*==========================================
* Sub-function of npc_enable, runs OnTouch event when enabled
*------------------------------------------*/
-int npc_enable_sub(struct block_list *bl, va_list ap)
+static int npc_enable_sub(struct block_list *bl, va_list ap)
{
struct npc_data *nd;
@@ -245,7 +241,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
/*==========================================
* Disable / Enable NPC
*------------------------------------------*/
-int npc_enable(const char* name, int flag)
+static int npc_enable(const char *name, int flag)
{
struct npc_data* nd = npc->name2id(name);
@@ -283,7 +279,7 @@ int npc_enable(const char* name, int flag)
/*==========================================
* NPC lookup (get npc_data through npcname)
*------------------------------------------*/
-struct npc_data *npc_name2id(const char *name)
+static struct npc_data *npc_name2id(const char *name)
{
return strdb_get(npc->name_db, name);
}
@@ -293,7 +289,8 @@ struct npc_data *npc_name2id(const char *name)
/**
* Timer to check for idle time and timeout the dialog if necessary
**/
-int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) {
+static int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data)
+{
#ifdef SECURE_NPCTIMEOUT
struct map_session_data* sd = NULL;
unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT;
@@ -340,7 +337,7 @@ int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Dequeue event and add timer for execution (100ms)
*------------------------------------------*/
-int npc_event_dequeue(struct map_session_data* sd)
+static int npc_event_dequeue(struct map_session_data *sd)
{
nullpo_ret(sd);
@@ -372,7 +369,7 @@ int npc_event_dequeue(struct map_session_data* sd)
/**
* @see DBCreateData
*/
-struct DBData npc_event_export_create(union DBKey key, va_list args)
+static struct DBData npc_event_export_create(union DBKey key, va_list args)
{
struct linkdb_node** head_ptr;
CREATE(head_ptr, struct linkdb_node*, 1);
@@ -384,7 +381,7 @@ struct DBData npc_event_export_create(union DBKey key, va_list args)
* exports a npc event label
* called from npc_parse_script
*------------------------------------------*/
-int npc_event_export(struct npc_data *nd, int i)
+static int npc_event_export(struct npc_data *nd, int i)
{
char* lname;
int pos;
@@ -410,13 +407,13 @@ int npc_event_export(struct npc_data *nd, int i)
return 0;
}
-int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname); //[Lance]
+static int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const char *eventname); //[Lance]
/**
* Exec name (NPC events) on player or global
* Do on all NPC when called with foreach
*/
-void npc_event_doall_sub(void *key, void *data, va_list ap)
+static void npc_event_doall_sub(void *key, void *data, va_list ap)
{
struct event_data* ev = data;
int* c;
@@ -442,7 +439,7 @@ void npc_event_doall_sub(void *key, void *data, va_list ap)
}
// runs the specified event (supports both single-npc and global events)
-int npc_event_do(const char* name)
+static int npc_event_do(const char *name)
{
nullpo_ret(name);
if( name[0] == ':' && name[1] == ':' ) {
@@ -459,7 +456,7 @@ int npc_event_do(const char* name)
}
// runs the specified event, with a RID attached (global only)
-int npc_event_doall_id(const char* name, int rid)
+static int npc_event_doall_id(const char *name, int rid)
{
int c = 0;
struct linkdb_node **label_linkdb = strdb_get(npc->ev_label_db, name);
@@ -472,7 +469,7 @@ int npc_event_doall_id(const char* name, int rid)
}
// runs the specified event (global only)
-int npc_event_doall(const char* name)
+static int npc_event_doall(const char *name)
{
return npc->event_doall_id(name, 0);
}
@@ -481,7 +478,8 @@ int npc_event_doall(const char* name)
* Clock event execution
* OnMinute/OnClock/OnHour/OnDay/OnDDHHMM
*------------------------------------------*/
-int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) {
+static int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data)
+{
static struct tm ev_tm_b; // tracks previous execution time
time_t clock;
struct tm* t;
@@ -533,7 +531,7 @@ int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) {
* OnInit event execution (the start of the event and watch)
* @param reload Is the server reloading?
**/
-void npc_event_do_oninit( bool reload )
+static 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"));
@@ -546,7 +544,7 @@ void npc_event_do_oninit( bool reload )
* Incorporation of the label for the timer event
* called from npc_parse_script
*------------------------------------------*/
-int npc_timerevent_export(struct npc_data *nd, int i)
+static int npc_timerevent_export(struct npc_data *nd, int i)
{
int t = 0, len = 0;
char *lname;
@@ -585,7 +583,7 @@ struct timer_event_data {
/*==========================================
* triger 'OnTimerXXXX' events
*------------------------------------------*/
-int npc_timerevent(int tid, int64 tick, int id, intptr_t data)
+static int npc_timerevent(int tid, int64 tick, int id, intptr_t data)
{
int old_rid, old_timer;
int64 old_tick;
@@ -656,7 +654,8 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data)
/*==========================================
* Start/Resume NPC timer
*------------------------------------------*/
-int npc_timerevent_start(struct npc_data* nd, int rid) {
+static int npc_timerevent_start(struct npc_data *nd, int rid)
+{
int j;
int64 tick = timer->gettick();
struct map_session_data *sd = NULL; //Player to whom script is attached.
@@ -708,7 +707,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid) {
/*==========================================
* Stop NPC timer
*------------------------------------------*/
-int npc_timerevent_stop(struct npc_data* nd)
+static int npc_timerevent_stop(struct npc_data *nd)
{
struct map_session_data *sd = NULL;
int *tid;
@@ -742,7 +741,7 @@ int npc_timerevent_stop(struct npc_data* nd)
/*==========================================
* Aborts a running NPC timer that is attached to a player.
*------------------------------------------*/
-void npc_timerevent_quit(struct map_session_data* sd)
+static void npc_timerevent_quit(struct map_session_data *sd)
{
const struct TimerData *td;
struct npc_data* nd;
@@ -807,7 +806,8 @@ void npc_timerevent_quit(struct map_session_data* sd)
* Get the tick value of an NPC timer
* If it's stopped, return stopped time
*------------------------------------------*/
-int64 npc_gettimerevent_tick(struct npc_data* nd) {
+static int64 npc_gettimerevent_tick(struct npc_data *nd)
+{
int64 tick;
nullpo_ret(nd);
@@ -823,7 +823,7 @@ int64 npc_gettimerevent_tick(struct npc_data* nd) {
/*==========================================
* Set tick for running and stopped timer
*------------------------------------------*/
-int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
+static int npc_settimerevent_tick(struct npc_data *nd, int newtimer)
{
bool flag;
int old_rid;
@@ -847,7 +847,7 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
return 0;
}
-int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname)
+static int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const char *eventname)
{
nullpo_retr(2, sd);
nullpo_retr(2, eventname);
@@ -878,7 +878,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
/*==========================================
* NPC processing event type
*------------------------------------------*/
-int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
+static int npc_event(struct map_session_data *sd, const char *eventname, int ontouch)
{
struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname);
struct npc_data *nd;
@@ -907,7 +907,8 @@ int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
/*==========================================
* Sub chk then execute area event type
*------------------------------------------*/
-int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) {
+static int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
+{
struct map_session_data *sd;
int pc_id;
char *name;
@@ -934,7 +935,8 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) {
* Chk if sd is still touching his assigned npc.
* If not, it unsets it and searches for another player in range.
*------------------------------------------*/
-int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) {
+static int npc_touchnext_areanpc(struct map_session_data *sd, bool leavemap)
+{
struct npc_data *nd;
short xs, ys;
@@ -963,7 +965,7 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) {
/*==========================================
* Exec OnTouch for player if in range of area event
*------------------------------------------*/
-int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
+static int npc_touch_areanpc(struct map_session_data *sd, int16 m, int16 x, int16 y)
{
int xs,ys;
int f = 1;
@@ -1052,7 +1054,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
/*==========================================
* Exec OnUnTouch for player if out range of area event
*------------------------------------------*/
-int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
+static int npc_untouch_areanpc(struct map_session_data *sd, int16 m, int16 x, int16 y)
{
struct npc_data *nd = NULL;
nullpo_retr(1, sd);
@@ -1074,7 +1076,7 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
// OnTouch NPC or Warp for Mobs
// Return 1 if Warped
-int npc_touch_areanpc2(struct mob_data *md)
+static int npc_touch_areanpc2(struct mob_data *md)
{
int i, m, x, y, id;
char eventname[EVENT_NAME_LENGTH];
@@ -1139,7 +1141,8 @@ int npc_touch_areanpc2(struct mob_data *md)
//Flag determines the type of object to check for:
//&1: NPC Warps
//&2: NPCs with on-touch events.
-int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) {
+static int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
+{
int i;
int x0,y0,x1,y1;
int xs,ys;
@@ -1198,7 +1201,7 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) {
* Chk if player not too far to access the npc.
* Returns npc_data (success) or NULL (fail).
*------------------------------------------*/
-struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl)
+static struct npc_data *npc_checknear(struct map_session_data *sd, struct block_list *bl)
{
struct npc_data *nd = BL_CAST(BL_NPC, bl);
int distance = AREA_SIZE + 1;
@@ -1231,7 +1234,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b
/*==========================================
* Make NPC talk in global chat (like npctalk)
*------------------------------------------*/
-int npc_globalmessage(const char* name, const char* mes)
+static int npc_globalmessage(const char *name, const char *mes)
{
struct npc_data* nd = npc->name2id(name);
char temp[100];
@@ -1249,11 +1252,15 @@ int npc_globalmessage(const char* name, const char* mes)
}
// MvP tomb [GreenBox]
-void run_tomb(struct map_session_data* sd, struct npc_data* nd) {
+static void run_tomb(struct map_session_data *sd, struct npc_data *nd)
+{
char buffer[200];
char time[10];
nullpo_retv(nd);
+
+ sd->npc_id = nd->bl.id;
+
strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
// TODO: Find exact color?
@@ -1277,7 +1284,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd) {
* NPC 1st call when clicking on npc
* Do specific action for NPC type (openshop, run scripts...)
*------------------------------------------*/
-int npc_click(struct map_session_data* sd, struct npc_data* nd)
+static int npc_click(struct map_session_data *sd, struct npc_data *nd)
{
nullpo_retr(1, sd);
@@ -1328,48 +1335,68 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
return 0;
}
-/*==========================================
+/**
+ * Validates a character's script related data and (re-)runs the script if validation was successful.
*
- *------------------------------------------*/
-int npc_scriptcont(struct map_session_data* sd, int id, bool closing) {
- struct block_list *target = map->id2bl(id);
+ * Is called when:
+ * - The Next/Close button was clicked.
+ * - A menu option was selected.
+ * - A value was entered by input() script command.
+ * - A progress bar has reached 100%.
+ * - The character timed out because of idling.
+ *
+ * @param sd The character's session data.
+ * @param id The NPC ID.
+ * @param closing Whether the script is closing, or not.
+ * @return 0 on success, otherwise 1.
+ *
+**/
+static int npc_scriptcont(struct map_session_data *sd, int id, bool closing)
+{
nullpo_retr(1, sd);
- if( id != sd->npc_id ){
- struct npc_data *nd_sd = map->id2nd(sd->npc_id);
- struct npc_data *nd = BL_CAST(BL_NPC, target);
- ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
- nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
- nd?(char*)nd->name:"'Unknown NPC'", (int)id);
- return 1;
+ struct block_list *target = map->id2bl(id);
+
+#ifdef SECURE_NPCTIMEOUT
+ if (sd->npc_idle_timer != INVALID_TIMER) { /// Not yet timed out.
+#endif
+ if (id != sd->npc_id) {
+ struct npc_data *nd_sd = map->id2nd(sd->npc_id);
+ struct npc_data *nd = BL_CAST(BL_NPC, target);
+
+ ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
+ (nd_sd != NULL) ? nd_sd->name : "'Unknown NPC'", sd->npc_id,
+ (nd != NULL) ? nd->name : "'Unknown NPC'", id);
+
+ return 1;
+ }
+#ifdef SECURE_NPCTIMEOUT
}
+#endif
- if(id != npc->fake_nd->bl.id) { // Not item script
- if ((npc->checknear(sd,target)) == NULL){
- ShowWarning("npc_scriptcont: failed npc->checknear test.\n");
+ if (id != npc->fake_nd->bl.id) { /// Not an item script.
+ if (sd->state.npc_unloaded != 0) {
+ sd->state.npc_unloaded = 0;
+ } else if (npc->checknear(sd, target) == NULL) {
+ ShowWarning("npc_scriptcont: Failed npc->checknear test.\n");
return 1;
}
}
- /**
- * For the Secure NPC Timeout option (check config/Secure.h) [RR]
- **/
+
#ifdef SECURE_NPCTIMEOUT
- /**
- * Update the last NPC iteration
- **/
- sd->npc_idle_tick = timer->gettick();
+ sd->npc_idle_tick = timer->gettick(); /// Update the last NPC iteration.
#endif
- /**
- * WPE can get to this point with a progressbar; we deny it.
- **/
- if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,timer->gettick()) > 0 )
+ /// WPE can get to this point with a progressbar; we deny it.
+ if (sd->progressbar.npc_id != 0 && DIFF_TICK(sd->progressbar.timeout, timer->gettick()) > 0)
return 1;
- if( !sd->st )
+ if (sd->st == NULL) {
+ sd->npc_id = 0;
return 1;
+ }
- if( closing && sd->st->state == CLOSE )
+ if (closing && sd->st->state == CLOSE)
sd->st->state = END;
script->run_main(sd->st);
@@ -1380,7 +1407,8 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) {
/*==========================================
* Chk if valid call then open buy or selling list
*------------------------------------------*/
-int npc_buysellsel(struct map_session_data* sd, int id, int type) {
+static int npc_buysellsel(struct map_session_data *sd, int id, int type)
+{
struct npc_data *nd;
nullpo_retr(1, sd);
@@ -1419,9 +1447,9 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) {
}
/*==========================================
-* Cash Shop Buy List
-*------------------------------------------*/
-int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlist *item_list)
+ * Cash Shop Buy List
+ *------------------------------------------*/
+static int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlist *item_list)
{
int i, j, new_, w, vt;
struct npc_data *nd = NULL;
@@ -1444,11 +1472,16 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlis
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 ) {
+ if (nd->subtype == SCRIPT && nd->u.scr.shop &&
+ nd->u.scr.shop->type != NST_ZENY &&
+ nd->u.scr.shop->type != NST_MARKET &&
+ nd->u.scr.shop->type != NST_BARTER &&
+ nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
- } else
+ } else {
return ERROR_TYPE_NPC;
+ }
} else {
shop = nd->u.shop.shop_item;
shop_size = nd->u.shop.count;
@@ -1522,7 +1555,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlis
}
//npc_buylist for script-controlled shops.
-int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd)
+static int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd)
{
char npc_ev[EVENT_NAME_LENGTH];
int i;
@@ -1554,7 +1587,7 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str
/**
* Loads persistent NPC Market Data from SQL
**/
-void npc_market_fromsql(void)
+static void npc_market_fromsql(void)
{
struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
char name[NAME_LENGTH+1];
@@ -1569,9 +1602,9 @@ void npc_market_fromsql(void)
return;
}
- SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name[0], sizeof(name), NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof name, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, sizeof itemid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, sizeof amount, NULL, NULL);
while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
struct npc_data *nd = NULL;
@@ -1579,11 +1612,11 @@ void npc_market_fromsql(void)
if( !(nd = npc->name2id(name)) ) {
ShowError("npc_market_fromsql: NPC '%s' not found! skipping...\n",name);
- npc->market_delfromsql_sub(name, USHRT_MAX);
+ npc->market_delfromsql_sub(name, INT_MAX);
continue;
- } else if ( nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_MARKET ) {
+ } else if (nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_MARKET) {
ShowError("npc_market_fromsql: NPC '%s' is not proper for market, skipping...\n",name);
- npc->market_delfromsql_sub(name, USHRT_MAX);
+ npc->market_delfromsql_sub(name, INT_MAX);
continue;
}
@@ -1605,18 +1638,20 @@ void npc_market_fromsql(void)
/**
* Saves persistent NPC Market Data into SQL
**/
-void npc_market_tosql(struct npc_data *nd, unsigned short index) {
+static void npc_market_tosql(struct npc_data *nd, int index)
+{
nullpo_retv(nd);
- Assert_retv(index < nd->u.scr.shop->items);
- if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%u')",
+ Assert_retv(index >= 0 && index < nd->u.scr.shop->items);
+ 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) {
- if( index == USHRT_MAX ) {
+static void npc_market_delfromsql_sub(const char *npcname, int index)
+{
+ if (index == INT_MAX ) {
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 {
@@ -1628,15 +1663,295 @@ void npc_market_delfromsql_sub(const char *npcname, unsigned short index) {
/**
* Removes persistent NPC Market Data from SQL
**/
-void npc_market_delfromsql(struct npc_data *nd, unsigned short index) {
+static void npc_market_delfromsql(struct npc_data *nd, int index)
+{
+ nullpo_retv(nd);
+ Assert_retv(index == INT_MAX || (index >= 0 && index < nd->u.scr.shop->items));
+ npc->market_delfromsql_sub(nd->exname, index == INT_MAX ? index : nd->u.scr.shop->item[index].nameid);
+}
+
+/**
+ * Loads persistent NPC Barter Data from SQL
+ **/
+static void npc_barter_fromsql(void)
+{
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+ char name[NAME_LENGTH + 1];
+ int itemid;
+ int amount;
+ int removeId;
+ int removeAmount;
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemId`, `amount`, `priceId`, `priceAmount` FROM `%s`", map->npc_barter_data_db)
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return;
+ }
+
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof name, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, sizeof itemid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_UINT32, &amount, sizeof amount, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 3, SQLDT_INT, &removeId, sizeof removeId, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 4, SQLDT_INT, &removeAmount, sizeof removeAmount, NULL, NULL);
+
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ struct npc_data *nd = NULL;
+ unsigned short i;
+
+ if (!(nd = npc->name2id(name))) {
+ ShowError("npc_barter_fromsql: NPC '%s' not found! skipping...\n",name);
+ npc->barter_delfromsql_sub(name, INT_MAX, 0, 0);
+ continue;
+ } else if (nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_BARTER) {
+ ShowError("npc_barter_fromsql: NPC '%s' is not proper for barter, skipping...\n",name);
+ npc->barter_delfromsql_sub(name, INT_MAX, 0, 0);
+ continue;
+ }
+
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == itemid && item->value == removeId && item->value2 == removeAmount) {
+ item->qty = amount;
+ break;
+ }
+ }
+
+ if (i == nd->u.scr.shop->items) {
+ ShowError("npc_barter_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n", name, itemid, amount);
+ npc->barter_delfromsql_sub(name, itemid, removeId, removeAmount);
+ continue;
+ }
+ }
+ SQL->StmtFree(stmt);
+}
+
+/**
+ * Saves persistent NPC Barter Data into SQL
+ **/
+static void npc_barter_tosql(struct npc_data *nd, int index)
+{
nullpo_retv(nd);
- Assert_retv(index == USHRT_MAX || index < nd->u.scr.shop->items);
- npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid);
+ Assert_retv(index >= 0 && index < nd->u.scr.shop->items);
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[index];
+ if (item->qty == -1)
+ return;
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s', '%d', '%d', '%u', '%d')",
+ map->npc_barter_data_db, nd->exname, item->nameid, item->qty, item->value, item->value2)) {
+ Sql_ShowDebug(map->mysql_handle);
+ }
}
+
+/**
+ * Removes persistent NPC Barter Data from SQL
+ */
+static void npc_barter_delfromsql_sub(const char *npcname, int itemId, int itemId2, int amount2)
+{
+ if (itemId == INT_MAX) {
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_barter_data_db, npcname))
+ Sql_ShowDebug(map->mysql_handle);
+ } else {
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s' AND `itemId`='%d' AND `priceId`='%d' AND `priceAmount`='%d' LIMIT 1",
+ map->npc_barter_data_db, npcname, itemId, itemId2, amount2)) {
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ }
+}
+
+/**
+ * Removes persistent NPC Barter Data from SQL
+ **/
+static void npc_barter_delfromsql(struct npc_data *nd, int index)
+{
+ nullpo_retv(nd);
+ if (index == INT_MAX) {
+ npc->barter_delfromsql_sub(nd->exname, INT_MAX, 0, 0);
+ } else {
+ Assert_retv(index >= 0 && index < nd->u.scr.shop->items);
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[index];
+ npc->barter_delfromsql_sub(nd->exname, item->nameid, item->value, item->value2);
+ }
+}
+
+
+/**
+ * Loads persistent NPC Expanded Barter Data from SQL
+ **/
+static void npc_expanded_barter_fromsql(void)
+{
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+ char name[NAME_LENGTH + 1];
+ int itemid;
+ int amount;
+ int zeny;
+ StringBuf buf;
+
+ StrBuf->Init(&buf);
+ StrBuf->AppendStr(&buf, "SELECT `name`, `itemId`, `amount`, `zeny`");
+ for (int k = 1; k < 11; k ++) {
+ StrBuf->Printf(&buf, ", `currencyId%d`, `currencyAmount%d`, `currencyRefine%d`", k, k, k);
+ }
+ StrBuf->Printf(&buf, " FROM `%s`", map->npc_expanded_barter_data_db);
+
+ if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ StrBuf->Destroy(&buf);
+ return;
+ }
+
+ struct npc_barter_currency tempCurrency[10];
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof name, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, sizeof itemid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_UINT32, &amount, sizeof amount, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 3, SQLDT_UINT32, &zeny, sizeof zeny, NULL, NULL);
+ for (int k = 0; k < 10; k ++) {
+ SQL->StmtBindColumn(stmt, k * 3 + 4, SQLDT_INT, &tempCurrency[k].nameid, sizeof tempCurrency[k].nameid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, k * 3 + 5, SQLDT_INT, &tempCurrency[k].amount, sizeof tempCurrency[k].amount, NULL, NULL);
+ SQL->StmtBindColumn(stmt, k * 3 + 6, SQLDT_INT, &tempCurrency[k].refine, sizeof tempCurrency[k].refine, NULL, NULL);
+ }
+
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ struct npc_data *nd = NULL;
+ unsigned short i;
+
+ if ((nd = npc->name2id(name)) == NULL) {
+ ShowError("npc_expanded_barter_fromsql: NPC '%s' not found! skipping...\n",name);
+ npc->expanded_barter_delfromsql_sub(name, INT_MAX, 0, 0, NULL);
+ continue;
+ } else if (nd->subtype != SCRIPT || nd->u.scr.shop == NULL || nd->u.scr.shop->items == 0 || nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ ShowError("npc_expanded_barter_fromsql: NPC '%s' is not proper for barter, skipping...\n",name);
+ npc->expanded_barter_delfromsql_sub(name, INT_MAX, 0, 0, NULL);
+ continue;
+ }
+
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == itemid && item->value == zeny) {
+ int count = nd->u.scr.shop->item[i].value2;
+ if (count > 10)
+ count = 10;
+ int curIndex;
+ for (curIndex = 0; curIndex < count; curIndex ++) {
+ struct npc_barter_currency *currency = &nd->u.scr.shop->item[i].currency[curIndex];
+ struct npc_barter_currency *currency2 = &tempCurrency[curIndex];
+ if (currency->nameid != currency2->nameid ||
+ currency->amount != currency2->amount ||
+ currency->refine != currency2->refine) {
+ break;
+ }
+ }
+ if (curIndex == count) {
+ item->qty = amount;
+ break;
+ }
+ }
+ }
+
+ if (i == nd->u.scr.shop->items) {
+ ShowError("npc_expanded_barter_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n", name, itemid, amount);
+ npc->expanded_barter_delfromsql_sub(name, itemid, zeny, 10, &tempCurrency[0]);
+ continue;
+ }
+ }
+ SQL->StmtFree(stmt);
+ StrBuf->Destroy(&buf);
+}
+
+/**
+ * Saves persistent NPC Expanded Barter Data into SQL
+ **/
+static void npc_expanded_barter_tosql(struct npc_data *nd, int index)
+{
+ nullpo_retv(nd);
+ Assert_retv(index >= 0 && index < nd->u.scr.shop->items);
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[index];
+ if (item->qty == -1)
+ return;
+
+ npc->expanded_barter_delfromsql(nd, index);
+
+ StringBuf buf;
+ StrBuf->Init(&buf);
+ StrBuf->Printf(&buf, "INSERT INTO `%s` VALUES ('%s', '%d', '%d', '%u'", map->npc_expanded_barter_data_db, nd->exname, item->nameid, item->qty, item->value);
+ int currencyCount = item->value2;
+ if (currencyCount > 10)
+ currencyCount = 10;
+ int k;
+ for (k = 0; k < currencyCount; k++) {
+ struct npc_barter_currency *currency = &item->currency[k];
+ StrBuf->Printf(&buf, ", '%d', '%d', '%d'", currency->nameid, currency->amount, currency->refine);
+ }
+ for (; k < 10; k ++) {
+ StrBuf->Printf(&buf, ", '0', '0', '0'");
+ }
+ StrBuf->AppendStr(&buf, ")");
+
+ if (SQL_ERROR == SQL->QueryStr(map->mysql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ StrBuf->Destroy(&buf);
+}
+
+/**
+ * Removes persistent NPC Expanded Barter Data from SQL
+ */
+static void npc_expanded_barter_delfromsql_sub(const char *npcname, int itemId, int zeny, int currencyCount, struct npc_barter_currency* currency)
+{
+ if (itemId == INT_MAX) {
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_expanded_barter_data_db, npcname))
+ Sql_ShowDebug(map->mysql_handle);
+ } else {
+ StringBuf buf;
+
+ StrBuf->Init(&buf);
+ StrBuf->Printf(&buf, "DELETE FROM `%s` WHERE `name`='%s' AND `itemId`='%d' AND `zeny`='%d'",
+ map->npc_expanded_barter_data_db, npcname, itemId, zeny);
+ int k = 0;
+ if (currencyCount > 10)
+ currencyCount = 10;
+ for (k = 0; k < currencyCount; k++) {
+ struct npc_barter_currency *currency1 = &currency[k];
+ StrBuf->Printf(&buf, " AND currencyId%d='%d' and currencyAmount%d='%d' and currencyRefine%d='%d'",
+ k + 1, currency1->nameid, k + 1, currency1->amount, k + 1, currency1->refine);
+ }
+ for (; k < 10; k ++) {
+ StrBuf->Printf(&buf, " AND currencyId%d='0' and currencyAmount%d='0' and currencyRefine%d='0'",
+ k + 1, k + 1, k + 1);
+ }
+ StrBuf->AppendStr(&buf, " LIMIT 1");
+
+ if (SQL_ERROR == SQL->QueryStr(map->mysql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ StrBuf->Destroy(&buf);
+ }
+}
+
+
+/**
+ * Removes persistent NPC Expanded Barter Data from SQL
+ **/
+static void npc_expanded_barter_delfromsql(struct npc_data *nd, int index)
+{
+ nullpo_retv(nd);
+ if (index == INT_MAX) {
+ npc->expanded_barter_delfromsql_sub(nd->exname, INT_MAX, 0, 0, NULL);
+ } else {
+ Assert_retv(index >= 0 && index < nd->u.scr.shop->items);
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[index];
+ npc->expanded_barter_delfromsql_sub(nd->exname, item->nameid, item->value, item->value2, &item->currency[0]);
+ }
+}
+
/**
* Judges whether to allow and spawn a trader's window.
**/
-bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
+static bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd)
+{
nullpo_retr(false, sd);
nullpo_retr(false, nd);
if( !nd->u.scr.shop || !nd->u.scr.shop->items )
@@ -1664,6 +1979,12 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
clif->npc_market_open(sd,nd);
}
break;
+ case NST_BARTER:
+ clif->npc_barter_open(sd, nd);
+ break;
+ case NST_EXPANDED_BARTER:
+ clif->npc_expanded_barter_open(sd, nd);
+ break;
default:
clif->cashshop_show(sd,nd);
break;
@@ -1676,7 +1997,8 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
*
* @param master id of the original npc
**/
-void npc_trader_update(int master) {
+static void npc_trader_update(int master)
+{
struct DBIterator *iter;
struct block_list* bl;
struct npc_data *master_nd = map->id2nd(master);
@@ -1700,7 +2022,8 @@ void npc_trader_update(int master) {
* @param nd shop
* @param sd player
**/
-void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) {
+static void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd)
+{
char evname[EVENT_NAME_LENGTH];
struct event_data *ev = NULL;
@@ -1740,7 +2063,8 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) {
*
* @return bool whether it was successful (if the script does not respond it will fail)
**/
-bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, int points) {
+static bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, int points)
+{
char evname[EVENT_NAME_LENGTH];
struct event_data *ev = NULL;
@@ -1750,8 +2074,8 @@ bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price,
snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname);
if ( (ev = strdb_get(npc->ev_db, evname)) ) {
- pc->setreg(sd,script->add_str("@price"),price);
- pc->setreg(sd,script->add_str("@points"),points);
+ pc->setreg(sd,script->add_variable("@price"),price);
+ pc->setreg(sd,script->add_variable("@points"),points);
script->run_npc(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
} else
ShowError("npc_trader_pay: '%s' event '%s' not found, operation failed\n",nd->exname,evname);
@@ -1761,7 +2085,8 @@ bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price,
/*==========================================
* Cash Shop Buy
*------------------------------------------*/
-int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points) {
+static int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points)
+{
struct npc_data *nd = NULL;
struct item_data *item;
struct npc_item_list *shop = NULL;
@@ -1786,11 +2111,16 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
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 ) {
+ if (nd->subtype == SCRIPT && nd->u.scr.shop &&
+ nd->u.scr.shop->type != NST_ZENY &&
+ nd->u.scr.shop->type != NST_MARKET &&
+ nd->u.scr.shop->type != NST_BARTER &&
+ nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
- } else
+ } else {
return ERROR_TYPE_NPC;
+ }
} else {
shop = nd->u.shop.shop_item;
shop_size = nd->u.shop.count;
@@ -1866,7 +2196,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
* @param item_list List of items.
* @return result code for clif->parse_NpcBuyListSend.
*/
-int npc_buylist(struct map_session_data *sd, struct itemlist *item_list)
+static int npc_buylist(struct map_session_data *sd, struct itemlist *item_list)
{
struct npc_data* nd;
struct npc_item_list *shop = NULL;
@@ -1935,7 +2265,11 @@ int npc_buylist(struct map_session_data *sd, struct itemlist *item_list)
break;
case ADDITEM_OVERAMOUNT:
+#if PACKETVER >= 20110705
+ return 9;
+#else
return 2;
+#endif
}
value = pc->modifybuyvalue(sd,value);
@@ -1989,7 +2323,7 @@ int npc_buylist(struct map_session_data *sd, struct itemlist *item_list)
/**
* Processes incoming npc market purchase list
**/
-int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
+static enum market_buy_result npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
{
struct npc_data* nd;
struct npc_item_list *shop = NULL;
@@ -2003,7 +2337,7 @@ int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
nd = npc->checknear(sd,map->id2bl(sd->npc_shopid));
if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET)
- return 1;
+ return MARKET_BUY_RESULT_ERROR;
shop = nd->u.scr.shop->item;
shop_size = nd->u.scr.shop->items;
@@ -2023,18 +2357,18 @@ int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement
);
if (j == shop_size) /* TODO find official response for this */
- return 1; // no such item in shop
+ return MARKET_BUY_RESULT_ERROR; // no such item in shop
entry->id = shop[j].nameid; //item_avail replacement
if (entry->amount > (int)shop[j].qty)
- return 1;
+ return MARKET_BUY_RESULT_AMOUNT_TOO_BIG;
value = shop[j].value;
npc_market_qty[i] = j;
if (!itemdb->exists(entry->id)) /* TODO find official response for this */
- return 1; // item no longer in itemdb
+ return MARKET_BUY_RESULT_ERROR; // item no longer in itemdb
if (!itemdb->isstackable(entry->id) && entry->amount > 1) {
//Exploit? You can't buy more than 1 of equipment types o.O
@@ -2058,13 +2392,13 @@ int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
}
if (z > sd->status.zeny) /* TODO find official response for this */
- return 1; // Not enough Zeny
+ return MARKET_BUY_RESULT_NO_ZENY; // Not enough Zeny
if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */
- return 1; // Too heavy
+ return MARKET_BUY_RESULT_OVER_WEIGHT; // Too heavy
if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */
- return 1; // Not enough space to store items
+ return MARKET_BUY_RESULT_OUT_OF_SPACE; // Not enough space to store items
pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
@@ -2074,7 +2408,7 @@ int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
j = npc_market_qty[i];
if (entry->amount > (int)shop[j].qty) /* wohoo someone tampered with the packet. */
- return 1;
+ return MARKET_BUY_RESULT_AMOUNT_TOO_BIG;
shop[j].qty -= entry->amount;
@@ -2092,14 +2426,292 @@ int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list)
}
}
- return 0;
+ return MARKET_BUY_RESULT_SUCCESS;
+}
+
+/**
+ * Processes incoming npc barter purchase list
+ **/
+static int npc_barter_buylist(struct map_session_data *sd, struct barteritemlist *item_list)
+{
+ struct npc_data* nd;
+ struct npc_item_list *shop = NULL;
+ int w, new_;
+ unsigned short shop_size = 0;
+
+ nullpo_retr(1, sd);
+ nullpo_retr(1, item_list);
+
+ nd = npc->checknear(sd, map->id2bl(sd->npc_shopid));
+
+ if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_BARTER)
+ return 11;
+
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+
+ w = 0;
+ new_ = 0;
+
+ int items[MAX_INVENTORY] = { 0 };
+
+ // process entries in buy list, one by one
+ for (int i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ struct barter_itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
+
+ const int n = entry->removeIndex;
+ if (n < 0 || n >= sd->status.inventorySize)
+ return 11; // wrong inventory index
+
+ if (entry->addAmount <= 0)
+ return 14; // not enough item amount in inventory
+
+ int removeId = sd->status.inventory[n].nameid;
+ const int j = entry->shopIndex;
+ if (j < 0 || j >= shop_size)
+ return 13; // no such item in shop
+ if (entry->addId != shop[j].nameid && entry->addId != itemdb_viewid(shop[j].nameid))
+ return 13; // no such item in shop
+ if (removeId != shop[j].value && removeId != itemdb_viewid(shop[j].value))
+ return 13; // no such item in shop
+ entry->addId = shop[j].nameid; // item_avail replacement
+ removeId = shop[j].value; // item_avail replacement
+
+ if (!itemdb->exists(entry->addId))
+ return 13; // item no longer in itemdb
+
+ const int removeAmount = shop[j].value2;
+
+ if ((int)shop[j].qty != -1 && entry->addAmount > (int)shop[j].qty)
+ return 14; // not enough item amount in shop
+
+ if (removeAmount * entry->addAmount > sd->status.inventory[n].amount)
+ return 14; // not enough item amount in inventory
+
+ items[n] += removeAmount * entry->addAmount;
+
+ if (items[n] > sd->status.inventory[n].amount)
+ return 14; // not enough item amount in inventory
+
+ entry->addId = shop[j].nameid; //item_avail replacement
+
+ npc_market_qty[i] = j;
+
+ if (!itemdb->isstackable(entry->addId) && entry->addAmount > 1) {
+ //Exploit? You can't buy more than 1 of equipment types o.O
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id, entry->addAmount, entry->addId);
+ entry->addAmount = 1;
+ }
+
+ switch (pc->checkadditem(sd, entry->addId, entry->addAmount)) {
+ case ADDITEM_EXIST:
+ break;
+ case ADDITEM_NEW:
+ new_++;
+ break;
+ case ADDITEM_OVERAMOUNT: /* TODO find official response for this */
+ return 1;
+ }
+
+ w += itemdb_weight(entry->addId) * entry->addAmount;
+ w -= itemdb_weight(removeId) * removeAmount;
+ }
+
+ if (w + sd->weight > sd->max_weight)
+ return 2; // Too heavy
+
+ if (pc->inventoryblank(sd) < new_)
+ return 3; // Not enough space to store items
+
+ for (int i = 0; i < sd->status.inventorySize; ++i) {
+ const int removeAmountTotal = items[i];
+ if (removeAmountTotal == 0)
+ continue;
+ if (pc->delitem(sd, i, removeAmountTotal, 0, DELITEM_SOLD, LOG_TYPE_NPC) != 0) {
+ return 11; // unknown exploit
+ }
+ }
+
+ for (int i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ struct barter_itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
+ const int shopIdx = npc_market_qty[i];
+
+ if ((int)shop[shopIdx].qty != -1) {
+ if (entry->addAmount > (int)shop[shopIdx].qty) /* wohoo someone tampered with the packet. */
+ return 14;
+ shop[shopIdx].qty -= entry->addAmount;
+ }
+
+ npc->barter_tosql(nd, shopIdx);
+
+ if (itemdb_type(entry->addId) == IT_PETEGG) {
+ pet->create_egg(sd, entry->addId);
+ } else {
+ struct item item_tmp;
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = entry->addId;
+ item_tmp.identify = 1;
+ pc->additem(sd, &item_tmp, entry->addAmount, LOG_TYPE_NPC);
+ }
+ }
+
+ return 12;
+}
+
+
+/**
+ * Processes incoming npc expanded barter purchase list
+ **/
+static int npc_expanded_barter_buylist(struct map_session_data *sd, struct barteritemlist *item_list)
+{
+ nullpo_retr(1, sd);
+ nullpo_retr(1, item_list);
+
+ struct npc_data* nd = npc->checknear(sd, map->id2bl(sd->npc_shopid));
+
+ if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 ||
+ !nd->u.scr.shop || nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ return 11;
+ }
+
+ struct npc_item_list *shop = nd->u.scr.shop->item;
+ unsigned short shop_size = nd->u.scr.shop->items;
+ int w = 0;
+ int new_ = 0;
+ int64 z = 0;
+ int items[MAX_INVENTORY] = { 0 };
+
+ // process entries in buy list, one by one
+ for (int i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ struct barter_itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
+
+ if (entry->addAmount <= 0)
+ return 14; // not enough item amount in inventory
+
+ const int j = entry->shopIndex;
+ if (j < 0 || j >= shop_size)
+ return 13; // no such item in shop
+ if (entry->addId != shop[j].nameid && entry->addId != itemdb_viewid(shop[j].nameid))
+ return 13; // no such item in shop
+ entry->addId = shop[j].nameid; // item_avail replacement
+ if (!itemdb->exists(entry->addId))
+ return 13; // item no longer in itemdb
+
+ if ((int)shop[j].qty != -1 && entry->addAmount > (int)shop[j].qty)
+ return 14; // not enough item amount in shop
+
+ int currencyCount = shop[j].value2;
+ for (int currencyIndex = 0; currencyIndex < currencyCount; currencyIndex ++) {
+ struct npc_barter_currency *currency = &shop[j].currency[currencyIndex];
+ const int currencyItemId = currency->nameid;
+ const int currencyRefine = currency->refine;
+ int removeAmount = currency->amount * entry->addAmount;
+ if (removeAmount <= 0)
+ continue;
+ for (int n = 0; n < sd->status.inventorySize && removeAmount > 0; ++n) {
+ // check item id and existing amount
+ if (sd->status.inventory[n].nameid == currencyItemId && sd->status.inventory[n].amount > 0) {
+ // check item refine level
+ if (currencyRefine != -1 && sd->status.inventory[n].refine != currencyRefine)
+ continue;
+ if (sd->status.inventory[n].amount >= removeAmount) {
+ items[n] += removeAmount;
+ removeAmount = 0;
+ w -= itemdb_weight(currencyItemId) * removeAmount;
+ break;
+ } else {
+ items[n] += sd->status.inventory[n].amount;
+ removeAmount -= sd->status.inventory[n].amount;
+ w -= itemdb_weight(currencyItemId) * sd->status.inventory[n].amount;
+ }
+ }
+ if (items[n] > sd->status.inventory[n].amount)
+ return 14; // not enough item amount in inventory
+ }
+ if (removeAmount != 0) {
+ return 14; // not enough item amount in inventory
+ }
+ }
+
+ entry->addId = shop[j].nameid; //item_avail replacement
+
+ npc_market_qty[i] = j;
+
+ if (!itemdb->isstackable(entry->addId) && entry->addAmount > 1) {
+ //Exploit? You can't buy more than 1 of equipment types o.O
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id, entry->addAmount, entry->addId);
+ entry->addAmount = 1;
+ }
+
+ switch (pc->checkadditem(sd, entry->addId, entry->addAmount)) {
+ case ADDITEM_EXIST:
+ break;
+ case ADDITEM_NEW:
+ new_++;
+ break;
+ case ADDITEM_OVERAMOUNT: /* TODO find official response for this */
+ return 1;
+ }
+
+ z += (int64)shop[j].value * entry->addAmount;
+ w += itemdb_weight(entry->addId) * entry->addAmount;
+ }
+
+ if (z > sd->status.zeny)
+ return 3; // Not enough Zeny
+
+ if ((int64)w + sd->weight > sd->max_weight)
+ return 2; // Too heavy
+
+ if (pc->inventoryblank(sd) < new_)
+ return 3; // Not enough space to store items
+
+ for (int i = 0; i < sd->status.inventorySize; ++i) {
+ const int removeAmountTotal = items[i];
+ if (removeAmountTotal == 0)
+ continue;
+ if (pc->delitem(sd, i, removeAmountTotal, 0, DELITEM_SOLD, LOG_TYPE_NPC) != 0) {
+ return 11; // unknown exploit
+ }
+ }
+
+ pc->payzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
+
+ for (int i = 0; i < VECTOR_LENGTH(*item_list); ++i) {
+ struct barter_itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
+ const int shopIdx = npc_market_qty[i];
+
+ if ((int)shop[shopIdx].qty != -1) {
+ if (entry->addAmount > (int)shop[shopIdx].qty) /* wohoo someone tampered with the packet. */
+ return 14;
+ shop[shopIdx].qty -= entry->addAmount;
+ }
+
+ npc->expanded_barter_tosql(nd, shopIdx);
+
+ if (itemdb_type(entry->addId) == IT_PETEGG) {
+ pet->create_egg(sd, entry->addId);
+ } else {
+ struct item item_tmp;
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = entry->addId;
+ item_tmp.identify = 1;
+ pc->additem(sd, &item_tmp, entry->addAmount, LOG_TYPE_NPC);
+ }
+ }
+
+ return 12;
}
/// npc_selllist for script-controlled shops
-int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd)
+static int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd)
{
char npc_ev[EVENT_NAME_LENGTH];
char card_slot[NAME_LENGTH];
+ char opt_index_str[NAME_LENGTH];
+ char opt_value_str[NAME_LENGTH];
int i, j;
int key_nameid = 0;
int key_amount = 0;
@@ -2107,6 +2719,8 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
int key_attribute = 0;
int key_identify = 0;
int key_card[MAX_SLOTS];
+ int key_opt_idx[MAX_ITEM_OPTIONS];
+ int key_opt_value[MAX_ITEM_OPTIONS];
nullpo_ret(sd);
nullpo_ret(item_list);
@@ -2126,6 +2740,17 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
script->cleararray_pc(sd, card_slot, (void*)0);
}
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) { // Clear Each item option entry
+ key_opt_idx[j] = 0;
+ key_opt_value[j] = 0;
+
+ snprintf(opt_index_str, sizeof(opt_index_str), "@slot_opt_idx%d", j + 1);
+ script->cleararray_pc(sd, opt_index_str, (void*)0);
+
+ snprintf(opt_value_str, sizeof(opt_value_str), "@slot_opt_val%d", j + 1);
+ script->cleararray_pc(sd, opt_value_str, (void*)0);
+ }
+
// save list of to be sold items
for (i = 0; i < VECTOR_LENGTH(*item_list); i++) {
struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
@@ -2151,6 +2776,17 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
script->setarray_pc(sd, card_slot, i, (void*)card, &key_card[j]);
}
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) {
+ intptr_t opt_idx = item->option[j].index;
+ intptr_t opt_value = item->option[j].value;
+
+ snprintf(opt_index_str, sizeof(opt_index_str), "@slot_opt_idx%d", j + 1);
+ script->setarray_pc(sd, opt_index_str, i, (void*)opt_idx, &key_opt_idx[j]);
+
+ snprintf(opt_value_str, sizeof(opt_value_str), "@slot_opt_val%d", j + 1);
+ script->setarray_pc(sd, opt_value_str, i, (void*)opt_value, &key_opt_value[j]);
+ }
+
}
// invoke event
@@ -2163,7 +2799,7 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
///
/// @param item_list 'n' pairs <index,amount>
/// @return result code for clif->parse_NpcSellListSend
-int npc_selllist(struct map_session_data *sd, struct itemlist *item_list)
+static int npc_selllist(struct map_session_data *sd, struct itemlist *item_list)
{
int64 z;
int i,skill_t, skill_idx = skill->get_index(MC_OVERCHARGE);
@@ -2178,18 +2814,21 @@ int npc_selllist(struct map_session_data *sd, struct itemlist *item_list)
}
if( nd->subtype != SHOP ) {
- if( !(nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type == NST_ZENY) )
+ if (!(nd->subtype == SCRIPT && nd->u.scr.shop && (nd->u.scr.shop->type == NST_ZENY || nd->u.scr.shop->type == NST_MARKET)))
return 1;
}
z = 0;
+ if (sd->status.zeny >= MAX_ZENY && nd->master_nd == NULL)
+ return 1;
+
// verify the sell list
for (i = 0; i < VECTOR_LENGTH(*item_list); i++) {
struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
int nameid, value, idx = entry->id;
- if (idx >= MAX_INVENTORY || idx < 0 || entry->amount < 0) {
+ if (idx >= sd->status.inventorySize || idx < 0 || entry->amount < 0) {
return 1;
}
@@ -2230,10 +2869,17 @@ int npc_selllist(struct map_session_data *sd, struct itemlist *item_list)
}
}
+ // Achievements [Smokexyz/Hercules]
+ achievement->validate_item_sell(sd, sd->status.inventory[idx].nameid, entry->amount);
+
pc->delitem(sd, idx, entry->amount, 0, DELITEM_SOLD, LOG_TYPE_NPC);
+
}
- if( z > MAX_ZENY )
+ if (z + sd->status.zeny > MAX_ZENY && nd->master_nd == NULL)
+ return 1;
+
+ if (z > MAX_ZENY)
z = MAX_ZENY;
pc->getzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
@@ -2256,7 +2902,8 @@ int npc_selllist(struct map_session_data *sd, struct itemlist *item_list)
//Atempt to remove an npc from a map
//This doesn't remove it from map_db
-int npc_remove_map(struct npc_data* nd) {
+static int npc_remove_map(struct npc_data *nd)
+{
int16 m,i;
nullpo_retr(1, nd);
@@ -2279,7 +2926,7 @@ int npc_remove_map(struct npc_data* nd) {
/**
* @see DBApply
*/
-int npc_unload_ev(union DBKey key, struct DBData *data, va_list ap)
+static int npc_unload_ev(union DBKey key, struct DBData *data, va_list ap)
{
struct event_data* ev = DB->data2ptr(data);
char* npcname = va_arg(ap, char *);
@@ -2294,7 +2941,7 @@ int npc_unload_ev(union DBKey key, struct DBData *data, va_list ap)
/**
* @see DBApply
*/
-int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap)
+static int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap)
{
struct linkdb_node **label_linkdb = DB->data2ptr(data);
struct npc_data* nd = va_arg(ap, struct npc_data *);
@@ -2304,119 +2951,193 @@ int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-//Chk if npc matches src_id, then unload.
-//Sub-function used to find duplicates.
-int npc_unload_dup_sub(struct npc_data* nd, va_list args)
+/**
+ * Unloads a NPC if it's a duplicate of the passed one.
+ *
+ * @param nd The NPC to check.
+ * @param args List of arguments.
+ * @return Always 0.
+ *
+ **/
+static int npc_unload_dup_sub(struct npc_data *nd, va_list args)
{
- int src_id;
-
nullpo_ret(nd);
- src_id = va_arg(args, int);
+
+ const int src_id = va_arg(args, int);
+ const int unload_mobs = va_arg(args, int);
+
if (nd->src_id == src_id)
- npc->unload(nd, true);
+ npc->unload(nd, true, (unload_mobs == 1));
+
return 0;
}
-//Removes all npcs that are duplicates of the passed one. [Skotlex]
-void npc_unload_duplicates(struct npc_data* nd) {
+/**
+ * Unloads all NPCs which are duplicates of the passed one.
+ *
+ * @param nd The source NPC.
+ * @param unload_mobs If true, mobs spawned by duplicates will be removed.
+ *
+ * @author Skotlex
+ *
+ **/
+static void npc_unload_duplicates(struct npc_data *nd, bool unload_mobs)
+{
nullpo_retv(nd);
- map->foreachnpc(npc->unload_dup_sub,nd->bl.id);
+
+ map->foreachnpc(npc->unload_dup_sub, nd->bl.id, unload_mobs);
+}
+
+/**
+ * Removes a mob, which was spawned by a NPC (monster/areamonster/guardian/bg_monster/atcommand("@monster xy")).
+ *
+ * @param md The mob to remove.
+ * @param args List of arguments.
+ * @return 1 on success, 0 on failure.
+ *
+ * @author Kenpachi
+ *
+ **/
+static int npc_unload_mob(struct mob_data *md, va_list args)
+{
+ nullpo_ret(md);
+
+ const int npc_id = va_arg(args, int);
+
+ if (md->npc_id == npc_id) {
+ md->state.npc_killmonster = 1;
+ status_kill(&md->bl);
+ return 1;
+ }
+
+ return 0;
}
-//Removes an npc from map and db.
-//Single is to free name (for duplicates).
-int npc_unload(struct npc_data* nd, bool single)
+/**
+ * Removes a NPC from map and database.
+ *
+ * @param nd The NPC which should be removed.
+ * @param single If true, names are freed. (For duplicates.)
+ * @param unload_mobs If true, mobs spawned by the NPC will be removed.
+ * @return Always 0.
+ *
+ **/
+static int npc_unload(struct npc_data *nd, bool single, bool unload_mobs)
{
nullpo_ret(nd);
- if( nd->ud && nd->ud != &npc->base_ud ) {
+ if (nd->ud != NULL && nd->ud != &npc->base_ud)
skill->clear_unitgroup(&nd->bl);
- }
npc->remove_map(nd);
map->deliddb(&nd->bl);
- if( single )
+
+ if (single)
strdb_remove(npc->name_db, nd->exname);
- if (nd->chat_id) // remove npc chatroom object and kick users
+ if (nd->chat_id != 0) /// Remove NPC chatroom object and kick users.
chat->delete_npc_chat(nd);
- npc_chat->finalize(nd); // deallocate npc PCRE data structures
+ npc_chat->finalize(nd); /// Deallocate NPC PCRE data structures.
if (single && nd->path != NULL) {
npc->releasepathreference(nd->path);
nd->path = NULL;
}
- if( single && nd->bl.m != -1 )
- map->remove_questinfo(nd->bl.m,nd);
+ if (single && nd->bl.m != INDEX_NOT_FOUND)
+ map->remove_questinfo(nd->bl.m, nd);
+
+ npc->questinfo_clear(nd);
- if (nd->src_id == 0 && ( nd->subtype == SHOP || nd->subtype == CASHSHOP)) {
- //src check for duplicate shops [Orcao]
- aFree(nd->u.shop.shop_item);
+ if (nd->src_id == 0 && (nd->subtype == SHOP || nd->subtype == CASHSHOP)) {
+ aFree(nd->u.shop.shop_item); /// src check for duplicate shops. [Orcao]
} else if (nd->subtype == SCRIPT) {
- struct s_mapiterator *iter;
- struct map_session_data *sd = NULL;
+ char evname[EVENT_NAME_LENGTH];
+
+ snprintf(evname, ARRAYLENGTH(evname), "%s::OnNPCUnload", nd->exname);
+
+ struct event_data *ev = strdb_get(npc->ev_db, evname);
+
+ if (ev != NULL)
+ script->run_npc(nd->u.scr.script, ev->pos, 0, nd->bl.id); /// Run OnNPCUnload.
- if( single ) {
- npc->ev_db->foreach(npc->ev_db,npc->unload_ev,nd->exname); //Clean up all events related
- npc->ev_label_db->foreach(npc->ev_label_db,npc->unload_ev_label,nd);
+ if (single) {
+ npc->ev_db->foreach(npc->ev_db, npc->unload_ev, nd->exname); /// Clean up all related events.
+ npc->ev_label_db->foreach(npc->ev_label_db, npc->unload_ev_label, nd);
}
- iter = mapit_geteachpc();
- for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if (sd->npc_timer_id != INVALID_TIMER ) {
+ struct s_mapiterator *iter = mapit_geteachpc();
+ struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter));
+
+ for (; mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (sd->npc_timer_id != INVALID_TIMER) {
const struct TimerData *td = timer->get(sd->npc_timer_id);
- if( td && td->id != nd->bl.id )
+ if (td != NULL && td->id != nd->bl.id)
continue;
- if( td && td->data )
+ if (td != NULL && td->data != 0)
ers_free(npc->timer_event_ers, (void*)td->data);
+
timer->delete(sd->npc_timer_id, npc->timerevent);
sd->npc_timer_id = INVALID_TIMER;
}
}
+
mapit->free(iter);
if (nd->u.scr.timerid != INVALID_TIMER) {
- const struct TimerData *td;
- td = timer->get(nd->u.scr.timerid);
- if (td && td->data)
+ const struct TimerData *td = timer->get(nd->u.scr.timerid);
+
+ if (td != NULL && td->data != 0)
ers_free(npc->timer_event_ers, (void*)td->data);
+
timer->delete(nd->u.scr.timerid, npc->timerevent);
}
- if (nd->u.scr.timer_event)
+
+ if (nd->u.scr.timer_event != NULL)
aFree(nd->u.scr.timer_event);
+
if (nd->src_id == 0) {
- if(nd->u.scr.script) {
+ if (nd->u.scr.script != NULL) {
script->free_code(nd->u.scr.script);
nd->u.scr.script = NULL;
}
- if (nd->u.scr.label_list) {
+
+ if (nd->u.scr.label_list != NULL) {
aFree(nd->u.scr.label_list);
nd->u.scr.label_list = NULL;
nd->u.scr.label_list_num = 0;
}
- if(nd->u.scr.shop) {
- if(nd->u.scr.shop->item)
+
+ if (nd->u.scr.shop != NULL) {
+ if (nd->u.scr.shop->item != NULL) {
+ for (int i = 0; i < nd->u.scr.shop->items; i ++) {
+ if (nd->u.scr.shop->item[i].currency != NULL)
+ aFree(nd->u.scr.shop->item[i].currency);
+ }
aFree(nd->u.scr.shop->item);
+ }
+
aFree(nd->u.scr.shop);
}
}
- if( nd->u.scr.guild_id )
+
+ if (nd->u.scr.guild_id > 0)
guild->flag_remove(nd);
}
- if( nd->ud && nd->ud != &npc->base_ud ) {
+ if (nd->ud != NULL && nd->ud != &npc->base_ud) {
aFree(nd->ud);
nd->ud = NULL;
}
- HPM->data_store_destroy(&nd->hdata);
+ if (unload_mobs)
+ map->foreachmob(npc->unload_mob, nd->bl.id);
+ HPM->data_store_destroy(&nd->hdata);
aFree(nd);
-
return 0;
}
@@ -2425,7 +3146,7 @@ int npc_unload(struct npc_data* nd, bool single)
//
/// Clears the npc source file list
-void npc_clearsrcfile(void)
+static void npc_clearsrcfile(void)
{
struct npc_src_list* file = npc->src_files;
@@ -2437,24 +3158,22 @@ void npc_clearsrcfile(void)
npc->src_files = NULL;
}
-/// Adds a npc source file (or removes all)
-void npc_addsrcfile(const char* name)
+/**
+ * Adds a npc source file.
+ *
+ * @param name The file name to add.
+ */
+static void npc_addsrcfile(const char *name)
{
struct npc_src_list* file;
struct npc_src_list* file_prev = NULL;
nullpo_retv(name);
- if( strcmpi(name, "clear") == 0 )
- {
- npc->clearsrcfile();
- return;
- }
// prevent multiple insert of source files
file = npc->src_files;
- while( file != NULL )
- {
- if( strcmp(name, file->name) == 0 )
+ while (file != NULL) {
+ if (strcmp(name, file->name) == 0)
return;// found the file, no need to insert it again
file_prev = file;
file = file->next;
@@ -2469,24 +3188,21 @@ void npc_addsrcfile(const char* name)
file_prev->next = file;
}
-/// Removes a npc source file (or all)
-void npc_delsrcfile(const char* name)
+/**
+ * Removes a npc source file.
+ *
+ * @param name The file name to remove.
+ */
+static void npc_delsrcfile(const char *name)
{
struct npc_src_list* file = npc->src_files;
struct npc_src_list* file_prev = NULL;
nullpo_retv(name);
- if( strcmpi(name, "all") == 0 )
- {
- npc->clearsrcfile();
- return;
- }
- while( file != NULL )
- {
- if( strcmp(file->name, name) == 0 )
- {
- if( npc->src_files == file )
+ while (file != NULL) {
+ if (strcmp(file->name, name) == 0) {
+ if (npc->src_files == file)
npc->src_files = file->next;
else
file_prev->next = file->next;
@@ -2504,15 +3220,15 @@ void npc_delsrcfile(const char* name)
* @param filepath The file path to retain.
* @return A retained reference to filepath.
*/
-const char *npc_retainpathreference(const char *filepath)
+static const char *npc_retainpathreference(const char *filepath)
{
struct npc_path_data * npd = NULL;
nullpo_ret(filepath);
- if (npc_last_path == filepath) {
- if (npc_last_npd != NULL)
- npc_last_npd->references++;
- return npc_last_ref;
+ if (npc->npc_last_path == filepath) {
+ if (npc->npc_last_npd != NULL)
+ npc->npc_last_npd->references++;
+ return npc->npc_last_ref;
}
if ((npd = strdb_get(npc->path_db,filepath)) == NULL) {
@@ -2527,9 +3243,9 @@ const char *npc_retainpathreference(const char *filepath)
npd->references++;
- npc_last_npd = npd;
- npc_last_ref = npd->path;
- npc_last_path = filepath;
+ npc->npc_last_npd = npd;
+ npc->npc_last_ref = npd->path;
+ npc->npc_last_path = filepath;
return npd->path;
}
@@ -2539,13 +3255,13 @@ const char *npc_retainpathreference(const char *filepath)
*
* @param filepath The file path to release.
*/
-void npc_releasepathreference(const char *filepath)
+static void npc_releasepathreference(const char *filepath)
{
struct npc_path_data* npd = NULL;
nullpo_retv(filepath);
- if (filepath != npc_last_ref) {
+ if (filepath != npc->npc_last_ref) {
npd = strdb_get(npc->path_db, filepath);
}
@@ -2558,7 +3274,8 @@ void npc_releasepathreference(const char *filepath)
/// Parses and sets the name and exname of a npc.
/// Assumes that m, x and y are already set in nd.
-void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) {
+static void npc_parsename(struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath)
+{
const char* p;
struct npc_data* dnd;// duplicate npc
char newname[NAME_LENGTH];
@@ -2601,7 +3318,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
do {
++i;
- snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y);
+ safesnprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y);
} while( npc->name2id(newname) != NULL );
strcpy(this_mapname, (nd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(nd->bl.m))));
@@ -2616,7 +3333,8 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
// Parse View
// Support for using Constants in place of NPC View IDs.
-int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) {
+static int npc_parseview(const char *w4, const char *start, const char *buffer, const char *filepath)
+{
int val = FAKE_NPC, i = 0;
char viewid[1024]; // Max size of name from constants.conf, see script->read_constdb.
@@ -2650,7 +3368,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c
// View is ID
// Checks if given view is an ID or constant.
-bool npc_viewisid(const char * viewid)
+static bool npc_viewisid(const char *viewid)
{
nullpo_retr(false, viewid);
if (atoi(viewid) != FAKE_NPC) {
@@ -2674,7 +3392,7 @@ bool npc_viewisid(const char * viewid)
* @param class_ The NPC view class.
* @return A pointer to the created NPC data (ownership passed to the caller).
*/
-struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, uint8 dir, int16 class_)
+static struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_)
{
struct npc_data *nd;
@@ -2690,12 +3408,15 @@ struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, u
nd->area_size = AREA_SIZE + 1;
nd->class_ = class_;
nd->speed = 200;
+ nd->vd = npc_viewdb[0]; // Copy INVISIBLE_CLASS view data. Actual view data is set by npc->add_to_location() later.
+ VECTOR_INIT(nd->qi_data);
return nd;
}
//Add then display an npc warp on map
-struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) {
+static struct npc_data *npc_add_warp(char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y)
+{
int i, flag = 0;
struct npc_data *nd;
@@ -2708,10 +3429,10 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
flag = 1;
if (flag == 1)
- snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y);
+ safesnprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y);
for( i = 0; npc->name2id(nd->exname) != NULL; ++i )
- snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y);
+ safesnprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y);
safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name));
nd->u.warp.mapindex = to_mapindex;
@@ -2742,7 +3463,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const 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;
@@ -2785,7 +3506,7 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const
nd->u.warp.y = to_y;
nd->u.warp.xs = xs;
nd->u.warp.ys = ys;
- npc_warp++;
+ npc->npc_warp++;
npc->add_to_location(nd);
@@ -2809,7 +3530,7 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
//TODO: could be rewritten to NOT need this temp array [ultramage]
// We could use nd->u.shop.shop_item to store directly the items, but this could lead
@@ -2818,7 +3539,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const
struct npc_item_list *items = NULL;
size_t items_count = 40; // Starting items size
- char *p;
+ const char *p;
int x, y, dir, m, i, class_;
struct npc_data *nd;
enum npc_subtype type;
@@ -2930,13 +3651,14 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const
npc->parsename(nd, w3, start, buffer, filepath);
nd->path = npc->retainpathreference(filepath);
- ++npc_shop;
+ ++npc->npc_shop;
npc->add_to_location(nd);
return strchr(start,'\n');// continue
}
-void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) {
+static void npc_convertlabel_db(struct npc_label_list *label_list, const char *filepath)
+{
int i;
nullpo_retv(label_list);
@@ -2968,7 +3690,8 @@ 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, int *retval) {
+static const char *npc_skip_script(const char *start, const char *buffer, const char *filepath, int *retval)
+{
const char* p;
int curly_count;
@@ -3054,7 +3777,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_script(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval)
+static const char *npc_parse_script(const char *w1, const char *w2, const char *w3, const 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
struct script_code *scriptroot;
@@ -3136,7 +3859,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con
if( options&NPO_TRADER )
nd->u.scr.trader = true;
nd->u.scr.shop = NULL;
- ++npc_script;
+ ++npc->npc_script;
npc->add_to_location(nd);
//-----------------------------------------
@@ -3174,7 +3897,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con
*
* @param nd The NPC to register.
*/
-void npc_add_to_location(struct npc_data *nd)
+static void npc_add_to_location(struct npc_data *nd)
{
nullpo_retv(nd);
@@ -3198,7 +3921,7 @@ void npc_add_to_location(struct npc_data *nd)
/**
* Duplicates a script (@see npc_duplicate_sub)
*/
-bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
+static bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
int i;
bool retval = true;
@@ -3206,7 +3929,7 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_script;
+ ++npc->npc_script;
nd->u.scr.xs = xs;
nd->u.scr.ys = ys;
nd->u.scr.script = snd->u.scr.script;
@@ -3248,12 +3971,12 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i
/**
* Duplicates a shop or cash shop (@see npc_duplicate_sub)
*/
-bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
+static bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_shop;
+ ++npc->npc_shop;
nd->u.shop.shop_item = snd->u.shop.shop_item;
nd->u.shop.count = snd->u.shop.count;
@@ -3266,12 +3989,12 @@ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int
/**
* Duplicates a warp (@see npc_duplicate_sub)
*/
-bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
+static bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_warp;
+ ++npc->npc_warp;
nd->u.warp.xs = xs;
nd->u.warp.ys = ys;
nd->u.warp.mapindex = snd->u.warp.mapindex;
@@ -3298,7 +4021,7 @@ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int
* @param options The NPC options.
* @retval false if there were any issues while creating and validating the NPC.
*/
-bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
+static bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
nullpo_retr(false, nd);
nullpo_retr(false, snd);
@@ -3356,7 +4079,7 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs,
* @remark
* Only `NPO_ONINIT` is available trough the options argument.
*/
-const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval)
+static const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3, const 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 srcname[128];
@@ -3448,7 +4171,7 @@ const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3,
* @return success state.
* @retval 0 in case of successful creation.
*/
-int npc_duplicate4instance(struct npc_data *snd, int16 m)
+static int npc_duplicate4instance(struct npc_data *snd, int16 m)
{
char newname[NAME_LENGTH];
int dm = -1, im = -1, xs = -1, ys = -1;
@@ -3504,7 +4227,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m)
}
//Set mapcell CELL_NPC to trigger event later
-void npc_setcells(struct npc_data* nd)
+static void npc_setcells(struct npc_data *nd)
{
int16 m, x, y, xs, ys;
int i,j;
@@ -3538,7 +4261,7 @@ void npc_setcells(struct npc_data* nd)
}
}
-int npc_unsetcells_sub(struct block_list *bl, va_list ap)
+static int npc_unsetcells_sub(struct block_list *bl, va_list ap)
{
struct npc_data *nd = NULL;
int id = va_arg(ap, int);
@@ -3553,7 +4276,8 @@ int npc_unsetcells_sub(struct block_list *bl, va_list ap)
return 1;
}
-void npc_unsetcells(struct npc_data* nd) {
+static void npc_unsetcells(struct npc_data *nd)
+{
int16 m, x, y, xs, ys;
int i,j, x0, x1, y0, y1;
@@ -3593,7 +4317,7 @@ void npc_unsetcells(struct npc_data* nd) {
map->foreachinarea( npc->unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id );
}
-void npc_movenpc(struct npc_data* nd, int16 x, int16 y)
+static void npc_movenpc(struct npc_data *nd, int16 x, int16 y)
{
int16 m;
nullpo_retv(nd);
@@ -3612,21 +4336,22 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y)
///
/// @param nd Target npc
/// @param newname New display name
-void npc_setdisplayname(struct npc_data* nd, const char* newname)
+static void npc_setdisplayname(struct npc_data *nd, const char *newname)
{
nullpo_retv(nd);
nullpo_retv(newname);
safestrncpy(nd->name, newname, sizeof(nd->name));
if( map->list[nd->bl.m].users )
- clif->charnameack(0, &nd->bl);
+ clif->blname_ack(0, &nd->bl);
}
/// Changes the display class of the npc.
///
/// @param nd Target npc
/// @param class_ New display class
-void npc_setclass(struct npc_data* nd, short class_) {
+static void npc_setclass(struct npc_data *nd, int class_)
+{
nullpo_retv(nd);
if( nd->class_ == class_ )
@@ -3640,8 +4365,20 @@ void npc_setclass(struct npc_data* nd, short class_) {
clif->spawn(&nd->bl);// fade in
}
+static void npc_refresh(struct npc_data *nd)
+{
+ nullpo_retv(nd);
+
+ if (map->list[nd->bl.m].users) {
+ // using here CLR_TRICKDEAD because other flags show effects.
+ // probably need use other flag or other way to refresh npc.
+ clif->clearunit_area(&nd->bl, CLR_TRICKDEAD); // fade out
+ clif->spawn(&nd->bl); // fade in
+ }
+}
+
// @commands (script based)
-int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname)
+static int npc_do_atcmd_event(struct map_session_data *sd, const char *command, const char *message, const char *eventname)
{
struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname);
struct npc_data *nd;
@@ -3728,7 +4465,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_function(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_function(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
struct DBMap *func_db;
struct DBData old_data;
@@ -3770,25 +4507,30 @@ const char *npc_parse_function(const char *w1, const char *w2, const char *w3, c
struct script_code *oldscript = (struct script_code*)DB->data2ptr(&old_data);
ShowWarning("npc_parse_function: Overwriting user function [%s] in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
script->free_vars(oldscript->local.vars);
- aFree(oldscript->script_buf);
+ VECTOR_CLEAR(oldscript->script_buf);
aFree(oldscript);
}
return end;
}
-/*==========================================
- * Parse Mob 1 - Parse mob list into each map
- * Parse Mob 2 - Actually Spawns Mob
- * [Wizputer]
- *------------------------------------------*/
-void npc_parse_mob2(struct spawn_data* mobspawn)
+/**
+ * Spawns a mob by using the passed spawn data. (Permanent mob spawns.)
+ * npc_parse_mob() - Parses mob list into each map.
+ * npc_parse_mob2() - Actually spawns mob.
+ *
+ * @param mobspawn The mobs spawn data.
+ *
+ * @author Wizputer
+ *
+ **/
+static void npc_parse_mob2(struct spawn_data *mobspawn)
{
- int i;
-
nullpo_retv(mobspawn);
- for( i = mobspawn->active; i < mobspawn->num; ++i ) {
- struct mob_data* md = mob->spawn_dataset(mobspawn);
+
+ for (int i = mobspawn->active; i < mobspawn->num; ++i) {
+ struct mob_data *md = mob->spawn_dataset(mobspawn, 0);
+
md->spawn = mobspawn;
md->spawn->active++;
mob->spawn(md);
@@ -3812,7 +4554,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn)
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const 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;
@@ -3827,7 +4569,12 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
memset(&mobspawn, 0, sizeof(struct spawn_data));
- mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0);
+ if (strcmp(w2, "boss_monster") == 0)
+ mobspawn.state.boss = BTYPE_MVP;
+ else if (strcmp(w2, "miniboss_monster") == 0)
+ mobspawn.state.boss = BTYPE_BOSS;
+ else
+ mobspawn.state.boss = BTYPE_NONE;
// w1=<map name>,<x>,<y>,<xs>,<ys>
// w3=<mob name>{,<mob level>}
@@ -3889,7 +4636,7 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
mobspawn.num = (unsigned short)num;
mobspawn.active = 0;
- mobspawn.class_ = (short) class_;
+ mobspawn.class_ = class_;
mobspawn.x = (unsigned short)x;
mobspawn.y = (unsigned short)y;
mobspawn.xs = (signed short)xs;
@@ -3919,10 +4666,10 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
}
//Use db names instead of the spawn file ones.
- if(battle_config.override_mob_names==1)
- strcpy(mobspawn.name,"--en--");
- else if (battle_config.override_mob_names==2)
- strcpy(mobspawn.name,"--ja--");
+ if (battle_config.override_mob_names == 1)
+ strcpy(mobspawn.name, DEFAULT_MOB_NAME);
+ else if (battle_config.override_mob_names == 2)
+ strcpy(mobspawn.name, DEFAULT_MOB_JNAME);
else
safestrncpy(mobspawn.name, mobname, sizeof(mobspawn.name));
@@ -3967,7 +4714,7 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
// spawn / cache the new mobs
if( battle_config.dynamic_mobs && map->addmobtolist(data->m, data) >= 0 ) {
data->state.dynamic = true;
- npc_cache_mob += data->num;
+ npc->npc_cache_mob += data->num;
// check if target map has players
// (usually shouldn't occur when map server is just starting,
@@ -3978,10 +4725,10 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
} else {
data->state.dynamic = false;
npc->parse_mob2(data);
- npc_delay_mob += data->num;
+ npc->npc_delay_mob += data->num;
}
- npc_mob++;
+ npc->npc_mob++;
return strchr(start,'\n');// continue
}
@@ -3993,7 +4740,7 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
*
* @see npc_parse_mapflag
*/
-void npc_parse_unknown_mapflag(const char *name, const char *w3, const char *w4, const char* start, const char* buffer, const char* filepath, int *retval)
+static void npc_parse_unknown_mapflag(const char *name, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
if (retval)
@@ -4025,7 +4772,7 @@ void npc_parse_unknown_mapflag(const char *name, const char *w3, const char *w4,
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
int16 m;
char mapname[32];
@@ -4055,8 +4802,7 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
if (!strcmpi(w3, "nosave")) {
char savemap[32];
int savex, savey;
- if (state == 0)
- ; //Map flag disabled.
+ if (state == 0); //Map flag disabled.
else if (w4 && !strcmpi(w4, "SavePoint")) {
map->list[m].save.map = 0;
map->list[m].save.x = -1;
@@ -4108,6 +4854,11 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
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.cvc) {
+ map->list[m].flag.cvc = 0;
+ ShowWarning("npc_parse_mapflag: You can't set CvC and PvP flags for the same map! Removing CvC 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 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));
@@ -4160,6 +4911,11 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
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.cvc) {
+ map->list[m].flag.cvc = 0;
+ ShowWarning("npc_parse_mapflag: You can't set CvC and GvG flags for the same map! Removing CvC 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));
@@ -4202,11 +4958,47 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
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 (map->list[m].flag.cvc) {
+ map->list[m].flag.cvc = 0;
+ ShowWarning("npc_parse_mapflag: You can't set CvC and BattleGround flags for the same map! Removing CvC 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)) != NULL && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
}
}
+ else if (!strcmpi(w3, "cvc")) {
+ struct map_zone_data *zone;
+
+ map->list[m].flag.cvc = state;
+ if (state && (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 CvC 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 && map->list[m].flag.pvp) {
+ map->list[m].flag.pvp = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and CvC 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 CvC 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_CVC_NAME)) != NULL && map->list[m].zone != zone) {
+ map->zone_change(m, zone, start, buffer, filepath);
+ }
+ }
else if (!strcmpi(w3,"noexppenalty"))
map->list[m].flag.noexppenalty=state;
else if (!strcmpi(w3,"nozenypenalty"))
@@ -4284,6 +5076,8 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
map->list[m].flag.reset=state;
else if (!strcmpi(w3,"notomb"))
map->list[m].flag.notomb=state;
+ else if (!strcmpi(w3, "noautoloot"))
+ map->list[m].flag.noautoloot = state;
else if (!strcmpi(w3,"adjust_unit_duration")) {
int skill_id, k;
char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
@@ -4301,7 +5095,8 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
}
}
- if( modifier[0] == '\0' ) {
+ if (state == 0); //Map flag disabled.
+ else 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) ) {
@@ -4360,7 +5155,8 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
}
}
- if( modifier[0] == '\0' ) {
+ if (state == 0); //Map flag disabled.
+ else 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) ) ) {
@@ -4432,6 +5228,14 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
map->list[m].flag.nocashshop = (state) ? 1 : 0;
} else if (!strcmpi(w3,"noviewid")) {
map->list[m].flag.noviewid = (state) ? atoi(w4) : 0;
+ } else if (!strcmpi(w3, "pairship_startable")) {
+ map->list[m].flag.pairship_startable = (state) ? 1 : 0;
+ } else if (!strcmpi(w3, "pairship_endable")) {
+ map->list[m].flag.pairship_endable = (state) ? 1 : 0;
+ } else if (!strcmpi(w3, "nostorage")) {
+ map->list[m].flag.nostorage = (state) ? cap_value(atoi(w4), 1, 3) : 0;
+ } else if (!strcmpi(w3, "nogstorage")) {
+ map->list[m].flag.nogstorage = (state) ? cap_value(atoi(w4), 1, 3) : 0;
} else {
npc->parse_unknown_mapflag(mapname, w3, w4, start, buffer, filepath, retval);
}
@@ -4456,7 +5260,7 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
* (EXIT_FAILURE) status. May be NULL.
* @return A pointer to the advanced buffer position.
*/
-const char *npc_parse_unknown_object(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
+static const char *npc_parse_unknown_object(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
nullpo_retr(start, retval);
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,start-buffer), w1, w2, w3, w4);
@@ -4474,7 +5278,8 @@ const char *npc_parse_unknown_object(const char *w1, const char *w2, const char
* @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) {
+static int npc_parsesrcfile(const char *filepath, bool runOnInit)
+{
int success = EXIT_SUCCESS;
int16 m, x, y;
int lines = 0;
@@ -4644,7 +5449,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
{
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) )
+ else if (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0 || strcmp(w2,"miniboss_monster") == 0)
{
p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath, &success);
}
@@ -4662,7 +5467,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
return success;
}
-int npc_script_event(struct map_session_data* sd, enum npce_event type)
+static int npc_script_event(struct map_session_data *sd, enum npce_event type)
{
int i;
if (type == NPCE_MAX)
@@ -4676,7 +5481,7 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type)
return i;
}
-void npc_read_event_script(void)
+static void npc_read_event_script(void)
{
int i;
struct {
@@ -4739,7 +5544,7 @@ void npc_read_event_script(void)
/**
* @see DBApply
*/
-int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
+static int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
struct npc_path_data *npd = DB->data2ptr(data);
nullpo_ret(npd);
@@ -4751,7 +5556,7 @@ int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
/**
* @see DBApply
*/
-int npc_ev_label_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
+static int npc_ev_label_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
struct linkdb_node **label_linkdb = DB->data2ptr(data);
linkdb_final(label_linkdb); // linked data (struct event_data*) is freed when clearing ev_db
@@ -4762,7 +5567,8 @@ int npc_ev_label_db_clear_sub(union DBKey key, struct DBData *data, va_list args
* 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 ) {
+static void npc_process_files(int npc_min)
+{
struct npc_src_list *file; // Current file
ShowStatus("Loading NPCs...\r");
@@ -4778,133 +5584,153 @@ void npc_process_files( int npc_min ) {
"\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);
+ npc->npc_id - npc_min, npc->npc_warp, npc->npc_shop, npc->npc_script, npc->npc_mob, npc->npc_cache_mob, npc->npc_delay_mob);
}
-//Clear then reload npcs files
-int npc_reload(void) {
- 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();
+/**
+ * Clears and then reloads all NPC files.
+ *
+ * @return Always 0.
+ *
+ **/
+static int npc_reload(void)
+{
+ if (map->retval == EXIT_FAILURE) /// Clear return status in case something failed before.
+ map->retval = EXIT_SUCCESS;
+ guild->flags_clear(); /// Clear guild flag cache.
npc->path_db->clear(npc->path_db, npc->path_db_clear_sub);
-
db_clear(npc->name_db);
db_clear(npc->ev_db);
npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub);
+ npc->npc_last_npd = NULL;
+ npc->npc_last_path = NULL;
+ npc->npc_last_ref = NULL;
+
+ const int npc_new_min = npc->npc_id;
+ struct s_mapiterator *iter = mapit_geteachiddb();
+
+ /** Remove all NPCs/mobs. [Skotlex] **/
+ for (struct block_list *bl = mapit->first(iter); mapit->exists(iter); bl = mapit->next(iter)) {
+ switch (bl->type) {
+ case BL_NPC:
+ if (bl->id != npc->fake_nd->bl.id) /// Don't remove fake_nd.
+ npc->unload(BL_UCAST(BL_NPC, bl), false, false);
- npc_last_npd = NULL;
- npc_last_path = NULL;
- npc_last_ref = NULL;
-
- //Remove all npcs/mobs. [Skotlex]
- iter = mapit_geteachiddb();
- for (bl = mapit->first(iter); mapit->exists(iter); bl = mapit->next(iter)) {
- switch(bl->type) {
- case BL_NPC:
- if( bl->id != npc->fake_nd->bl.id )// don't remove fake_nd
- npc->unload(BL_UCAST(BL_NPC, bl), false);
- break;
- case BL_MOB:
- unit->free(bl,CLR_OUTSIGHT);
- break;
+ break;
+ case BL_MOB:
+ unit->free(bl, CLR_OUTSIGHT);
+ break;
+ default:
+ break;
}
}
+
mapit->free(iter);
- if(battle_config.dynamic_mobs) {// dynamic check by [random]
- int16 m;
- for (m = 0; m < map->count; m++) {
- int16 i;
- for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
+ if (battle_config.dynamic_mobs) { /// Dynamic check. [random]
+ for (int m = 0; m < map->count; m++) {
+ for (int i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
if (map->list[m].moblist[i] != NULL) {
aFree(map->list[m].moblist[i]);
map->list[m].moblist[i] = NULL;
}
- if( map->list[m].mob_delete_timer != INVALID_TIMER )
- { // Mobs were removed anyway,so delete the timer [Inkfish]
+
+ if (map->list[m].mob_delete_timer != INVALID_TIMER) { /// Mobs were removed anyway, so delete the timer. [Inkfish]
timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer);
map->list[m].mob_delete_timer = INVALID_TIMER;
}
}
+
if (map->list[m].npc_num > 0)
- ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map->list[m].npc_num, map->list[m].name);
+ ShowWarning("npc_reload: %d NPCs weren't removed from map %s!\n",
+ map->list[m].npc_num, map->list[m].name);
}
}
- // clear mob spawn lookup index
mob->clear_spawninfo();
-
- npc_warp = npc_shop = npc_script = 0;
- npc_mob = npc_cache_mob = npc_delay_mob = 0;
-
- // reset mapflags
+ npc->npc_warp = 0;
+ npc->npc_shop = 0;
+ npc->npc_script = 0;
+ npc->npc_mob = 0;
+ npc->npc_cache_mob = 0;
+ npc->npc_delay_mob = 0;
+ map->zone_reload();
map->flags_init();
-
- // Reprocess npc files and reload constants
itemdb->name_constants();
- npc_process_files( npc_new_min );
-
+ clan->set_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->motd = npc->name2id("HerculesMOTD"); /// [Ind/Hercules]
npc->read_event_script();
- // Execute main initialisation events
- // The correct initialisation order is:
- // OnInit -> OnInterIfInit -> OnInterIfInitOnce -> OnAgitInit -> OnAgitInit2
- npc->event_do_oninit( true );
+ /**
+ * Execute main initialization events
+ * The correct initialization 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]
- // 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->barter_fromsql();
+ npc->expanded_barter_fromsql();
+
+ /*
+ * Execute rest of the startup events if connected to char-server. [Lance]
+ * Executed when connection is established with char-server in chrif_connectack().
+ */
+ if (intif->CheckForCharServer() == 0) {
+ 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;
}
-//Unload all npc in the given file
-bool npc_unloadfile(const char *filepath)
+/**
+ * Unloads all NPCs in the given file.
+ *
+ * @param filepath Path to the file which should be unloaded.
+ * @param unload_mobs If true, mobs spawned by NPCs in the file will be removed.
+ * @return true if at least one NPC was unloaded, otherwise false.
+ *
+ **/
+static bool npc_unloadfile(const char *filepath, bool unload_mobs)
{
+ nullpo_retr(false, filepath);
+
struct DBIterator *iter = db_iterator(npc->name_db);
- struct npc_data* nd = NULL;
bool found = false;
- nullpo_retr(false, filepath);
-
- for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) {
- if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems
+ for (struct npc_data *nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter)) {
+ if (nd->path != NULL && strcasecmp(nd->path, filepath) == 0) { // FIXME: This can break in case-sensitive file systems.
found = true;
- npc->unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */
- npc->unload(nd, true);
+ npc->unload_duplicates(nd, unload_mobs); /// Unload any NPC which could duplicate this but be in a different file.
+ npc->unload(nd, true, unload_mobs);
}
}
dbi_destroy(iter);
- if( found ) /* refresh event cache */
+ if (found) /// Refresh event cache.
npc->read_event_script();
return found;
}
-void do_clear_npc(void) {
+static void do_clear_npc(void)
+{
db_clear(npc->name_db);
db_clear(npc->ev_db);
npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub);
@@ -4913,7 +5739,8 @@ void do_clear_npc(void) {
/*==========================================
* Destructor
*------------------------------------------*/
-int do_final_npc(void) {
+static int do_final_npc(void)
+{
db_destroy(npc->ev_db);
npc->ev_label_db->destroy(npc->ev_label_db, npc->ev_label_db_clear_sub);
db_destroy(npc->name_db);
@@ -4924,7 +5751,8 @@ int do_final_npc(void) {
return 0;
}
-void npc_debug_warps_sub(struct npc_data* nd) {
+static void npc_debug_warps_sub(struct npc_data *nd)
+{
int16 m;
nullpo_retv(nd);
@@ -4952,49 +5780,57 @@ void npc_debug_warps_sub(struct npc_data* nd) {
}
}
-static void npc_debug_warps(void) {
+static void npc_debug_warps(void)
+{
int16 m, i;
for (m = 0; m < map->count; m++)
for (i = 0; i < map->list[m].npc_num; i++)
npc->debug_warps_sub(map->list[m].npc[i]);
}
+static void npc_questinfo_clear(struct npc_data *nd)
+{
+ nullpo_retv(nd);
+
+ for (int i = 0; i < VECTOR_LENGTH(nd->qi_data); i++) {
+ struct questinfo *qi = &VECTOR_INDEX(nd->qi_data, i);
+ VECTOR_CLEAR(qi->items);
+ VECTOR_CLEAR(qi->quest_requirement);
+ }
+ VECTOR_CLEAR(nd->qi_data);
+}
+
/*==========================================
* npc initialization
*------------------------------------------*/
-int do_init_npc(bool minimal) {
+static int do_init_npc(bool minimal)
+{
int i;
- memset(&npc->base_ud, 0, sizeof( struct unit_data) );
- npc->base_ud.bl = NULL;
- npc->base_ud.walktimer = INVALID_TIMER;
- npc->base_ud.skilltimer = INVALID_TIMER;
- npc->base_ud.attacktimer = INVALID_TIMER;
- npc->base_ud.attackabletime =
- npc->base_ud.canact_tick =
- npc->base_ud.canmove_tick = timer->gettick();
+ unit->init_ud(&npc->base_ud);
+ npc->base_ud.bl = NULL;
//Stock view data for normal npcs.
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
- npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here.
+ npc_viewdb[0].class = INVISIBLE_CLASS; //Invisible class is stored here.
for( i = 1; i < MAX_NPC_CLASS; i++ )
- npc_viewdb[i].class_ = i;
+ npc_viewdb[i].class = i;
for( i = MAX_NPC_CLASS2_START; i < MAX_NPC_CLASS2_END; i++ )
- npc_viewdb2[i - MAX_NPC_CLASS2_START].class_ = i;
-
+ npc_viewdb2[i - MAX_NPC_CLASS2_START].class = i;
npc->ev_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, EVENT_NAME_LENGTH);
npc->ev_label_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, NAME_LENGTH);
npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH);
npc->path_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
- npc_last_npd = NULL;
- npc_last_path = NULL;
- npc_last_ref = NULL;
+ npc->npc_last_npd = NULL;
+ npc->npc_last_path = NULL;
+ npc->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();
+ clan->set_constants();
if (!minimal) {
npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
@@ -5019,12 +5855,6 @@ int do_init_npc(bool minimal) {
timer->add_func_list(npc->timerevent,"npc_timerevent");
}
- if( script->lang_export_fp ) {
- ShowInfo("Lang exported to '%s'\n",script->lang_export_file);
- fclose(script->lang_export_fp);
- script->lang_export_fp = NULL;
- }
-
// Init dummy NPC
CREATE(npc->fake_nd, struct npc_data, 1);
npc->fake_nd->bl.m = -1;
@@ -5034,7 +5864,7 @@ int do_init_npc(bool minimal) {
strcpy(npc->fake_nd->name,"FAKE_NPC");
memcpy(npc->fake_nd->exname, npc->fake_nd->name, 9);
- npc_script++;
+ npc->npc_script++;
npc->fake_nd->bl.type = BL_NPC;
npc->fake_nd->subtype = SCRIPT;
@@ -5045,9 +5875,21 @@ int do_init_npc(bool minimal) {
return 0;
}
-void npc_defaults(void) {
+void npc_defaults(void)
+{
npc = &npc_s;
+ npc->npc_id = START_NPC_NUM;
+ npc->npc_warp = 0;
+ npc->npc_shop = 0;
+ npc->npc_script = 0;
+ npc->npc_mob = 0;
+ npc->npc_delay_mob = 0;
+ npc->npc_cache_mob = 0;
+ npc->npc_last_path = NULL;
+ npc->npc_last_ref = NULL;
+ npc->npc_last_npd = NULL;
+
npc->motd = NULL;
npc->ev_db = NULL;
npc->ev_label_db = NULL;
@@ -5114,6 +5956,7 @@ void npc_defaults(void) {
npc->unload_ev_label = npc_unload_ev_label;
npc->unload_dup_sub = npc_unload_dup_sub;
npc->unload_duplicates = npc_unload_duplicates;
+ npc->unload_mob = npc_unload_mob;
npc->unload = npc_unload;
npc->clearsrcfile = npc_clearsrcfile;
npc->addsrcfile = npc_addsrcfile;
@@ -5166,10 +6009,22 @@ void npc_defaults(void) {
npc->trader_pay = npc_trader_pay;
npc->trader_update = npc_trader_update;
npc->market_buylist = npc_market_buylist;
+ npc->barter_buylist = npc_barter_buylist;
+ npc->expanded_barter_buylist = npc_expanded_barter_buylist;
npc->trader_open = npc_trader_open;
npc->market_fromsql = npc_market_fromsql;
npc->market_tosql = npc_market_tosql;
npc->market_delfromsql = npc_market_delfromsql;
npc->market_delfromsql_sub = npc_market_delfromsql_sub;
+ npc->barter_fromsql = npc_barter_fromsql;
+ npc->barter_tosql = npc_barter_tosql;
+ npc->barter_delfromsql = npc_barter_delfromsql;
+ npc->barter_delfromsql_sub = npc_barter_delfromsql_sub;
+ npc->expanded_barter_fromsql = npc_expanded_barter_fromsql;
+ npc->expanded_barter_tosql = npc_expanded_barter_tosql;
+ npc->expanded_barter_delfromsql = npc_expanded_barter_delfromsql;
+ npc->expanded_barter_delfromsql_sub = npc_expanded_barter_delfromsql_sub;
npc->db_checkid = npc_db_checkid;
+ npc->refresh = npc_refresh;
+ npc->questinfo_clear = npc_questinfo_clear;
}
diff --git a/src/map/npc.h b/src/map/npc.h
index 8ee59e410..1585a2bc8 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,6 +34,8 @@ struct hplugin_data_store;
struct itemlist; // map/itemdb.h
struct view_data;
+enum market_buy_result;
+
enum npc_parse_options {
NPO_NONE = 0x0,
NPO_ONINIT = 0x1,
@@ -41,10 +43,12 @@ enum npc_parse_options {
};
enum npc_shop_types {
- NST_ZENY,/* default */
- NST_CASH,/* official npc cash shop */
- NST_MARKET,/* official npc market type */
+ NST_ZENY, /* default */
+ NST_CASH, /* official npc cash shop */
+ NST_MARKET, /* official npc market type */
NST_CUSTOM,
+ NST_BARTER, /* official npc barter type */
+ NST_EXPANDED_BARTER, /* official npc expanded barter type */
/* */
NST_MAX,
};
@@ -56,33 +60,46 @@ struct npc_label_list {
char name[NAME_LENGTH];
int pos;
};
+
+struct npc_barter_currency {
+ int nameid;
+ int refine;
+ int amount;
+};
+
struct npc_item_list {
- unsigned short nameid;
- unsigned int value;
- unsigned int qty;
+ int nameid;
+ unsigned int value; // price or barter currency item id
+ int value2; // barter currency item amount / expanded barter currency size
+ int qty;
+ struct npc_barter_currency *currency;
};
+
struct npc_shop_data {
unsigned char type;/* what am i */
struct npc_item_list *item;/* list */
- unsigned short items;/* total */
+ unsigned int items;/* total */
+ int shop_last_index; // only for NST_EXPANDED_BARTER
};
struct npc_parse;
struct npc_data {
struct block_list bl;
struct unit_data *ud;
- struct view_data *vd;
+ struct view_data vd;
unsigned int option;
struct npc_data *master_nd;
- short class_;
+ int class_;
short speed;
char name[NAME_LENGTH+1];// display name
char exname[NAME_LENGTH+1];// unique npc name
int chat_id;
int touching_id;
int64 next_walktime;
- uint8 dir;
+ enum unit_dir dir;
uint8 area_size;
+ int clan_id;
+
unsigned size : 2;
struct status_data status;
@@ -120,12 +137,13 @@ struct npc_data {
struct mob_data *md;
time_t kill_time;
char killer_name[NAME_LENGTH];
+ int spawn_timer;
} tomb;
} u;
+ VECTOR_DECL(struct questinfo) qi_data;
struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
-
#define START_NPC_NUM 110000000
enum actor_classes {
@@ -142,7 +160,7 @@ enum actor_classes {
#define MAX_NPC_CLASS 1000
// New NPC range
#define MAX_NPC_CLASS2_START 10001
-#define MAX_NPC_CLASS2_END 10203
+#define MAX_NPC_CLASS2_END 10344
//Script NPC events.
enum npce_event {
@@ -188,6 +206,16 @@ struct npc_interface {
/* npc trader global data, for ease of transition between the script, cleared on every usage */
bool trader_ok;
int trader_funds[2];
+ int npc_id;
+ int npc_warp;
+ int npc_shop;
+ int npc_script;
+ int npc_mob;
+ int npc_delay_mob;
+ int npc_cache_mob;
+ const char *npc_last_path;
+ const char *npc_last_ref;
+ struct npc_path_data *npc_last_npd;
/* */
int (*init) (bool minimal);
int (*final) (void);
@@ -242,8 +270,9 @@ struct npc_interface {
int (*unload_ev) (union DBKey key, struct DBData *data, va_list ap);
int (*unload_ev_label) (union DBKey key, struct DBData *data, va_list ap);
int (*unload_dup_sub) (struct npc_data *nd, va_list args);
- void (*unload_duplicates) (struct npc_data *nd);
- int (*unload) (struct npc_data *nd, bool single);
+ void (*unload_duplicates) (struct npc_data *nd, bool unload_mobs);
+ int (*unload_mob) (struct mob_data *md, va_list args);
+ int (*unload) (struct npc_data *nd, bool single, bool unload_mobs);
void (*clearsrcfile) (void);
void (*addsrcfile) (const char *name);
void (*delsrcfile) (const char *name);
@@ -252,7 +281,7 @@ struct npc_interface {
void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath);
int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath);
bool (*viewisid) (const char *viewid);
- struct npc_data *(*create_npc) (enum npc_subtype subtype, int m, int x, int y, uint8 dir, int16 class_);
+ struct npc_data *(*create_npc) (enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_);
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) (const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char *(*parse_shop) (const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
@@ -272,7 +301,7 @@ struct npc_interface {
void (*unsetcells) (struct npc_data *nd);
void (*movenpc) (struct npc_data *nd, int16 x, int16 y);
void (*setdisplayname) (struct npc_data *nd, const char *newname);
- void (*setclass) (struct npc_data *nd, short class_);
+ void (*setclass) (struct npc_data *nd, int class_);
int (*do_atcmd_event) (struct map_session_data *sd, const char *command, const char *message, const char *eventname);
const char *(*parse_function) (const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
void (*parse_mob2) (struct spawn_data *mobspawn);
@@ -285,7 +314,7 @@ struct npc_interface {
int (*path_db_clear_sub) (union DBKey key, struct DBData *data, va_list args);
int (*ev_label_db_clear_sub) (union DBKey key, struct DBData *data, va_list args);
int (*reload) (void);
- bool (*unloadfile) (const char *filepath);
+ bool (*unloadfile) (const char *filepath, bool unload_mobs);
void (*do_clear_npc) (void);
void (*debug_warps_sub) (struct npc_data *nd);
void (*debug_warps) (void);
@@ -293,13 +322,25 @@ struct npc_interface {
void (*trader_count_funds) (struct npc_data *nd, struct map_session_data *sd);
bool (*trader_pay) (struct npc_data *nd, struct map_session_data *sd, int price, int points);
void (*trader_update) (int master);
- int (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list);
+ enum market_buy_result (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list);
+ int (*barter_buylist) (struct map_session_data *sd, struct barteritemlist *item_list);
+ int (*expanded_barter_buylist) (struct map_session_data *sd, struct barteritemlist *item_list);
bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd);
void (*market_fromsql) (void);
- void (*market_tosql) (struct npc_data *nd, unsigned short index);
- void (*market_delfromsql) (struct npc_data *nd, unsigned short index);
- void (*market_delfromsql_sub) (const char *npcname, unsigned short index);
+ void (*market_tosql) (struct npc_data *nd, int index);
+ void (*market_delfromsql) (struct npc_data *nd, int index);
+ void (*market_delfromsql_sub) (const char *npcname, int index);
+ void (*barter_fromsql) (void);
+ void (*barter_tosql) (struct npc_data *nd, int index);
+ void (*barter_delfromsql) (struct npc_data *nd, int index);
+ void (*barter_delfromsql_sub) (const char *npcname, int itemId, int itemId2, int amount2);
+ void (*expanded_barter_fromsql) (void);
+ void (*expanded_barter_tosql) (struct npc_data *nd, int index);
+ void (*expanded_barter_delfromsql) (struct npc_data *nd, int index);
+ void (*expanded_barter_delfromsql_sub) (const char *npcname, int itemId, int zeny, int currencyCount, struct npc_barter_currency* currency);
bool (*db_checkid) (const int id);
+ void (*refresh) (struct npc_data* nd);
+ void (*questinfo_clear) (struct npc_data *nd);
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
**/
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index 6726c65a9..0ca84cff4 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,8 +40,8 @@
/**
* interface sources
**/
-struct npc_chat_interface npc_chat_s;
-struct pcre_interface libpcre_s;
+static struct npc_chat_interface npc_chat_s;
+static struct pcre_interface libpcre_s;
struct npc_chat_interface *npc_chat;
struct pcre_interface *libpcre;
@@ -98,8 +98,9 @@ struct pcre_interface *libpcre;
*
* This does NOT do the list management
*/
-void finalize_pcrematch_entry(struct pcrematch_entry* e)
+static void finalize_pcrematch_entry(struct pcrematch_entry *e)
{
+ nullpo_retv(e);
libpcre->free(e->pcre_);
libpcre->free(e->pcre_extra_);
aFree(e->pattern);
@@ -109,9 +110,13 @@ 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) {
+static struct pcrematch_set *lookup_pcreset(struct npc_data *nd, int setid)
+{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+
+ nullpo_retr(NULL, nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
nd->chatdb = npcParse = (struct npc_parse *)aCalloc(sizeof(struct npc_parse), 1);
@@ -148,10 +153,12 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) {
*
* if the setid does not exist, this will silently return
*/
-void activate_pcreset(struct npc_data* nd, int setid)
+static void activate_pcreset(struct npc_data *nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to activate...
pcreset = npcParse->inactive;
@@ -181,10 +188,12 @@ void activate_pcreset(struct npc_data* nd, int setid)
*
* if the setid does not exist, this will silently return
*/
-void deactivate_pcreset(struct npc_data* nd, int setid)
+static void deactivate_pcreset(struct npc_data *nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to deactivate...
if (setid == -1) {
@@ -217,11 +226,13 @@ void deactivate_pcreset(struct npc_data* nd, int setid)
/**
* delete a set of patterns.
*/
-void delete_pcreset(struct npc_data* nd, int setid)
+static void delete_pcreset(struct npc_data *nd, int setid)
{
int active = 1;
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to deactivate...
pcreset = npcParse->active;
@@ -267,10 +278,14 @@ void delete_pcreset(struct npc_data* nd, int setid)
/**
* create a new pattern entry
*/
-struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
+static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set *set)
{
- struct pcrematch_entry * e = (struct pcrematch_entry *) aCalloc(sizeof(struct pcrematch_entry), 1);
- struct pcrematch_entry * last = set->head;
+ struct pcrematch_entry *e;
+ struct pcrematch_entry *last;
+
+ nullpo_retr(NULL, set);
+ e = (struct pcrematch_entry *)aCalloc(sizeof(struct pcrematch_entry), 1);
+ last = set->head;
// Normally we would have just stuck it at the end of the list but
// this doesn't sink up with peoples usage pattern. They wanted
@@ -296,13 +311,14 @@ struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
/**
* define/compile a new pattern
*/
-void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, const char* label)
+static void npc_chat_def_pattern(struct npc_data *nd, int setid, const char *pattern, const char *label)
{
const char *err;
int erroff;
struct pcrematch_set * s = npc_chat->lookup_pcreset(nd, setid);
struct pcrematch_entry *e = npc_chat->create_pcrematch_entry(s);
+ nullpo_retv(e);
e->pattern = aStrdup(pattern);
e->label = aStrdup(label);
e->pcre_ = libpcre->compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
@@ -315,9 +331,12 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c
*
* this could be more efficient but.. how often do you do this?
*/
-void npc_chat_finalize(struct npc_data* nd)
+static void npc_chat_finalize(struct npc_data *nd)
{
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return;
@@ -334,7 +353,7 @@ void npc_chat_finalize(struct npc_data* nd)
/**
* Handler called whenever a global message is spoken in a NPC's area
*/
-int npc_chat_sub(struct block_list* bl, va_list ap)
+static int npc_chat_sub(struct block_list *bl, va_list ap)
{
struct npc_data *nd = NULL;
struct npc_parse *npcParse = NULL;
@@ -358,6 +377,8 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
len = va_arg(ap,int);
sd = va_arg(ap,struct map_session_data *);
+ nullpo_ret(sd);
+
// iterate across all active sets
for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next)
{
@@ -373,7 +394,7 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
// save out the matched strings
for (i = 0; i < r; i++)
{
- char var[6], val[255];
+ char var[15], val[255];
snprintf(var, sizeof(var), "$@p%i$", i);
libpcre->copy_substring(msg, offsets, r, i, val, sizeof(val));
script->set_var(sd, var, val);
@@ -443,7 +464,8 @@ BUILDIN(deletepset)
return true;
}
-void npc_chat_defaults(void) {
+void npc_chat_defaults(void)
+{
npc_chat = &npc_chat_s;
npc_chat->sub = npc_chat_sub;
diff --git a/src/map/packets.h b/src/map/packets.h
index 0badd94f5..e30acbdf7 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,3156 +18,1983 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-//Included directly by clif.h in packet_loaddb()
+//Included directly by clif.c in packet_loaddb()
#ifndef MAP_PACKETS_H
#define MAP_PACKETS_H
#ifndef packet
- #define packet(a,b,...)
-#endif
-
-#ifndef packetKeys
- #define packetKeys(a,b,c)
+ #define packet(a,...)
#endif
/*
* packet syntax
- * - packet(packet_id,length)
+ * - packet(packet_id)
* OR
- * - packet(packet_id,length,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet ),...)
- * - Example: packet(0x0072,19,clif->pWantToConnection,2,6,10,14,18);
+ * - packet(packet_id,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet),...)
+ * - Example: packet(0x0072,clif->pWantToConnection,2,6,10,14,18);
*/
-packet(0x0064,55);
-packet(0x0065,17);
-packet(0x0066,6);
-packet(0x0067,37);
-packet(0x0068,46);
-packet(0x0069,-1);
-packet(0x006a,23);
-packet(0x006b,-1);
-packet(0x006c,3);
-packet(0x006d,108);
-packet(0x006e,3);
-packet(0x006f,2);
-packet(0x0070,6);
-packet(0x0071,28);
-packet(0x0072,19,clif->pWantToConnection,2,6,10,14,18);
-packet(0x0073,11);
-packet(0x0074,3);
-packet(0x0075,-1);
-packet(0x0076,9);
-packet(0x0077,5);
-packet(0x0078,54);
-packet(0x0079,53);
-packet(0x007a,58);
-packet(0x007b,60);
-packet(0x007c,41);
-packet(0x007d,2,clif->pLoadEndAck,0);
-packet(0x007e,6,clif->pTickSend,2);
-packet(0x007f,6);
-packet(0x0080,7);
-packet(0x0081,3);
-packet(0x0082,2);
-packet(0x0083,2);
-packet(0x0084,2);
-packet(0x0085,5,clif->pWalkToXY,2);
-packet(0x0086,16);
-packet(0x0087,12);
-packet(0x0088,10);
-packet(0x0089,7,clif->pActionRequest,2,6);
-packet(0x008a,29);
-packet(0x008b,2);
-packet(0x008c,-1,clif->pGlobalMessage,2,4);
-packet(0x008d,-1);
-packet(0x008e,-1);
-//packet(0x008f,-1);
-packet(0x0090,7,clif->pNpcClicked,2);
-packet(0x0091,22);
-packet(0x0092,28);
-packet(0x0093,2);
-packet(0x0094,6,clif->pGetCharNameRequest,2);
-packet(0x0095,30);
-packet(0x0096,-1,clif->pWisMessage,2,4,28);
-packet(0x0097,-1);
-packet(0x0098,3);
-packet(0x0099,-1,clif->pBroadcast,2,4);
-packet(0x009a,-1);
-packet(0x009b,5,clif->pChangeDir,2,4);
-packet(0x009c,9);
-packet(0x009d,17);
-packet(0x009e,17);
-packet(0x009f,6,clif->pTakeItem,2);
-packet(0x00a0,23);
-packet(0x00a1,6);
-packet(0x00a2,6,clif->pDropItem,2,4);
-packet(0x00a3,-1);
-packet(0x00a4,-1);
-packet(0x00a5,-1);
-packet(0x00a6,-1);
-packet(0x00a7,8,clif->pUseItem,2,4);
-packet(0x00a8,7);
-packet(0x00a9,6,clif->pEquipItem,2,4);
-packet(0x00aa,7);
-packet(0x00ab,4,clif->pUnequipItem,2);
-packet(0x00ac,7);
-//packet(0x00ad,-1);
-packet(0x00ae,-1);
-packet(0x00af,6);
-packet(0x00b0,8);
-packet(0x00b1,8);
-packet(0x00b2,3,clif->pRestart,2);
-packet(0x00b3,3);
-packet(0x00b4,-1);
-packet(0x00b5,6);
-packet(0x00b6,6);
-packet(0x00b7,-1);
-packet(0x00b8,7,clif->pNpcSelectMenu,2,6);
-packet(0x00b9,6,clif->pNpcNextClicked,2);
-packet(0x00ba,2);
-packet(0x00bb,5,clif->pStatusUp,2,4);
-packet(0x00bc,6);
-packet(0x00bd,44);
-packet(0x00be,5);
-packet(0x00bf,3,clif->pEmotion,2);
-packet(0x00c0,7);
-packet(0x00c1,2,clif->pHowManyConnections,0);
-packet(0x00c2,6);
-packet(0x00c3,8);
-packet(0x00c4,6);
-packet(0x00c5,7,clif->pNpcBuySellSelected,2,6);
-packet(0x00c6,-1);
-packet(0x00c7,-1);
-packet(0x00c8,-1,clif->pNpcBuyListSend,2,4);
-packet(0x00c9,-1,clif->pNpcSellListSend,2,4);
-packet(0x00ca,3);
-packet(0x00cb,3);
-packet(0x00cc,6,clif->pGMKick,2);
-packet(0x00cd,3);
-packet(0x00ce,2,clif->pGMKickAll,0);
-packet(0x00cf,27,clif->pPMIgnore,2,26);
-packet(0x00d0,3,clif->pPMIgnoreAll,2);
-packet(0x00d1,4);
-packet(0x00d2,4);
-packet(0x00d3,2,clif->pPMIgnoreList,0);
-packet(0x00d4,-1);
-packet(0x00d5,-1,clif->pCreateChatRoom,2,4,6,7,15);
-packet(0x00d6,3);
-packet(0x00d7,-1);
-packet(0x00d8,6);
-packet(0x00d9,14,clif->pChatAddMember,2,6);
-packet(0x00da,3);
-packet(0x00db,-1);
-packet(0x00dc,28);
-packet(0x00dd,29);
-packet(0x00de,-1,clif->pChatRoomStatusChange,2,4,6,7,15);
-packet(0x00df,-1);
-packet(0x00e0,30,clif->pChangeChatOwner,2,6);
-packet(0x00e1,30);
-packet(0x00e2,26,clif->pKickFromChat,2);
-packet(0x00e3,2,clif->pChatLeave,0);
-packet(0x00e4,6,clif->pTradeRequest,2);
-packet(0x00e5,26);
-packet(0x00e6,3,clif->pTradeAck,2);
-packet(0x00e7,3);
-packet(0x00e8,8,clif->pTradeAddItem,2,4);
-packet(0x00e9,19);
-packet(0x00ea,5);
-packet(0x00eb,2,clif->pTradeOk,0);
-packet(0x00ec,3);
-packet(0x00ed,2,clif->pTradeCancel,0);
-packet(0x00ee,2);
-packet(0x00ef,2,clif->pTradeCommit,0);
-packet(0x00f0,3);
-packet(0x00f1,2);
-packet(0x00f2,6);
-packet(0x00f3,8,clif->pMoveToKafra,2,4);
-packet(0x00f4,21);
-packet(0x00f5,8,clif->pMoveFromKafra,2,4);
-packet(0x00f6,8);
-packet(0x00f7,2,clif->pCloseKafra,0);
-packet(0x00f8,2);
-packet(0x00f9,26,clif->pCreateParty,2);
-packet(0x00fa,3);
-packet(0x00fb,-1);
-packet(0x00fc,6,clif->pPartyInvite,2);
-packet(0x00fd,27);
-packet(0x00fe,30);
-packet(0x00ff,10,clif->pReplyPartyInvite,2,6);
-packet(0x0100,2,clif->pLeaveParty,0);
-packet(0x0101,6);
-packet(0x0102,6,clif->pPartyChangeOption,2);
-packet(0x0103,30,clif->pRemovePartyMember,2,6);
-packet(0x0104,79);
-packet(0x0105,31);
-packet(0x0106,10);
-packet(0x0107,10);
-packet(0x0108,-1,clif->pPartyMessage,2,4);
-packet(0x0109,-1);
-packet(0x010a,4);
-packet(0x010b,6);
-packet(0x010c,6);
-packet(0x010d,2);
-packet(0x010e,11);
-packet(0x010f,-1);
-packet(0x0110,10);
-packet(0x0111,39);
-packet(0x0112,4,clif->pSkillUp,2);
-packet(0x0113,10,clif->pUseSkillToId,2,4,6);
-packet(0x0114,31);
-packet(0x0115,35);
-packet(0x0116,10,clif->pUseSkillToPos,2,4,6,8);
-packet(0x0117,18);
-packet(0x0118,2,clif->pStopAttack,0);
-packet(0x0119,13);
-packet(0x011a,15);
-packet(0x011b,20,clif->pUseSkillMap,2,4);
-packet(0x011c,68);
-packet(0x011d,2,clif->pRequestMemo,0);
-packet(0x011e,3);
-packet(0x011f,16);
-packet(0x0120,6);
-packet(0x0121,14);
-packet(0x0122,-1);
-packet(0x0123,-1);
-packet(0x0124,21);
-packet(0x0125,8);
-packet(0x0126,8,clif->pPutItemToCart,2,4);
-packet(0x0127,8,clif->pGetItemFromCart,2,4);
-packet(0x0128,8,clif->pMoveFromKafraToCart,2,4);
-packet(0x0129,8,clif->pMoveToKafraFromCart,2,4);
-packet(0x012a,2,clif->pRemoveOption,0);
-packet(0x012b,2);
-packet(0x012c,3);
-packet(0x012d,4);
-packet(0x012e,2,clif->pCloseVending,0);
-packet(0x012f,-1);
-packet(0x0130,6,clif->pVendingListReq,2);
-packet(0x0131,86);
-packet(0x0132,6);
-packet(0x0133,-1);
-packet(0x0134,-1,clif->pPurchaseReq,2,4,8);
-packet(0x0135,7);
-packet(0x0136,-1);
-packet(0x0137,6);
-packet(0x0138,3);
-packet(0x0139,16);
-packet(0x013a,4);
-packet(0x013b,4);
-packet(0x013c,4);
-packet(0x013d,6);
-packet(0x013e,24);
-packet(0x013f,26,clif->pGM_Monster_Item,2);
-packet(0x0140,22,clif->pMapMove,2,18,20);
-packet(0x0141,14);
-packet(0x0142,6);
-packet(0x0143,10,clif->pNpcAmountInput,2,6);
-packet(0x0144,23);
-packet(0x0145,19);
-packet(0x0146,6,clif->pNpcCloseClicked,2);
-packet(0x0147,39);
-packet(0x0148,8);
-packet(0x0149,9,clif->pGMReqNoChat,2,6,7);
-packet(0x014a,6);
-packet(0x014b,27);
-packet(0x014c,-1);
-packet(0x014d,2,clif->pGuildCheckMaster,0);
-packet(0x014e,6);
-packet(0x014f,6,clif->pGuildRequestInfo,2);
-packet(0x0150,110);
-packet(0x0151,6,clif->pGuildRequestEmblem,2);
-packet(0x0152,-1);
-packet(0x0153,-1,clif->pGuildChangeEmblem,2,4);
-packet(0x0154,-1);
-packet(0x0155,-1,clif->pGuildChangeMemberPosition,2);
-packet(0x0156,-1);
-packet(0x0157,6);
-packet(0x0158,-1);
-packet(0x0159,54,clif->pGuildLeave,2,6,10,14);
-packet(0x015a,66);
-packet(0x015b,54,clif->pGuildExpulsion,2,6,10,14);
-packet(0x015c,90);
-packet(0x015d,42,clif->pGuildBreak,2);
-packet(0x015e,6);
-packet(0x015f,42);
-packet(0x0160,-1);
-packet(0x0161,-1,clif->pGuildChangePositionInfo,2);
-packet(0x0162,-1);
-packet(0x0163,-1);
-packet(0x0164,-1);
-packet(0x0165,30,clif->pCreateGuild,6);
-packet(0x0166,-1);
-packet(0x0167,3);
-packet(0x0168,14,clif->pGuildInvite,2);
-packet(0x0169,3);
-packet(0x016a,30);
-packet(0x016b,10,clif->pGuildReplyInvite,2,6);
-packet(0x016c,43);
-packet(0x016d,14);
-packet(0x016e,186,clif->pGuildChangeNotice,2,6,66);
-packet(0x016f,182);
-packet(0x0170,14,clif->pGuildRequestAlliance,2);
-packet(0x0171,30);
-packet(0x0172,10,clif->pGuildReplyAlliance,2,6);
-packet(0x0173,3);
-packet(0x0174,-1);
-packet(0x0175,6);
-packet(0x0176,106);
-packet(0x0177,-1);
-packet(0x0178,4,clif->pItemIdentify,2);
-packet(0x0179,5);
-packet(0x017a,4,clif->pUseCard,2);
-packet(0x017b,-1);
-packet(0x017c,6,clif->pInsertCard,2,4);
-packet(0x017d,7);
-packet(0x017e,-1,clif->pGuildMessage,2,4);
-packet(0x017f,-1);
-packet(0x0180,6,clif->pGuildOpposition,2);
-packet(0x0181,3);
-packet(0x0182,106);
-packet(0x0183,10,clif->pGuildDelAlliance,2,6);
-packet(0x0184,10);
-packet(0x0185,34);
-//packet(0x0186,-1);
-packet(0x0187,6);
-packet(0x0188,8);
-packet(0x0189,4);
-packet(0x018a,4,clif->pQuitGame,0);
-packet(0x018b,4);
-packet(0x018c,29);
-packet(0x018d,-1);
-packet(0x018e,10,clif->pProduceMix,2,4,6,8);
-packet(0x018f,6);
-packet(0x0190,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
-packet(0x0191,86);
-packet(0x0192,24);
-packet(0x0193,6,clif->pSolveCharName,2);
-packet(0x0194,30);
-packet(0x0195,102);
-packet(0x0196,9);
-packet(0x0197,4,clif->pResetChar,2);
-packet(0x0198,8,clif->pGMChangeMapType,2,4,6);
-packet(0x0199,4);
-packet(0x019a,14);
-packet(0x019b,10);
-packet(0x019c,-1,clif->pLocalBroadcast,2,4);
-packet(0x019d,6,clif->pGMHide,0);
-packet(0x019e,2);
-packet(0x019f,6,clif->pCatchPet,2);
-packet(0x01a0,3);
-packet(0x01a1,3,clif->pPetMenu,2);
-packet(0x01a2,35);
-packet(0x01a3,5);
-packet(0x01a4,11);
-packet(0x01a5,26,clif->pChangePetName,2);
-packet(0x01a6,-1);
-packet(0x01a7,4,clif->pSelectEgg,2);
-packet(0x01a8,4);
-packet(0x01a9,6,clif->pSendEmotion,2);
-packet(0x01aa,10);
-packet(0x01ab,12);
-packet(0x01ac,6);
-packet(0x01ad,-1);
-packet(0x01ae,4,clif->pSelectArrow,2);
-packet(0x01af,4,clif->pChangeCart,2);
-packet(0x01b0,11);
-packet(0x01b1,7);
-packet(0x01b2,-1,clif->pOpenVending,2,4,84,85);
-packet(0x01b3,67);
-packet(0x01b4,12);
-packet(0x01b5,18);
-packet(0x01b6,114);
-packet(0x01b7,6);
-packet(0x01b8,3);
-packet(0x01b9,6);
-packet(0x01ba,26,clif->pGMShift,2);
-packet(0x01bb,26,clif->pGMShift,2);
-packet(0x01bc,26,clif->pGMRecall,2);
-packet(0x01bd,26,clif->pGMRecall,2);
-packet(0x01be,2);
-packet(0x01bf,3);
-packet(0x01c0,2);
-packet(0x01c1,14);
-packet(0x01c2,10);
-packet(0x01c3,-1);
-packet(0x01c4,22);
-packet(0x01c5,22);
-packet(0x01c6,4);
-packet(0x01c7,2);
-packet(0x01c8,13);
-packet(0x01c9,97);
-//packet(0x01ca,-1);
-packet(0x01cb,9);
-packet(0x01cc,9);
-packet(0x01cd,30);
-packet(0x01ce,6,clif->pAutoSpell,2);
-packet(0x01cf,28);
-packet(0x01d0,8);
-packet(0x01d1,14);
-packet(0x01d2,10);
-packet(0x01d3,35);
-packet(0x01d4,6);
-packet(0x01d5,-1,clif->pNpcStringInput,2,4,8);
-packet(0x01d6,4);
-packet(0x01d7,11);
-packet(0x01d8,54);
-packet(0x01d9,53);
-packet(0x01da,60);
-packet(0x01db,2);
-packet(0x01dc,-1);
-packet(0x01dd,47);
-packet(0x01de,33);
-packet(0x01df,6,clif->pGMReqAccountName,2);
-packet(0x01e0,30);
-packet(0x01e1,8);
-packet(0x01e2,34);
-packet(0x01e3,14);
-packet(0x01e4,2);
-packet(0x01e5,6);
-packet(0x01e6,26);
-packet(0x01e7,2,clif->pNoviceDoriDori,0);
-packet(0x01e8,28,clif->pCreateParty2,2);
-packet(0x01e9,81);
-packet(0x01ea,6);
-packet(0x01eb,10);
-packet(0x01ec,26);
-packet(0x01ed,2,clif->pNoviceExplosionSpirits,0);
-packet(0x01ee,-1);
-packet(0x01ef,-1);
-packet(0x01f0,-1);
-packet(0x01f1,-1);
-packet(0x01f2,20);
-packet(0x01f3,10);
-packet(0x01f4,32);
-packet(0x01f5,9);
-packet(0x01f6,34);
-packet(0x01f7,14,clif->pAdopt_reply,0);
-packet(0x01f8,2);
-packet(0x01f9,6,clif->pAdopt_request,0);
-packet(0x01fa,48);
-packet(0x01fb,56);
-packet(0x01fc,-1);
-packet(0x01fd,4,clif->pRepairItem,2);
-packet(0x01fe,5);
-packet(0x01ff,10);
-packet(0x0200,26);
-packet(0x0201,-1);
-packet(0x0202,26,clif->pFriendsListAdd,2);
-packet(0x0203,10,clif->pFriendsListRemove,2,6);
-packet(0x0204,18);
-packet(0x0205,26);
-packet(0x0206,11);
-packet(0x0207,34);
-packet(0x0208,11,clif->pFriendsListReply,2,6,10);
-packet(0x0209,36);
-packet(0x020a,10);
-//packet(0x020b,-1);
-//packet(0x020c,-1);
-packet(0x020d,-1);
-packet(0x974,2,clif->cancelmergeitem);
-packet(0x96e,-1,clif->ackmergeitems);
+packet(0x0072,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+packet(0x007d,clif->pLoadEndAck,0);
+packet(0x007e,clif->pTickSend,2); // CZ_REQUEST_TIME
+packet(0x0085,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+packet(0x0089,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+packet(0x008c,clif->pGlobalMessage,2,4);
+packet(0x0090,clif->pNpcClicked,2);
+packet(0x0094,clif->pGetCharNameRequest,2); // CZ_REQNAME
+packet(0x0096,clif->pWisMessage,2,4,28);
+packet(0x0099,clif->pBroadcast,2,4);
+packet(0x009b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+packet(0x009f,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+packet(0x00a2,clif->pDropItem,2,4); // CZ_ITEM_THROW
+packet(0x00a7,clif->pUseItem,2,4);
+packet(0x00a9,clif->pEquipItem,2,4);
+packet(0x00ab,clif->pUnequipItem,2);
+packet(0x00b2,clif->pRestart,2);
+packet(0x00b8,clif->pNpcSelectMenu,2,6);
+packet(0x00b9,clif->pNpcNextClicked,2);
+packet(0x00bb,clif->pStatusUp,2,4);
+packet(0x00bf,clif->pEmotion,2);
+packet(0x00c1,clif->pHowManyConnections,0);
+packet(0x00c5,clif->pNpcBuySellSelected,2,6);
+packet(0x00c8,clif->pNpcBuyListSend,2,4);
+packet(0x00c9,clif->pNpcSellListSend,2,4);
+packet(0x00cc,clif->pGMKick,2);
+packet(0x00ce,clif->pGMKickAll,0);
+packet(0x00cf,clif->pPMIgnore,2,26);
+packet(0x00d0,clif->pPMIgnoreAll,2);
+packet(0x00d3,clif->pPMIgnoreList,0);
+packet(0x00d5,clif->pCreateChatRoom,2,4,6,7,15);
+packet(0x00d9,clif->pChatAddMember,2,6);
+packet(0x00de,clif->pChatRoomStatusChange,2,4,6,7,15);
+packet(0x00e0,clif->pChangeChatOwner,2,6);
+packet(0x00e2,clif->pKickFromChat,2);
+packet(0x00e3,clif->pChatLeave,0);
+packet(0x00e4,clif->pTradeRequest,2);
+packet(0x00e6,clif->pTradeAck,2);
+packet(0x00e8,clif->pTradeAddItem,2,4);
+packet(0x00eb,clif->pTradeOk,0);
+packet(0x00ed,clif->pTradeCancel,0);
+packet(0x00ef,clif->pTradeCommit,0);
+packet(0x00f3,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+packet(0x00f5,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+packet(0x00f7,clif->pCloseKafra,0);
+packet(0x00f9,clif->pCreateParty,2);
+packet(0x00fc,clif->pPartyInvite,2);
+packet(0x00ff,clif->pReplyPartyInvite,2,6);
+packet(0x0100,clif->pLeaveParty,0);
+packet(0x0102,clif->pPartyChangeOption,2);
+packet(0x0103,clif->pRemovePartyMember,2,6);
+packet(0x0108,clif->pPartyMessage,2,4);
+packet(0x0112,clif->pSkillUp,2);
+packet(0x0113,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+packet(0x0116,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+packet(0x0118,clif->pStopAttack,0);
+packet(0x011b,clif->pUseSkillMap,2,4);
+packet(0x011d,clif->pRequestMemo,0);
+packet(0x0126,clif->pPutItemToCart,2,4);
+packet(0x0127,clif->pGetItemFromCart,2,4);
+packet(0x0128,clif->pMoveFromKafraToCart,2,4);
+packet(0x0129,clif->pMoveToKafraFromCart,2,4);
+packet(0x012a,clif->pRemoveOption,0);
+packet(0x012e,clif->pCloseVending,0);
+packet(0x0130,clif->pVendingListReq,2);
+packet(0x0134,clif->pPurchaseReq,2,4,8);
+packet(0x013f,clif->pGM_Monster_Item,2);
+packet(0x0140,clif->pMapMove,2,18,20);
+packet(0x0143,clif->pNpcAmountInput,2,6);
+packet(0x0146,clif->pNpcCloseClicked,2);
+packet(0x0149,clif->pGMReqNoChat,2,6,7);
+packet(0x014d,clif->pGuildCheckMaster,0);
+packet(0x014f,clif->pGuildRequestInfo,2);
+packet(0x0151,clif->pGuildRequestEmblem,2);
+packet(0x0153,clif->pGuildChangeEmblem,2,4);
+packet(0x0155,clif->pGuildChangeMemberPosition,2);
+packet(0x0159,clif->pGuildLeave,2,6,10,14);
+packet(0x015b,clif->pGuildExpulsion,2,6,10,14);
+packet(0x015d,clif->pGuildBreak,2);
+packet(0x0161,clif->pGuildChangePositionInfo,2);
+packet(0x0165,clif->pCreateGuild,6);
+packet(0x0168,clif->pGuildInvite,2);
+packet(0x016b,clif->pGuildReplyInvite,2,6);
+packet(0x016e,clif->pGuildChangeNotice,2,6,66);
+packet(0x0170,clif->pGuildRequestAlliance,2);
+packet(0x0172,clif->pGuildReplyAlliance,2,6);
+packet(0x0178,clif->pItemIdentify,2);
+packet(0x017a,clif->pUseCard,2);
+packet(0x017c,clif->pInsertCard,2,4);
+packet(0x017e,clif->pGuildMessage,2,4);
+packet(0x0180,clif->pGuildOpposition,2);
+packet(0x0183,clif->pGuildDelAlliance,2,6);
+packet(0x018a,clif->pQuitGame,0);
+packet(0x018e,clif->pProduceMix,2,4,6,8);
+packet(0x0190,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+packet(0x0193,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+packet(0x0197,clif->pResetChar,2);
+packet(0x0198,clif->pGMChangeMapType,2,4,6);
+packet(0x019c,clif->pLocalBroadcast,2,4);
+packet(0x019d,clif->pGMHide,0);
+packet(0x019f,clif->pCatchPet,2);
+packet(0x01a1,clif->pPetMenu,2);
+packet(0x01a5,clif->pChangePetName,2);
+packet(0x01a7,clif->pSelectEgg,2);
+packet(0x01a9,clif->pSendEmotion,2);
+packet(0x01ae,clif->pSelectArrow,2);
+packet(0x01af,clif->pChangeCart,2);
+packet(0x01b2,clif->pOpenVending,2,4,84,85);
+packet(0x01ba,clif->pGMShift,2);
+packet(0x01bb,clif->pGMShift,2);
+packet(0x01bc,clif->pGMRecall,2);
+packet(0x01bd,clif->pGMRecall,2);
+packet(0x01c0,clif->pReqRemainTime);
+packet(0x01ce,clif->pAutoSpell,2);
+packet(0x01d5,clif->pNpcStringInput,2,4,8);
+packet(0x01df,clif->pGMReqAccountName,2);
+packet(0x01e7,clif->pNoviceDoriDori,0);
+packet(0x01e8,clif->pCreateParty2,2);
+packet(0x01ed,clif->pNoviceExplosionSpirits,0);
+packet(0x01f7,clif->pAdopt_reply,0);
+packet(0x01f9,clif->pAdopt_request,0);
+packet(0x01fd,clif->pRepairItem,2);
+packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+packet(0x0203,clif->pFriendsListRemove,2,6);
+packet(0x0208,clif->pFriendsListReply,2,6,10);
+packet(0x974,clif->cancelmergeitem);
+packet(0x96e,clif->ackmergeitems);
//2004-07-05aSakexe
#if PACKETVER >= 20040705
- packet(0x0072,22,clif->pWantToConnection,5,9,13,17,21);
- packet(0x0085,8,clif->pWalkToXY,5);
- packet(0x00a7,13,clif->pUseItem,5,9);
- packet(0x0113,15,clif->pUseSkillToId,4,9,11);
- packet(0x0116,15,clif->pUseSkillToPos,4,9,11,13);
- packet(0x0190,95,clif->pUseSkillToPosMoreInfo,4,9,11,13,15);
- packet(0x0208,14,clif->pFriendsListReply,2,6,10);
- packet(0x020e,24);
+ packet(0x0072,clif->pWantToConnection,5,9,13,17,21);
+ packet(0x0085,clif->pWalkToXY,5);
+ packet(0x00a7,clif->pUseItem,5,9);
+ packet(0x0113,clif->pUseSkillToId,4,9,11);
+ packet(0x0116,clif->pUseSkillToPos,4,9,11,13);
+ packet(0x0190,clif->pUseSkillToPosMoreInfo,4,9,11,13,15);
+ packet(0x0208,clif->pFriendsListReply,2,6,10);
#endif
//2004-07-13aSakexe
#if PACKETVER >= 20040713
- packet(0x0072,39,clif->pWantToConnection,12,22,30,34,38);
- packet(0x0085,9,clif->pWalkToXY,6);
- packet(0x009b,13,clif->pChangeDir,5,12);
- packet(0x009f,10,clif->pTakeItem,6);
- packet(0x00a7,17,clif->pUseItem,6,13);
- packet(0x0113,19,clif->pUseSkillToId,7,9,15);
- packet(0x0116,19,clif->pUseSkillToPos,7,9,15,17);
- packet(0x0190,99,clif->pUseSkillToPosMoreInfo,7,9,15,17,19);
+ packet(0x0072,clif->pWantToConnection,12,22,30,34,38);
+ packet(0x0085,clif->pWalkToXY,6);
+ packet(0x009b,clif->pChangeDir,5,12);
+ packet(0x009f,clif->pTakeItem,6);
+ packet(0x00a7,clif->pUseItem,6,13);
+ packet(0x0113,clif->pUseSkillToId,7,9,15);
+ packet(0x0116,clif->pUseSkillToPos,7,9,15,17);
+ packet(0x0190,clif->pUseSkillToPosMoreInfo,7,9,15,17,19);
#endif
//2004-07-26aSakexe
#if PACKETVER >= 20040726
- packet(0x0072,14,clif->pDropItem,5,12);
- packet(0x007e,33,clif->pWantToConnection,12,18,24,28,32);
- packet(0x0085,20,clif->pUseSkillToId,7,12,16);
- packet(0x0089,15,clif->pGetCharNameRequest,11);
- packet(0x008c,23,clif->pUseSkillToPos,3,6,17,21);
- packet(0x0094,10,clif->pTakeItem,6);
- packet(0x009b,6,clif->pWalkToXY,3);
- packet(0x009f,13,clif->pChangeDir,5,12);
- packet(0x00a2,103,clif->pUseSkillToPosMoreInfo,3,6,17,21,23);
- packet(0x00a7,12,clif->pSolveCharName,8);
- packet(0x00f3,-1,clif->pGlobalMessage,2,4);
- packet(0x00f5,17,clif->pUseItem,6,12);
- packet(0x00f7,10,clif->pTickSend,6);
- packet(0x0113,16,clif->pMoveToKafra,5,12);
- packet(0x0116,2,clif->pCloseKafra,0);
- packet(0x0190,26,clif->pMoveFromKafra,10,22);
- packet(0x0193,9,clif->pActionRequest,3,8);
+ packet(0x0072,clif->pDropItem,5,12);
+ packet(0x007e,clif->pWantToConnection,12,18,24,28,32);
+ packet(0x0085,clif->pUseSkillToId,7,12,16);
+ packet(0x0089,clif->pGetCharNameRequest,11);
+ packet(0x008c,clif->pUseSkillToPos,3,6,17,21);
+ packet(0x0094,clif->pTakeItem,6);
+ packet(0x009b,clif->pWalkToXY,3);
+ packet(0x009f,clif->pChangeDir,5,12);
+ packet(0x00a2,clif->pUseSkillToPosMoreInfo,3,6,17,21,23);
+ packet(0x00a7,clif->pSolveCharName,8);
+ packet(0x00f3,clif->pGlobalMessage,2,4);
+ packet(0x00f5,clif->pUseItem,6,12);
+ packet(0x00f7,clif->pTickSend,6);
+ packet(0x0113,clif->pMoveToKafra,5,12);
+ packet(0x0116,clif->pCloseKafra,0);
+ packet(0x0190,clif->pMoveFromKafra,10,22);
+ packet(0x0193,clif->pActionRequest,3,8);
#endif
//2004-08-09aSakexe
#if PACKETVER >= 20040809
- packet(0x0072,17,clif->pDropItem,8,15);
- packet(0x007e,37,clif->pWantToConnection,9,21,28,32,36);
- packet(0x0085,26,clif->pUseSkillToId,11,18,22);
- packet(0x0089,12,clif->pGetCharNameRequest,8);
- packet(0x008c,40,clif->pUseSkillToPos,5,15,29,38);
- packet(0x0094,13,clif->pTakeItem,9);
- packet(0x009b,15,clif->pWalkToXY,12);
- packet(0x009f,12,clif->pChangeDir,7,11);
- packet(0x00a2,120,clif->pUseSkillToPosMoreInfo,5,15,29,38,40);
- packet(0x00a7,11,clif->pSolveCharName,7);
- packet(0x00f5,24,clif->pUseItem,9,20);
- packet(0x00f7,13,clif->pTickSend,9);
- packet(0x0113,23,clif->pMoveToKafra,5,19);
- packet(0x0190,26,clif->pMoveFromKafra,11,22);
- packet(0x0193,18,clif->pActionRequest,7,17);
+ packet(0x0072,clif->pDropItem,8,15);
+ packet(0x007e,clif->pWantToConnection,9,21,28,32,36);
+ packet(0x0085,clif->pUseSkillToId,11,18,22);
+ packet(0x0089,clif->pGetCharNameRequest,8);
+ packet(0x008c,clif->pUseSkillToPos,5,15,29,38);
+ packet(0x0094,clif->pTakeItem,9);
+ packet(0x009b,clif->pWalkToXY,12);
+ packet(0x009f,clif->pChangeDir,7,11);
+ packet(0x00a2,clif->pUseSkillToPosMoreInfo,5,15,29,38,40);
+ packet(0x00a7,clif->pSolveCharName,7);
+ packet(0x00f5,clif->pUseItem,9,20);
+ packet(0x00f7,clif->pTickSend,9);
+ packet(0x0113,clif->pMoveToKafra,5,19);
+ packet(0x0190,clif->pMoveFromKafra,11,22);
+ packet(0x0193,clif->pActionRequest,7,17);
#endif
//2004-08-16aSakexe
#if PACKETVER >= 20040816
- packet(0x0212,26,clif->pGMRc,2);
- packet(0x0213,26,clif->pCheck,2);
- packet(0x0214,42);
+ packet(0x0212,clif->pGMRc,2);
+ packet(0x0213,clif->pCheck,2);
#endif
//2004-08-17aSakexe
#if PACKETVER >= 20040817
- packet(0x020f,10,clif->pPVPInfo,2,6);
- packet(0x0210,22);
+ packet(0x020f,clif->pPVPInfo,2,6);
#endif
//2004-09-06aSakexe
#if PACKETVER >= 20040906
- packet(0x0072,20,clif->pUseItem,9,20);
- packet(0x007e,19,clif->pMoveToKafra,3,15);
- packet(0x0085,23,clif->pActionRequest,9,22);
- packet(0x0089,9,clif->pWalkToXY,6);
- packet(0x008c,105,clif->pUseSkillToPosMoreInfo,10,14,18,23,25);
- packet(0x0094,17,clif->pDropItem,6,15);
- packet(0x009b,14,clif->pGetCharNameRequest,10);
- packet(0x009f,-1,clif->pGlobalMessage,2,4);
- packet(0x00a2,14,clif->pSolveCharName,10);
- packet(0x00a7,25,clif->pUseSkillToPos,10,14,18,23);
- packet(0x00f3,10,clif->pChangeDir,4,9);
- packet(0x00f5,34,clif->pWantToConnection,7,15,25,29,33);
- packet(0x00f7,2,clif->pCloseKafra,0);
- packet(0x0113,11,clif->pTakeItem,7);
- packet(0x0116,11,clif->pTickSend,7);
- packet(0x0190,22,clif->pUseSkillToId,9,15,18);
- packet(0x0193,17,clif->pMoveFromKafra,3,13);
+ packet(0x0072,clif->pUseItem,9,20);
+ packet(0x007e,clif->pMoveToKafra,3,15);
+ packet(0x0085,clif->pActionRequest,9,22);
+ packet(0x0089,clif->pWalkToXY,6);
+ packet(0x008c,clif->pUseSkillToPosMoreInfo,10,14,18,23,25);
+ packet(0x0094,clif->pDropItem,6,15);
+ packet(0x009b,clif->pGetCharNameRequest,10);
+ packet(0x009f,clif->pGlobalMessage,2,4);
+ packet(0x00a2,clif->pSolveCharName,10);
+ packet(0x00a7,clif->pUseSkillToPos,10,14,18,23);
+ packet(0x00f3,clif->pChangeDir,4,9);
+ packet(0x00f5,clif->pWantToConnection,7,15,25,29,33);
+ packet(0x00f7,clif->pCloseKafra,0);
+ packet(0x0113,clif->pTakeItem,7);
+ packet(0x0116,clif->pTickSend,7);
+ packet(0x0190,clif->pUseSkillToId,9,15,18);
+ packet(0x0193,clif->pMoveFromKafra,3,13);
#endif
//2004-09-20aSakexe
#if PACKETVER >= 20040920
- packet(0x0072,18,clif->pUseItem,10,14);
- packet(0x007e,25,clif->pMoveToKafra,6,21);
- packet(0x0085,9,clif->pActionRequest,3,8);
- packet(0x0089,14,clif->pWalkToXY,11);
- packet(0x008c,109,clif->pUseSkillToPosMoreInfo,16,20,23,27,29);
- packet(0x0094,19,clif->pDropItem,12,17);
- packet(0x009b,10,clif->pGetCharNameRequest,6);
- packet(0x00a2,10,clif->pSolveCharName,6);
- packet(0x00a7,29,clif->pUseSkillToPos,6,20,23,27);
- packet(0x00f3,18,clif->pChangeDir,8,17);
- packet(0x00f5,32,clif->pWantToConnection,10,17,23,27,31);
- packet(0x0113,14,clif->pTakeItem,10);
- packet(0x0116,14,clif->pTickSend,10);
- packet(0x0190,14,clif->pUseSkillToId,4,7,10);
- packet(0x0193,12,clif->pMoveFromKafra,4,8);
+ packet(0x0072,clif->pUseItem,10,14);
+ packet(0x007e,clif->pMoveToKafra,6,21);
+ packet(0x0085,clif->pActionRequest,3,8);
+ packet(0x0089,clif->pWalkToXY,11);
+ packet(0x008c,clif->pUseSkillToPosMoreInfo,16,20,23,27,29);
+ packet(0x0094,clif->pDropItem,12,17);
+ packet(0x009b,clif->pGetCharNameRequest,6);
+ packet(0x00a2,clif->pSolveCharName,6);
+ packet(0x00a7,clif->pUseSkillToPos,6,20,23,27);
+ packet(0x00f3,clif->pChangeDir,8,17);
+ packet(0x00f5,clif->pWantToConnection,10,17,23,27,31);
+ packet(0x0113,clif->pTakeItem,10);
+ packet(0x0116,clif->pTickSend,10);
+ packet(0x0190,clif->pUseSkillToId,4,7,10);
+ packet(0x0193,clif->pMoveFromKafra,4,8);
#endif
//2004-10-05aSakexe
#if PACKETVER >= 20041005
- packet(0x0072,17,clif->pUseItem,6,13);
- packet(0x007e,16,clif->pMoveToKafra,5,12);
- packet(0x0089,6,clif->pWalkToXY,3);
- packet(0x008c,103,clif->pUseSkillToPosMoreInfo,2,6,17,21,23);
- packet(0x0094,14,clif->pDropItem,5,12);
- packet(0x009b,15,clif->pGetCharNameRequest,11);
- packet(0x00a2,12,clif->pSolveCharName,8);
- packet(0x00a7,23,clif->pUseSkillToPos,3,6,17,21);
- packet(0x00f3,13,clif->pChangeDir,5,12);
- packet(0x00f5,33,clif->pWantToConnection,12,18,24,28,32);
- packet(0x0113,10,clif->pTakeItem,6);
- packet(0x0116,10,clif->pTickSend,6);
- packet(0x0190,20,clif->pUseSkillToId,7,12,16);
- packet(0x0193,26,clif->pMoveFromKafra,10,22);
+ packet(0x0072,clif->pUseItem,6,13);
+ packet(0x007e,clif->pMoveToKafra,5,12);
+ packet(0x0089,clif->pWalkToXY,3);
+ packet(0x008c,clif->pUseSkillToPosMoreInfo,2,6,17,21,23);
+ packet(0x0094,clif->pDropItem,5,12);
+ packet(0x009b,clif->pGetCharNameRequest,11);
+ packet(0x00a2,clif->pSolveCharName,8);
+ packet(0x00a7,clif->pUseSkillToPos,3,6,17,21);
+ packet(0x00f3,clif->pChangeDir,5,12);
+ packet(0x00f5,clif->pWantToConnection,12,18,24,28,32);
+ packet(0x0113,clif->pTakeItem,6);
+ packet(0x0116,clif->pTickSend,6);
+ packet(0x0190,clif->pUseSkillToId,7,12,16);
+ packet(0x0193,clif->pMoveFromKafra,10,22);
#endif
//2004-10-25aSakexe
#if PACKETVER >= 20041025
- packet(0x0072,13,clif->pUseItem,5,9);
- packet(0x007e,13,clif->pMoveToKafra,6,9);
- packet(0x0085,15,clif->pActionRequest,4,14);
- packet(0x008c,108,clif->pUseSkillToPosMoreInfo,6,9,23,26,28);
- packet(0x0094,12,clif->pDropItem,6,10);
- packet(0x009b,10,clif->pGetCharNameRequest,6);
- packet(0x00a2,16,clif->pSolveCharName,12);
- packet(0x00a7,28,clif->pUseSkillToPos,6,9,23,26);
- packet(0x00f3,15,clif->pChangeDir,6,14);
- packet(0x00f5,29,clif->pWantToConnection,5,14,20,24,28);
- packet(0x0113,9,clif->pTakeItem,5);
- packet(0x0116,9,clif->pTickSend,5);
- packet(0x0190,26,clif->pUseSkillToId,4,10,22);
- packet(0x0193,22,clif->pMoveFromKafra,12,18);
-#endif
-
-//2004-11-01aSakexe
-#if PACKETVER >= 20041101
- packet(0x0084,-1);
- packet(0x0215,6);
+ packet(0x0072,clif->pUseItem,5,9);
+ packet(0x007e,clif->pMoveToKafra,6,9);
+ packet(0x0085,clif->pActionRequest,4,14);
+ packet(0x008c,clif->pUseSkillToPosMoreInfo,6,9,23,26,28);
+ packet(0x0094,clif->pDropItem,6,10);
+ packet(0x009b,clif->pGetCharNameRequest,6);
+ packet(0x00a2,clif->pSolveCharName,12);
+ packet(0x00a7,clif->pUseSkillToPos,6,9,23,26);
+ packet(0x00f3,clif->pChangeDir,6,14);
+ packet(0x00f5,clif->pWantToConnection,5,14,20,24,28);
+ packet(0x0113,clif->pTakeItem,5);
+ packet(0x0116,clif->pTickSend,5);
+ packet(0x0190,clif->pUseSkillToId,4,10,22);
+ packet(0x0193,clif->pMoveFromKafra,12,18);
#endif
//2004-11-08aSakexe
#if PACKETVER >= 20041108
- packet(0x0084,2);
- packet(0x0216,6);
- packet(0x0217,2,clif->pBlacksmith,0);
- packet(0x0218,2,clif->pAlchemist,0);
- packet(0x0219,282);
- packet(0x021a,282);
- packet(0x021b,10);
- packet(0x021c,10);
+ packet(0x0217,clif->pBlacksmith,0);
+ packet(0x0218,clif->pAlchemist,0);
#endif
//2004-11-15aSakexe
#if PACKETVER >= 20041115
- packet(0x021d,6,clif->pLessEffect,2);
+ packet(0x021d,clif->pLessEffect,2);
#endif
//2004-11-29aSakexe
#if PACKETVER >= 20041129
- packet(0x0072,22,clif->pUseSkillToId,8,12,18);
- packet(0x007e,30,clif->pUseSkillToPos,4,9,22,28);
- packet(0x0085,-1,clif->pGlobalMessage,2,4);
- packet(0x0089,7,clif->pTickSend,3);
- packet(0x008c,13,clif->pGetCharNameRequest,9);
- packet(0x0094,14,clif->pMoveToKafra,4,10);
- packet(0x009b,2,clif->pCloseKafra,0);
- packet(0x009f,18,clif->pActionRequest,6,17);
- packet(0x00a2,7,clif->pTakeItem,3);
- packet(0x00a7,7,clif->pWalkToXY,4);
- packet(0x00f3,8,clif->pChangeDir,3,7);
- packet(0x00f5,29,clif->pWantToConnection,3,10,20,24,28);
- packet(0x00f7,14,clif->pSolveCharName,10);
- packet(0x0113,110,clif->pUseSkillToPosMoreInfo,4,9,22,28,30);
- packet(0x0116,12,clif->pDropItem,4,10);
- packet(0x0190,15,clif->pUseItem,3,11);
- packet(0x0193,21,clif->pMoveFromKafra,4,17);
- packet(0x0221,-1);
- packet(0x0222,6,clif->pWeaponRefine,2);
- packet(0x0223,8);
-#endif
-
-//2004-12-13aSakexe
-#if PACKETVER >= 20041213
-//skipped: many packets being set to -1
- packet(0x0066,3);
- packet(0x0070,3);
- packet(0x01ca,3);
- packet(0x021e,6);
- packet(0x021f,66);
- packet(0x0220,10);
+ packet(0x0072,clif->pUseSkillToId,8,12,18);
+ packet(0x007e,clif->pUseSkillToPos,4,9,22,28);
+ packet(0x0085,clif->pGlobalMessage,2,4);
+ packet(0x0089,clif->pTickSend,3);
+ packet(0x008c,clif->pGetCharNameRequest,9);
+ packet(0x0094,clif->pMoveToKafra,4,10);
+ packet(0x009b,clif->pCloseKafra,0);
+ packet(0x009f,clif->pActionRequest,6,17);
+ packet(0x00a2,clif->pTakeItem,3);
+ packet(0x00a7,clif->pWalkToXY,4);
+ packet(0x00f3,clif->pChangeDir,3,7);
+ packet(0x00f5,clif->pWantToConnection,3,10,20,24,28);
+ packet(0x00f7,clif->pSolveCharName,10);
+ packet(0x0113,clif->pUseSkillToPosMoreInfo,4,9,22,28,30);
+ packet(0x0116,clif->pDropItem,4,10);
+ packet(0x0190,clif->pUseItem,3,11);
+ packet(0x0193,clif->pMoveFromKafra,4,17);
+ packet(0x0222,clif->pWeaponRefine,2);
#endif
//2005-01-10bSakexe
#if PACKETVER >= 20050110
- packet(0x0072,26,clif->pUseSkillToId,8,16,22);
- packet(0x007e,114,clif->pUseSkillToPosMoreInfo,10,18,22,32,34);
- packet(0x0085,23,clif->pChangeDir,12,22);
- packet(0x0089,9,clif->pTickSend,5);
- packet(0x008c,8,clif->pGetCharNameRequest,4);
- packet(0x0094,20,clif->pMoveToKafra,10,16);
- packet(0x009b,32,clif->pWantToConnection,3,12,23,27,31);
- packet(0x009f,17,clif->pUseItem,5,13);
- packet(0x00a2,11,clif->pSolveCharName,7);
- packet(0x00a7,13,clif->pWalkToXY,10);
- packet(0x00f3,-1,clif->pGlobalMessage,2,4);
- packet(0x00f5,9,clif->pTakeItem,5);
- packet(0x00f7,21,clif->pMoveFromKafra,11,17);
- packet(0x0113,34,clif->pUseSkillToPos,10,18,22,32);
- packet(0x0116,20,clif->pDropItem,15,18);
- packet(0x0190,20,clif->pActionRequest,9,19);
- packet(0x0193,2,clif->pCloseKafra,0);
+ packet(0x0072,clif->pUseSkillToId,8,16,22);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,10,18,22,32,34);
+ packet(0x0085,clif->pChangeDir,12,22);
+ packet(0x0089,clif->pTickSend,5);
+ packet(0x008c,clif->pGetCharNameRequest,4);
+ packet(0x0094,clif->pMoveToKafra,10,16);
+ packet(0x009b,clif->pWantToConnection,3,12,23,27,31);
+ packet(0x009f,clif->pUseItem,5,13);
+ packet(0x00a2,clif->pSolveCharName,7);
+ packet(0x00a7,clif->pWalkToXY,10);
+ packet(0x00f3,clif->pGlobalMessage,2,4);
+ packet(0x00f5,clif->pTakeItem,5);
+ packet(0x00f7,clif->pMoveFromKafra,11,17);
+ packet(0x0113,clif->pUseSkillToPos,10,18,22,32);
+ packet(0x0116,clif->pDropItem,15,18);
+ packet(0x0190,clif->pActionRequest,9,19);
+ packet(0x0193,clif->pCloseKafra,0);
#endif
//2005-03-28aSakexe
#if PACKETVER >= 20050328
- packet(0x0224,10);
- packet(0x0225,2,clif->pTaekwon,0);
- packet(0x0226,282);
-#endif
-
-//2005-04-04aSakexe
-#if PACKETVER >= 20050404
- packet(0x0227,18);
- packet(0x0228,18);
-#endif
-
-//2005-04-11aSakexe
-#if PACKETVER >= 20050411
- packet(0x0229,15);
- packet(0x022a,58);
- packet(0x022b,57);
- packet(0x022c,64);
+ packet(0x0225,clif->pTaekwon,0);
#endif
//2005-04-25aSakexe
#if PACKETVER >= 20050425
- packet(0x022d,5,clif->pHomMenu,2,4);
- packet(0x0232,9,clif->pHomMoveTo,2,6);
- packet(0x0233,11,clif->pHomAttack,2,6,10);
- packet(0x0234,6,clif->pHomMoveToMaster,2);
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0232,clif->pHomMoveTo,2,6);
+ packet(0x0233,clif->pHomAttack,2,6,10);
+ packet(0x0234,clif->pHomMoveToMaster,2);
#endif
//2005-05-09aSakexe
#if PACKETVER >= 20050509
- packet(0x0072,25,clif->pUseSkillToId,6,10,21);
- packet(0x007e,102,clif->pUseSkillToPosMoreInfo,5,9,12,20,22);
- packet(0x0085,11,clif->pChangeDir,7,10);
- packet(0x0089,8,clif->pTickSend,4);
- packet(0x008c,11,clif->pGetCharNameRequest,7);
- packet(0x0094,14,clif->pMoveToKafra,7,10);
- packet(0x009b,26,clif->pWantToConnection,4,9,17,21,25);
- packet(0x009f,14,clif->pUseItem,4,10);
- packet(0x00a2,15,clif->pSolveCharName,11);
- packet(0x00a7,8,clif->pWalkToXY,5);
- packet(0x00f5,8,clif->pTakeItem,4);
- packet(0x00f7,22,clif->pMoveFromKafra,14,18);
- packet(0x0113,22,clif->pUseSkillToPos,5,9,12,20);
- packet(0x0116,10,clif->pDropItem,5,8);
- packet(0x0190,19,clif->pActionRequest,5,18);
-#endif
-
-//2005-05-23aSakexe
-#if PACKETVER >= 20050523
- packet(0x022e,69);
- packet(0x0230,12);
+ packet(0x0072,clif->pUseSkillToId,6,10,21);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,5,9,12,20,22);
+ packet(0x0085,clif->pChangeDir,7,10);
+ packet(0x0089,clif->pTickSend,4);
+ packet(0x008c,clif->pGetCharNameRequest,7);
+ packet(0x0094,clif->pMoveToKafra,7,10);
+ packet(0x009b,clif->pWantToConnection,4,9,17,21,25);
+ packet(0x009f,clif->pUseItem,4,10);
+ packet(0x00a2,clif->pSolveCharName,11);
+ packet(0x00a7,clif->pWalkToXY,5);
+ packet(0x00f5,clif->pTakeItem,4);
+ packet(0x00f7,clif->pMoveFromKafra,14,18);
+ packet(0x0113,clif->pUseSkillToPos,5,9,12,20);
+ packet(0x0116,clif->pDropItem,5,8);
+ packet(0x0190,clif->pActionRequest,5,18);
#endif
//2005-05-30aSakexe
#if PACKETVER >= 20050530
- packet(0x022e,71);
- packet(0x0235,-1);
- packet(0x0236,10);
- packet(0x0237,2,clif->pRankingPk,0);
- packet(0x0238,282);
-#endif
-
-//2005-05-31aSakexe
-#if PACKETVER >= 20050531
- packet(0x0216,2);
- packet(0x0239,11);
+ packet(0x0237,clif->pRankingPk,0);
#endif
//2005-06-08aSakexe
#if PACKETVER >= 20050608
- packet(0x0216,6);
- packet(0x0217,2,clif->pBlacksmith,0);
- packet(0x022f,5);
- packet(0x0231,26,clif->pChangeHomunculusName,0);
- packet(0x023a,4);
- packet(0x023b,36,clif->pStoragePassword,2,4,20);
- packet(0x023c,6);
-#endif
-
-//2005-06-22aSakexe
-#if PACKETVER >= 20050622
- packet(0x022e,71);
-
+ packet(0x0217,clif->pBlacksmith,0);
+ packet(0x0231,clif->pChangeHomunculusName,0);
+ packet(0x023b,clif->pStoragePassword,2,4,20);
#endif
//2005-06-28aSakexe
#if PACKETVER >= 20050628
- packet(0x0072,34,clif->pUseSkillToId,6,17,30);
- packet(0x007e,113,clif->pUseSkillToPosMoreInfo,12,15,18,31,33);
- packet(0x0085,17,clif->pChangeDir,8,16);
- packet(0x0089,13,clif->pTickSend,9);
- packet(0x008c,8,clif->pGetCharNameRequest,4);
- packet(0x0094,31,clif->pMoveToKafra,16,27);
- packet(0x009b,32,clif->pWantToConnection,9,15,23,27,31);
- packet(0x009f,19,clif->pUseItem,9,15);
- packet(0x00a2,9,clif->pSolveCharName,5);
- packet(0x00a7,11,clif->pWalkToXY,8);
- packet(0x00f5,13,clif->pTakeItem,9);
- packet(0x00f7,18,clif->pMoveFromKafra,11,14);
- packet(0x0113,33,clif->pUseSkillToPos,12,15,18,31);
- packet(0x0116,12,clif->pDropItem,3,10);
- packet(0x0190,24,clif->pActionRequest,11,23);
- packet(0x0216,-1);
- packet(0x023d,-1);
- packet(0x023e,4);
+ packet(0x0072,clif->pUseSkillToId,6,17,30);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,12,15,18,31,33);
+ packet(0x0085,clif->pChangeDir,8,16);
+ packet(0x0089,clif->pTickSend,9);
+ packet(0x008c,clif->pGetCharNameRequest,4);
+ packet(0x0094,clif->pMoveToKafra,16,27);
+ packet(0x009b,clif->pWantToConnection,9,15,23,27,31);
+ packet(0x009f,clif->pUseItem,9,15);
+ packet(0x00a2,clif->pSolveCharName,5);
+ packet(0x00a7,clif->pWalkToXY,8);
+ packet(0x00f5,clif->pTakeItem,9);
+ packet(0x00f7,clif->pMoveFromKafra,11,14);
+ packet(0x0113,clif->pUseSkillToPos,12,15,18,31);
+ packet(0x0116,clif->pDropItem,3,10);
+ packet(0x0190,clif->pActionRequest,11,23);
#endif
//2005-07-18aSakexe
#if PACKETVER >= 20050718
- packet(0x0072,19,clif->pUseSkillToId,5,11,15);
- packet(0x007e,110,clif->pUseSkillToPosMoreInfo,9,15,23,28,30);
- packet(0x0085,11,clif->pChangeDir,6,10);
- packet(0x0089,7,clif->pTickSend,3);
- packet(0x008c,11,clif->pGetCharNameRequest,7);
- packet(0x0094,21,clif->pMoveToKafra,12,17);
- packet(0x009b,31,clif->pWantToConnection,3,13,22,26,30);
- packet(0x009f,12,clif->pUseItem,3,8);
- packet(0x00a2,18,clif->pSolveCharName,14);
- packet(0x00a7,15,clif->pWalkToXY,12);
- packet(0x00f5,7,clif->pTakeItem,3);
- packet(0x00f7,13,clif->pMoveFromKafra,5,9);
- packet(0x0113,30,clif->pUseSkillToPos,9,15,23,28);
- packet(0x0116,12,clif->pDropItem,6,10);
- packet(0x0190,21,clif->pActionRequest,5,20);
- packet(0x0216,6);
- packet(0x023f,2,clif->pMail_refreshinbox,0);
- packet(0x0240,8);
- packet(0x0241,6,clif->pMail_read,2);
- packet(0x0242,-1);
- packet(0x0243,6,clif->pMail_delete,2);
- packet(0x0244,6,clif->pMail_getattach,2);
- packet(0x0245,7);
- packet(0x0246,4,clif->pMail_winopen,2);
- packet(0x0247,8,clif->pMail_setattach,2,4);
- packet(0x0248,68);
- packet(0x0249,3);
- packet(0x024a,70);
- packet(0x024b,4,clif->pAuction_cancelreg,0);
- packet(0x024c,8,clif->pAuction_setitem,0);
- packet(0x024d,14);
- packet(0x024e,6,clif->pAuction_cancel,0);
- packet(0x024f,10,clif->pAuction_bid,0);
- packet(0x0250,3);
- packet(0x0251,2);
- packet(0x0252,-1);
+ packet(0x0072,clif->pUseSkillToId,5,11,15);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,9,15,23,28,30);
+ packet(0x0085,clif->pChangeDir,6,10);
+ packet(0x0089,clif->pTickSend,3);
+ packet(0x008c,clif->pGetCharNameRequest,7);
+ packet(0x0094,clif->pMoveToKafra,12,17);
+ packet(0x009b,clif->pWantToConnection,3,13,22,26,30);
+ packet(0x009f,clif->pUseItem,3,8);
+ packet(0x00a2,clif->pSolveCharName,14);
+ packet(0x00a7,clif->pWalkToXY,12);
+ packet(0x00f5,clif->pTakeItem,3);
+ packet(0x00f7,clif->pMoveFromKafra,5,9);
+ packet(0x0113,clif->pUseSkillToPos,9,15,23,28);
+ packet(0x0116,clif->pDropItem,6,10);
+ packet(0x0190,clif->pActionRequest,5,20);
+ packet(0x023f,clif->pMail_refreshinbox,0);
+ packet(0x0241,clif->pMail_read,2);
+ packet(0x0243,clif->pMail_delete,2);
+ packet(0x0244,clif->pMail_getattach,2);
+ packet(0x0246,clif->pMail_winopen,2);
+ packet(0x0247,clif->pMail_setattach,2,4);
+ packet(0x024b,clif->pAuction_cancelreg,0);
+ packet(0x024c,clif->pAuction_setitem,0);
+ packet(0x024e,clif->pAuction_cancel,0);
+ packet(0x024f,clif->pAuction_bid,0);
#endif
//2005-07-19bSakexe
#if PACKETVER >= 20050719
- packet(0x0072,34,clif->pUseSkillToId,6,17,30);
- packet(0x007e,113,clif->pUseSkillToPosMoreInfo,12,15,18,31,33);
- packet(0x0085,17,clif->pChangeDir,8,16);
- packet(0x0089,13,clif->pTickSend,9);
- packet(0x008c,8,clif->pGetCharNameRequest,4);
- packet(0x0094,31,clif->pMoveToKafra,16,27);
- packet(0x009b,32,clif->pWantToConnection,9,15,23,27,31);
- packet(0x009f,19,clif->pUseItem,9,15);
- packet(0x00a2,9,clif->pSolveCharName,5);
- packet(0x00a7,11,clif->pWalkToXY,8);
- packet(0x00f5,13,clif->pTakeItem,9);
- packet(0x00f7,18,clif->pMoveFromKafra,11,14);
- packet(0x0113,33,clif->pUseSkillToPos,12,15,18,31);
- packet(0x0116,12,clif->pDropItem,3,10);
- packet(0x0190,24,clif->pActionRequest,11,23);
-#endif
-
-//2005-08-01aSakexe
-#if PACKETVER >= 20050801
- packet(0x0245,3);
- packet(0x0251,4);
+ packet(0x0072,clif->pUseSkillToId,6,17,30);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,12,15,18,31,33);
+ packet(0x0085,clif->pChangeDir,8,16);
+ packet(0x0089,clif->pTickSend,9);
+ packet(0x008c,clif->pGetCharNameRequest,4);
+ packet(0x0094,clif->pMoveToKafra,16,27);
+ packet(0x009b,clif->pWantToConnection,9,15,23,27,31);
+ packet(0x009f,clif->pUseItem,9,15);
+ packet(0x00a2,clif->pSolveCharName,5);
+ packet(0x00a7,clif->pWalkToXY,8);
+ packet(0x00f5,clif->pTakeItem,9);
+ packet(0x00f7,clif->pMoveFromKafra,11,14);
+ packet(0x0113,clif->pUseSkillToPos,12,15,18,31);
+ packet(0x0116,clif->pDropItem,3,10);
+ packet(0x0190,clif->pActionRequest,11,23);
#endif
//2005-08-08aSakexe
#if PACKETVER >= 20050808
- packet(0x024d,12,clif->pAuction_register,0);
- packet(0x024e,4);
+ packet(0x024d,clif->pAuction_register,0);
#endif
//2005-08-17aSakexe
#if PACKETVER >= 20050817
- packet(0x0253,3);
- packet(0x0254,3,clif->pFeelSaveOk,0);
+ packet(0x0254,clif->pFeelSaveOk,0);
#endif
//2005-08-29aSakexe
#if PACKETVER >= 20050829
- packet(0x0240,-1);
- packet(0x0248,-1,clif->pMail_send,2,4,28,68);
- packet(0x0255,5);
- packet(0x0256,-1);
- packet(0x0257,8);
-#endif
-
-//2005-09-12bSakexe
-#if PACKETVER >= 20050912
- packet(0x0256,5);
- packet(0x0258,2);
- packet(0x0259,3);
+ packet(0x0248,clif->pMail_send,2,4,28,68);
#endif
//2005-10-10aSakexe
#if PACKETVER >= 20051010
- packet(0x020e,32);
- packet(0x025a,-1);
- packet(0x025b,6,clif->pCooking,0);
+ packet(0x025b,clif->pCooking,0);
#endif
//2005-10-13aSakexe
#if PACKETVER >= 20051013
- packet(0x007a,6);
- packet(0x0251,32);
- packet(0x025c,4,clif->pAuction_buysell,0);
+ packet(0x025c,clif->pAuction_buysell,0);
#endif
//2005-10-17aSakexe
#if PACKETVER >= 20051017
- packet(0x007a,58);
- packet(0x025d,6,clif->pAuction_close,0);
- packet(0x025e,4);
-#endif
-
-//2005-10-24aSakexe
-#if PACKETVER >= 20051024
- packet(0x025f,6);
- packet(0x0260,6);
+ packet(0x025d,clif->pAuction_close,0);
#endif
//2005-11-07aSakexe
#if PACKETVER >= 20051107
- packet(0x024e,6,clif->pAuction_cancel,0);
- packet(0x0251,34,clif->pAuction_search,0);
-#endif
-
-//2006-01-09aSakexe
-#if PACKETVER >= 20060109
- packet(0x0261,11);
- packet(0x0262,11);
- packet(0x0263,11);
- packet(0x0264,20);
- packet(0x0265,20);
- packet(0x0266,30);
- packet(0x0267,4);
- packet(0x0268,4);
- packet(0x0269,4);
- packet(0x026a,4);
- packet(0x026b,4);
- packet(0x026c,4);
- packet(0x026d,4);
- packet(0x026f,2);
- packet(0x0270,2);
- packet(0x0271,38);
- packet(0x0272,44);
-#endif
-
-//2006-01-26aSakexe
-#if PACKETVER >= 20060126
- packet(0x0271,40);
-
-#endif
-
-//2006-03-06aSakexe
-#if PACKETVER >= 20060306
- packet(0x0273,6);
- packet(0x0274,8);
+ packet(0x024e,clif->pAuction_cancel,0);
+ packet(0x0251,clif->pAuction_search,0);
#endif
//2006-03-13aSakexe
#if PACKETVER >= 20060313
- packet(0x0273,30,clif->pMail_return,2,6);
+ packet(0x0273,clif->pMail_return,2,6);
#endif
//2006-03-27aSakexe
#if PACKETVER >= 20060327
- packet(0x0072,26,clif->pUseSkillToId,11,18,22);
- packet(0x007e,120,clif->pUseSkillToPosMoreInfo,5,15,29,38,40);
- packet(0x0085,12,clif->pChangeDir,7,11);
- //packet(0x0089,13,clif->pTickSend,9);
- packet(0x008c,12,clif->pGetCharNameRequest,8);
- packet(0x0094,23,clif->pMoveToKafra,5,19);
- packet(0x009b,37,clif->pWantToConnection,9,21,28,32,36);
- packet(0x009f,24,clif->pUseItem,9,20);
- packet(0x00a2,11,clif->pSolveCharName,7);
- packet(0x00a7,15,clif->pWalkToXY,12);
- packet(0x00f5,13,clif->pTakeItem,9);
- packet(0x00f7,26,clif->pMoveFromKafra,11,22);
- packet(0x0113,40,clif->pUseSkillToPos,5,15,29,38);
- packet(0x0116,17,clif->pDropItem,8,15);
- packet(0x0190,18,clif->pActionRequest,7,17);
-#endif
-
-//2006-10-23aSakexe
-#if PACKETVER >= 20061023
- packet(0x006d,110);
+ packet(0x0072,clif->pUseSkillToId,11,18,22);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,5,15,29,38,40);
+ packet(0x0085,clif->pChangeDir,7,11);
+ packet(0x008c,clif->pGetCharNameRequest,8);
+ packet(0x0094,clif->pMoveToKafra,5,19);
+ packet(0x009b,clif->pWantToConnection,9,21,28,32,36);
+ packet(0x009f,clif->pUseItem,9,20);
+ packet(0x00a2,clif->pSolveCharName,7);
+ packet(0x00a7,clif->pWalkToXY,12);
+ packet(0x00f5,clif->pTakeItem,9);
+ packet(0x00f7,clif->pMoveFromKafra,11,22);
+ packet(0x0113,clif->pUseSkillToPos,5,15,29,38);
+ packet(0x0116,clif->pDropItem,8,15);
+ packet(0x0190,clif->pActionRequest,7,17);
#endif
//2006-04-24aSakexe to 2007-01-02aSakexe
#if PACKETVER >= 20060424
- packet(0x023e,8);
- packet(0x0277,84);
- packet(0x0278,2);
- packet(0x0279,2);
- packet(0x027a,-1);
- packet(0x027b,14);
- packet(0x027c,60);
- packet(0x027d,62);
- packet(0x027e,-1);
- packet(0x027f,8);
- packet(0x0280,12);
- packet(0x0281,4);
- packet(0x0282,284);
- packet(0x0283,6);
- packet(0x0284,14);
- packet(0x0285,6);
- packet(0x0286,4);
- packet(0x0287,-1);
- packet(0x0288,6);
- packet(0x0289,8);
- packet(0x028a,18);
- packet(0x028b,-1);
- packet(0x028c,46);
- packet(0x028d,34);
- packet(0x028e,4);
- packet(0x028f,6);
- packet(0x0290,4);
- packet(0x0291,4);
- packet(0x0292,2,clif->pAutoRevive,0);
- packet(0x0293,70);
- packet(0x0294,10);
- packet(0x0295,-1);
- packet(0x0296,-1);
- packet(0x0297,-1);
- packet(0x0298,8);
- packet(0x0299,6);
- packet(0x029a,27);
- packet(0x029c,66);
- packet(0x029d,-1);
- packet(0x029e,11);
- packet(0x029f,3,clif->pmercenary_action,0);
- packet(0x02a0,-1);
- packet(0x02a1,-1);
- packet(0x02a2,8);
+ packet(0x0292,clif->pAutoRevive,0);
+ packet(0x029f,clif->pmercenary_action,0);
#endif
//2007-01-08aSakexe
#if PACKETVER >= 20070108
- packet(0x0072,30,clif->pUseSkillToId,10,14,26);
- packet(0x007e,120,clif->pUseSkillToPosMoreInfo,10,19,23,38,40);
- packet(0x0085,14,clif->pChangeDir,10,13);
- packet(0x0089,11,clif->pTickSend,7);
- packet(0x008c,17,clif->pGetCharNameRequest,13);
- packet(0x0094,17,clif->pMoveToKafra,4,13);
- packet(0x009b,35,clif->pWantToConnection,7,21,26,30,34);
- packet(0x009f,21,clif->pUseItem,7,17);
- packet(0x00a2,10,clif->pSolveCharName,6);
- packet(0x00a7,8,clif->pWalkToXY,5);
- packet(0x00f5,11,clif->pTakeItem,7);
- packet(0x00f7,15,clif->pMoveFromKafra,3,11);
- packet(0x0113,40,clif->pUseSkillToPos,10,19,23,38);
- packet(0x0116,19,clif->pDropItem,11,17);
- packet(0x0190,10,clif->pActionRequest,4,9);
-#endif
-
-//2007-01-22aSakexe
-#if PACKETVER >= 20070122
- packet(0x02a3,18);
- packet(0x02a4,2);
-#endif
-
-//2007-01-29aSakexe
-#if PACKETVER >= 20070129
- packet(0x029b,72);
- packet(0x02a3,-1);
- packet(0x02a4,-1);
- packet(0x02a5,8);
-
-#endif
-
-//2007-02-05aSakexe
-#if PACKETVER >= 20070205
- packet(0x02aa,4);
- packet(0x02ab,36);
- packet(0x02ac,6);
+ packet(0x0072,clif->pUseSkillToId,10,14,26);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,10,19,23,38,40);
+ packet(0x0085,clif->pChangeDir,10,13);
+ packet(0x0089,clif->pTickSend,7);
+ packet(0x008c,clif->pGetCharNameRequest,13);
+ packet(0x0094,clif->pMoveToKafra,4,13);
+ packet(0x009b,clif->pWantToConnection,7,21,26,30,34);
+ packet(0x009f,clif->pUseItem,7,17);
+ packet(0x00a2,clif->pSolveCharName,6);
+ packet(0x00a7,clif->pWalkToXY,5);
+ packet(0x00f5,clif->pTakeItem,7);
+ packet(0x00f7,clif->pMoveFromKafra,3,11);
+ packet(0x0113,clif->pUseSkillToPos,10,19,23,38);
+ packet(0x0116,clif->pDropItem,11,17);
+ packet(0x0190,clif->pActionRequest,4,9);
#endif
//2007-02-12aSakexe
#if PACKETVER >= 20070212
- packet(0x0072,25,clif->pUseSkillToId,6,10,21);
- packet(0x007e,102,clif->pUseSkillToPosMoreInfo,5,9,12,20,22);
- packet(0x0085,11,clif->pChangeDir,7,10);
- packet(0x0089,8,clif->pTickSend,4);
- packet(0x008c,11,clif->pGetCharNameRequest,7);
- packet(0x0094,14,clif->pMoveToKafra,7,10);
- packet(0x009b,26,clif->pWantToConnection,4,9,17,21,25);
- packet(0x009f,14,clif->pUseItem,4,10);
- packet(0x00a2,15,clif->pSolveCharName,11);
- //packet(0x00a7,8,clif->pWalkToXY,5);
- packet(0x00f5,8,clif->pTakeItem,4);
- packet(0x00f7,22,clif->pMoveFromKafra,14,18);
- packet(0x0113,22,clif->pUseSkillToPos,5,9,12,20);
- packet(0x0116,10,clif->pDropItem,5,8);
- packet(0x0190,19,clif->pActionRequest,5,18);
+ packet(0x0072,clif->pUseSkillToId,6,10,21);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,5,9,12,20,22);
+ packet(0x0085,clif->pChangeDir,7,10);
+ packet(0x0089,clif->pTickSend,4);
+ packet(0x008c,clif->pGetCharNameRequest,7);
+ packet(0x0094,clif->pMoveToKafra,7,10);
+ packet(0x009b,clif->pWantToConnection,4,9,17,21,25);
+ packet(0x009f,clif->pUseItem,4,10);
+ packet(0x00a2,clif->pSolveCharName,11);
+ packet(0x00f5,clif->pTakeItem,4);
+ packet(0x00f7,clif->pMoveFromKafra,14,18);
+ packet(0x0113,clif->pUseSkillToPos,5,9,12,20);
+ packet(0x0116,clif->pDropItem,5,8);
+ packet(0x0190,clif->pActionRequest,5,18);
#endif
//2007-05-07aSakexe
#if PACKETVER >= 20070507
- packet(0x01fd,15,clif->pRepairItem,2);
+ packet(0x01fd,clif->pRepairItem,2);
#endif
//2007-02-27aSakexe to 2007-10-02aSakexe
#if PACKETVER >= 20070227
- packet(0x0288,10,clif->pcashshop_buy,2,4,6);
- packet(0x0289,12);
- packet(0x02a6,22);
- packet(0x02a7,22);
- packet(0x02a8,162);
- packet(0x02a9,58);
- packet(0x02ad,8);
- packet(0x02b0,85);
- packet(0x02b1,-1);
- packet(0x02b2,-1);
- packet(0x02b3,107);
- packet(0x02b4,6);
- packet(0x02b5,-1);
- packet(0x02b6,7,clif->pquestStateAck,2,6);
- packet(0x02b7,7);
- packet(0x02b8,22);
- packet(0x02b9,191);
- packet(0x02ba,11,clif->pHotkey,2,4,5,9);
- packet(0x02bb,8);
- packet(0x02bc,6);
- packet(0x02bf,10);
- packet(0x02c0,2);
- packet(0x02c1,-1);
- packet(0x02c2,-1);
- packet(0x02c4,26,clif->pPartyInvite2,2);
- packet(0x02c5,30);
- packet(0x02c6,30);
- packet(0x02c7,7,clif->pReplyPartyInvite2,2,6);
- packet(0x02c8,3,clif->pPartyTick,2);
- packet(0x02c9,3);
- packet(0x02ca,3);
- packet(0x02cb,20);
- packet(0x02cc,4);
- packet(0x02cd,26);
- packet(0x02ce,10);
- packet(0x02cf,6);
- packet(0x02d0,-1);
- packet(0x02d1,-1);
- packet(0x02d2,-1);
- packet(0x02d3,4);
- packet(0x02d4,29);
- packet(0x02d5,2);
- packet(0x02d6,6,clif->pViewPlayerEquip,2);
- packet(0x02d7,-1);
- packet(0x02d8,10,clif->pEquipTick,6);
- packet(0x02d9,10);
- packet(0x02da,3);
- packet(0x02db,-1,clif->pBattleChat,2,4);
- packet(0x02dc,-1);
- packet(0x02dd,32);
- packet(0x02de,6);
- packet(0x02df,36);
- packet(0x02e0,34);
-#endif
-
-//2007-10-23aSakexe
-#if PACKETVER >= 20071023
- packet(0x02cb,65);
- packet(0x02cd,71);
-#endif
-
-//2007-11-06aSakexe
-#if PACKETVER >= 20071106
- packet(0x0078,55);
- packet(0x007c,42);
- packet(0x022c,65);
- packet(0x029b,80);
-#endif
-
-//2007-11-13aSakexe
-#if PACKETVER >= 20071113
- packet(0x02e1,33);
-#endif
-
-//2007-11-20aSakexe
-#if PACKETVER >= 20071120
- //packet(0x01df,10 <- ???);
- packet(0x02e2,14);
- packet(0x02e3,25);
- packet(0x02e4,8);
- packet(0x02e5,8);
- packet(0x02e6,6);
-#endif
-
-//2007-11-27aSakexe
-#if PACKETVER >= 20071127
- packet(0x02e7,-1);
+ packet(0x0288,clif->pcashshop_buy,2,4,6);
+ packet(0x02b6,clif->pquestStateAck,2,6);
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x02c7,clif->pReplyPartyInvite2,2,6);
+ packet(0x02c8,clif->pPartyTick,2);
+ packet(0x02cf,clif->pMemorialDungeonCommand);
+ packet(0x02d6,clif->pViewPlayerEquip,2);
+ packet(0x02d8,clif->p_cz_config,6);
+ packet(0x02db,clif->pBattleChat,2,4);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20070618 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO) || PACKETVER_AD_NUM >= 20070618 || PACKETVER_SAK_NUM >= 20070618
+ packet(0x02ba,clif->pHotkey1);
#endif
//2008-01-02aSakexe
#if PACKETVER >= 20080102
- packet(0x01df,6,clif->pGMReqAccountName,2);
- packet(0x02e8,-1);
- packet(0x02e9,-1);
- packet(0x02ea,-1);
- packet(0x02eb,13);
- packet(0x02ec,67);
- packet(0x02ed,59);
- packet(0x02ee,60);
- packet(0x02ef,8);
+ packet(0x01df,clif->pGMReqAccountName,2);
#endif
//2008-03-18aSakexe
#if PACKETVER >= 20080318
- packet(0x02bf,-1);
- packet(0x02c0,-1);
- packet(0x02f0,10);
- packet(0x02f1,2,clif->pProgressbar,0);
- packet(0x02f2,2);
-#endif
-
-//2008-03-25bSakexe
-#if PACKETVER >= 20080325
- packet(0x02f3,-1);
- packet(0x02f4,-1);
- packet(0x02f5,-1);
- packet(0x02f6,-1);
- packet(0x02f7,-1);
- packet(0x02f8,-1);
- packet(0x02f9,-1);
- packet(0x02fa,-1);
- packet(0x02fb,-1);
- packet(0x02fc,-1);
- packet(0x02fd,-1);
- packet(0x02fe,-1);
- packet(0x02ff,-1);
- packet(0x0300,-1);
-#endif
-
-//2008-04-01aSakexe
-#if PACKETVER >= 20080401
- packet(0x0301,-1);
- packet(0x0302,-1);
- packet(0x0303,-1);
- packet(0x0304,-1);
- packet(0x0305,-1);
- packet(0x0306,-1);
- packet(0x0307,-1);
- packet(0x0308,-1);
- packet(0x0309,-1);
- packet(0x030a,-1);
- packet(0x030b,-1);
- packet(0x030c,-1);
- packet(0x030d,-1);
- packet(0x030e,-1);
- packet(0x030f,-1);
- packet(0x0310,-1);
- packet(0x0311,-1);
- packet(0x0312,-1);
- packet(0x0313,-1);
- packet(0x0314,-1);
- packet(0x0315,-1);
- packet(0x0316,-1);
- packet(0x0317,-1);
- packet(0x0318,-1);
- packet(0x0319,-1);
- packet(0x031a,-1);
- packet(0x031b,-1);
- packet(0x031c,-1);
- packet(0x031d,-1);
- packet(0x031e,-1);
- packet(0x031f,-1);
- packet(0x0320,-1);
- packet(0x0321,-1);
- packet(0x0322,-1);
- packet(0x0323,-1);
- packet(0x0324,-1);
- packet(0x0325,-1);
- packet(0x0326,-1);
- packet(0x0327,-1);
- packet(0x0328,-1);
- packet(0x0329,-1);
- packet(0x032a,-1);
- packet(0x032b,-1);
- packet(0x032c,-1);
- packet(0x032d,-1);
- packet(0x032e,-1);
- packet(0x032f,-1);
- packet(0x0330,-1);
- packet(0x0331,-1);
- packet(0x0332,-1);
- packet(0x0333,-1);
- packet(0x0334,-1);
- packet(0x0335,-1);
- packet(0x0336,-1);
- packet(0x0337,-1);
- packet(0x0338,-1);
- packet(0x0339,-1);
- packet(0x033a,-1);
- packet(0x033b,-1);
- packet(0x033c,-1);
- packet(0x033d,-1);
- packet(0x033e,-1);
- packet(0x033f,-1);
- packet(0x0340,-1);
- packet(0x0341,-1);
- packet(0x0342,-1);
- packet(0x0343,-1);
- packet(0x0344,-1);
- packet(0x0345,-1);
- packet(0x0346,-1);
- packet(0x0347,-1);
- packet(0x0348,-1);
- packet(0x0349,-1);
- packet(0x034a,-1);
- packet(0x034b,-1);
- packet(0x034c,-1);
- packet(0x034d,-1);
- packet(0x034e,-1);
- packet(0x034f,-1);
- packet(0x0350,-1);
- packet(0x0351,-1);
- packet(0x0352,-1);
- packet(0x0353,-1);
- packet(0x0354,-1);
- packet(0x0355,-1);
- packet(0x0356,-1);
- packet(0x0357,-1);
- packet(0x0358,-1);
- packet(0x0359,-1);
- packet(0x035a,-1);
-#endif
-
-//2008-05-27aSakexe
-#if PACKETVER >= 20080527
- packet(0x035b,-1);
- packet(0x035c,2);
- packet(0x035d,-1);
- packet(0x035e,2);
- packet(0x035f,-1);
- packet(0x0389,-1);
-#endif
-
-//2008-08-20aSakexe
-#if PACKETVER >= 20080820
- packet(0x040c,-1);
- packet(0x040d,-1);
- packet(0x040e,-1);
- packet(0x040f,-1);
- packet(0x0410,-1);
- packet(0x0411,-1);
- packet(0x0412,-1);
- packet(0x0413,-1);
- packet(0x0414,-1);
- packet(0x0415,-1);
- packet(0x0416,-1);
- packet(0x0417,-1);
- packet(0x0418,-1);
- packet(0x0419,-1);
- packet(0x041a,-1);
- packet(0x041b,-1);
- packet(0x041c,-1);
- packet(0x041d,-1);
- packet(0x041e,-1);
- packet(0x041f,-1);
- packet(0x0420,-1);
- packet(0x0421,-1);
- packet(0x0422,-1);
- packet(0x0423,-1);
- packet(0x0424,-1);
- packet(0x0425,-1);
- packet(0x0426,-1);
- packet(0x0427,-1);
- packet(0x0428,-1);
- packet(0x0429,-1);
- packet(0x042a,-1);
- packet(0x042b,-1);
- packet(0x042c,-1);
- packet(0x042d,-1);
- packet(0x042e,-1);
- packet(0x042f,-1);
- packet(0x0430,-1);
- packet(0x0431,-1);
- packet(0x0432,-1);
- packet(0x0433,-1);
- packet(0x0434,-1);
- packet(0x0435,-1);
+ packet(0x02f1,clif->pProgressbar,0);
#endif
//2008-09-10aSakexe
#if PACKETVER >= 20080910
- packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0437,7,clif->pActionRequest,2,6);
- packet(0x0438,10,clif->pUseSkillToId,2,4,6);
- packet(0x0439,8,clif->pUseItem,2,4);
-#endif
-
-//2008-11-13aSakexe
-#if PACKETVER >= 20081113
- packet(0x043d,8);
- packet(0x043e,-1);
- packet(0x043f,8);
-#endif
-
-//2008-11-26aSakexe
-#if PACKETVER >= 20081126
- packet(0x01a2,37);
- packet(0x0440,10);
- packet(0x0441,4);
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0439,clif->pUseItem,2,4);
#endif
//2008-12-10aSakexe
#if PACKETVER >= 20081210
- packet(0x0442,-1);
- packet(0x0443,8,clif->pSkillSelectMenu,2,6);
-#endif
-
-//2009-01-14aSakexe
-#if PACKETVER >= 20090114
- packet(0x043f,25);
- packet(0x0444,-1);
- packet(0x0445,10);
-#endif
-
-//2009-02-18aSakexe
-#if PACKETVER >= 20090218
- packet(0x0446,14);
-#endif
-
-//2009-02-25aSakexe
-#if PACKETVER >= 20090225
- packet(0x0448,-1);
-#endif
-
-//2009-03-30aSakexe
-#if PACKETVER >= 20090330
- packet(0x0449,4);
-#endif
-
-//2009-04-08aSakexe
-#if PACKETVER >= 20090408
- packet(0x02a6,-1);
- packet(0x02a7,-1);
- packet(0x044a,6);
+ packet(0x0443,clif->pSkillSelectMenu,2,6);
#endif
//2008-08-27aRagexeRE
#if PACKETVER >= 20080827
- packet(0x0072,22,clif->pUseSkillToId,9,15,18);
- packet(0x007c,44);
- packet(0x007e,105,clif->pUseSkillToPosMoreInfo,10,14,18,23,25);
- packet(0x0085,10,clif->pChangeDir,4,9);
- packet(0x0089,11,clif->pTickSend,7);
- packet(0x008c,14,clif->pGetCharNameRequest,10);
- packet(0x0094,19,clif->pMoveToKafra,3,15);
- packet(0x009b,34,clif->pWantToConnection,7,15,25,29,33);
- packet(0x009f,20,clif->pUseItem,7,20);
- packet(0x00a2,14,clif->pSolveCharName,10);
- packet(0x00a7,9,clif->pWalkToXY,6);
- packet(0x00f5,11,clif->pTakeItem,7);
- packet(0x00f7,17,clif->pMoveFromKafra,3,13);
- packet(0x0113,25,clif->pUseSkillToPos,10,14,18,23);
- packet(0x0116,17,clif->pDropItem,6,15);
- packet(0x0190,23,clif->pActionRequest,9,22);
- packet(0x02e2,20);
- packet(0x02e3,22);
- packet(0x02e4,11);
- packet(0x02e5,9);
+ packet(0x0072,clif->pUseSkillToId,9,15,18);
+ packet(0x007e,clif->pUseSkillToPosMoreInfo,10,14,18,23,25);
+ packet(0x0085,clif->pChangeDir,4,9);
+ packet(0x0089,clif->pTickSend,7);
+ packet(0x008c,clif->pGetCharNameRequest,10);
+ packet(0x0094,clif->pMoveToKafra,3,15);
+ packet(0x009b,clif->pWantToConnection,7,15,25,29,33);
+ packet(0x009f,clif->pUseItem,7,20);
+ packet(0x00a2,clif->pSolveCharName,10);
+ packet(0x00a7,clif->pWalkToXY,6);
+ packet(0x00f5,clif->pTakeItem,7);
+ packet(0x00f7,clif->pMoveFromKafra,3,13);
+ packet(0x0113,clif->pUseSkillToPos,10,14,18,23);
+ packet(0x0116,clif->pDropItem,6,15);
+ packet(0x0190,clif->pActionRequest,9,22);
#endif
//2008-09-10aRagexeRE
#if PACKETVER >= 20080910
- packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0437,7,clif->pActionRequest,2,6);
- packet(0x0438,10,clif->pUseSkillToId,2,4,6);
- packet(0x0439,8,clif->pUseItem,2,4);
-
-#endif
-
-//2008-11-12aRagexeRE
-#if PACKETVER >= 20081112
- packet(0x043d,8);
- //packet(0x043e,-1);
- packet(0x043f,8);
-#endif
-
-//2008-12-17aRagexeRE
-#if PACKETVER >= 20081217
- packet(0x01a2,37);
- //packet(0x0440,10);
- //packet(0x0441,4);
- //packet(0x0442,8);
- //packet(0x0443,8);
-#endif
-
-//2008-12-17bRagexeRE
-#if PACKETVER >= 20081217
- packet(0x006d,114);
-
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0439,clif->pUseItem,2,4);
#endif
-//2009-01-21aRagexeRE
-#if PACKETVER >= 20090121
- packet(0x043f,25);
- //packet(0x0444,-1);
- //packet(0x0445,10);
+#if PACKETVER_MAIN_NUM >= 20090406 || PACKETVER_RE_NUM >= 20090408 || PACKETVER_SAK_NUM >= 20090408 || defined(PACKETVER_ZERO)
+ packet(0x044a,clif->pClientVersion);
#endif
-//2009-02-18aRagexeRE
-#if PACKETVER >= 20090218
- //packet(0x0446,14);
-#endif
-
-//2009-02-26cRagexeRE
-#if PACKETVER >= 20090226
- //packet(0x0448,-1);
-#endif
-
-//2009-04-01aRagexeRE
-#if PACKETVER >= 20090401
- //packet(0x0449,4);
-#endif
-
-//2009-05-14aRagexeRE
-#if PACKETVER >= 20090514
- //packet(0x044b,2);
-#endif
-
-//2009-05-20aRagexeRE
+// 2009-05-20aRagexe, 2009-05-20aRagexeRE
#if PACKETVER >= 20090520
- //packet(0x07d0,6);
- //packet(0x07d1,2);
- //packet(0x07d2,-1);
- //packet(0x07d3,4);
- //packet(0x07d4,4);
- //packet(0x07d5,4);
- //packet(0x07d6,4);
- //packet(0x0447,2);
+// new packets
+ packet(0x0447,clif->p_cz_blocking_play_cancel); // PACKET_CZ_BLOCKING_PLAY_CANCEL
#endif
//2009-06-03aRagexeRE
#if PACKETVER >= 20090603
- packet(0x07d7,8,clif->pPartyChangeOption,2,6,7);
- packet(0x07d8,8);
- packet(0x07d9,254);
- packet(0x07da,6,clif->pPartyChangeLeader,2);
-#endif
-
-//2009-06-10aRagexeRE
-#if PACKETVER >= 20090610
- //packet(0x07db,8);
-#endif
-
-//2009-06-17aRagexeRE
-#if PACKETVER >= 20090617
- packet(0x07d9,268);
- //packet(0x07dc,6);
- //packet(0x07dd,54);
- //packet(0x07de,30);
- //packet(0x07df,54);
-#endif
-
-//2009-07-01aRagexeRE
-#if PACKETVER >= 20090701
- //packet(0x0275,37);
- //packet(0x0276,-1);
-#endif
-
-//2009-07-08aRagexeRE
-#if PACKETVER >= 20090708
- //packet(0x07e0,58);
-#endif
-
-//2009-07-15aRagexeRE
-#if PACKETVER >= 20090715
- packet(0x07e1,15);
-#endif
-
-//2009-08-05aRagexeRE
-#if PACKETVER >= 20090805
- packet(0x07e2,8);
+ packet(0x07d7,clif->pPartyChangeOption,2,6,7);
+ packet(0x07da,clif->pPartyChangeLeader,2);
#endif
//2009-08-18aRagexeRE
#if PACKETVER >= 20090818
- packet(0x07e3,6);
- packet(0x07e4,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x07e6,8);
-#endif
-
-//2009-08-25aRagexeRE
-#if PACKETVER >= 20090825
- //packet(0x07e6,28);
- packet(0x07e7,5);
-#endif
-
-//2009-09-22aRagexeRE
-#if PACKETVER >= 20090922
- packet(0x07e5,8);
- packet(0x07e6,8);
- packet(0x07e7,32);
- packet(0x07e8,-1);
- packet(0x07e9,5);
-#endif
-
-//2009-09-29aRagexeRE
-#if PACKETVER >= 20090929
- //packet(0x07ea,2);
- //packet(0x07eb,-1);
- //packet(0x07ec,6);
- //packet(0x07ed,8);
- //packet(0x07ee,6);
- //packet(0x07ef,8);
- //packet(0x07f0,4);
- //packet(0x07f2,4);
- //packet(0x07f3,3);
-#endif
-
-//2009-10-06aRagexeRE
-#if PACKETVER >= 20091006
- //packet(0x07ec,8);
- //packet(0x07ed,10);
- //packet(0x07f0,8);
- //packet(0x07f1,15);
- //packet(0x07f2,6);
- //packet(0x07f3,4);
- //packet(0x07f4,3);
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
#endif
//2009-10-27aRagexeRE
#if PACKETVER >= 20091027
- packet(0x07f5,6,clif->pGMFullStrip,2);
- packet(0x07f6,14);
-#endif
-
-//2009-11-03aRagexeRE
-#if PACKETVER >= 20091103
- packet(0x07f7,-1);
- packet(0x07f8,-1);
- packet(0x07f9,-1);
-#endif
-
-//2009-11-17aRagexeRE
-#if PACKETVER >= 20091117
- packet(0x07fa,8);
-
-#endif
-
-//2009-11-24aRagexeRE
-#if PACKETVER >= 20091124
- packet(0x07fb,25);
-#endif
-
-//2009-12-01aRagexeRE
-#if PACKETVER >= 20091201
- //packet(0x07fc,10);
- //packet(0x07fd,-1);
- packet(0x07fe,26);
- //packet(0x07ff,-1);
-#endif
-
-//2009-12-15aRagexeRE
-#if PACKETVER >= 20091215
- packet(0x0800,-1);
- //packet(0x0801,-1);
+ packet(0x07f5,clif->pGMFullStrip,2);
#endif
//2009-12-22aRagexeRE
#if PACKETVER >= 20091222
- packet(0x0802,18,clif->pPartyBookingRegisterReq,2,4,6); // Booking System
- packet(0x0803,4);
- packet(0x0804,8); // Booking System
- packet(0x0805,-1);
- packet(0x0806,4,clif->pPartyBookingDeleteReq,2);// Booking System
- //packet(0x0807,2);
- packet(0x0808,4); // Booking System
- //packet(0x0809,14);
- //packet(0x080A,50);
- //packet(0x080B,18);
- //packet(0x080C,6);
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4,6); // Booking System
+ packet(0x0806,clif->pPartyBookingDeleteReq,2);// Booking System
#endif
//2009-12-29aRagexeRE
#if PACKETVER >= 20091229
- packet(0x0804,14,clif->pPartyBookingSearchReq,2,4,6,8,12);// Booking System
- packet(0x0806,2,clif->pPartyBookingDeleteReq,0);// Booking System
- packet(0x0807,4);
- packet(0x0808,14,clif->pPartyBookingUpdateReq,2); // Booking System
- packet(0x0809,50);
- packet(0x080A,18);
- packet(0x080B,6);// Booking System
+ packet(0x0804,clif->pPartyBookingSearchReq,2,4,6,8,12);// Booking System
+ packet(0x0806,clif->pPartyBookingDeleteReq,0);// Booking System
+ packet(0x0808,clif->pPartyBookingUpdateReq,2); // Booking System
#endif
//2010-01-05aRagexeRE
#if PACKETVER >= 20100105
- packet(0x0801,-1,clif->pPurchaseReq2,2,4,8,12);
-#endif
-
- //2010-01-26aRagexeRE
-#if PACKETVER >= 20100126
- //packet(0x080C,2);
- //packet(0x080D,3);
- packet(0x080E,14);
+ packet(0x0801,clif->pPurchaseReq2,2,4,8,12);
#endif
- //2010-02-09aRagexeRE
-#if PACKETVER >= 20100209
- //packet(0x07F0,6);
-#endif
-
- //2010-02-23aRagexeRE
-#if PACKETVER >= 20100223
- packet(0x080F,20);
-#endif
-
- //2010-03-03aRagexeRE
+//2010-03-03aRagexeRE
#if PACKETVER >= 20100303
- packet(0x0810,3);
- packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- //packet(0x0812,86);
- //packet(0x0813,6);
- //packet(0x0814,6);
- //packet(0x0815,-1);
- //packet(0x0817,-1);
- //packet(0x0818,6);
- //packet(0x0819,4);
-#endif
-
- //2010-03-09aRagexeRE
-#if PACKETVER >= 20100309
- packet(0x0813,-1);
- //packet(0x0814,2);
- //packet(0x0815,6);
- packet(0x0816,6);
- packet(0x0818,-1);
- //packet(0x0819,10);
- //packet(0x081A,4);
- //packet(0x081B,4);
- //packet(0x081C,6);
- packet(0x081d,22);
- packet(0x081e,8);
-#endif
-
- //2010-03-23aRagexeRE
-#if PACKETVER >= 20100323
- //packet(0x081F,-1);
-#endif
-
- //2010-04-06aRagexeRE
-#if PACKETVER >= 20100406
- //packet(0x081A,6);
-#endif
-
- //2010-04-13aRagexeRE
-#if PACKETVER >= 20100413
- //packet(0x081A,10);
- packet(0x0820,11);
- //packet(0x0821,2);
- //packet(0x0822,9);
- //packet(0x0823,-1);
-#endif
-
- //2010-04-14dRagexeRE
-#if PACKETVER >= 20100414
- //packet(0x081B,8);
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#endif
//2010-04-20aRagexeRE
#if PACKETVER >= 20100420
- packet(0x0812,8);
- packet(0x0814,86);
- packet(0x0815,2,clif->pReqCloseBuyingStore,0);
- packet(0x0817,6,clif->pReqClickBuyingStore,2);
- packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x081a,4);
- packet(0x081b,10);
- packet(0x081c,10);
- packet(0x0824,6);
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
#endif
//2010-06-01aRagexeRE
#if PACKETVER >= 20100601
- //packet(0x0825,-1);
- //packet(0x0826,4);
- packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0836,-1);
- packet(0x0837,3);
- //packet(0x0838,3);
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
#endif
//2010-06-08aRagexeRE
#if PACKETVER >= 20100608
- packet(0x0838,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x083A,4); // Search Stalls Feature
- packet(0x083B,2,clif->pCloseSearchStoreInfo,0);
- packet(0x083C,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x083D,6);
-#endif
-
-//2010-06-15aRagexeRE
-#if PACKETVER >= 20100615
- //packet(0x083E,26);
-#endif
-
-//2010-06-22aRagexeRE
-#if PACKETVER >= 20100622
- //packet(0x083F,22);
-#endif
-
-//2010-06-29aRagexeRE
-#if PACKETVER >= 20100629
- packet(0x00AA,9);
- //packet(0x07F1,18);
- //packet(0x07F2,8);
- //packet(0x07F3,6);
-#endif
-
-//2010-07-01aRagexeRE
-#if PACKETVER >= 20100701
- packet(0x083A,5);// Search Stalls Feature
-#endif
-
-//2010-07-13aRagexeRE
-#if PACKETVER >= 20100713
- //packet(0x0827,6);
- //packet(0x0828,14);
- //packet(0x0829,6);
- //packet(0x082A,10);
- //packet(0x082B,6);
- //packet(0x082C,14);
- //packet(0x0840,-1);
- //packet(0x0841,19);
-#endif
-
-//2010-07-14aRagexeRE
-#if PACKETVER >= 20100714
- //packet(0x841,4);
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x083B,clif->pCloseSearchStoreInfo,0);
+ packet(0x083C,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
#endif
//2010-08-03aRagexeRE
#if PACKETVER >= 20100803
- packet(0x0839,66);
- packet(0x0842,6,clif->pGMRecall2,2);
- packet(0x0843,6,clif->pGMRemove2,2);
+ packet(0x0842,clif->pGMRecall2,2);
+ packet(0x0843,clif->pGMRemove2,2);
+#endif
+
+// all versions
+#if PACKETVER >= 20100824
+ packet(0x0844,clif->pCashShopOpen1);
#endif
//2010-11-24aRagexeRE
#if PACKETVER >= 20101124
- packet(0x0288,-1,clif->pcashshop_buy,4,8);
- packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x035f,5,clif->pWalkToXY,2);
- packet(0x0360,6,clif->pTickSend,2);
- packet(0x0361,5,clif->pChangeDir,2,4);
- packet(0x0362,6,clif->pTakeItem,2);
- packet(0x0363,6,clif->pDropItem,2,4);
- packet(0x0364,8,clif->pMoveToKafra,2,4);
- packet(0x0365,8,clif->pMoveFromKafra,2,4);
- packet(0x0366,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x0367,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x0368,6,clif->pGetCharNameRequest,2);
- packet(0x0369,6,clif->pSolveCharName,2);
- packet(0x0856,-1);
- packet(0x0857,-1);
- packet(0x0858,-1);
- packet(0x0859,-1);
+ packet(0x0288,clif->pcashshop_buy,4,8);
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+#endif
+
+// 2011-01-25aRagexe
+#if PACKETVER >= 20110125
+// shuffle packets not added
+// new packets
+ packet(0x08b5,clif->pDull,2); // CZ_TRYCOLLECTION
+#endif
+
+// 2011-01-31aRagexe
+#if PACKETVER >= 20110131
+// shuffle packets not added
+// new packets
+ packet(0x02f3,clif->pDull); // CZ_IRMAIL_SEND
+ packet(0x02f6,clif->pDull,2); // CZ_IRMAIL_LIST
+#endif
+
+// 2011-02-22aRagexe
+#if PACKETVER >= 20110222
+// shuffle packets not added
+// new packets
+ packet(0x08c1,clif->pDull); // CZ_MACRO_START
+ packet(0x08c2,clif->pDull); // CZ_MACRO_STOP
+#endif
+
+// 2011-06-14aRagexe
+#if PACKETVER >= 20110614
+// shuffle packets not added
+// new packets
+ packet(0x08c9,clif->pCashShopSchedule,0);
#endif
//2011-07-18aRagexe (Thanks to Yommy!)
#if PACKETVER >= 20110718
- packet(0x0844,2,clif->pCashShopOpen,2);/* tell server cashshop window is being open */
- packet(0x084a,2,clif->pCashShopClose,2);/* tell server cashshop window is being closed */
- packet(0x0846,4,clif->pCashShopReqTab,2);
- packet(0x08c9,2,clif->pCashShopSchedule,0);
- packet(0x0848,-1,clif->pCashShopBuy,2);
+// shuffle packets not added
+ packet(0x084a,clif->pCashShopClose,2);/* tell server cashshop window is being closed */
+ packet(0x0846,clif->pCashShopReqTab,2);
+ packet(0x0848,clif->pCashShopBuy,2);
#endif
//2011-10-05aRagexeRE
#if PACKETVER >= 20111005
- packet(0x0364,5,clif->pWalkToXY,2);
- packet(0x0817,6,clif->pTickSend,2);
- packet(0x0366,5,clif->pChangeDir,2,4);
- packet(0x0815,6,clif->pTakeItem,2);
- packet(0x0885,6,clif->pDropItem,2,4);
- packet(0x0893,8,clif->pMoveToKafra,2,4);
- packet(0x0897,8,clif->pMoveFromKafra,2,4);
- packet(0x0369,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x08ad,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x088a,6,clif->pGetCharNameRequest,2);
- packet(0x0838,6,clif->pSolveCharName,2);
- packet(0x0439,8,clif->pUseItem,2,4);
- packet(0x08d2,10);
- packet(0x08d7,28,clif->pBGQueueRegister,2);
- packet(0x090a,26,clif->pBGQueueCheckState,2);
- packet(0x08da,26,clif->pBGQueueRevokeReq,2);
- packet(0x08e0,51,clif->pBGQueueBattleBeginAck,2);
+ packet(0x0364,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0817,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0366,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0815,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0893,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0897,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0369,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x08ad,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x088a,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0838,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0439,clif->pUseItem,2,4);
+ packet(0x08d7,clif->pBGQueueRegister,2);
+ packet(0x090a,clif->pBGQueueCheckState,2);
+ packet(0x08da,clif->pBGQueueRevokeReq,2);
+ packet(0x08e0,clif->pBGQueueBattleBeginAck,2);
#endif
//2011-11-02aRagexe
#if PACKETVER >= 20111102
- packet(0x0436,26,clif->pFriendsListAdd,2);
- packet(0x0898,5,clif->pHomMenu,4);
- packet(0x0281,36,clif->pStoragePassword,0);
- packet(0x088d,26,clif->pPartyInvite2,2);
- packet(0x083c,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x08aa,7,clif->pActionRequest,2,6);
- packet(0x02c4,10,clif->pUseSkillToId,2,4,6);
- packet(0x0811,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x890,8);
- packet(0x08a5,18,clif->pPartyBookingRegisterReq,2,4,6);
- packet(0x0835,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x089b,2,clif->pReqCloseBuyingStore,0);
- packet(0x08a1,6,clif->pReqClickBuyingStore,2);
- packet(0x089e,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x08ab,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x088b,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x08a2,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0898,clif->pHomMenu,4);
+ packet(0x0281,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x088d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x083c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x08aa,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x02c4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0811,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x08a5,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x0835,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x089b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x08a1,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x089e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x08ab,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x088b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x08a2,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
#ifndef PACKETVER_RE
- packet(0x0835,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0892,5,clif->pWalkToXY,2);
- packet(0x0899,6,clif->pTickSend,2);
+ packet(0x0835,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0892,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0899,clif->pTickSend,2); // CZ_REQUEST_TIME
#endif
#endif
//2012-03-07fRagexeRE
#if PACKETVER >= 20120307
- packet(0x086A,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0437,5,clif->pWalkToXY,2);
- packet(0x0887,6,clif->pTickSend,2);
- packet(0x0890,5,clif->pChangeDir,2,4);
- packet(0x0865,6,clif->pTakeItem,2);
- packet(0x02C4,6,clif->pDropItem,2,4);
- packet(0x093B,8,clif->pMoveToKafra,2,4);
- packet(0x0963,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(0x0369,26,clif->pFriendsListAdd,2);
- packet(0x0863,5,clif->pHomMenu,4);
- packet(0x0861,36,clif->pStoragePassword,0);
- packet(0x0929,26,clif->pPartyInvite2,2);
- packet(0x0885,7,clif->pActionRequest,2,6);
- packet(0x0889,10,clif->pUseSkillToId,2,4,6);
- packet(0x0870,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4,6);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0817,2,clif->pReqCloseBuyingStore,0);
- packet(0x0360,6,clif->pReqClickBuyingStore,2);
- packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0884,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0439,8,clif->pUseItem,2,4);
+ packet(0x086A,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0887,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0890,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0865,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x02C4,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x093B,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0369,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0863,clif->pHomMenu,4);
+ packet(0x0861,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0929,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0885,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0889,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0870,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0884,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0439,clif->pUseItem,2,4);
+// changed packet sizes
#endif
//2012-04-10aRagexeRE
#if PACKETVER >= 20120410
- packet(0x01FD,15,clif->pRepairItem,2);
- packet(0x089C,26,clif->pFriendsListAdd,2);
- packet(0x0885,5,clif->pHomMenu,2,4);
- packet(0x0961,36,clif->pStoragePassword,0);
- packet(0x0288,-1,clif->pcashshop_buy,4,8);
- packet(0x091C,26,clif->pPartyInvite2,2);
- packet(0x094B,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0369,7,clif->pActionRequest,2,6);
- packet(0x083C,10,clif->pUseSkillToId,2,4,6);
- packet(0x0439,8,clif->pUseItem,2,4);
- packet(0x0945,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0817,2,clif->pReqCloseBuyingStore,0);
- packet(0x0360,6,clif->pReqClickBuyingStore,2);
- packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0437,5,clif->pWalkToXY,2);
- packet(0x0886,6,clif->pTickSend,2);
- packet(0x0871,5,clif->pChangeDir,2,4);
- packet(0x0938,6,clif->pTakeItem,2);
- packet(0x0891,6,clif->pDropItem,2,4);
- packet(0x086C,8,clif->pMoveToKafra,2,4);
- packet(0x08A6,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(0x0889,6,clif->pGetCharNameRequest,2);
- packet(0x0884,6,clif->pSolveCharName,2);
+ packet(0x01FD,clif->pRepairItem,2);
+ packet(0x089C,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0885,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0961,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0288,clif->pcashshop_buy,4,8);
+ packet(0x091C,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x094B,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0439,clif->pUseItem,2,4);
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0886,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0871,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0938,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0891,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x086C,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x08A6,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0889,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0884,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
#ifndef PACKETVER_RE
- packet(0x091D,18,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x091D,clif->pPartyBookingRegisterReq,2,4,6);
#else
- packet(0x08E5,41,clif->pPartyRecruitRegisterReq,2,4);
-#endif
- packet(0x08E6,4);
- packet(0x08E7,10,clif->pPartyRecruitSearchReq,2);
- packet(0x08E8,-1);
- packet(0x08E9,2,clif->pPartyRecruitDeleteReq,2);
- packet(0x08EA,4);
- packet(0x08EB,39,clif->pPartyRecruitUpdateReq,2);
- packet(0x08EC,73);
- packet(0x08ED,43);
- packet(0x08EE,6);
+ packet(0x08E5,clif->pPartyRecruitRegisterReq,2,4);
+#endif
+ packet(0x08E7,clif->pPartyRecruitSearchReq,2);
+ packet(0x08E9,clif->pPartyRecruitDeleteReq,2);
+ packet(0x08EB,clif->pPartyRecruitUpdateReq,2);
#ifdef PARTY_RECRUIT
- packet(0x08EF,6,clif->pDull,2); //bookingignorereq
- packet(0x08F0,6,clif->pDull,2);
- packet(0x08F1,6,clif->pDull,2); //bookingjoinpartyreq
-#endif
- packet(0x08F2,36);
- packet(0x08F3,-1);
- packet(0x08F4,6);
- packet(0x08F5,-1,clif->pDull,2,4); //bookingsummonmember
- packet(0x08F6,22);
- packet(0x08F7,3);
- packet(0x08F8,7);
- packet(0x08F9,6);
+ packet(0x08EF,clif->pDull,2); //bookingignorereq
+ packet(0x08F0,clif->pDull,2);
+ packet(0x08F1,clif->pDull,2); //bookingjoinpartyreq
+#endif
+ packet(0x08F5,clif->pDull,2,4); //bookingsummonmember
#ifdef PARTY_RECRUIT
- packet(0x08F9,6,clif->pDull,2);
+ packet(0x08F9,clif->pDull,2);
#endif
- packet(0x08FA,6);
- packet(0x08FB,6,clif->pDull,2); //bookingcanceljoinparty
- packet(0x0907,5,clif->pMoveItem,2,4);
- packet(0x0908,5);
- packet(0x08CF,10);//Amulet spirits
- packet(0x0977,14);//Monster HP Bar
+ packet(0x08FB,clif->pDull,2); //bookingcanceljoinparty
+ packet(0x0907,clif->pMoveItem,2,4);
#endif
//2012-04-18aRagexeRE [Special Thanks to Judas!]
#if PACKETVER >= 20120418
- packet(0x023B,26,clif->pFriendsListAdd,2);
- packet(0x0361,5,clif->pHomMenu,2,4);
- packet(0x08A8,36,clif->pStoragePassword,0);
- packet(0x0802,26,clif->pPartyInvite2,2);
- packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
- 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(0x096A,6,clif->pGetCharNameRequest,2);
- packet(0x0368,6,clif->pSolveCharName,2);
- packet(0x08E5,41,clif->pPartyRecruitRegisterReq,2,4);
- packet(0x08d2,10);
- packet(0x0916,26,clif->pGuildInvite2,2);
+ packet(0x023B,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x08A8,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x022D,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x08E5,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0916,clif->pGuildInvite2,2);
+#endif
+
+// 2012-05-02aRagexeRE
+#if PACKETVER >= 20120502
+// shuffle packets not added
+ packet(0x0980,clif->pSelectCart); // CZ_SELECTCART
#endif
#ifndef PACKETVER_RE
#if PACKETVER >= 20120604
- packet(0x0861,18,clif->pPartyRecruitRegisterReq,2,4,6);
-#endif
+// shuffle packets not added
+ packet(0x0861,clif->pPartyRecruitRegisterReq,2,4,6);
#endif
-
-//2012-06-18aRagexeRE
-#if PACKETVER >= 20120618
- packet(0x0983,29);
#endif
// ========== 2012-07-02aRagexeRE =============
// - 2012-07-02 is NOT STABLE.
// - The packets are kept here for reference, DONT USE THEM.
#if PACKETVER >= 20120702
- packet(0x0363,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0364,6,clif->pTickSend,2);
- packet(0x085a,7,clif->pActionRequest,2,6);
- packet(0x0861,8,clif->pMoveFromKafra,2,4);
- packet(0x0862,10,clif->pUseSkillToId,2,4,6);
- packet(0x0863,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x0886,6,clif->pSolveCharName,2);
- packet(0x0889,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x089e,6,clif->pDropItem,2,4);
- packet(0x089f,6,clif->pTakeItem,2);
- packet(0x08a0,8,clif->pMoveToKafra,2,4);
- packet(0x094a,6,clif->pGetCharNameRequest,2);
- packet(0x0953,5,clif->pWalkToXY,2);
- packet(0x0960,5,clif->pChangeDir,2,4);
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0364,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x085a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0861,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0862,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0863,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0886,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0889,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x089e,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x089f,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x094a,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0953,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0960,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
#endif
//2012-07-10
#if PACKETVER >= 20120710
- packet(0x0886,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0886,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
#endif
//2012-07-16aRagExe (special thanks to Yommy/Frost!)
#if PACKETVER >= 20120716
- packet(0x0879,18,clif->pPartyBookingRegisterReq,2,4,6);
- packet(0x023B,26,clif->pFriendsListAdd,2);
- packet(0x0361,5,clif->pHomMenu,2,4);
- packet(0x0819,36,clif->pStoragePassword,0);
- packet(0x0802,26,clif->pPartyInvite2,2);
- packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0369,7,clif->pActionRequest,2,6);
- packet(0x083C,10,clif->pUseSkillToId,2,4,6);
- packet(0x0439,8,clif->pUseItem,2,4);
- packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0817,2,clif->pReqCloseBuyingStore,0);
- packet(0x0360,6,clif->pReqClickBuyingStore,2);
- packet(0x0940,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0811,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- 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(0x0879,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x023B,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0819,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x022D,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0439,clif->pUseItem,2,4);
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0940,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0811,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0436,clif->pDull); // CZ_GANGSI_RANK
+#endif
+
+//2012-07-16aRagExe
+#if PACKETVER >= 20120716
+// new packets
+ packet(0x098d,clif->pClanMessage,2,4); // CZ_CLAN_CHAT
+#endif
+
+// 2012-09-25aRagexe
+#if PACKETVER >= 20120925
+// new packets (not all)
+ packet(0x0998,clif->pEquipItem,2,4);
+#endif
+
+// 2013-03-06aRagexe
+#if PACKETVER >= 20130306
+// new packets
+ packet(0x09a7,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_DEPOSIT
+ packet(0x09a9,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_WITHDRAW
+// changed packet sizes
+#endif
+
+// 2013-03-13aRagexe
+#if PACKETVER >= 20130313
+// new packets
+ packet(0x09ab,clif->pDull/*,XXX*/); // CZ_REQ_BANKING_CHECK
+ packet(0x09ac,clif->pDull/*,XXX*/); // CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO
+ packet(0x09ae,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM
+ packet(0x09b0,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM
+// changed packet sizes
#endif
//2013-03-20Ragexe (Judas + Yommy)
#if PACKETVER >= 20130320
// Shuffle Start
- packet(0x088E,7,clif->pActionRequest,2,6);
- packet(0x089B,10,clif->pUseSkillToId,2,4,6);
- packet(0x0881,5,clif->pWalkToXY,2);
- packet(0x0363,6,clif->pTickSend,2);
- packet(0x0897,5,clif->pChangeDir,2,4);
- packet(0x0933,6,clif->pTakeItem,2);
- packet(0x0438,6,clif->pDropItem,2,4);
- packet(0x08AC,8,clif->pMoveToKafra,2,4);
- packet(0x0874,8,clif->pMoveFromKafra,2,4);
- packet(0x0959,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x085A,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x0898,6,clif->pGetCharNameRequest,2);
- packet(0x094C,6,clif->pSolveCharName,2);
- packet(0x0365,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x092E,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x094E,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0922,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x035F,6,clif->pReqClickBuyingStore,2);
- packet(0x0886,2,clif->pReqCloseBuyingStore,0);
- packet(0x0938,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x088E,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x089B,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0881,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0363,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0933,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0438,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x08AC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0874,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0959,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x085A,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0898,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x094C,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x092E,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x094E,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0922,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x035F,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0886,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0938,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x085D,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x085D,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x085D,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x085D,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- //packet(0x095A,8); // unknown usage
- packet(0x0868,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0888,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x086D,26,clif->pPartyInvite2,2);
- //packet(0x0890,4); // unknown usage
- packet(0x086F,26,clif->pFriendsListAdd,2);
- packet(0x093F,5,clif->pHomMenu,2,4);
- packet(0x0947,36,clif->pStoragePassword,0);
+ packet(0x0868,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x086D,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x086F,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x093F,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0890,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x095a,clif->pDull); // CZ_JOIN_BATTLE_FIELD
// Shuffle End
- // New Packets
- packet(0x0998,8,clif->pEquipItem,2,4);
- packet(0x0447,2); // PACKET_CZ_BLOCKING_PLAY_CANCEL
- packet(0x099f,24);
+ // New Packets (wrong version or packet not exists)
// New Packets End
#endif
+#if PACKETVER >= 20130320
+// new packets
+// changed packet sizes
+ packet(0x09a7,clif->pBankDeposit,2,4,6); // CZ_REQ_BANKING_DEPOSIT
+ packet(0x09a9,clif->pBankWithdraw,2,4,6); // CZ_REQ_BANKING_WITHDRAW
+ packet(0x09ab,clif->pBankCheck,2,4); // CZ_REQ_BANKING_CHECK
+#endif
+
+// 2013-03-27bRagexe
+#if PACKETVER >= 20130327
+// new packets
+ packet(0x09ac,clif->pDull/*,XXX*/); // CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO
+ packet(0x09ae,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM
+ packet(0x09b0,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM
+// changed packet sizes
+#endif
+
//2013-05-15aRagexe (Shakto)
#if PACKETVER >= 20130515
// Shuffle Start
- 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(0x0362,5,clif->pChangeDir,2,4);
- packet(0x08A1,6,clif->pTakeItem,2);
- packet(0x0944,6,clif->pDropItem,2,4);
- packet(0x0887,8,clif->pMoveToKafra,2,4);
- packet(0x08AC,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(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0362,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x08A1,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0944,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0887,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x08AC,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x092D,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x092D,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x092D,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x092D,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- //packet(0x08AA,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x0963,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0943,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0947,26,clif->pPartyInvite2,2);
- //packet(0x0862,4); // CZ_GANGSI_RANK
- packet(0x0962,26,clif->pFriendsListAdd,2);
- packet(0x0931,5,clif->pHomMenu,2,4);
- packet(0x093E,36,clif->pStoragePassword,0);
+ packet(0x0963,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0943,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0947,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0962,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x093E,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0862,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x08aa,clif->pDull); // CZ_JOIN_BATTLE_FIELD
// Shuffle End
#endif
//2013-05-22Ragexe (Shakto)
#if PACKETVER >= 20130522
// Shuffle Start
- packet(0x08A2,7,clif->pActionRequest,2,6);
- packet(0x095C,10,clif->pUseSkillToId,2,4,6);
- packet(0x0360,5,clif->pWalkToXY,2);
- packet(0x07EC,6,clif->pTickSend,2);
- packet(0x0925,5,clif->pChangeDir,2,4);
- packet(0x095E,6,clif->pTakeItem,2);
- packet(0x089C,6,clif->pDropItem,2,4);
- packet(0x08A3,8,clif->pMoveToKafra,2,4);
- packet(0x087E,8,clif->pMoveFromKafra,2,4);
- packet(0x0811,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x0964,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x08A6,6,clif->pGetCharNameRequest,2);
- packet(0x0369,6,clif->pSolveCharName,2);
- packet(0x093E,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x08AA,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x095B,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0952,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0368,6,clif->pReqClickBuyingStore,2);
- packet(0x086E,2,clif->pReqCloseBuyingStore,0);
- packet(0x0874,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x08A2,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x095C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0360,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x07EC,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x095E,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x089C,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x08A3,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x087E,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0811,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0964,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x08A6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x093E,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x08AA,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x095B,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0952,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0368,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x086E,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0874,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x089B,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x089B,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x089B,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x089B,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- //packet(0x0965,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x086A,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x08A9,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0950,26,clif->pPartyInvite2,2);
- //packet(0x08AC,4); // CZ_GANGSI_RANK
- packet(0x0362,26,clif->pFriendsListAdd,2);
- packet(0x0926,5,clif->pHomMenu,2,4);
- packet(0x088E,36,clif->pStoragePassword,0);
+ packet(0x086A,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x08A9,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0950,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x088E,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x08ac,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x0965,clif->pDull); // CZ_JOIN_BATTLE_FIELD
// Shuffle End
#endif
//2013-05-29Ragexe (Shakto)
#if PACKETVER >= 20130529
- packet(0x0890,7,clif->pActionRequest,2,6);
- packet(0x0438,10,clif->pUseSkillToId,2,4,6);
- packet(0x0876,5,clif->pWalkToXY,2);
- packet(0x0897,6,clif->pTickSend,2);
- packet(0x0951,5,clif->pChangeDir,2,4);
- packet(0x0895,6,clif->pTakeItem,2);
- packet(0x08A7,6,clif->pDropItem,2,4);
- packet(0x0938,8,clif->pMoveToKafra,2,4);
- packet(0x0957,8,clif->pMoveFromKafra,2,4);
- packet(0x0917,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x085E,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x0863,6,clif->pGetCharNameRequest,2);
- packet(0x0937,6,clif->pSolveCharName,2);
- packet(0x085A,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0941,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x0918,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0936,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0892,6,clif->pReqClickBuyingStore,2);
- packet(0x0964,2,clif->pReqCloseBuyingStore,0);
- packet(0x0869,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0890,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0876,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0897,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0951,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x08A7,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0938,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x085E,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0937,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x085A,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0918,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0936,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0892,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0964,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0874,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0874,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0874,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0874,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // packet(0x088E,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x0958,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0919,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x08A8,26,clif->pPartyInvite2,2);
- // packet(0x0888,4); // CZ_GANGSI_RANK
- packet(0x0877,26,clif->pFriendsListAdd,2);
- packet(0x023B,5,clif->pHomMenu,2,4);
- packet(0x0956,36,clif->pStoragePassword,0);
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x08A8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0877,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x023B,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0888,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x088e,clif->pDull); // CZ_JOIN_BATTLE_FIELD
#endif
//2013-06-05Ragexe (Shakto)
#if PACKETVER >= 20130605
- 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(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0365,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // 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(0x0883,36,clif->pStoragePassword,0);
- packet(0x097C,4,clif->pRanklist);
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x022D,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x023B,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0883,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x097C,clif->pRanklist);
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0436,clif->pDull); // CZ_GANGSI_RANK
#endif
//2013-06-12Ragexe (Shakto)
#if PACKETVER >= 20130612
- packet(0x087E,5,clif->pChangeDir,2,4);
- packet(0x0919,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0940,26,clif->pFriendsListAdd,2);
- packet(0x093A,5,clif->pHomMenu,2,4);
- packet(0x0964,36,clif->pStoragePassword,0);
+// most shuffle packets used from 20130605
+ packet(0x087E,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0940,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x093A,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0964,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
#endif
//2013-06-18Ragexe (Shakto)
#if PACKETVER >= 20130618
- packet(0x0889,7,clif->pActionRequest,2,6);
- packet(0x0951,10,clif->pUseSkillToId,2,4,6);
- packet(0x088E,5,clif->pWalkToXY,2);
- packet(0x0930,6,clif->pTickSend,2);
- packet(0x08A6,5,clif->pChangeDir,2,4);
- packet(0x0962,6,clif->pTakeItem,2);
- packet(0x0917,6,clif->pDropItem,2,4);
- packet(0x0885,8,clif->pMoveToKafra,2,4);
- packet(0x0936,8,clif->pMoveFromKafra,2,4);
- packet(0x096A,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x094F,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x0944,6,clif->pGetCharNameRequest,2);
- packet(0x0945,6,clif->pSolveCharName,2);
- packet(0x0890,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0363,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x0281,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0891,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0862,6,clif->pReqClickBuyingStore,2);
- packet(0x085A,2,clif->pReqCloseBuyingStore,0);
- packet(0x0932,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0951,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x088E,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x08A6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0936,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x096A,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x094F,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0944,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0945,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0890,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0363,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0281,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0862,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x085A,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0932,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x08A7,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x08A7,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x08A7,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x08A7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // packet(0x087A,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x0942,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x095B,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0887,26,clif->pPartyInvite2,2);
- // packet(0x0878,4); // CZ_GANGSI_RANK
- packet(0x0953,26,clif->pFriendsListAdd,2);
- packet(0x02C4,5,clif->pHomMenu,2,4);
- packet(0x0864,36,clif->pStoragePassword,0);
+ packet(0x0942,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x095B,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0953,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x02C4,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0878,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x087a,clif->pDull); // CZ_JOIN_BATTLE_FIELD
#endif
//2013-06-26Ragexe (Shakto)
#if PACKETVER >= 20130626
- 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(0x094D,5,clif->pChangeDir,2,4);
- packet(0x088B,6,clif->pTakeItem,2);
- packet(0x0952,6,clif->pDropItem,2,4);
- packet(0x0921,8,clif->pMoveToKafra,2,4);
- packet(0x0817,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(0x0365,2,clif->pReqCloseBuyingStore,0);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x094D,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x088B,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0817,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0365,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0894,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0894,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0894,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0894,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // packet(0x0860,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x08A5,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x088C,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0895,26,clif->pPartyInvite2,2);
- // packet(0x088F,4); // CZ_GANGSI_RANK
- packet(0x08AB,26,clif->pFriendsListAdd,2);
- packet(0x0960,5,clif->pHomMenu,2,4);
- packet(0x0930,36,clif->pStoragePassword,0);
+ packet(0x08A5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x088C,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0895,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x08AB,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0930,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0860,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x088f,clif->pDull); // CZ_GANGSI_RANK
#endif
//2013-07-03Ragexe (Shakto)
#if PACKETVER >= 20130703
- packet(0x0930,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(0x0202,6,clif->pReqClickBuyingStore,2);
- packet(0x0817,2,clif->pReqCloseBuyingStore,0);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0930,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0202,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0365,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // 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(0x0360,26,clif->pFriendsListAdd,2);
- packet(0x094A,5,clif->pHomMenu,2,4);
- packet(0x0873,36,clif->pStoragePassword,0);
-#endif
-
-/* Bank System [Yommy/Hercules] */
-#if PACKETVER >= 20130724
- packet(0x09A6,12); // ZC_BANKING_CHECK
- packet(0x09A7,10,clif->pBankDeposit,2,4,6);
- packet(0x09A8,16); // ZC_ACK_BANKING_DEPOSIT
- packet(0x09A9,10,clif->pBankWithdraw,2,4,6);
- packet(0x09AA,16); // ZC_ACK_BANKING_WITHDRAW
- packet(0x09AB,6,clif->pBankCheck,2,4);
- ////
- packet(0x09B6,6,clif->pBankOpen,2,4);
- packet(0x09B7,4); // ZC_ACK_OPEN_BANKING
- packet(0x09B8,6,clif->pBankClose,2,4);
- packet(0x09B9,4); // ZC_ACK_CLOSE_BANKING
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x022D,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0360,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x094A,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0436,clif->pDull); // CZ_GANGSI_RANK
+#endif
+
+// 2013-04-17aRagexe
+#if PACKETVER >= 20130417
+// new packets
+ packet(0x09b4,clif->pDull/*,XXX*/); // CZ_OPEN_BARGAIN_SALE_TOOL
+ packet(0x09b6,clif->pBankOpen,2,4); // CZ_REQ_OPEN_BANKING
+ packet(0x09b8,clif->pBankClose,2,4); // CZ_REQ_CLOSE_BANKING
+// changed packet sizes
+#endif
+
+// 2013-04-24aRagexe
+#if PACKETVER >= 20130424
+// new packets
+ packet(0x09ba,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_GUILD_STORAGE
+ packet(0x09bc,clif->pDull/*,XXX*/); // CZ_CLOSE_BARGAIN_SALE_TOOL
+// changed packet sizes
+#endif
+
+// 2013-05-02aRagexe
+#if PACKETVER >= 20130502
+// new packets
+ packet(0x09be,clif->pDull/*,XXX*/); // CZ_REQ_CLOSE_GUILD_STORAGE
+// changed packet sizes
+#endif
+
+// 2013-05-29Ragexe
+#if PACKETVER >= 20130529
+// new packets
+ packet(0x09c3,clif->pDull/*,XXX*/); // CZ_REQ_COUNT_BARGAIN_SALE_ITEM
+// changed packet sizes
#endif
//2013-08-07Ragexe (Shakto)
#if PACKETVER >= 20130807
- 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(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0365,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif // PACKETVER_RE
- // 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(0x0887,36,clif->pStoragePassword,0);
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x022D,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x023B,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0436,clif->pDull); // CZ_GANGSI_RANK
#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);
+ packet(0x0874,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0947,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x093A,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x088A,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x088C,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0926,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x095F,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0202,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0873,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0887,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0962,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0937,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0923,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0868,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x094E,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0936,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
#ifdef PACKETVER_RE
- packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+ packet(0x0365,clif->pPartyRecruitRegisterReq,2,4);
#else // not PACKETVER_RE
- packet(0x0959,18,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x0959,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#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);
- packet(0x083C,10,clif->pUseSkillToId,2,4,6);
- packet(0x0437,5,clif->pWalkToXY,2);
- packet(0x035F,6,clif->pTickSend,2);
- packet(0x0947,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(0x022D,-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(0x092F,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0802,26,clif->pPartyInvite2,2);
- // packet(0x087B,4); // CZ_GANGSI_RANK
- packet(0x08AB,26,clif->pFriendsListAdd,2);
- packet(0x0811,5,clif->pHomMenu,2,4);
- packet(0x085C,36,clif->pStoragePassword,0);
- /* New */
- packet(0x09d4,2,clif->pNPCShopClosed);
- packet(0x09ce,102,clif->pGM_Monster_Item,2);
- /* NPC Market */
- packet(0x09d8,2,clif->pNPCMarketClosed);
- packet(0x09d6,-1,clif->pNPCMarketPurchase);
+ packet(0x08A4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0368,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0281,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0815,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x0896,clif->pDull); // CZ_JOIN_BATTLE_FIELD
#endif
-// 2013-12-23cRagexe - Yommy
-#if PACKETVER >= 20131223
- 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(0x08A4,36,clif->pStoragePassword,0);
- packet(0x09df,7);
+// 2013-08-14aRagexe
+#if PACKETVER >= 20130814
+// new packets
+ packet(0x09ce,clif->pGM_Monster_Item,2); // CZ_ITEM_CREATE_EX
+ packet(0x09d0,clif->pDull/*,XXX*/); // CZ_NPROTECTGAMEGUARDCSAUTH
+// changed packet sizes
#endif
-// 2013-12-30aRagexe - Yommy
-#if PACKETVER >= 20131230
- packet(0x0871,7,clif->pActionRequest,2,6);
- packet(0x02C4,10,clif->pUseSkillToId,2,4,6);
- packet(0x035F,5,clif->pWalkToXY,2);
- packet(0x0438,6,clif->pTickSend,2);
- packet(0x094A,5,clif->pChangeDir,2,4);
- packet(0x092A,6,clif->pTakeItem,2);
- packet(0x0860,6,clif->pDropItem,2,4);
- packet(0x0968,8,clif->pMoveToKafra,2,4);
- packet(0x0895,8,clif->pMoveFromKafra,2,4);
- packet(0x091E,10,clif->pUseSkillToPos,2,4,6,8);
- packet(0x096A,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
- packet(0x0926,6,clif->pGetCharNameRequest,2);
- packet(0x0898,6,clif->pSolveCharName,2);
- packet(0x087B,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0369,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x093D,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x087F,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x0969,6,clif->pReqClickBuyingStore,2);
- packet(0x094C,2,clif->pReqCloseBuyingStore,0);
- packet(0x0365,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x091F,18,clif->pPartyBookingRegisterReq,2,4);
- // packet(0x093E,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x022D,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x089C,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x08A9,26,clif->pPartyInvite2,2);
- // packet(0x087E,4); // CZ_GANGSI_RANK
- packet(0x0943,26,clif->pFriendsListAdd,2);
- packet(0x0949,5,clif->pHomMenu,2,4);
- packet(0x091D,36,clif->pStoragePassword,0);
+// 2013-08-28bRagexe
+#if PACKETVER >= 20130828
+// new packets
+// changed packet sizes
+ packet(0x09ba,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_GUILD_STORAGE
+ packet(0x09be,clif->pDull/*,XXX*/); // CZ_REQ_CLOSE_GUILD_STORAGE
#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
-
-// 2014-10-16aRagexe - YomRawr
-#if PACKETVER >= 20141016
- 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(0x0967,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(0x022D,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(0x086E,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0802,26,clif->pPartyInvite2,2);
- // packet(0x0922,4); // CZ_GANGSI_RANK
- packet(0x094B,26,clif->pFriendsListAdd,2);
- packet(0x0364,5,clif->pHomMenu,2,4);
- packet(0x0936,36,clif->pStoragePassword,0);
- packet(0x09DF,7);
- packet(0x0a00,269);
+// 2013-09-11aRagexe
+#if PACKETVER >= 20130911
+// new packets
+ packet(0x09d4,clif->pNPCShopClosed); // CZ_NPC_TRADE_QUIT
+ packet(0x09d6,clif->pNPCMarketPurchase); // CZ_NPC_MARKET_PURCHASE
+ packet(0x09d8,clif->pNPCMarketClosed); // CZ_NPC_MARKET_CLOSE
+ packet(0x09d9,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG
+// changed packet sizes
#endif
-/* Roulette System [Yommy/Hercules] */
-#if PACKETVER >= 20141016
- packet(0x0A19,2,clif->pRouletteOpen,0); // HEADER_CZ_REQ_OPEN_ROULETTE
- packet(0x0A1A,23); // HEADER_ZC_ACK_OPEN_ROULETTE
- packet(0x0A1B,2,clif->pRouletteInfo,0); // HEADER_CZ_REQ_ROULETTE_INFO
- packet(0x0A1C,-1); // HEADER_ZC_ACK_ROULEITTE_INFO
- packet(0x0A1D,2,clif->pRouletteClose,0); // HEADER_CZ_REQ_CLOSE_ROULETTE
- packet(0x0A1E,3); // HEADER_ZC_ACK_CLOSE_ROULETTE
- packet(0x0A1F,2,clif->pRouletteGenerate,0); // HEADER_CZ_REQ_GENERATE_ROULETTE
- packet(0x0A20,21); // HEADER_ZC_ACK_GENERATE_ROULETTE
- packet(0x0A21,3,clif->pRouletteRecvItem,2); // HEADER_CZ_RECV_ROULETTE_ITEM
- packet(0x0A22,5); // HEADER_ZC_RECV_ROULETTE_ITEM
-#endif
-
-// 2014-10-22bRagexe - YomRawr
-#if PACKETVER >= 20141022
- 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(0x08AD,5,clif->pChangeDir,2,4);
- packet(0x094E,6,clif->pTakeItem,2);
- packet(0x087D,6,clif->pDropItem,2,4);
- packet(0x0878,8,clif->pMoveToKafra,2,4);
- packet(0x08AA,8,clif->pMoveFromKafra,2,4);
- packet(0x023B,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(0x0835,12,clif->pSearchStoreInfoListItemClick,2,6,10);
- packet(0x0940,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(0x0955,18,clif->pPartyBookingRegisterReq,2,4);
- // packet(0x092B,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x093B,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x0896,26,clif->pPartyInvite2,2);
- // packet(0x08AB,4); // CZ_GANGSI_RANK
- packet(0x091A,26,clif->pFriendsListAdd,2);
- packet(0x0899,5,clif->pHomMenu,2,4);
- packet(0x0438,36,clif->pStoragePassword,0);
- packet(0x0A01,3,clif->pHotkeyRowShift,2);
-#endif
-
-#if PACKETVER >= 20150226
- packet(0x0A09,45);
- packet(0x0A0A,47);
- packet(0x0A0B,47);
- packet(0x0A0C,56);
- packet(0x0A0D,-1);
- packet(0x0A0F,-1);
- packet(0x0A10,-1);
-#endif
-
-// 2015-05-13aRagexe
-#if PACKETVER >= 20150513
- 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(0x0924,5,clif->pChangeDir,2,4);
- packet(0x0958,6,clif->pTakeItem,2);
- packet(0x0885,6,clif->pDropItem,2,4);
- packet(0x0879,8,clif->pMoveToKafra,2,4);
- packet(0x0864,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(0x022D,2,clif->pReqCloseBuyingStore,0);
- packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0883,18,clif->pPartyBookingRegisterReq,2,4);
- packet(0x02C4,8); // CZ_JOIN_BATTLE_FIELD
- packet(0x0960,-1,clif->pItemListWindowSelected,2,4,8);
- packet(0x0363,19,clif->pWantToConnection,2,6,10,14,18);
- packet(0x094A,26,clif->pPartyInvite2,2);
- packet(0x0927,4); // CZ_GANGSI_RANK
- packet(0x08A8,26,clif->pFriendsListAdd,2);
- packet(0x0817,5,clif->pHomMenu,2,4);
- packet(0x0923,36,clif->pStoragePassword,0);
- packet(0x09E8,11,clif->pDull); // CZ_OPEN_MAILBOX
- packet(0x0A2E,6,clif->pDull); // TITLE
- packet(0x0A02,4); // ZC_DRESSROOM_OPEN
- packet(0x0A35,4,clif->pOneClick_ItemIdentify,2);
-#endif
-
-#if PACKETVER >= 20150805 // RagexeRE
- packet(0x097f,-1); // ZC_SELECTCART
- packet(0x0980,7,clif->pSelectCart); // CZ_SELECTCART
-#endif
-
-/* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */
-#if PACKETVER >= 20110817
- packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */
-#endif
-
-#if PACKETVER >= 20110824
- packetKeys(0x35C91401,0x262A5556,0x28FA03AA); /* Thanks to Shakto */
-#endif
-
-#if PACKETVER >= 20110831
- packetKeys(0x3AD67ED0,0x44703C69,0x6F876809); /* Thanks to Shakto */
-#endif
-
-#if PACKETVER >= 20110906
- packetKeys(0x3AD67ED0,0x44703C69,0x6F876809); /* Thanks to Shakto */
+// 2013-10-02aRagexe
+#if PACKETVER >= 20131002
+// new packets
+// changed packet sizes
+ packet(0x09d9,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG
#endif
-#if PACKETVER >= 20111005
- packetKeys(0x291E6762,0x77CD391A,0x60AC2F16); /* Thanks to Shakto */
+// 2013-10-16aRagexe
+#if PACKETVER >= 20131016
+// new packets
+// changed packet sizes
+ packet(0x09d9,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG
#endif
-#if PACKETVER >= 20111012
- packetKeys(0x7F3C2D29,0x59B01DE6,0x1DBB44CA); /* Thanks to Shakto */
+// 2013-10-23aRagexe
+#if PACKETVER >= 20131023
+// new packets
+// changed packet sizes
+ packet(0x09d9,clif->pDull/*,XXX*/); // CZ_REQ_GUILDSTORAGE_LOG
#endif
-#if PACKETVER >= 20111021
- packetKeys(0x357D55DC,0x5A8D759F,0x245C30F5); /* Thanks to Shakto */
+// 2013-11-06aRagexe
+#if PACKETVER >= 20131106
+// new packets
+ packet(0x09e1,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_BODY_TO_GUILDSTORAGE
+ packet(0x09e2,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_GUILDSTORAGE_TO_BODY
+ packet(0x09e3,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_CART_TO_GUILDSTORAGE
+ packet(0x09e4,clif->pDull/*,XXX*/); // CZ_MOVE_ITEM_FROM_GUILDSTORAGE_TO_CART
+// changed packet sizes
#endif
-#if PACKETVER >= 20111025
- packetKeys(0x50AE1A63,0x3CE579B5,0x29C10406); /* Thanks to Shakto */
+// 2013-12-11dRagexe
+#if PACKETVER >= 20131211
+// new packets
+ packet(0x09e8,clif->pDull/*,XXX*/); // CZ_OPEN_RODEXBOX
+ packet(0x09e9,clif->pRodexCloseMailbox); // CZ_CLOSE_RODEXBOX
+ packet(0x09ee,clif->pDull/*,XXX*/); // CZ_REQ_NEXT_RODEX
+// changed packet sizes
#endif
-#if PACKETVER >= 20111102
- packetKeys(0x5324329D,0x5D545D52,0x06137269); /* Thanks to Shakto */
+// 2013-12-18bRagexe - Yommy
+#if PACKETVER >= 20131218
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0947,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x022D,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x092F,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x08AB,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0811,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x085C,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x087b,clif->pDull); // CZ_GANGSI_RANK
+#endif
+
+// 2013-12-18bRagexe
+#if PACKETVER >= 20131218
+// new packets
+ packet(0x09ea,clif->pDull/*,XXX*/); // CZ_REQ_READ_RODEX
+ packet(0x09ef,clif->pRodexRefreshMaillist); // CZ_REQ_REFRESH_RODEX
+ packet(0x09f5,clif->pRodexDeleteMail); // CZ_REQ_DELETE_RODEX
+// changed packet sizes
+ packet(0x09e8,clif->pDull/*,XXX*/); // CZ_OPEN_RODEXBOX
+ packet(0x09ee,clif->pRodexNextMaillist); // CZ_REQ_NEXT_RODEX
#endif
-#if PACKETVER >= 20111109
- packetKeys(0x0B642BDA,0x6ECB1D1C,0x61C7454B); /* Thanks to Shakto */
+// 2013-12-23cRagexe - Yommy
+#if PACKETVER >= 20131223
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x083C,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x035F,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x07E4,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x07EC,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x096A,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x023B,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x08A4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0363,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0436,clif->pDull); // CZ_GANGSI_RANK
+#endif
+
+// 2013-12-23bRagexe
+#if PACKETVER >= 20131223
+// new packets
+// changed packet sizes
+ packet(0x09ea,clif->pRodexReadMail); // CZ_REQ_READ_RODEX
#endif
-#if PACKETVER >= 20111122
- packetKeys(0x3B550F07,0x1F666C7C,0x60304EF5); /* Thanks to Shakto */
+// 2013-12-30aRagexe - Yommy
+#if PACKETVER >= 20131230
+ packet(0x0871,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x02C4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x035F,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x094A,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x092A,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0968,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x091E,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x096A,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0926,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x087B,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0369,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x093D,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x087F,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0969,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x094C,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0365,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x091F,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x022D,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x089C,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x08A9,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0943,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0949,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x091D,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x087e,clif->pDull); // CZ_GANGSI_RANK
+ packet(0x093e,clif->pDull); // CZ_JOIN_BATTLE_FIELD
+#endif
+
+// 2013-12-30aRagexe
+#if PACKETVER >= 20131230
+// new packets
+ packet(0x09ec,clif->pRodexSendMail); // CZ_REQ_SEND_RODEX
+// changed packet sizes
#endif
-#if PACKETVER >= 20111207
- packetKeys(0x2A610886,0x3E09165E,0x57C11888); /* Thanks to Shakto */
-#endif
+// 2014 Packet Data
-#if PACKETVER >= 20111214
- packetKeys(0x5151306B,0x7AE32886,0x53060628); /* Thanks to Shakto */
+// 2014-01-15cRagexeRE
+#if PACKETVER >= 20140115
+// new packets
+ packet(0x09f1,clif->pDull/*,XXX*/); // CZ_REQ_ZENY_FROM_RODEX
+ packet(0x09f3,clif->pDull/*,XXX*/); // CZ_REQ_ITEM_FROM_RODEX
+// changed packet sizes
#endif
-#if PACKETVER >= 20111220
- packetKeys(0x05D53871,0x7D0027B4,0x29975333); /* Thanks to Shakto */
+// 2014-01-22aRagexeRE
+#if PACKETVER >= 20140122
+// new packets
+ packet(0x09fb,clif->pPetEvolution); // CZ_PET_EVOLUTION
+// changed packet sizes
#endif
-#if PACKETVER >= 20111228
- packetKeys(0x0FF87E93,0x6CFF7860,0x3A3D1DEC); /* Thanks to Shakto */
+#if PACKETVER_MAIN_NUM >= 20140129 || PACKETVER_RE_NUM >= 20140129 || defined(PACKETVER_ZERO)
+ packet(0x0a01,clif->pHotkeyRowShift1); // CZ_SHORTCUTKEYBAR_ROTATE
#endif
-#if PACKETVER >= 20120104
- packetKeys(0x262034A1,0x674542A5,0x73A50BA5); /* Thanks to Shakto */
+// 2014-02-12aRagexeRE
+#if PACKETVER >= 20140212
+// new packets
+// changed packet sizes
+ packet(0x09e8,clif->pRodexOpenMailbox); // CZ_OPEN_RODEXBOX
#endif
-#if PACKETVER >= 20120111
- packetKeys(0x2B412AFC,0x4FF94487,0x6705339D); /* Thanks to Shakto */
+// 2014-02-26aRagexeRE
+#if PACKETVER >= 20140226
+// new packets
+ packet(0x0a03,clif->pDull/*,XXX*/); // CZ_REQ_CANCEL_WRITE_RODEX
+ packet(0x0a04,clif->pDull/*,XXX*/); // CZ_REQ_ADD_ITEM_RODEX
+ packet(0x0a06,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_RODEX_ITEM
+// changed packet sizes
#endif
-#if PACKETVER >= 20120120
- packetKeys(0x504345D0,0x3D427B1B,0x794C2DCC); /* Thanks to Shakto */
+// 2014-03-05aRagexeRE
+#if PACKETVER >= 20140305
+// new packets
+ packet(0x0a08,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_WRITE_RODEX
+// changed packet sizes
+ packet(0x09f3,clif->pDull/*,XXX*/); // CZ_REQ_ITEM_FROM_RODEX
#endif
-#if PACKETVER >= 20120202
- packetKeys(0x2CFC0A71,0x2BA91D8D,0x087E39E0); /* Thanks to Shakto */
+// 2014-03-26cRagexeRE
+#if PACKETVER >= 20140326
+// changed packet sizes
+ packet(0x09f1,clif->pRodexRequestZeny); // CZ_REQ_ZENY_FROM_RODEX
+ packet(0x09f3,clif->pRodexRequestItems); // CZ_REQ_ITEM_FROM_RODEX
+ packet(0x0a03,clif->pRodexCancelWriteMail); // CZ_REQ_CANCEL_WRITE_RODEX
+ packet(0x0a08,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_WRITE_RODEX
#endif
-#if PACKETVER >= 20120207
- packetKeys(0x1D373F5D,0x5ACD604D,0x1C4D7C4D); /* Thanks to Shakto */
+// 2014-04-16aRagexeRE
+#if PACKETVER >= 20140416
+// new packets
+ packet(0x0a04,clif->pRodexAddItem); // CZ_REQ_ADD_ITEM_RODEX
+ packet(0x0a13,clif->pRodexCheckName); // CZ_CHECK_RECEIVE_CHARACTER_NAME
+// changed packet sizes
+ packet(0x0a06,clif->pRodexRemoveItem); // CZ_REQ_REMOVE_RODEX_ITEM
+ packet(0x0a08,clif->pRodexOpenWriteMail); // CZ_REQ_OPEN_WRITE_RODEX
#endif
-#if PACKETVER >= 20120214
- packetKeys(0x7A255EFA,0x30977276,0x2D4A0448); /* Thanks to Shakto */
+// 2014-04-23aRagexeRE
+#if PACKETVER >= 20140423
+// new packets
+// changed packet sizes
+ packet(0x0a13,clif->pRodexCheckName); // CZ_CHECK_RECEIVE_CHARACTER_NAME
#endif
-#if PACKETVER >= 20120229
- packetKeys(0x520B4C64,0x2800407D,0x47651458); /* Thanks to Shakto */
+// 2014-04-30aRagexeRE
+#if PACKETVER >= 20140430
+// new packets
+ packet(0x0a16,clif->pDull/*,XXX*/); // CZ_DYNAMICNPC_CREATE_REQUEST
#endif
-#if PACKETVER >= 20120307
- packetKeys(0x382A6DEF,0x5CBE7202,0x61F46637); /* Thanks to Shakto */
+/* Roulette System [Yommy/Hercules] */
+// 2014-06-05aRagexe
+#if PACKETVER >= 20140605
+// new packets
+ packet(0x0a19,clif->pDull/*,XXX*/); // CZ_REQ_OPEN_ROULETTE
+ packet(0x0A1B,clif->pRouletteInfo,0); // HEADER_CZ_REQ_ROULETTE_INFO
+ packet(0x0a1d,clif->pDull/*,XXX*/); // CZ_REQ_CLOSE_ROULETTE
#endif
-#if PACKETVER >= 20120314
- packetKeys(0x689C1729,0x11812639,0x60F82967); /* Thanks to Shakto */
+/* Roulette System [Yommy/Hercules] */
+// 2014-06-11bRagexe / RE. moved by 4144
+#if PACKETVER >= 20140611
+// new packets
+ packet(0x0a1f,clif->pRouletteGenerate,0); // CZ_REQ_GENERATE_ROULETTE
+ packet(0x0a21,clif->pDull/*,XXX*/); // CZ_RECV_ROULETTE_ITEM
+ packet(0x0a25,clif->pAchievementGetReward,2); // CZ_REQ_ACH_REWARD
+// changed packet sizes
+ packet(0x0a19,clif->pRouletteOpen,0); // CZ_REQ_OPEN_ROULETTE
+ packet(0x0a1d,clif->pRouletteClose,0); // CZ_REQ_CLOSE_ROULETTE
#endif
-#if PACKETVER >= 20120321
- packetKeys(0x21F9683F,0x710C5CA5,0x1FD910E9); /* Thanks to Shakto */
+// 2014-06-18cRagexeRE
+#if PACKETVER >= 20140618
+// changed packet sizes
+ packet(0x0a21,clif->pRouletteRecvItem,2); // CZ_RECV_ROULETTE_ITEM
#endif
-#if PACKETVER >= 20120328
- packetKeys(0x75B8553B,0x37F20B12,0x385C2B40); /* Thanks to Shakto */
+// 2014-07-02aRagexeRE
+#if PACKETVER >= 20140702
+// new packets
+ packet(0x0a2a,clif->pDull/*,XXX*/); // CZ_ACK_AU_BOT
#endif
-#if PACKETVER >= 20120404
- packetKeys(0x0036310C,0x2DCD0BED,0x1EE62A78); /* Thanks to Shakto */
+// 2014-09-03aRagexeRE
+#if PACKETVER >= 20140903
+// new packets
+ packet(0x0a2e,clif->pChangeTitle); // CZ_REQ_CHANGE_TITLE
+// changed packet sizes
#endif
-#if PACKETVER >= 20120410
- packetKeys(0x01581359,0x452D6FFA,0x6AFB6E2E); /* Thanks to Shakto */
+// 2014-11-19bRagexeRE
+#if PACKETVER >= 20141119
+// new packets
+ packet(0x0A35,clif->pOneClick_ItemIdentify,2);
+// changed packet sizes
#endif
-#if PACKETVER >= 20120418
- packetKeys(0x01540E48,0x13041224,0x31247924); /* Thanks to Shakto */
+// 2015-11-04aRagexeRE
+#if PACKETVER >= 20151104
+// new packets
+ packet(0x0a46,clif->pReqStyleChange);
+ packet(0x0a48,clif->pStyleClose);
#endif
-#if PACKETVER >= 20120424
- packetKeys(0x411D1DBB,0x4CBA4848,0x1A432FC4); /* Thanks to Shakto */
-#endif
-#if PACKETVER >= 20120509
- packetKeys(0x16CF3301,0x1F472B9B,0x0B4A3CD2); /* Thanks to Shakto */
+// 2016-03-23aRagexeRE
+#if PACKETVER >= 20160323
+// new packets
+ packet(0x0a68,clif->pOpenUIRequest);
+// changed packet sizes
#endif
-#if PACKETVER >= 20120515
- packetKeys(0x4A715EF9,0x79103E4F,0x405C1238); /* Thanks to Shakto */
+// 2016-03-30aRagexeRE
+#if PACKETVER >= 20160330
+// new packets
+ packet(0x0a6e,clif->pRodexSendMail); // CZ_RODEX_SEND_MAIL
+// changed packet sizes
#endif
-#if PACKETVER >= 20120525
- packetKeys(0x70EB4CCB,0x0487713C,0x398D4B08); /* Thanks to Shakto */
+#if PACKETVER >= 20160302
+ packet(0x0a4f,clif->plapineDdukDdak_ack);
#endif
-#if PACKETVER >= 20120605
- packetKeys(0x68CA3080,0x31B74BDD,0x505208F1); /* Thanks to Shakto */
+#if PACKETVER_MAIN_NUM >= 20160504 || PACKETVER_RE_NUM >= 20160504 || defined(PACKETVER_ZERO)
+ packet(0x0a70,clif->plapineDdukDdak_close);
#endif
-#if PACKETVER >= 20120612
- packetKeys(0x32E45D64,0x35643564,0x35643564); /* Thanks to Shakto */
+// all 2016-05-25
+#if PACKETVER >= 20160525
+ packet(0x0a77,clif->pCameraInfo); // CZ_CAMERA_INFO
#endif
-#if PACKETVER >= 20120618
- packetKeys(0x261F261F,0x261F261F,0x261F261F); /* Thanks to Shakto */
+// all 20160622+
+#if PACKETVER >= 20160622
+ packet(0x0a88,clif->pResetCooldown);
#endif
-#if PACKETVER >= 20120702
- packetKeys(0x25733B31,0x53486CFD,0x398649BD); /* Thanks to Shakto */
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+ packet(0x0aa1, clif->pAddItemRefineryUI);
+ packet(0x0aa3, clif->pRefineryUIRefine);
+ packet(0x0aa4, clif->pRefineryUIClose);
#endif
-#if PACKETVER >= 20120716
- packetKeys(0x76052205,0x22052205,0x22052205); /* Thanks to Shakto */
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+ packet(0x0ab5, clif->pLapineUpgrade_close);
+ packet(0x0ab6, clif->pLapineUpgrade_makeItem);
#endif
-#if PACKETVER >= 20130320
- packetKeys(0x3F094C49,0x55F86C1E,0x58AA359A); /* Thanks to Shakto */
+// 2017-02-28aRagexeRE
+#if PACKETVER >= 20170228
+// new packets
+ packet(0x0ac0,clif->pRodexOpenMailbox); // CZ_OPEN_RODEXBOX
+ packet(0x0ac1,clif->pRodexRefreshMaillist); // CZ_REQ_REFRESH_RODEX
+// changed packet sizes
#endif
-#if PACKETVER >= 20130514
- packetKeys(0x75794A38,0x58A96BC1,0x296E6FB8); /* Thanks to Shakto */
+// 2017-08-30aRagexeRE
+#if PACKETVER >= 20170830
+// new packets
+// changed packet sizes
+ packet(0x0a49,clif->pPrivateAirshipRequest);
#endif
-#if PACKETVER >= 20130522
- packetKeys(0x6948050B,0x06511D9D,0x725D4DF1); /* Thanks to Shakto */
+#ifdef PACKETVER_ZERO
+#if PACKETVER >= 20171214
+// new packets
+ packet(0x0ae8,clif->pChangeDress);
+// changed packet sizes
#endif
+#endif // PACKETVER_ZERO
-#if PACKETVER >= 20130529
- packetKeys(0x023A6C87,0x14BF1F1E,0x5CC70CC9); /* Thanks to Shakto */
+// 2017-12-20aRagexe
+#if PACKETVER >= 20171220
+// new packets
+ packet(0x0ae8,clif->pChangeDress);
+// changed packet sizes
#endif
-#if PACKETVER >= 20130605
- packetKeys(0x646E08D9,0x5F153AB5,0x61B509B5); /* Thanks to Shakto */
+#if PACKETVER >= 20180117
+// new packets
+ packet(0x0aef,clif->pAttendanceRewardRequest);
+// changed packet sizes
#endif
-#if PACKETVER >= 20130612
- packetKeys(0x6D166F66,0x3C000FCF,0x295B0FCB); /* Thanks to Shakto */
+#ifdef PACKETVER_ZERO
+// 2018-01-31dRagexe_zero
+#if PACKETVER >= 20180131
+// new packets
+ packet(0x0af4,clif->pUseSkillToPos,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND
+// changed packet sizes
#endif
+#endif // PACKETVER_ZERO
-#if PACKETVER >= 20130618
- packetKeys(0x434115DE,0x34A10FE9,0x6791428E); /* Thanks to Shakto */
+#ifndef PACKETVER_ZERO
+// 2018-02-07bRagexeRE, 2018-02-07bRagexe
+#if PACKETVER >= 20180207
+// new packets
+ packet(0x0af4,clif->pUseSkillToPos,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND
+// changed packet sizes
#endif
+#endif // PACKETVER_ZERO
-#if PACKETVER >= 20130626
- packetKeys(0x38F453EF,0x6A040FD8,0X65BD6668); /* Thanks to Shakto */
+#ifndef PACKETVER_ZERO
+// 2018-05-16cRagexe, 2018-05-16cRagexeRE
+#if PACKETVER >= 20180516
+// new packets
+ packet(0x0afc,clif->pReqStyleChange2);
+// changed packet sizes
#endif
+#endif // PACKETVER_ZERO
-#if PACKETVER >= 20130703
- packetKeys(0x4FF90E23,0x0F1432F2,0x4CFA1EDA); /* Thanks to Shakto */
+#ifdef PACKETVER_ZERO
+// 2018-05-23aRagexe_zero
+#if PACKETVER >= 20180523
+// new packets
+ packet(0x0afc,clif->pReqStyleChange2);
+// changed packet sizes
#endif
+#endif // PACKETVER_ZERO
-#if PACKETVER >= 20130807
- packetKeys(0x7E241DE0,0x5E805580,0x3D807D80); /* Thanks to Shakto */
+// 2018-07-04aRagexeRE
+#if PACKETVER_RE_NUM >= 20180704
+// new packets
+// changed packet sizes
+ packet(0x018e,clif->pProduceMix); // CZ_REQMAKINGITEM
+ packet(0x01ae,clif->pSelectArrow,2); // CZ_REQ_MAKINGARROW
+ packet(0x01fd,clif->pRepairItem); // CZ_REQ_ITEMREPAIR
+ packet(0x025b,clif->pCooking); // CZ_REQ_MAKINGITEM
+ packet(0x0445,clif->pDull/*,XXX*/); // CZ_SIMPLE_BUY_CASH_POINT_ITEM
+ packet(0x09ae,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM
+ packet(0x09b0,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM
+ packet(0x09c3,clif->pDull/*,XXX*/); // CZ_REQ_COUNT_BARGAIN_SALE_ITEM
+ packet(0x0a49,clif->pPrivateAirshipRequest); // CZ_PRIVATE_AIRSHIP_REQUEST
#endif
-#if PACKETVER >= 20130814
- packetKeys(0x23A23148,0x0C41420E,0x53785AD7); /* Themon */
+// 2018-11-14aRagexe_zero
+#if PACKETVER_ZERO_NUM >= 20181114
+// new packets
+// changed packet sizes
+ packet(0x018e,clif->pProduceMix); // CZ_REQMAKINGITEM
+ packet(0x01ae,clif->pSelectArrow,2); // CZ_REQ_MAKINGARROW
+ packet(0x01fd,clif->pRepairItem); // CZ_REQ_ITEMREPAIR
+ packet(0x025b,clif->pCooking); // CZ_REQ_MAKINGITEM
+ packet(0x0445,clif->pDull/*,XXX*/); // CZ_SIMPLE_BUY_CASH_POINT_ITEM
+ packet(0x09ae,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM
+ packet(0x09b0,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM
+ packet(0x09c3,clif->pDull/*,XXX*/); // CZ_REQ_COUNT_BARGAIN_SALE_ITEM
+ packet(0x0a49,clif->pPrivateAirshipRequest); // CZ_PRIVATE_AIRSHIP_REQUEST
#endif
-#if PACKETVER >= 20131218
- packetKeys(0x6A596301,0x76866D0E,0x32294A45);
+// 2018-11-21bRagexe
+#if PACKETVER_ZERO_NUM >= 20181121
+// new packets
+// changed packet sizes
+ packet(0x018e,clif->pProduceMix); // CZ_REQMAKINGITEM
+ packet(0x01ae,clif->pSelectArrow,2); // CZ_REQ_MAKINGARROW
+ packet(0x01fd,clif->pRepairItem); // CZ_REQ_ITEMREPAIR
+ packet(0x025b,clif->pCooking); // CZ_REQ_MAKINGITEM
+ packet(0x0445,clif->pDull/*,XXX*/); // CZ_SIMPLE_BUY_CASH_POINT_ITEM
+ packet(0x09ae,clif->pDull/*,XXX*/); // CZ_REQ_APPLY_BARGAIN_SALE_ITEM
+ packet(0x09b0,clif->pDull/*,XXX*/); // CZ_REQ_REMOVE_BARGAIN_SALE_ITEM
+ packet(0x09c3,clif->pDull/*,XXX*/); // CZ_REQ_COUNT_BARGAIN_SALE_ITEM
+ packet(0x0a49,clif->pPrivateAirshipRequest); // CZ_PRIVATE_AIRSHIP_REQUEST
#endif
-#if PACKETVER >= 20131223
- packetKeys(0x631C511C,0x111C111C,0x111C111C);
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+ packet(0x0b10,clif->pStartUseSkillToId);
+ packet(0x0b11,clif->pStopUseSkillToId);
#endif
-#if PACKETVER >= 20131230
- packetKeys(0x611B7097,0x01F957A1,0x768A0FCB);
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+ packet(0x0b14,clif->pInventoryExpansion);
+ packet(0x0b16,clif->pInventoryExpansionConfirmed);
+ packet(0x0b19,clif->pInventoryExpansionRejected);
#endif
-// 2014 Packet Keys
-
-#if PACKETVER >= 20140115
- packetKeys(0x63224335,0x0F3A1F27,0x6D217B24); /* Thanks to Yommy */
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+ packet(0x0b0f,clif->pNPCBarterPurchase);
+ packet(0x0b12,clif->pNPCBarterClosed);
#endif
-#if PACKETVER >= 20140205
- packetKeys(0x63DC7BDC,0x7BDC7BDC,0x7BDC7BDC); /* Themon */
+#if PACKETVER_MAIN_NUM >= 20190227 || PACKETVER_RE_NUM >= 20190220 || PACKETVER_ZERO_NUM >= 20190220
+ packet(0x0b1c,clif->pPing);
#endif
-#if PACKETVER >= 20140305
- packetKeys(0x116763F2,0x41117DAC,0x7FD13C45); /* Themon */
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+ packet(0x0b21,clif->pHotkey2);
+ packet(0x0b22,clif->pHotkeyRowShift2); // CZ_SHORTCUTKEYBAR_ROTATE
#endif
-#if PACKETVER >= 20140402
- packetKeys(0x15D3271C,0x004D725B,0x111A3A37); /* Themon */
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+ packet(0x0b28,clif->pGuildCastleTeleportRequest);
+ packet(0x0b2c,clif->pGuildCastleInfoRequest);
#endif
-#if PACKETVER >= 20140416
- packetKeys(0x04810281,0x42814281,0x42814281); /* Themon */
+#if PACKETVER_MAIN_NUM >= 20190703 || PACKETVER_RE_NUM >= 20190703
+ packet(0x0b35,clif->pReqGearOff);
#endif
-#if PACKETVER >= 20141016
- packetKeys(0x2DFF467C,0x444B37EE,0x2C1B634F); /* YomRawr */
+#if PACKETVER_ZERO_NUM >= 20190709
+ packet(0x0b35,clif->pReqGearOff);
#endif
-#if PACKETVER >= 20141022
- packetKeys(0x290551EA,0x2B952C75,0x2D67669B); /* YomRawr */
+#if PACKETVER >= 20190724
+ packet(0x0b4c,clif->pCashShopLimitedReq);
#endif
-// 2015 Packet Keys
-
-#if PACKETVER >= 20150513
- packetKeys(0x62C86D09,0x75944F17,0x112C133D); /* Dastgir */
+#if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
+ packet(0x0b57,clif->pNPCExpandedBarterPurchase);
+ packet(0x0b58,clif->pNPCExpandedBarterClosed);
#endif
-#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
- packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
+#if PACKETVER >= 20191224
+ packet(0x0b6d,clif->pCashShopOpen2);
#endif
#endif /* MAP_PACKETS_H */
diff --git a/src/map/packets_keys_main.h b/src/map/packets_keys_main.h
new file mode 100644
index 000000000..8ebbb39be
--- /dev/null
+++ b/src/map/packets_keys_main.h
@@ -0,0 +1,2137 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_PACKETS_MAIN_KEYS_H
+#define MAP_PACKETS_MAIN_KEYS_H
+
+#ifndef packetKeys
+ #define packetKeys(a,b,c)
+#endif
+
+/* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */
+
+/* This file is autogenerated, please do not commit manual changes */
+
+// 2010-11-23aRagexe, 2010-11-24aRagexe, 2010-11-24dRagexe, 2010-11-24eRagexe, 2010-11-24fRagexe, 2010-11-26aRagexe
+#if PACKETVER == 20101123 || \
+ PACKETVER == 20101124 || \
+ PACKETVER == 20101126
+ packetKeys(0x49357d72,0x22c370a1,0x5f836591);
+#endif
+
+// 2010-11-23aRagexeRE, 2010-11-24aRagexeRE, 2010-11-24bRagexeRE, 2010-11-25aRagexeRE, 2010-11-26aRagexeRE, 2010-11-30aRagexeRE, 2010-12-07aRagexeRE, 2010-12-14aRagexeRE, 2010-12-21aRagexeRE, 2010-12-23aRagexeRE, 2010-12-28aRagexeRE, 2011-01-04aRagexeRE, 2011-01-05aRagexeRE, 2011-01-11aRagexeRE, 2011-01-18aRagexeRE, 2011-01-25aRagexeRE, 2011-01-26aRagexeRE, 2011-01-26bRagexeRE, 2011-01-31aRagexeRE, 2011-01-31bRagexeRE, 2011-01-31cRagexeRE, 2011-02-08aRagexeRE, 2011-02-15aRagexeRE, 2011-02-22aRagexeRE, 2011-02-23aRagexeRE, 2011-02-23bRagexeRE, 2011-02-24aRagexeRE, 2011-02-25aRagexeRE, 2011-02-28aRagexeRE, 2011-03-08aRagexeRE, 2011-03-09aRagexeRE, 2011-03-09bRagexeRE, 2011-03-09cRagexeRE, 2011-03-09dRagexeRE, 2011-03-15aRagexeRE, 2011-03-22aRagexeRE, 2011-03-29aRagexeRE, 2011-03-30aRagexeRE, 2011-03-30cRagexeRE, 2011-04-05aRagexeRE, 2011-04-12aRagexeRE, 2011-04-19aRagexeRE, 2011-04-20aRagexeRE, 2011-04-26aRagexeRE, 2011-04-27aRagexeRE, 2011-05-03aRagexeRE, 2011-05-11aRagexeRE, 2011-05-17bRagexeRE, 2011-05-24aRagexeRE, 2011-05-26aRagexeRE, 2011-05-31aRagexeRE, 2011-06-07aRagexeRE, 2011-06-08aRagexeRE, 2011-06-08bRagexeRE, 2011-06-08cRagexeRE, 2011-06-09aRagexeRE, 2011-06-14bRagexeRE, 2011-06-22aRagexeRE, 2011-06-28aRagexeRE, 2011-07-06aRagexeRE, 2011-07-13aRagexeRE, 2011-07-13bRagexeRE, 2011-07-13cRagexeRE, 2011-07-19aRagexeRE, 2011-07-26aRagexeRE, 2011-08-03aRagexeRE, 2011-08-03bRagexeRE, 2011-08-10aRagexeRE, 2013-12-23aRagexeRE, 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-21aRagexeRE, 2018-03-28bRagexe, 2018-03-28bRagexeRE, 2018-04-04bRagexe, 2018-04-04cRagexeRE, 2018-04-18aRagexe, 2018-04-18bRagexeRE, 2018-04-25cRagexe, 2018-04-25cRagexeRE, 2018-05-02bRagexe, 2018-05-02bRagexeRE, 2018-05-02dRagexeRE, 2018-05-09aRagexe, 2018-05-16cRagexe, 2018-05-16cRagexeRE, 2018-05-23aRagexe, 2018-05-23aRagexeRE, 2018-05-30aRagexe, 2018-05-30bRagexeRE, 2018-05-30cRagexeRE, 2018-06-05bRagexe, 2018-06-05bRagexeRE, 2018-06-12aRagexeRE, 2018-06-12bRagexeRE, 2018-06-20cRagexe, 2018-06-20dRagexeRE, 2018-06-20eRagexe, 2018-06-20eRagexeRE, 2018-06-21aRagexe, 2018-06-21aRagexeRE, 2018-07-04aRagexe, 2018-07-04aRagexeRE, 2018-07-11aRagexeRE, 2018-07-18bRagexe, 2018-07-18bRagexeRE, 2018-07-18bRagexeRE1, 2018-07-18cRagexe, 2018-07-18cRagexeRE, 2018-08-01cRagexe, 2018-08-01cRagexeRE, 2018-08-08bRagexe, 2018-08-08bRagexeRE, 2018-08-22cRagexe, 2018-08-22cRagexeRE, 2018-08-29aRagexe, 2018-08-29aRagexeRE, 2018-08-29bRagexeRE, 2018-08-31aRagexe, 2018-09-12dRagexe, 2018-09-12dRagexeRE, 2018-09-19aRagexe, 2018-09-19aRagexeRE, 2018-10-02aRagexe, 2018-10-02aRagexeRE, 2018-10-02bRagexe, 2018-10-02bRagexeRE, 2018-10-17_02aRagexe, 2018-10-17_02aRagexeRE, 2018-10-17_03aRagexe, 2018-10-17_03aRagexeRE, 2018-10-17bRagexe, 2018-10-17bRagexeRE, 2018-10-24bRagexe, 2018-10-31aRagexe, 2018-10-31bRagexe, 2018-10-31cRagexeRE, 2018-11-07aRagexe, 2018-11-07aRagexeRE, 2018-11-14cRagexe, 2018-11-14cRagexeRE, 2018-11-14dRagexe, 2018-11-14dRagexeRE, 2018-11-21bRagexe, 2018-11-21cRagexeRE, 2018-11-28aRagexe, 2018-11-28aRagexeRE, 2018-11-28bRagexe, 2018-11-28cRagexe, 2018-12-05aRagexe, 2018-12-05bRagexeRE, 2018-12-12aRagexe, 2018-12-12aRagexeRE, 2018-12-12bRagexe, 2018-12-12bRagexeRE, 2018-12-19bRagexe, 2018-12-19bRagexeRE, 2018-12-26aRagexe, 2018-12-26aRagexeRE, 2019-01-09aRagexe, 2019-01-09bRagexeRE, 2019-01-16bRagexe, 2019-01-16bRagexeRE, 2019-01-16cRagexe, 2019-01-16cRagexeRE, 2019-01-23dRagexe, 2019-01-23dRagexeRE, 2019-02-13IRagexeRE, 2019-02-13bRagexe, 2019-02-13eRagexe, 2019-02-20aRagexeRE, 2019-02-27aRagexe, 2019-02-27bRagexeRE, 2019-02-28aRagexe, 2019-02-28aRagexeRE, 2019-03-06bRagexe, 2019-03-06bRagexeRE, 2019-03-06cRagexe, 2019-03-06cRagexeRE, 2019-03-13aRagexe, 2019-03-20aRagexe, 2019-03-20aRagexeRE, 2019-03-22aRagexe, 2019-03-22aRagexeRE, 2019-03-27bRagexe, 2019-03-27bRagexeRE, 2019-04-03aRagexe, 2019-04-03bRagexeRE, 2019-04-03cRagexeRE, 2019-04-17aRagexe, 2019-04-17cRagexeRE, 2019-04-18aRagexe, 2019-04-18aRagexeRE, 2019-05-08cRagexe, 2019-05-08dRagexeRE, 2019-05-08eRagexeRE, 2019-05-22bRagexe, 2019-05-22bRagexeRE, 2019-05-22cRagexe, 2019-05-22cRagexeRE, 2019-05-23aRagexe, 2019-05-29aRagexe, 2019-05-29bRagexeRE, 2019-05-29cRagexe, 2019-05-29cRagexeRE, 2019-05-30aRagexe, 2019-05-30aRagexeRE, 2019-06-05JRagexeRE, 2019-06-05KRagexe, 2019-06-05LRagexeRE, 2019-06-05fRagexe, 2019-06-05hRagexeRE, 2019-06-19bRagexe, 2019-06-19cRagexeRE, 2019-06-19eRagexe, 2019-06-19hRagexe, 2019-06-26bRagexeRE, 2019-07-03aRagexe, 2019-07-03bRagexeRE, 2019-07-17aRagexe, 2019-07-17cRagexeRE, 2019-07-17dRagexe, 2019-07-17dRagexeRE, 2019-07-24aRagexe, 2019-07-24bRagexeRE, 2019-07-31bRagexe, 2019-07-31bRagexeRE, 2019-08-02aRagexe, 2019-08-02aRagexeRE, 2019-08-07aRagexe, 2019-08-07dRagexeRE, 2019-08-21aRagexe, 2019-08-21cRagexeRE, 2019-08-21dRagexeRE, 2019-08-28aRagexe, 2019-08-28aRagexeRE, 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-04bRagexeRE, 2019-09-18bRagexe, 2019-09-18cRagexeRE, 2019-09-25aRagexe, 2019-09-25aRagexeRE, 2019-09-25bRagexe, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexe, 2019-10-16fRagexeRE, 2019-10-16gRagexe, 2019-10-16gRagexeRE, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-06bRagexeRE, 2019-11-07aRagexe, 2019-11-07aRagexeRE, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-13eRagexeRE, 2019-11-20aRagexe, 2019-11-20cRagexeRE, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27aRagexeRE, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04aRagexeRE, 2019-12-04bRagexe, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11aRagexe, 2019-12-11fRagexeRE, 2019-12-18bRagexe, 2019-12-18bRagexeRE, 2019-12-24aRagexe, 2019-12-24aRagexeRE, 2019-12-24bRagexe, 2019-12-24bRagexeRE, 2020-01-08aRagexe, 2020-01-08bRagexeRE, 2020-01-22cRagexe, 2020-01-22cRagexeRE, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-05aRagexeRE, 2020-02-06aRagexe, 2020-02-12aRagexe, 2020-02-12aRagexeRE, 2020-02-19dRagexe, 2020-02-19eRagexeRE, 2020-03-04aRagexe, 2020-03-04aRagexeRE, 2020-03-18bRagexe, 2020-04-01bRagexe, 2020-04-14_6aRagexe, 2020-04-14eRagexe
+#if PACKETVER == 20101123 || \
+ PACKETVER == 20101124 || \
+ PACKETVER == 20101125 || \
+ PACKETVER == 20101126 || \
+ PACKETVER == 20101130 || \
+ PACKETVER == 20101207 || \
+ PACKETVER == 20101214 || \
+ PACKETVER == 20101221 || \
+ PACKETVER == 20101223 || \
+ PACKETVER == 20101228 || \
+ PACKETVER == 20110104 || \
+ PACKETVER == 20110105 || \
+ PACKETVER == 20110111 || \
+ PACKETVER == 20110118 || \
+ PACKETVER == 20110125 || \
+ PACKETVER == 20110126 || \
+ PACKETVER == 20110131 || \
+ PACKETVER == 20110208 || \
+ PACKETVER == 20110215 || \
+ PACKETVER == 20110222 || \
+ PACKETVER == 20110223 || \
+ PACKETVER == 20110224 || \
+ PACKETVER == 20110225 || \
+ PACKETVER == 20110228 || \
+ PACKETVER == 20110308 || \
+ PACKETVER == 20110309 || \
+ PACKETVER == 20110315 || \
+ PACKETVER == 20110322 || \
+ PACKETVER == 20110329 || \
+ PACKETVER == 20110330 || \
+ PACKETVER == 20110405 || \
+ PACKETVER == 20110412 || \
+ PACKETVER == 20110419 || \
+ PACKETVER == 20110420 || \
+ PACKETVER == 20110426 || \
+ PACKETVER == 20110427 || \
+ PACKETVER == 20110503 || \
+ PACKETVER == 20110511 || \
+ PACKETVER == 20110517 || \
+ PACKETVER == 20110524 || \
+ PACKETVER == 20110526 || \
+ PACKETVER == 20110531 || \
+ PACKETVER == 20110607 || \
+ PACKETVER == 20110608 || \
+ PACKETVER == 20110609 || \
+ PACKETVER == 20110614 || \
+ PACKETVER == 20110622 || \
+ PACKETVER == 20110628 || \
+ PACKETVER == 20110706 || \
+ PACKETVER == 20110713 || \
+ PACKETVER == 20110719 || \
+ PACKETVER == 20110726 || \
+ PACKETVER == 20110803 || \
+ PACKETVER == 20110810 || \
+ PACKETVER == 20131223 || \
+ PACKETVER == 20140508 || \
+ PACKETVER == 20140611 || \
+ PACKETVER == 20150225 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER == 20180404 || \
+ PACKETVER == 20180418 || \
+ PACKETVER == 20180425 || \
+ PACKETVER == 20180502 || \
+ PACKETVER == 20180509 || \
+ PACKETVER == 20180516 || \
+ PACKETVER == 20180523 || \
+ PACKETVER == 20180530 || \
+ PACKETVER == 20180605 || \
+ PACKETVER == 20180612 || \
+ PACKETVER == 20180620 || \
+ PACKETVER == 20180621 || \
+ PACKETVER == 20180704 || \
+ PACKETVER == 20180711 || \
+ PACKETVER == 20180718 || \
+ PACKETVER == 20180801 || \
+ PACKETVER == 20180808 || \
+ PACKETVER == 20180822 || \
+ PACKETVER == 20180829 || \
+ PACKETVER == 20180831 || \
+ PACKETVER == 20180912 || \
+ PACKETVER == 20180919 || \
+ PACKETVER == 20181002 || \
+ PACKETVER == 20181017 || \
+ PACKETVER == 20181024 || \
+ PACKETVER == 20181031 || \
+ PACKETVER == 20181107 || \
+ PACKETVER == 20181114 || \
+ PACKETVER == 20181121 || \
+ PACKETVER == 20181128 || \
+ PACKETVER == 20181205 || \
+ PACKETVER == 20181212 || \
+ PACKETVER == 20181219 || \
+ PACKETVER == 20181226 || \
+ PACKETVER == 20190109 || \
+ PACKETVER == 20190116 || \
+ PACKETVER == 20190123 || \
+ PACKETVER == 20190213 || \
+ PACKETVER == 20190220 || \
+ PACKETVER == 20190227 || \
+ PACKETVER == 20190228 || \
+ PACKETVER == 20190306 || \
+ PACKETVER == 20190313 || \
+ PACKETVER == 20190320 || \
+ PACKETVER == 20190322 || \
+ PACKETVER == 20190327 || \
+ PACKETVER == 20190403 || \
+ PACKETVER == 20190417 || \
+ PACKETVER == 20190418 || \
+ PACKETVER == 20190508 || \
+ PACKETVER == 20190522 || \
+ PACKETVER == 20190523 || \
+ PACKETVER == 20190529 || \
+ PACKETVER == 20190530 || \
+ PACKETVER == 20190605 || \
+ PACKETVER == 20190619 || \
+ PACKETVER == 20190626 || \
+ PACKETVER == 20190703 || \
+ PACKETVER == 20190717 || \
+ PACKETVER == 20190724 || \
+ PACKETVER == 20190731 || \
+ PACKETVER == 20190802 || \
+ PACKETVER == 20190807 || \
+ PACKETVER == 20190821 || \
+ PACKETVER == 20190828 || \
+ PACKETVER == 20190904 || \
+ PACKETVER == 20190918 || \
+ PACKETVER == 20190925 || \
+ PACKETVER == 20191002 || \
+ PACKETVER == 20191016 || \
+ PACKETVER == 20191018 || \
+ PACKETVER == 20191023 || \
+ PACKETVER == 20191030 || \
+ PACKETVER == 20191106 || \
+ PACKETVER == 20191107 || \
+ PACKETVER == 20191113 || \
+ PACKETVER == 20191120 || \
+ PACKETVER == 20191127 || \
+ PACKETVER == 20191204 || \
+ PACKETVER == 20191211 || \
+ PACKETVER == 20191218 || \
+ PACKETVER == 20191224 || \
+ PACKETVER == 20200108 || \
+ PACKETVER == 20200122 || \
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200130 || \
+ PACKETVER == 20200205 || \
+ PACKETVER == 20200206 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401 || \
+ PACKETVER >= 20200414
+ packetKeys(0x00000000,0x00000000,0x00000000);
+#endif
+
+// 2010-11-30aRagexe
+#if PACKETVER == 20101130
+ packetKeys(0x3726593c,0x0efd5ee8,0x79036df9);
+#endif
+
+// 2010-12-07bRagexe
+#if PACKETVER == 20101207
+ packetKeys(0x66111112,0x2b7b53aa,0x04e76df8);
+#endif
+
+// 2010-12-14aRagexe
+#if PACKETVER == 20101214
+ packetKeys(0x5e535d06,0x4e297f0e,0x400b6ad8);
+#endif
+
+// 2010-12-21aRagexe
+#if PACKETVER == 20101221
+ packetKeys(0x0448466a,0x41554ac9,0x5b4710b2);
+#endif
+
+// 2010-12-28aRagexe
+#if PACKETVER == 20101228
+ packetKeys(0x50c638a5,0x4bf86b20,0x480c3746);
+#endif
+
+// 2011-01-04aRagexe
+#if PACKETVER == 20110104
+ packetKeys(0x55db401f,0x047d4e02,0x6d8f2ea3);
+#endif
+
+// 2011-01-11aRagexe
+#if PACKETVER == 20110111
+ packetKeys(0x2d5f6302,0x2a361cd6,0x39d661d6);
+#endif
+
+// 2011-01-18aRagexe
+#if PACKETVER == 20110118
+ packetKeys(0x3c777d2d,0x00541a1d,0x5e0053a2);
+#endif
+
+// 2011-01-25aRagexe, 2011-01-26aRagexe, 2011-01-26bRagexe, 2011-01-31aRagexe
+#if PACKETVER == 20110125 || \
+ PACKETVER == 20110126 || \
+ PACKETVER == 20110131
+ packetKeys(0x6bb84bb0,0x4c004382,0x10ae3260);
+#endif
+
+// 2011-01-31bRagexe, 2011-02-01aRagexe
+#if PACKETVER == 20110131 || \
+ PACKETVER == 20110201
+ packetKeys(0x68871e62,0x60d17266,0x74726daa);
+#endif
+
+// 2011-02-08aRagexe, 2011-02-10aRagexe, 2011-02-10bRagexe
+#if PACKETVER == 20110208 || \
+ PACKETVER == 20110210
+ packetKeys(0x72ba4e9d,0x281e1df1,0x208255aa);
+#endif
+
+// 2011-02-15aRagexe
+#if PACKETVER == 20110215
+ packetKeys(0x1b174d76,0x32005014,0x7b8b72d5);
+#endif
+
+// 2011-02-22aRagexe, 2011-02-23aRagexe, 2011-02-23bRagexe, 2011-02-24aRagexe, 2011-02-25aRagexe, 2011-02-25bRagexe
+#if PACKETVER == 20110222 || \
+ PACKETVER == 20110223 || \
+ PACKETVER == 20110224 || \
+ PACKETVER == 20110225
+ packetKeys(0x48f73b56,0x155f7d66,0x44ab57ce);
+#endif
+
+// 2011-02-28aRagexe
+#if PACKETVER == 20110228
+ packetKeys(0x26385ebf,0x7a8c7534,0x60ae2c34);
+#endif
+
+// 2011-03-08aRagexe, 2011-03-09aRagexe, 2011-03-09bRagexe, 2011-03-09cRagexe, 2011-03-09dRagexe
+#if PACKETVER == 20110308 || \
+ PACKETVER == 20110309
+ packetKeys(0x003f1b20,0x7a1e12a3,0x34994aad);
+#endif
+
+// 2011-03-15aRagexe, 2011-03-16aRagexe
+#if PACKETVER == 20110315 || \
+ PACKETVER == 20110316
+ packetKeys(0x62967d7d,0x34833d1a,0x26d45eca);
+#endif
+
+// 2011-03-22aRagexe
+#if PACKETVER == 20110322
+ packetKeys(0x5870617c,0x638d5376,0x739f4817);
+#endif
+
+// 2011-03-29aRagexe, 2011-03-30aRagexe
+#if PACKETVER == 20110329 || \
+ PACKETVER == 20110330
+ packetKeys(0x06900bb7,0x45db687b,0x197b017b);
+#endif
+
+// 2011-04-05aRagexe
+#if PACKETVER == 20110405
+ packetKeys(0x248d5c37,0x1c6a1b37,0x1f644fdb);
+#endif
+
+// 2011-04-12bRagexe
+#if PACKETVER == 20110412
+ packetKeys(0x3de86bfc,0x0dd47f80,0x42481c9b);
+#endif
+
+// 2011-04-19aRagexe
+#if PACKETVER == 20110419
+ packetKeys(0x26073204,0x62013a51,0x22ac58e0);
+#endif
+
+// 2011-04-26aRagexe
+#if PACKETVER == 20110426
+ packetKeys(0x392813f9,0x09905054,0x40db732e);
+#endif
+
+// 2011-05-03aRagexe
+#if PACKETVER == 20110503
+ packetKeys(0x28be32ee,0x1d506fcb,0x63832421);
+#endif
+
+// 2011-05-11aRagexe
+#if PACKETVER == 20110511
+ packetKeys(0x6a715733,0x3c5c0d74,0x408a48ec);
+#endif
+
+// 2011-05-17aRagexe
+#if PACKETVER == 20110517
+ packetKeys(0x07fe0c72,0x46766bad,0x5eb5126a);
+#endif
+
+// 2011-05-23aRagexe, 2011-05-26bRagexe
+#if PACKETVER == 20110523 || \
+ PACKETVER == 20110526
+ packetKeys(0x69166916,0x69166916,0x69166916);
+#endif
+
+// 2011-05-31aRagexe
+#if PACKETVER == 20110531
+ packetKeys(0x5aba2c7c,0x3cd22073,0x78953988);
+#endif
+
+// 2011-06-07aRagexe, 2011-06-08aRagexe, 2011-06-08bRagexe, 2011-06-08cRagexe, 2011-06-09aRagexe
+#if PACKETVER == 20110607 || \
+ PACKETVER == 20110608 || \
+ PACKETVER == 20110609
+ packetKeys(0x76b0426c,0x0dd74deb,0x1f92228e);
+#endif
+
+// 2011-06-14aRagexe
+#if PACKETVER == 20110614
+ packetKeys(0x5749027b,0x71710972,0x5b096475);
+#endif
+
+// 2011-06-20aRagexe
+#if PACKETVER == 20110620
+ packetKeys(0x3a1760d4,0x254e0df9,0x440e2357);
+#endif
+
+// 2011-06-27aRagexe
+#if PACKETVER == 20110627
+ packetKeys(0x3efc29bd,0x699e4b11,0x7b900a13);
+#endif
+
+// 2011-07-05aRagexe
+#if PACKETVER == 20110705
+ packetKeys(0x48801a5e,0x68fc7726,0x081d7f6e);
+#endif
+
+// 2011-07-11bRagexe, 2011-07-13aRagexe, 2011-07-13bRagexe
+#if PACKETVER == 20110711 || \
+ PACKETVER == 20110713
+ packetKeys(0x489c544b,0x33ba1c25,0x2de66e4e);
+#endif
+
+// 2011-07-18aRagexe
+#if PACKETVER == 20110718
+ packetKeys(0x08464674,0x1eeb3bd5,0x33395199);
+#endif
+
+// 2011-07-26aRagexe
+#if PACKETVER == 20110726
+ packetKeys(0x41e5730b,0x119c6c11,0x5356524a);
+#endif
+
+// 2011-08-02aRagexe
+#if PACKETVER == 20110802
+ packetKeys(0x607c08a1,0x65b20528,0x360571e9);
+#endif
+
+// 2011-08-09aRagexe
+#if PACKETVER == 20110809
+ packetKeys(0x742a559a,0x047f425d,0x5c8c2ca0);
+#endif
+
+// 2011-08-16aRagexe, 2011-08-16aRagexeRE, 2011-08-17aRagexe, 2011-08-17aRagexeRE, 2011-08-17bRagexe, 2011-08-17bRagexeRE
+#if PACKETVER == 20110816 || \
+ PACKETVER == 20110817
+ packetKeys(0x053d5ced,0x3ded6ded,0x6ded6ded);
+#endif
+
+// 2011-08-23aRagexe, 2011-08-23aRagexeRE, 2011-08-24aRagexe, 2011-08-24aRagexeRE, 2011-08-24bRagexeRE
+#if PACKETVER == 20110823 || \
+ PACKETVER == 20110824
+ packetKeys(0x35c91401,0x262a5556,0x28fa03aa);
+#endif
+
+// 2011-08-31aRagexe, 2011-08-31aRagexeRE, 2011-08-31bRagexe, 2011-08-31bRagexeRE, 2011-08-31cRagexe, 2011-08-31cRagexeRE, 2011-08-31dRagexeRE, 2011-08-31eRagexeRE
+#if PACKETVER == 20110831
+ packetKeys(0x3ad67ed0,0x44703c69,0x6f876809);
+#endif
+
+// 2011-09-06aRagexe, 2011-09-06aRagexeRE, 2011-09-14aRagexe, 2011-09-14aRagexeRE
+#if PACKETVER == 20110906 || \
+ PACKETVER == 20110914
+ packetKeys(0x350124ec,0x39a14595,0x0de56125);
+#endif
+
+// 2011-09-20aRagexe, 2011-09-20aRagexeRE, 2011-09-20aRagexeRE2
+#if PACKETVER == 20110920
+ packetKeys(0x79c91a12,0x20450cc0,0x584b2a38);
+#endif
+
+// 2011-09-28aRagexe, 2011-09-28aRagexe-retry, 2011-09-28aRagexeRE, 2011-09-29aRagexe, 2011-09-29aRagexeRE
+#if PACKETVER == 20110928 || \
+ PACKETVER == 20110929
+ packetKeys(0x26567512,0x4b0732df,0x57d266c6);
+#endif
+
+// 2011-10-04aRagexe, 2011-10-04aRagexeRE, 2011-10-05aRagexe, 2011-10-05aRagexeRE
+#if PACKETVER == 20111004 || \
+ PACKETVER == 20111005
+ packetKeys(0x291e6762,0x77cd391a,0x60ac2f16);
+#endif
+
+// 2011-10-10aRagexe, 2011-10-10bRagexeRE, 2011-10-12aRagexeRE, 2011-10-12bRagexe
+#if PACKETVER == 20111010 || \
+ PACKETVER == 20111012
+ packetKeys(0x7f3c2d29,0x59b01de6,0x1dbb44ca);
+#endif
+
+// 2011-10-17aRagexe, 2011-10-17aRagexeRE, 2011-10-19aRagexeRE, 2011-10-19bRagexeRE, 2011-10-21aRagexe, 2011-10-21aRagexeRE, 2011-10-21cRagexe
+#if PACKETVER == 20111017 || \
+ PACKETVER == 20111019 || \
+ PACKETVER == 20111021
+ packetKeys(0x357d55dc,0x5a8d759f,0x245c30f5);
+#endif
+
+// 2011-10-25aRagexe, 2011-10-25aRagexeRE
+#if PACKETVER == 20111025
+ packetKeys(0x50ae1a63,0x3ce579b5,0x29c10406);
+#endif
+
+// 2011-11-01cRagexe, 2011-11-01cRagexeRE, 2011-11-02aRagexe, 2011-11-02aRagexeRE
+#if PACKETVER == 20111101 || \
+ PACKETVER == 20111102
+ packetKeys(0x5324329d,0x5d545d52,0x06137269);
+#endif
+
+// 2011-11-08aRagexe, 2011-11-08aRagexeRE, 2011-11-09aRagexe, 2011-11-09aRagexeRE, 2011-11-09bRagexe, 2011-11-09cRagexe, 2011-11-09dRagexe, 2011-11-09eRagexe
+#if PACKETVER == 20111108 || \
+ PACKETVER == 20111109
+ packetKeys(0x0b642bda,0x6ecb1d1c,0x61c7454b);
+#endif
+
+// 2011-11-14aRagexe, 2011-11-14aRagexeRE, 2011-11-16aRagexe, 2011-11-16aRagexeRE
+#if PACKETVER == 20111114 || \
+ PACKETVER == 20111116
+ packetKeys(0x419d0db0,0x74916bf4,0x027371b4);
+#endif
+
+// 2011-11-22aRagexe, 2011-11-22aRagexeRE, 2011-11-23aRagexe
+#if PACKETVER == 20111122 || \
+ PACKETVER == 20111123
+ packetKeys(0x3b550f07,0x1f666c7c,0x60304ef5);
+#endif
+
+// 2011-12-07aRagexe, 2011-12-07aRagexeRE
+#if PACKETVER == 20111207
+ packetKeys(0x2a610886,0x3e09165e,0x57c11888);
+#endif
+
+// 2011-12-13aRagexe, 2011-12-13aRagexeRE, 2011-12-14aRagexe, 2011-12-14aRagexeRE, 2011-12-14bRagexeRE, 2011-12-14cRagexeRE
+#if PACKETVER == 20111213 || \
+ PACKETVER == 20111214
+ packetKeys(0x5151306b,0x7ae32886,0x53060628);
+#endif
+
+// 2011-12-20bRagexe, 2011-12-20bRagexeRE
+#if PACKETVER == 20111220
+ packetKeys(0x05d53871,0x7d0027b4,0x29975333);
+#endif
+
+// 2011-12-27aRagexe, 2011-12-27aRagexeRE, 2011-12-28aRagexe, 2011-12-28aRagexeRE
+#if PACKETVER == 20111227 || \
+ PACKETVER == 20111228
+ packetKeys(0x0ff87e93,0x6cff7860,0x3a3d1dec);
+#endif
+
+// 2012-01-03aRagexe, 2012-01-03bRagexeRE, 2012-01-04aRagexe, 2012-01-04aRagexeRE, 2012-01-04bRagexe
+#if PACKETVER == 20120103 || \
+ PACKETVER == 20120104
+ packetKeys(0x262034a1,0x674542a5,0x73a50ba5);
+#endif
+
+// 2012-01-10aRagexeRE, 2012-01-10bRagexe
+#if PACKETVER == 20120110
+ packetKeys(0x2b412afc,0x4ff94487,0x6705339d);
+#endif
+
+// 2012-01-17aRagexe, 2012-01-17aRagexeRE, 2012-01-18aRagexe
+#if PACKETVER == 20120117 || \
+ PACKETVER == 20120118
+ packetKeys(0x24e32c2e,0x48dd17a5,0x64f8771a);
+#endif
+
+// 2012-01-20aRagexe, 2012-01-20aRagexeRE
+#if PACKETVER == 20120120
+ packetKeys(0x504345d0,0x3d427b1b,0x794c2dcc);
+#endif
+
+// 2012-01-31aRagexe, 2012-01-31cRagexeRE, 2012-02-01aRagexeRE, 2012-02-02aRagexe, 2012-02-02aRagexeRE, 2012-02-02bRagexe, 2012-02-02bRagexeRE
+#if PACKETVER == 20120131 || \
+ PACKETVER == 20120201 || \
+ PACKETVER == 20120202
+ packetKeys(0x2cfc0a71,0x2ba91d8d,0x087e39e0);
+#endif
+
+// 2012-02-07bRagexe, 2012-02-07bRagexeRE, 2012-02-08aRagexe, 2012-02-09aRagexe
+#if PACKETVER == 20120207 || \
+ PACKETVER == 20120208 || \
+ PACKETVER == 20120209
+ packetKeys(0x1d373f5d,0x5acd604d,0x1c4d7c4d);
+#endif
+
+// 2012-02-14bRagexe, 2012-02-14bRagexeRE, 2012-02-15aRagexe
+#if PACKETVER == 20120214 || \
+ PACKETVER == 20120215
+ packetKeys(0x7a255efa,0x30977276,0x2d4a0448);
+#endif
+
+// 2012-02-21aRagexe, 2012-02-21aRagexeRE, 2012-02-22aRagexe, 2012-02-22aRagexeRE
+#if PACKETVER == 20120221 || \
+ PACKETVER == 20120222
+ packetKeys(0x1ca5130f,0x43ed240a,0x7fea3be0);
+#endif
+
+// 2012-02-28bRagexe, 2012-02-28bRagexeRE, 2012-02-29aRagexe, 2012-02-29aRagexeRE
+#if PACKETVER == 20120228 || \
+ PACKETVER == 20120229
+ packetKeys(0x520b4c64,0x2800407d,0x47651458);
+#endif
+
+// 2012-03-07aRagexe, 2012-03-07aRagexeRE, 2012-03-07bRagexe, 2012-03-07bRagexeRE, 2012-03-07cRagexe, 2012-03-07cRagexeRE, 2012-03-07dRagexe, 2012-03-07dRagexeRE, 2012-03-07eRagexeRE, 2012-03-07fRagexeRE
+#if PACKETVER == 20120307
+ packetKeys(0x382a6def,0x5cbe7202,0x61f46637);
+#endif
+
+// 2012-03-14aRagexe, 2012-03-14aRagexeRE, 2012-03-14bRagexe, 2012-03-14bRagexeRE, 2012-03-14cRagexe, 2012-03-14cRagexeRE
+#if PACKETVER == 20120314
+ packetKeys(0x689c1729,0x11812639,0x60f82967);
+#endif
+
+// 2012-03-20aRagexe, 2012-03-20aRagexeRE, 2012-03-21aRagexeRE
+#if PACKETVER == 20120320 || \
+ PACKETVER == 20120321
+ packetKeys(0x21f9683f,0x710c5ca5,0x1fd910e9);
+#endif
+
+// 2012-03-28aRagexe, 2012-03-28aRagexeRE, 2012-03-28bRagexe, 2012-03-28bRagexeRE, 2012-03-28cRagexe, 2012-03-28cRagexeRE, 2012-03-28dRagexe, 2012-03-28dRagexeRE, 2012-03-28eRagexeRE, 2012-03-28fRagexeRE, 2012-03-28gRagexeRE
+#if PACKETVER == 20120328
+ packetKeys(0x75b8553b,0x37f20b12,0x385c2b40);
+#endif
+
+// 2012-04-04aRagexe, 2012-04-04aRagexeRE
+#if PACKETVER == 20120404
+ packetKeys(0x0036310c,0x2dcd0bed,0x1ee62a78);
+#endif
+
+// 2012-04-10aRagexe, 2012-04-10aRagexeRE
+#if PACKETVER == 20120410
+ packetKeys(0x01581359,0x452d6ffa,0x6afb6e2e);
+#endif
+
+// 2012-04-17aRagexe, 2012-04-17aRagexeRE, 2012-04-18aRagexeRE
+#if PACKETVER == 20120417 || \
+ PACKETVER == 20120418
+ packetKeys(0x01540e48,0x13041224,0x31247924);
+#endif
+
+// 2012-04-24aRagexe, 2012-04-24aRagexeRE
+#if PACKETVER == 20120424
+ packetKeys(0x411d1dbb,0x4cba4848,0x1a432fc4);
+#endif
+
+// 2012-05-02aRagexeRE, 2012-05-03aRagexe, 2012-05-03aRagexeRE, 2012-05-03bRagexe
+#if PACKETVER == 20120502 || \
+ PACKETVER == 20120503
+ packetKeys(0x37a91d19,0x10190019,0x00190019);
+#endif
+
+// 2012-05-08aRagexe, 2012-05-08aRagexeRE, 2012-05-09aRagexeRE, 2012-05-09bRagexeRE
+#if PACKETVER == 20120508 || \
+ PACKETVER == 20120509
+ packetKeys(0x16cf3301,0x1f472b9b,0x0b4a3cd2);
+#endif
+
+// 2012-05-15aRagexe, 2012-05-15aRagexeRE
+#if PACKETVER == 20120515
+ packetKeys(0x4a715ef9,0x79103e4f,0x405c1238);
+#endif
+
+// 2012-05-22aRagexe, 2012-05-23aRagexe, 2012-05-23aRagexeRE, 2012-05-23bRagexeRE, 2012-05-25aRagexeRE
+#if PACKETVER == 20120522 || \
+ PACKETVER == 20120523 || \
+ PACKETVER == 20120525
+ packetKeys(0x70eb4ccb,0x0487713c,0x398d4b08);
+#endif
+
+// 2012-05-29bRagexe, 2012-05-29bRagexeRE
+#if PACKETVER == 20120529
+ packetKeys(0x53415dde,0x34953e16,0x27623df2);
+#endif
+
+// 2012-06-01aRagexeRE, 2012-06-04aRagexe, 2012-06-05aRagexeRE
+#if PACKETVER == 20120601 || \
+ PACKETVER == 20120604 || \
+ PACKETVER == 20120605
+ packetKeys(0x68ca3080,0x31b74bdd,0x505208f1);
+#endif
+
+// 2012-06-12aRagexe, 2012-06-12aRagexeRE
+#if PACKETVER == 20120612
+ packetKeys(0x32e45d64,0x35643564,0x35643564);
+#endif
+
+// 2012-06-18aRagexe, 2012-06-18aRagexeRE
+#if PACKETVER == 20120618
+ packetKeys(0x261f261f,0x261f261f,0x261f261f);
+#endif
+
+// 2012-06-26aRagexe, 2012-06-26aRagexeRE, 2012-06-27aRagexe, 2012-06-27aRagexeRE
+#if PACKETVER == 20120626 || \
+ PACKETVER == 20120627
+ packetKeys(0x02277e66,0x045723f1,0x7107392c);
+#endif
+
+// 2012-07-02aRagexe, 2012-07-02aRagexeRE
+#if PACKETVER == 20120702
+ packetKeys(0x25733b31,0x53486cfd,0x398649bd);
+#endif
+
+// 2012-07-10aRagexe, 2012-07-10aRagexeRE, 2012-07-12aRagexe, 2012-07-12aRagexeRE
+#if PACKETVER == 20120710 || \
+ PACKETVER == 20120712
+ packetKeys(0x0e8b7afb,0x6930362d,0x42d33a57);
+#endif
+
+// 2012-07-16aRagexe, 2012-07-16aRagexeRE
+#if PACKETVER == 20120716
+ packetKeys(0x76052205,0x22052205,0x22052205);
+#endif
+
+// 2012-07-24aRagexe, 2012-07-24aRagexeRE
+#if PACKETVER == 20120724
+ packetKeys(0x783d5bc6,0x3aac2176,0x66616f02);
+#endif
+
+// 2012-08-01aRagexe, 2012-08-01aRagexeRE, 2012-08-01bRagexe, 2012-08-01bRagexeRE
+#if PACKETVER == 20120801
+ packetKeys(0x71fb6768,0x5843166b,0x6cb445c6);
+#endif
+
+// 2012-08-08aRagexe, 2012-08-08aRagexeRE, 2012-08-08bRagexe, 2012-08-08bRagexeRE, 2012-08-08cRagexe, 2012-08-08cRagexeRE, 2012-08-08dRagexeRE
+#if PACKETVER == 20120808
+ packetKeys(0x5d5068bb,0x36732065,0x47cf7367);
+#endif
+
+// 2012-08-14aRagexe, 2012-08-14aRagexeRE, 2012-08-14bRagexe, 2012-08-14bRagexeRE
+#if PACKETVER == 20120814
+ packetKeys(0x203e21bd,0x047459fb,0x56af5a97);
+#endif
+
+// 2012-08-22aRagexe, 2012-08-22aRagexeRE, 2012-08-22bRagexe, 2012-08-22bRagexeRE, 2012-08-22cRagexe, 2012-08-22cRagexeRE
+#if PACKETVER == 20120822
+ packetKeys(0x06a92e7b,0x3d324f29,0x5fd63004);
+#endif
+
+// 2012-08-30aRagexe, 2012-08-30aRagexeRE, 2012-08-30bRagexeRE
+#if PACKETVER == 20120830
+ packetKeys(0x0af1363d,0x4ab33e3b,0x48421dbe);
+#endif
+
+// 2012-09-05aRagexe, 2012-09-05aRagexeRE
+#if PACKETVER == 20120905
+ packetKeys(0x04f50d80,0x092f5c4d,0x29bf3dcf);
+#endif
+
+// 2012-09-11aRagexe, 2012-09-11aRagexeRE
+#if PACKETVER == 20120911
+ packetKeys(0x1f3d1145,0x02db3c32,0x4be34c49);
+#endif
+
+// 2012-09-19aRagexe, 2012-09-19aRagexeRE
+#if PACKETVER == 20120919
+ packetKeys(0x72e00f24,0x4ea02d80,0x7c803480);
+#endif
+
+// 2012-09-25aRagexe, 2012-09-25aRagexeRE, 2012-09-26aRagexe, 2012-09-26aRagexeRE
+#if PACKETVER == 20120925 || \
+ PACKETVER == 20120926
+ packetKeys(0x43a66e22,0x36c2229f,0x08172ece);
+#endif
+
+// 2012-10-10aRagexe, 2012-10-10aRagexeRE, 2012-10-10bRagexe, 2012-10-10bRagexeRE, 2012-10-11aRagexeRE
+#if PACKETVER == 20121010 || \
+ PACKETVER == 20121011
+ packetKeys(0x169733e2,0x4c4640dc,0x31636531);
+#endif
+
+// 2012-10-17aRagexe, 2012-10-17aRagexeRE, 2012-10-17bRagexe, 2012-10-17bRagexeRE
+#if PACKETVER == 20121017
+ packetKeys(0x340c0c31,0x33205ea8,0x55964bff);
+#endif
+
+// 2012-10-24aRagexe, 2012-10-24aRagexeRE
+#if PACKETVER == 20121024
+ packetKeys(0x6166335c,0x45393483,0x7edc5478);
+#endif
+
+// 2012-10-31aRagexe, 2012-10-31aRagexeRE
+#if PACKETVER == 20121031
+ packetKeys(0x66eb7adb,0x242864bb,0x354a4cde);
+#endif
+
+// 2012-11-07aRagexe, 2012-11-07aRagexeRE
+#if PACKETVER == 20121107
+ packetKeys(0x49967892,0x48025276,0x1e192ca3);
+#endif
+
+// 2012-11-14aRagexe, 2012-11-14aRagexeRE
+#if PACKETVER == 20121114
+ packetKeys(0x3473545c,0x2706445c,0x79647616);
+#endif
+
+// 2012-11-21aRagexe, 2012-11-21aRagexeRE
+#if PACKETVER == 20121121
+ packetKeys(0x6eb54b0b,0x3f2a6be5,0x0b2866e6);
+#endif
+
+// 2012-11-28aRagexe, 2012-11-28aRagexeRE
+#if PACKETVER == 20121128
+ packetKeys(0x146d4d5e,0x5c3d161b,0x759250b8);
+#endif
+
+// 2012-12-05aRagexe, 2012-12-05aRagexeRE, 2012-12-05bRagexe, 2012-12-05bRagexeRE
+#if PACKETVER == 20121205
+ packetKeys(0x218c64b6,0x4efe17ae,0x27ea5e74);
+#endif
+
+// 2012-12-12aRagexe, 2012-12-12aRagexeRE, 2012-12-12bRagexe, 2012-12-12bRagexeRE, 2012-12-12cRagexeRE
+#if PACKETVER == 20121212
+ packetKeys(0x7f8026f0,0x32ee2a4b,0x73746c0e);
+#endif
+
+// 2012-12-18aRagexe, 2012-12-18aRagexeRE, 2012-12-18bRagexe, 2012-12-18bRagexeRE
+#if PACKETVER == 20121218
+ packetKeys(0x6a5450a2,0x4322498a,0x2c6574fb);
+#endif
+
+// 2012-12-27aRagexe, 2012-12-27aRagexeRE
+#if PACKETVER == 20121227
+ packetKeys(0x71773018,0x36a14eeb,0x28cd5a20);
+#endif
+
+// 2013-01-03aRagexe, 2013-01-03aRagexeRE, 2013-01-07aRagexe
+#if PACKETVER == 20130103 || \
+ PACKETVER == 20130107
+ packetKeys(0x1e1a559a,0x199a799a,0x799a799a);
+#endif
+
+// 2013-01-09aRagexe, 2013-01-09aRagexeRE
+#if PACKETVER == 20130109
+ packetKeys(0x6435360f,0x0a283678,0x64a04ac7);
+#endif
+
+// 2013-01-15aRagexeRE, 2013-01-15bRagexe, 2013-01-16aRagexe, 2013-01-16aRagexeRE, 2013-01-16bRagexe
+#if PACKETVER == 20130115 || \
+ PACKETVER == 20130116
+ packetKeys(0x273c25cd,0x06aa48af,0x45a01bd4);
+#endif
+
+// 2013-01-21aRagexe, 2013-01-21aRagexeRE
+#if PACKETVER == 20130121
+ packetKeys(0x5dd874b0,0x7d98233f,0x28ff5566);
+#endif
+
+// 2013-01-30aRagexe, 2013-01-30aRagexeRE
+#if PACKETVER == 20130130
+ packetKeys(0x1ea57961,0x27786856,0x30301fa0);
+#endif
+
+// 2013-02-06aRagexe, 2013-02-06aRagexeRE
+#if PACKETVER == 20130206
+ packetKeys(0x1d8f4227,0x675812aa,0x29132929);
+#endif
+
+// 2013-02-15aRagexe, 2013-02-15aRagexeRE, 2013-02-15bRagexe
+#if PACKETVER == 20130215
+ packetKeys(0x69fb1c38,0x7d386860,0x62805311);
+#endif
+
+// 2013-02-20aRagexe, 2013-02-20bRagexeRE
+#if PACKETVER == 20130220
+ packetKeys(0x0d555256,0x28c26722,0x72220a22);
+#endif
+
+// 2013-02-27aRagexe, 2013-02-27aRagexeRE
+#if PACKETVER == 20130227
+ packetKeys(0x44f86842,0x43786a7a,0x71654528);
+#endif
+
+// 2013-03-06aRagexe, 2013-03-06aRagexeRE, 2013-03-06bRagexeRE
+#if PACKETVER == 20130306
+ packetKeys(0x7e274326,0x7d182df2,0x4fc27dfa);
+#endif
+
+// 2013-03-13aRagexe, 2013-03-13aRagexeRE, 2013-03-13bRagexeRE, 2013-03-13cRagexeRE
+#if PACKETVER == 20130313
+ packetKeys(0x560021c3,0x6a5d110f,0x52bd40a5);
+#endif
+
+// 2013-03-20bRagexeRE, 2013-03-20cRagexeRE, 2013-03-20dRagexe, 2013-03-20eRagexe
+#if PACKETVER == 20130320
+ packetKeys(0x3f094c49,0x55f86c1e,0x58aa359a);
+#endif
+
+// 2013-03-27bRagexe, 2013-03-27bRagexeRE
+#if PACKETVER == 20130327
+ packetKeys(0x114b1ba0,0x2c4f0ae2,0x5fa1183f);
+#endif
+
+// 2013-04-03aRagexe, 2013-04-03aRagexeRE
+#if PACKETVER == 20130403
+ packetKeys(0x424a43ae,0x4a9d5ebe,0x4b3518a9);
+#endif
+
+// 2013-04-10aRagexe, 2013-04-10aRagexeRE
+#if PACKETVER == 20130410
+ packetKeys(0x3ad52aca,0x314d1aed,0x086e415e);
+#endif
+
+// 2013-04-17aRagexe, 2013-04-17aRagexeRE
+#if PACKETVER == 20130417
+ packetKeys(0x7fb13b83,0x6e003749,0x07a02b94);
+#endif
+
+// 2013-04-24aRagexe, 2013-04-24aRagexeRE
+#if PACKETVER == 20130424
+ packetKeys(0x79f679f6,0x79f679f6,0x79f679f6);
+#endif
+
+// 2013-05-02aRagexe, 2013-05-02aRagexeRE, 2013-05-02bRagexe
+#if PACKETVER == 20130502
+ packetKeys(0x62e733b9,0x62204281,0x7f044dca);
+#endif
+
+// 2013-05-08bRagexe, 2013-05-08bRagexeRE, 2013-05-08cRagexe, 2013-05-08dRagexe, 2013-05-08eRagexe, 2013-05-08fRagexe
+#if PACKETVER == 20130508
+ packetKeys(0x25421e49,0x175200ba,0x6c0b5239);
+#endif
+
+// 2013-05-15aRagexe, 2013-05-15aRagexeRE
+#if PACKETVER == 20130515
+ packetKeys(0x75794a38,0x58a96bc1,0x296e6fb8);
+#endif
+
+// 2013-05-22aRagexe, 2013-05-22aRagexeRE
+#if PACKETVER == 20130522
+ packetKeys(0x6948050b,0x06511d9d,0x725d4df1);
+#endif
+
+// 2013-05-29aRagexe, 2013-05-29aRagexeRE
+#if PACKETVER == 20130529
+ packetKeys(0x023a6c87,0x14bf1f1e,0x5cc70cc9);
+#endif
+
+// 2013-06-05aRagexe, 2013-06-05bRagexe, 2013-06-05cRagexeRE
+#if PACKETVER == 20130605
+ packetKeys(0x646e08d9,0x5f153ab5,0x61b509b5);
+#endif
+
+// 2013-06-12aRagexe, 2013-06-12bRagexe, 2013-06-12bRagexeRE, 2013-06-12cRagexe, 2013-06-12dRagexe, 2013-06-12eRagexe
+#if PACKETVER == 20130612
+ packetKeys(0x6d166f66,0x3c000fcf,0x295b0fcb);
+#endif
+
+// 2013-06-18#1aRagexe, 2013-06-18#1aRagexeRE
+#if PACKETVER == 20130618
+ packetKeys(0x434115de,0x34a10fe9,0x6791428e);
+#endif
+
+// 2013-06-26_3bRagexeRE, 2013-06-26_3cRagexe, 2013-06-26aRagexeRE, 2013-06-26bRagexe
+#if PACKETVER == 20130626
+ packetKeys(0x38f453ef,0x6a040fd8,0x65bd6668);
+#endif
+
+// 2013-07-03aRagexe, 2013-07-03bRagexeRE
+#if PACKETVER == 20130703
+ packetKeys(0x4ff90e23,0x0f1432f2,0x4cfa1eda);
+#endif
+
+// 2013-07-10aRagexeRE, 2013-07-10bRagexe, 2013-07-10bRagexeRE, 2013-07-10cRagexeRE, 2013-07-10dRagexeRE, 2013-07-10eRagexeRE
+#if PACKETVER == 20130710
+ packetKeys(0x4a9c4237,0x4ccf3f8f,0x458f758f);
+#endif
+
+// 2013-07-17cRagexe, 2013-07-17cRagexeRE, 2013-07-17dRagexeRE, 2013-07-17eRagexeRE
+#if PACKETVER == 20130717
+ packetKeys(0x5ee5520c,0x5f9e00cf,0x2bed4f91);
+#endif
+
+// 2013-07-24eRagexe, 2013-07-24eRagexeRE, 2013-07-24fRagexeRE
+#if PACKETVER == 20130724
+ packetKeys(0x3c243bf5,0x42cc4e2f,0x02106ec6);
+#endif
+
+// 2013-07-31cRagexe, 2013-07-31cRagexeRE
+#if PACKETVER == 20130731
+ packetKeys(0x1e9d11a6,0x21a232b8,0x6a9e02b7);
+#endif
+
+// 2013-08-07aRagexe, 2013-08-07aRagexeRE
+#if PACKETVER == 20130807
+ packetKeys(0x7e241de0,0x5e805580,0x3d807d80);
+#endif
+
+// 2013-08-14aRagexe, 2013-08-14aRagexeRE
+#if PACKETVER == 20130814
+ packetKeys(0x23a23148,0x0c41420e,0x53785ad7);
+#endif
+
+// 2013-08-21bRagexe, 2013-08-21dRagexeRE
+#if PACKETVER == 20130821
+ packetKeys(0x51673f38,0x01663512,0x5cff0b3d);
+#endif
+
+// 2013-08-28bRagexe, 2013-08-28bRagexeRE, 2013-08-28cRagexe, 2013-08-28cRagexeRE
+#if PACKETVER == 20130828
+ packetKeys(0x02ef7a9a,0x4882042f,0x76796678);
+#endif
+
+// 2013-09-04aRagexe, 2013-09-04bRagexeRE
+#if PACKETVER == 20130904
+ packetKeys(0x41af20c5,0x0997799e,0x4ae803a0);
+#endif
+
+// 2013-09-11aRagexe, 2013-09-11aRagexeRE, 2013-09-11bRagexe, 2013-09-11bRagexeRE
+#if PACKETVER == 20130911
+ packetKeys(0x232b3f47,0x0ad0515f,0x1ca31828);
+#endif
+
+// 2013-09-17aRagexe, 2013-09-17aRagexeRE
+#if PACKETVER == 20130917
+ packetKeys(0x5c9164c5,0x32b62f83,0x52864548);
+#endif
+
+// 2013-09-25aRagexe, 2013-09-25aRagexeRE, 2013-09-25bRagexe, 2013-09-25bRagexeRE, 2013-09-25cRagexe
+#if PACKETVER == 20130925
+ packetKeys(0x4b9c279a,0x0c7849c4,0x72a77646);
+#endif
+
+// 2013-10-02aRagexe, 2013-10-02aRagexeRE
+#if PACKETVER == 20131002
+ packetKeys(0x63a466f7,0x635362f3,0x41f369f3);
+#endif
+
+// 2013-10-08aRagexe, 2013-10-08bRagexeRE
+#if PACKETVER == 20131008
+ packetKeys(0x64924aad,0x08ca0445,0x1cbc36de);
+#endif
+
+// 2013-10-16aRagexe, 2013-10-16aRagexeRE, 2013-10-16bRagexe, 2013-10-16bRagexeRE
+#if PACKETVER == 20131016
+ packetKeys(0x33ad7a93,0x720c7c49,0x12c4205a);
+#endif
+
+// 2013-10-23aRagexe, 2013-10-23aRagexeRE
+#if PACKETVER == 20131023
+ packetKeys(0x02ef6163,0x2b774814,0x58ec3036);
+#endif
+
+// 2013-10-30aRagexe, 2013-10-30aRagexeRE
+#if PACKETVER == 20131030
+ packetKeys(0x4a6a3eff,0x7e2d5237,0x01ca019e);
+#endif
+
+// 2013-11-06aRagexe, 2013-11-06aRagexeRE, 2013-11-07aRagexe, 2013-11-07bRagexe, 2013-11-07cRagexe, 2013-11-08aRagexe
+#if PACKETVER == 20131106 || \
+ PACKETVER == 20131107 || \
+ PACKETVER == 20131108
+ packetKeys(0x143e528f,0x5ca05899,0x44b85b23);
+#endif
+
+// 2013-11-13aRagexeRE, 2013-11-13bRagexe
+#if PACKETVER == 20131113
+ packetKeys(0x44ea14cd,0x49311c88,0x40c86c31);
+#endif
+
+// 2013-11-20dRagexe, 2013-11-20eRagexeRE
+#if PACKETVER == 20131120
+ packetKeys(0x541e5172,0x1b1d30a0,0x28aa7ce5);
+#endif
+
+// 2013-11-27aRagexeRE, 2013-11-27bRagexe, 2013-11-27bRagexeRE
+#if PACKETVER == 20131127
+ packetKeys(0x21426a48,0x5c505d6a,0x046d06ad);
+#endif
+
+// 2013-12-04dRagexeRE, 2013-12-04eRagexe, 2013-12-04eRagexeRE
+#if PACKETVER == 20131204
+ packetKeys(0x792760b2,0x5af45387,0x36165603);
+#endif
+
+// 2013-12-11cRagexe, 2013-12-11cRagexeRE, 2013-12-11dRagexe, 2013-12-11eRagexeRE
+#if PACKETVER == 20131211
+ packetKeys(0x55b0394e,0x4d341ff2,0x60bc1dc3);
+#endif
+
+// 2013-12-18aRagexeRE, 2013-12-18bRagexe
+#if PACKETVER == 20131218
+ packetKeys(0x6a596301,0x76866d0e,0x32294a45);
+#endif
+
+// 2013-12-23bRagexe, 2013-12-23bRagexeRE, 2013-12-23cRagexe, 2013-12-23xRagexeRE
+#if PACKETVER == 20131223
+ packetKeys(0x631c511c,0x111c111c,0x111c111c);
+#endif
+
+// 2013-12-30aRagexe, 2013-12-30aRagexeRE
+#if PACKETVER == 20131230
+ packetKeys(0x611b7097,0x01f957a1,0x768a0fcb);
+#endif
+
+// 2014-01-08bRagexeRE, 2014-01-08cRagexe, 2014-01-08cRagexeRE, 2014-01-08dRagexe
+#if PACKETVER == 20140108
+ packetKeys(0x4a1e26f2,0x231e7efe,0x61fe19fe);
+#endif
+
+// 2014-01-15aRagexe, 2014-01-15bRagexe, 2014-01-15cRagexe, 2014-01-15cRagexeRE, 2014-01-15dRagexeRE, 2014-01-15eRagexe, 2014-01-15eRagexeRE
+#if PACKETVER == 20140115
+ packetKeys(0x63224335,0x0f3a1f27,0x6d217b24);
+#endif
+
+// 2014-01-22aRagexe, 2014-01-22aRagexeRE
+#if PACKETVER == 20140122
+ packetKeys(0x6123177b,0x05b42c99,0x71702594);
+#endif
+
+// 2014-01-29aRagexe, 2014-01-29bRagexeRE, 2014-01-29cRagexe
+#if PACKETVER == 20140129
+ packetKeys(0x2e52163c,0x605e518b,0x3c7a62cb);
+#endif
+
+// 2014-02-05bRagexe, 2014-02-05bRagexeRE
+#if PACKETVER == 20140205
+ packetKeys(0x63dc7bdc,0x7bdc7bdc,0x7bdc7bdc);
+#endif
+
+// 2014-02-12aRagexe, 2014-02-12aRagexeRE
+#if PACKETVER == 20140212
+ packetKeys(0x46837074,0x65292e89,0x77237f9c);
+#endif
+
+// 2014-02-19aRagexe, 2014-02-19aRagexeRE, 2014-02-19bRagexeRE
+#if PACKETVER == 20140219
+ packetKeys(0x4e3c5327,0x3a6b5469,0x2ce36aed);
+#endif
+
+// 2014-02-26aRagexe, 2014-02-26aRagexeRE, 2014-02-26bRagexeRE
+#if PACKETVER == 20140226
+ packetKeys(0x36d71056,0x52122f5e,0x6ff76e99);
+#endif
+
+// 2014-03-05aRagexe, 2014-03-05aRagexeRE, 2014-03-05bRagexe, 2014-03-05bRagexeRE
+#if PACKETVER == 20140305
+ packetKeys(0x116763f2,0x41117dac,0x7fd13c45);
+#endif
+
+// 2014-03-12bRagexeRE, 2014-03-12dRagexe
+#if PACKETVER == 20140312
+ packetKeys(0x48911e4e,0x58cb2eb3,0x05232619);
+#endif
+
+// 2014-03-19aRagexe, 2014-03-19aRagexeRE
+#if PACKETVER == 20140319
+ packetKeys(0x3da44383,0x1abb165f,0x5b6846b9);
+#endif
+
+// 2014-03-26aRagexe, 2014-03-26cRagexeRE
+#if PACKETVER == 20140326
+ packetKeys(0x68e72af6,0x27db4c3d,0x348f2677);
+#endif
+
+// 2014-04-02eRagexeRE, 2014-04-02fRagexe, 2014-04-02fRagexeRE, 2014-04-02gRagexe
+#if PACKETVER == 20140402
+ packetKeys(0x15d3271c,0x004d725b,0x111a3a37);
+#endif
+
+// 2014-04-09aRagexe, 2014-04-09aRagexeRE, 2014-04-09bRagexe
+#if PACKETVER == 20140409
+ packetKeys(0x7f6c390f,0x139c254c,0x7f25708c);
+#endif
+
+// 2014-04-16aRagexe, 2014-04-16aRagexeRE, 2014-04-16bRagexe
+#if PACKETVER == 20140416
+ packetKeys(0x04810281,0x42814281,0x42814281);
+#endif
+
+// 2014-04-23aRagexe, 2014-04-23aRagexeRE
+#if PACKETVER == 20140423
+ packetKeys(0x7e0d6b56,0x74673cd3,0x2eba4940);
+#endif
+
+// 2014-04-30aRagexe, 2014-04-30aRagexeRE
+#if PACKETVER == 20140430
+ packetKeys(0x400145d8,0x3fe50155,0x11624f70);
+#endif
+
+// 2014-05-08bRagexe, 2014-05-08bRagexeRE
+#if PACKETVER == 20140508
+ packetKeys(0x087e57ec,0x25224f4a,0x024f12c6);
+#endif
+
+// 2014-05-14bRagexe, 2014-05-14bRagexeRE, 2014-05-14cRagexeRE
+#if PACKETVER == 20140514
+ packetKeys(0x4be46730,0x047926e0,0x37773bbb);
+#endif
+
+// 2014-05-21aRagexeRE, 2014-05-21bRagexe
+#if PACKETVER == 20140521
+ packetKeys(0x14ed2d86,0x17371c33,0x2d0473c8);
+#endif
+
+// 2014-05-28aRagexe, 2014-05-28aRagexeRE
+#if PACKETVER == 20140528
+ packetKeys(0x579445eb,0x26734878,0x7c861628);
+#endif
+
+// 2014-06-05aRagexe, 2014-06-05aRagexeRE, 2014-06-05bRagexe
+#if PACKETVER == 20140605
+ packetKeys(0x5abc4223,0x04dd2636,0x0d5850e0);
+#endif
+
+// 2014-06-11bRagexeRE, 2014-06-11cRagexe, 2014-06-11dRagexe, 2014-06-11hRagexe, 2014-06-12aRagexe, 2014-06-13aRagexe
+#if PACKETVER == 20140611 || \
+ PACKETVER == 20140612 || \
+ PACKETVER == 20140613
+ packetKeys(0x4fc83479,0x3ab04d1f,0x477b4010);
+#endif
+
+// 2014-06-18aRagexe, 2014-06-18cRagexeRE
+#if PACKETVER == 20140618
+ packetKeys(0x2db507bb,0x11ba12e7,0x7f447760);
+#endif
+
+// 2014-06-25aRagexe, 2014-06-25aRagexeRE, 2014-06-25bRagexe
+#if PACKETVER == 20140625
+ packetKeys(0x09987045,0x644b1051,0x1a091cb8);
+#endif
+
+// 2014-07-02aRagexe, 2014-07-02aRagexeRE
+#if PACKETVER == 20140702
+ packetKeys(0x5c4574f4,0x5d446386,0x48bd24c9);
+#endif
+
+// 2014-07-09aRagexe, 2014-07-09aRagexeRE
+#if PACKETVER == 20140709
+ packetKeys(0x2c7a6e92,0x324f1b85,0x29916fc2);
+#endif
+
+// 2014-07-16aRagexe, 2014-07-16aRagexeRE, 2014-07-16bRagexe, 2014-07-16cRagexe
+#if PACKETVER == 20140716
+ packetKeys(0x0eb20408,0x6d6c4292,0x4f6e4cf3);
+#endif
+
+// 2014-07-23aRagexe, 2014-07-23aRagexeRE, 2014-07-23bRagexe, 2014-07-23bRagexeRE
+#if PACKETVER == 20140723
+ packetKeys(0x42a21713,0x51ce6ead,0x102f7b0b);
+#endif
+
+// 2014-07-30aRagexe, 2014-07-30bRagexeRE
+#if PACKETVER == 20140730
+ packetKeys(0x63ce4e53,0x04f969a3,0x690954db);
+#endif
+
+// 2014-08-06aRagexe, 2014-08-06aRagexeRE, 2014-08-06bRagexe
+#if PACKETVER == 20140806
+ packetKeys(0x0d5b69ac,0x3c001f20,0x0c201420);
+#endif
+
+// 2014-08-13aRagexe, 2014-08-13aRagexeRE, 2014-08-13bRagexe, 2014-08-14aRagexe
+#if PACKETVER == 20140813 || \
+ PACKETVER == 20140814
+ packetKeys(0x7ad51e0a,0x28c72c46,0x210205bd);
+#endif
+
+// 2014-08-20aRagexe, 2014-08-20aRagexeRE
+#if PACKETVER == 20140820
+ packetKeys(0x374f15d0,0x64c87dec,0x65ce2a41);
+#endif
+
+// 2014-08-27aRagexe, 2014-08-27aRagexeRE
+#if PACKETVER == 20140827
+ packetKeys(0x53814ca2,0x27de193e,0x503e683e);
+#endif
+
+// 2014-09-03aRagexe, 2014-09-03aRagexeRE
+#if PACKETVER == 20140903
+ packetKeys(0x2f386f34,0x0f935365,0x76a43888);
+#endif
+
+// 2014-09-17aRagexe, 2014-09-17cRagexeRE
+#if PACKETVER == 20140917
+ packetKeys(0x180118ea,0x440134cf,0x3a99179d);
+#endif
+
+// 2014-09-24bRagexeRE, 2014-09-24cRagexe, 2014-09-24cRagexeRE
+#if PACKETVER == 20140924
+ packetKeys(0x6f5222d8,0x593b798c,0x4cbd655e);
+#endif
+
+// 2014-10-01aRagexe, 2014-10-01bRagexeRE, 2014-10-01cRagexeRE
+#if PACKETVER == 20141001
+ packetKeys(0x6d882c11,0x7df959e2,0x4f3f60e8);
+#endif
+
+// 2014-10-08aRagexe, 2014-10-08bRagexe, 2014-10-08bRagexeRE, 2014-10-08cRagexe, 2014-10-08cRagexeRE, 2014-10-08dRagexe
+#if PACKETVER == 20141008
+ packetKeys(0x754365b3,0x36b326b3,0x26b326b3);
+#endif
+
+// 2014-10-15bRagexe, 2014-10-15bRagexeRE, 2014-10-15cRagexe, 2014-10-15dRagexe, 2014-10-16aRagexe, 2014-10-16aRagexeRE
+#if PACKETVER == 20141015 || \
+ PACKETVER == 20141016
+ packetKeys(0x2dff467c,0x444b37ee,0x2c1b634f);
+#endif
+
+// 2014-10-22aRagexeRE, 2014-10-22bRagexe
+#if PACKETVER == 20141022
+ packetKeys(0x290551ea,0x2b952c75,0x2d67669b);
+#endif
+
+// 2014-10-29aRagexe, 2014-10-29aRagexeRE
+#if PACKETVER == 20141029
+ packetKeys(0x1afd581d,0x2e1d4e1d,0x4e1d4e1d);
+#endif
+
+// 2014-11-05aRagexe, 2014-11-05aRagexeRE, 2014-11-05bRagexe, 2014-11-05bRagexeRE
+#if PACKETVER == 20141105
+ packetKeys(0x7f310819,0x5ff45401,0x2d303dd9);
+#endif
+
+// 2014-11-12aRagexeRE, 2014-11-12cRagexe, 2014-11-12dRagexe
+#if PACKETVER == 20141112
+ packetKeys(0x430c0c27,0x067153cf,0x5e5439a9);
+#endif
+
+// 2014-11-19bRagexeRE, 2014-11-19dRagexe
+#if PACKETVER == 20141119
+ packetKeys(0x7a7e7ede,0x24eb02e3,0x71603607);
+#endif
+
+// 2014-11-26aRagexe, 2014-11-26aRagexeRE, 2014-11-26bRagexe, 2014-11-26bRagexeRE, 2014-11-26cRagexe, 2014-11-26cRagexeRE, 2014-11-26dRagexe, 2014-11-26dRagexeRE, 2014-11-26eRagexeRE
+#if PACKETVER == 20141126
+ packetKeys(0x01e14c42,0x56d73044,0x4b3278df);
+#endif
+
+// 2014-12-03aRagexe, 2014-12-03aRagexeRE
+#if PACKETVER == 20141203
+ packetKeys(0x66cb52e4,0x1eb84093,0x33563e18);
+#endif
+
+// 2014-12-10bRagexe, 2014-12-10cRagexe, 2014-12-10cRagexeRE
+#if PACKETVER == 20141210
+ packetKeys(0x0b0b1dd3,0x26ef1797,0x4f40370b);
+#endif
+
+// 2014-12-17aRagexe, 2014-12-17aRagexeRE
+#if PACKETVER == 20141217
+ packetKeys(0x01ab478c,0x0fde58f2,0x1dac7303);
+#endif
+
+// 2014-12-23cRagexeRE, 2014-12-24aRagexe
+#if PACKETVER == 20141223 || \
+ PACKETVER == 20141224
+ packetKeys(0x2e8936e6,0x34463c46,0x67cd3885);
+#endif
+
+// 2014-12-31aRagexe, 2014-12-31aRagexeRE
+#if PACKETVER == 20141231
+ packetKeys(0x154c347e,0x54b26512,0x52126a12);
+#endif
+
+// 2015-01-07aRagexe, 2015-01-07aRagexeRE
+#if PACKETVER == 20150107
+ packetKeys(0x6c494a14,0x4ddb6427,0x3e6d7b65);
+#endif
+
+// 2015-01-14aRagexe, 2015-01-14aRagexeRE, 2015-01-14bRagexe, 2015-01-14cRagexe, 2015-01-14dRagexe
+#if PACKETVER == 20150114
+ packetKeys(0x21c96102,0x13142934,0x1abf4ea3);
+#endif
+
+// 2015-01-21aRagexe, 2015-01-21aRagexeRE, 2015-01-21bRagexeRE
+#if PACKETVER == 20150121
+ packetKeys(0x0b9d2af5,0x658a3346,0x379e3654);
+#endif
+
+// 2015-01-28aRagexe, 2015-01-28aRagexeRE, 2015-01-29aRagexe, 2015-01-30aRagexe
+#if PACKETVER == 20150128 || \
+ PACKETVER == 20150129 || \
+ PACKETVER == 20150130
+ packetKeys(0x77ca2d55,0x28b608f0,0x75b47957);
+#endif
+
+// 2015-02-04aRagexe, 2015-02-04cRagexeRE
+#if PACKETVER == 20150204
+ packetKeys(0x134529db,0x5b4f6cef,0x29ef11ef);
+#endif
+
+// 2015-02-11aRagexe, 2015-02-11aRagexeRE
+#if PACKETVER == 20150211
+ packetKeys(0x33911a25,0x1e6945fd,0x7385623a);
+#endif
+
+// 2015-02-17aRagexe, 2015-02-17aRagexeRE
+#if PACKETVER == 20150217
+ packetKeys(0x731b731b,0x731b731b,0x731b731b);
+#endif
+
+// 2015-02-25aRagexeRE, 2015-02-25bRagexeRE, 2015-02-25cRagexeRE, 2015-02-25dRagexeRE, 2015-02-25eRagexe, 2015-02-25eRagexeRE, 2015-02-25fRagexe, 2015-02-25gRagexe, 2015-02-25iRagexe, 2015-02-25jRagexe, 2015-02-26aRagexe, 2015-02-26aRagexeRE
+#if PACKETVER == 20150225 || \
+ PACKETVER == 20150226
+ packetKeys(0x57fd4b7b,0x19cc16fb,0x0d255d72);
+#endif
+
+// 2015-03-04aRagexe, 2015-03-04aRagexeRE, 2015-03-04bRagexeRE
+#if PACKETVER == 20150304
+ packetKeys(0x1a657b1c,0x7e1806e7,0x55396a5c);
+#endif
+
+// 2015-03-11aRagexe, 2015-03-11aRagexeRE, 2015-03-11bRagexe, 2015-03-11bRagexeRE
+#if PACKETVER == 20150311
+ packetKeys(0x48c45d97,0x06ce09b0,0x5836642f);
+#endif
+
+// 2015-03-18aRagexe, 2015-03-18aRagexeRE, 2015-03-18bRagexe, 2015-03-18bRagexeRE, 2015-03-18cRagexeRE
+#if PACKETVER == 20150318
+ packetKeys(0x1b3738e7,0x0ad4238f,0x7d252a1f);
+#endif
+
+// 2015-03-25aRagexe, 2015-03-25bRagexeRE, 2015-03-25cRagexeRE
+#if PACKETVER == 20150325
+ packetKeys(0x68f62b8c,0x337c3468,0x38fc0ac7);
+#endif
+
+// 2015-04-01aRagexe, 2015-04-01bRagexeRE
+#if PACKETVER == 20150401
+ packetKeys(0x207f3a08,0x57e6160c,0x02a60382);
+#endif
+
+// 2015-04-08aRagexe, 2015-04-08aRagexeRE
+#if PACKETVER == 20150408
+ packetKeys(0x39812c9d,0x23da516e,0x59a33dd2);
+#endif
+
+// 2015-04-15aRagexe, 2015-04-15aRagexeRE
+#if PACKETVER == 20150415
+ packetKeys(0x7ec44f6a,0x7de57139,0x60da5436);
+#endif
+
+// 2015-04-22aRagexe, 2015-04-22aRagexeRE
+#if PACKETVER == 20150422
+ packetKeys(0x10d22ce2,0x69e279e2,0x79e279e2);
+#endif
+
+// 2015-04-29aRagexe, 2015-04-29aRagexeRE
+#if PACKETVER == 20150429
+ packetKeys(0x2bf61a71,0x565d5ddf,0x0fb90019);
+#endif
+
+// 2015-05-07bRagexe, 2015-05-07bRagexeRE, 2015-05-07cRagexe
+#if PACKETVER == 20150507
+ packetKeys(0x55b54373,0x58967821,0x67f41832);
+#endif
+
+// 2015-05-13aRagexe, 2015-05-13aRagexeRE
+#if PACKETVER == 20150513
+ packetKeys(0x62c86d09,0x75944f17,0x112c133d);
+#endif
+
+// 2015-05-20aRagexe, 2015-05-20aRagexeRE
+#if PACKETVER == 20150520
+ packetKeys(0x17430238,0x44de585f,0x56a40616);
+#endif
+
+// 2015-05-27aRagexe, 2015-05-27aRagexeRE
+#if PACKETVER == 20150527
+ packetKeys(0x35ae7bae,0x3bae3bae,0x3bae3bae);
+#endif
+
+// 2015-06-03aRagexe, 2015-06-03bRagexeRE
+#if PACKETVER == 20150603
+ packetKeys(0x1ddd245d,0x309446e0,0x58e53f1f);
+#endif
+
+// 2015-06-10aRagexe, 2015-06-10aRagexeRE
+#if PACKETVER == 20150610
+ packetKeys(0x2fc406d3,0x7b3e32f5,0x02b80b47);
+#endif
+
+// 2015-06-17aRagexe, 2015-06-17aRagexeRE, 2015-06-18aRagexe, 2015-06-18aRagexeRE
+#if PACKETVER == 20150617 || \
+ PACKETVER == 20150618
+ packetKeys(0x250f7e09,0x25416076,0x029a780e);
+#endif
+
+// 2015-06-24aRagexe, 2015-06-24aRagexeRE
+#if PACKETVER == 20150624
+ packetKeys(0x440b0e24,0x1bea7a4c,0x2c646784);
+#endif
+
+// 2015-07-01bRagexe, 2015-07-01bRagexeRE, 2015-07-02aRagexe
+#if PACKETVER == 20150701 || \
+ PACKETVER == 20150702
+ packetKeys(0x4dd55f9b,0x70c67b03,0x78c60db6);
+#endif
+
+// 2015-07-08bRagexeRE, 2015-07-08cRagexe, 2015-07-08cRagexeRE, 2015-07-08dRagexeRE
+#if PACKETVER == 20150708
+ packetKeys(0x451c5e19,0x5661750b,0x2f4644ac);
+#endif
+
+// 2015-07-15aRagexe, 2015-07-15aRagexeRE
+#if PACKETVER == 20150715
+ packetKeys(0x1f805483,0x67745585,0x7fce189c);
+#endif
+
+// 2015-07-22bRagexe, 2015-07-22bRagexeRE
+#if PACKETVER == 20150722
+ packetKeys(0x41fa53d4,0x2cf044e2,0x663a3f1d);
+#endif
+
+// 2015-07-29aRagexe, 2015-07-29aRagexeRE
+#if PACKETVER == 20150729
+ packetKeys(0x08ee40a9,0x206f3d7f,0x0ae37339);
+#endif
+
+// 2015-08-05aRagexe, 2015-08-05dRagexeRE
+#if PACKETVER == 20150805
+ packetKeys(0x1c3f243f,0x243f243f,0x243f243f);
+#endif
+
+// 2015-08-12aRagexe, 2015-08-12aRagexeRE
+#if PACKETVER == 20150812
+ packetKeys(0x0b6f64a8,0x5bcc47ec,0x00ec08ec);
+#endif
+
+// 2015-08-19aRagexe, 2015-08-19aRagexeRE, 2015-08-19bRagexeRE
+#if PACKETVER == 20150819
+ packetKeys(0x1a2400e0,0x736e5686,0x10f315d5);
+#endif
+
+// 2015-08-26aRagexe, 2015-08-26aRagexeRE, 2015-08-26bRagexe, 2015-08-26bRagexeRE
+#if PACKETVER == 20150826
+ packetKeys(0x77883c56,0x1829359f,0x0de635b6);
+#endif
+
+// 2015-09-02aRagexe, 2015-09-02aRagexeRE
+#if PACKETVER == 20150902
+ packetKeys(0x4edb18c1,0x6b9355ba,0x38aa6239);
+#endif
+
+// 2015-09-09aRagexe, 2015-09-09aRagexeRE
+#if PACKETVER == 20150909
+ packetKeys(0x19ab2bf0,0x04754299,0x48770736);
+#endif
+
+// 2015-09-16aRagexe, 2015-09-16cRagexe, 2015-09-16cRagexeRE
+#if PACKETVER == 20150916
+ packetKeys(0x17f83a19,0x116944f4,0x1cc541e9);
+#endif
+
+// 2015-09-23bRagexe, 2015-09-23bRagexeRE, 2015-09-23cRagexe, 2015-09-23dRagexe, 2015-09-23eRagexe, 2015-09-23eRagexeRE, 2015-09-23fRagexe, 2015-09-23fRagexeRE
+#if PACKETVER == 20150923
+ packetKeys(0x765742b9,0x22d61c2f,0x7da94fb2);
+#endif
+
+// 2015-10-01aRagexe, 2015-10-01bRagexeRE
+#if PACKETVER == 20151001
+ packetKeys(0x5cff4561,0x32514ad1,0x06d126d1);
+#endif
+
+// 2015-10-07aRagexe, 2015-10-07aRagexeRE
+#if PACKETVER == 20151007
+ packetKeys(0x3c6447a8,0x032170d7,0x6490476c);
+#endif
+
+// 2015-10-14bRagexe, 2015-10-14bRagexeRE
+#if PACKETVER == 20151014
+ packetKeys(0x402728a8,0x5d0e309f,0x240018fd);
+#endif
+
+// 2015-10-21aRagexe, 2015-10-21aRagexeRE, 2015-10-22aRagexe, 2015-10-22aRagexeRE
+#if PACKETVER == 20151021 || \
+ PACKETVER == 20151022
+ packetKeys(0x0311104d,0x46c326d6,0x00e82720);
+#endif
+
+// 2015-10-28bRagexeRE, 2015-10-28bRagexeRE_2, 2015-10-28cRagexe, 2015-10-28cRagexeRE, 2015-10-28dRagexe, 2015-10-28dRagexeRE, 2015-10-29aRagexe, 2015-10-29aRagexeRE
+#if PACKETVER == 20151028 || \
+ PACKETVER == 20151029
+ packetKeys(0x45b945b9,0x45b945b9,0x45b945b9);
+#endif
+
+// 2015-11-04aRagexe, 2015-11-04aRagexeRE
+#if PACKETVER == 20151104
+ packetKeys(0x4c17382a,0x7ed174c9,0x29961e4f);
+#endif
+
+// 2015-11-11aRagexe, 2015-11-11aRagexeRE, 2015-11-11bRagexe
+#if PACKETVER == 20151111
+ packetKeys(0x46097c77,0x5f193871,0x29140a21);
+#endif
+
+// 2015-11-18aRagexe, 2015-11-18aRagexeRE
+#if PACKETVER == 20151118
+ packetKeys(0x734c3241,0x6e846f34,0x731c06d6);
+#endif
+
+// 2015-11-25bRagexe, 2015-11-25bRagexeRE, 2015-11-25cRagexeRE, 2015-11-25dRagexe, 2015-11-25dRagexeRE
+#if PACKETVER == 20151125
+ packetKeys(0x237446c0,0x5efb343a,0x0edf06c5);
+#endif
+
+// 2015-12-02aRagexe, 2015-12-02bRagexeRE
+#if PACKETVER == 20151202
+ packetKeys(0x4ede52de,0x52de52de,0x52de52de);
+#endif
+
+// 2015-12-09aRagexe, 2015-12-09aRagexeRE
+#if PACKETVER == 20151209
+ packetKeys(0x652c5898,0x7a351fb3,0x67ea2886);
+#endif
+
+// 2015-12-16aRagexe, 2015-12-16aRagexeRE
+#if PACKETVER == 20151216
+ packetKeys(0x25dd643d,0x61ac39de,0x77a8206d);
+#endif
+
+// 2015-12-23bRagexe, 2015-12-23bRagexeRE
+#if PACKETVER == 20151223
+ packetKeys(0x347d68d0,0x2c705320,0x7b4a199d);
+#endif
+
+// 2015-12-30aRagexe, 2015-12-30aRagexeRE
+#if PACKETVER == 20151230
+ packetKeys(0x54c51241,0x33883499,0x3cda35f0);
+#endif
+
+// 2016-01-06aRagexe, 2016-01-06aRagexeRE
+#if PACKETVER == 20160106
+ packetKeys(0x40520265,0x33fe26fc,0x7136294f);
+#endif
+
+// 2016-01-13aRagexe, 2016-01-13aRagexeRE, 2016-01-13bRagexe, 2016-01-13bRagexeRE, 2016-01-13bRagexeRE_2, 2016-01-13bRagexe_2, 2016-01-13cRagexeRE
+#if PACKETVER == 20160113
+ packetKeys(0x18005c4b,0x19a94a72,0x73f678ec);
+#endif
+
+// 2016-01-20aRagexe, 2016-01-20aRagexeRE
+#if PACKETVER == 20160120
+ packetKeys(0x51495149,0x51495149,0x51495149);
+#endif
+
+// 2016-01-27aRagexeRE, 2016-01-27aRagexeRE_2, 2016-01-27bRagexeRE, 2016-01-27cRagexe, 2016-01-27dRagexe
+#if PACKETVER == 20160127
+ packetKeys(0x6b1e7146,0x612c47e6,0x274e56ee);
+#endif
+
+// 2016-02-03aRagexe, 2016-02-03aRagexeRE
+#if PACKETVER == 20160203
+ packetKeys(0x3e1411af,0x6c744497,0x7cfa1bde);
+#endif
+
+// 2016-02-11aRagexe, 2016-02-11aRagexeRE
+#if PACKETVER == 20160211
+ packetKeys(0x613813ea,0x05251dab,0x1fd35e33);
+#endif
+
+// 2016-02-17aRagexe, 2016-02-17aRagexeRE, 2016-02-17bRagexeRE, 2016-02-17bRagexeRE_2, 2016-02-17cRagexeRE
+#if PACKETVER == 20160217
+ packetKeys(0x25895a8e,0x09421c19,0x763a2d7a);
+#endif
+
+// 2016-02-24aRagexe, 2016-02-24aRagexeRE, 2016-02-24bRagexeRE
+#if PACKETVER == 20160224
+ packetKeys(0x7088019a,0x13471f02,0x42356a7d);
+#endif
+
+// 2016-03-02bRagexe, 2016-03-02bRagexeRE
+#if PACKETVER == 20160302
+ packetKeys(0x7b4441b9,0x5bbc63af,0x45da0e71);
+#endif
+
+// 2016-03-09aRagexeRE, 2016-03-09cRagexe
+#if PACKETVER == 20160309
+ packetKeys(0x21587520,0x353a7706,0x1b722b25);
+#endif
+
+// 2016-03-16aRagexe, 2016-03-16aRagexeRE, 2016-03-18aRagexe
+#if PACKETVER == 20160316 || \
+ PACKETVER == 20160318
+ packetKeys(0x62363e36,0x3e363e36,0x3e363e36);
+#endif
+
+// 2016-03-23aRagexe, 2016-03-23aRagexeRE, 2016-03-23bRagexe, 2016-03-23bRagexeRE
+#if PACKETVER == 20160323
+ packetKeys(0x73e35a83,0x62142fa8,0x12ba36bd);
+#endif
+
+// 2016-03-30aRagexe, 2016-03-30aRagexeRE, 2016-03-30bRagexe
+#if PACKETVER == 20160330
+ packetKeys(0x02050940,0x545336ff,0x7e7d4902);
+#endif
+
+// 2016-04-06aRagexe, 2016-04-06aRagexeRE, 2016-04-06bRagexe
+#if PACKETVER == 20160406
+ packetKeys(0x568611ea,0x32457d8d,0x2b020477);
+#endif
+
+// 2016-04-14aRagexe, 2016-04-14aRagexeRE, 2016-04-14bRagexe, 2016-04-14bRagexeRE, 2016-04-14bRagexe_2, 2016-04-14cRagexe
+#if PACKETVER == 20160414
+ packetKeys(0x31bd479a,0x40c61398,0x397c1a80);
+#endif
+
+// 2016-04-20aRagexeRE, 2016-04-20cRagexe
+#if PACKETVER == 20160420
+ packetKeys(0x67d2163a,0x3068215b,0x4835474d);
+#endif
+
+// 2016-04-27aRagexe, 2016-04-27aRagexeRE
+#if PACKETVER == 20160427
+ packetKeys(0x12dc378e,0x4e3e7ebe,0x0abe2abe);
+#endif
+
+// 2016-05-04aRagexe, 2016-05-04aRagexeRE
+#if PACKETVER == 20160504
+ packetKeys(0x09e0544c,0x0231251d,0x2f4e195f);
+#endif
+
+// 2016-05-11aRagexe, 2016-05-11aRagexeRE, 2016-05-11bRagexeRE
+#if PACKETVER == 20160511
+ packetKeys(0x3c666fe2,0x27e84e3e,0x53e11ba5);
+#endif
+
+// 2016-05-18aRagexe, 2016-05-18aRagexeRE
+#if PACKETVER == 20160518
+ packetKeys(0x57db7ca1,0x1fea1629,0x26dd244d);
+#endif
+
+// 2016-05-25aRagexe, 2016-05-25aRagexeRE, 2016-05-26aRagexe
+#if PACKETVER == 20160525 || \
+ PACKETVER == 20160526
+ packetKeys(0x485c45b6,0x47dc6192,0x76b34a36);
+#endif
+
+// 2016-06-01aRagexe, 2016-06-01aRagexeRE
+#if PACKETVER == 20160601
+ packetKeys(0x3dad32c4,0x59f001be,0x73f65e56);
+#endif
+
+// 2016-06-08aRagexe, 2016-06-08aRagexeRE, 2016-06-08bRagexe, 2016-06-08bRagexeRE, 2016-06-09aRagexe
+#if PACKETVER == 20160608 || \
+ PACKETVER == 20160609
+ packetKeys(0x11d74609,0x77c43e8a,0x44290f53);
+#endif
+
+// 2016-06-15aRagexe, 2016-06-15aRagexeRE
+#if PACKETVER == 20160615
+ packetKeys(0x062c5c26,0x6cf47e82,0x4dd53480);
+#endif
+
+// 2016-06-22aRagexe, 2016-06-22aRagexeRE
+#if PACKETVER == 20160622
+ packetKeys(0x426548ab,0x5c0f5dd4,0x03022710);
+#endif
+
+// 2016-06-29aRagexe, 2016-06-29aRagexeRE, 2016-06-30aRagexe, 2016-06-30aRagexeRE
+#if PACKETVER == 20160629 || \
+ PACKETVER == 20160630
+ packetKeys(0x0df31ccc,0x54281606,0x5c4c6855);
+#endif
+
+// 2016-07-06bRagexe, 2016-07-06cRagexeRE
+#if PACKETVER == 20160706
+ packetKeys(0x33a766d0,0x743f04f8,0x0fa0276c);
+#endif
+
+// 2016-07-13aRagexe, 2016-07-13aRagexeRE, 2016-07-13bRagexe, 2016-07-13bRagexeRE, 2016-07-13cRagexe, 2016-07-13dRagexe
+#if PACKETVER == 20160713
+ packetKeys(0x714f2495,0x7ddc6f32,0x3fd8533d);
+#endif
+
+// 2016-07-20aRagexe, 2016-07-20aRagexeRE, 2016-07-20bRagexe, 2016-07-20bRagexeRE
+#if PACKETVER == 20160720
+ packetKeys(0x4f8a19c0,0x2d8e085c,0x37bb67d6);
+#endif
+
+// 2016-07-27aRagexe, 2016-07-27aRagexeRE, 2016-07-27bRagexe, 2016-07-27bRagexeRE
+#if PACKETVER == 20160727
+ packetKeys(0x3c6952ab,0x26e4077f,0x37e25df7);
+#endif
+
+// 2016-08-03bRagexe, 2016-08-03bRagexeRE
+#if PACKETVER == 20160803
+ packetKeys(0x67f438c2,0x512a4eb7,0x2d353182);
+#endif
+
+// 2016-08-10aRagexe, 2016-08-10aRagexeRE
+#if PACKETVER == 20160810
+ packetKeys(0x2f252886,0x242234a2,0x48bc5032);
+#endif
+
+// 2016-08-17aRagexe, 2016-08-17aRagexeRE
+#if PACKETVER == 20160817
+ packetKeys(0x675e6900,0x3f8e1d16,0x58d650e5);
+#endif
+
+// 2016-08-24aRagexe, 2016-08-24aRagexeRE
+#if PACKETVER == 20160824
+ packetKeys(0x2fa92fa9,0x2fa92fa9,0x2fa92fa9);
+#endif
+
+// 2016-08-31aRagexe, 2016-08-31aRagexeRE, 2016-08-31bRagexe, 2016-08-31bRagexeRE
+#if PACKETVER == 20160831
+ packetKeys(0x564e13b0,0x7f680549,0x382d273b);
+#endif
+
+// 2016-09-07aRagexe, 2016-09-07aRagexeRE
+#if PACKETVER == 20160907
+ packetKeys(0x32e5237d,0x57bd4dbd,0x5dbd5dbd);
+#endif
+
+// 2016-09-13aRagexe, 2016-09-13aRagexeRE
+#if PACKETVER == 20160913
+ packetKeys(0x7c79748f,0x1aa03b1d,0x6eac4747);
+#endif
+
+// 2016-09-21aRagexe, 2016-09-21bRagexeRE
+#if PACKETVER == 20160921
+ packetKeys(0x11cd15cd,0x15cd15cd,0x15cd15cd);
+#endif
+
+// 2016-09-28cRagexe, 2016-09-28cRagexeRE, 2016-09-28dRagexeRE
+#if PACKETVER == 20160928
+ packetKeys(0x2f8c67f5,0x22d42c38,0x57513774);
+#endif
+
+// 2016-10-05aRagexe, 2016-10-05aRagexeRE
+#if PACKETVER == 20161005
+ packetKeys(0x5bae21f8,0x021e2ffc,0x3beb7c31);
+#endif
+
+// 2016-10-12aRagexe, 2016-10-12aRagexeRE
+#if PACKETVER == 20161012
+ packetKeys(0x5e2311f2,0x14fd012c,0x76eb64f6);
+#endif
+
+// 2016-10-19aRagexe, 2016-10-19aRagexeRE
+#if PACKETVER == 20161019
+ packetKeys(0x34882f11,0x7c870e70,0x7e61350d);
+#endif
+
+// 2016-10-26bRagexe, 2016-10-26bRagexeRE, 2016-10-26cRagexe, 2016-10-26cRagexeRE
+#if PACKETVER == 20161026
+ packetKeys(0x2cb86ae6,0x7d12660e,0x1b004deb);
+#endif
+
+// 2016-11-02aRagexe, 2016-11-02aRagexeRE, 2016-11-03aRagexe, 2016-11-03aRagexeRE
+#if PACKETVER == 20161102 || \
+ PACKETVER == 20161103
+ packetKeys(0x76725c17,0x72fe4ec1,0x07a91bfd);
+#endif
+
+// 2016-11-09aRagexe, 2016-11-09aRagexeRE, 2016-11-09bRagexe, 2016-11-09bRagexeRE, 2016-11-09cRagexeRE, 2016-11-09dRagexeRE
+#if PACKETVER == 20161109
+ packetKeys(0x0a5277c0,0x2db17506,0x0e8f26da);
+#endif
+
+// 2016-11-16aRagexe, 2016-11-16bRagexeRE, 2016-11-16cRagexeRE
+#if PACKETVER == 20161116
+ packetKeys(0x780c5c3f,0x15e92272,0x2ba770c5);
+#endif
+
+// 2016-11-23aRagexe, 2016-11-23aRagexeRE
+#if PACKETVER == 20161123
+ packetKeys(0x66ff559f,0x00d3535b,0x236246f7);
+#endif
+
+// 2016-11-30aRagexe, 2016-11-30aRagexeRE, 2016-11-30bRagexe, 2016-11-30bRagexeRE
+#if PACKETVER == 20161130
+ packetKeys(0x2ed80296,0x0d837373,0x20266f9a);
+#endif
+
+// 2016-12-07cRagexe, 2016-12-07cRagexeRE, 2016-12-07dRagexeRE, 2016-12-07eRagexe, 2016-12-07eRagexeRE
+#if PACKETVER == 20161207
+ packetKeys(0x52d267aa,0x4fe42156,0x1292153e);
+#endif
+
+// 2016-12-14bRagexe, 2016-12-14bRagexeRE, 2016-12-14cRagexe, 2016-12-14cRagexeRE
+#if PACKETVER == 20161214
+ packetKeys(0x4dde217b,0x07863ae0,0x5b591656);
+#endif
+
+// 2016-12-21aRagexe, 2016-12-21aRagexeRE, 2016-12-21bRagexe, 2016-12-21bRagexeRE, 2016-12-21cRagexeRE, 2016-12-21dRagexeRE
+#if PACKETVER == 20161221
+ packetKeys(0x69cb4f56,0x793c165e,0x673a2354);
+#endif
+
+// 2016-12-28aRagexe, 2016-12-28aRagexeRE
+#if PACKETVER == 20161228
+ packetKeys(0x09366971,0x005672f1,0x6f3712ae);
+#endif
+
+// 2017-01-04aRagexe, 2017-01-04bRagexeRE
+#if PACKETVER == 20170104
+ packetKeys(0x44416bc3,0x6c8d1817,0x072d75d5);
+#endif
+
+// 2017-01-11aRagexe, 2017-01-11aRagexeRE
+#if PACKETVER == 20170111
+ packetKeys(0x19b637f9,0x0e9c378a,0x41673186);
+#endif
+
+// 2017-01-18aRagexe, 2017-01-18aRagexeRE
+#if PACKETVER == 20170118
+ packetKeys(0x456b36eb,0x15eb34b0,0x18c42e43);
+#endif
+
+// 2017-01-25aRagexe, 2017-01-25aRagexeRE
+#if PACKETVER == 20170125
+ packetKeys(0x066e04fe,0x3004224a,0x04ff0458);
+#endif
+
+// 2017-02-01aRagexe, 2017-02-01aRagexeRE
+#if PACKETVER == 20170201
+ packetKeys(0x2011228e,0x00453005,0x628e7f0a);
+#endif
+
+// 2017-02-08aRagexeRE, 2017-02-08bRagexe, 2017-02-08bRagexeRE
+#if PACKETVER == 20170208
+ packetKeys(0x6a764e5f,0x0609570d,0x28ae07fa);
+#endif
+
+// 2017-02-15aRagexe, 2017-02-15aRagexeRE
+#if PACKETVER == 20170215
+ packetKeys(0x50c01315,0x51012a42,0x679e16c3);
+#endif
+
+// 2017-02-22aRagexe, 2017-02-22aRagexeRE
+#if PACKETVER == 20170222
+ packetKeys(0x5a242f2f,0x6c556187,0x73c022cb);
+#endif
+
+// 2017-02-28aRagexe, 2017-02-28aRagexeRE, 2017-02-28bRagexe
+#if PACKETVER == 20170228
+ packetKeys(0x771d4f2b,0x20ef1f4c,0x0d5135c8);
+#endif
+
+// 2017-03-08aRagexe, 2017-03-08bRagexeRE
+#if PACKETVER == 20170308
+ packetKeys(0x653470a9,0x6b316a71,0x5c712c71);
+#endif
+
+// 2017-03-15cRagexe, 2017-03-15cRagexeRE
+#if PACKETVER == 20170315
+ packetKeys(0x399a0856,0x56642a94,0x7f77157d);
+#endif
+
+// 2017-03-22aRagexe, 2017-03-22aRagexeRE, 2017-03-22bRagexe, 2017-03-22bRagexeRE
+#if PACKETVER == 20170322
+ packetKeys(0x2050167b,0x01731233,0x40337033);
+#endif
+
+// 2017-03-29bRagexe, 2017-03-29cRagexe, 2017-03-29cRagexeRE, 2017-03-29dRagexeRE
+#if PACKETVER == 20170329
+ packetKeys(0x18b31a80,0x1b0b1d56,0x16857d6a);
+#endif
+
+// 2017-04-05bRagexe, 2017-04-05bRagexeRE, 2017-04-05cRagexe, 2017-04-05cRagexeRE
+#if PACKETVER == 20170405
+ packetKeys(0x1fde7dac,0x2f9f5b63,0x3f2062af);
+#endif
+
+// 2017-04-12aRagexe, 2017-04-12aRagexeRE
+#if PACKETVER == 20170412
+ packetKeys(0x39223393,0x5c847779,0x10217985);
+#endif
+
+// 2017-04-19aRagexe, 2017-04-19bRagexeRE
+#if PACKETVER == 20170419
+ packetKeys(0x1f8f4b3f,0x2e481f03,0x39ed4178);
+#endif
+
+// 2017-04-26bRagexe, 2017-04-26dRagexeRE
+#if PACKETVER == 20170426
+ packetKeys(0x167642a7,0x1dec3d26,0x6d046d4c);
+#endif
+
+// 2017-05-02aRagexe, 2017-05-02bRagexe, 2017-05-02dRagexeRE
+#if PACKETVER == 20170502
+ packetKeys(0x05224194,0x466d4204,0x31f02ee0);
+#endif
+
+// 2017-05-17aRagexe, 2017-05-17aRagexeRE, 2017-05-17bRagexeRE
+#if PACKETVER == 20170517
+ packetKeys(0x2cc4749a,0x1fa954dc,0x72276857);
+#endif
+
+// 2017-05-24aRagexe, 2017-05-24aRagexeRE, 2017-05-24bRagexe
+#if PACKETVER == 20170524
+ packetKeys(0x0b4e03a6,0x2b93427c,0x583d4477);
+#endif
+
+// 2017-05-31aRagexe, 2017-05-31aRagexeRE
+#if PACKETVER == 20170531
+ packetKeys(0x03fa5a97,0x20b802d5,0x339f1977);
+#endif
+
+// 2017-06-07bRagexeRE, 2017-06-07cRagexe, 2017-06-07cRagexeRE
+#if PACKETVER == 20170607
+ packetKeys(0x50564acd,0x79ca4e15,0x405f4894);
+#endif
+
+// 2017-06-14bRagexe, 2017-06-14bRagexeRE
+#if PACKETVER == 20170614
+ packetKeys(0x5ed10a48,0x667f4301,0x2e5d761f);
+#endif
+
+// 2017-06-21aRagexeRE, 2017-06-21bRagexe
+#if PACKETVER == 20170621
+ packetKeys(0x155f34ec,0x2d943fa9,0x3d9170eb);
+#endif
+
+// 2017-06-28bRagexe, 2017-06-28bRagexeRE
+#if PACKETVER == 20170628
+ packetKeys(0x04691c86,0x43c210e2,0x2fe277e2);
+#endif
+
+// 2017-07-05aRagexe, 2017-07-05aRagexeRE
+#if PACKETVER == 20170705
+ packetKeys(0x7eb000ae,0x02fb1dbc,0x5cb131e6);
+#endif
+
+// 2017-07-12bRagexe, 2017-07-12bRagexeRE
+#if PACKETVER == 20170712
+ packetKeys(0x2c3c202c,0x3f2c2f2c,0x2f2c2f2c);
+#endif
+
+// 2017-07-19aRagexe, 2017-07-19aRagexeRE
+#if PACKETVER == 20170719
+ packetKeys(0x46465c88,0x10116f66,0x200866f9);
+#endif
+
+// 2017-07-26aRagexe, 2017-07-26cRagexeRE
+#if PACKETVER == 20170726
+ packetKeys(0x102f23db,0x7e767751,0x3bc172ef);
+#endif
+
+// 2017-08-01aRagexe, 2017-08-01aRagexeRE, 2017-08-01bRagexe
+#if PACKETVER == 20170801
+ packetKeys(0x26b52a7f,0x5377619d,0x4f580ac4);
+#endif
+
+// 2017-08-09cRagexe, 2017-08-09cRagexeRE
+#if PACKETVER == 20170809
+ packetKeys(0x452156cb,0x71442624,0x2ee66d1c);
+#endif
+
+// 2017-08-16cRagexe, 2017-08-16cRagexeRE, 2017-08-16dRagexe, 2017-08-16dRagexeRE
+#if PACKETVER == 20170816
+ packetKeys(0x78914673,0x3f8b7634,0x55b814bc);
+#endif
+
+// 2017-08-23aRagexe, 2017-08-23aRagexeRE
+#if PACKETVER == 20170823
+ packetKeys(0x22677205,0x393d1002,0x58dc6bb4);
+#endif
+
+// 2017-08-30aRagexe, 2017-08-30aRagexeRE, 2017-08-30bRagexe, 2017-08-30bRagexeRE
+#if PACKETVER == 20170830
+ packetKeys(0x1d49592b,0x00970c17,0x1e640103);
+#endif
+
+// 2017-09-06cRagexe, 2017-09-06cRagexeRE
+#if PACKETVER == 20170906
+ packetKeys(0x7def7677,0x351f36e6,0x52303485);
+#endif
+
+// 2017-09-13bRagexeRE, 2017-09-13cRagexe
+#if PACKETVER == 20170913
+ packetKeys(0x7a645935,0x1da05062,0x5a7a4c43);
+#endif
+
+// 2017-09-20aRagexe, 2017-09-20bRagexeRE
+#if PACKETVER == 20170920
+ packetKeys(0x53024da5,0x04ec212d,0x0bf87cd4);
+#endif
+
+// 2017-09-27bRagexe, 2017-09-27bRagexeRE, 2017-09-27cRagexe, 2017-09-27dRagexe, 2017-09-27dRagexeRE
+#if PACKETVER == 20170927
+ packetKeys(0x15624100,0x0ce1463e,0x0e5d6534);
+#endif
+
+// 2017-10-02cRagexe, 2017-10-02cRagexeRE
+#if PACKETVER == 20171002
+ packetKeys(0x15e1716c,0x4e765b63,0x357d2370);
+#endif
+
+// 2017-10-11aRagexe, 2017-10-11aRagexeRE, 2017-10-11bRagexe, 2017-10-11bRagexeRE
+#if PACKETVER == 20171011
+ packetKeys(0x4f121b3e,0x12670e17,0x19896c11);
+#endif
+
+// 2017-10-18aRagexe, 2017-10-18aRagexeRE
+#if PACKETVER == 20171018
+ packetKeys(0x2caa109c,0x158c1ec2,0x7a5e58f3);
+#endif
+
+// 2017-10-25bRagexe, 2017-10-25bRagexeRE, 2017-10-25cRagexe, 2017-10-25cRagexeRE, 2017-10-25dRagexe, 2017-10-25dRagexeRE, 2017-10-25eRagexe, 2017-10-25eRagexeRE
+#if PACKETVER == 20171025
+ packetKeys(0x165c565c,0x565c565c,0x565c565c);
+#endif
+
+// 2017-11-01aRagexe, 2017-11-01bRagexeRE
+#if PACKETVER == 20171101
+ packetKeys(0x7056317f,0x7eee0589,0x02672373);
+#endif
+
+// 2017-11-08aRagexe, 2017-11-08bRagexeRE
+#if PACKETVER == 20171108
+ packetKeys(0x03695685,0x7fac12ce,0x182f7a7b);
+#endif
+
+// 2017-11-15aRagexe, 2017-11-15aRagexeRE
+#if PACKETVER == 20171115
+ packetKeys(0x23b97a3b,0x34610993,0x2892070e);
+#endif
+
+// 2017-11-22aRagexe, 2017-11-22bRagexeRE
+#if PACKETVER == 20171122
+ packetKeys(0x03221b0e,0x73ab7a5f,0x0dd80fd4);
+#endif
+
+// 2017-11-29aRagexe, 2017-11-29aRagexeRE
+#if PACKETVER == 20171129
+ packetKeys(0x581b77a7,0x62f74d7a,0x4f102173);
+#endif
+
+// 2017-12-06aRagexeRE, 2017-12-06bRagexe, 2017-12-06cRagexe
+#if PACKETVER == 20171206
+ packetKeys(0x39d54bd3,0x577a0c21,0x4c1c316e);
+#endif
+
+// 2017-12-13bRagexe, 2017-12-13bRagexeRE
+#if PACKETVER == 20171213
+ packetKeys(0x44e41107,0x3b126921,0x00e06aac);
+#endif
+
+// 2017-12-20aRagexe, 2017-12-20aRagexeRE
+#if PACKETVER == 20171220
+ packetKeys(0x6efe009a,0x440b7bfa,0x052339c8);
+#endif
+
+// 2017-12-27aRagexe, 2017-12-27aRagexeRE
+#if PACKETVER == 20171227
+ packetKeys(0x257a2f6e,0x51140eee,0x00fa4452);
+#endif
+
+// 2018-01-03aRagexe, 2018-01-03aRagexeRE, 2018-01-03bRagexe, 2018-01-03bRagexeRE
+#if PACKETVER == 20180103
+ packetKeys(0x348f4bd7,0x7a425a54,0x628f589a);
+#endif
+
+// 2018-01-17aRagexe, 2018-01-17aRagexeRE
+#if PACKETVER == 20180117
+ packetKeys(0x21f477f4,0x37f437f4,0x37f437f4);
+#endif
+
+// 2018-01-24bRagexe, 2018-01-24bRagexeRE, 2018-01-31Ragexe
+#if PACKETVER == 20180124 || \
+ PACKETVER == 20180131
+ packetKeys(0x7eaa1ce0,0x415d1cfd,0x4c8f19fa);
+#endif
+
+// 2018-02-07bRagexe, 2018-02-07bRagexeRE, 2018-02-07cRagexe
+#if PACKETVER == 20180207
+ packetKeys(0x45aa1b44,0x20e716b7,0x5388105c);
+#endif
+
+// 2018-02-13aRagexe, 2018-02-13aRagexeRE, 2018-02-13bRagexe
+#if PACKETVER == 20180213
+ packetKeys(0x189d69b2,0x43b85ead,0x2b7a687e);
+#endif
+
+// 2018-02-21aRagexeRE, 2018-02-21bRagexe, 2018-02-21bRagexeRE
+#if PACKETVER == 20180221
+ packetKeys(0x6e2f6233,0x193b0a66,0x0d1d2ca5);
+#endif
+
+// 2018-03-07bRagexe, 2018-03-07bRagexeRE, 2018-03-09aRagexe
+#if PACKETVER == 20180307 || \
+ PACKETVER == 20180309
+ packetKeys(0x47da10eb,0x4b922ccf,0x765c5055);
+#endif
+
+// 2018-03-14nRagexe
+#if PACKETVER == 20180314
+ packetKeys(0x2ff07149,0x00596ea3,0x2b853026);
+#endif
+
+
+#endif /* MAP_PACKETS_MAIN_KEYS_H */
diff --git a/src/map/packets_keys_zero.h b/src/map/packets_keys_zero.h
new file mode 100644
index 000000000..904159d37
--- /dev/null
+++ b/src/map/packets_keys_zero.h
@@ -0,0 +1,228 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MAP_PACKETS_ZERO_KEYS_H
+#define MAP_PACKETS_ZERO_KEYS_H
+
+#ifndef packetKeys
+ #define packetKeys(a,b,c)
+#endif
+
+/* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */
+
+/* This file is autogenerated, please do not commit manual changes */
+
+// 2017-10-18aRagexe_zero, 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero, 2018-04-11aRagexe_zero, 2018-04-25_3aRagexe_zero, 2018-05-09_3aRagexe_zero, 2018-05-23aRagexe_zero, 2018-06-05bRagexe_zero, 2018-06-05cRagexe_zero, 2018-06-27aRagexe_zero, 2018-07-03aRagexe_zero, 2018-07-11_2aRagexe_zero, 2018-07-25_2aRagexe_zero, 2018-08-01aRagexe_zero, 2018-08-08_2aRagexe_zero, 2018-08-22aRagexe_zero, 2018-08-29aRagexe_zero, 2018-09-05aRagexe_zero, 2018-09-12aRagexe_zero, 2018-09-19aRagexe_zero, 2018-09-28aRagexe_zero, 2018-10-10_2aRagexe_zero, 2018-10-24_2aRagexe_zero, 2018-11-14aRagexe_zero, 2018-11-20aRagexe_zero, 2018-11-28aRagexe_zero, 2018-12-12aRagexe_zero, 2018-12-19aRagexe_zero, 2018-12-26_2aRagexe_zero, 2019-01-16_2aRagexe_zero, 2019-01-17_1aRagexe_zero, 2019-01-30_2aRagexe_zero, 2019-02-13aRagexe_zero, 2019-02-20aRagexe_zero, 2019-02-27aRagexe_zero, 2019-03-13aRagexe_zero, 2019-03-27_2aRagexe_zero, 2019-03-27_3aRagexe_zero, 2019-04-03aRagexe_zero, 2019-04-10bRagexe_zero, 2019-04-24aRagexe_zero, 2019-05-02aRagexe_zero, 2019-05-08_2aRagexe_zero, 2019-05-08aRagexe_zero, 2019-05-15aRagexe_zero, 2019-05-29aRagexe_zero, 2019-05-30aRagexe_zero, 2019-06-05_2aRagexe_zero, 2019-06-26_2aRagexe_zero, 2019-06-26_3aRagexe_zero, 2019-07-09aRagexe_zero, 2019-07-10_3aRagexe_zero, 2019-07-17aRagexe_zero, 2019-07-24aRagexe_zero, 2019-08-14_3aRagexe_zero, 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero, 2020-02-12aRagexe_zero, 2020-02-26aRagexe_zero, 2020-02-26bRagexe_zero, 2020-03-04aRagexe_zero, 2020-03-18_2aRagexe_zero, 2020-04-01_2aRagexe_zero, 2020-04-14bRagexe_zero
+#if PACKETVER == 20171018 || \
+ PACKETVER == 20171019 || \
+ PACKETVER == 20171023 || \
+ PACKETVER == 20171024 || \
+ PACKETVER == 20171025 || \
+ PACKETVER == 20171027 || \
+ PACKETVER == 20171030 || \
+ PACKETVER == 20171031 || \
+ PACKETVER == 20171109 || \
+ PACKETVER == 20171113 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER == 20180411 || \
+ PACKETVER == 20180425 || \
+ PACKETVER == 20180509 || \
+ PACKETVER == 20180523 || \
+ PACKETVER == 20180605 || \
+ PACKETVER == 20180627 || \
+ PACKETVER == 20180703 || \
+ PACKETVER == 20180711 || \
+ PACKETVER == 20180725 || \
+ PACKETVER == 20180801 || \
+ PACKETVER == 20180808 || \
+ PACKETVER == 20180822 || \
+ PACKETVER == 20180829 || \
+ PACKETVER == 20180905 || \
+ PACKETVER == 20180912 || \
+ PACKETVER == 20180919 || \
+ PACKETVER == 20180928 || \
+ PACKETVER == 20181010 || \
+ PACKETVER == 20181024 || \
+ PACKETVER == 20181114 || \
+ PACKETVER == 20181120 || \
+ PACKETVER == 20181128 || \
+ PACKETVER == 20181212 || \
+ PACKETVER == 20181219 || \
+ PACKETVER == 20181226 || \
+ PACKETVER == 20190116 || \
+ PACKETVER == 20190117 || \
+ PACKETVER == 20190130 || \
+ PACKETVER == 20190213 || \
+ PACKETVER == 20190220 || \
+ PACKETVER == 20190227 || \
+ PACKETVER == 20190313 || \
+ PACKETVER == 20190327 || \
+ PACKETVER == 20190403 || \
+ PACKETVER == 20190410 || \
+ PACKETVER == 20190424 || \
+ PACKETVER == 20190502 || \
+ PACKETVER == 20190508 || \
+ PACKETVER == 20190515 || \
+ PACKETVER == 20190529 || \
+ PACKETVER == 20190530 || \
+ PACKETVER == 20190605 || \
+ PACKETVER == 20190626 || \
+ PACKETVER == 20190709 || \
+ PACKETVER == 20190710 || \
+ PACKETVER == 20190717 || \
+ PACKETVER == 20190724 || \
+ PACKETVER == 20190814 || \
+ PACKETVER == 20190828 || \
+ PACKETVER == 20190911 || \
+ PACKETVER == 20190918 || \
+ PACKETVER == 20190925 || \
+ PACKETVER == 20191008 || \
+ PACKETVER == 20191023 || \
+ PACKETVER == 20191106 || \
+ PACKETVER == 20191113 || \
+ PACKETVER == 20191127 || \
+ PACKETVER == 20191204 || \
+ PACKETVER == 20191211 || \
+ PACKETVER == 20191224 || \
+ PACKETVER == 20200115 || \
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200226 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401 || \
+ PACKETVER >= 20200414
+ packetKeys(0x00000000,0x00000000,0x00000000);
+#endif
+
+// 2017-11-15aRagexe_zero, 2017-11-15bRagexe_zero, 2017-11-16aRagexe_zero, 2017-11-17aRagexe_zero
+#if PACKETVER == 20171115 || \
+ PACKETVER == 20171116 || \
+ PACKETVER == 20171117
+ packetKeys(0x3b93061d,0x3cb50dcd,0x410a197e);
+#endif
+
+// 2017-11-21aRagexe_zero, 2017-11-22aRagexe_zero
+#if PACKETVER == 20171121 || \
+ PACKETVER == 20171122
+ packetKeys(0x195b4da8,0x6e3a473b,0x126f4b61);
+#endif
+
+// 2017-11-23dRagexe_zero
+#if PACKETVER == 20171123
+ packetKeys(0x6087733a,0x5c5c4aee,0x0f10408f);
+#endif
+
+// 2017-11-27aRagexe_zero, 2017-11-27cRagexe_zero, 2017-11-28aRagexe_zero
+#if PACKETVER == 20171127 || \
+ PACKETVER == 20171128
+ packetKeys(0x141c135c,0x675c275c,0x275c275c);
+#endif
+
+// 2017-11-30bRagexe_zero
+#if PACKETVER == 20171130
+ packetKeys(0x31a04b32,0x3ac96b76,0x1742085d);
+#endif
+
+// 2017-12-04bRagexe_zero
+#if PACKETVER == 20171204
+ packetKeys(0x06a109f1,0x6a953256,0x0a6040a3);
+#endif
+
+// 2017-12-06aRagexe_zero, 2017-12-06bRagexe_zero, 2017-12-06cRagexe_zero, 2017-12-06dRagexe_zero, 2017-12-08aRagexe_zero, 2017-12-08cRagexe_zero, 2017-12-08dRagexe_zero, 2017-12-09bRagexe_zero, 2017-12-09cRagexe_zero, 2017-12-10aRagexe_zero, 2017-12-11bRagexe_zero, 2017-12-12aRagexe_zero, 2017-12-13aRagexe_zero, 2017-12-13bRagexe_zero, 2017-12-13cRagexe_zero
+#if PACKETVER == 20171206 || \
+ PACKETVER == 20171208 || \
+ PACKETVER == 20171209 || \
+ PACKETVER == 20171210 || \
+ PACKETVER == 20171211 || \
+ PACKETVER == 20171212 || \
+ PACKETVER == 20171213
+ packetKeys(0x718d0388,0x56a11525,0x20042f67);
+#endif
+
+// 2017-12-14cRagexe_zero
+#if PACKETVER == 20171214
+ packetKeys(0x6ce1021d,0x77703b04,0x4e722232);
+#endif
+
+// 2017-12-20aRagexe_zero, 2017-12-21aRagexe_zero, 2017-12-21bRagexe_zero
+#if PACKETVER == 20171220 || \
+ PACKETVER == 20171221
+ packetKeys(0x1e2047d2,0x7ee31ac2,0x31434f61);
+#endif
+
+// 2017-12-27bRagexe_zero, 2017-12-29aRagexe_zero
+#if PACKETVER == 20171227 || \
+ PACKETVER == 20171229
+ packetKeys(0x7cbf0846,0x02f92654,0x22aa5e2d);
+#endif
+
+// 2018-01-03aRagexe_zero
+#if PACKETVER == 20180103
+ packetKeys(0x2a3d4e64,0x7008690c,0x69ff066f);
+#endif
+
+// 2018-01-17aRagexe_zero
+#if PACKETVER == 20180117
+ packetKeys(0x230959eb,0x1ccb0182,0x1ffa2b30);
+#endif
+
+// 2018-01-31dRagexe_zero
+#if PACKETVER == 20180131
+ packetKeys(0x1f422e02,0x12025202,0x52025202);
+#endif
+
+// 2018-02-07bRagexe_zero
+#if PACKETVER == 20180207
+ packetKeys(0x07cb29cb,0x69cb69cb,0x69cb69cb);
+#endif
+
+// 2018-02-13aRagexe_zero
+#if PACKETVER == 20180213
+ packetKeys(0x0513075e,0x347075af,0x67c56c6f);
+#endif
+
+// 2018-02-21aRagexe_zero
+#if PACKETVER == 20180221
+ packetKeys(0x28ed7635,0x76591f21,0x59383498);
+#endif
+
+// 2018-02-28bRagexe_zero, 2018-03-07aRagexe_zero, 2018-03-09aRagexe_zero
+#if PACKETVER == 20180228 || \
+ PACKETVER == 20180307 || \
+ PACKETVER == 20180309
+ packetKeys(0x56c82abe,0x61ae2b2e,0x472e272e);
+#endif
+
+// 2018-03-14nRagexe_zero
+#if PACKETVER == 20180314
+ packetKeys(0x2fc330dd,0x01c04e1f,0x4d914de2);
+#endif
+
+// 2018-05-11aRagexe_zero, 2018-05-11bRagexe_zero
+#if PACKETVER == 20180511
+ packetKeys(0x1c055b65,0x68ce748d,0x32af761d);
+#endif
+
+
+#endif /* MAP_PACKETS_ZERO_KEYS_H */
diff --git a/src/map/packets_shuffle_main.h b/src/map/packets_shuffle_main.h
new file mode 100644
index 000000000..d643f3b0e
--- /dev/null
+++ b/src/map/packets_shuffle_main.h
@@ -0,0 +1,9859 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//Included directly by clif.c in packet_loaddb()
+
+#ifndef MAP_PACKETS_SHUFFLE_MAIN_H
+#define MAP_PACKETS_SHUFFLE_MAIN_H
+
+#ifndef packet
+ #define packet(a,...)
+#endif
+
+/*
+ * packet syntax
+ * - packet(packet_id,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet ),...)
+ * - Example: packet(0x0072,clif->pWantToConnection,2,6,10,14,18);
+ */
+
+/* This file is autogenerated, please do not commit manual changes */
+
+
+// 2012-07-10aRagexe, 2012-07-12aRagexe
+#if PACKETVER == 20120710 || \
+ PACKETVER == 20120712
+ packet(0x0202,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0362,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0367,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07e4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0877,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0878,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a3,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0936,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0948,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0956,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2012-07-16aRagexe
+#if PACKETVER == 20120716
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-07-24aRagexe
+#if PACKETVER == 20120724
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0815,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0865,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a1,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x092b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0935,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0938,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0945,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0959,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0965,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2012-08-01aRagexe, 2012-08-01bRagexe
+#if PACKETVER == 20120801
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0438,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0873,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a2,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08aa,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0934,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0946,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2012-08-08aRagexe, 2012-08-08bRagexe, 2012-08-08cRagexe
+#if PACKETVER == 20120808
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-08-14aRagexe, 2012-08-14bRagexe
+#if PACKETVER == 20120814
+ packet(0x0281,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0365,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0366,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07ec,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0815,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0838,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0861,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0862,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0865,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0875,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0895,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0920,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0932,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0934,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0967,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0969,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2012-08-22aRagexe, 2012-08-22bRagexe, 2012-08-22cRagexe
+#if PACKETVER == 20120822
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0872,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x087d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0917,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0924,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0927,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0935,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0940,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0943,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0953,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0958,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2012-08-30aRagexe
+#if PACKETVER == 20120830
+ packet(0x022d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0838,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0926,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0945,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-09-05aRagexe
+#if PACKETVER == 20120905
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0817,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0895,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0897,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a6,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0917,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0918,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0944,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0945,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0950,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0959,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0967,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2012-09-11aRagexe
+#if PACKETVER == 20120911
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0879,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a4,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a6,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a7,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0930,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0935,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0948,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0949,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0958,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0959,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0962,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0963,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2012-09-19aRagexe
+#if PACKETVER == 20120919
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-09-25aRagexe, 2012-09-26aRagexe
+#if PACKETVER == 20120925 || \
+ PACKETVER == 20120926
+ packet(0x07e4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0815,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0873,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a4,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0923,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0927,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0932,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0948,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0950,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2012-10-10aRagexe, 2012-10-10bRagexe
+#if PACKETVER == 20121010
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0817,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0874,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0883,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0896,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0925,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0942,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0947,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0964,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2012-10-17aRagexe, 2012-10-17bRagexe
+#if PACKETVER == 20121017
+ packet(0x023b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0887,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0897,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0918,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0920,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0965,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-10-24aRagexe
+#if PACKETVER == 20121024
+ packet(0x0436,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0437,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0882,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0889,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a9,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08aa,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0931,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0942,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0954,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0955,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0965,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2012-10-31aRagexe
+#if PACKETVER == 20121031
+ packet(0x022d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-11-07aRagexe
+#if PACKETVER == 20121107
+ packet(0x0360,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0861,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0865,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0871,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0873,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0896,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0922,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0934,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0945,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0960,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0963,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0966,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2012-11-14aRagexe
+#if PACKETVER == 20121114
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0815,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0862,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0876,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0879,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0881,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0898,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0899,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08aa,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0935,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0938,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0949,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0965,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2012-11-21aRagexe
+#if PACKETVER == 20121121
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0863,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0880,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a7,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08aa,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0927,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0938,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0950,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2012-11-28aRagexe
+#if PACKETVER == 20121128
+ packet(0x0362,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07ec,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0861,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0867,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0888,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a8,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0921,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0931,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0945,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0950,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0953,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0960,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2012-12-05aRagexe, 2012-12-05bRagexe
+#if PACKETVER == 20121205
+ packet(0x035f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0360,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0815,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0863,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0873,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0875,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0878,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0889,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0959,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2012-12-12aRagexe, 2012-12-12bRagexe
+#if PACKETVER == 20121212
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0368,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0369,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0893,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a3,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a7,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0920,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0932,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0951,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0953,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0966,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-12-18aRagexe, 2012-12-18bRagexe
+#if PACKETVER == 20121218
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0872,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-12-27aRagexe
+#if PACKETVER == 20121227
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x02c4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0860,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0870,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0872,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0888,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0890,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0894,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0896,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a6,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0917,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0920,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0932,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0933,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0943,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0947,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0958,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2013-01-03aRagexe, 2013-01-07aRagexe
+#if PACKETVER == 20130103 || \
+ PACKETVER == 20130107
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-01-09aRagexe
+#if PACKETVER == 20130109
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0888,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0918,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0922,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0927,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0928,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0931,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093e,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0950,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0951,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0955,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-01-15bRagexe, 2013-01-16aRagexe, 2013-01-16bRagexe
+#if PACKETVER == 20130115 || \
+ PACKETVER == 20130116
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0817,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0861,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0870,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0871,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0879,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0888,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0894,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0895,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a0,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0918,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0939,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2013-01-21aRagexe
+#if PACKETVER == 20130121
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0802,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0874,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0893,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-01-30aRagexe
+#if PACKETVER == 20130130
+ packet(0x035f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0368,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0437,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0885,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0887,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a0,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a9,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0920,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0924,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0956,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2013-02-06aRagexe
+#if PACKETVER == 20130206
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0883,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a0,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0925,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-15aRagexe, 2013-02-15bRagexe
+#if PACKETVER == 20130215
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0886,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-20aRagexe
+#if PACKETVER == 20130220
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-27aRagexe
+#if PACKETVER == 20130227
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0811,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0815,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0893,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a0,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a1,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0924,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0951,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0967,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2013-03-06aRagexe
+#if PACKETVER == 20130306
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0367,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0368,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0802,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0898,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0926,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0934,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0936,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0943,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0945,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0946,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0951,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0960,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-03-13aRagexe
+#if PACKETVER == 20130313
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0887,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0920,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-03-20dRagexe, 2013-03-20eRagexe
+#if PACKETVER == 20130320
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0438,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0868,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0874,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0881,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0886,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0898,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0922,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0933,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0959,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2013-03-27bRagexe
+#if PACKETVER == 20130327
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0835,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0878,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0893,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a1,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0938,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0939,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0955,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0960,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0961,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0967,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2013-04-03aRagexe
+#if PACKETVER == 20130403
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0884,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0942,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0950,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-04-10aRagexe
+#if PACKETVER == 20130410
+ packet(0x0367,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0860,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0881,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x088c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a7,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0917,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0933,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0939,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x093d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0945,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0955,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2013-04-17aRagexe
+#if PACKETVER == 20130417
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0929,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x096a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2013-04-24aRagexe
+#if PACKETVER == 20130424
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0969,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-02aRagexe, 2013-05-02bRagexe
+#if PACKETVER == 20130502
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0874,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0875,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0877,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a1,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a3,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-05-08bRagexe, 2013-05-08cRagexe, 2013-05-08dRagexe, 2013-05-08eRagexe, 2013-05-08fRagexe
+#if PACKETVER == 20130508
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0897,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-15aRagexe
+#if PACKETVER == 20130515
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0887,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a1,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0943,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0947,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0962,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-22aRagexe
+#if PACKETVER == 20130522
+ packet(0x0360,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0368,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0874,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a2,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a3,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a6,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0950,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0965,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2013-05-29aRagexe
+#if PACKETVER == 20130529
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0877,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0892,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0897,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a7,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0918,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0936,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0938,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0951,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0964,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2013-06-05aRagexe, 2013-06-05bRagexe
+#if PACKETVER == 20130605
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0883,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-06-12aRagexe, 2013-06-12bRagexe, 2013-06-12cRagexe, 2013-06-12dRagexe, 2013-06-12eRagexe
+#if PACKETVER == 20130612
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0964,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-06-18#1aRagexe
+#if PACKETVER == 20130618
+ packet(0x0281,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0862,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0890,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0932,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0936,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0942,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0945,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0951,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0953,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2013-06-26_3cRagexe, 2013-06-26bRagexe
+#if PACKETVER == 20130626
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0894,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ab,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0930,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-03aRagexe
+#if PACKETVER == 20130703
+ packet(0x0202,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-10bRagexe
+#if PACKETVER == 20130710
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0880,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-17cRagexe
+#if PACKETVER == 20130717
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0863,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0882,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0897,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0898,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a9,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0918,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0956,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0960,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x096a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2013-07-24eRagexe
+#if PACKETVER == 20130724
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0437,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0867,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0891,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0893,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0924,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0953,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0954,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0956,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0958,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2013-07-31cRagexe
+#if PACKETVER == 20130731
+ packet(0x022d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0894,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0923,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0925,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0962,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2013-08-07aRagexe
+#if PACKETVER == 20130807
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-08-14aRagexe
+#if PACKETVER == 20130814
+ packet(0x0202,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0281,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0368,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0815,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0873,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0874,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0887,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0923,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0926,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0936,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0937,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x093a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0947,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0959,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2013-08-21bRagexe
+#if PACKETVER == 20130821
+ packet(0x0202,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0437,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0438,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0815,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0879,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0892,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a6,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x093e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0954,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0967,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2013-08-28bRagexe, 2013-08-28cRagexe
+#if PACKETVER == 20130828
+ packet(0x023b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0361,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0817,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0873,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0889,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a3,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0917,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0919,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0944,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2013-09-04aRagexe
+#if PACKETVER == 20130904
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0838,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0937,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-09-11aRagexe, 2013-09-11bRagexe
+#if PACKETVER == 20130911
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0891,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0948,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2013-09-17aRagexe
+#if PACKETVER == 20130917
+ packet(0x035f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x083c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0863,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0895,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a8,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0918,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0923,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0934,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0959,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x096a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2013-09-25aRagexe, 2013-09-25bRagexe, 2013-09-25cRagexe
+#if PACKETVER == 20130925
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0885,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-10-02aRagexe
+#if PACKETVER == 20131002
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-10-08aRagexe
+#if PACKETVER == 20131008
+ packet(0x0202,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0362,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x083c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0863,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0883,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0927,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0932,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0936,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0956,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2013-10-16aRagexe, 2013-10-16bRagexe
+#if PACKETVER == 20131016
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0281,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0364,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x07ec,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0867,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0870,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0887,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0894,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x091e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0927,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0946,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0962,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2013-10-23aRagexe
+#if PACKETVER == 20131023
+ packet(0x0366,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0819,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a7,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0919,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0923,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0935,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0937,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0944,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0951,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2013-10-30aRagexe
+#if PACKETVER == 20131030
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-11-06aRagexe, 2013-11-07aRagexe, 2013-11-07bRagexe, 2013-11-07cRagexe, 2013-11-08aRagexe
+#if PACKETVER == 20131106 || \
+ PACKETVER == 20131107 || \
+ PACKETVER == 20131108
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0369,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0436,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0867,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0887,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0891,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0894,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0919,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0942,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0946,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0948,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0950,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0954,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0962,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0967,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2013-11-13bRagexe
+#if PACKETVER == 20131113
+ packet(0x0364,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0879,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0929,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0934,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0936,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0949,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0950,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0964,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0969,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2013-11-20dRagexe
+#if PACKETVER == 20131120
+ packet(0x0361,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0802,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0817,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a1,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0926,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0927,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0950,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0955,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2013-11-27bRagexe
+#if PACKETVER == 20131127
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0930,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2013-12-04eRagexe
+#if PACKETVER == 20131204
+ packet(0x0365,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0862,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0869,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0879,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0882,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a0,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a7,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0928,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x092d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0932,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0958,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0959,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0961,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0967,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2013-12-11cRagexe, 2013-12-11dRagexe
+#if PACKETVER == 20131211
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0892,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a3,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-18bRagexe
+#if PACKETVER == 20131218
+ packet(0x022d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ab,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0947,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-23bRagexe, 2013-12-23cRagexe
+#if PACKETVER == 20131223
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-30aRagexe
+#if PACKETVER == 20131230
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0365,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0369,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a9,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0926,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0943,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0949,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0968,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x096a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2014-01-08cRagexe, 2014-01-08dRagexe
+#if PACKETVER == 20140108
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-01-15aRagexe, 2014-01-15bRagexe, 2014-01-15cRagexe, 2014-01-15eRagexe
+#if PACKETVER == 20140115
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0865,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0965,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0966,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-01-22aRagexe
+#if PACKETVER == 20140122
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0811,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0863,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0893,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08aa,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0925,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0942,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0950,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0952,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0955,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2014-01-29aRagexe, 2014-01-29cRagexe
+#if PACKETVER == 20140129
+ packet(0x0281,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0885,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0924,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-02-05bRagexe
+#if PACKETVER == 20140205
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0938,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-02-12aRagexe
+#if PACKETVER == 20140212
+ packet(0x02c4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0369,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0874,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0878,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a0,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a1,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a7,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0919,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0934,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0936,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0952,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0960,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2014-02-19aRagexe
+#if PACKETVER == 20140219
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0360,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0364,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0802,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0860,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0868,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0927,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0939,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0953,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0961,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2014-02-26aRagexe
+#if PACKETVER == 20140226
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0887,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0894,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0921,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0931,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0941,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-03-05aRagexe, 2014-03-05bRagexe
+#if PACKETVER == 20140305
+ packet(0x0202,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0934,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-03-12dRagexe
+#if PACKETVER == 20140312
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0889,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0891,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0894,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0948,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2014-03-19aRagexe
+#if PACKETVER == 20140319
+ packet(0x02c4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07e4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0802,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0811,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0815,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0864,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0866,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0883,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0933,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0944,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0947,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0955,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x096a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2014-03-26aRagexe
+#if PACKETVER == 20140326
+ packet(0x0362,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x07ec,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x083c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0867,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0869,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0918,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0969,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2014-04-02fRagexe, 2014-04-02gRagexe
+#if PACKETVER == 20140402
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0360,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0364,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0867,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0868,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0882,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0883,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0890,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0896,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0920,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0926,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0933,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x093f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0944,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0950,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2014-04-09aRagexe, 2014-04-09bRagexe
+#if PACKETVER == 20140409
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0868,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0873,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0883,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0884,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0896,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a6,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08a7,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0918,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0942,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0947,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2014-04-16aRagexe, 2014-04-16bRagexe
+#if PACKETVER == 20140416
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-04-23aRagexe
+#if PACKETVER == 20140423
+ packet(0x022d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0811,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x083c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0866,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0873,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0890,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0895,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0896,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a8,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-04-30aRagexe
+#if PACKETVER == 20140430
+ packet(0x023b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0860,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0871,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0884,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0899,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a1,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0956,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2014-05-08bRagexe
+#if PACKETVER == 20140508
+ packet(0x022d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0927,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0932,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-05-14bRagexe
+#if PACKETVER == 20140514
+ packet(0x0437,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0865,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0876,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0877,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0886,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a5,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0921,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0925,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0965,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2014-05-21bRagexe
+#if PACKETVER == 20140521
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0968,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-05-28aRagexe
+#if PACKETVER == 20140528
+ packet(0x0202,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0862,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0875,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0877,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a8,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0930,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0963,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0966,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2014-06-05aRagexe, 2014-06-05bRagexe
+#if PACKETVER == 20140605
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0369,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0921,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-06-11cRagexe, 2014-06-11dRagexe, 2014-06-11hRagexe, 2014-06-12aRagexe, 2014-06-13aRagexe
+#if PACKETVER == 20140611 || \
+ PACKETVER == 20140612 || \
+ PACKETVER == 20140613
+ packet(0x0364,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0838,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0864,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0867,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0874,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0878,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0891,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0893,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0894,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a1,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0924,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0950,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0951,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0952,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0957,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0958,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0965,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-28bRagexe, 2018-04-04bRagexe, 2018-04-18aRagexe, 2018-04-25cRagexe, 2018-05-02bRagexe, 2018-05-09aRagexe, 2018-05-16cRagexe, 2018-05-23aRagexe, 2018-05-30aRagexe, 2018-06-05bRagexe, 2018-06-20cRagexe, 2018-06-20eRagexe, 2018-06-21aRagexe, 2018-07-04aRagexe, 2018-07-18bRagexe, 2018-07-18cRagexe, 2018-08-01cRagexe, 2018-08-08bRagexe, 2018-08-22cRagexe, 2018-08-29aRagexe, 2018-08-31aRagexe, 2018-09-12dRagexe, 2018-09-19aRagexe, 2018-10-02aRagexe, 2018-10-02bRagexe, 2018-10-17_02aRagexe, 2018-10-17_03aRagexe, 2018-10-17bRagexe, 2018-10-24bRagexe, 2018-10-31aRagexe, 2018-10-31bRagexe, 2018-11-07aRagexe, 2018-11-14cRagexe, 2018-11-14dRagexe
+#if PACKETVER == 20140611 || \
+ PACKETVER == 20150225 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER == 20180404 || \
+ PACKETVER == 20180418 || \
+ PACKETVER == 20180425 || \
+ PACKETVER == 20180502 || \
+ PACKETVER == 20180509 || \
+ PACKETVER == 20180516 || \
+ PACKETVER == 20180523 || \
+ PACKETVER == 20180530 || \
+ PACKETVER == 20180605 || \
+ PACKETVER == 20180620 || \
+ PACKETVER == 20180621 || \
+ PACKETVER == 20180704 || \
+ PACKETVER == 20180718 || \
+ PACKETVER == 20180801 || \
+ PACKETVER == 20180808 || \
+ PACKETVER == 20180822 || \
+ PACKETVER == 20180829 || \
+ PACKETVER == 20180831 || \
+ PACKETVER == 20180912 || \
+ PACKETVER == 20180919 || \
+ PACKETVER == 20181002 || \
+ PACKETVER == 20181017 || \
+ PACKETVER == 20181024 || \
+ PACKETVER == 20181031 || \
+ PACKETVER == 20181107 || \
+ PACKETVER == 20181114
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2014-06-18aRagexe
+#if PACKETVER == 20140618
+ packet(0x085d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0860,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0861,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0878,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0884,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0885,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0886,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0890,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0939,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0945,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0967,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-06-25aRagexe, 2014-06-25bRagexe
+#if PACKETVER == 20140625
+ packet(0x0202,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x023b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0815,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0817,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0861,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0886,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0897,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a1,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a2,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0928,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0959,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0968,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0969,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-07-02aRagexe
+#if PACKETVER == 20140702
+ packet(0x022d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0438,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x07e4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a0,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a2,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0933,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-07-09aRagexe
+#if PACKETVER == 20140709
+ packet(0x0364,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0869,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0877,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0879,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0887,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0894,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0897,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0898,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0925,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0931,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0939,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0961,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2014-07-16aRagexe, 2014-07-16bRagexe, 2014-07-16cRagexe
+#if PACKETVER == 20140716
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0871,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0881,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a4,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0918,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0926,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0938,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0952,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0959,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2014-07-23aRagexe, 2014-07-23bRagexe
+#if PACKETVER == 20140723
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0436,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0819,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x087d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0888,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0891,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0896,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ad,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0927,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0934,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0935,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0939,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0945,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0947,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0948,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0960,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2014-07-30aRagexe
+#if PACKETVER == 20140730
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0367,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0437,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0815,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0889,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0892,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0924,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0934,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-08-06aRagexe, 2014-08-06bRagexe
+#if PACKETVER == 20140806
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0948,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-08-13aRagexe, 2014-08-13bRagexe, 2014-08-14aRagexe
+#if PACKETVER == 20140813 || \
+ PACKETVER == 20140814
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0878,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0897,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0967,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-08-20aRagexe
+#if PACKETVER == 20140820
+ packet(0x035f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0861,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0869,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0872,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0876,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0899,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a7,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0937,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0951,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0952,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0956,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-08-27aRagexe
+#if PACKETVER == 20140827
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0943,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-09-03aRagexe
+#if PACKETVER == 20140903
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0943,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0945,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-09-17aRagexe
+#if PACKETVER == 20140917
+ packet(0x022d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0364,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0365,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0367,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0895,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0897,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0898,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a8,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0919,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x091e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0949,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0951,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x095e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0966,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-09-24cRagexe
+#if PACKETVER == 20140924
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0864,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0886,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0894,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0898,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a5,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a7,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0918,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0925,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0926,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0949,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0952,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2014-10-01aRagexe
+#if PACKETVER == 20141001
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0885,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0952,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-10-08aRagexe, 2014-10-08bRagexe, 2014-10-08cRagexe, 2014-10-08dRagexe
+#if PACKETVER == 20141008
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-15bRagexe, 2014-10-15cRagexe, 2014-10-15dRagexe, 2014-10-16aRagexe
+#if PACKETVER == 20141015 || \
+ PACKETVER == 20141016
+ packet(0x022d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0922,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-22bRagexe
+#if PACKETVER == 20141022
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0896,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0899,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08aa,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-29aRagexe
+#if PACKETVER == 20141029
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-11-05aRagexe, 2014-11-05bRagexe
+#if PACKETVER == 20141105
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0864,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0865,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0874,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0879,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0887,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0892,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0950,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x095f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0968,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-11-12cRagexe, 2014-11-12dRagexe
+#if PACKETVER == 20141112
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0438,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0885,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a0,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a1,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08ab,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0919,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0929,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0943,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0960,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0962,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2014-11-19dRagexe
+#if PACKETVER == 20141119
+ packet(0x0202,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0866,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0873,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0887,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0895,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0918,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0920,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0921,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0938,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0963,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2014-11-26aRagexe, 2014-11-26bRagexe, 2014-11-26cRagexe, 2014-11-26dRagexe
+#if PACKETVER == 20141126
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0871,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0920,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0942,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-12-03aRagexe
+#if PACKETVER == 20141203
+ packet(0x0202,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0281,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0861,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0880,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0889,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a5,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08aa,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0936,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0957,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0962,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2014-12-10bRagexe, 2014-12-10cRagexe
+#if PACKETVER == 20141210
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0885,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08ac,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0917,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0954,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0967,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-12-17aRagexe
+#if PACKETVER == 20141217
+ packet(0x0360,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0879,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0883,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0889,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a1,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ab,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0919,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0924,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0930,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0932,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0933,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0939,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0945,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0948,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0960,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-12-24aRagexe
+#if PACKETVER == 20141224
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0438,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0835,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0870,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a3,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08ac,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0932,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0945,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0946,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0949,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0953,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2014-12-31aRagexe
+#if PACKETVER == 20141231
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-07aRagexe
+#if PACKETVER == 20150107
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0895,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-14aRagexe, 2015-01-14bRagexe, 2015-01-14cRagexe, 2015-01-14dRagexe
+#if PACKETVER == 20150114
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0955,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-21aRagexe
+#if PACKETVER == 20150121
+ packet(0x0281,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0919,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0955,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0959,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-28aRagexe, 2015-01-29aRagexe, 2015-01-30aRagexe
+#if PACKETVER == 20150128 || \
+ PACKETVER == 20150129 || \
+ PACKETVER == 20150130
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x023b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0838,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0864,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0874,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0888,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0929,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0963,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0968,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2015-02-04aRagexe
+#if PACKETVER == 20150204
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0966,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-02-11aRagexe
+#if PACKETVER == 20150211
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0368,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0369,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x07e4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0819,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0862,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0873,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0882,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0883,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0885,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0886,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0919,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2015-02-17aRagexe
+#if PACKETVER == 20150217
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-02-25eRagexe, 2015-02-25fRagexe, 2015-02-25gRagexe, 2015-02-25iRagexe, 2015-02-25jRagexe, 2015-02-26aRagexe
+#if PACKETVER == 20150225 || \
+ PACKETVER == 20150226
+ packet(0x02c4,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0948,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0955,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-03-04aRagexe
+#if PACKETVER == 20150304
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0879,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0892,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-03-11aRagexe, 2015-03-11bRagexe
+#if PACKETVER == 20150311
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0838,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0896,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a5,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a6,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0928,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0943,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0957,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0958,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0964,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2015-03-18aRagexe, 2015-03-18bRagexe
+#if PACKETVER == 20150318
+ packet(0x0202,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x023b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0802,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0862,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0885,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0928,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0936,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0951,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0960,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-03-25aRagexe
+#if PACKETVER == 20150325
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0365,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0883,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a7,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0919,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0931,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0932,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0938,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0954,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0969,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2015-04-01aRagexe
+#if PACKETVER == 20150401
+ packet(0x0362,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0437,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x083c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a5,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0924,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0939,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0949,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0953,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0964,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-04-08aRagexe
+#if PACKETVER == 20150408
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0865,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0868,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0891,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0922,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0946,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0957,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0959,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0963,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2015-04-15aRagexe
+#if PACKETVER == 20150415
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0364,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0368,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0802,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0867,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0869,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0880,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0898,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a0,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x093c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0941,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0946,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0953,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-04-22aRagexe
+#if PACKETVER == 20150422
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0955,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-04-29aRagexe
+#if PACKETVER == 20150429
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0886,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0894,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0899,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0943,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-07bRagexe, 2015-05-07cRagexe
+#if PACKETVER == 20150507
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0924,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0941,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0942,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0953,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0955,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-13aRagexe
+#if PACKETVER == 20150513
+ packet(0x022d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x02c4,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0883,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a8,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0923,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0924,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0960,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-20aRagexe
+#if PACKETVER == 20150520
+ packet(0x0202,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0880,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a2,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0924,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0931,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0936,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x093d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0945,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0960,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-05-27aRagexe
+#if PACKETVER == 20150527
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x083c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-06-03aRagexe
+#if PACKETVER == 20150603
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0437,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0864,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0867,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0873,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0881,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a1,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ad,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0922,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0960,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0969,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x096a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2015-06-10aRagexe
+#if PACKETVER == 20150610
+ packet(0x022d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07e4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0872,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0885,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0897,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a0,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ac,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0925,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0932,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0946,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0949,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0957,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0964,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-06-17aRagexe, 2015-06-18aRagexe
+#if PACKETVER == 20150617 || \
+ PACKETVER == 20150618
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0362,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-06-24aRagexe
+#if PACKETVER == 20150624
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0365,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-07-01bRagexe, 2015-07-02aRagexe
+#if PACKETVER == 20150701 || \
+ PACKETVER == 20150702
+ packet(0x023b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x07e4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0883,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a0,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a4,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a5,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a6,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ad,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0919,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0923,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0928,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0954,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0958,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-07-08cRagexe
+#if PACKETVER == 20150708
+ packet(0x022d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0872,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-07-15aRagexe
+#if PACKETVER == 20150715
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0436,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0437,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0873,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0895,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0897,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0899,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0917,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0944,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-07-22bRagexe
+#if PACKETVER == 20150722
+ packet(0x023b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0368,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0811,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0880,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0899,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0919,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0925,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2015-07-29aRagexe
+#if PACKETVER == 20150729
+ packet(0x0437,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0870,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0880,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ad,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0920,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x093a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0955,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0961,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2015-08-05aRagexe
+#if PACKETVER == 20150805
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-12aRagexe
+#if PACKETVER == 20150812
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-19aRagexe
+#if PACKETVER == 20150819
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x022d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0281,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0865,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0919,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0927,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0967,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-26aRagexe, 2015-08-26bRagexe
+#if PACKETVER == 20150826
+ packet(0x0362,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x07ec,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0861,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a0,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a1,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0924,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0928,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0945,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0951,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0959,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0968,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0969,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2015-09-02aRagexe
+#if PACKETVER == 20150902
+ packet(0x023b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0367,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x083c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0886,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x088d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0892,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0897,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0923,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0941,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0947,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0953,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2015-09-09aRagexe
+#if PACKETVER == 20150909
+ packet(0x023b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0361,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0437,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0871,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0886,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0895,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0941,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-09-16aRagexe, 2015-09-16cRagexe
+#if PACKETVER == 20150916
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0817,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0869,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0873,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0877,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0920,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0924,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0936,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0942,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0948,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0969,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-09-23bRagexe, 2015-09-23cRagexe, 2015-09-23dRagexe, 2015-09-23eRagexe, 2015-09-23fRagexe
+#if PACKETVER == 20150923
+ packet(0x0361,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0817,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0864,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0879,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0892,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a6,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0936,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0951,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2015-10-01aRagexe
+#if PACKETVER == 20151001
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-07aRagexe
+#if PACKETVER == 20151007
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0961,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-14bRagexe
+#if PACKETVER == 20151014
+ packet(0x0202,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0838,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0863,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0874,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0881,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0883,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0884,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0889,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08aa,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0934,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0944,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0956,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-10-21aRagexe, 2015-10-22aRagexe
+#if PACKETVER == 20151021 || \
+ PACKETVER == 20151022
+ packet(0x023b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-28cRagexe, 2015-10-28dRagexe, 2015-10-29aRagexe
+#if PACKETVER == 20151028 || \
+ PACKETVER == 20151029
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-04aRagexe
+#if PACKETVER == 20151104
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0363,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0886,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a5,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0939,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093a,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2015-11-11aRagexe, 2015-11-11bRagexe
+#if PACKETVER == 20151111
+ packet(0x02c4,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0862,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0885,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0942,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0969,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-18aRagexe
+#if PACKETVER == 20151118
+ packet(0x022d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088b,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0925,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0943,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095c,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-25bRagexe, 2015-11-25dRagexe
+#if PACKETVER == 20151125
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0438,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0802,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0838,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0863,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0883,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0884,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a9,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0939,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0951,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0959,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2015-12-02aRagexe
+#if PACKETVER == 20151202
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-12-09aRagexe
+#if PACKETVER == 20151209
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07ec,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0811,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085b,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0861,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0866,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0894,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a1,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0920,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0932,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0948,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0956,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0964,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2015-12-16aRagexe
+#if PACKETVER == 20151216
+ packet(0x022d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0361,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0436,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0865,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a2,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0954,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0966,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0968,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2015-12-23bRagexe
+#if PACKETVER == 20151223
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0815,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0864,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0866,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0875,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0876,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0881,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0884,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0886,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08aa,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0918,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0923,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0965,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0967,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2015-12-30aRagexe
+#if PACKETVER == 20151230
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07ec,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0861,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0869,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0897,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0923,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0949,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-06aRagexe
+#if PACKETVER == 20160106
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0878,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0891,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-13aRagexe, 2016-01-13bRagexe, 2016-01-13bRagexe_2
+#if PACKETVER == 20160113
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x023b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x035f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0864,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0888,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0893,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a6,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0919,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0924,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0930,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0932,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0941,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0967,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2016-01-20aRagexe
+#if PACKETVER == 20160120
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0865,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-27cRagexe, 2016-01-27dRagexe
+#if PACKETVER == 20160127
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0922,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-03aRagexe
+#if PACKETVER == 20160203
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0940,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0947,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-11aRagexe
+#if PACKETVER == 20160211
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0870,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-17aRagexe
+#if PACKETVER == 20160217
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0362,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0864,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0873,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x087a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a0,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a9,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ac,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ad,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0920,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0926,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0941,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0966,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0969,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2016-02-24aRagexe
+#if PACKETVER == 20160224
+ packet(0x022d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0364,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0436,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0861,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0884,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0888,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0929,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0938,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-02bRagexe
+#if PACKETVER == 20160302
+ packet(0x022d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0367,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0819,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0864,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0883,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a6,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a9,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0945,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0950,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0968,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2016-03-09cRagexe
+#if PACKETVER == 20160309
+ packet(0x023b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0281,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0819,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0838,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x083c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0920,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0922,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0932,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0956,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2016-03-16aRagexe, 2016-03-18aRagexe
+#if PACKETVER == 20160316 || \
+ PACKETVER == 20160318
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0922,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-23aRagexe, 2016-03-23bRagexe
+#if PACKETVER == 20160323
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0883,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0926,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-30aRagexe, 2016-03-30bRagexe
+#if PACKETVER == 20160330
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0889,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0925,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0930,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0939,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x093b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-06aRagexe, 2016-04-06bRagexe
+#if PACKETVER == 20160406
+ packet(0x0364,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0869,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0877,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0879,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0884,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0892,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0898,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a9,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0927,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0934,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0949,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0953,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2016-04-14aRagexe, 2016-04-14bRagexe, 2016-04-14bRagexe_2, 2016-04-14cRagexe
+#if PACKETVER == 20160414
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0880,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0922,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0945,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0953,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-20cRagexe
+#if PACKETVER == 20160420
+ packet(0x022d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0870,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0874,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a5,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-27aRagexe
+#if PACKETVER == 20160427
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-04aRagexe
+#if PACKETVER == 20160504
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x083c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0890,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0898,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0918,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0924,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0941,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0948,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0952,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0969,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2016-05-11aRagexe
+#if PACKETVER == 20160511
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0920,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-18aRagexe
+#if PACKETVER == 20160518
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0874,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-25aRagexe, 2016-05-26aRagexe
+#if PACKETVER == 20160525 || \
+ PACKETVER == 20160526
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0945,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-01aRagexe
+#if PACKETVER == 20160601
+ packet(0x0202,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0870,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0895,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0924,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-08aRagexe, 2016-06-08bRagexe, 2016-06-09aRagexe
+#if PACKETVER == 20160608 || \
+ PACKETVER == 20160609
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0437,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0802,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a6,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-15aRagexe
+#if PACKETVER == 20160615
+ packet(0x0281,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0369,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x083c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0870,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0888,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0948,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0954,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0961,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2016-06-22aRagexe
+#if PACKETVER == 20160622
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07e4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0867,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0880,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0887,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0890,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0891,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0892,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a8,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0959,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0965,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0969,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2016-06-29aRagexe, 2016-06-30aRagexe
+#if PACKETVER == 20160629 || \
+ PACKETVER == 20160630
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x022d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0363,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0861,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0863,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0867,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0881,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0893,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0925,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0926,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0946,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0948,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0957,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0968,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0969,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2016-07-06bRagexe
+#if PACKETVER == 20160706
+ packet(0x0362,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0860,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0869,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0884,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0899,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a5,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a8,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0918,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x091b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0924,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0926,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0939,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0945,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2016-07-13aRagexe, 2016-07-13bRagexe, 2016-07-13cRagexe, 2016-07-13dRagexe
+#if PACKETVER == 20160713
+ packet(0x022d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0363,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0838,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0860,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0877,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0883,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0892,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0931,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0945,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0947,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0957,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-07-20aRagexe, 2016-07-20bRagexe
+#if PACKETVER == 20160720
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0365,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07e4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0838,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0883,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08aa,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0917,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2016-07-27aRagexe, 2016-07-27bRagexe
+#if PACKETVER == 20160727
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0436,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07ec,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0869,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0874,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0877,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a4,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a7,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0936,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0949,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0951,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0966,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2016-08-03bRagexe
+#if PACKETVER == 20160803
+ packet(0x0364,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0881,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0888,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0891,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0895,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08a1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0929,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0932,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0934,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0952,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0959,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2016-08-10aRagexe
+#if PACKETVER == 20160810
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0819,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x085d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0860,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0875,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0879,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0885,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a9,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0943,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0967,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-08-17aRagexe
+#if PACKETVER == 20160817
+ packet(0x0364,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07e4,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0819,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x083c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0867,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0875,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0886,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a5,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a9,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08ab,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ac,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0929,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0930,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0939,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0963,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-08-24aRagexe
+#if PACKETVER == 20160824
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-08-31aRagexe, 2016-08-31bRagexe
+#if PACKETVER == 20160831
+ packet(0x022d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0835,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0874,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a9,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0938,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0946,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0950,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0954,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0960,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0967,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2016-09-07aRagexe
+#if PACKETVER == 20160907
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x091c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-09-13aRagexe
+#if PACKETVER == 20160913
+ packet(0x0361,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0865,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0874,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0875,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0887,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0889,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0891,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0935,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0949,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0950,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0952,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0963,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0968,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2016-09-21aRagexe
+#if PACKETVER == 20160921
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-09-28cRagexe
+#if PACKETVER == 20160928
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0878,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0889,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0897,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a9,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0919,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0927,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0944,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0953,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0957,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2016-10-05aRagexe
+#if PACKETVER == 20161005
+ packet(0x0202,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0886,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0891,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08ac,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0918,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0919,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0931,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0932,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0942,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0945,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2016-10-12aRagexe
+#if PACKETVER == 20161012
+ packet(0x023b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0365,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0369,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07ec,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0819,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0868,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0875,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0880,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0893,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0937,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0939,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0943,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0944,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0962,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0966,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2016-10-19aRagexe
+#if PACKETVER == 20161019
+ packet(0x022d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0361,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0889,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0892,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-10-26bRagexe, 2016-10-26cRagexe
+#if PACKETVER == 20161026
+ packet(0x0363,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0862,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0886,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0891,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0894,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0898,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0926,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0930,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0953,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0962,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-11-02aRagexe, 2016-11-03aRagexe
+#if PACKETVER == 20161102 || \
+ PACKETVER == 20161103
+ packet(0x0361,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0367,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0802,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x083c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0874,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0886,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a2,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08aa,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0922,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0925,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0936,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0964,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0965,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0966,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2016-11-09aRagexe, 2016-11-09bRagexe
+#if PACKETVER == 20161109
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0362,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0870,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0876,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0881,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0898,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a7,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0937,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-11-16aRagexe
+#if PACKETVER == 20161116
+ packet(0x0368,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0369,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0835,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x085f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0885,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0890,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a2,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0925,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0931,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0967,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-11-23aRagexe
+#if PACKETVER == 20161123
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0861,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0880,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0882,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0926,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2016-11-30aRagexe, 2016-11-30bRagexe
+#if PACKETVER == 20161130
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0959,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-07cRagexe, 2016-12-07eRagexe
+#if PACKETVER == 20161207
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0886,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a2,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0943,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0965,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-14bRagexe, 2016-12-14cRagexe
+#if PACKETVER == 20161214
+ packet(0x022d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0862,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0887,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0899,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-21aRagexe, 2016-12-21bRagexe
+#if PACKETVER == 20161221
+ packet(0x035f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0817,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0866,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0876,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08aa,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0926,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0965,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-12-28aRagexe
+#if PACKETVER == 20161228
+ packet(0x0362,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0865,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0870,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0871,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0889,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a3,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a5,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ac,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0934,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0935,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0944,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2017-01-04aRagexe
+#if PACKETVER == 20170104
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0896,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-01-11aRagexe
+#if PACKETVER == 20170111
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a6,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-01-18aRagexe
+#if PACKETVER == 20170118
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0865,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0962,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2017-01-25aRagexe
+#if PACKETVER == 20170125
+ packet(0x0438,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0879,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0881,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0895,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0920,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x092b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0930,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0943,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0944,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0965,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0968,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2017-02-01aRagexe
+#if PACKETVER == 20170201
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0879,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0881,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0886,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a4,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0919,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0938,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-08bRagexe
+#if PACKETVER == 20170208
+ packet(0x02c4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0860,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0892,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a1,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0921,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0923,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0932,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0937,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-15aRagexe
+#if PACKETVER == 20170215
+ packet(0x02c4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0876,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0883,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a8,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0925,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0942,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2017-02-22aRagexe
+#if PACKETVER == 20170222
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0866,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0877,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0894,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a3,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0943,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-28aRagexe, 2017-02-28bRagexe
+#if PACKETVER == 20170228
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0819,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0863,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0873,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0874,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0876,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0883,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0889,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0893,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a7,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0944,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0948,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2017-03-08aRagexe
+#if PACKETVER == 20170308
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-03-15cRagexe
+#if PACKETVER == 20170315
+ packet(0x02c4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0360,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0436,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0863,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0884,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0922,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0952,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2017-03-22aRagexe, 2017-03-22bRagexe
+#if PACKETVER == 20170322
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x091a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-03-29bRagexe, 2017-03-29cRagexe
+#if PACKETVER == 20170329
+ packet(0x0281,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0888,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a8,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0926,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0929,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0949,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-04-05bRagexe, 2017-04-05cRagexe
+#if PACKETVER == 20170405
+ packet(0x022d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0281,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0860,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0865,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0893,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a5,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-04-12aRagexe
+#if PACKETVER == 20170412
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0365,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0869,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0879,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0938,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0942,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0945,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0949,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0959,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2017-04-19aRagexe
+#if PACKETVER == 20170419
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0838,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0872,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0881,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0897,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0920,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0922,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0931,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0935,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0942,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0963,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0965,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2017-04-26bRagexe
+#if PACKETVER == 20170426
+ packet(0x0281,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0866,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0899,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0927,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-05-02aRagexe, 2017-05-02bRagexe
+#if PACKETVER == 20170502
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0894,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-05-17aRagexe
+#if PACKETVER == 20170517
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0367,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0868,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0896,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a2,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a8,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2017-05-24aRagexe, 2017-05-24bRagexe
+#if PACKETVER == 20170524
+ packet(0x0364,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0866,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0868,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0874,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0882,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0894,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a1,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0923,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0925,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0967,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0968,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2017-05-31aRagexe
+#if PACKETVER == 20170531
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0369,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07ec,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0819,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0873,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0894,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ac,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0933,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0940,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0945,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0963,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0968,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-06-07cRagexe
+#if PACKETVER == 20170607
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07e4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x085e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0862,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0897,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a9,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ab,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0917,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0919,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0925,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0927,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0931,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0934,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0938,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x093d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0944,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0949,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2017-06-14bRagexe
+#if PACKETVER == 20170614
+ packet(0x023b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0361,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0364,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0367,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0838,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0866,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0867,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0877,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0889,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ad,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0928,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0944,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0963,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2017-06-21bRagexe
+#if PACKETVER == 20170621
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0365,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0802,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0885,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-06-28bRagexe
+#if PACKETVER == 20170628
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-05aRagexe
+#if PACKETVER == 20170705
+ packet(0x0202,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0886,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0930,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0932,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0934,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-12bRagexe
+#if PACKETVER == 20170712
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-19aRagexe
+#if PACKETVER == 20170719
+ packet(0x022d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0367,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0369,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x07e4,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0881,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0882,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0898,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a6,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0944,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2017-07-26aRagexe
+#if PACKETVER == 20170726
+ packet(0x0363,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0369,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0838,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0873,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0874,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a7,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08aa,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0921,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0923,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0943,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0950,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0952,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0954,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0963,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-08-01aRagexe, 2017-08-01bRagexe
+#if PACKETVER == 20170801
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0281,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-08-09cRagexe
+#if PACKETVER == 20170809
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0281,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0364,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0367,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x07e4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0802,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0868,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0880,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0892,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a3,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a6,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0918,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0931,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0939,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2017-08-16cRagexe, 2017-08-16dRagexe
+#if PACKETVER == 20170816
+ packet(0x022d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x035f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0438,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0862,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0864,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0881,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0882,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0889,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a3,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a9,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08ac,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x091c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0921,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0925,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0950,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0960,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-08-23aRagexe
+#if PACKETVER == 20170823
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ac,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-08-30aRagexe, 2017-08-30bRagexe
+#if PACKETVER == 20170830
+ packet(0x0281,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x02c4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0925,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0940,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0942,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0943,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0951,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-09-06cRagexe
+#if PACKETVER == 20170906
+ packet(0x0202,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0281,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0866,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0953,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-09-13cRagexe
+#if PACKETVER == 20170913
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x035f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0835,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0860,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0866,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0891,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0892,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08aa,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ab,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ac,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0920,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0923,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0925,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0927,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2017-09-20aRagexe
+#if PACKETVER == 20170920
+ packet(0x0369,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0436,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0862,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0865,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0874,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0919,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0921,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0926,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0939,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0945,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0961,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0966,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x096a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2017-09-27bRagexe, 2017-09-27cRagexe, 2017-09-27dRagexe
+#if PACKETVER == 20170927
+ packet(0x02c4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0875,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0899,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ad,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x091e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0922,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0923,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0942,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0945,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-10-02cRagexe
+#if PACKETVER == 20171002
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0928,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0943,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-11aRagexe, 2017-10-11bRagexe
+#if PACKETVER == 20171011
+ packet(0x023b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0882,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0950,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-18aRagexe
+#if PACKETVER == 20171018
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0938,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-25bRagexe, 2017-10-25cRagexe, 2017-10-25dRagexe, 2017-10-25eRagexe
+#if PACKETVER == 20171025
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-01aRagexe
+#if PACKETVER == 20171101
+ packet(0x022d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0369,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0860,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0876,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a0,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ab,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0939,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0957,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0966,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-11-08aRagexe
+#if PACKETVER == 20171108
+ packet(0x0202,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x07e4,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0819,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0863,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0878,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0884,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a2,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a9,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0945,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0949,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0963,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0965,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0967,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-11-15aRagexe
+#if PACKETVER == 20171115
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0365,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0883,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0890,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0926,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-22aRagexe
+#if PACKETVER == 20171122
+ packet(0x0281,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0838,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x083c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0862,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0867,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0877,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0891,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a6,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a9,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0920,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0923,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0945,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0947,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0968,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2017-11-29aRagexe
+#if PACKETVER == 20171129
+ packet(0x02c4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0365,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0878,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a5,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0953,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0966,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-06bRagexe, 2017-12-06cRagexe
+#if PACKETVER == 20171206
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0897,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a2,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0923,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0936,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0961,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-13bRagexe
+#if PACKETVER == 20171213
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-20aRagexe
+#if PACKETVER == 20171220
+ packet(0x0281,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0369,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0880,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0882,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0899,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a7,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0924,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0929,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0941,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0957,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0964,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2017-12-27aRagexe
+#if PACKETVER == 20171227
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0888,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a5,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2018-01-03aRagexe, 2018-01-03bRagexe
+#if PACKETVER == 20180103
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0363,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0872,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0876,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ac,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0922,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0948,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2018-01-17aRagexe
+#if PACKETVER == 20180117
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-01-24bRagexe, 2018-01-31Ragexe
+#if PACKETVER == 20180124 || \
+ PACKETVER == 20180131
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0890,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0919,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-07bRagexe, 2018-02-07cRagexe
+#if PACKETVER == 20180207
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0360,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0950,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-13aRagexe, 2018-02-13bRagexe
+#if PACKETVER == 20180213
+ packet(0x0369,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0817,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0874,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0882,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0898,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a3,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a9,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0917,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0922,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0924,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0936,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0943,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2018-02-21bRagexe
+#if PACKETVER == 20180221
+ packet(0x0202,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0838,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0867,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0871,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0880,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0881,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0891,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x089d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0929,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0964,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2018-03-07bRagexe, 2018-03-09aRagexe
+#if PACKETVER == 20180307 || \
+ PACKETVER == 20180309
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x07e4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0861,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0862,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0870,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0877,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0893,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a6,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08aa,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0920,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0937,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0939,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0941,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0951,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0954,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0969,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2018-03-14nRagexe
+#if PACKETVER == 20180314
+ packet(0x0361,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0366,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0369,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0436,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0862,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0863,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0874,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0894,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0921,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0927,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0933,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0935,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0945,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0959,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0962,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2018-11-21bRagexe, 2018-11-28aRagexe, 2018-11-28bRagexe, 2018-11-28cRagexe, 2018-12-05aRagexe, 2018-12-12aRagexe, 2018-12-12bRagexe, 2018-12-19bRagexe, 2018-12-26aRagexe, 2019-01-09aRagexe, 2019-01-16bRagexe, 2019-01-16cRagexe, 2019-01-23dRagexe, 2019-02-13bRagexe, 2019-02-13eRagexe, 2019-02-27aRagexe, 2019-02-28aRagexe, 2019-03-06bRagexe, 2019-03-06cRagexe, 2019-03-13aRagexe, 2019-03-20aRagexe, 2019-03-22aRagexe, 2019-03-27bRagexe, 2019-04-03aRagexe, 2019-04-17aRagexe, 2019-04-18aRagexe, 2019-05-08cRagexe, 2019-05-22bRagexe, 2019-05-22cRagexe, 2019-05-23aRagexe, 2019-05-29aRagexe, 2019-05-29cRagexe, 2019-05-30aRagexe, 2019-06-05fRagexe, 2019-06-05KRagexe, 2019-06-19bRagexe, 2019-06-19eRagexe, 2019-06-19hRagexe, 2019-07-03aRagexe, 2019-07-17aRagexe, 2019-07-17dRagexe, 2019-07-24aRagexe, 2019-07-31bRagexe, 2019-08-02aRagexe, 2019-08-07aRagexe, 2019-08-21aRagexe, 2019-08-28aRagexe
+#if PACKETVER == 20181121 || \
+ PACKETVER == 20181128 || \
+ PACKETVER == 20181205 || \
+ PACKETVER == 20181212 || \
+ PACKETVER == 20181219 || \
+ PACKETVER == 20181226 || \
+ PACKETVER == 20190109 || \
+ PACKETVER == 20190116 || \
+ PACKETVER == 20190123 || \
+ PACKETVER == 20190213 || \
+ PACKETVER == 20190227 || \
+ PACKETVER == 20190228 || \
+ PACKETVER == 20190306 || \
+ PACKETVER == 20190313 || \
+ PACKETVER == 20190320 || \
+ PACKETVER == 20190322 || \
+ PACKETVER == 20190327 || \
+ PACKETVER == 20190403 || \
+ PACKETVER == 20190417 || \
+ PACKETVER == 20190418 || \
+ PACKETVER == 20190508 || \
+ PACKETVER == 20190522 || \
+ PACKETVER == 20190523 || \
+ PACKETVER == 20190529 || \
+ PACKETVER == 20190530 || \
+ PACKETVER == 20190605 || \
+ PACKETVER == 20190619 || \
+ PACKETVER == 20190703 || \
+ PACKETVER == 20190717 || \
+ PACKETVER == 20190724 || \
+ PACKETVER == 20190731 || \
+ PACKETVER == 20190802 || \
+ PACKETVER == 20190807 || \
+ PACKETVER == 20190821 || \
+ PACKETVER >= 20190828
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+// 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-18bRagexe, 2019-09-25aRagexe, 2019-09-25bRagexe, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-16fRagexe, 2019-10-16gRagexe, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-07aRagexe, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-20aRagexe, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04bRagexe, 2019-12-11aRagexe, 2019-12-18bRagexe, 2019-12-24aRagexe, 2019-12-24bRagexe, 2020-01-08aRagexe, 2020-01-22cRagexe, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-06aRagexe, 2020-02-12aRagexe, 2020-02-19dRagexe, 2020-03-04aRagexe, 2020-03-18bRagexe, 2020-04-01bRagexe, 2020-04-14_6aRagexe, 2020-04-14eRagexe
+#if PACKETVER == 20190904 || \
+ PACKETVER == 20190918 || \
+ PACKETVER == 20190925 || \
+ PACKETVER == 20191002 || \
+ PACKETVER == 20191016 || \
+ PACKETVER == 20191018 || \
+ PACKETVER == 20191023 || \
+ PACKETVER == 20191030 || \
+ PACKETVER == 20191106 || \
+ PACKETVER == 20191107 || \
+ PACKETVER == 20191113 || \
+ PACKETVER == 20191120 || \
+ PACKETVER == 20191127 || \
+ PACKETVER == 20191204 || \
+ PACKETVER == 20191211 || \
+ PACKETVER == 20191218 || \
+ PACKETVER == 20191224 || \
+ PACKETVER == 20200108 || \
+ PACKETVER == 20200122 || \
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200130 || \
+ PACKETVER == 20200205 || \
+ PACKETVER == 20200206 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401 || \
+ PACKETVER == 20200414
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 31
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+
+#endif /* MAP_PACKETS_SHUFFLE_MAIN_H */
diff --git a/src/map/packets_shuffle_re.h b/src/map/packets_shuffle_re.h
new file mode 100644
index 000000000..490d517fd
--- /dev/null
+++ b/src/map/packets_shuffle_re.h
@@ -0,0 +1,9802 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//Included directly by clif.c in packet_loaddb()
+
+#ifndef MAP_PACKETS_SHUFFLE_RE_H
+#define MAP_PACKETS_SHUFFLE_RE_H
+
+#ifndef packet
+ #define packet(a,...)
+#endif
+
+/*
+ * packet syntax
+ * - packet(packet_id,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet ),...)
+ * - Example: packet(0x0072,clif->pWantToConnection,2,6,10,14,18);
+ */
+
+/* This file is autogenerated, please do not commit manual changes */
+
+
+// 2012-07-10aRagexeRE, 2012-07-12aRagexeRE
+#if PACKETVER == 20120710 || \
+ PACKETVER == 20120712
+ packet(0x0202,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0362,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0367,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07e4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0877,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0878,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a3,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0936,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0948,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0956,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2012-07-16aRagexeRE
+#if PACKETVER == 20120716
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-07-24aRagexeRE
+#if PACKETVER == 20120724
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0815,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0865,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a1,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x092b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0935,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0938,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0945,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0959,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0965,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2012-08-01aRagexeRE, 2012-08-01bRagexeRE
+#if PACKETVER == 20120801
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0438,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0873,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a2,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08aa,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0934,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0946,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2012-08-08aRagexeRE, 2012-08-08bRagexeRE, 2012-08-08cRagexeRE, 2012-08-08dRagexeRE
+#if PACKETVER == 20120808
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-08-14aRagexeRE, 2012-08-14bRagexeRE
+#if PACKETVER == 20120814
+ packet(0x0281,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0365,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0366,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07ec,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0815,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0838,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0861,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0862,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0865,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0875,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0895,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0920,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0932,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0934,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0967,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0969,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2012-08-22aRagexeRE, 2012-08-22bRagexeRE, 2012-08-22cRagexeRE
+#if PACKETVER == 20120822
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0872,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x087d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0917,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0924,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0927,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0935,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0940,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0943,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0953,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0958,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2012-08-30aRagexeRE, 2012-08-30bRagexeRE
+#if PACKETVER == 20120830
+ packet(0x022d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0838,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0926,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0945,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-09-05aRagexeRE
+#if PACKETVER == 20120905
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0817,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0895,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0897,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a6,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0917,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0918,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0944,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0945,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0950,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0959,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0967,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2012-09-11aRagexeRE
+#if PACKETVER == 20120911
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0879,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a4,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a6,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a7,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0930,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0935,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0948,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0949,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0958,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0959,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0962,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0963,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2012-09-19aRagexeRE
+#if PACKETVER == 20120919
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-09-25aRagexeRE, 2012-09-26aRagexeRE
+#if PACKETVER == 20120925 || \
+ PACKETVER == 20120926
+ packet(0x07e4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0815,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0873,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a4,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0923,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0927,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0932,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0948,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0950,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2012-10-10aRagexeRE, 2012-10-10bRagexeRE, 2012-10-11aRagexeRE
+#if PACKETVER == 20121010 || \
+ PACKETVER == 20121011
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0817,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0874,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0883,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0896,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0925,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0942,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0947,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0964,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2012-10-17aRagexeRE, 2012-10-17bRagexeRE
+#if PACKETVER == 20121017
+ packet(0x023b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0887,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0897,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0918,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0920,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0965,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-10-24aRagexeRE
+#if PACKETVER == 20121024
+ packet(0x0436,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0437,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0882,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0889,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a9,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08aa,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0931,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0942,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0954,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0955,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0965,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2012-10-31aRagexeRE
+#if PACKETVER == 20121031
+ packet(0x022d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-11-07aRagexeRE
+#if PACKETVER == 20121107
+ packet(0x0360,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0861,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0865,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0871,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0873,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0896,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0922,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0934,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0945,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0960,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0963,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0966,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2012-11-14aRagexeRE
+#if PACKETVER == 20121114
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0815,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0862,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0876,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0879,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0881,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0898,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0899,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08aa,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0935,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0938,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0949,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0965,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2012-11-21aRagexeRE
+#if PACKETVER == 20121121
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0863,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0880,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a7,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08aa,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0927,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0938,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0950,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2012-11-28aRagexeRE
+#if PACKETVER == 20121128
+ packet(0x0362,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07ec,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0861,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0867,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0888,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a8,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0921,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0931,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0945,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0950,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0953,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0960,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2012-12-05aRagexeRE, 2012-12-05bRagexeRE
+#if PACKETVER == 20121205
+ packet(0x035f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0360,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0815,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0863,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0873,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0875,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0878,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0889,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0959,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2012-12-12aRagexeRE, 2012-12-12bRagexeRE, 2012-12-12cRagexeRE
+#if PACKETVER == 20121212
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0368,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0369,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0893,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a3,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a7,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0920,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0932,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0951,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0953,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0966,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-12-18aRagexeRE, 2012-12-18bRagexeRE
+#if PACKETVER == 20121218
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0872,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2012-12-27aRagexeRE
+#if PACKETVER == 20121227
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x02c4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0860,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0870,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0872,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0888,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0890,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0894,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0896,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a6,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0917,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0920,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0932,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0933,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0943,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0947,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0958,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2013-01-03aRagexeRE
+#if PACKETVER == 20130103
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-01-09aRagexeRE
+#if PACKETVER == 20130109
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0888,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0918,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0922,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0927,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0928,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0931,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093e,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0950,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0951,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0955,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-01-15aRagexeRE, 2013-01-16aRagexeRE
+#if PACKETVER == 20130115 || \
+ PACKETVER == 20130116
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0817,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0861,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0870,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0871,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0879,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0888,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0894,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0895,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a0,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0918,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0939,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2013-01-21aRagexeRE
+#if PACKETVER == 20130121
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0802,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0874,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0893,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-01-30aRagexeRE
+#if PACKETVER == 20130130
+ packet(0x035f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0368,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0437,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0885,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0887,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a0,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a9,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0920,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0924,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0956,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2013-02-06aRagexeRE
+#if PACKETVER == 20130206
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0883,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a0,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0925,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-15aRagexeRE
+#if PACKETVER == 20130215
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0886,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-20bRagexeRE
+#if PACKETVER == 20130220
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-02-27aRagexeRE
+#if PACKETVER == 20130227
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0811,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0815,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0893,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a0,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a1,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0924,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0951,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0967,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2013-03-06aRagexeRE, 2013-03-06bRagexeRE
+#if PACKETVER == 20130306
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0367,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0368,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0802,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0898,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0926,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0934,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0936,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0943,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0945,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0946,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0951,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0960,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-03-13aRagexeRE, 2013-03-13bRagexeRE, 2013-03-13cRagexeRE
+#if PACKETVER == 20130313
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0887,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0920,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-03-20bRagexeRE, 2013-03-20cRagexeRE
+#if PACKETVER == 20130320
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0438,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0868,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0874,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0881,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0886,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0898,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0922,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0933,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0959,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2013-03-27bRagexeRE
+#if PACKETVER == 20130327
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0835,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0878,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0893,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a1,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0938,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0939,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0955,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0960,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0961,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0967,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2013-04-03aRagexeRE
+#if PACKETVER == 20130403
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0884,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0942,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0950,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-04-10aRagexeRE
+#if PACKETVER == 20130410
+ packet(0x0367,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0860,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0881,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x088c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a7,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0917,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0933,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0939,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x093d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0945,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0955,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2013-04-17aRagexeRE
+#if PACKETVER == 20130417
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0929,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x096a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2013-04-24aRagexeRE
+#if PACKETVER == 20130424
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0969,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-02aRagexeRE
+#if PACKETVER == 20130502
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0874,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0875,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0877,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a1,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a3,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2013-05-08bRagexeRE
+#if PACKETVER == 20130508
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0897,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-15aRagexeRE
+#if PACKETVER == 20130515
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0887,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a1,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0943,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0947,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0962,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-05-22aRagexeRE
+#if PACKETVER == 20130522
+ packet(0x0360,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0368,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0874,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a2,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a3,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a6,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0950,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0965,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2013-05-29aRagexeRE
+#if PACKETVER == 20130529
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0877,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0892,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0897,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a7,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0918,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0936,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0938,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0951,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0964,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2013-06-05cRagexeRE
+#if PACKETVER == 20130605
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0883,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-06-12bRagexeRE
+#if PACKETVER == 20130612
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0919,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0964,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-06-18#1aRagexeRE
+#if PACKETVER == 20130618
+ packet(0x0281,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0862,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0890,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0932,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0936,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0942,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0945,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0951,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0953,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2013-06-26_3bRagexeRE, 2013-06-26aRagexeRE
+#if PACKETVER == 20130626
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0894,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ab,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0930,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-03bRagexeRE
+#if PACKETVER == 20130703
+ packet(0x0202,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-10aRagexeRE, 2013-07-10bRagexeRE, 2013-07-10cRagexeRE, 2013-07-10dRagexeRE, 2013-07-10eRagexeRE
+#if PACKETVER == 20130710
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0880,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-07-17cRagexeRE, 2013-07-17dRagexeRE, 2013-07-17eRagexeRE
+#if PACKETVER == 20130717
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0863,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0882,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0897,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0898,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a9,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0918,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0956,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0960,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x096a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2013-07-24eRagexeRE, 2013-07-24fRagexeRE
+#if PACKETVER == 20130724
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0437,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0867,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0891,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0893,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0924,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0953,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0954,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0956,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0958,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2013-07-31cRagexeRE
+#if PACKETVER == 20130731
+ packet(0x022d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0894,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0923,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0925,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0962,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2013-08-07aRagexeRE
+#if PACKETVER == 20130807
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-08-14aRagexeRE
+#if PACKETVER == 20130814
+ packet(0x0202,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0281,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0368,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0815,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0873,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0874,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0887,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0923,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0926,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0936,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0937,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x093a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0947,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0959,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2013-08-21dRagexeRE
+#if PACKETVER == 20130821
+ packet(0x0202,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0437,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0438,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0815,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0879,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0892,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a6,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x093e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0954,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0967,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2013-08-28bRagexeRE, 2013-08-28cRagexeRE
+#if PACKETVER == 20130828
+ packet(0x023b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0361,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0817,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0873,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0889,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a3,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0917,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0919,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0944,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2013-09-04bRagexeRE
+#if PACKETVER == 20130904
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0838,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0937,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-09-11aRagexeRE, 2013-09-11bRagexeRE
+#if PACKETVER == 20130911
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0891,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0948,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2013-09-17aRagexeRE
+#if PACKETVER == 20130917
+ packet(0x035f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x083c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0863,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0895,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a8,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0918,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0923,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0934,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0959,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x096a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2013-09-25aRagexeRE, 2013-09-25bRagexeRE
+#if PACKETVER == 20130925
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0885,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-10-02aRagexeRE
+#if PACKETVER == 20131002
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-10-08bRagexeRE
+#if PACKETVER == 20131008
+ packet(0x0202,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0362,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x083c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0863,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0883,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0927,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0932,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0936,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0952,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0956,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2013-10-16aRagexeRE, 2013-10-16bRagexeRE
+#if PACKETVER == 20131016
+ packet(0x022d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0281,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0364,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x07ec,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0867,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0870,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0887,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0894,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x091e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0927,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0946,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0962,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2013-10-23aRagexeRE
+#if PACKETVER == 20131023
+ packet(0x0366,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0819,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a7,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0919,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0923,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0935,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0937,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0944,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0951,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2013-10-30aRagexeRE
+#if PACKETVER == 20131030
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-11-06aRagexeRE
+#if PACKETVER == 20131106
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0369,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0436,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0867,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0887,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0891,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0894,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0919,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0942,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0946,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0948,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0950,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0954,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0962,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0967,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2013-11-13aRagexeRE
+#if PACKETVER == 20131113
+ packet(0x0364,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0879,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0929,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0934,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0936,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0949,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0950,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0964,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0969,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2013-11-20eRagexeRE
+#if PACKETVER == 20131120
+ packet(0x0361,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0802,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0817,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a1,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0917,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0926,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0927,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0950,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0955,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2013-11-27aRagexeRE, 2013-11-27bRagexeRE
+#if PACKETVER == 20131127
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0930,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2013-12-04dRagexeRE, 2013-12-04eRagexeRE
+#if PACKETVER == 20131204
+ packet(0x0365,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0862,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0869,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0879,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0882,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a0,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a7,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0928,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x092d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0932,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0958,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0959,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0961,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0967,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2013-12-11cRagexeRE, 2013-12-11eRagexeRE
+#if PACKETVER == 20131211
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0892,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a3,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-18aRagexeRE
+#if PACKETVER == 20131218
+ packet(0x022d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ab,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0947,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-23bRagexeRE, 2013-12-23xRagexeRE
+#if PACKETVER == 20131223
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2013-12-30aRagexeRE
+#if PACKETVER == 20131230
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0365,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0369,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a9,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0926,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0943,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0949,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0968,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x096a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2014-01-08bRagexeRE, 2014-01-08cRagexeRE
+#if PACKETVER == 20140108
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-01-15cRagexeRE, 2014-01-15dRagexeRE, 2014-01-15eRagexeRE
+#if PACKETVER == 20140115
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0865,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0965,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0966,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-01-22aRagexeRE
+#if PACKETVER == 20140122
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0811,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0863,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0893,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08aa,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0925,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x092f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0942,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0950,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0952,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0955,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2014-01-29bRagexeRE
+#if PACKETVER == 20140129
+ packet(0x0281,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0885,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0924,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-02-05bRagexeRE
+#if PACKETVER == 20140205
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0938,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-02-12aRagexeRE
+#if PACKETVER == 20140212
+ packet(0x02c4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0369,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0438,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0874,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0878,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a0,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a1,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a7,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0919,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0930,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0934,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0936,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0952,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0953,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0960,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2014-02-19aRagexeRE, 2014-02-19bRagexeRE
+#if PACKETVER == 20140219
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0360,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0364,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0802,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0860,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0868,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0927,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0939,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0953,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0961,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2014-02-26aRagexeRE, 2014-02-26bRagexeRE
+#if PACKETVER == 20140226
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0887,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0894,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0921,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0931,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0941,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-03-05aRagexeRE, 2014-03-05bRagexeRE
+#if PACKETVER == 20140305
+ packet(0x0202,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0934,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-03-12bRagexeRE
+#if PACKETVER == 20140312
+ packet(0x0202,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0889,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0891,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0894,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0948,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2014-03-19aRagexeRE
+#if PACKETVER == 20140319
+ packet(0x02c4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07e4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0802,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0811,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0815,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0864,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0866,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0883,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0933,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0944,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0947,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0955,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x096a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2014-03-26cRagexeRE
+#if PACKETVER == 20140326
+ packet(0x0362,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x07ec,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x083c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0867,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0869,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08aa,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0918,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0969,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2014-04-02eRagexeRE, 2014-04-02fRagexeRE
+#if PACKETVER == 20140402
+ packet(0x023b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0360,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0364,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0867,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0868,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0882,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0883,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0890,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0896,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0920,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0926,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0933,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x093f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0944,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0950,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2014-04-09aRagexeRE
+#if PACKETVER == 20140409
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0868,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0873,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0883,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0884,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0896,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a6,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08a7,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0918,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0942,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0947,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2014-04-16aRagexeRE
+#if PACKETVER == 20140416
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-04-23aRagexeRE
+#if PACKETVER == 20140423
+ packet(0x022d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0811,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x083c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0866,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0873,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0890,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0895,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0896,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a8,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x091a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-04-30aRagexeRE
+#if PACKETVER == 20140430
+ packet(0x023b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0860,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0871,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0884,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0899,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a1,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0956,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2014-05-08bRagexeRE
+#if PACKETVER == 20140508
+ packet(0x022d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0927,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0932,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-05-14bRagexeRE, 2014-05-14cRagexeRE
+#if PACKETVER == 20140514
+ packet(0x0437,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0817,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0865,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0876,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0877,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0886,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a5,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0921,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0925,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0965,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2014-05-21aRagexeRE
+#if PACKETVER == 20140521
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0968,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-05-28aRagexeRE
+#if PACKETVER == 20140528
+ packet(0x0202,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0862,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0875,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0877,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a8,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0930,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0963,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0966,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2014-06-05aRagexeRE
+#if PACKETVER == 20140605
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0369,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0921,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-06-11bRagexeRE
+#if PACKETVER == 20140611
+ packet(0x0364,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0838,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0864,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0867,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0874,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0878,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0891,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0893,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0894,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a1,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0924,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0950,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0951,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0952,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0957,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0958,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0965,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2014-06-18cRagexeRE
+#if PACKETVER == 20140618
+ packet(0x085d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0860,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0861,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0878,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0884,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0885,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0886,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0890,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0939,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0945,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0967,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-06-25aRagexeRE
+#if PACKETVER == 20140625
+ packet(0x0202,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x023b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0815,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0817,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0861,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0886,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0897,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a1,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a2,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0923,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0928,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0959,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0968,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0969,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-07-02aRagexeRE
+#if PACKETVER == 20140702
+ packet(0x022d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0438,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x07e4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a0,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a2,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0925,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0933,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-07-09aRagexeRE
+#if PACKETVER == 20140709
+ packet(0x0364,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0869,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0877,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0879,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0887,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0888,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0894,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0897,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0898,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0925,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0931,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0934,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0939,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0961,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2014-07-16aRagexeRE
+#if PACKETVER == 20140716
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0871,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0881,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a4,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0918,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0926,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0938,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0952,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0959,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2014-07-23aRagexeRE, 2014-07-23bRagexeRE
+#if PACKETVER == 20140723
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0436,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0819,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x087d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0888,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0891,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0896,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ad,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0927,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0934,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0935,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0939,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0945,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0947,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0948,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0960,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2014-07-30bRagexeRE
+#if PACKETVER == 20140730
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0367,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0437,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0815,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0889,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0892,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0924,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0934,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-08-06aRagexeRE
+#if PACKETVER == 20140806
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0948,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-08-13aRagexeRE
+#if PACKETVER == 20140813
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0868,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0878,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0897,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0967,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-08-20aRagexeRE
+#if PACKETVER == 20140820
+ packet(0x035f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0861,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0869,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0872,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0876,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0899,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a7,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0937,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x093a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0951,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0952,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0956,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-08-27aRagexeRE
+#if PACKETVER == 20140827
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0943,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-09-03aRagexeRE
+#if PACKETVER == 20140903
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0943,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0945,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-09-17cRagexeRE
+#if PACKETVER == 20140917
+ packet(0x022d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0364,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0365,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0367,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0895,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0897,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0898,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a8,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0919,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x091e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0949,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0951,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x095e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0966,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-09-24bRagexeRE, 2014-09-24cRagexeRE
+#if PACKETVER == 20140924
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0864,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0886,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0894,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0898,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a5,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a7,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0918,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0925,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0926,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0928,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0949,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0952,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2014-10-01bRagexeRE, 2014-10-01cRagexeRE
+#if PACKETVER == 20141001
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0885,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0952,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2014-10-08bRagexeRE, 2014-10-08cRagexeRE
+#if PACKETVER == 20141008
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-15bRagexeRE, 2014-10-16aRagexeRE
+#if PACKETVER == 20141015 || \
+ PACKETVER == 20141016
+ packet(0x022d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0922,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0967,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-22aRagexeRE
+#if PACKETVER == 20141022
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0878,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0896,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0899,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08aa,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ab,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-10-29aRagexeRE
+#if PACKETVER == 20141029
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-11-05aRagexeRE, 2014-11-05bRagexeRE
+#if PACKETVER == 20141105
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0864,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0865,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0874,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0879,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0887,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0892,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0950,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x095f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0968,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2014-11-12aRagexeRE
+#if PACKETVER == 20141112
+ packet(0x0362,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0438,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0885,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a0,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a1,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08ab,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0919,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0926,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0929,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0943,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0960,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0962,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2014-11-19bRagexeRE
+#if PACKETVER == 20141119
+ packet(0x0202,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0866,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0873,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0887,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0895,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a8,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0918,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0920,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0921,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0938,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0940,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0963,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2014-11-26aRagexeRE, 2014-11-26bRagexeRE, 2014-11-26cRagexeRE, 2014-11-26dRagexeRE, 2014-11-26eRagexeRE
+#if PACKETVER == 20141126
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0871,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0920,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0942,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-12-03aRagexeRE
+#if PACKETVER == 20141203
+ packet(0x0202,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0281,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0861,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0880,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0889,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a5,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08aa,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0936,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0957,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0962,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2014-12-10cRagexeRE
+#if PACKETVER == 20141210
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0885,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08ac,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0917,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0954,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0958,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0967,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2014-12-17aRagexeRE
+#if PACKETVER == 20141217
+ packet(0x0360,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0879,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0883,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0889,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x088e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a1,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ab,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0919,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0924,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0930,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0932,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0933,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0939,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0944,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0945,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0948,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0960,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2014-12-23cRagexeRE
+#if PACKETVER == 20141223
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0438,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0835,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0870,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a3,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08ac,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0932,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0945,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0946,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0949,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0953,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2014-12-31aRagexeRE
+#if PACKETVER == 20141231
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-07aRagexeRE
+#if PACKETVER == 20150107
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0895,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-14aRagexeRE
+#if PACKETVER == 20150114
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0899,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0955,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0957,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-21aRagexeRE, 2015-01-21bRagexeRE
+#if PACKETVER == 20150121
+ packet(0x0281,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0919,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0955,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0959,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-01-28aRagexeRE
+#if PACKETVER == 20150128
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x023b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0838,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0864,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0874,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0875,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0888,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0929,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0963,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0968,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2015-02-04cRagexeRE
+#if PACKETVER == 20150204
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0966,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-02-11aRagexeRE
+#if PACKETVER == 20150211
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0368,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0369,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x07e4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0819,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0862,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0873,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0882,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0883,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0885,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0886,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08aa,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0919,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2015-02-17aRagexeRE
+#if PACKETVER == 20150217
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-02-25aRagexeRE, 2015-02-25bRagexeRE, 2015-02-25cRagexeRE, 2015-02-25dRagexeRE, 2015-02-25eRagexeRE, 2015-02-26aRagexeRE
+#if PACKETVER == 20150225 || \
+ PACKETVER == 20150226
+ packet(0x02c4,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0948,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0955,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-03-04aRagexeRE, 2015-03-04bRagexeRE
+#if PACKETVER == 20150304
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0879,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0892,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0947,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-03-11aRagexeRE, 2015-03-11bRagexeRE
+#if PACKETVER == 20150311
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0838,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0896,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a5,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a6,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0928,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0943,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0957,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0958,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0963,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0964,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2015-03-18aRagexeRE, 2015-03-18bRagexeRE, 2015-03-18cRagexeRE
+#if PACKETVER == 20150318
+ packet(0x0202,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x023b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0802,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0862,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0885,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0889,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0928,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0936,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0951,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0958,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0960,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-03-25bRagexeRE, 2015-03-25cRagexeRE
+#if PACKETVER == 20150325
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0365,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0883,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0897,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a7,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0919,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0931,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0932,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0938,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0954,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0969,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+#endif
+
+// 2015-04-01bRagexeRE
+#if PACKETVER == 20150401
+ packet(0x0362,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0367,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0437,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x083c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0875,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0895,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0898,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a5,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0924,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0938,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0939,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0949,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0953,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0964,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-04-08aRagexeRE
+#if PACKETVER == 20150408
+ packet(0x0819,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0865,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0868,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x087f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0891,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0922,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0946,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0957,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0959,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0963,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2015-04-15aRagexeRE
+#if PACKETVER == 20150415
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0364,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0368,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0802,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0867,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0869,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0880,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0898,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a0,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x093c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0941,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0946,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0953,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-04-22aRagexeRE
+#if PACKETVER == 20150422
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0955,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-04-29aRagexeRE
+#if PACKETVER == 20150429
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0886,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0894,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0899,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a8,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ad,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0943,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-07bRagexeRE
+#if PACKETVER == 20150507
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0924,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0941,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0942,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0953,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0955,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-13aRagexeRE
+#if PACKETVER == 20150513
+ packet(0x022d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x02c4,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0883,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a8,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0923,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0924,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0960,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-05-20aRagexeRE
+#if PACKETVER == 20150520
+ packet(0x0202,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0868,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0880,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0882,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a2,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0924,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0931,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0936,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x093d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0945,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0960,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-05-27aRagexeRE
+#if PACKETVER == 20150527
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x083c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-06-03bRagexeRE
+#if PACKETVER == 20150603
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0437,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0864,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0867,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0873,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0881,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a1,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ad,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0922,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0960,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0969,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x096a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2015-06-10aRagexeRE
+#if PACKETVER == 20150610
+ packet(0x022d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0438,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07e4,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0872,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0877,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0885,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0897,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a0,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ac,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0925,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0932,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0940,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0946,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0949,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0957,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0964,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-06-17aRagexeRE, 2015-06-18aRagexeRE
+#if PACKETVER == 20150617 || \
+ PACKETVER == 20150618
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0362,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0365,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0870,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-06-24aRagexeRE
+#if PACKETVER == 20150624
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0365,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0940,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0966,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-07-01bRagexeRE
+#if PACKETVER == 20150701
+ packet(0x023b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x07e4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0883,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0893,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a0,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a4,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a5,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a6,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ad,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0919,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0923,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0928,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0954,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0958,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0968,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-07-08bRagexeRE, 2015-07-08cRagexeRE, 2015-07-08dRagexeRE
+#if PACKETVER == 20150708
+ packet(0x022d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0872,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-07-15aRagexeRE
+#if PACKETVER == 20150715
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0362,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0436,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0437,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0835,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0873,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0895,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0896,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0897,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0899,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08ac,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0917,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0944,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0956,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0965,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2015-07-22bRagexeRE
+#if PACKETVER == 20150722
+ packet(0x023b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0361,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0368,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0811,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0880,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0884,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0899,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0919,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0925,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2015-07-29aRagexeRE
+#if PACKETVER == 20150729
+ packet(0x0437,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0870,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0880,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0886,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ac,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ad,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0920,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x093a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0955,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0961,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2015-08-05dRagexeRE
+#if PACKETVER == 20150805
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-12aRagexeRE
+#if PACKETVER == 20150812
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-19aRagexeRE, 2015-08-19bRagexeRE
+#if PACKETVER == 20150819
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x022d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0281,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0865,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0888,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0919,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0927,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0961,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0967,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-08-26aRagexeRE, 2015-08-26bRagexeRE
+#if PACKETVER == 20150826
+ packet(0x0362,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0436,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x07ec,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0819,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0861,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x087b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a0,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a1,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0924,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0928,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0945,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0951,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0959,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0968,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0969,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2015-09-02aRagexeRE
+#if PACKETVER == 20150902
+ packet(0x023b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0360,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0367,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0802,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x083c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0863,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0886,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0887,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x088d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0892,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0897,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0899,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a9,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0923,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0941,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0947,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0953,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2015-09-09aRagexeRE
+#if PACKETVER == 20150909
+ packet(0x023b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0361,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0437,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0871,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0886,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0895,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0940,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0941,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0962,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2015-09-16cRagexeRE
+#if PACKETVER == 20150916
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0817,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0869,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0873,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0877,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0920,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0924,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0936,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0942,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0948,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0960,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0969,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-09-23bRagexeRE, 2015-09-23eRagexeRE, 2015-09-23fRagexeRE
+#if PACKETVER == 20150923
+ packet(0x0361,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0817,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0864,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0879,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0892,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a6,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0936,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0951,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2015-10-01bRagexeRE
+#if PACKETVER == 20151001
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0960,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-07aRagexeRE
+#if PACKETVER == 20151007
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0961,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-14bRagexeRE
+#if PACKETVER == 20151014
+ packet(0x0202,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0838,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0863,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0874,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0881,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0883,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0884,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0889,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x089f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08aa,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0934,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0944,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x094f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0956,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+#endif
+
+// 2015-10-21aRagexeRE, 2015-10-22aRagexeRE
+#if PACKETVER == 20151021 || \
+ PACKETVER == 20151022
+ packet(0x023b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-10-28bRagexeRE, 2015-10-28bRagexeRE_2, 2015-10-28cRagexeRE, 2015-10-28dRagexeRE, 2015-10-29aRagexeRE
+#if PACKETVER == 20151028 || \
+ PACKETVER == 20151029
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-04aRagexeRE
+#if PACKETVER == 20151104
+ packet(0x023b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0363,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0886,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a5,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0939,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093a,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2015-11-11aRagexeRE
+#if PACKETVER == 20151111
+ packet(0x02c4,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0862,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0885,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0942,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0967,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0969,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-18aRagexeRE
+#if PACKETVER == 20151118
+ packet(0x022d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088b,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0921,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0925,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0943,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095c,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-11-25bRagexeRE, 2015-11-25cRagexeRE, 2015-11-25dRagexeRE
+#if PACKETVER == 20151125
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0366,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0438,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0802,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0838,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0863,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0883,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0884,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a9,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0939,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0951,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0959,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2015-12-02bRagexeRE
+#if PACKETVER == 20151202
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2015-12-09aRagexeRE
+#if PACKETVER == 20151209
+ packet(0x0365,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07ec,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0811,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0819,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085b,clif->pStoragePassword,2,4,20); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0861,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0866,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0894,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a1,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0920,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0932,clif->pItemListWindowSelected,2,4,8,12); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0948,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094a,clif->pPartyBookingRegisterReq,2,4,6); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0956,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0961,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0964,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+#endif
+
+// 2015-12-16aRagexeRE
+#if PACKETVER == 20151216
+ packet(0x022d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0361,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0436,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0865,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0870,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0885,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a2,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0954,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0966,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0968,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2015-12-23bRagexeRE
+#if PACKETVER == 20151223
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0362,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0802,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0815,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0864,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0866,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0875,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0876,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0881,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0884,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0886,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08aa,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0918,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0923,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0924,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0965,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0967,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2015-12-30aRagexeRE
+#if PACKETVER == 20151230
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07ec,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0861,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0869,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x088e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0897,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0923,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0949,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-06aRagexeRE
+#if PACKETVER == 20160106
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0861,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0878,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0891,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-13aRagexeRE, 2016-01-13bRagexeRE, 2016-01-13bRagexeRE_2, 2016-01-13cRagexeRE
+#if PACKETVER == 20160113
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x023b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x035f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0864,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0888,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0893,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a0,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a6,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08aa,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0919,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0924,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0930,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0932,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0941,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0967,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2016-01-20aRagexeRE
+#if PACKETVER == 20160120
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0865,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-01-27aRagexeRE, 2016-01-27aRagexeRE_2, 2016-01-27bRagexeRE
+#if PACKETVER == 20160127
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0922,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-03aRagexeRE
+#if PACKETVER == 20160203
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0835,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0940,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0947,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0954,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-11aRagexeRE
+#if PACKETVER == 20160211
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0870,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0886,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-02-17aRagexeRE, 2016-02-17bRagexeRE, 2016-02-17bRagexeRE_2, 2016-02-17cRagexeRE
+#if PACKETVER == 20160217
+ packet(0x0202,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x023b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0362,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0365,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0864,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0870,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0873,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x087a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a0,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a9,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ac,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ad,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x091d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0920,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0926,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0941,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0966,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0969,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2016-02-24aRagexeRE, 2016-02-24bRagexeRE
+#if PACKETVER == 20160224
+ packet(0x022d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0364,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0436,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0861,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0884,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0888,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0929,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0936,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0938,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-02bRagexeRE
+#if PACKETVER == 20160302
+ packet(0x022d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0367,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0802,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0819,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0864,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0865,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0867,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0868,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0883,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a6,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a9,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0945,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094e,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0950,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0967,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0968,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2016-03-09aRagexeRE
+#if PACKETVER == 20160309
+ packet(0x023b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0281,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0819,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0838,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x083c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0920,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0922,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0929,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0932,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0956,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2016-03-16aRagexeRE
+#if PACKETVER == 20160316
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0922,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-23aRagexeRE, 2016-03-23bRagexeRE
+#if PACKETVER == 20160323
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0869,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0878,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0883,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0896,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0926,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-03-30aRagexeRE
+#if PACKETVER == 20160330
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0365,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0889,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0925,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0930,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0939,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x093b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-06aRagexeRE
+#if PACKETVER == 20160406
+ packet(0x0364,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x07e4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0869,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0877,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0879,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0884,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0892,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0898,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a9,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ac,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0927,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0934,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0949,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0953,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2016-04-14aRagexeRE, 2016-04-14bRagexeRE
+#if PACKETVER == 20160414
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0363,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0880,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0918,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0922,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0931,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0934,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0945,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0953,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-20aRagexeRE
+#if PACKETVER == 20160420
+ packet(0x022d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x035f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0870,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0872,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0874,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a5,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0935,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-04-27aRagexeRE
+#if PACKETVER == 20160427
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0835,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-04aRagexeRE
+#if PACKETVER == 20160504
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0365,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x083c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0884,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0890,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0898,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08ad,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0918,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0924,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0940,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0941,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0948,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0952,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0969,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2016-05-11aRagexeRE, 2016-05-11bRagexeRE
+#if PACKETVER == 20160511
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0918,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0920,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-18aRagexeRE
+#if PACKETVER == 20160518
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0874,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a9,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0928,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-05-25aRagexeRE
+#if PACKETVER == 20160525
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0867,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x092c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0945,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-01aRagexeRE
+#if PACKETVER == 20160601
+ packet(0x0202,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0870,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x088f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0895,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ac,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0924,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0961,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-08aRagexeRE, 2016-06-08bRagexeRE
+#if PACKETVER == 20160608
+ packet(0x022d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0437,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07ec,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0802,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0889,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0899,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a6,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-06-15aRagexeRE
+#if PACKETVER == 20160615
+ packet(0x0281,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0369,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x083c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0866,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0870,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0887,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0888,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x092f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0947,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0948,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0954,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0958,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0961,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2016-06-22aRagexeRE
+#if PACKETVER == 20160622
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07e4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0867,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0880,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0887,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0890,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0891,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0892,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x089a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a2,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a8,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0936,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0959,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0965,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0969,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+#endif
+
+// 2016-06-29aRagexeRE, 2016-06-30aRagexeRE
+#if PACKETVER == 20160629 || \
+ PACKETVER == 20160630
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x022d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0363,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0861,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0863,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0867,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x086b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0881,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0893,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0922,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0925,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0926,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0946,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0948,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0957,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0968,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0969,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2016-07-06cRagexeRE
+#if PACKETVER == 20160706
+ packet(0x0362,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x085f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0860,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0869,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x086b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0884,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0899,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a5,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a8,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0918,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x091b,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0924,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0926,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0927,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0929,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0939,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x093d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0945,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0957,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0958,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2016-07-13aRagexeRE, 2016-07-13bRagexeRE
+#if PACKETVER == 20160713
+ packet(0x022d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0363,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0838,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0860,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0869,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0877,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0883,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0892,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x089a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0921,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0922,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0931,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0944,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0945,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0947,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0957,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-07-20aRagexeRE, 2016-07-20bRagexeRE
+#if PACKETVER == 20160720
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0363,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0365,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x07e4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0838,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x085b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0883,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a0,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08aa,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0917,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x091c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093b,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0946,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0953,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0960,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2016-07-27aRagexeRE, 2016-07-27bRagexeRE
+#if PACKETVER == 20160727
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x023b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0436,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x07ec,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0866,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0868,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0869,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0874,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0877,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0887,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0891,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a4,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a7,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0936,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0949,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0951,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0966,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2016-08-03bRagexeRE
+#if PACKETVER == 20160803
+ packet(0x0364,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0881,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0886,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0887,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0888,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0891,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0895,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08a1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0929,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0930,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0932,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0934,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0937,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x093a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x093e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0952,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0955,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0956,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0959,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2016-08-10aRagexeRE
+#if PACKETVER == 20160810
+ packet(0x0361,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0819,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x085d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0860,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0875,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0879,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0885,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0888,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0890,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a9,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0943,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0967,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-08-17aRagexeRE
+#if PACKETVER == 20160817
+ packet(0x0364,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x07e4,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0819,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x083c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x085c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0867,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0875,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0886,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0891,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a5,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a9,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08ab,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ac,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0929,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0930,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0939,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0960,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0963,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-08-24aRagexeRE
+#if PACKETVER == 20160824
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-08-31aRagexeRE, 2016-08-31bRagexeRE
+#if PACKETVER == 20160831
+ packet(0x022d,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0835,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0874,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x087c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08a8,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a9,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0938,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0946,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0950,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0954,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0957,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0960,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0964,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0967,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2016-09-07aRagexeRE
+#if PACKETVER == 20160907
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x091c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-09-13aRagexeRE
+#if PACKETVER == 20160913
+ packet(0x0361,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0817,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0865,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0874,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0875,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0887,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0889,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x088e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0891,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0935,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0949,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0950,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0952,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0963,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0968,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+#endif
+
+// 2016-09-21bRagexeRE
+#if PACKETVER == 20160921
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-09-28cRagexeRE, 2016-09-28dRagexeRE
+#if PACKETVER == 20160928
+ packet(0x0202,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0811,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0864,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0872,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0878,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0889,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x088e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0897,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x089a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a9,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0919,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0927,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0944,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0953,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0957,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+#endif
+
+// 2016-10-05aRagexeRE
+#if PACKETVER == 20161005
+ packet(0x0202,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0838,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0863,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0886,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0891,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08ac,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0918,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0919,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x092b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0931,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0932,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0942,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0944,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0945,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0952,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x095b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0967,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2016-10-12aRagexeRE
+#if PACKETVER == 20161012
+ packet(0x023b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0365,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0369,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x07ec,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0819,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x085e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0863,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0868,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0872,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0875,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0880,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0893,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0937,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0939,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0943,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0944,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0962,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0966,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2016-10-19aRagexeRE
+#if PACKETVER == 20161019
+ packet(0x022d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0361,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0889,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0892,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0963,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-10-26bRagexeRE, 2016-10-26cRagexeRE
+#if PACKETVER == 20161026
+ packet(0x0363,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085f,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0862,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x086a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x087c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0886,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0891,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0894,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0898,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0926,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x092e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0930,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0953,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x095e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0962,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-11-02aRagexeRE, 2016-11-03aRagexeRE
+#if PACKETVER == 20161102 || \
+ PACKETVER == 20161103
+ packet(0x0361,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0367,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0802,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x083c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0869,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0874,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0886,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a2,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08aa,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0922,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0925,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0936,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0946,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0949,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x095e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0964,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0965,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0966,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2016-11-09aRagexeRE, 2016-11-09bRagexeRE, 2016-11-09cRagexeRE, 2016-11-09dRagexeRE
+#if PACKETVER == 20161109
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0362,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0366,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0870,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0876,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0881,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x088e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0898,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a7,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0927,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0937,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0954,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0956,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-11-16bRagexeRE, 2016-11-16cRagexeRE
+#if PACKETVER == 20161116
+ packet(0x0368,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0369,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0835,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x085f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0885,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x088d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0890,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a2,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08ac,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0920,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0925,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0931,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x094a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0967,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+#endif
+
+// 2016-11-23aRagexeRE
+#if PACKETVER == 20161123
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0362,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0437,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0861,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0866,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x086f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0880,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0882,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a9,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08aa,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0926,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2016-11-30aRagexeRE, 2016-11-30bRagexeRE
+#if PACKETVER == 20161130
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0931,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0959,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-07cRagexeRE, 2016-12-07dRagexeRE, 2016-12-07eRagexeRE
+#if PACKETVER == 20161207
+ packet(0x023b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0886,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a2,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ad,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0943,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0965,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-14bRagexeRE, 2016-12-14cRagexeRE
+#if PACKETVER == 20161214
+ packet(0x022d,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0281,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x02c4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0436,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0862,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0887,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0899,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2016-12-21aRagexeRE, 2016-12-21bRagexeRE, 2016-12-21cRagexeRE, 2016-12-21dRagexeRE
+#if PACKETVER == 20161221
+ packet(0x035f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0438,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0817,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x085b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0866,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0876,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0881,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08aa,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0926,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x092e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0930,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0943,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0964,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0965,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2016-12-28aRagexeRE
+#if PACKETVER == 20161228
+ packet(0x0362,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x085a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0865,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x086a,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0870,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0871,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0886,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0889,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a3,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a5,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ab,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ac,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08ad,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x092c,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0934,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0935,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0938,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x093d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0944,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2017-01-04bRagexeRE
+#if PACKETVER == 20170104
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x085a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0896,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-01-11aRagexeRE
+#if PACKETVER == 20170111
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a1,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a3,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a6,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0961,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0969,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-01-18aRagexeRE
+#if PACKETVER == 20170118
+ packet(0x022d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0364,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0865,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0927,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0962,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2017-01-25aRagexeRE
+#if PACKETVER == 20170125
+ packet(0x0438,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0877,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0879,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0881,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0894,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0895,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0920,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0929,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x092b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0930,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0943,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0944,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0965,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0968,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2017-02-01aRagexeRE
+#if PACKETVER == 20170201
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0815,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0875,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0879,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0881,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0886,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a4,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0919,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0920,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0938,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0940,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x094c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0969,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-08aRagexeRE, 2017-02-08bRagexeRE
+#if PACKETVER == 20170208
+ packet(0x02c4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0860,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0892,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a1,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ac,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0921,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0923,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0932,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0937,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-15aRagexeRE
+#if PACKETVER == 20170215
+ packet(0x02c4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0876,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087c,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087e,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0883,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x088b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x088c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0890,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a8,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0925,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x092d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0942,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0969,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+#endif
+
+// 2017-02-22aRagexeRE
+#if PACKETVER == 20170222
+ packet(0x0202,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0866,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0870,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0871,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0877,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0894,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a3,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a8,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0943,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0962,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-02-28aRagexeRE
+#if PACKETVER == 20170228
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0360,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0819,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x085e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0863,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086b,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0873,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0874,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0876,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0883,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0884,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0889,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0893,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x089e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a0,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a7,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091f,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0944,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0948,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0955,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2017-03-08bRagexeRE
+#if PACKETVER == 20170308
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-03-15cRagexeRE
+#if PACKETVER == 20170315
+ packet(0x02c4,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x035f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0360,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0366,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0436,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x07ec,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0863,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x086a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0884,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x088b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x091d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0920,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0922,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x094a,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x094e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0950,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0952,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2017-03-22aRagexeRE, 2017-03-22bRagexeRE
+#if PACKETVER == 20170322
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x091a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-03-29cRagexeRE, 2017-03-29dRagexeRE
+#if PACKETVER == 20170329
+ packet(0x0281,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0888,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a8,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0917,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0926,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0929,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x092e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0937,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0949,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-04-05bRagexeRE, 2017-04-05cRagexeRE
+#if PACKETVER == 20170405
+ packet(0x022d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0281,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0860,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0864,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0865,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0893,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a5,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094c,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0964,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-04-12aRagexeRE
+#if PACKETVER == 20170412
+ packet(0x023b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0365,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0863,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0869,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0879,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0890,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0893,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0898,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x089a,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08a1,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x091e,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0929,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0938,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0942,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0945,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0949,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x094f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0952,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0959,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x095d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2017-04-19bRagexeRE
+#if PACKETVER == 20170419
+ packet(0x0811,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0819,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0838,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0862,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0868,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0872,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0881,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0897,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0898,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0920,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0922,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0930,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0931,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0935,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0942,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x095d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0963,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0965,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+#endif
+
+// 2017-04-26dRagexeRE
+#if PACKETVER == 20170426
+ packet(0x0281,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0866,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0887,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0899,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0927,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0958,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0963,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-05-02dRagexeRE
+#if PACKETVER == 20170502
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0894,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093c,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0950,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-05-17aRagexeRE, 2017-05-17bRagexeRE
+#if PACKETVER == 20170517
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0367,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0815,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0817,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0868,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0875,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087b,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0894,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0896,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x089f,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a2,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a8,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08aa,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x091b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x093b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0960,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0964,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2017-05-24aRagexeRE
+#if PACKETVER == 20170524
+ packet(0x0364,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0860,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0864,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0866,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0868,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x086d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0873,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0874,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0882,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0894,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089c,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a1,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0923,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0925,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0934,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0958,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x095b,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0964,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0967,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0968,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2017-05-31aRagexeRE
+#if PACKETVER == 20170531
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0369,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x07ec,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0819,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x085f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0873,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0878,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0894,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08ac,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ad,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0933,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0940,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0945,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0963,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0968,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-06-07bRagexeRE, 2017-06-07cRagexeRE
+#if PACKETVER == 20170607
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0364,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x07e4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x085e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0862,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0871,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0873,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0875,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0897,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x089d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a9,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ab,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0917,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0918,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0919,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0925,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0927,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0931,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0934,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0938,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x093d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0944,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0949,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2017-06-14bRagexeRE
+#if PACKETVER == 20170614
+ packet(0x023b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0361,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0364,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0367,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0838,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x083c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0860,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0866,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0867,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x086b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x086c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0877,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0889,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a2,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ad,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0928,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0936,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0944,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0957,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0963,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2017-06-21aRagexeRE
+#if PACKETVER == 20170621
+ packet(0x0202,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0365,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0802,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0885,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0957,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x095c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0961,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-06-28bRagexeRE
+#if PACKETVER == 20170628
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0863,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-05aRagexeRE
+#if PACKETVER == 20170705
+ packet(0x0202,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x02c4,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0886,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x088d,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x092f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0930,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0932,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0934,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x094c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-12bRagexeRE
+#if PACKETVER == 20170712
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0944,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-07-19aRagexeRE
+#if PACKETVER == 20170719
+ packet(0x022d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0367,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0368,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0369,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x07e4,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085a,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x087d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0881,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0882,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0891,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0898,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089d,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a6,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a8,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091b,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x092c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x092e,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x092f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x093d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0944,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0966,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+#endif
+
+// 2017-07-26cRagexeRE
+#if PACKETVER == 20170726
+ packet(0x0363,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0369,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0438,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0838,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0873,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0874,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0878,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a3,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a7,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08aa,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ab,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08ac,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x091e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0921,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0923,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0943,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x094f,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0950,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0952,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0954,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0963,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-08-01aRagexeRE
+#if PACKETVER == 20170801
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0281,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0362,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095a,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-08-09cRagexeRE
+#if PACKETVER == 20170809
+ packet(0x022d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0281,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0364,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0366,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0367,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x07e4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0802,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0868,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x086e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086f,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0876,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0880,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0892,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0895,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a3,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a6,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0918,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0921,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x092b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0931,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0939,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0940,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2017-08-16cRagexeRE, 2017-08-16dRagexeRE
+#if PACKETVER == 20170816
+ packet(0x022d,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x035f,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0361,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0362,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0438,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x085a,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0862,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0864,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x087e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0881,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0882,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0884,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0888,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0889,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x08a3,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a9,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08ac,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x091c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0921,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0925,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x092c,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x093a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0940,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0950,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0960,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+#endif
+
+// 2017-08-23aRagexeRE
+#if PACKETVER == 20170823
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x086d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08ac,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-08-30aRagexeRE, 2017-08-30bRagexeRE
+#if PACKETVER == 20170830
+ packet(0x0281,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x02c4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0364,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0865,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x086a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0884,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0888,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0897,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0899,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089e,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0921,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0925,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x092e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0939,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0940,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0942,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0943,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0947,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0951,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0959,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-09-06cRagexeRE
+#if PACKETVER == 20170906
+ packet(0x0202,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0281,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x02c4,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0866,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a2,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a7,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x091a,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0953,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-09-13bRagexeRE
+#if PACKETVER == 20170913
+ packet(0x0281,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x035f,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0437,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x07e4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0817,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0835,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0860,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0865,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0866,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x088c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0890,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0891,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0892,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a7,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08aa,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08ab,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08ac,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ad,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0920,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0923,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0925,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0927,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x095a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095c,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+#endif
+
+// 2017-09-20bRagexeRE
+#if PACKETVER == 20170920
+ packet(0x0369,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0436,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x085a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0861,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0862,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0864,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0865,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x086c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0874,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0875,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0889,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x088e,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x089b,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0919,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x091e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0921,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0923,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0926,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0937,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0939,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0945,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x094c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0961,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0966,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x096a,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+#endif
+
+// 2017-09-27bRagexeRE, 2017-09-27dRagexeRE
+#if PACKETVER == 20170927
+ packet(0x02c4,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x035f,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0361,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0362,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0366,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x085c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0875,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x087e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x088b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0899,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x089a,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08a3,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a5,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a6,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08ad,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x091e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0922,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0923,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0927,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x093b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0942,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0945,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-10-02cRagexeRE
+#if PACKETVER == 20171002
+ packet(0x022d,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0885,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0928,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x092d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093b,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x093e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0943,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-11aRagexeRE, 2017-10-11bRagexeRE
+#if PACKETVER == 20171011
+ packet(0x023b,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0882,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0950,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0954,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-18aRagexeRE
+#if PACKETVER == 20171018
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0363,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x087a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089a,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a6,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0938,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0944,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x094a,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x094f,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-10-25bRagexeRE, 2017-10-25cRagexeRE, 2017-10-25dRagexeRE, 2017-10-25eRagexeRE
+#if PACKETVER == 20171025
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a2,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-01bRagexeRE
+#if PACKETVER == 20171101
+ packet(0x022d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0369,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0438,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0835,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x085b,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0860,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0872,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0876,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0886,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0890,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0895,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0899,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x089b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x089c,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a0,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x08ab,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08ad,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x091b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0939,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094a,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x094d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0952,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0957,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x095a,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0962,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0966,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-11-08bRagexeRE
+#if PACKETVER == 20171108
+ packet(0x0202,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x07e4,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0815,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0819,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0838,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x085d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0863,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0878,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x087e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0884,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0896,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x08a2,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x08a9,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08ad,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0941,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0945,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0947,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0949,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x094e,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0958,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x095a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0963,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0965,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0967,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-11-15aRagexeRE
+#if PACKETVER == 20171115
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0365,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x086d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086f,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x087e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0883,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0890,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0898,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0926,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x095a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-22bRagexeRE
+#if PACKETVER == 20171122
+ packet(0x0281,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x02c4,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x035f,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0838,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x083c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x085b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0862,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0867,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0877,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0885,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0890,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0891,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0893,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0897,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0898,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x089a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x089e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x08a6,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x08a9,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091e,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0920,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0923,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0934,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0945,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0947,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0962,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0968,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+#endif
+
+// 2017-11-29aRagexeRE
+#if PACKETVER == 20171129
+ packet(0x02c4,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0363,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0365,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0862,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x086d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0878,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x08a5,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x094b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0953,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0966,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-06aRagexeRE
+#if PACKETVER == 20171206
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0867,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0885,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0888,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0897,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x089d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08a2,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x08a4,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0923,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0936,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0942,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0958,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0961,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-13bRagexeRE
+#if PACKETVER == 20171213
+ packet(0x0202,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0890,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0957,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-20aRagexeRE
+#if PACKETVER == 20171220
+ packet(0x0281,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0366,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0369,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0436,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0437,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x085e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0861,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0872,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0873,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0880,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0882,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0885,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0899,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x089e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a7,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x091b,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091e,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0924,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0929,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0933,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x093e,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0941,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0946,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x094e,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0951,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0957,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0964,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+#endif
+
+// 2017-12-27aRagexeRE
+#if PACKETVER == 20171227
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x087d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0888,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a0,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a5,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092c,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x092e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0938,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0945,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0969,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+#endif
+
+// 2018-01-03aRagexeRE, 2018-01-03bRagexeRE
+#if PACKETVER == 20180103
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0363,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0865,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086b,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0872,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0876,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0879,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088e,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x089f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x08a9,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ab,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x08ac,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091d,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0922,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0927,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0935,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0938,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0941,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0946,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0948,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094e,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x095f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0960,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+#endif
+
+// 2018-01-17aRagexeRE
+#if PACKETVER == 20180117
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0875,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-01-24bRagexeRE
+#if PACKETVER == 20180124
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0868,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x086a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x086f,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x087a,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0888,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0890,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0919,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0940,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0946,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x094d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0958,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-07bRagexeRE
+#if PACKETVER == 20180207
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0360,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0870,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0940,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0950,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-13aRagexeRE
+#if PACKETVER == 20180213
+ packet(0x0369,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0802,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0817,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x085a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x086f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0874,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0875,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0878,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x087b,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0882,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x088c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0892,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0898,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x089c,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x08a3,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x08a5,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08a9,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08ad,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0917,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0922,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0924,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0926,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0933,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0936,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x093c,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0943,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0955,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0962,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2018-02-21aRagexeRE, 2018-02-21bRagexeRE
+#if PACKETVER == 20180221
+ packet(0x0202,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0366,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0436,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0838,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0867,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0871,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0876,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0879,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x087d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0880,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0881,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0883,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x088f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0891,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0897,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x089d,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0917,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x091e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0929,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x093d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x094b,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x094e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0964,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x096a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2018-03-07bRagexeRE
+#if PACKETVER == 20180307
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x035f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0437,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x07e4,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0861,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0862,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0864,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x086c,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0870,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0872,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0877,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x088d,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0893,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a6,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x08aa,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08ab,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0917,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0920,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0937,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0939,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x093d,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0941,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0944,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0948,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0951,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0954,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0957,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0969,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+#endif
+
+// 2018-03-21aRagexeRE, 2018-03-28bRagexeRE, 2018-04-04cRagexeRE, 2018-04-18bRagexeRE, 2018-04-25cRagexeRE, 2018-05-02bRagexeRE, 2018-05-02dRagexeRE, 2018-05-16cRagexeRE, 2018-05-23aRagexeRE, 2018-05-30bRagexeRE, 2018-05-30cRagexeRE, 2018-06-05bRagexeRE, 2018-06-12aRagexeRE, 2018-06-12bRagexeRE, 2018-06-20dRagexeRE, 2018-06-20eRagexeRE, 2018-06-21aRagexeRE
+#if PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER == 20180404 || \
+ PACKETVER == 20180418 || \
+ PACKETVER == 20180425 || \
+ PACKETVER == 20180502 || \
+ PACKETVER == 20180516 || \
+ PACKETVER == 20180523 || \
+ PACKETVER == 20180530 || \
+ PACKETVER == 20180605 || \
+ PACKETVER == 20180612 || \
+ PACKETVER == 20180620 || \
+ PACKETVER == 20180621
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2018-07-04aRagexeRE, 2018-07-11aRagexeRE, 2018-07-18bRagexeRE, 2018-07-18bRagexeRE1, 2018-07-18cRagexeRE, 2018-08-01cRagexeRE, 2018-08-08bRagexeRE, 2018-08-22cRagexeRE, 2018-08-29aRagexeRE, 2018-08-29bRagexeRE, 2018-09-12dRagexeRE, 2018-09-19aRagexeRE, 2018-10-02aRagexeRE, 2018-10-02bRagexeRE, 2018-10-17_02aRagexeRE, 2018-10-17_03aRagexeRE, 2018-10-17bRagexeRE, 2018-10-31cRagexeRE, 2018-11-07aRagexeRE, 2018-11-14cRagexeRE, 2018-11-14dRagexeRE, 2018-11-21cRagexeRE, 2018-11-28aRagexeRE, 2018-12-05bRagexeRE, 2018-12-12aRagexeRE, 2018-12-12bRagexeRE, 2018-12-19bRagexeRE, 2018-12-26aRagexeRE, 2019-01-09bRagexeRE, 2019-01-16bRagexeRE, 2019-01-16cRagexeRE, 2019-01-23dRagexeRE, 2019-02-13IRagexeRE, 2019-02-20aRagexeRE, 2019-02-27bRagexeRE, 2019-02-28aRagexeRE, 2019-03-06bRagexeRE, 2019-03-06cRagexeRE, 2019-03-20aRagexeRE, 2019-03-22aRagexeRE, 2019-03-27bRagexeRE, 2019-04-03bRagexeRE, 2019-04-03cRagexeRE, 2019-04-17cRagexeRE, 2019-04-18aRagexeRE, 2019-05-08dRagexeRE, 2019-05-08eRagexeRE, 2019-05-22bRagexeRE, 2019-05-22cRagexeRE, 2019-05-29bRagexeRE, 2019-05-29cRagexeRE, 2019-05-30aRagexeRE, 2019-06-05hRagexeRE, 2019-06-05JRagexeRE, 2019-06-05LRagexeRE, 2019-06-19cRagexeRE, 2019-06-26bRagexeRE, 2019-07-03bRagexeRE, 2019-07-17cRagexeRE, 2019-07-17dRagexeRE, 2019-07-24bRagexeRE, 2019-07-31bRagexeRE, 2019-08-02aRagexeRE, 2019-08-07dRagexeRE, 2019-08-21cRagexeRE, 2019-08-21dRagexeRE, 2019-08-28aRagexeRE
+#if PACKETVER == 20180704 || \
+ PACKETVER == 20180711 || \
+ PACKETVER == 20180718 || \
+ PACKETVER == 20180801 || \
+ PACKETVER == 20180808 || \
+ PACKETVER == 20180822 || \
+ PACKETVER == 20180829 || \
+ PACKETVER == 20180912 || \
+ PACKETVER == 20180919 || \
+ PACKETVER == 20181002 || \
+ PACKETVER == 20181017 || \
+ PACKETVER == 20181031 || \
+ PACKETVER == 20181107 || \
+ PACKETVER == 20181114 || \
+ PACKETVER == 20181121 || \
+ PACKETVER == 20181128 || \
+ PACKETVER == 20181205 || \
+ PACKETVER == 20181212 || \
+ PACKETVER == 20181219 || \
+ PACKETVER == 20181226 || \
+ PACKETVER == 20190109 || \
+ PACKETVER == 20190116 || \
+ PACKETVER == 20190123 || \
+ PACKETVER == 20190213 || \
+ PACKETVER == 20190220 || \
+ PACKETVER == 20190227 || \
+ PACKETVER == 20190228 || \
+ PACKETVER == 20190306 || \
+ PACKETVER == 20190320 || \
+ PACKETVER == 20190322 || \
+ PACKETVER == 20190327 || \
+ PACKETVER == 20190403 || \
+ PACKETVER == 20190417 || \
+ PACKETVER == 20190418 || \
+ PACKETVER == 20190508 || \
+ PACKETVER == 20190522 || \
+ PACKETVER == 20190529 || \
+ PACKETVER == 20190530 || \
+ PACKETVER == 20190605 || \
+ PACKETVER == 20190619 || \
+ PACKETVER == 20190626 || \
+ PACKETVER == 20190703 || \
+ PACKETVER == 20190717 || \
+ PACKETVER == 20190724 || \
+ PACKETVER == 20190731 || \
+ PACKETVER == 20190802 || \
+ PACKETVER == 20190807 || \
+ PACKETVER == 20190821 || \
+ PACKETVER >= 20190828
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+// 2019-09-04bRagexeRE, 2019-09-18cRagexeRE, 2019-09-25aRagexeRE, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexeRE, 2019-10-16gRagexeRE, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-11-06bRagexeRE, 2019-11-07aRagexeRE, 2019-11-13eRagexeRE, 2019-11-20cRagexeRE, 2019-11-27aRagexeRE, 2019-12-04aRagexeRE, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11fRagexeRE, 2019-12-18bRagexeRE, 2019-12-24aRagexeRE, 2019-12-24bRagexeRE, 2020-01-08bRagexeRE, 2020-01-22cRagexeRE, 2020-02-05aRagexeRE, 2020-02-12aRagexeRE, 2020-02-19eRagexeRE, 2020-03-04aRagexeRE
+#if PACKETVER == 20190904 || \
+ PACKETVER == 20190918 || \
+ PACKETVER == 20190925 || \
+ PACKETVER == 20191002 || \
+ PACKETVER == 20191016 || \
+ PACKETVER == 20191023 || \
+ PACKETVER == 20191030 || \
+ PACKETVER == 20191106 || \
+ PACKETVER == 20191107 || \
+ PACKETVER == 20191113 || \
+ PACKETVER == 20191120 || \
+ PACKETVER == 20191127 || \
+ PACKETVER == 20191204 || \
+ PACKETVER == 20191211 || \
+ PACKETVER == 20191218 || \
+ PACKETVER == 20191224 || \
+ PACKETVER == 20200108 || \
+ PACKETVER == 20200122 || \
+ PACKETVER == 20200205 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 31
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+
+#endif /* MAP_PACKETS_SHUFFLE_RE_H */
diff --git a/src/map/packets_shuffle_zero.h b/src/map/packets_shuffle_zero.h
new file mode 100644
index 000000000..fb12688c0
--- /dev/null
+++ b/src/map/packets_shuffle_zero.h
@@ -0,0 +1,859 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//Included directly by clif.c in packet_loaddb()
+
+#ifndef MAP_PACKETS_SHUFFLE_ZERO_H
+#define MAP_PACKETS_SHUFFLE_ZERO_H
+
+#ifndef packet
+ #define packet(a,...)
+#endif
+
+/*
+ * packet syntax
+ * - packet(packet_id,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet ),...)
+ * - Example: packet(0x0072,clif->pWantToConnection,2,6,10,14,18);
+ */
+
+/* This file is autogenerated, please do not commit manual changes */
+
+
+// 2017-10-18aRagexe_zero, 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero, 2018-04-11aRagexe_zero, 2018-04-25_3aRagexe_zero, 2018-05-09_3aRagexe_zero, 2018-05-23aRagexe_zero, 2018-06-05bRagexe_zero, 2018-06-05cRagexe_zero, 2018-06-27aRagexe_zero, 2018-07-03aRagexe_zero, 2018-07-11_2aRagexe_zero, 2018-07-25_2aRagexe_zero, 2018-08-01aRagexe_zero, 2018-08-08_2aRagexe_zero, 2018-08-22aRagexe_zero, 2018-08-29aRagexe_zero, 2018-09-05aRagexe_zero, 2018-09-12aRagexe_zero, 2018-09-19aRagexe_zero, 2018-09-28aRagexe_zero, 2018-10-10_2aRagexe_zero, 2018-10-24_2aRagexe_zero
+#if PACKETVER == 20171018 || \
+ PACKETVER == 20171019 || \
+ PACKETVER == 20171023 || \
+ PACKETVER == 20171024 || \
+ PACKETVER == 20171025 || \
+ PACKETVER == 20171027 || \
+ PACKETVER == 20171030 || \
+ PACKETVER == 20171031 || \
+ PACKETVER == 20171109 || \
+ PACKETVER == 20171113 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER == 20180411 || \
+ PACKETVER == 20180425 || \
+ PACKETVER == 20180509 || \
+ PACKETVER == 20180523 || \
+ PACKETVER == 20180605 || \
+ PACKETVER == 20180627 || \
+ PACKETVER == 20180703 || \
+ PACKETVER == 20180711 || \
+ PACKETVER == 20180725 || \
+ PACKETVER == 20180801 || \
+ PACKETVER == 20180808 || \
+ PACKETVER == 20180822 || \
+ PACKETVER == 20180829 || \
+ PACKETVER == 20180905 || \
+ PACKETVER == 20180912 || \
+ PACKETVER == 20180919 || \
+ PACKETVER == 20180928 || \
+ PACKETVER == 20181010 || \
+ PACKETVER == 20181024
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2017-11-15aRagexe_zero, 2017-11-15bRagexe_zero, 2017-11-16aRagexe_zero, 2017-11-17aRagexe_zero
+#if PACKETVER == 20171115 || \
+ PACKETVER == 20171116 || \
+ PACKETVER == 20171117
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0860,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0881,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0922,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0959,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0966,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-21aRagexe_zero, 2017-11-22aRagexe_zero
+#if PACKETVER == 20171121 || \
+ PACKETVER == 20171122
+ packet(0x0202,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x022d,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0866,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0889,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0892,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08ad,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0918,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x091f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0928,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0943,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0950,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-23dRagexe_zero
+#if PACKETVER == 20171123
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0367,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0860,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0876,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0882,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x088c,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0896,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x089e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x08a8,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x092b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0930,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0935,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0960,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-27aRagexe_zero, 2017-11-27cRagexe_zero, 2017-11-28aRagexe_zero
+#if PACKETVER == 20171127 || \
+ PACKETVER == 20171128
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0893,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-11-30bRagexe_zero
+#if PACKETVER == 20171130
+ packet(0x0361,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0864,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x086f,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0871,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0872,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0875,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0878,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0881,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0884,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0886,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0887,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x088b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0894,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0899,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x08a0,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x08a7,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0925,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0928,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0930,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0931,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0935,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093a,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0947,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x094c,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x095b,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x095f,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0960,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0965,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+#endif
+
+// 2017-12-04bRagexe_zero
+#if PACKETVER == 20171204
+ packet(0x0281,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x085b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086f,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x087d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0885,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0887,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0892,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0896,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x08aa,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0917,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0921,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0924,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0937,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0960,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2017-12-06aRagexe_zero, 2017-12-06bRagexe_zero, 2017-12-06cRagexe_zero, 2017-12-06dRagexe_zero, 2017-12-08aRagexe_zero, 2017-12-08cRagexe_zero, 2017-12-08dRagexe_zero, 2017-12-09bRagexe_zero, 2017-12-09cRagexe_zero, 2017-12-10aRagexe_zero, 2017-12-11bRagexe_zero, 2017-12-12aRagexe_zero, 2017-12-13aRagexe_zero, 2017-12-13bRagexe_zero, 2017-12-13cRagexe_zero
+#if PACKETVER == 20171206 || \
+ PACKETVER == 20171208 || \
+ PACKETVER == 20171209 || \
+ PACKETVER == 20171210 || \
+ PACKETVER == 20171211 || \
+ PACKETVER == 20171212 || \
+ PACKETVER == 20171213
+ packet(0x0281,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0366,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0436,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0835,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x083c,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0860,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0862,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0864,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0870,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0878,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x087a,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087b,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0885,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x088d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0893,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0897,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x089e,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a4,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x08ac,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0920,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0934,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0936,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x093a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0940,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0941,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0959,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x095c,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x095f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+#endif
+
+// 2017-12-14cRagexe_zero
+#if PACKETVER == 20171214
+ packet(0x023b,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x02c4,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0438,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x085b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x085e,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0862,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0864,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x086a,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0871,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0873,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0886,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x088b,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088c,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0892,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0894,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0897,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x08a3,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x08a5,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x08ac,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0933,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x094f,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0951,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095a,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x095b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0960,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0969,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x096a,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+#endif
+
+// 2017-12-20aRagexe_zero, 2017-12-21aRagexe_zero, 2017-12-21bRagexe_zero
+#if PACKETVER == 20171220 || \
+ PACKETVER == 20171221
+ packet(0x022d,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0281,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0438,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x07ec,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x085f,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0867,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x086c,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0872,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x087e,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0899,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x089b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x089c,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a3,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a5,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x08ad,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x091f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0921,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092d,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092e,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0932,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0934,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0937,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x094d,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+#endif
+
+// 2017-12-27bRagexe_zero, 2017-12-29aRagexe_zero
+#if PACKETVER == 20171227 || \
+ PACKETVER == 20171229
+ packet(0x02c4,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0860,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x086c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0871,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0872,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0874,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0876,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0877,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0878,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x087b,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0885,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0889,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x088b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0894,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x089f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x091c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0920,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0925,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092d,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0930,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0939,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x093e,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0941,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0945,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0946,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x094b,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x095e,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0967,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0968,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+#endif
+
+// 2018-01-03aRagexe_zero
+#if PACKETVER == 20180103
+ packet(0x035f,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0360,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x07e4,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x083c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0860,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0866,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x086d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0871,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0872,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0874,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x087b,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0885,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0888,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0890,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0896,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x089d,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x08a6,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x091e,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0924,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0938,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x093b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0956,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0958,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x095b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x095d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0964,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0966,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x096a,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+#endif
+
+// 2018-01-17aRagexe_zero
+#if PACKETVER == 20180117
+ packet(0x0361,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0364,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0438,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x07e4,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x083c,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0866,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x086e,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086f,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x087d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0881,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0884,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0886,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0890,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0891,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0893,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0899,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x089d,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x089e,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0919,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x091c,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x091f,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0921,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0928,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0929,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x092d,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0933,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0946,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x095e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0963,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+#endif
+
+// 2018-01-31dRagexe_zero
+#if PACKETVER == 20180131
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0367,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0940,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-07bRagexe_zero
+#if PACKETVER == 20180207
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-02-13aRagexe_zero
+#if PACKETVER == 20180213
+ packet(0x022d,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x02c4,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x035f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0361,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0802,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0815,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x085a,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0868,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x087b,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0882,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0887,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0888,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x088a,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x088e,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0899,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0917,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091d,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0922,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0930,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0941,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0942,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0947,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x094d,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0958,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x095b,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x095c,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0967,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2018-02-21aRagexe_zero
+#if PACKETVER == 20180221
+ packet(0x02c4,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0362,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0364,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0438,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x0817,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x085b,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x086a,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0878,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0880,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0884,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x088d,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0892,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0895,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x08a1,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x08a3,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x091b,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0921,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0923,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x092d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0932,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x093b,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x093d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x093e,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0942,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0951,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0952,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0958,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0959,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x095d,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+#endif
+
+// 2018-02-28bRagexe_zero, 2018-03-07aRagexe_zero, 2018-03-09aRagexe_zero
+#if PACKETVER == 20180228 || \
+ PACKETVER == 20180307 || \
+ PACKETVER == 20180309
+ packet(0x0202,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x022d,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x023b,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0281,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x035f,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0360,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0361,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0362,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0363,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0364,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0365,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0366,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0369,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0436,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0437,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0438,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x07e4,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x07ec,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0802,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0811,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0815,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0819,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0835,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0838,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x083c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x0930,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x096a,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+#endif
+
+// 2018-03-14nRagexe_zero
+#if PACKETVER == 20180314
+ packet(0x023b,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x0438,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x07ec,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0817,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x083c,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x085d,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x085f,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0866,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0878,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x088d,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0891,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0897,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0899,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x089e,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x08a1,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x0917,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0918,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x091f,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0920,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0923,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x0930,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0931,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x093f,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0946,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x094a,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x094e,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0954,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0956,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0958,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+#endif
+
+// 2018-05-11aRagexe_zero, 2018-05-11bRagexe_zero
+#if PACKETVER == 20180511
+ packet(0x0817,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x085f,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0863,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x086c,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0877,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x087e,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0880,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0889,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0893,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0896,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0899,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 12
+ packet(0x08a2,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x08a4,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x08a5,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0919,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x091a,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x091d,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0920,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x092c,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x092d,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x092e,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0941,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x0942,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x094a,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0955,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x0956,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x095c,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0961,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x0968,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+#endif
+
+// 2018-11-14aRagexe_zero, 2018-11-20aRagexe_zero, 2018-11-28aRagexe_zero, 2018-12-12aRagexe_zero, 2018-12-19aRagexe_zero, 2018-12-26_2aRagexe_zero, 2019-01-16_2aRagexe_zero, 2019-01-17_1aRagexe_zero, 2019-01-30_2aRagexe_zero, 2019-02-13aRagexe_zero, 2019-02-20aRagexe_zero, 2019-02-27aRagexe_zero, 2019-03-13aRagexe_zero, 2019-03-27_2aRagexe_zero, 2019-03-27_3aRagexe_zero, 2019-04-03aRagexe_zero, 2019-04-10bRagexe_zero, 2019-04-24aRagexe_zero, 2019-05-02aRagexe_zero, 2019-05-08_2aRagexe_zero, 2019-05-08aRagexe_zero, 2019-05-15aRagexe_zero, 2019-05-29aRagexe_zero, 2019-05-30aRagexe_zero, 2019-06-05_2aRagexe_zero, 2019-06-26_2aRagexe_zero, 2019-06-26_3aRagexe_zero, 2019-07-09aRagexe_zero, 2019-07-10_3aRagexe_zero, 2019-07-17aRagexe_zero, 2019-07-24aRagexe_zero, 2019-08-14_3aRagexe_zero
+#if PACKETVER == 20181114 || \
+ PACKETVER == 20181120 || \
+ PACKETVER == 20181128 || \
+ PACKETVER == 20181212 || \
+ PACKETVER == 20181219 || \
+ PACKETVER == 20181226 || \
+ PACKETVER == 20190116 || \
+ PACKETVER == 20190117 || \
+ PACKETVER == 20190130 || \
+ PACKETVER == 20190213 || \
+ PACKETVER == 20190220 || \
+ PACKETVER == 20190227 || \
+ PACKETVER == 20190313 || \
+ PACKETVER == 20190327 || \
+ PACKETVER == 20190403 || \
+ PACKETVER == 20190410 || \
+ PACKETVER == 20190424 || \
+ PACKETVER == 20190502 || \
+ PACKETVER == 20190508 || \
+ PACKETVER == 20190515 || \
+ PACKETVER == 20190529 || \
+ PACKETVER == 20190530 || \
+ PACKETVER == 20190605 || \
+ PACKETVER == 20190626 || \
+ PACKETVER == 20190709 || \
+ PACKETVER == 20190710 || \
+ PACKETVER == 20190717 || \
+ PACKETVER == 20190724 || \
+ PACKETVER >= 20190814
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 90
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+// 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero, 2020-02-12aRagexe_zero, 2020-02-26aRagexe_zero, 2020-02-26bRagexe_zero, 2020-03-04aRagexe_zero, 2020-03-18_2aRagexe_zero, 2020-04-01_2aRagexe_zero, 2020-04-14bRagexe_zero
+#if PACKETVER == 20190828 || \
+ PACKETVER == 20190911 || \
+ PACKETVER == 20190918 || \
+ PACKETVER == 20190925 || \
+ PACKETVER == 20191008 || \
+ PACKETVER == 20191023 || \
+ PACKETVER == 20191106 || \
+ PACKETVER == 20191113 || \
+ PACKETVER == 20191127 || \
+ PACKETVER == 20191204 || \
+ PACKETVER == 20191211 || \
+ PACKETVER == 20191224 || \
+ PACKETVER == 20200115 || \
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200226 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401 || \
+ PACKETVER == 20200414
+ packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
+ packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
+ packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
+ packet(0x0281,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK // 4
+ packet(0x02c4,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ // 26
+ packet(0x035f,clif->pWalkToXY,2); // CZ_REQUEST_MOVE // 5
+ packet(0x0360,clif->pTickSend,2); // CZ_REQUEST_TIME // 6
+ packet(0x0361,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION // 5
+ packet(0x0362,clif->pTakeItem,2); // CZ_ITEM_PICKUP // 6
+ packet(0x0363,clif->pDropItem,2,4); // CZ_ITEM_THROW // 6
+ packet(0x0364,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE // 8
+ packet(0x0365,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY // 8
+ packet(0x0366,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND // 10
+ packet(0x0367,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX // 31
+ packet(0x0368,clif->pGetCharNameRequest,2); // CZ_REQNAME // 6
+ packet(0x0369,clif->pSolveCharName,2); // CZ_REQNAME_BYGID // 6
+ packet(0x0436,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER // 19
+ packet(0x0437,clif->pActionRequest,2,6); // CZ_REQUEST_ACT // 7
+ packet(0x0438,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL // 10
+ packet(0x07e4,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES // -1
+ packet(0x07ec,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD // 8
+ packet(0x0802,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER // 18
+ packet(0x0811,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE // -1
+ packet(0x0815,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE // 2
+ packet(0x0817,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE // 6
+ packet(0x0819,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE // -1
+ packet(0x0835,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO // -1
+ packet(0x0838,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE // 2
+ packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
+#endif
+
+
+#endif /* MAP_PACKETS_SHUFFLE_ZERO_H */
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index e8f04c653..3129a05d9 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2020 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,10 @@
#include "common/cbasetypes.h"
#include "common/mmo.h"
+#include "common/packetsstatic_len.h"
+
+// Packet DB
+#define MAX_PACKET_POS 20
/**
*
@@ -35,13 +39,6 @@ enum packet_headers {
banking_checkType = 0x9a6,
cart_additem_ackType = 0x12c,
sc_notickType = 0x196,
-#if PACKETVER >= 20141022
- hotkeyType = 0xa00,
-#elif PACKETVER >= 20090603
- hotkeyType = 0x7d9,
-#else
- hotkeyType = 0x2b9,
-#endif
#if PACKETVER >= 20150226
cartaddType = 0xa0b,
#elif PACKETVER >= 5
@@ -71,8 +68,10 @@ enum packet_headers {
additemType = 0x2d4,
#elif PACKETVER < 20150226
additemType = 0x990,
-#else
+#elif PACKETVER < 20160921
additemType = 0xa0c,
+#else
+ additemType = 0xa37,
#endif
#if PACKETVER < 4
idle_unitType = 0x78,
@@ -136,8 +135,11 @@ enum packet_headers {
authokType = 0x73,
#elif PACKETVER < 20141022
authokType = 0x2eb,
-#else
+// Some clients smaller than 20160330 cant be tested [4144]
+#elif PACKETVER < 20160330
authokType = 0xa18,
+#else
+ authokType = 0x2eb,
#endif
script_clearType = 0x8d6,
package_item_announceType = 0x7fd,
@@ -181,12 +183,16 @@ enum packet_headers {
skill_entryType = 0x9ca,
#endif
graffiti_entryType = 0x1c9,
-#if PACKETVER > 20130000 /* not sure date */
+#if defined(PACKETVER_ZERO) || PACKETVER >= 20180418
+ dropflooritemType = 0xadd,
+#elif PACKETVER > 20130000 /* not sure date */
dropflooritemType = 0x84b,
#else
dropflooritemType = 0x9e,
#endif
-#if PACKETVER >= 20120925
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ inventorylistnormalType = 0xb09,
+#elif PACKETVER >= 20120925
inventorylistnormalType = 0x991,
#elif PACKETVER >= 20080102
inventorylistnormalType = 0x2e8,
@@ -195,7 +201,9 @@ enum packet_headers {
#else
inventorylistnormalType = 0xa3,
#endif
-#if PACKETVER >= 20150226
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ inventorylistequipType = 0xb0a,
+#elif PACKETVER >= 20150226
inventorylistequipType = 0xa0d,
#elif PACKETVER >= 20120925
inventorylistequipType = 0x992,
@@ -206,27 +214,33 @@ enum packet_headers {
#else
inventorylistequipType = 0xa4,
#endif
-#if PACKETVER >= 20120925
- storagelistnormalType = 0x995,
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storageListNormalType = 0xb09,
+#elif PACKETVER >= 20120925
+ storageListNormalType = 0x995,
#elif PACKETVER >= 20080102
- storagelistnormalType = 0x2ea,
+ storageListNormalType = 0x2ea,
#elif PACKETVER >= 20071002
- storagelistnormalType = 0x295,
+ storageListNormalType = 0x295,
#else
- storagelistnormalType = 0xa5,
+ storageListNormalType = 0xa5,
#endif
-#if PACKETVER >= 20150226
- storagelistequipType = 0xa10,
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ storageListEquipType = 0xb0a,
+#elif PACKETVER >= 20150226
+ storageListEquipType = 0xa10,
#elif PACKETVER >= 20120925
- storagelistequipType = 0x996,
+ storageListEquipType = 0x996,
#elif PACKETVER >= 20080102
- storagelistequipType = 0x2d1,
+ storageListEquipType = 0x2d1,
#elif PACKETVER >= 20071002
- storagelistequipType = 0x296,
+ storageListEquipType = 0x296,
#else
- storagelistequipType = 0xa6,
+ storageListEquipType = 0xa6,
#endif
-#if PACKETVER >= 20120925
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ cartlistnormalType = 0xb09,
+#elif PACKETVER >= 20120925
cartlistnormalType = 0x993,
#elif PACKETVER >= 20080102
cartlistnormalType = 0x2e9,
@@ -235,7 +249,9 @@ enum packet_headers {
#else
cartlistnormalType = 0x123,
#endif
-#if PACKETVER >= 20150226
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ cartlistequipType = 0xb0a,
+#elif PACKETVER >= 20150226
cartlistequipType = 0xa0f,
#elif PACKETVER >= 20120925
cartlistequipType = 0x994,
@@ -267,10 +283,15 @@ enum packet_headers {
#else
unequipitemackType = 0xac,
#endif
-#if PACKETVER >= 20150226
+#if PACKETVER_MAIN_NUM >= 20180801 || PACKETVER_RE_NUM >= 20180801 || PACKETVER_ZERO_NUM >= 20180808
+ viewequipackType = 0xb03,
+#elif PACKETVER >= 20150226
viewequipackType = 0xa2d,
#elif PACKETVER >= 20120925
viewequipackType = 0x997,
+// [4144] not supported due other packets/structs not updated
+//#elif (PACKETVER_MAIN_NUM >= 20111207) || (PACKETVER_RE_NUM >= 20111122)
+// viewequipackType = 0x906,
#elif PACKETVER >= 20101124
viewequipackType = 0x859,
#else
@@ -279,9 +300,7 @@ enum packet_headers {
notifybindonequip = 0x2d3,
monsterhpType = 0x977,
maptypeproperty2Type = 0x99b,
- npcmarketresultackType = 0x9d7,
- npcmarketopenType = 0x9d5,
-#if PACKETVER >= 20131223
+#if PACKETVER >= 20131223 // version probably can be 20131030 [4144]
wisendType = 0x9df,
#else
wisendType = 0x98,
@@ -290,13 +309,124 @@ enum packet_headers {
rouletteinfoackType = 0xa1c,
roulettgenerateackType = 0xa20,
roulettercvitemackType = 0xa22,
-#if 0 // Unknown
+#if PACKETVER >= 20141016
+ achievementListType = 0xa23,
+ achievementUpdateType = 0xa24,
+ achievementRewardAckType = 0xa26,
+#endif // PACKETVER >= 20141016
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ questListType = 0xaff, ///< ZC_ALL_QUEST_LIST4
+#elif PACKETVER >= 20150513 // [4144] 0x09f8 handling in client from 2014-10-29aRagexe and 2014-03-26cRagexeRE
questListType = 0x9f8, ///< ZC_ALL_QUEST_LIST3
#elif PACKETVER >= 20141022
questListType = 0x97a, ///< ZC_ALL_QUEST_LIST2
#else // PACKETVER < 20141022
questListType = 0x2b1, ///< ZC_ALL_QUEST_LIST
#endif // PACKETVER >= 20141022
+ /* Rodex */
+ rodexicon = 0x09E7,
+ rodexread = 0x09EB,
+ rodexwriteresult = 0x09ED,
+ rodexnextpage = 0x09F0,
+ rodexgetzeny = 0x09F2,
+ rodexgetitem = 0x09F4,
+ rodexdelete = 0x09F6,
+ rodexadditem = 0x0A05,
+ rodexremoveitem = 0x0A07,
+ rodexopenwrite = 0x0A12,
+#if PACKETVER < 20160601
+ rodexmailList = 0x09F0,
+#elif PACKETVER < 20170419
+ rodexmailList = 0x0A7D,
+#else // PACKETVER >= 20170419
+ rodexmailList = 0x0Ac2,
+#endif
+#if PACKETVER < 20160316
+ rodexcheckplayer = 0x0A14,
+#else // PACKETVER >= 20160316
+ rodexcheckplayer = 0x0A51,
+#endif
+#if PACKETVER >= 20151223
+ skillscale = 0xA41,
+#endif
+#if PACKETVER >= 20130821
+ progressbarunit = 0x09D1,
+#endif
+#if PACKETVER >= 20171207
+ partymemberinfo = 0x0ae4,
+ partyinfo = 0x0ae5,
+#elif PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ partymemberinfo = 0x0a43,
+ partyinfo = 0x0a44,
+#else
+ partymemberinfo = 0x01e9,
+ partyinfo = 0x00fb,
+#endif
+#if PACKETVER >= 20120716
+ clanOnlineCount = 0x0988, ///< ZC_NOTIFY_CLAN_CONNECTINFO
+ clanLeave = 0x0989, ///< ZC_ACK_CLAN_LEAVE
+ clanMessage = 0x098E, ///< ZC_NOTIFY_CLAN_CHAT
+#endif
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ questAddType = 0xb0c,
+#elif PACKETVER >= 20150513 // [4144] 0x09f9 handled in client from 2014-10-29aRagexe and 2014-03-26cRagexeRE
+ questAddType = 0x9f9,
+#else
+ questAddType = 0x2b3,
+#endif // PACKETVER < 20150513
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ questUpdateType = 0xafe,
+#elif PACKETVER >= 20150513
+ questUpdateType = 0x9fa,
+#else
+ questUpdateType = 0x2b5,
+#endif // PACKETVER < 20150513
+ questUpdateType2 = 0x8fe,
+#if PACKETVER >= 20171122
+ openUiType = 0xAE2,
+#elif PACKETVER >= 20150128
+ openUiType = 0xA38,
+#endif
+#if PACKETVER >= 20180627
+ authError = 0xb02,
+#elif PACKETVER >= 20101123
+ authError = 0x83e,
+#else
+ authError = 0x6a,
+#endif
+#if PACKETVER >= 3
+ useItemAckType = 0x1c8,
+#else
+ useItemAckType = 0xa8,
+#endif
+#if PACKETVER >= 4
+ sendLookType = 0x1d7,
+#else
+ sendLookType = 0xc3,
+#endif
+#if PACKETVER >= 20141016
+ buyingStoreUpdateItemType = 0x9e6,
+#else
+ buyingStoreUpdateItemType = 0x81b,
+#endif
+ reqName = 0x95,
+#if PACKETVER_MAIN_NUM >= 20170502 || PACKETVER_RE_NUM >= 20170419 || defined(PACKETVER_ZERO)
+ skilWarpPointType = 0xabe,
+#else
+ skilWarpPointType = 0x11c,
+#endif
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+ guildExpulsion = 0xa82,
+#elif PACKETVER >= 20100803
+ guildExpulsion = 0x839,
+#else
+ guildExpulsion = 0x15c,
+#endif
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+ guildLeave = 0xa83,
+#else
+ guildLeave = 0x15a,
+#endif
};
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
@@ -307,186 +437,215 @@ enum packet_headers {
* structs for data
*/
struct EQUIPSLOTINFO {
- unsigned short card[4];
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 card[4];
+#else
+ uint16 card[4];
+#endif
} __attribute__((packed));
struct NORMALITEM_INFO {
- short index;
- unsigned short ITID;
- unsigned char type;
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
+ uint8 type;
#if PACKETVER < 20120925
uint8 IsIdentified;
#endif
- short count;
+ int16 count;
#if PACKETVER >= 20120925
- unsigned int WearState;
+ uint32 WearState;
#else
- unsigned short WearState;
+ uint16 WearState;
#endif
#if PACKETVER >= 5
struct EQUIPSLOTINFO slot;
#endif
#if PACKETVER >= 20080102
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20120925
struct {
- unsigned char IsIdentified : 1;
- unsigned char PlaceETCTab : 1;
- unsigned char SpareBits : 6;
+ uint8 IsIdentified : 1;
+ uint8 PlaceETCTab : 1;
+ uint8 SpareBits : 6;
} Flag;
#endif
} __attribute__((packed));
-struct RndOptions {
- short index;
- short value;
- unsigned char param;
+struct ItemOptions {
+ int16 index;
+ int16 value;
+ uint8 param;
} __attribute__((packed));
struct EQUIPITEM_INFO {
- short index;
- unsigned short ITID;
- unsigned char type;
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
+ uint8 type;
#if PACKETVER < 20120925
uint8 IsIdentified;
#endif
#if PACKETVER >= 20120925
- unsigned int location;
- unsigned int WearState;
+ uint32 location;
+ uint32 WearState;
#else
- unsigned short location;
- unsigned short WearState;
+ uint16 location;
+ uint16 WearState;
#endif
#if PACKETVER < 20120925
uint8 IsDamaged;
#endif
- unsigned char RefiningLevel;
+ uint8 RefiningLevel;
struct EQUIPSLOTINFO slot;
#if PACKETVER >= 20071002
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20080102
- unsigned short bindOnEquipType;
+ uint16 bindOnEquipType;
#endif
#if PACKETVER >= 20100629
- unsigned short wItemSpriteNumber;
+ uint16 wItemSpriteNumber;
#endif
#if PACKETVER >= 20150226
- unsigned char option_count;
- struct RndOptions option_data[5];
+ uint8 option_count;
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
#endif
#if PACKETVER >= 20120925
struct {
- unsigned char IsIdentified : 1;
- unsigned char IsDamaged : 1;
- unsigned char PlaceETCTab : 1;
- unsigned char SpareBits : 5;
+ uint8 IsIdentified : 1;
+ uint8 IsDamaged : 1;
+ uint8 PlaceETCTab : 1;
+ uint8 SpareBits : 5;
} Flag;
#endif
} __attribute__((packed));
struct packet_authok {
- short PacketType;
- unsigned int startTime;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
+ int16 PacketType;
+ uint32 startTime;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
-#if PACKETVER >= 20141022
- unsigned char sex;
+// Some clients smaller than 20160330 cant be tested [4144]
+#if PACKETVER >= 20141022 && PACKETVER < 20160330
+ uint8 sex;
#endif
} __attribute__((packed));
struct packet_monster_hp {
- short PacketType;
- unsigned int GID;
- int HP;
- int MaxHP;
+ int16 PacketType;
+ uint32 GID;
+ int32 HP;
+ int32 MaxHP;
} __attribute__((packed));
struct packet_sc_notick {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
} __attribute__((packed));
struct packet_additem {
- short PacketType;
- unsigned short Index;
- unsigned short count;
- unsigned short nameid;
+ int16 PacketType;
+ uint16 Index;
+ uint16 count;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 nameid;
+#else
+ uint16 nameid;
+#endif
uint8 IsIdentified;
uint8 IsDamaged;
- unsigned char refiningLevel;
+ uint8 refiningLevel;
struct EQUIPSLOTINFO slot;
#if PACKETVER >= 20120925
- unsigned int location;
+ uint32 location;
#else
- unsigned short location;
+ uint16 location;
#endif
- unsigned char type;
- unsigned char result;
+ uint8 type;
+ uint8 result;
#if PACKETVER >= 20061218
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20071002
- unsigned short bindOnEquipType;
+ uint16 bindOnEquipType;
#endif
#if PACKETVER >= 20150226
- struct RndOptions option_data[5];
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+#if PACKETVER >= 20160921
+ uint8 favorite;
+ uint16 look;
#endif
} __attribute__((packed));
struct packet_dropflooritem {
- short PacketType;
- unsigned int ITAID;
- unsigned short ITID;
+ int16 PacketType;
+ uint32 ITAID;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
#if PACKETVER >= 20130000 /* not sure date */
- unsigned short type;
+ uint16 type;
#endif
uint8 IsIdentified;
- short xPos;
- short yPos;
- unsigned char subX;
- unsigned char subY;
- short count;
+ int16 xPos;
+ int16 yPos;
+ uint8 subX;
+ uint8 subY;
+ int16 count;
+#if defined(PACKETVER_ZERO) || PACKETVER >= 20180418
+ int8 showdropeffect;
+ int16 dropeffectmode;
+#endif
} __attribute__((packed));
struct packet_idle_unit2 {
#if PACKETVER < 20091103
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20071106
- unsigned char objecttype;
-#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
- short effectState;
- short job;
- short head;
- short weapon;
- short accessory;
- short shield;
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
- unsigned int GUID;
- short GEmblemVer;
- short honor;
- short virtue;
+ uint8 objecttype;
+#endif
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
+ int16 effectState;
+ int16 job;
+ uint16 head;
+ uint16 weapon;
+ uint16 accessory;
+ uint16 shield;
+ uint16 accessory2;
+ uint16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
+ int16 virtue;
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- unsigned char state;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ uint8 state;
+ int16 clevel;
#else // ! PACKETVER < 20091103
UNAVAILABLE_STRUCT;
#endif // PACKETVER < 20091103
@@ -494,607 +653,700 @@ struct packet_idle_unit2 {
struct packet_spawn_unit2 {
#if PACKETVER < 20091103
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20071106
- unsigned char objecttype;
-#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
- short effectState;
- short head;
- short weapon;
- short accessory;
- short job;
- short shield;
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ uint8 objecttype;
+#endif
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
+ int16 effectState;
+ uint16 head;
+ uint16 weapon;
+ uint16 accessory;
+ int16 job;
+ uint16 shield;
+ uint16 accessory2;
+ uint16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
#else // ! PACKETVER < 20091103
UNAVAILABLE_STRUCT;
#endif // PACKETVER < 20091103
} __attribute__((packed));
struct packet_spawn_unit {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
- unsigned char objecttype;
+ int16 PacketLength;
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 20080102
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ uint16 head;
#if PACKETVER < 7
- short weapon;
+ uint16 weapon;
#else
- int weapon;
+ uint32 weapon;
+#endif
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 shield;
#endif
- short accessory;
+ uint16 accessory;
#if PACKETVER < 7
- short shield;
+ uint16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ uint16 accessory2;
+ uint16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ uint16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ int16 body;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_unit_walking {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
+ int16 PacketLength;
#endif
-#if PACKETVER > 20071106
- unsigned char objecttype;
+#if PACKETVER >= 20071106
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 7
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ uint16 head;
#if PACKETVER < 7
- short weapon;
+ uint16 weapon;
#else
- int weapon;
+ uint32 weapon;
+#endif
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 shield;
#endif
- short accessory;
- unsigned int moveStartTime;
+ uint16 accessory;
+ uint32 moveStartTime;
#if PACKETVER < 7
- short shield;
+ uint16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ uint16 accessory2;
+ uint16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ uint16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char MoveData[6];
- unsigned char xSize;
- unsigned char ySize;
- short clevel;
+ uint8 sex;
+ uint8 MoveData[6];
+ uint8 xSize;
+ uint8 ySize;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ uint16 body;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_idle_unit {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
- unsigned char objecttype;
+ int16 PacketLength;
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 20080102
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ uint16 head;
#if PACKETVER < 7
- short weapon;
+ uint16 weapon;
#else
- int weapon;
+ uint32 weapon;
#endif
- short accessory;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 shield;
+#endif
+ uint16 accessory;
#if PACKETVER < 7
- short shield;
+ uint16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ uint16 accessory2;
+ uint16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ uint16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- unsigned char state;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ uint8 state;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ uint16 body;
+#endif
+/* Might be earlier, this is when the named item bug began */
+#if PACKETVER >= 20131223
char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_status_change {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
#if PACKETVER >= 20120618
- unsigned int Total;
+ uint32 Total;
#endif
#if PACKETVER >= 20090121
- unsigned int Left;
- int val1;
- int val2;
- int val3;
+ uint32 Left;
+ int32 val1;
+ int32 val2;
+ int32 val3;
#endif
} __attribute__((packed));
struct packet_status_change_end {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
} __attribute__((packed));
struct packet_status_change2 {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
- unsigned int Left;
- int val1;
- int val2;
- int val3;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
+ uint32 Left;
+ int32 val1;
+ int32 val2;
+ int32 val3;
} __attribute__((packed));
struct packet_maptypeproperty2 {
- short PacketType;
- short type;
+ int16 PacketType;
+ int16 type;
struct {
- unsigned int party : 1; // Show attack cursor on non-party members (PvP)
- unsigned int guild : 1; // Show attack cursor on non-guild members (GvG)
- unsigned int siege : 1; // Show emblem over characters' heads when in GvG (WoE castle)
- unsigned int mineffect : 1; // Automatically enable /mineffect
- unsigned int nolockon : 1; // TODO: What does this do? (shows attack cursor on non-party members)
- unsigned int countpk : 1; /// Show the PvP counter
- unsigned int nopartyformation : 1; /// Prevent party creation/modification
- unsigned int bg : 1; // TODO: What does this do? Probably related to Battlegrounds, but I'm not sure on the effect
- unsigned int nocostume : 1; /// Does not show costume sprite.
- unsigned int usecart : 1; /// Allow opening cart inventory
- unsigned int summonstarmiracle : 1; // TODO: What does this do? Related to Taekwon Masters, but I have no idea.
- unsigned int SpareBits : 15; /// Currently ignored, reserved for future updates
+ uint32 party : 1; // Show attack cursor on non-party members (PvP)
+ uint32 guild : 1; // Show attack cursor on non-guild members (GvG)
+ uint32 siege : 1; // Show emblem over characters' heads when in GvG (WoE castle)
+ uint32 mineffect : 1; // Automatically enable /mineffect
+ uint32 nolockon : 1; // TODO: What does this do? (shows attack cursor on non-party members)
+ uint32 countpk : 1; /// Show the PvP counter
+ uint32 nopartyformation : 1; /// Prevent party creation/modification
+ uint32 bg : 1; // TODO: What does this do? Probably related to Battlegrounds, but I'm not sure on the effect
+ uint32 nocostume : 1; /// Does not show costume sprite.
+ uint32 usecart : 1; /// Allow opening cart inventory
+ uint32 summonstarmiracle : 1; // TODO: What does this do? Related to Taekwon Masters, but I have no idea.
+ uint32 SpareBits : 21; /// Currently ignored, reserved for future updates
} flag;
} __attribute__((packed));
struct packet_bgqueue_ack {
- short PacketType;
- unsigned char type;
+ int16 PacketType;
+ uint8 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_notice_delete {
- short PacketType;
- unsigned char type;
+ int16 PacketType;
+ uint8 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_register {
- short PacketType;
- short type;
+ int16 PacketType;
+ int16 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_update_info {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
- int position;
+ int32 position;
} __attribute__((packed));
struct packet_bgqueue_checkstate {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_revoke_req {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_battlebegin_ack {
- short PacketType;
- unsigned char result;
+ int16 PacketType;
+ uint8 result;
char bg_name[NAME_LENGTH];
char game_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_notify_entry {
- short PacketType;
+ int16 PacketType;
char name[NAME_LENGTH];
- int position;
+ int32 position;
} __attribute__((packed));
struct packet_bgqueue_battlebegins {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
char game_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_script_clear {
- short PacketType;
- unsigned int NpcID;
+ int16 PacketType;
+ uint32 NpcID;
} __attribute__((packed));
/* made possible thanks to Yommy!! */
struct packet_package_item_announce {
- short PacketType;
- short PacketLength;
- unsigned char type;
- unsigned short ItemID;
- char len;
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 type;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ItemID;
+#else
+ uint16 ItemID;
+#endif
+ int8 len;
char Name[NAME_LENGTH];
- char unknown;
- unsigned short BoxItemID;
+ int8 unknown; // probably unused
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 BoxItemID;
+#else
+ uint16 BoxItemID;
+#endif
} __attribute__((packed));
/* made possible thanks to Yommy!! */
struct packet_item_drop_announce {
- short PacketType;
- short PacketLength;
- unsigned char type;
- unsigned short ItemID;
- char len;
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 type;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ItemID;
+#else
+ uint16 ItemID;
+#endif
+ int8 len;
char Name[NAME_LENGTH];
char monsterNameLen;
char monsterName[NAME_LENGTH];
} __attribute__((packed));
struct packet_cart_additem_ack {
- short PacketType;
- char result;
+ int16 PacketType;
+ int8 result;
} __attribute__((packed));
struct packet_banking_check {
- short PacketType;
+ int16 PacketType;
int64 Money;
- short Reason;
+ int16 Reason;
} __attribute__((packed));
struct packet_banking_deposit_req {
- short PacketType;
- unsigned int AID;
- int Money;
+ int16 PacketType;
+ uint32 AID;
+ int32 Money;
} __attribute__((packed));
struct packet_banking_withdraw_req {
- short PacketType;
- unsigned int AID;
- int Money;
+ int16 PacketType;
+ uint32 AID;
+ int32 Money;
} __attribute__((packed));
struct packet_banking_deposit_ack {
- short PacketType;
- short Reason;
+ int16 PacketType;
+ int16 Reason;
int64 Money;
- int Balance;
+ int32 Balance;
} __attribute__((packed));
struct packet_banking_withdraw_ack {
- short PacketType;
- short Reason;
+ int16 PacketType;
+ int16 Reason;
int64 Money;
- int Balance;
+ int32 Balance;
} __attribute__((packed));
/* Roulette System [Yommy/Hercules] */
struct packet_roulette_open_ack {
- short PacketType;
- char Result;
- int Serial;
- char Step;
- char Idx;
- short AdditionItemID;
- int GoldPoint;
- int SilverPoint;
- int BronzePoint;
+ int16 PacketType;
+ int8 Result;
+ int32 Serial;
+ int8 Step;
+ int8 Idx;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 AdditionItemID;
+#else
+ uint16 AdditionItemID;
+#endif
+ int32 GoldPoint;
+ int32 SilverPoint;
+ int32 BronzePoint;
} __attribute__((packed));
struct packet_roulette_info_ack {
- short PacketType;
- short PacketLength;
- unsigned int RouletteSerial;
+ int16 PacketType;
+ int16 PacketLength;
+ uint32 RouletteSerial;
struct {
- unsigned short Row;
- unsigned short Position;
- unsigned short ItemId;
- unsigned short Count;
+ uint16 Row;
+ uint16 Position;
+#if PACKETVER >= 20180511
+ uint32 ItemId;
+ uint16 Count;
+ uint16 unused;
+#else
+ uint16 ItemId;
+ uint16 Count;
+#endif
} ItemInfo[42];
} __attribute__((packed));
struct packet_roulette_close_ack {
- short PacketType;
- unsigned char Result;
+ int16 PacketType;
+ uint8 Result;
} __attribute__((packed));
struct packet_roulette_generate_ack {
- short PacketType;
- unsigned char Result;
- unsigned short Step;
- unsigned short Idx;
- unsigned short AdditionItemID;
- int RemainGold;
- int RemainSilver;
- int RemainBronze;
+ int16 PacketType;
+ uint8 Result;
+ uint16 Step;
+ uint16 Idx;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 AdditionItemID;
+#else
+ uint16 AdditionItemID;
+#endif
+ int32 RemainGold;
+ int32 RemainSilver;
+ int32 RemainBronze;
} __attribute__((packed));
struct packet_roulette_itemrecv_req {
- short PacketType;
- unsigned char Condition;
+ int16 PacketType;
+ uint8 Condition;
} __attribute__((packed));
struct packet_roulette_itemrecv_ack {
- short PacketType;
- unsigned char Result;
- unsigned short AdditionItemID;
+ int16 PacketType;
+ uint8 Result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 AdditionItemID;
+#else
+ uint16 AdditionItemID;
+#endif
} __attribute__((packed));
struct packet_itemlist_normal {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
struct NORMALITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
struct packet_itemlist_equip {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
struct EQUIPITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
-struct packet_storelist_normal {
- short PacketType;
- short PacketLength;
-#if PACKETVER >= 20120925
+struct ZC_STORE_ITEMLIST_NORMAL {
+ int16 PacketType;
+ int16 PacketLength;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
char name[NAME_LENGTH];
#endif
struct NORMALITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
-struct packet_storelist_equip {
- short PacketType;
- short PacketLength;
-#if PACKETVER >= 20120925
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+struct PACKET_ZC_INVENTORY_START {
+ int16 packetType;
+#if PACKETVER_RE_NUM >= 20180919 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ int16 packetLength;
+#endif
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
+#if PACKETVER_RE_NUM >= 20180919 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ char name[];
+#else
+ char name[NAME_LENGTH];
+#endif
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_INVENTORY_START, 0x0b08);
+#endif // PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+
+#if PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+struct PACKET_ZC_INVENTORY_END {
+ int16 packetType;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
+ char flag;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_INVENTORY_END, 0x0b0b);
+#endif // PACKETVER_RE_NUM >= 20180829 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+
+struct ZC_STORE_ITEMLIST_EQUIP {
+ int16 PacketType;
+ int16 PacketLength;
+#if PACKETVER_RE_NUM >= 20180912 || PACKETVER_ZERO_NUM >= 20180919 || PACKETVER_MAIN_NUM >= 20181002
+ uint8 invType;
+#endif
+#if PACKETVER >= 20120925 && PACKETVER_RE_NUM < 20180829 && PACKETVER_ZERO_NUM < 20180919 && PACKETVER_MAIN_NUM < 20181002
char name[NAME_LENGTH];
#endif
struct EQUIPITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
struct packet_equip_item {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
} __attribute__((packed));
struct packet_equipitem_ack {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
#if PACKETVER >= 20100629
- unsigned short wItemSpriteNumber;
+ uint16 wItemSpriteNumber;
#endif
- unsigned char result;
+ uint8 result;
} __attribute__((packed));
struct packet_unequipitem_ack {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
- unsigned char result;
+ uint8 result;
} __attribute__((packed));
struct packet_viewequip_ack {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
char characterName[NAME_LENGTH];
- short job;
- short head;
- short accessory;
- short accessory2;
- short accessory3;
+ int16 job;
+ int16 head;
+ int16 accessory;
+ int16 accessory2;
+ int16 accessory3;
#if PACKETVER >= 20101124
- short robe;
+ int16 robe;
+#endif
+ int16 headpalette;
+ int16 bodypalette;
+#if PACKETVER_MAIN_NUM >= 20180801 || PACKETVER_RE_NUM >= 20180801 || PACKETVER_ZERO_NUM >= 20180808
+ int16 body2;
#endif
- short headpalette;
- short bodypalette;
- unsigned char sex;
+ uint8 sex;
+ // [4144] need remove MAX_INVENTORY from here
struct EQUIPITEM_INFO list[MAX_INVENTORY];
} __attribute__((packed));
struct packet_notify_bounditem {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
} __attribute__((packed));
struct packet_skill_entry {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20110718
- short PacketLength;
+ int16 PacketLength;
#endif
- unsigned int AID;
- unsigned int creatorAID;
- short xPos;
- short yPos;
+ uint32 AID;
+ uint32 creatorAID;
+ int16 xPos;
+ int16 yPos;
#if PACKETVER >= 20121212
- int job;
+ int32 job;
#else
- unsigned char job;
+ uint8 job;
#endif
#if PACKETVER >= 20110718
- char RadiusRange;
+ int8 RadiusRange;
#endif
- unsigned char isVisible;
+ uint8 isVisible;
#if PACKETVER >= 20130731
- unsigned char level;
+ uint8 level;
#endif
} __attribute__((packed));
struct packet_graffiti_entry {
- short PacketType;
- unsigned int AID;
- unsigned int creatorAID;
- short xPos;
- short yPos;
- unsigned char job;
- unsigned char isVisible;
- unsigned char isContens;
+ int16 PacketType;
+ uint32 AID;
+ uint32 creatorAID;
+ int16 xPos;
+ int16 yPos;
+ uint8 job;
+ uint8 isVisible;
+ uint8 isContens;
char msg[80];
} __attribute__((packed));
struct packet_damage {
- short PacketType;
- unsigned int GID;
- unsigned int targetGID;
- unsigned int startTime;
- int attackMT;
- int attackedMT;
+ int16 PacketType;
+ uint32 GID;
+ uint32 targetGID;
+ uint32 startTime;
+ int32 attackMT;
+ int32 attackedMT;
#if PACKETVER < 20071113
- short damage;
+ int16 damage;
#else
- int damage;
+ int32 damage;
#endif
#if PACKETVER >= 20131223
- unsigned char is_sp_damaged;
+ uint8 is_sp_damaged;
#endif
- short count;
- unsigned char action;
+ int16 count;
+ uint8 action;
#if PACKETVER < 20071113
- short leftDamage;
+ int16 leftDamage;
#else
- int leftDamage;
+ int32 leftDamage;
#endif
} __attribute__((packed));
struct packet_gm_monster_item {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20131218
char str[100];
#else
@@ -1103,77 +1355,159 @@ struct packet_gm_monster_item {
} __attribute__((packed));
struct packet_npc_market_purchase {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
struct {
- unsigned short ITID;
- int qty;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
+ int32 qty;
} list[]; // Note: We assume this should be <= MAX_INVENTORY (since you can't hold more than MAX_INVENTORY items thus cant buy that many at once).
} __attribute__((packed));
-struct packet_npc_market_result_ack {
- short PacketType;
- short PacketLength;
- unsigned char result;
- struct {
- unsigned short ITID;
- unsigned short qty;
- unsigned int price;
- } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */
+#if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20131106 || defined(PACKETVER_ZERO)
+/* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
+struct PACKET_ZC_NPC_MARKET_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 nameid;
+#else
+ uint16 nameid;
+#endif
+ uint8 type;
+ uint32 price;
+ uint32 qty;
+ uint16 weight;
} __attribute__((packed));
-struct packet_npc_market_open {
- short PacketType;
- short PacketLength;
- /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
- struct {
- unsigned short nameid;
- unsigned char type;
- 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? */
+struct PACKET_ZC_NPC_MARKET_OPEN {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_NPC_MARKET_OPEN_sub list[];
} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_MARKET_OPEN, 0x09d5);
+#endif
+
struct packet_wis_end {
- short PacketType;
- char result;
+ int16 PacketType;
+ int8 result;
#if PACKETVER >= 20131223
- unsigned int unknown;/* maybe AID, not sure what for (works sending as 0) */
+ uint32 AID;
#endif
} __attribute__((packed));
struct packet_party_leader_changed {
- short PacketType;
- unsigned int prev_leader_aid;
- unsigned int new_leader_aid;
+ int16 PacketType;
+ uint32 prev_leader_aid;
+ uint32 new_leader_aid;
} __attribute__((packed));
-struct packet_hotkey {
#ifdef HOTKEY_SAVING
- short PacketType;
-#if PACKETVER >= 20141022
- char Rotate;
+struct hotkey_data {
+ int8 isSkill; // 0: Item, 1:Skill
+ uint32 id; // Item/Skill ID
+ int16 count; // Item Quantity/Skill Level
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+#define MAX_HOTKEYS_PACKET 38
+struct PACKET_ZC_SHORTCUT_KEY_LIST {
+ int16 packetType;
+ int8 rotate;
+ int16 tab;
+ struct hotkey_data hotkey[MAX_HOTKEYS_PACKET];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SHORTCUT_KEY_LIST, 0x0b20);
+#elif PACKETVER_MAIN_NUM >= 20141022 || PACKETVER_RE_NUM >= 20141015 || defined(PACKETVER_ZERO)
+#define MAX_HOTKEYS_PACKET 38
+struct PACKET_ZC_SHORTCUT_KEY_LIST {
+ int16 packetType;
+ int8 rotate;
+ struct hotkey_data hotkey[MAX_HOTKEYS_PACKET];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SHORTCUT_KEY_LIST, 0x0a00);
+#elif PACKETVER_MAIN_NUM >= 20090617 || PACKETVER_RE_NUM >= 20090617 || PACKETVER_SAK_NUM >= 20090617
+#define MAX_HOTKEYS_PACKET 38
+struct PACKET_ZC_SHORTCUT_KEY_LIST {
+ int16 packetType;
+ struct hotkey_data hotkey[MAX_HOTKEYS_PACKET];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SHORTCUT_KEY_LIST, 0x07d9);
+#elif PACKETVER_MAIN_NUM >= 20090603 || PACKETVER_RE_NUM >= 20090603 || PACKETVER_SAK_NUM >= 20090603
+#define MAX_HOTKEYS_PACKET 36
+struct PACKET_ZC_SHORTCUT_KEY_LIST {
+ int16 packetType;
+ struct hotkey_data hotkey[MAX_HOTKEYS_PACKET];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SHORTCUT_KEY_LIST, 0x07d9);
+#elif PACKETVER_MAIN_NUM >= 20070711 || PACKETVER_RE_NUM >= 20080827 || PACKETVER_AD_NUM >= 20070711 || PACKETVER_SAK_NUM >= 20070628
+#define MAX_HOTKEYS_PACKET 27
+struct PACKET_ZC_SHORTCUT_KEY_LIST {
+ int16 packetType;
+ struct hotkey_data hotkey[MAX_HOTKEYS_PACKET];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SHORTCUT_KEY_LIST, 0x02b9);
#endif
- struct {
- char isSkill; // 0: Item, 1:Skill
- unsigned int ID; // Item/Skill ID
- short count; // Item Quantity/Skill Level
- } hotkey[MAX_HOTKEYS];
-#else // not HOTKEY_SAVING
- UNAVAILABLE_STRUCT;
-#endif // HOTKEY_SAVING
+
+#if PACKETVER_MAIN_NUM >= 20070618 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO) || PACKETVER_AD_NUM >= 20070618 || PACKETVER_SAK_NUM >= 20070618
+struct PACKET_CZ_SHORTCUT_KEY_CHANGE1 {
+ int16 packetType;
+ uint16 index;
+ struct hotkey_data hotkey;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SHORTCUT_KEY_CHANGE1, 0x02ba);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+struct PACKET_CZ_SHORTCUT_KEY_CHANGE2 {
+ int16 packetType;
+ uint16 tab;
+ uint16 index;
+ struct hotkey_data hotkey;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SHORTCUT_KEY_CHANGE2, 0x0b21);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20140129 || PACKETVER_RE_NUM >= 20140129 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_SHORTCUTKEYBAR_ROTATE1 {
+ int16 packetType;
+ uint8 rowshift;
} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SHORTCUTKEYBAR_ROTATE1, 0x0a01);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190508 || PACKETVER_ZERO_NUM >= 20190605
+struct PACKET_CZ_SHORTCUTKEYBAR_ROTATE2 {
+ int16 packetType;
+ uint16 tab;
+ uint8 rowshift;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SHORTCUTKEYBAR_ROTATE2, 0x0b22);
+#endif
+
+#endif // HOTKEY_SAVING
/**
- * MISSION_HUNT_INFO
+ * MISSION_HUNT_INFO (PACKETVER >= 20141022)
+ * MISSION_HUNT_INFO_EX (PACKETVER >= 20150513)
*/
struct packet_mission_info_sub {
- int32 mob_id;
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ uint32 huntIdent;
+ uint32 huntIdent2;
+ uint32 mobType;
+#elif PACKETVER >= 20150513
+ uint32 huntIdent;
+ uint32 mobType;
+#endif
+ uint32 mob_id;
+#if PACKETVER >= 20150513
+ int16 levelMin;
+ int16 levelMax;
+#endif
int16 huntCount;
int16 maxCount;
char mobName[NAME_LENGTH];
@@ -1181,7 +1515,7 @@ struct packet_mission_info_sub {
/**
* PACKET_ZC_ALL_QUEST_LIST2_INFO (PACKETVER >= 20141022)
- * PACKET_ZC_ALL_QUEST_LIST3_INFO (PACKETVER Unknown) / unused
+ * PACKET_ZC_ALL_QUEST_LIST3_INFO (PACKETVER >= 20150513)
*/
struct packet_quest_list_info {
int32 questID;
@@ -1198,7 +1532,7 @@ struct packet_quest_list_info {
* Header for:
* PACKET_ZC_ALL_QUEST_LIST (PACKETVER < 20141022)
* PACKET_ZC_ALL_QUEST_LIST2 (PACKETVER >= 20141022)
- * PACKET_ZC_ALL_QUEST_LIST3 (PACKETVER Unknown) / unused
+ * PACKET_ZC_ALL_QUEST_LIST3 (PACKETVER >= 20150513)
*
* @remark
* Contains (is followed by) a variable-length array of packet_quest_list_info
@@ -1210,6 +1544,2389 @@ struct packet_quest_list_header {
//struct packet_quest_list_info list[]; // Variable-length
} __attribute__((packed));
+struct packet_chat_message {
+ uint16 packet_id;
+ int16 packet_len;
+ char message[];
+} __attribute__((packed));
+
+struct packet_whisper_message {
+ uint16 packet_id;
+ int16 packet_len;
+ char name[NAME_LENGTH];
+ char message[];
+} __attribute__((packed));
+
+/* RoDEX */
+struct PACKET_CZ_ADD_ITEM_TO_MAIL {
+ int16 PacketType;
+ int16 index;
+ int16 count;
+} __attribute__((packed));
+
+struct PACKET_ZC_ADD_ITEM_TO_MAIL {
+ int16 PacketType;
+ int8 result;
+ int16 index;
+ int16 count;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ int8 type;
+ int8 IsIdentified;
+ int8 IsDamaged;
+ int8 refiningLevel;
+ struct EQUIPSLOTINFO slot;
+ struct ItemOptions optionData[MAX_ITEM_OPTIONS];
+ int16 weight;
+ uint8 favorite;
+ uint32 location;
+} __attribute__((packed));
+
+struct mail_item {
+ int16 count;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
+ int8 IsIdentified;
+ int8 IsDamaged;
+ int8 refiningLevel;
+ struct EQUIPSLOTINFO slot;
+ uint32 location;
+ uint8 type;
+ uint16 viewSprite;
+ uint16 bindOnEquip;
+ struct ItemOptions optionData[MAX_ITEM_OPTIONS];
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_OPEN_WRITE_MAIL {
+ int16 PacketType;
+ char receiveName[NAME_LENGTH];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_OPEN_WRITE_MAIL {
+ int16 PacketType;
+ char receiveName[NAME_LENGTH];
+ int8 result;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_REMOVE_ITEM_MAIL {
+ int16 PacketType;
+ int16 index;
+ uint16 cnt;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_REMOVE_ITEM_MAIL {
+ int16 PacketType;
+ int8 result;
+ int16 index;
+ uint16 cnt;
+ int16 weight;
+} __attribute__((packed));
+
+struct PACKET_CZ_SEND_MAIL {
+ int16 PacketType;
+ int16 PacketLength;
+ char receiveName[24];
+ char senderName[24];
+ int64 zeny;
+ int16 Titlelength;
+ int16 TextcontentsLength;
+#if PACKETVER > 20160600
+ int32 receiver_char_id;
+#endif // PACKETVER > 20160600
+ char string[];
+} __attribute__((packed));
+
+struct PACKET_ZC_WRITE_MAIL_RESULT {
+ int16 PacketType;
+ int8 result;
+} __attribute__((packed));
+
+struct PACKET_CZ_CHECKNAME {
+ int16 PacketType;
+ char Name[24];
+} __attribute__((packed));
+
+struct PACKET_ZC_CHECKNAME {
+ int16 PacketType;
+ int32 CharId;
+ int16 Class;
+ int16 BaseLevel;
+#if PACKETVER >= 20160316
+ char Name[24];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_UNREADMAIL {
+ int16 PacketType;
+ char result;
+} __attribute__((packed));
+
+struct maillistinfo {
+#if PACKETVER >= 20170419
+ uint8 openType;
+#endif
+ int64 MailID;
+ int8 Isread;
+ uint8 type;
+ char SenderName[24];
+#if PACKETVER < 20170419
+ int32 regDateTime;
+#endif
+ int32 expireDateTime;
+ int16 Titlelength;
+ char title[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MAIL_LIST {
+ int16 PacketType;
+ int16 PacketLength;
+#if PACKETVER < 20170419
+ int8 opentype;
+ int8 cnt;
+#endif
+ int8 IsEnd;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_NEXT_MAIL_LIST {
+ int16 PacketType;
+ int8 opentype;
+ int64 Lower_MailID;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_OPEN_MAIL {
+ int16 PacketType;
+#if PACKETVER >= 20170419
+ int64 char_Upper_MailID;
+ int64 return_Upper_MailID;
+ int64 account_Upper_MailID;
+#else
+ int8 opentype;
+ int64 Upper_MailID;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_READ_MAIL {
+ int16 PacketType;
+ int8 opentype;
+ int64 MailID;
+} __attribute__((packed));
+
+struct PACKET_ZC_READ_MAIL {
+ int16 PacketType;
+ int16 PacketLength;
+ int8 opentype;
+ int64 MailID;
+ int16 TextcontentsLength;
+ int64 zeny;
+ int8 ItemCnt;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_DELETE_MAIL {
+ int16 PacketType;
+ int8 opentype;
+ int64 MailID;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_DELETE_MAIL {
+ int16 PacketType;
+ int8 opentype;
+ int64 MailID;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_REFRESH_MAIL_LIST {
+ int16 PacketType;
+#if PACKETVER >= 20170419
+ int64 Upper_MailID;
+ int8 unknown[16];
+#else
+ int8 opentype;
+ int64 Upper_MailID;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_ZENY_FROM_MAIL {
+ int16 PacketType;
+ int64 MailID;
+ int8 opentype;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_ZENY_FROM_MAIL {
+ int16 PacketType;
+ int64 MailID;
+ int8 opentype;
+ int8 result;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_ITEM_FROM_MAIL {
+ int16 PacketType;
+ int64 MailID;
+ int8 opentype;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_ITEM_FROM_MAIL {
+ int16 PacketType;
+ int64 MailID;
+ int8 opentype;
+ int8 result;
+} __attribute__((packed));
+
+struct PACKET_ZC_SKILL_SCALE {
+ int16 PacketType;
+ uint32 AID;
+ int16 skill_id;
+ int16 skill_lv;
+ int16 x;
+ int16 y;
+ uint32 casttime;
+} __attribute__((packed));
+
+struct ZC_PROGRESS_ACTOR {
+ int16 PacketType;
+ int32 GID;
+ int32 color;
+ uint32 time;
+} __attribute__((packed));
+
+struct PACKET_ZC_ADD_MEMBER_TO_GROUP {
+ int16 packetType;
+ uint32 AID;
+#if PACKETVER >= 20171207
+ uint32 GID;
+#endif
+ uint32 leader;
+#if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ int16 class;
+ int16 baseLevel;
+#endif
+ int16 x;
+ int16 y;
+ uint8 offline;
+ char partyName[NAME_LENGTH];
+ char playerName[NAME_LENGTH];
+ char mapName[MAP_NAME_LENGTH_EXT];
+ int8 sharePickup;
+ int8 shareLoot;
+} __attribute__((packed));
+
+struct PACKET_ZC_GROUP_LIST_SUB {
+ uint32 AID;
+#if PACKETVER >= 20171207
+ uint32 GID;
+#endif
+ char playerName[NAME_LENGTH];
+ char mapName[MAP_NAME_LENGTH_EXT];
+ uint8 leader;
+ uint8 offline;
+#if PACKETVER_MAIN_NUM >= 20170524 || PACKETVER_RE_NUM >= 20170502 || defined(PACKETVER_ZERO)
+ int16 class;
+ int16 baseLevel;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_GROUP_LIST {
+ int16 packetType;
+ int16 packetLen;
+ char partyName[NAME_LENGTH];
+ struct PACKET_ZC_GROUP_LIST_SUB members[];
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20130626 || PACKETVER_RE_NUM >= 20130605 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_CLANINFO {
+ int16 PacketType;
+ int16 PacketLength;
+ uint32 ClanID;
+ char ClanName[NAME_LENGTH];
+ char MasterName[NAME_LENGTH];
+ char Map[MAP_NAME_LENGTH_EXT];
+ uint8 AllyCount;
+ uint8 AntagonistCount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CLANINFO, 0x098a);
+#endif
+
+struct PACKET_ZC_NOTIFY_CLAN_CONNECTINFO {
+ int16 PacketType;
+ int16 NumConnect;
+ int16 NumTotal;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_CLAN_LEAVE {
+ int16 PacketType;
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_CLAN_CHAT {
+ int16 PacketType;
+ int16 PacketLength;
+ char MemberName[NAME_LENGTH];
+ char Message[];
+} __attribute__((packed));
+
+/**
+ * PACKET_ZC_MISSION_HUNT (PACKETVER < 20150513)
+ * PACKET_ZC_MISSION_HUNT_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_sub {
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ uint32 huntIdent;
+ uint32 huntIdent2;
+ uint32 mobType;
+#elif PACKETVER >= 20150513
+ uint32 huntIdent;
+ uint32 mobType;
+#endif
+ uint32 mob_id;
+#if PACKETVER >= 20150513
+ int16 levelMin;
+ int16 levelMax;
+#endif
+ int16 huntCount;
+ char mobName[NAME_LENGTH];
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_ZC_ADD_QUEST (PACKETVER < 20150513)
+ * PACKET_ZC_ADD_QUEST_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_add_header {
+ uint16 PacketType;
+ uint32 questID;
+ uint8 active;
+ int32 quest_svrTime;
+ int32 quest_endTime;
+ int16 count;
+ struct packet_quest_hunt_sub objectives[];
+} __attribute__((packed));
+
+/**
+ * PACKET_MOB_HUNTING (PACKETVER < 20150513)
+ * PACKET_MOB_HUNTING_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_update_hunt {
+ uint32 questID;
+#if PACKETVER_ZERO_NUM >= 20181010 || PACKETVER >= 20181017
+ uint32 huntIdent;
+ uint32 huntIdent2;
+#elif PACKETVER >= 20150513
+ uint32 huntIdent;
+#else
+ uint32 mob_id;
+#endif // PACKETVER < 20150513
+ int16 maxCount;
+ int16 count;
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_ZC_UPDATE_MISSION_HUNT (PACKETVER < 20150513)
+ * PACKET_ZC_UPDATE_MISSION_HUNT_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_update_header {
+ uint16 PacketType;
+ uint16 PacketLength;
+ int16 count;
+ struct packet_quest_update_hunt objectives[];
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_MOB_HUNTING (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_info_sub {
+ uint32 questID;
+ uint32 mob_id;
+ int16 maxCount;
+ int16 count;
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * ZC_HUNTING_QUEST_INFO (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_info {
+ uint16 PacketType;
+ uint16 PacketLength;
+ struct packet_quest_hunt_info_sub info[];
+} __attribute__((packed));
+
+struct PACKET_ZC_FORMATSTRING_MSG {
+ uint16 PacketType;
+ uint16 PacketLength;
+ uint16 MessageId;
+ char MessageString[];
+} __attribute__((packed));
+
+struct PACKET_ZC_FORMATSTRING_MSG_COLOR {
+ uint16 PacketType;
+ uint16 PacketLength;
+ uint16 messageId;
+#if PACKETVER >= 20160406
+ uint32 color;
+#endif
+ char messageString[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MSG_COLOR {
+ uint16 PacketType;
+ uint16 MessageId;
+ uint32 MessageColor;
+} __attribute__((packed));
+
+struct PACKET_CZ_OPEN_UI {
+ int16 PacketType;
+ int8 UIType;
+} __attribute__((packed));
+
+struct PACKET_ZC_OPEN_UI {
+ int16 PacketType;
+ int8 UIType;
+#if PACKETVER >= 20171122
+ int32 data;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_UI_ACTION {
+ int16 PacketType;
+ int32 UIType;
+ int32 data;
+} __attribute__((packed));
+
+struct PACKET_CZ_PRIVATE_AIRSHIP_REQUEST {
+ int16 PacketType;
+ char mapName[MAP_NAME_LENGTH_EXT];
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ItemID;
+#else
+ uint16 ItemID;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_PRIVATE_AIRSHIP_RESPONSE {
+ int16 PacketType;
+ uint32 flag;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_STYLE_CHANGE {
+ int16 PacketType;
+ int16 HeadPalette;
+ int16 HeadStyle;
+ int16 BodyPalette;
+ int16 TopAccessory;
+ int16 MidAccessory;
+ int16 BottomAccessory;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_STYLE_CHANGE2 {
+ int16 PacketType;
+ int16 HeadPalette;
+ int16 HeadStyle;
+ int16 BodyPalette;
+ int16 TopAccessory;
+ int16 MidAccessory;
+ int16 BottomAccessory;
+ int16 BodyStyle;
+} __attribute__((packed));
+
+struct PACKET_ZC_STYLE_CHANGE_RES {
+ int16 PacketType;
+ int8 flag;
+} __attribute__((packed));
+
+struct pet_evolution_items {
+ int16 index;
+ int16 amount;
+} __attribute__((packed));
+
+struct PACKET_CZ_PET_EVOLUTION {
+ int16 PacketType;
+ uint16 PacketLength;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 EvolvedPetEggID;
+#else
+ uint16 EvolvedPetEggID;
+#endif
+ // struct pet_evolution_items items[];
+} __attribute__((packed));
+
+struct packet_ZC_REFUSE_LOGIN {
+ int16 PacketType;
+#if PACKETVER >= 20101123
+ uint32 error_code;
+#else
+ uint8 error_code;
+#endif
+ char block_date[20];
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_CHAT {
+ int16 PacketType;
+ int16 PacketLength;
+ uint32 GID;
+ char Message[];
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_PLAYERCHAT {
+ int16 PacketType;
+ int16 PacketLength;
+ char Message[];
+} __attribute__((packed));
+
+struct PACKET_ZC_ITEM_ENTRY {
+ int16 packetType;
+ uint32 AID;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 identify;
+ uint16 x;
+ uint16 y;
+ uint16 amount;
+ uint8 subX;
+ uint8 subY;
+} __attribute__((packed));
+
+struct PACKET_ZC_ADD_ITEM_TO_STORE {
+ int16 packetType;
+ int16 index;
+ int32 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+#if PACKETVER >= 5
+ uint8 itemType;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_MVP_GETTING_ITEM {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_TOUSESKILL {
+ int16 packetType;
+ uint16 skillId;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ int32 btype;
+ uint32 itemId;
+#else
+ int16 btype;
+ uint16 itemId;
+#endif
+ uint8 flag;
+ uint8 cause;
+} __attribute__((packed));
+
+struct PACKET_ZC_ADD_ITEM_TO_CART {
+ int16 packetType;
+ int16 index;
+ int32 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+#if PACKETVER >= 5
+ uint8 itemType;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_REQMAKINGITEM {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+ uint32 material[3];
+#else
+ uint16 itemId;
+ uint16 material[3];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_REQMAKINGITEM {
+ int16 packetType;
+ int16 result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_FEED_PET {
+ int16 packetType;
+ uint8 result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_FEED_MER {
+ int16 packetType;
+ uint8 result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_USE_ITEM_ACK {
+ int16 packetType;
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+ uint32 AID;
+#elif PACKETVER >= 3
+ uint16 itemId;
+ uint32 AID;
+#endif
+ int16 amount;
+ uint8 result;
+} __attribute__((packed));
+
+struct PACKET_ZC_SPRITE_CHANGE {
+ int16 packetType;
+ uint32 AID;
+ uint8 type;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 val;
+ uint32 val2;
+#elif PACKETVER >= 4
+ uint16 val;
+ uint16 val2;
+#else
+ uint8 val;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ADD_EXCHANGE_ITEM {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+ uint8 itemType;
+ int32 amount;
+#elif PACKETVER >= 20100223
+ uint16 itemId;
+ uint8 itemType;
+ int32 amount;
+#else
+ int32 amount;
+ uint16 itemId;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_CASH_TIME_COUNTER {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint32 seconds;
+} __attribute__((packed));
+
+struct PACKET_ZC_CASH_ITEM_DELETE {
+ int16 packetType;
+ uint16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ITEM_PICKUP_PARTY {
+ int16 packetType;
+ uint32 AID;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+ uint16 location;
+ uint8 itemType;
+} __attribute__((packed));
+
+struct PACKET_ZC_UPDATE_ITEM_FROM_BUYING_STORE {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 amount;
+#if PACKETVER >= 20141016
+ uint32 zeny;
+ uint32 zenyLimit;
+ uint32 charId;
+ uint32 updateTime;
+#else
+ uint32 zenyLimit;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_WEAPONREFINE {
+ int16 packetType;
+ int32 result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20190619 || PACKETVER_RE_NUM >= 20190605 || PACKETVER_ZERO_NUM >= 20190626
+// PACKET_ZC_PROPERTY_HOMUN3
+struct PACKET_ZC_PROPERTY_HOMUN {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
+ uint8 flags;
+ uint16 level;
+ uint16 hunger;
+ uint16 intimacy;
+ uint16 atk2;
+ uint16 matk;
+ uint16 hit;
+ uint16 crit;
+ uint16 def;
+ uint16 mdef;
+ uint16 flee;
+ uint16 amotion;
+ uint32 hp;
+ uint32 maxHp;
+ uint16 sp;
+ uint16 maxSp;
+ uint32 exp;
+ uint32 expNext;
+ uint16 skillPoints;
+ uint16 range;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PROPERTY_HOMUN, 0x0b2f);
+#elif PACKETVER_MAIN_NUM >= 20131230 || PACKETVER_RE_NUM >= 20131230 || defined(PACKETVER_ZERO)
+// PACKET_ZC_PROPERTY_HOMUN2
+struct PACKET_ZC_PROPERTY_HOMUN {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
+ uint8 flags;
+ uint16 level;
+ uint16 hunger;
+ uint16 intimacy;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 atk2;
+ uint16 matk;
+ uint16 hit;
+ uint16 crit;
+ uint16 def;
+ uint16 mdef;
+ uint16 flee;
+ uint16 amotion;
+ uint32 hp;
+ uint32 maxHp;
+ uint16 sp;
+ uint16 maxSp;
+ uint32 exp;
+ uint32 expNext;
+ uint16 skillPoints;
+ uint16 range;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PROPERTY_HOMUN, 0x09f7);
+#elif PACKETVER_MAIN_NUM >= 20101005 || PACKETVER_RE_NUM >= 20080827 || defined(PACKETVER_ZERO)
+// PACKET_ZC_PROPERTY_HOMUN1
+struct PACKET_ZC_PROPERTY_HOMUN {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
+ uint8 flags;
+ uint16 level;
+ uint16 hunger;
+ uint16 intimacy;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 atk2;
+ uint16 matk;
+ uint16 hit;
+ uint16 crit;
+ uint16 def;
+ uint16 mdef;
+ uint16 flee;
+ uint16 amotion;
+ uint16 hp;
+ uint16 maxHp;
+ uint16 sp;
+ uint16 maxSp;
+ uint32 exp;
+ uint32 expNext;
+ uint16 skillPoints;
+ uint16 range;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PROPERTY_HOMUN, 0x022e);
+#endif
+
+struct PACKET_ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER {
+ int16 packetType;
+ uint16 result;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_ITEMREPAIR {
+ int16 packetType;
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_MAKINGITEM {
+ int16 packetType;
+ int16 type;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_SSILIST_ITEM_CLICK {
+ int16 packetType;
+ uint32 AID;
+ uint32 storeId;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_SCHEDULER_CASHITEM_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint32 price;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_SCHEDULER_CASHITEM {
+ int16 packetType;
+ int16 packetLength;
+ int16 count;
+ int16 tabNum;
+ struct PACKET_ZC_ACK_SCHEDULER_CASHITEM_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_MYITEMLIST_sub {
+ uint32 price;
+ int16 index;
+ int16 amount;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_MYITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+ struct PACKET_ZC_PC_PURCHASE_MYITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub {
+ uint32 price;
+ uint32 discountPrice;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_CZ_PC_PURCHASE_ITEMLIST_sub {
+ uint16 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_PC_PURCHASE_ITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_CZ_PC_PURCHASE_ITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 amount;
+ uint32 price;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_OPEN_BUYING_STORE {
+ int16 packetType;
+ int16 packetLength;
+ uint32 zenyLimit;
+ uint8 result;
+ char storeName[MESSAGE_SIZE];
+ struct PACKET_CZ_REQ_OPEN_BUYING_STORE_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MYITEMLIST_BUYING_STORE_sub {
+ uint32 price;
+ uint16 amount;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_MYITEMLIST_BUYING_STORE {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+ uint32 zenyLimit;
+ struct PACKET_ZC_MYITEMLIST_BUYING_STORE_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC_sub {
+ uint32 price;
+ uint16 amount;
+ int16 index;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 identified;
+ uint8 damaged;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+// [4144] date 20160921 not confirmed. Can be bigger or smaller
+#if PACKETVER >= 20160921
+ uint32 location;
+ uint16 viewSprite;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+#if PACKETVER >= 20100105
+ uint32 venderId;
+#endif
+ struct PACKET_ZC_PC_PURCHASE_ITEMLIST_FROMMC_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE_sub {
+ uint32 price;
+ uint16 amount;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+ uint32 storeId;
+ uint32 zenyLimit;
+ struct PACKET_ZC_ACK_ITEMLIST_BUYING_STORE_sub items[];
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub {
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 amount;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_TRADE_BUYING_STORE {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+ uint32 storeId;
+ struct PACKET_CZ_REQ_TRADE_BUYING_STORE_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKABLEITEMLIST_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+ uint32 material[3];
+#else
+ uint16 itemId;
+ uint16 material[3];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKABLEITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_MAKABLEITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKINGARROW_LIST_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKINGARROW_LIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_MAKINGARROW_LIST_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_MAKINGARROW_LIST, 0x01ad);
+
+struct PACKET_ZC_REPAIRITEMLIST_sub {
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 refine; // unused?
+ struct EQUIPSLOTINFO slot; // unused?
+} __attribute__((packed));
+
+struct PACKET_ZC_REPAIRITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_REPAIRITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub {
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 refine; // unused?
+ struct EQUIPSLOTINFO slot; // unused?
+} __attribute__((packed));
+
+struct PACKET_ZC_NOTIFY_WEAPONITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_NOTIFY_WEAPONITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKINGITEM_LIST_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_MAKINGITEM_LIST {
+ int16 packetType;
+ int16 packetLength;
+ uint16 makeItem;
+ struct PACKET_ZC_MAKINGITEM_LIST_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_MAKINGITEM_LIST, 0x025a);
+
+struct PACKET_ZC_PC_CASH_POINT_ITEMLIST_sub {
+ uint32 price;
+ uint32 discountPrice;
+ uint8 itemType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_CASH_POINT_ITEMLIST {
+ int16 packetType;
+ int16 packetLength;
+ uint32 cashPoints;
+#if PACKETVER >= 20070711
+ uint32 kafraPoints;
+#endif
+ struct PACKET_ZC_PC_CASH_POINT_ITEMLIST_sub items[];
+} __attribute__((packed));
+
+struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub {
+ uint16 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM {
+ int16 packetType;
+#if PACKETVER >= 20101116
+ int16 packetLength;
+ uint32 kafraPoints;
+ uint16 count;
+ struct PACKET_CZ_PC_BUY_CASH_POINT_ITEM_sub items[];
+#else
+ uint16 itemId;
+ uint16 amount;
+#if PACKETVER >= 20070711
+ uint32 kafraPoints;
+#endif
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_SEARCH_STORE_INFO_item {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+
+struct PACKET_CZ_SEARCH_STORE_INFO {
+ int16 packetType;
+ int16 packetLength;
+ uint8 searchType;
+ uint32 maxPrice;
+ uint32 minPrice;
+ uint8 itemsCount;
+ uint8 cardsCount;
+ struct PACKET_CZ_SEARCH_STORE_INFO_item items[]; // items[itemCount]
+/*
+ struct PACKET_CZ_SEARCH_STORE_INFO_item cards[cardCount];
+*/
+} __attribute__((packed));
+
+struct PACKET_ZC_SEARCH_STORE_INFO_ACK_sub {
+ uint32 storeId;
+ uint32 AID;
+ char shopName[MESSAGE_SIZE];
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint8 itemType;
+ uint32 price;
+ uint16 amount;
+ uint8 refine;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20150226
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_SEARCH_STORE_INFO_ACK {
+ int16 packetType;
+ int16 packetLength;
+ uint8 firstPage;
+ uint8 nextPage;
+ uint8 usesCount;
+ struct PACKET_ZC_SEARCH_STORE_INFO_ACK_sub items[];
+} __attribute__((packed));
+
+/* Achievement System */
+struct ach_list_info {
+ uint32 ach_id;
+ uint8 completed;
+ uint32 objective[MAX_ACHIEVEMENT_OBJECTIVES];
+ uint32 completed_at;
+ uint8 reward;
+} __attribute__((packed));
+
+struct packet_achievement_list {
+ uint16 packet_id;
+ uint16 packet_len;
+ uint32 total_achievements;
+ uint32 total_points;
+ uint16 rank;
+ uint32 current_rank_points;
+ uint32 next_rank_points;
+ struct ach_list_info ach[MAX_ACHIEVEMENT_DB];
+} __attribute__((packed));
+
+struct packet_achievement_update {
+ uint16 packet_id;
+ uint32 total_points;
+ uint16 rank;
+ uint32 current_rank_points;
+ uint32 next_rank_points;
+ struct ach_list_info ach;
+} __attribute__((packed));
+
+struct packet_achievement_reward_ack {
+ uint16 packet_id;
+ uint8 failed;
+ uint32 ach_id;
+} __attribute__((packed));
+
+// Name Packet ZC_ACK_REQNAME
+struct packet_reqname_ack {
+ uint16 packet_id;
+ int32 gid;
+ char name[NAME_LENGTH];
+} __attribute__((packed));
+
+// ZC_ACK_REQNAMEALL / ZC_ACK_REQNAMEALL2
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_ACK_REQNAMEALL {
+ uint16 packet_id;
+ int32 gid;
+ char name[NAME_LENGTH];
+ char party_name[NAME_LENGTH];
+ char guild_name[NAME_LENGTH];
+ char position_name[NAME_LENGTH];
+ int32 title_id;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_REQNAMEALL, 0x0a30);
+#else
+struct PACKET_ZC_ACK_REQNAMEALL {
+ uint16 packet_id;
+ int32 gid;
+ char name[NAME_LENGTH];
+ char party_name[NAME_LENGTH];
+ char guild_name[NAME_LENGTH];
+ char position_name[NAME_LENGTH];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_REQNAMEALL, 0x0195);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+struct PACKET_ZC_ACK_REQNAME_TITLE {
+ uint16 packet_id;
+ int32 gid;
+ int32 groupId;
+ char name[NAME_LENGTH];
+ char title[NAME_LENGTH];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_REQNAME_TITLE, 0x0adf);
+#else
+struct PACKET_ZC_ACK_REQNAME_TITLE {
+ uint16 packet_id;
+ int32 gid;
+ char name[NAME_LENGTH];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_REQNAME_TITLE, 0x0095);
+#endif
+
+struct PACKET_ZC_OVERWEIGHT_PERCENT {
+ int16 packetType;
+ uint32 percent;
+} __attribute__((packed));
+
+struct PACKET_ZC_WARPLIST_sub {
+ char map[MAP_NAME_LENGTH_EXT];
+} __attribute__((packed));
+
+struct PACKET_ZC_WARPLIST {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20170502 || PACKETVER_RE_NUM >= 20170419 || defined(PACKETVER_ZERO)
+ int16 packetLength;
+ uint16 skillId;
+ struct PACKET_ZC_WARPLIST_sub maps[];
+#else
+ uint16 skillId;
+ struct PACKET_ZC_WARPLIST_sub maps[4];
+#endif
+} __attribute__((packed));
+
+struct PACKET_ZC_GROUP_ISALIVE {
+ int16 packetType;
+ uint32 AID;
+ uint8 isDead;
+} __attribute__((packed));
+
+struct PACKET_ZC_GUILD_POSITION {
+ int16 packetType;
+ int16 packetLength;
+ uint32 AID;
+ char position[];
+} __attribute__((packed));
+
+struct PACKET_ZC_INVENTORY_MOVE_FAILED {
+ int16 packetType;
+ int16 index;
+ int16 unknown;
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+#define PACKET_ZC_ACK_BAN_GUILD PACKET_ZC_ACK_BAN_GUILD3
+#elif PACKETVER >= 20100803
+#define PACKET_ZC_ACK_BAN_GUILD PACKET_ZC_ACK_BAN_GUILD2
+#else
+#define PACKET_ZC_ACK_BAN_GUILD PACKET_ZC_ACK_BAN_GUILD1
+#endif
+
+struct PACKET_ZC_ACK_BAN_GUILD1 {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ char reason[40];
+ char account_name[NAME_LENGTH];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_BAN_GUILD2 {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ char reason[40];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_BAN_GUILD3 {
+ int16 packetType;
+ char reason[40];
+ uint32 GID;
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+#define PACKET_ZC_ACK_LEAVE_GUILD PACKET_ZC_ACK_LEAVE_GUILD2
+#else
+#define PACKET_ZC_ACK_LEAVE_GUILD PACKET_ZC_ACK_LEAVE_GUILD1
+#endif
+
+struct PACKET_ZC_ACK_LEAVE_GUILD1 {
+ int16 packetType;
+ char name[NAME_LENGTH];
+ char reason[40];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_LEAVE_GUILD2 {
+ int16 packetType;
+ uint32 GID;
+ char reason[40];
+} __attribute__((packed));
+
+struct PACKET_CZ_MEMORIALDUNGEON_COMMAND {
+ int16 packetType;
+ int32 command;
+} __attribute__((packed));
+
+struct PACKET_ZC_REMOVE_EFFECT {
+ int16 packetType;
+ uint32 aid;
+ uint32 effectId;
+} __attribute__((packed));
+
+#if PACKETVER >= 20160525
+struct PACKET_ZC_CAMERA_INFO {
+ int16 packetType;
+ int8 action;
+ float range;
+ float rotation;
+ float latitude;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CAMERA_INFO, 0x0a78);
+#endif
+
+#if PACKETVER >= 20160525
+struct PACKET_CZ_CAMERA_INFO {
+ int16 packetType;
+ int8 action;
+ float range;
+ float rotation;
+ float latitude;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CAMERA_INFO, 0x0a77);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181128 || PACKETVER_RE_NUM >= 20181031
+// PACKET_ZC_AUTOSPELLLIST2
+struct PACKET_ZC_AUTOSPELLLIST {
+ int16 packetType;
+ int16 packetLength;
+ int skills[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_AUTOSPELLLIST, 0x0afb);
+#elif PACKETVER_MAIN_NUM >= 20090406 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO) || PACKETVER_SAK_NUM >= 20080618
+// PACKET_ZC_AUTOSPELLLIST1
+struct PACKET_ZC_AUTOSPELLLIST {
+ int16 packetType;
+ int skills[7];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_AUTOSPELLLIST, 0x01cd);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+#if PACKETVER_MAIN_NUM >= 20181017 || PACKETVER_RE_NUM >= 20181017 || PACKETVER_ZERO_NUM >= 20181024
+struct PACKET_ZC_ITEM_PREVIEW {
+ int16 packetType;
+ int16 index;
+ int8 isDamaged;
+ int16 refiningLevel;
+ struct EQUIPSLOTINFO slot;
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ITEM_PREVIEW, 0x0b13);
+#else // PACKETVER_MAIN_NUM >= 20181017 || PACKETVER_RE_NUM >= 20181017 || PACKETVER_ZERO_NUM >= 20181024
+
+struct PACKET_ZC_ITEM_PREVIEW {
+ int16 packetType;
+ int16 index;
+ int16 refiningLevel;
+ struct EQUIPSLOTINFO slot;
+ struct ItemOptions option_data[MAX_ITEM_OPTIONS];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ITEM_PREVIEW, 0x0ab9);
+#endif // PACKETVER_MAIN_NUM >= 20181017 || PACKETVER_RE_NUM >= 20181017 || PACKETVER_ZERO_NUM >= 20181024
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20160831 || PACKETVER_RE_NUM >= 20151118 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_ENCHANT_EQUIPMENT {
+ int16 packetType;
+ int16 wearState;
+ int16 cardSlot;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ int32 itemId;
+#else
+ int16 itemId;
+#endif
+ int8 equipFlag;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ENCHANT_EQUIPMENT, 0x0a3f);
+#endif // PACKETVER_MAIN_NUM >= 20160831 || PACKETVER_RE_NUM >= 20151118 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20170830 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_SERVICE_MESSAGE_COLOR {
+ int16 packetType;
+ int16 packetLength;
+ int32 color;
+ char message[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SERVICE_MESSAGE_COLOR, 0x0adb);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181002 || PACKETVER_RE_NUM >= 20181002 || PACKETVER_ZERO_NUM >= 20181010
+struct PACKET_CZ_START_USE_SKILL {
+ int16 packetType;
+ int16 skillId;
+ int16 skillLv;
+ uint32 targetId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_START_USE_SKILL, 0x0b10);
+
+struct PACKET_CZ_STOP_USE_SKILL {
+ int16 packetType;
+ int16 skillId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_STOP_USE_SKILL, 0x0b11);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+struct PACKET_ZC_INVENTORY_EXPANSION_INFO {
+ int16 packetType;
+ int16 expansionSize;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_INVENTORY_EXPANSION_INFO, 0x0b18);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+struct PACKET_ZC_ACK_INVENTORY_EXPAND {
+ int16 packetType;
+ uint8 result;
+ uint32 itemId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_INVENTORY_EXPAND, 0x0b15);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181219 || PACKETVER_RE_NUM >= 20181219 || PACKETVER_ZERO_NUM >= 20181212
+struct PACKET_ZC_ACK_INVENTORY_EXPAND_RESULT {
+ int16 packetType;
+ uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_INVENTORY_EXPAND_RESULT, 0x0b17);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+struct PACKET_CZ_INVENTORY_EXPAND {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_INVENTORY_EXPAND, 0x0b14);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+struct PACKET_CZ_INVENTORY_EXPAND_CONFIRMED {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_INVENTORY_EXPAND_CONFIRMED, 0x0b16);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181031 || PACKETVER_RE_NUM >= 20181031 || PACKETVER_ZERO_NUM >= 20181114
+struct PACKET_CZ_INVENTORY_EXPAND_REJECTED {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_INVENTORY_EXPAND_REJECTED, 0x0b19);
+#endif
+
+struct PACKET_CZ_REQ_REMAINTIME {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_REMAINTIME, 0x01c0);
+
+struct PACKET_CZ_PARTY_CONFIG {
+ int16 packetType;
+ uint8 refuseInvite;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_PARTY_CONFIG, 0x02c8);
+
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+struct PACKET_ZC_NPC_BARTER_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 nameid;
+#else
+ uint16 nameid;
+#endif
+ uint8 type;
+ uint32 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 currencyNameid;
+#else
+ uint16 currencyNameid;
+#endif
+ uint32 currencyAmount;
+ uint32 weight;
+ uint32 index;
+} __attribute__((packed));
+
+struct PACKET_ZC_NPC_BARTER_OPEN {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_ZC_NPC_BARTER_OPEN_sub list[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_NPC_BARTER_OPEN, 0x0b0e);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+struct PACKET_CZ_NPC_BARTER_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_NPC_BARTER_CLOSE, 0x0b12);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+struct PACKET_CZ_NPC_BARTER_PURCHASE_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint32 amount;
+ uint16 invIndex;
+ uint32 shopIndex;
+} __attribute__((packed));
+
+struct PACKET_CZ_NPC_BARTER_PURCHASE {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_CZ_NPC_BARTER_PURCHASE_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_NPC_BARTER_PURCHASE, 0x0b0f);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20181212 || PACKETVER_RE_NUM >= 20181212 || PACKETVER_ZERO_NUM >= 20190130
+struct PACKET_ZC_USESKILL_ACK {
+ int16 packetType;
+ uint32 srcId;
+ uint32 dstId;
+ uint16 x;
+ uint16 y;
+ uint16 skillId;
+ uint32 element;
+ uint32 delayTime;
+ uint8 disposable;
+ uint32 unknown;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_USESKILL_ACK, 0x0b1a);
+#elif PACKETVER_MAIN_NUM >= 20091124 || PACKETVER_RE_NUM >= 20091124 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_USESKILL_ACK {
+ int16 packetType;
+ uint32 srcId;
+ uint32 dstId;
+ uint16 x;
+ uint16 y;
+ uint16 skillId;
+ uint32 element;
+ uint32 delayTime;
+ uint8 disposable;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_USESKILL_ACK, 0x07fb);
+#elif PACKETVER_MAIN_NUM >= 20090406 || PACKETVER_SAK_NUM >= 20080618 || PACKETVER_RE_NUM >= 20080827 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_USESKILL_ACK {
+ int16 packetType;
+ uint32 srcId;
+ uint32 dstId;
+ uint16 x;
+ uint16 y;
+ uint16 skillId;
+ uint32 element;
+ uint32 delayTime;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_USESKILL_ACK, 0x013e);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20090406 || PACKETVER_RE_NUM >= 20090408 || PACKETVER_SAK_NUM >= 20090408 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_CLIENT_VERSION {
+ int16 packetType;
+ uint32 clientVersion;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CLIENT_VERSION, 0x044a);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190227 || PACKETVER_RE_NUM >= 20190220 || PACKETVER_ZERO_NUM >= 20190220
+struct PACKET_CZ_PING {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_PING, 0x0b1c);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190227 || PACKETVER_RE_NUM >= 20190220 || PACKETVER_ZERO_NUM >= 20190220
+struct PACKET_ZC_PING {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PING, 0x0b1d);
+#endif
+
+#if PACKETVER >= 20160622
+struct PACKET_CZ_COOLDOWN_RESET {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_COOLDOWN_RESET, 0x0a88);
+#endif
+
+#if PACKETVER >= 20151104
+struct PACKET_CZ_STYLE_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_STYLE_CLOSE, 0x0a48);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320 || PACKETVER_ZERO_NUM >= 20190410
+struct PACKET_ZC_LOAD_CONFIRM {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LOAD_CONFIRM, 0x0b1b);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20070911 || defined(PACKETVER_RE) || PACKETVER_AD_NUM >= 20070911 || PACKETVER_SAK_NUM >= 20070904 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_PARTY_CONFIG {
+ int16 packetType;
+ uint8 denyPartyInvites;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PARTY_CONFIG, 0x02c9);
+#endif
+
+struct PACKET_ZC_ROLE_CHANGE {
+ int16 packetType;
+ int32 flag;
+ char name[NAME_LENGTH];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ROLE_CHANGE, 0x00e1);
+
+#if PACKETVER_MAIN_NUM >= 20161019 || PACKETVER_RE_NUM >= 20160921 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_BAN_LIST_sub {
+ int char_id;
+ char message[40];
+} __attribute__((packed));
+
+struct PACKET_ZC_BAN_LIST {
+ int16 packetType;
+ uint16 packetLen;
+ struct PACKET_ZC_BAN_LIST_sub chars[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_BAN_LIST, 0x0a87);
+// version unconfirmed
+#elif PACKETVER >= 20100803
+struct PACKET_ZC_BAN_LIST_sub {
+ char char_name[NAME_LENGTH];
+ char message[40];
+} __attribute__((packed));
+
+struct PACKET_ZC_BAN_LIST {
+ int16 packetType;
+ uint16 packetLen;
+ struct PACKET_ZC_BAN_LIST_sub chars[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_BAN_LIST, 0x0163);
+#else
+struct PACKET_ZC_BAN_LIST_sub {
+ char char_name[NAME_LENGTH];
+ char account_name[NAME_LENGTH];
+ char message[40];
+} __attribute__((packed));
+
+struct PACKET_ZC_BAN_LIST {
+ int16 packetType;
+ uint16 packetLen;
+ struct PACKET_ZC_BAN_LIST_sub chars[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_BAN_LIST, 0x0163);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20141008 || PACKETVER_RE_NUM >= 20140903 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_ACK_CLOSE_ROULETTE {
+ int16 packetType;
+ uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_CLOSE_ROULETTE, 0x0a1e);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20120314 || PACKETVER_RE_NUM >= 20120221 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_ACK_MERGE_ITEM {
+ int16 packetType;
+ int16 index;
+ int16 amount;
+ uint8 reason;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_MERGE_ITEM, 0x096f);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20120314 || PACKETVER_RE_NUM >= 20120221 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_MERGE_ITEM_OPEN_sub {
+ int16 index;
+} __attribute__((packed));
+
+struct PACKET_ZC_MERGE_ITEM_OPEN {
+ int16 packetType;
+ uint16 packetLen;
+ struct PACKET_ZC_MERGE_ITEM_OPEN_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_MERGE_ITEM_OPEN, 0x096d);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_SE_PC_BUY_CASHITEM_RESULT {
+ int16 packetType;
+ uint32 itemId; // unused
+ uint16 result;
+ uint32 cashPoints;
+ uint32 kafraPoints;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SE_PC_BUY_CASHITEM_RESULT, 0x0849);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_REFINE_OPEN_WINDOW {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_REFINE_OPEN_WINDOW, 0x0aa0);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20161005 || PACKETVER_RE_NUM >= 20161005 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_REFINE_ADD_ITEM {
+ int16 packetType;
+ int16 index;
+};
+DEFINE_PACKET_HEADER(CZ_REFINE_ADD_ITEM, 0x0aa1);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20161130 || PACKETVER_RE_NUM >= 20161109 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_REFINE_ADD_ITEM_SUB {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ int8 chance;
+ int32 zeny;
+} __attribute__((packed));
+
+struct PACKET_ZC_REFINE_ADD_ITEM {
+ int16 packetType;
+ int16 packtLength;
+ int16 itemIndex;
+ int8 blacksmithBlessing;
+ struct PACKET_ZC_REFINE_ADD_ITEM_SUB req[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_REFINE_ADD_ITEM, 0x0aa2);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20161005 || PACKETVER_RE_NUM >= 20161005 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_REFINE_ITEM_REQUEST {
+ int16 packetType;
+ int16 index;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ int8 blacksmithBlessing;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REFINE_ITEM_REQUEST, 0x0aa3);
+
+struct PACKET_CZ_REFINE_WINDOW_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REFINE_WINDOW_CLOSE, 0x0aa4);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20170906 || PACKETVER_RE_NUM >= 20170830 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_REFINE_STATUS {
+ int16 packetType;
+ char name[NAME_LENGTH];
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ int8 refine_level;
+ int8 status;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_REFINE_STATUS, 0x0ada);
+#endif
+
+struct PACKET_ZC_ACK_RANKING_name {
+ char name[NAME_LENGTH];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_RANKING_points {
+ uint32 points;
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190724
+struct PACKET_ZC_ACK_RANKING_sub {
+ char name[NAME_LENGTH];
+ uint32 points;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_RANKING {
+ int16 packetType;
+ int16 rankType;
+ uint32 chars[10];
+ uint32 points[10];
+ uint32 myPoints;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_RANKING, 0x0af6);
+#elif PACKETVER_MAIN_NUM >= 20130605 || PACKETVER_RE_NUM >= 20130529 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_ACK_RANKING_sub {
+ struct PACKET_ZC_ACK_RANKING_name names[10];
+ struct PACKET_ZC_ACK_RANKING_points points[10];
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_RANKING {
+ int16 packetType;
+ int16 rankType;
+ struct PACKET_ZC_ACK_RANKING_sub ranks;
+ uint32 myPoints;
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_ACK_RANKING, 0x097d);
+#else
+struct PACKET_ZC_ACK_RANKING_sub {
+ struct PACKET_ZC_ACK_RANKING_name names[10];
+ struct PACKET_ZC_ACK_RANKING_points points[10];
+} __attribute__((packed));
+#endif
+
+struct PACKET_ZC_STATUS_CHANGE_ACK {
+ int16 packetType;
+ uint16 sp;
+ uint8 ok;
+ uint8 value;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_STATUS_CHANGE_ACK, 0x00bc);
+
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_HAT_EFFECT {
+ int16 packetType;
+ int16 packetLength;
+ uint32 aid;
+ int8 status;
+ uint16 effects[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_HAT_EFFECT, 0x0a3b);
+#endif
+
+// [4144] this struct updated not in all packets in client
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+struct SKILLDATA {
+ uint16 id;
+ int inf;
+ uint16 level;
+ uint16 sp;
+ uint16 range2;
+ uint8 upFlag;
+ uint16 level2;
+} __attribute__((packed));
+#else
+struct SKILLDATA {
+ uint16 id;
+ int inf;
+ uint16 level;
+ uint16 sp;
+ uint16 range2;
+ char name[NAME_LENGTH];
+ uint8 upFlag;
+} __attribute__((packed));
+#endif
+
+struct PACKET_ZC_ADD_SKILL {
+ int16 packetType;
+ struct SKILLDATA skill;
+} __attribute__((packed));
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+DEFINE_PACKET_HEADER(ZC_ADD_SKILL, 0x0b31);
+#else
+DEFINE_PACKET_HEADER(ZC_ADD_SKILL, 0x0111);
+#endif
+
+struct PACKET_ZC_SKILLINFO_LIST {
+ int16 packetType;
+ int16 packetLength;
+ struct SKILLDATA skills[];
+} __attribute__((packed));
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+DEFINE_PACKET_HEADER(ZC_SKILLINFO_LIST, 0x0b32);
+#else
+DEFINE_PACKET_HEADER(ZC_SKILLINFO_LIST, 0x010f);
+#endif
+
+#if PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
+struct PACKET_ZC_SKILLINFO_UPDATE2 {
+ int16 packetType;
+ uint16 id;
+ int inf;
+ uint16 level;
+ uint16 sp;
+ uint16 range2;
+ uint8 upFlag;
+ uint16 level2;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SKILLINFO_UPDATE2, 0x0b33);
+#else
+struct PACKET_ZC_SKILLINFO_UPDATE2 {
+ int16 packetType;
+ uint16 id;
+ int inf;
+ uint16 level;
+ uint16 sp;
+ uint16 range2;
+ uint8 upFlag;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SKILLINFO_UPDATE2, 0x07e1);
+#endif
+
+struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 ITID;
+#else
+ uint16 ITID;
+#endif
+ uint16 qty;
+ uint32 price;
+} __attribute__((packed));
+
+#if PACKETVER_MAIN_NUM >= 20190807 || PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190814
+struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT {
+ int16 PacketType;
+ int16 PacketLength;
+ uint16 result;
+ struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_MARKET_PURCHASE_RESULT, 0x0b4e);
+#elif PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20130911 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT {
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 result;
+ struct PACKET_ZC_NPC_MARKET_PURCHASE_RESULT_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_MARKET_PURCHASE_RESULT, 0x09d7);
+#endif
+
+struct PACKET_ZC_TALKBOX_CHATCONTENTS {
+ int16 PacketType;
+ uint32 aid;
+ char message[TALKBOX_MESSAGE_SIZE];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_TALKBOX_CHATCONTENTS, 0x0191);
+
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+struct PACKET_ZC_GUILD_CASTLE_LIST {
+ int16 packetType;
+ int16 packetLength;
+ int8 castle_list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_GUILD_CASTLE_LIST, 0x0b27);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+struct PACKET_CZ_CASTLE_TELEPORT_REQUEST {
+ int16 packetType;
+ int8 castle_id;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CASTLE_TELEPORT_REQUEST, 0x0b28);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+struct PACKET_ZC_CASTLE_TELEPORT_RESPONSE {
+ int16 packetType;
+ int16 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CASTLE_TELEPORT_RESPONSE, 0x0b2e);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190731 || PACKETVER_RE_NUM >= 20190717 || PACKETVER_ZERO_NUM >= 20190814
+struct PACKET_ZC_CASTLE_INFO {
+ int16 packetType;
+ int8 castle_id;
+ int32 economy;
+ int32 defense;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CASTLE_INFO, 0x0b2d);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190522 || PACKETVER_RE_NUM >= 20190522 || PACKETVER_ZERO_NUM >= 20190515
+struct PACKET_CZ_CASTLE_INFO_REQUEST {
+ int16 packetType;
+ int8 castle_id;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CASTLE_INFO_REQUEST, 0x0b2c);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_LAPINEDDUKDDAK_OPEN {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ int32 itemId;
+#else
+ int16 itemId;
+#endif
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEDDUKDDAK_OPEN, 0x0a4e);
+#endif // PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20160504 || PACKETVER_RE_NUM >= 20160504 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_LAPINEDDUKDDAK_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEDDUKDDAK_CLOSE, 0x0a70);
+#endif // PACKETVER_MAIN_NUM >= 20160504 || PACKETVER_RE_NUM >= 20160504 || defined(PACKETVER_ZERO)
+
+#if PACKETVER >= 20160302
+struct PACKET_CZ_LAPINEDDUKDDAK_ACK_sub {
+ int16 index;
+ int16 count;
+} __attribute__((packed));
+
+struct PACKET_CZ_LAPINEDDUKDDAK_ACK {
+ int16 packetType;
+ int16 packetLength;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ int32 itemId;
+#else
+ int16 itemId;
+#endif
+ struct PACKET_CZ_LAPINEDDUKDDAK_ACK_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEDDUKDDAK_ACK, 0x0a4f);
+#endif // PACKETVER >= 20160302
+
+#if PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_LAPINEDDUKDDAK_RESULT {
+ int16 packetType;
+ int16 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEDDUKDDAK_RESULT, 0x0a50);
+#endif // PACKETVER_MAIN_NUM >= 20160601 || PACKETVER_RE_NUM >= 20160525 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20190703 || PACKETVER_RE_NUM >= 20190703 || PACKETVER_ZERO_NUM >= 20190709
+struct PACKET_CZ_REQ_MOUNTOFF {
+ int16 packetType;
+ uint8 action;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_MOUNTOFF, 0x0b35);
+#endif
+
+// in 3 clients from same version
+#if PACKETVER >= 20191127
+struct PACKET_ZC_NOTIFY_EFFECT3 {
+ int16 packetType;
+ uint32 aid;
+ uint32 effectId;
+ uint64 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_EFFECT3, 0x0b69);
+#elif PACKETVER_MAIN_NUM >= 20060911 || PACKETVER_AD_NUM >= 20060911 || PACKETVER_SAK_NUM >= 20060911 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO)
+struct PACKET_ZC_NOTIFY_EFFECT3 {
+ int16 packetType;
+ uint32 aid;
+ uint32 effectId;
+ uint32 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_EFFECT3, 0x0284);
+#endif
+
+#if PACKETVER >= 20100824
+struct PACKET_CZ_SE_CASHSHOP_OPEN1 {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SE_CASHSHOP_OPEN1, 0x0844);
+#endif
+
+#if PACKETVER >= 20191224
+struct PACKET_CZ_SE_CASHSHOP_OPEN2 {
+ int16 packetType;
+ uint32 tab;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SE_CASHSHOP_OPEN2, 0x0b6d);
+#endif
+
+#if PACKETVER >= 20190724
+struct PACKET_CZ_SE_CASHSHOP_LIMITED_REQ {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SE_CASHSHOP_LIMITED_REQ, 0x0b4c);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20200129 || PACKETVER_RE_NUM >= 20200205 || PACKETVER_ZERO_NUM >= 20191224
+struct PACKET_ZC_SE_CASHSHOP_OPEN {
+ int16 packetType;
+ uint32 cashPoints;
+ uint32 kafraPoints;
+ uint32 tab;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SE_CASHSHOP_OPEN, 0x0b6e);
+// for ragexeRE in some version this packet unused [4144]
+#elif PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_SE_CASHSHOP_OPEN {
+ int16 packetType;
+ uint32 cashPoints;
+ uint32 kafraPoints;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SE_CASHSHOP_OPEN, 0x0845);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
+struct PACKET_CZ_NPC_EXPANDED_BARTER_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_NPC_EXPANDED_BARTER_CLOSE, 0x0b58);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 nameid;
+#else
+ uint16 nameid;
+#endif
+ uint16 refine_level;
+ uint32 amount;
+ uint16 type;
+} __attribute__((packed));
+
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 nameid;
+#else
+ uint16 nameid;
+#endif
+ uint16 type;
+ uint32 amount;
+ uint32 weight;
+ uint32 index;
+ uint32 zeny;
+ uint32 currency_count;
+ // Workaround for fix Visual Studio bug (error C2233). Here should be currencies[]
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[1];
+} __attribute__((packed));
+
+// Workaround check for Visual Studio bug (error C2233)
+STATIC_ASSERT(sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2[1]) ==
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2),
+ "Wrong PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub size");
+
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
+ int16 packetType;
+ int16 packetLength;
+ int32 items_count;
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub items[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_NPC_EXPANDED_BARTER_OPEN, 0x0b56);
+#endif
+
+#if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
+struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint32 shopIndex;
+ uint32 amount;
+} __attribute__((packed));
+
+struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE {
+ int16 packetType;
+ int16 packetLength;
+ struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_NPC_EXPANDED_BARTER_PURCHASE, 0x0b57);
+#endif
+
+#if PACKETVER >= 7
+struct PACKET_ZC_STATE_CHANGE {
+ int16 packetType;
+ uint32 AID;
+ int16 bodyState;
+ int16 healthState;
+ int32 effectState;
+ int8 isPKModeON;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_STATE_CHANGE, 0x0229);
+#else
+struct PACKET_ZC_STATE_CHANGE {
+ int16 PacketType;
+ uint32 AID;
+ int16 bodyState;
+ int16 healthState;
+ int16 effectState;
+ int8 isPKModeON;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_STATE_CHANGE, 0x0119);
+#endif
+
+struct PACKET_ZC_AUTORUN_SKILL {
+ int16 packetType;
+ uint16 skill_id;
+ uint32 skill_type;
+ uint16 skill_lv;
+ uint16 skill_sp;
+ uint16 skill_range;
+ char skill_name[NAME_LENGTH];
+ char up_flag;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_AUTORUN_SKILL, 0x0147);
+
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_LAPINEUPGRADE_OPEN {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEUPGRADE_OPEN, 0x0ab4);
+
+struct PACKET_ZC_LAPINEUPGRADE_RESULT {
+ int16 packetType;
+ uint16 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEUPGRADE_RESULT, 0x0ab7);
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_LAPINEUPGRADE_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEUPGRADE_CLOSE, 0x0ab5);
+
+struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 index;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEUPGRADE_MAKE_ITEM, 0x0ab6);
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/party.c b/src/map/party.c
index 551c4d56f..7d7f69620 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,10 +31,12 @@
#include "map/itemdb.h"
#include "map/log.h"
#include "map/map.h"
+#include "map/messages.h"
#include "map/mob.h" // struct mob_data
#include "map/pc.h"
#include "map/skill.h"
#include "map/status.h"
+#include "map/achievement.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
#include "common/memmgr.h"
@@ -50,18 +52,22 @@
#include <stdlib.h>
#include <string.h>
-struct party_interface party_s;
+static struct party_interface party_s;
struct party_interface *party;
/*==========================================
* Fills the given party_member structure according to the sd provided.
* Used when creating/adding people to a party. [Skotlex]
*------------------------------------------*/
-void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) {
+static void party_fill_member(struct party_member *member, struct map_session_data *sd, unsigned int leader)
+{
+ nullpo_retv(member);
+ nullpo_retv(sd);
+
member->account_id = sd->status.account_id;
member->char_id = sd->status.char_id;
safestrncpy(member->name, sd->status.name, NAME_LENGTH);
- member->class_ = sd->status.class_;
+ member->class = sd->status.class;
member->map = sd->mapindex;
member->lv = sd->status.base_level;
member->online = 1;
@@ -76,7 +82,7 @@ void party_fill_member(struct party_member* member, struct map_session_data* sd,
* @return the member_id.
* @retval INDEX_NOT_FOUND if not in party.
*/
-int party_getmemberid(struct party_data *p, struct map_session_data *sd)
+static int party_getmemberid(struct party_data *p, struct map_session_data *sd)
{
int member_id;
nullpo_retr(INDEX_NOT_FOUND, p);
@@ -94,7 +100,7 @@ int party_getmemberid(struct party_data *p, struct map_session_data *sd)
/*==========================================
* Request an available sd of this party
*------------------------------------------*/
-struct map_session_data* party_getavailablesd(struct party_data *p)
+static struct map_session_data *party_getavailablesd(struct party_data *p)
{
int i;
nullpo_retr(NULL, p);
@@ -105,7 +111,7 @@ struct map_session_data* party_getavailablesd(struct party_data *p)
/*==========================================
* Retrieves and validates the sd pointer for this party member [Skotlex]
*------------------------------------------*/
-struct map_session_data *party_sd_check(int party_id, int account_id, int char_id)
+static struct map_session_data *party_sd_check(int party_id, int account_id, int char_id)
{
struct map_session_data *sd = map->id2sd(account_id);
@@ -122,7 +128,7 @@ struct map_session_data *party_sd_check(int party_id, int account_id, int char_i
return sd;
}
-int party_db_final(union DBKey key, struct DBData *data, va_list ap)
+static int party_db_final(union DBKey key, struct DBData *data, va_list ap)
{
struct party_data *p;
@@ -135,7 +141,7 @@ int party_db_final(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
/// Party data lookup using party id.
-struct party_data* party_search(int party_id)
+static struct party_data *party_search(int party_id)
{
if(!party_id)
return NULL;
@@ -143,7 +149,7 @@ struct party_data* party_search(int party_id)
}
/// Party data lookup using party name.
-struct party_data* party_searchname(const char* str)
+static struct party_data *party_searchname(const char *str)
{
struct party_data* p;
@@ -157,11 +163,14 @@ struct party_data* party_searchname(const char* str)
return p;
}
-int party_create(struct map_session_data *sd, const char *name,int item,int item2)
+static int party_create(struct map_session_data *sd, const char *name, int item, int item2)
{
struct party_member leader;
char tname[NAME_LENGTH];
+ nullpo_retr(0, sd);
+ nullpo_retr(0, name);
+
safestrncpy(tname, name, NAME_LENGTH);
trim(tname);
@@ -181,10 +190,13 @@ int party_create(struct map_session_data *sd, const char *name,int item,int item
party->fill_member(&leader, sd, 1);
intif->create_party(&leader,name,item,item2);
+
+ achievement->validate_party_create(sd); //Achievements (Smokexyz)
+
return 0;
}
-void party_created(int account_id, int char_id, int fail, int party_id, const char *name)
+static void party_created(int account_id, int char_id, int fail, int party_id, const char *name)
{
struct map_session_data *sd;
sd=map->id2sd(account_id);
@@ -208,13 +220,14 @@ void party_created(int account_id, int char_id, int fail, int party_id, const ch
}
-int party_request_info(int party_id, int char_id)
+static int party_request_info(int party_id, int char_id)
{
return intif->request_partyinfo(party_id, char_id);
}
/// Invoked (from char-server) when the party info is not found.
-int party_recv_noinfo(int party_id, int char_id) {
+static int party_recv_noinfo(int party_id, int char_id)
+{
party->broken(party_id);
if( char_id != 0 ) {
// requester
@@ -226,32 +239,39 @@ int party_recv_noinfo(int party_id, int char_id) {
return 0;
}
-void party_check_state(struct party_data *p) {
+static void party_check_state(struct party_data *p)
+{
int i;
+ nullpo_retv(p);
memset(&p->state, 0, sizeof(p->state));
- for (i = 0; i < MAX_PARTY; i ++) {
+ for (i = 0; i < MAX_PARTY; i++) {
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_) {
+ switch (p->party.member[i].class) {
case JOB_MONK:
case JOB_BABY_MONK:
case JOB_CHAMPION:
+ case JOB_SURA:
+ case JOB_SURA_T:
+ case JOB_BABY_SURA:
p->state.monk = 1;
- break;
+ break;
case JOB_STAR_GLADIATOR:
p->state.sg = 1;
- break;
+ break;
case JOB_SUPER_NOVICE:
case JOB_SUPER_BABY:
+ case JOB_SUPER_NOVICE_E:
+ case JOB_SUPER_BABY_E:
p->state.snovice = 1;
- break;
+ break;
case JOB_TAEKWON:
p->state.tk = 1;
- break;
+ break;
}
}
}
-int party_recv_info(const struct party *sp, int char_id)
+static int party_recv_info(const struct party *sp, int char_id)
{
struct party_data* p;
const struct party_member *member;
@@ -262,6 +282,7 @@ int party_recv_info(const struct party *sp, int char_id)
int added_count = 0;
int j;
int member_id;
+ int leader_account_id = 0, leader_char_id = 0;
nullpo_ret(sp);
@@ -275,8 +296,12 @@ int party_recv_info(const struct party *sp, int char_id)
ARR_FIND(0, MAX_PARTY, i,
sp->member[i].account_id == member->account_id &&
sp->member[i].char_id == member->char_id);
- if (i == MAX_PARTY)
+ if (i == MAX_PARTY) {
removed[removed_count++] = member_id;
+ } else if (member->leader != 0) {
+ leader_account_id = member->account_id;
+ leader_char_id = member->char_id;
+ }
}
for (member_id = 0; member_id < MAX_PARTY; ++member_id) {
member = &sp->member[member_id];
@@ -304,6 +329,7 @@ int party_recv_info(const struct party *sp, int char_id)
continue;// not online
party->member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id);
}
+
memcpy(&p->party, sp, sizeof(struct party));
memset(&p->state, 0, sizeof(p->state));
memset(&p->data, 0, sizeof(p->data));
@@ -312,6 +338,8 @@ int party_recv_info(const struct party *sp, int char_id)
if ( member->char_id == 0 )
continue;// empty
p->data[member_id].sd = party->sd_check(sp->party_id, member->account_id, member->char_id);
+ if (member->account_id == leader_account_id && member->char_id == leader_char_id)
+ p->party.member[member_id].leader = 1;
}
party->check_state(p);
while( added_count > 0 ) { // new in party
@@ -341,7 +369,7 @@ int party_recv_info(const struct party *sp, int char_id)
return 0;
}
-int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
+static int party_invite(struct map_session_data *sd, struct map_session_data *tsd)
{
struct party_data *p;
int i;
@@ -355,7 +383,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd);
if( i == MAX_PARTY || !p->party.member[i].leader ) {
- clif->message(sd->fd, msg_sd(sd,282));
+ clif->message(sd->fd, msg_sd(sd,282)); // You need to be a party leader to use this command.
return 0;
}
@@ -396,6 +424,12 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
return 0;
}
+ if ((tsd->status.allow_party & 1) != 0) {
+ // party invite blocked by player
+ clif->party_inviteack(sd, tsd->status.name, 5);
+ return 0;
+ }
+
tsd->party_invite=sd->status.party_id;
tsd->party_invite_account=sd->status.account_id;
@@ -403,10 +437,13 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
return 1;
}
-void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {
+static void party_reply_invite(struct map_session_data *sd, int party_id, int flag)
+{
struct map_session_data* tsd;
struct party_member member;
+ nullpo_retv(sd);
+
if( sd->party_invite != party_id )
{// forged
sd->party_invite = 0;
@@ -434,10 +471,13 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {
//- Loads up party data if not in server
//- Sets up the pointer to him
//- Player must be authed/active and belong to a party before calling this method
-void party_member_joined(struct map_session_data *sd)
+static void party_member_joined(struct map_session_data *sd)
{
- struct party_data* p = party->search(sd->status.party_id);
+ struct party_data* p;
int i;
+
+ nullpo_retv(sd);
+ p = party->search(sd->status.party_id);
if (!p) {
party->request_info(sd->status.party_id, sd->status.char_id);
return;
@@ -460,7 +500,8 @@ void party_member_joined(struct map_session_data *sd)
/// Invoked (from char-server) when a new member is added to the party.
/// flag: 0-success, 1-failure
-int party_member_added(int party_id,int account_id,int char_id, int flag) {
+static int party_member_added(int party_id, int account_id, int char_id, int flag)
+{
struct map_session_data *sd = map->id2sd(account_id),*sd2;
struct party_data *p = party->search(party_id);
int i, j;
@@ -520,7 +561,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) {
}
/// Party member 'sd' requesting kick of member with <account_id, name>.
-int party_removemember(struct map_session_data* sd, int account_id, const char *name)
+static int party_removemember(struct map_session_data *sd, int account_id, const char *name)
{
struct party_data *p;
int i;
@@ -536,6 +577,7 @@ int party_removemember(struct map_session_data* sd, int account_id, const char *
if( !p->party.member[i].leader )
return 0; // only party leader may remove members
+ nullpo_retr(0, name);
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && strncmp(p->party.member[i].name,name,NAME_LENGTH) == 0 );
if( i == MAX_PARTY )
return 0; // no such char in party
@@ -545,11 +587,12 @@ int party_removemember(struct map_session_data* sd, int account_id, const char *
}
/// Party member 'sd' requesting exit from party.
-int party_leave(struct map_session_data *sd)
+static int party_leave(struct map_session_data *sd)
{
struct party_data *p;
int i;
+ nullpo_ret(sd);
p = party->search(sd->status.party_id);
if( p == NULL )
return 0;
@@ -563,7 +606,7 @@ int party_leave(struct map_session_data *sd)
}
/// Invoked (from char-server) when a party member leaves the party.
-int party_member_withdraw(int party_id, int account_id, int char_id)
+static int party_member_withdraw(int party_id, int account_id, int char_id)
{
struct map_session_data* sd = map->id2sd(account_id);
struct party_data* p = party->search(party_id);
@@ -572,11 +615,43 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
int i;
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id );
if( i < MAX_PARTY ) {
+ bool was_leader = false;
+ int prev_leader_accountId = 0;
+ if (p->party.member[i].leader != 0) {
+ was_leader = true;
+ prev_leader_accountId = p->party.member[i].account_id;
+ }
+
clif->party_withdraw(p,sd,account_id,p->party.member[i].name,0x0);
memset(&p->party.member[i], 0, sizeof(p->party.member[0]));
memset(&p->data[i], 0, sizeof(p->data[0]));
p->party.count--;
party->check_state(p);
+
+ if (was_leader) {
+ int k;
+ // Member was party leader, try to pick a new leader from online members
+ ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0 && p->party.member[k].online == 1);
+
+ if (k == MAX_PARTY) {
+ // No online members, get an offline one
+ ARR_FIND(0, MAX_PARTY, k, p->party.member[k].account_id != 0);
+ }
+
+ if (k < MAX_PARTY) {
+ // Update party's leader
+ p->party.member[k].leader = 1;
+
+ if (p->data[k].sd != NULL) {
+ /** update members **/
+ clif->PartyLeaderChanged(p->data[k].sd, prev_leader_accountId, p->data[k].sd->status.account_id);
+ }
+
+ //Update info.
+ intif->party_leaderchange(p->party.party_id, p->party.member[k].account_id, p->party.member[k].char_id);
+ clif->party_info(p, NULL);
+ }
+ }
}
}
@@ -600,7 +675,7 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
}
/// Invoked (from char-server) when a party is disbanded.
-int party_broken(int party_id)
+static int party_broken(int party_id)
{
struct party_data* p;
int i, j;
@@ -620,6 +695,7 @@ int party_broken(int party_id)
if( p->data[i].sd!=NULL ) {
clif->party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10);
p->data[i].sd->status.party_id=0;
+ clif->charnameupdate(p->data[i].sd);
}
}
@@ -632,7 +708,7 @@ int party_broken(int party_id)
return 0;
}
-int party_changeoption(struct map_session_data *sd,int exp,int item)
+static int party_changeoption(struct map_session_data *sd, int exp, int item)
{
nullpo_ret(sd);
@@ -642,7 +718,8 @@ int party_changeoption(struct map_session_data *sd,int exp,int item)
return 0;
}
-int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) {
+static int party_optionchanged(int party_id, int account_id, int exp, int item, int flag)
+{
struct party_data *p;
struct map_session_data *sd=map->id2sd(account_id);
if( (p=party->search(party_id))==NULL)
@@ -659,7 +736,7 @@ int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) {
return 0;
}
-bool party_changeleader(struct map_session_data *sd, struct map_session_data *tsd)
+static bool party_changeleader(struct map_session_data *sd, struct map_session_data *tsd)
{
struct party_data *p;
int mi, tmi;
@@ -668,12 +745,19 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
return false;
if (!tsd || tsd->status.party_id != sd->status.party_id) {
- clif->message(sd->fd, msg_sd(sd,283));
+ clif->message(sd->fd, msg_sd(sd,283)); // Target character must be online and in your current party.
+ return false;
+ }
+
+ if (battle_config.party_change_leader_same_map && sd->bl.m != tsd->bl.m) {
+#if PACKETVER >= 20120307
+ clif->msgtable(sd, MSG_PARTY_MASTER_CHANGE_SAME_MAP); // It is only possible to change the party leader while on the same map.
+#endif
return false;
}
if( map->list[sd->bl.m].flag.partylock ) {
- clif->message(sd->fd, msg_sd(sd,287));
+ clif->message(sd->fd, msg_sd(sd,287)); // You cannot change party leaders in this map.
return false;
}
@@ -685,8 +769,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
return false; //Shouldn't happen
if (!p->party.member[mi].leader) {
- //Need to be a party leader.
- clif->message(sd->fd, msg_sd(sd,282));
+ clif->message(sd->fd, msg_sd(sd,282)); // You need to be a party leader to use this command.
return false;
}
@@ -711,7 +794,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
/// - changes maps
/// - logs in or out
/// - gains a level (disabled)
-int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short mapid,int online,int lv)
+static int party_recv_movemap(int party_id, int account_id, int char_id, unsigned short mapid, int online, int lv)
{
struct party_member* m;
struct party_data* p;
@@ -739,10 +822,12 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m
return 0;
}
-void party_send_movemap(struct map_session_data *sd)
+static void party_send_movemap(struct map_session_data *sd)
{
struct party_data *p;
+ nullpo_retv(sd);
+
if( sd->status.party_id==0 )
return;
@@ -772,16 +857,18 @@ void party_send_movemap(struct map_session_data *sd)
return;
}
-void party_send_levelup(struct map_session_data *sd)
+static void party_send_levelup(struct map_session_data *sd)
{
intif->party_changemap(sd,1);
}
-int party_send_logout(struct map_session_data *sd)
+static int party_send_logout(struct map_session_data *sd)
{
struct party_data *p;
int i;
+ nullpo_ret(sd);
+
if(!sd->status.party_id)
return 0;
@@ -798,12 +885,22 @@ int party_send_logout(struct map_session_data *sd)
return 1;
}
-int party_send_message(struct map_session_data *sd,const char *mes,int len)
+static int party_send_message(struct map_session_data *sd, const char *mes)
{
- if(sd->status.party_id==0)
+ nullpo_ret(sd);
+ nullpo_ret(mes);
+
+ if (sd->status.party_id == 0)
+ return 0;
+
+ struct party_data *p = party->search(sd->status.party_id);
+
+ if (p == NULL)
return 0;
- intif->party_message(sd->status.party_id,sd->status.account_id,mes,len);
- party->recv_message(sd->status.party_id,sd->status.account_id,mes,len);
+
+ int len = (int)strlen(mes);
+
+ clif->party_message(p, sd->status.account_id, mes, len);
// Chat logging type 'P' / Party Chat
logs->chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
@@ -811,16 +908,7 @@ int party_send_message(struct map_session_data *sd,const char *mes,int len)
return 0;
}
-int party_recv_message(int party_id,int account_id,const char *mes,int len)
-{
- struct party_data *p;
- if( (p=party->search(party_id))==NULL)
- return 0;
- clif->party_message(p,account_id,mes,len);
- return 0;
-}
-
-int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv)
+static int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv)
{
struct party_data *p;
struct map_session_data *p_sd;
@@ -843,6 +931,8 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
return 0; //Unknown case?
}
+ nullpo_ret(sd);
+
for(i=0;i<MAX_PARTY;i++){
if ((p_sd = p->data[i].sd) == NULL)
continue;
@@ -850,15 +940,14 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
continue;
switch(skill_id) {
case TK_COUNTER: //Increase Triple Attack rate of Monks.
- if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK
- && pc->checkskill(p_sd,MO_TRIPLEATTACK)) {
+ if ((p_sd->job & MAPID_UPPERMASK) == MAPID_MONK && pc->checkskill(p_sd, MO_TRIPLEATTACK)) {
sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK,
50+50*skill_lv, //+100/150/200% rate
0,0,skill->get_time(SG_FRIEND, 1));
}
break;
case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators
- if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
+ if ((p_sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
&& sd->sc.data[SC_COUNTERKICK_READY]
&& pc->checkskill(p_sd,SG_FRIEND)) {
sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER,
@@ -871,7 +960,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
return 0;
}
-int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
+static int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
{
struct DBIterator *iter = db_iterator(party->db);
struct party_data* p;
@@ -910,7 +999,7 @@ int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
}
-int party_send_xy_clear(struct party_data *p)
+static int party_send_xy_clear(struct party_data *p)
{
int i;
@@ -926,15 +1015,13 @@ int party_send_xy_clear(struct party_data *p)
}
// exp share and added zeny share [Valaris]
-int party_exp_share(struct party_data* p, struct block_list* src, unsigned int base_exp, unsigned int job_exp, int zeny)
+static int party_exp_share(struct party_data *p, struct block_list *src, unsigned int base_exp, unsigned int job_exp, int zeny)
{
struct map_session_data* sd[MAX_PARTY];
unsigned int i, c;
-#ifdef RENEWAL_EXP
- unsigned int job_exp_bonus, base_exp_bonus;
-#endif
nullpo_ret(p);
+ nullpo_ret(src);
// count the number of players eligible for exp sharing
for (i = c = 0; i < MAX_PARTY; i++) {
@@ -959,21 +1046,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX);
}
-#ifdef RENEWAL_EXP
- base_exp_bonus = base_exp;
- job_exp_bonus = job_exp;
-#endif
-
for (i = 0; i < c; i++) {
-#ifdef RENEWAL_EXP
- struct mob_data *md = BL_CAST(BL_MOB, src);
- if (md != NULL && md->db->mexp == 0) {
- int rate = pc->level_penalty_mod(md->level - (sd[i])->status.base_level, md->status.race, md->status.mode, 1);
-
- base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX);
- job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX);
- }
-#endif
pc->gainexp(sd[i], src, base_exp, job_exp, false);
if (zeny) // zeny from mobs [Valaris]
@@ -983,12 +1056,16 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
}
//Does party loot. first_charid holds the charid of the player who has time priority to take the item.
-int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid)
+static int party_share_loot(struct party_data *p, struct map_session_data *sd, struct item *item_data, int first_charid)
{
struct map_session_data *target = NULL;
int i;
+
+ nullpo_ret(item_data);
+
if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1)))
{
+ nullpo_ret(sd);
//item distribution to party members.
if (battle_config.party_share_type&2) {
//Round Robin
@@ -1048,8 +1125,9 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
return 0;
}
-int party_send_dot_remove(struct map_session_data *sd)
+static int party_send_dot_remove(struct map_session_data *sd)
{
+ nullpo_ret(sd);
if (sd->status.party_id)
clif->party_xy_remove(sd);
return 0;
@@ -1058,13 +1136,14 @@ int party_send_dot_remove(struct map_session_data *sd)
// To use for Taekwon's "Fighting Chant"
// int c = 0;
// party_foreachsamemap(party->sub_count, sd, 0, &c);
-int party_sub_count(struct block_list *bl, va_list ap)
+static int party_sub_count(struct block_list *bl, va_list ap)
{
const struct map_session_data *sd = NULL;
nullpo_ret(bl);
Assert_ret(bl->type == BL_PC);
sd = BL_UCCAST(BL_PC, bl);
+ nullpo_ret(sd);
if (sd->state.autotrade)
return 0;
@@ -1079,7 +1158,8 @@ int party_sub_count(struct block_list *bl, va_list ap)
* Arglist-based version of party_foreachsamemap
* @see party_foreachsamemap
*/
-int party_vforeachsamemap(int (*func)(struct block_list*,va_list), struct map_session_data *sd, int range, va_list ap) {
+static int party_vforeachsamemap(int (*func)(struct block_list*, va_list), struct map_session_data *sd, int range, va_list ap)
+{
struct party_data *p;
int i;
int x0,y0,x1,y1;
@@ -1125,7 +1205,7 @@ int party_vforeachsamemap(int (*func)(struct block_list*,va_list), struct map_se
}
// Special check for Minstrel's and Wanderer's chorus skills.
-int party_sub_count_chorus(struct block_list *bl, va_list ap)
+static int party_sub_count_chorus(struct block_list *bl, va_list ap)
{
const struct map_session_data *sd = NULL;
@@ -1139,7 +1219,7 @@ int party_sub_count_chorus(struct block_list *bl, va_list ap)
if (battle_config.idle_no_share && pc_isidle(sd))
return 0;
- if ( (sd->class_&MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER )
+ if ((sd->job & MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER)
return 0;
return 1;
@@ -1153,7 +1233,8 @@ int party_sub_count_chorus(struct block_list *bl, va_list ap)
* @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, ...) {
+static int party_foreachsamemap(int (*func)(struct block_list*, va_list), struct map_session_data *sd, int range, ...)
+{
va_list ap;
int ret;
va_start(ap, range);
@@ -1166,17 +1247,22 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list), struct map_ses
* Party Booking in KRO [Spiria]
*------------------------------------------*/
-struct party_booking_ad_info* create_party_booking_data(void) {
+static struct party_booking_ad_info *create_party_booking_data(void)
+{
struct party_booking_ad_info *pb_ad;
CREATE(pb_ad, struct party_booking_ad_info, 1);
pb_ad->index = party->booking_nextid++;
return pb_ad;
}
-void party_recruit_register(struct map_session_data *sd, short level, const char *notice) {
+static void party_recruit_register(struct map_session_data *sd, short level, const char *notice)
+{
#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
+ nullpo_retv(notice);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1202,11 +1288,15 @@ void party_recruit_register(struct map_session_data *sd, short level, const char
#endif
}
-void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job) {
+static void party_booking_register(struct map_session_data *sd, short level, short mapid, short *job)
+{
#ifndef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
int i;
+ nullpo_retv(sd);
+ nullpo_retv(job);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
{
@@ -1236,10 +1326,12 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi
#endif
}
-void party_recruit_update(struct map_session_data *sd, const char *notice) {
+static void party_recruit_update(struct map_session_data *sd, const char *notice)
+{
#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1256,11 +1348,15 @@ void party_recruit_update(struct map_session_data *sd, const char *notice) {
return;
#endif
}
-void party_booking_update(struct map_session_data *sd, short* job) {
+static void party_booking_update(struct map_session_data *sd, short *job)
+{
#ifndef PARTY_RECRUIT
int i;
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
+ nullpo_retv(job);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1279,7 +1375,8 @@ void party_booking_update(struct map_session_data *sd, short* job) {
#endif
}
-void party_recruit_search(struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount) {
+static void party_recruit_search(struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount)
+{
#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
int count = 0;
@@ -1287,6 +1384,7 @@ void party_recruit_search(struct map_session_data *sd, short level, short mapid,
bool more_result = false;
struct DBIterator *iter = db_iterator(party->booking_db);
+ nullpo_retv(sd);
memset(result_list, 0, sizeof(result_list));
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) )
@@ -1309,7 +1407,8 @@ void party_recruit_search(struct map_session_data *sd, short level, short mapid,
return;
#endif
}
-void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount) {
+static void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount)
+{
#ifndef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
int i;
@@ -1318,6 +1417,8 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
bool more_result = false;
struct DBIterator *iter = db_iterator(party->booking_db);
+ nullpo_retv(sd);
+
memset(result_list, 0, sizeof(result_list));
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) ) {
@@ -1349,10 +1450,12 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
#endif
}
-bool party_booking_delete(struct map_session_data *sd)
+static bool party_booking_delete(struct map_session_data *sd)
{
struct party_booking_ad_info* pb_ad;
+ nullpo_retr(false, sd);
+
if((pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id))!=NULL)
{
#ifdef PARTY_RECRUIT
@@ -1364,12 +1467,14 @@ bool party_booking_delete(struct map_session_data *sd)
}
return true;
}
-void do_final_party(void) {
+static void do_final_party(void)
+{
party->db->destroy(party->db,party->db_final);
db_destroy(party->booking_db); // Party Booking [Spiria]
}
// Constructor, init vars
-void do_init_party(bool minimal) {
+static void do_init_party(bool minimal)
+{
if (minimal)
return;
@@ -1378,12 +1483,14 @@ void do_init_party(bool minimal) {
timer->add_func_list(party->send_xy_timer, "party_send_xy_timer");
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
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void party_defaults(void) {
+ * Default Functions : party.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void party_defaults(void)
+{
party = &party_s;
/* */
@@ -1420,7 +1527,6 @@ void party_defaults(void) {
party->send_levelup = party_send_levelup;
party->send_logout = party_send_logout;
party->send_message = party_send_message;
- party->recv_message = party_recv_message;
party->skill_check = party_skill_check;
party->send_xy_clear = party_send_xy_clear;
party->exp_share = party_exp_share;
diff --git a/src/map/party.h b/src/map/party.h
index 253f074bb..c2306b7a8 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -117,8 +117,7 @@ struct party_interface {
void (*send_movemap) (struct map_session_data *sd);
void (*send_levelup) (struct map_session_data *sd);
int (*send_logout) (struct map_session_data *sd);
- int (*send_message) (struct map_session_data *sd,const char *mes,int len);
- int (*recv_message) (int party_id,int account_id,const char *mes,int len);
+ int (*send_message) (struct map_session_data *sd, const char *mes);
int (*skill_check) (struct map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv);
int (*send_xy_clear) (struct party_data *p);
int (*exp_share) (struct party_data *p,struct block_list *src,unsigned int base_exp,unsigned int job_exp,int zeny);
diff --git a/src/map/path.c b/src/map/path.c
index 543497c33..f271e8219 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
#define DIR_SOUTH 4
#define DIR_EAST 8
-struct path_interface path_s;
+static struct path_interface path_s;
struct path_interface *path;
/// @name Structures and defines for A* pathfinding
@@ -85,10 +85,11 @@ static const unsigned char walk_choices [3][3] =
* Find the closest reachable cell, 'count' cells away from (x0,y0) in direction (dx,dy).
* Income after the coordinates of the blow
*------------------------------------------*/
-int path_blownpos(struct block_list *bl, int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
+static int path_blownpos(struct block_list *bl, int16 m, int16 x0, int16 y0, int16 dx, int16 dy, int count)
{
struct map_data *md;
+ Assert_retr(-1, m >= 0 && m < map->count);
if( !map->list[m].cell )
return -1;
md = &map->list[m];
@@ -118,7 +119,7 @@ int path_blownpos(struct block_list *bl, int16 m,int16 x0,int16 y0,int16 dx,int1
/*==========================================
* is ranged attack from (x0,y0) to (x1,y1) possible?
*------------------------------------------*/
-bool path_search_long(struct shootpath_data *spd,struct block_list *bl,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,cell_chk cell)
+static bool path_search_long(struct shootpath_data *spd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, cell_chk cell)
{
int dx, dy;
int wx = 0, wy = 0;
@@ -126,6 +127,8 @@ bool path_search_long(struct shootpath_data *spd,struct block_list *bl,int16 m,i
struct map_data *md;
struct shootpath_data s_spd;
+ Assert_retr(false, m >= 0 && m < map->count);
+
if( spd == NULL )
spd = &s_spd; // use dummy output variable
@@ -189,10 +192,8 @@ bool path_search_long(struct shootpath_data *spd,struct block_list *bl,int16 m,i
/// Ensures there is enough space in array to store new element.
static void heap_push_node(struct node_heap *heap, struct path_node *node)
{
-#ifndef __clang_analyzer__ // TODO: Figure out why clang's static analyzer doesn't like this
BHEAP_ENSURE(*heap, 1, 256);
BHEAP_PUSH2(*heap, node, NODE_MINTOPCMP, swap_ptr);
-#endif // __clang_analyzer__
}
/// Updates path_node in the binary node_heap.
@@ -252,12 +253,14 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16
* flag: &1 = easy path search only
* cell: type of obstruction to check for
*------------------------------------------*/
-bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
+static bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
{
- register int i, j, x, y, dx, dy;
+ register int i, x, y, dx, dy;
struct map_data *md;
struct walkpath_data s_wpd;
+ Assert_retr(false, m >= 0 && m < map->count);
+
if (wpd == NULL)
wpd = &s_wpd; // use dummy output variable
@@ -315,8 +318,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
}
return false; // easy path unsuccessful
- }
- else { // !(flag&1)
+ } else { // !(flag&1)
// A* (A-star) pathfinding
// We always use A* for finding walkpaths because it is what game client uses.
// Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
@@ -331,6 +333,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
int xs = md->xs - 1;
int ys = md->ys - 1;
int len = 0;
+ int j;
memset(tp, 0, sizeof(tp));
// Start node
@@ -407,7 +410,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
}
for (it = current; it->parent != NULL; it = it->parent, len++);
- if (len > sizeof(wpd->path)) {
+ if (len > (int)sizeof(wpd->path)) {
return false;
}
@@ -426,7 +429,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
}
//Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml
-bool check_distance(int dx, int dy, int distance)
+static bool check_distance(int dx, int dy, int distance)
{
#ifdef CIRCULAR_AREA
//In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks.
@@ -438,7 +441,7 @@ bool check_distance(int dx, int dy, int distance)
#endif
}
-unsigned int distance(int dx, int dy)
+static unsigned int distance(int dx, int dy)
{
#ifdef CIRCULAR_AREA
unsigned int min, max;
@@ -475,7 +478,7 @@ unsigned int distance(int dx, int dy)
* @param distance: Distance to check against
* @return Within distance(1); Not within distance(0);
*/
-bool check_distance_client(int dx, int dy, int distance)
+static bool check_distance_client(int dx, int dy, int distance)
{
if(distance < 0) distance = 0;
@@ -489,7 +492,7 @@ bool check_distance_client(int dx, int dy, int distance)
* @param dy: Vertical distance
* @return Circular distance
*/
-int distance_client(int dx, int dy)
+static int distance_client(int dx, int dy)
{
double temp_dist = sqrt((double)(dx*dx + dy*dy));
@@ -502,7 +505,8 @@ int distance_client(int dx, int dy)
return ((int)temp_dist);
}
-void path_defaults(void) {
+void path_defaults(void)
+{
path = &path_s;
path->blownpos = path_blownpos;
diff --git a/src/map/path.h b/src/map/path.h
index c84b77eb0..04072e303 100644
--- a/src/map/path.h
+++ b/src/map/path.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/pc.c b/src/map/pc.c
index 57b2fe19a..5faadf76a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/date.h" // is_day_of_*()
#include "map/duel.h"
@@ -42,6 +43,7 @@
#include "map/mail.h"
#include "map/map.h"
#include "map/mercenary.h"
+#include "map/messages.h"
#include "map/mob.h" // struct mob_data
#include "map/npc.h" // fake_nd
#include "map/party.h" // party-"search()
@@ -53,6 +55,7 @@
#include "map/skill.h"
#include "map/status.h" // struct status_data
#include "map/storage.h"
+#include "map/achievement.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/core.h" // get_svn_revision()
@@ -74,16 +77,21 @@
#include <string.h>
#include <time.h>
-struct pc_interface pc_s;
+static struct pc_interface pc_s;
struct pc_interface *pc;
+static struct class_exp_tables exptables;
+
//Converts a class to its array index for CLASS_COUNT defined arrays.
//Note that it does not do a validity check for speed purposes, where parsing
//player input make sure to use a pc->db_checkid first!
-int pc_class2idx(int class_) {
- if (class_ >= JOB_NOVICE_HIGH)
- return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC;
- return class_;
+static int pc_class2idx(int class)
+{
+ if (class >= JOB_NOVICE_HIGH) {
+ class += - JOB_NOVICE_HIGH + JOB_MAX_BASIC;
+ }
+ Assert_ret(class >= 0 && class < CLASS_COUNT);
+ return class;
}
/**
@@ -92,7 +100,7 @@ int pc_class2idx(int class_) {
* required to provide a session.
* Caller must release dummy on its own when it's no longer needed.
*/
-struct map_session_data* pc_get_dummy_sd(void)
+static struct map_session_data *pc_get_dummy_sd(void)
{
struct map_session_data *dummy_sd;
CREATE(dummy_sd, struct map_session_data, 1);
@@ -106,9 +114,10 @@ struct map_session_data* pc_get_dummy_sd(void)
* @param group_id Group ID
* @return 1 on error, 0 on success
*/
-int pc_set_group(struct map_session_data *sd, int group_id)
+static int pc_set_group(struct map_session_data *sd, int group_id)
{
GroupSettings *group = pcg->id2group(group_id);
+ nullpo_retr(1, sd);
if (group == NULL)
return 1;
sd->group_id = group_id;
@@ -119,12 +128,13 @@ int pc_set_group(struct map_session_data *sd, int group_id)
/**
* Checks if commands used by player should be logged.
*/
-bool pc_should_log_commands(struct map_session_data *sd)
+static bool pc_should_log_commands(struct map_session_data *sd)
{
+ nullpo_retr(true, sd);
return pcg->should_log_commands(sd->group);
}
-int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data)
+static int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data)
{
struct map_session_data *sd = map->id2sd(id);
@@ -141,7 +151,8 @@ int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
}
-void pc_setinvincibletimer(struct map_session_data* sd, int val) {
+static void pc_setinvincibletimer(struct map_session_data *sd, int val)
+{
nullpo_retv(sd);
val += map->list[sd->bl.m].invincible_time_inc;
@@ -151,7 +162,7 @@ void pc_setinvincibletimer(struct map_session_data* sd, int val) {
sd->invincible_timer = timer->add(timer->gettick()+val,pc->invincible_timer,sd->bl.id,0);
}
-void pc_delinvincibletimer(struct map_session_data* sd)
+static void pc_delinvincibletimer(struct map_session_data *sd)
{
nullpo_retv(sd);
@@ -163,7 +174,8 @@ void pc_delinvincibletimer(struct map_session_data* sd)
}
}
-int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
int i;
@@ -195,12 +207,13 @@ int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) {
}
/**
-* Get the possible number of spiritball that a player can call.
-* @param sd the affected player structure
-* @param min the minimum number of spiritball regardless the level of MO_CALLSPIRITS
-* @retval total number of spiritball
-**/
-int pc_getmaxspiritball(struct map_session_data *sd, int min) {
+ * Get the possible number of spiritball that a player can call.
+ * @param sd the affected player structure
+ * @param min the minimum number of spiritball regardless the level of MO_CALLSPIRITS
+ * @retval total number of spiritball
+ */
+static int pc_getmaxspiritball(struct map_session_data *sd, int min)
+{
int result;
nullpo_ret(sd);
@@ -216,7 +229,7 @@ int pc_getmaxspiritball(struct map_session_data *sd, int min) {
return result;
}
-int pc_addspiritball(struct map_session_data *sd,int interval,int max)
+static int pc_addspiritball(struct map_session_data *sd, int interval, int max)
{
int tid, i;
@@ -242,15 +255,22 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int));
sd->spirit_timer[i] = tid;
sd->spiritball++;
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
+ pc->addspiritball_sub(sd);
+
+ return 0;
+}
+
+static int pc_addspiritball_sub(struct map_session_data *sd)
+{
+ nullpo_ret(sd);
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD)
clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
-
return 0;
}
-int pc_delspiritball(struct map_session_data *sd,int count,int type)
+static int pc_delspiritball(struct map_session_data *sd, int count, int type)
{
int i;
@@ -280,15 +300,23 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
sd->spirit_timer[i] = INVALID_TIMER;
}
- if(!type) {
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(&sd->bl,sd->spiritball);
- else
- clif->spiritball(&sd->bl);
+ if (!type) {
+ pc->delspiritball_sub(sd);
}
return 0;
}
-int pc_check_banding(struct block_list *bl, va_list ap)
+
+static int pc_delspiritball_sub(struct map_session_data *sd)
+{
+ nullpo_ret(sd);
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD)
+ clif->millenniumshield(&sd->bl,sd->spiritball);
+ else
+ clif->spiritball(&sd->bl);
+ return 0;
+}
+
+static int pc_check_banding(struct block_list *bl, va_list ap)
{
int *c, *b_sd;
struct block_list *src;
@@ -316,7 +344,8 @@ int pc_check_banding(struct block_list *bl, va_list ap)
return 0;
}
-int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
+static int pc_banding(struct map_session_data *sd, uint16 skill_lv)
+{
int c;
int b_sd[MAX_PARTY]; // In case of a full Royal Guard party.
int i, j, hp, extra_hp = 0, tmp_qty = 0;
@@ -370,7 +399,7 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
for( j = 0; j < i; j++ ) {
bsd = map->id2sd(b_sd[j]);
if( bsd != NULL ) {
- status->set_hp(&bsd->bl,hp,0); // Set hp
+ status->set_hp(&bsd->bl, hp, STATUS_HEAL_DEFAULT); // Set hp
if( (sc = status->get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] ) {
sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
status_calc_bl(&bsd->bl, status->sc2scb_flag(SC_BANDING)); // Set atk and def.
@@ -381,53 +410,111 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
return c;
}
-// Increases a player's fame points and displays a notice to him
-void pc_addfame(struct map_session_data *sd,int count)
+/**
+ * Increases a player's fame points and displays a notice to them.
+ *
+ * If the character's job class doesn't allow the specified rank type, nothing
+ * happens and the request is ignored.
+ *
+ * @param sd The target character.
+ * @param type The fame list type (@see enum fame_list_type).
+ * @param count The amount of points to add.
+ */
+static void pc_addfame(struct map_session_data *sd, int ranktype, int count)
{
- int ranktype = -1;
nullpo_retv(sd);
+
+ switch (ranktype) {
+ case RANKTYPE_BLACKSMITH:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_BLACKSMITH)
+ return;
+ break;
+ case RANKTYPE_ALCHEMIST:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_ALCHEMIST)
+ return;
+ break;
+ case RANKTYPE_TAEKWON:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_TAEKWON)
+ return;
+ break;
+ case RANKTYPE_PK:
+ // Not supported
+ FALLTHROUGH
+ default:
+ Assert_retv(0);
+ }
+
sd->status.fame += count;
- if(sd->status.fame > MAX_FAME)
+ if (sd->status.fame > MAX_FAME)
sd->status.fame = MAX_FAME;
- switch(sd->class_&MAPID_UPPERMASK){
- case MAPID_BLACKSMITH: ranktype = RANKTYPE_BLACKSMITH; break;
- case MAPID_ALCHEMIST: ranktype = RANKTYPE_ALCHEMIST; break;
- case MAPID_TAEKWON: ranktype = RANKTYPE_TAEKWON; break;
- }
+
clif->update_rankingpoint(sd, ranktype, count);
chrif->updatefamelist(sd);
}
-// Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else
-unsigned char pc_famerank(int char_id, int job)
+/**
+ * Returns a character's rank in the specified fame list.
+ *
+ * @param char_id The character ID.
+ * @param ranktype The rank list type (@see enum fame_list_type).
+ * @return The rank position (1-based index)
+ * @retval 0 if the character isn't in the specified list.
+ */
+static int pc_fame_rank(int char_id, int ranktype)
{
int i;
- switch(job){
- case MAPID_BLACKSMITH: // Blacksmith
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->smith_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
- case MAPID_ALCHEMIST: // Alchemist
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->chemist_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
- case MAPID_TAEKWON: // Taekwon
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->taekwon_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
+ switch (ranktype) {
+ case RANKTYPE_BLACKSMITH:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->smith_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_ALCHEMIST:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->chemist_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_TAEKWON:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->taekwon_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_PK: // Not implemented
+ FALLTHROUGH
+ default:
+ Assert_ret(0);
}
return 0;
}
-int pc_setrestartvalue(struct map_session_data *sd,int type) {
+/**
+ * Returns the appropriate fame list type for the given job.
+ *
+ * @param job_mapid The job (in MapID format)
+ * @return the appropriate fame list type (@see enum fame_list_type).
+ * @retval RANKTYPE_UNKNOWN if no appropriate type exists.
+ */
+static int pc_famelist_type(uint16 job_mapid)
+{
+ switch (job_mapid & MAPID_UPPERMASK) {
+ case MAPID_BLACKSMITH:
+ return RANKTYPE_BLACKSMITH;
+ case MAPID_ALCHEMIST:
+ return RANKTYPE_ALCHEMIST;
+ case MAPID_TAEKWON:
+ return RANKTYPE_TAEKWON;
+ default:
+ return RANKTYPE_UNKNOWN;
+ }
+}
+
+static int pc_setrestartvalue(struct map_session_data *sd, int type)
+{
struct status_data *st, *bst;
nullpo_ret(sd);
@@ -436,10 +523,9 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
if (type&1) {
//Normal resurrection
- st->hp = 1; //Otherwise status->heal may fail if dead.
- status->heal(&sd->bl, bst->hp, 0, 1);
+ status->heal(&sd->bl, bst->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_ALLOWREVIVE);
if( st->sp < bst->sp )
- status->set_sp(&sd->bl, bst->sp, 1);
+ status->set_sp(&sd->bl, bst->sp, STATUS_HEAL_FORCED);
} else { //Just for saving on the char-server (with values as if respawned)
sd->status.hp = bst->hp;
sd->status.sp = (st->sp < bst->sp) ? bst->sp : st->sp;
@@ -450,7 +536,8 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
/*==========================================
Rental System
*------------------------------------------*/
-int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
+static int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
if( sd == NULL )
return 0;
@@ -464,8 +551,9 @@ int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
return 1;
}
-int pc_inventory_rental_clear(struct map_session_data *sd)
+static int pc_inventory_rental_clear(struct map_session_data *sd)
{
+ nullpo_ret(sd);
if( sd->rental_timer != INVALID_TIMER )
{
timer->delete(sd->rental_timer, pc->inventory_rental_end);
@@ -475,79 +563,21 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
return 1;
}
/* assumes i is valid (from default areas where it is called, it is) */
-void pc_rental_expire(struct map_session_data *sd, int i) {
- short nameid = sd->status.inventory[i].nameid;
-
- /* Soon to be dropped, we got plans to integrate it with item db */
- switch( nameid ) {
- case ITEMID_REINS_OF_MOUNT:
- status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
- break;
- case ITEMID_LOVE_ANGEL:
- if( sd->status.font == 1 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_SQUIRREL:
- if( sd->status.font == 2 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_GOGO:
- if( sd->status.font == 3 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_PICTURE_DIARY:
- if( sd->status.font == 4 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_MINI_HEART:
- if( sd->status.font == 5 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_NEWCOMER:
- if( sd->status.font == 6 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_KID:
- if( sd->status.font == 7 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_MAGIC_CASTLE:
- if( sd->status.font == 8 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- case ITEMID_BULGING_HEAD:
- if( sd->status.font == 9 ) {
- sd->status.font = 0;
- clif->font(sd);
- }
- break;
- }
+static void pc_rental_expire(struct map_session_data *sd, int i)
+{
+ nullpo_retv(sd);
+ Assert_retv(i >= 0 && i < sd->status.inventorySize);
clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_RENTAL);
}
-void pc_inventory_rentals(struct map_session_data *sd)
+static void pc_inventory_rentals(struct map_session_data *sd)
{
- int i, c = 0;
+ int c = 0;
int64 expire_tick, next_tick = INT64_MAX;
- for( i = 0; i < MAX_INVENTORY; i++ )
+ nullpo_retv(sd);
+ for (int i = 0; i < sd->status.inventorySize; i++ )
{ // Check for Rentals on Inventory
if( sd->status.inventory[i].nameid == 0 )
continue; // Nothing here
@@ -570,7 +600,7 @@ void pc_inventory_rentals(struct map_session_data *sd)
sd->rental_timer = INVALID_TIMER;
}
-void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
+static void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
{
int tick = seconds * 1000;
@@ -594,7 +624,7 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
/*==========================================
* prepares character for saving.
*------------------------------------------*/
-int pc_makesavestatus(struct map_session_data *sd)
+static int pc_makesavestatus(struct map_session_data *sd)
{
nullpo_ret(sd);
@@ -660,7 +690,7 @@ int pc_makesavestatus(struct map_session_data *sd)
/*==========================================
* Off init ? Connection?
*------------------------------------------*/
-int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd)
+static int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd)
{
nullpo_ret(sd);
@@ -673,7 +703,8 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo
sd->client_tick = client_tick;
sd->state.active = 0; //to be set to 1 after player is fully authed and loaded.
sd->bl.type = BL_PC;
- sd->canlog_tick = timer->gettick();
+ if (battle_config.prevent_logout_trigger & PLT_LOGIN)
+ sd->canlog_tick = timer->gettick();
//Required to prevent homunculus copuing a base speed of 0.
sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED;
sd->state.warp_clean = 1;
@@ -681,11 +712,13 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo
return 0;
}
-int pc_equippoint(struct map_session_data *sd,int n)
+// [4144] probably pc_equippoint should be replaced to pc_item_equippoint
+static int pc_equippoint(struct map_session_data *sd, int n)
{
int ep = 0;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < sd->status.inventorySize);
if(!sd->inventory_data[n])
return 0;
@@ -694,13 +727,13 @@ int pc_equippoint(struct map_session_data *sd,int n)
return 0; //Not equippable by players.
ep = sd->inventory_data[n]->equip;
- if (sd->inventory_data[n]->look == W_DAGGER
- || sd->inventory_data[n]->look == W_1HSWORD
- || sd->inventory_data[n]->look == W_1HAXE
+ if (sd->inventory_data[n]->subtype == W_DAGGER
+ || sd->inventory_data[n]->subtype == W_1HSWORD
+ || sd->inventory_data[n]->subtype == W_1HAXE
) {
if (pc->checkskill(sd,AS_LEFT) > 0
- || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN
- || (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO
+ || (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN
+ || (sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO
) {
//Kagerou and Oboro can dual wield daggers. [Rytech]
if( ep == EQP_HAND_R )
@@ -712,64 +745,89 @@ int pc_equippoint(struct map_session_data *sd,int n)
return ep;
}
-int pc_setinventorydata(struct map_session_data *sd)
+static int pc_item_equippoint(struct map_session_data *sd, struct item_data *id)
{
- int i;
+ int ep = 0;
+
+ nullpo_ret(sd);
+ nullpo_ret(id);
+
+ if (!itemdb->isequip2(id))
+ return 0; //Not equippable by players.
+
+ ep = id->equip;
+ if (id->subtype == W_DAGGER ||
+ id->subtype == W_1HSWORD ||
+ id->subtype == W_1HAXE) {
+ if (pc->checkskill(sd, AS_LEFT) > 0 ||
+ (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN ||
+ (sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) {
+ // Kagerou and Oboro can dual wield daggers. [Rytech]
+ if (ep == EQP_HAND_R)
+ return EQP_ARMS;
+ if (ep == EQP_SHADOW_WEAPON)
+ return EQP_SHADOW_ARMS;
+ }
+ }
+ return ep;
+}
+static int pc_setinventorydata(struct map_session_data *sd)
+{
nullpo_ret(sd);
- for (i = 0; i < MAX_INVENTORY; i++) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
int id = sd->status.inventory[i].nameid;
sd->inventory_data[i] = id?itemdb->search(id):NULL;
}
return 0;
}
-int pc_calcweapontype(struct map_session_data *sd)
+static int pc_calcweapontype(struct map_session_data *sd)
{
nullpo_ret(sd);
// single-hand
if(sd->weapontype2 == W_FIST) {
- sd->status.weapon = sd->weapontype1;
+ sd->weapontype = sd->weapontype1;
return 1;
}
if(sd->weapontype1 == W_FIST) {
- sd->status.weapon = sd->weapontype2;
+ sd->weapontype = sd->weapontype2;
return 1;
}
// dual-wield
- sd->status.weapon = 0;
+ sd->weapontype = W_FIST;
switch (sd->weapontype1){
case W_DAGGER:
switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DD; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_DS; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_DA; break;
+ case W_DAGGER: sd->weapontype = W_DOUBLE_DD; break;
+ case W_1HSWORD: sd->weapontype = W_DOUBLE_DS; break;
+ case W_1HAXE: sd->weapontype = W_DOUBLE_DA; break;
}
break;
case W_1HSWORD:
switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DS; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_SS; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_SA; break;
+ case W_DAGGER: sd->weapontype = W_DOUBLE_DS; break;
+ case W_1HSWORD: sd->weapontype = W_DOUBLE_SS; break;
+ case W_1HAXE: sd->weapontype = W_DOUBLE_SA; break;
}
break;
case W_1HAXE:
switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DA; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_SA; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_AA; break;
+ case W_DAGGER: sd->weapontype = W_DOUBLE_DA; break;
+ case W_1HSWORD: sd->weapontype = W_DOUBLE_SA; break;
+ case W_1HAXE: sd->weapontype = W_DOUBLE_AA; break;
}
}
// unknown, default to right hand type
- if (!sd->status.weapon)
- sd->status.weapon = sd->weapontype1;
+ if (sd->weapontype == W_FIST)
+ sd->weapontype = sd->weapontype1;
return 2;
}
-int pc_setequipindex(struct map_session_data *sd)
+static int pc_setequipindex(struct map_session_data *sd)
{
int i,j;
@@ -778,7 +836,7 @@ int pc_setequipindex(struct map_session_data *sd)
for(i=0;i<EQI_MAX;i++)
sd->equip_index[i] = -1;
- for(i=0;i<MAX_INVENTORY;i++) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if(sd->status.inventory[i].nameid <= 0)
continue;
if(sd->status.inventory[i].equip) {
@@ -786,20 +844,30 @@ int pc_setequipindex(struct map_session_data *sd)
if(sd->status.inventory[i].equip & pc->equip_pos[j])
sd->equip_index[j] = i;
- if(sd->status.inventory[i].equip & EQP_HAND_R)
- {
- if(sd->inventory_data[i])
- sd->weapontype1 = sd->inventory_data[i]->look;
- else
- sd->weapontype1 = 0;
+ if (sd->status.inventory[i].equip & EQP_HAND_R) {
+ if (sd->inventory_data[i]) {
+ sd->weapontype1 = sd->inventory_data[i]->subtype;
+ sd->status.look.weapon = sd->inventory_data[i]->view_sprite;
+ } else {
+ sd->weapontype1 = W_FIST;
+ sd->status.look.weapon = 0;
+ }
}
- if( sd->status.inventory[i].equip & EQP_HAND_L )
- {
- if( sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON )
- sd->weapontype2 = sd->inventory_data[i]->look;
- else
- sd->weapontype2 = 0;
+ if (sd->status.inventory[i].equip & EQP_HAND_L) {
+ if (sd->inventory_data[i] != NULL) {
+ if (sd->inventory_data[i]->type == IT_WEAPON)
+ sd->weapontype2 = sd->inventory_data[i]->subtype;
+ else
+ sd->weapontype2 = W_FIST;
+ if (sd->inventory_data[i]->type == IT_ARMOR)
+ sd->has_shield = true;
+ else
+ sd->has_shield = false;
+ } else {
+ sd->weapontype2 = W_FIST;
+ sd->has_shield = false;
+ }
}
}
}
@@ -808,10 +876,11 @@ int pc_setequipindex(struct map_session_data *sd)
return 0;
}
-bool pc_isequipped(struct map_session_data *sd, int nameid)
+static bool pc_isequipped(struct map_session_data *sd, int nameid)
{
int i, j;
+ nullpo_retr(false, sd);
for (i = 0; i < EQI_MAX; i++) {
int index = sd->equip_index[i];
if( index < 0 ) continue;
@@ -833,7 +902,7 @@ bool pc_isequipped(struct map_session_data *sd, int nameid)
return false;
}
-bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd )
+static bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd)
{
if( !p1_sd || !p2_sd || !b_sd )
return false;
@@ -874,7 +943,7 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd
return false;
}
- if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) )
+ if (!(b_sd->status.class >= JOB_NOVICE && b_sd->status.class <= JOB_THIEF) && b_sd->status.class != JOB_SUPER_NOVICE)
return false;
return true;
@@ -883,21 +952,22 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd
/*==========================================
* Adoption Process
*------------------------------------------*/
-bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd)
+static bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd)
{
- int job, joblevel;
- unsigned int jobexp;
+ int class, joblevel;
+ uint64 jobexp;
if( !pc->can_Adopt(p1_sd, p2_sd, b_sd) )
return false;
+ nullpo_retr(false, b_sd);
// Preserve current job levels and progress
joblevel = b_sd->status.job_level;
jobexp = b_sd->status.job_exp;
- job = pc->mapid2jobid(b_sd->class_|JOBL_BABY, b_sd->status.sex);
- if( job != -1 && !pc->jobchange(b_sd, job, 0) )
- { // Success, proceed to configure parents and baby skills
+ class = pc->mapid2jobid(b_sd->job | JOBL_BABY, b_sd->status.sex);
+ if (class != -1 && !pc->jobchange(b_sd, class, 0)) {
+ // Success, proceed to configure parents and baby skills
p1_sd->status.child = b_sd->status.char_id;
p2_sd->status.child = b_sd->status.char_id;
b_sd->status.father = p1_sd->status.char_id;
@@ -917,25 +987,34 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,
pc->skill(p1_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT);
pc->skill(p2_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT);
+ // Achievements [Smokexyz/Hercules]
+ achievement->validate_adopt(p1_sd, true); // Parent 1
+ achievement->validate_adopt(p2_sd, true); // Parent 2
+ achievement->validate_adopt(b_sd, false); // Baby
+
return true;
}
return false; // Job Change Fail
}
-/*=================================================
- * Checks if the player can equip the item at index n in inventory.
- * Returns 0 (no) or 1 (yes).
- *------------------------------------------------*/
-int pc_isequip(struct map_session_data *sd,int n)
+/**
+ * Checks if a character can equip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @retval 0 Character can't equip the item.
+ * @retval 1 Character can equip the item.
+ *
+ **/
+static int pc_isequip(struct map_session_data *sd, int n)
{
- struct item_data *item;
-
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < sd->status.inventorySize);
- item = sd->inventory_data[n];
+ struct item_data *item = sd->inventory_data[n];
- if(item == NULL)
+ if (item == NULL)
return 0;
#if PACKETVER <= 20100707
@@ -943,89 +1022,120 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
#endif
- if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
+ if (pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
return 1;
- if (item->elv && sd->status.base_level < (unsigned int)item->elv) {
- clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL);
+ if (item->elv != 0 && sd->status.base_level < item->elv) {
+#if PACKETVER >= 20100525
+ clif->msgtable(sd, MSG_CANNOT_EQUIP_ITEM_LEVEL);
+#endif
return 0;
}
- if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) {
- clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL);
+
+ if (item->elvmax != 0 && sd->status.base_level > item->elvmax) {
+#if PACKETVER >= 20100525
+ clif->msgtable(sd, MSG_CANNOT_EQUIP_ITEM_LEVEL);
+#endif
return 0;
}
- if(item->sex != 2 && sd->status.sex != item->sex)
+
+ if (item->sex != SEX_SERVER && sd->status.sex != item->sex)
return 0;
- if ( item->equip & EQP_AMMO ) {
- if ( (sd->state.active && !pc_iscarton(sd)) // check if sc data is already loaded.
- && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) {
- clif->msgtable(sd, MSG_ITEM_NEED_CART);
+ if ((item->equip & EQP_AMMO) != 0) {
+ if (sd->state.active != 0 && !pc_iscarton(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_GENETIC) { // Check if sc data is already loaded.
+#if PACKETVER_RE_NUM >= 20090529 || PACKETVER_MAIN_NUM >= 20090603 || defined(PACKETVER_ZERO)
+ clif->msgtable(sd, MSG_USESKILL_FAIL_CART);
+#endif
return 0;
}
- if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) {
- clif->msgtable(sd, MSG_ITEM_NEED_MADO);
+
+ if (!pc_ismadogear(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
+#if PACKETVER_RE_NUM >= 20090226 || PACKETVER_MAIN_NUM >= 20090304 || defined(PACKETVER_ZERO)
+ clif->msgtable(sd, MSG_USESKILL_FAIL_MADOGEAR);
+#endif
return 0;
}
}
- if (sd->sc.count) {
- if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON]) // Also works with left-hand weapons [DracoRPG]
+ if ((battle_config.unequip_restricted_equipment & 1) != 0) {
+ for (int i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++)
+ if (map->list[sd->bl.m].zone->disabled_items[i] == item->nameid)
+ return 0;
+ }
+
+ if ((battle_config.unequip_restricted_equipment & 2) != 0 && !itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int slot = 0; slot < item->slot; slot++)
+ for (int i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++)
+ if (map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].card[slot])
+ return 0;
+ }
+
+ if (sd->sc.count != 0) {
+ if ((item->equip & EQP_ARMS) != 0 && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON] != NULL) // Also works with left-hand weapons. [DracoRPG]
return 0;
- if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_NOEQUIPSHIELD])
+
+ if ((item->equip & EQP_SHIELD) != 0 && item->type == IT_ARMOR && sd->sc.data[SC_NOEQUIPSHIELD] != NULL)
return 0;
- if(item->equip & EQP_ARMOR && sd->sc.data[SC_NOEQUIPARMOR])
+
+ if ((item->equip & EQP_ARMOR) != 0 && sd->sc.data[SC_NOEQUIPARMOR] != NULL)
return 0;
- if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_NOEQUIPHELM])
+
+ if ((item->equip & EQP_HEAD_TOP) != 0 && sd->sc.data[SC_NOEQUIPHELM] != NULL)
return 0;
- if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSARY])
+
+ if ((item->equip & EQP_ACC) != 0 && sd->sc.data[SC__STRIPACCESSARY] != NULL)
return 0;
- if(item->equip && sd->sc.data[SC_KYOUGAKU])
+
+ if (item->equip != 0 && sd->sc.data[SC_KYOUGAKU] != NULL)
return 0;
- if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SUPERNOVICE) {
- //Spirit of Super Novice equip bonuses. [Skotlex]
- if (sd->status.base_level > 90 && item->equip & EQP_HELM)
- return 1; //Can equip all helms
-
- if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON)
- switch(item->look) { //In weapons, the look determines type of weapon.
- case W_DAGGER: //Level 4 Knives are equippable.. this means all knives, I'd guess?
- case W_1HSWORD: //All 1H swords
- case W_1HAXE: //All 1H Axes
- case W_MACE: //All 1H Maces
- case W_STAFF: //All 1H Staves
- return 1;
+ if (sd->sc.data[SC_SOULLINK] != NULL && sd->sc.data[SC_SOULLINK]->val2 == SL_SUPERNOVICE) { // Spirit of Super Novice equip bonuses. [Skotlex]
+ if (sd->status.base_level > 90 && (item->equip & EQP_HELM) != 0)
+ return 1; // Can equip all helms.
+
+ if (sd->status.base_level > 96 && (item->equip & EQP_ARMS) != 0 && item->type == IT_WEAPON) {
+ switch (item->subtype) { // In weapons, the look determines type of weapon.
+ case W_DAGGER: // Level 4 Knives are equippable.. this means all knives, I'd guess?
+ case W_1HSWORD: // All 1H swords.
+ case W_1HAXE: // All 1H axes.
+ case W_MACE: // All 1H maces.
+ case W_STAFF: // All 1H staffs.
+ return 1;
}
+ }
}
}
- //Not equipable by class. [Skotlex]
- if (!(1ULL<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]))
- return 0;
- //Not usable by upper class. [Inkfish]
- while( 1 ) {
- if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
- if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY ) break;
- if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD ) break;
+
+ uint64 mask_job = 1ULL << (sd->job & MAPID_BASEMASK);
+ uint64 mask_item = item->class_base[((sd->job & JOBL_2_1) != 0) ? 1 : (((sd->job & JOBL_2_2) != 0) ? 2 : 0)];
+
+ if ((mask_job & mask_item) == 0) // Not equipable by class. [Skotlex]
return 0;
- }
- if ( battle_config.unequip_restricted_equipment & 1 ) {
- int i;
- for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
- if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid )
- return 0;
- }
+ // Not usable by upper class. [Inkfish]
+ while (1) {
+ if ((item->class_upper & ITEMUPPER_NORMAL) != 0) {
+ if ((sd->job & (JOBL_UPPER | JOBL_THIRD | JOBL_BABY)) == 0)
+ break;
+ }
- if ( battle_config.unequip_restricted_equipment & 2 ) {
- if ( !itemdb_isspecial( sd->status.inventory[n].card[0] ) ) {
- int i, slot;
- for ( slot = 0; slot < MAX_SLOTS; slot++ )
- for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
- if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].card[slot] )
- return 0;
+ if ((item->class_upper & ITEMUPPER_UPPER) != 0) {
+ if ((sd->job & (JOBL_UPPER | JOBL_THIRD)) != 0)
+ break;
+ }
+
+ if ((item->class_upper & ITEMUPPER_BABY) != 0) {
+ if ((sd->job & JOBL_BABY) != 0)
+ break;
}
+
+ if ((item->class_upper & ITEMUPPER_THIRD) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0)
+ break;
+ }
+
+ return 0;
}
return 1;
@@ -1035,11 +1145,14 @@ int pc_isequip(struct map_session_data *sd,int n)
* No problem with the session id
* set the status that has been sent from char server
*------------------------------------------*/
-bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers)
+static bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers)
{
int i;
int64 tick = timer->gettick();
- uint32 ip = sockt->session[sd->fd]->client_addr;
+ uint32 ip;
+
+ nullpo_retr(false, sd);
+ ip = sockt->session[sd->fd]->client_addr;
sd->login_id2 = login_id2;
@@ -1051,6 +1164,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
}
memcpy(&sd->status, st, sizeof(*st));
+ memset(&sd->rodex, 0x0, sizeof(sd->rodex));
+ VECTOR_INIT(sd->rodex.messages);
if (st->sex != sd->status.sex) {
clif->authfail_fd(sd->fd, 0);
@@ -1058,13 +1173,16 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
}
//Set the map-server used job id. [Skotlex]
- i = pc->jobid2mapid(sd->status.class_);
- if (i == -1) { //Invalid class?
- ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id);
- sd->status.class_ = JOB_NOVICE;
- sd->class_ = MAPID_NOVICE;
- } else
- sd->class_ = i;
+ {
+ int job = pc->jobid2mapid(sd->status.class);
+ if (job == -1) {
+ ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class, sd->status.name, sd->status.account_id, sd->status.char_id);
+ sd->status.class = JOB_NOVICE;
+ sd->job = MAPID_NOVICE;
+ } else {
+ sd->job = job;
+ }
+ }
// Checks and fixes to character status data, that are required
// in case of configuration change or stuff, which cannot be
@@ -1145,7 +1263,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->sc.option = sd->status.option; //This is the actual option used in battle.
//Set here because we need the inventory data for weapon sprite parsing.
- status->set_viewdata(&sd->bl, sd->status.class_);
+ status->set_viewdata(&sd->bl, sd->status.class);
unit->dataset(&sd->bl);
sd->guild_x = -1;
@@ -1161,14 +1279,18 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->bg_queue.client_has_bg_data = 0;
sd->bg_queue.type = 0;
+ VECTOR_INIT(sd->channels);
VECTOR_INIT(sd->script_queues);
+ VECTOR_INIT(sd->achievement); // Achievements [Smokexyz/Hercules]
+ VECTOR_INIT(sd->storage.item); // initialize storage item vector.
+ VECTOR_INIT(sd->hatEffectId);
sd->state.dialog = 0;
sd->delayed_damage = 0;
- if( battle_config.item_check )
- sd->state.itemcheck = 1;
+ if (battle->bc->item_check != PCCHECKITEM_NONE) // Check and flag items for inspection.
+ sd->itemcheck = (enum pc_checkitem_types) battle->bc->item_check;
// Event Timers
for( i = 0; i < MAX_EVENTTIMER; i++ )
@@ -1207,6 +1329,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
pc->setpos(sd,sd->status.last_point.map,0,0,CLR_OUTSIGHT);
}
+ clif->inventoryExpansionInfo(sd);
+ clif->overweight_percent(sd);
clif->authok(sd);
//Prevent S. Novices from getting the no-death bonus just yet. [Skotlex]
@@ -1219,6 +1343,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
" Group '"CL_WHITE"%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id,
CONVIP(ip), sd->group_id);
+
// Send friends list
clif->friendslist_send(sd);
@@ -1240,16 +1365,6 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
clif->changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
}
- /**
- * Check if player have any cool downs on
- **/
- skill->cooldown_load(sd);
-
- /**
- * Check if player have any item cooldowns on
- **/
- pc->itemcd_do(sd,true);
-
#ifdef GP_BOUND_ITEMS
if( sd->status.party_id == 0 )
pc->bound_clear(sd,IBT_PARTY);
@@ -1267,14 +1382,15 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
/*==========================================
* Closes a connection because it failed to be authenticated from the char server.
*------------------------------------------*/
-void pc_authfail(struct map_session_data *sd)
+static void pc_authfail(struct map_session_data *sd)
{
+ nullpo_retv(sd);
clif->authfail_fd(sd->fd, 0);
return;
}
//Attempts to set a mob.
-int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
+static int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
{
int class_;
if (!sd || !bl || pos < 0 || pos >= MAX_PC_FEELHATE)
@@ -1294,7 +1410,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
return 0; //Wrong size
}
sd->hate_mob[pos] = class_;
- pc_setglobalreg(sd,script->add_str(pc->sg_info[pos].hate_var),class_+1);
+ pc_setglobalreg(sd,script->add_variable(pc->sg_info[pos].hate_var),class_+1);
clif->hate_info(sd, pos, class_, 1);
return 1;
}
@@ -1302,33 +1418,34 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
/*==========================================
* Invoked once after the char/account/account2 registry variables are received. [Skotlex]
*------------------------------------------*/
-int pc_reg_received(struct map_session_data *sd)
+static int pc_reg_received(struct map_session_data *sd)
{
int i, idx = 0;
+ nullpo_ret(sd);
sd->vars_ok = true;
- sd->change_level_2nd = pc_readglobalreg(sd,script->add_str("jobchange_level"));
- sd->change_level_3rd = pc_readglobalreg(sd,script->add_str("jobchange_level_3rd"));
- sd->die_counter = pc_readglobalreg(sd,script->add_str("PC_DIE_COUNTER"));
+ sd->change_level_2nd = pc_readglobalreg(sd,script->add_variable("jobchange_level"));
+ sd->change_level_3rd = pc_readglobalreg(sd,script->add_variable("jobchange_level_3rd"));
+ sd->die_counter = pc_readglobalreg(sd,script->add_variable("PC_DIE_COUNTER"));
// Cash shop
- sd->cashPoints = pc_readaccountreg(sd,script->add_str("#CASHPOINTS"));
- sd->kafraPoints = pc_readaccountreg(sd,script->add_str("#KAFRAPOINTS"));
+ sd->cashPoints = pc_readaccountreg(sd,script->add_variable("#CASHPOINTS"));
+ sd->kafraPoints = pc_readaccountreg(sd,script->add_variable("#KAFRAPOINTS"));
// Cooking Exp
- sd->cook_mastery = pc_readglobalreg(sd,script->add_str("COOK_MASTERY"));
+ sd->cook_mastery = pc_readglobalreg(sd,script->add_variable("COOK_MASTERY"));
- if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
+ if ((sd->job & MAPID_BASEMASK) == MAPID_TAEKWON) {
// Better check for class rather than skill to prevent "skill resets" from unsetting this
- sd->mission_mobid = pc_readglobalreg(sd,script->add_str("TK_MISSION_ID"));
- sd->mission_count = pc_readglobalreg(sd,script->add_str("TK_MISSION_COUNT"));
+ sd->mission_mobid = pc_readglobalreg(sd,script->add_variable("TK_MISSION_ID"));
+ sd->mission_count = pc_readglobalreg(sd,script->add_variable("TK_MISSION_COUNT"));
}
//SG map and mob read [Komurka]
for (i = 0; i < MAX_PC_FEELHATE; i++) {
//for now - someone need to make reading from txt/sql
- int j = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].feel_var));
+ int j = pc_readglobalreg(sd,script->add_variable(pc->sg_info[i].feel_var));
if (j != 0) {
sd->feel_map[i].index = j;
sd->feel_map[i].m = map->mapindex2mapid(j);
@@ -1336,24 +1453,24 @@ int pc_reg_received(struct map_session_data *sd)
sd->feel_map[i].index = 0;
sd->feel_map[i].m = -1;
}
- sd->hate_mob[i] = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].hate_var))-1;
+ sd->hate_mob[i] = pc_readglobalreg(sd,script->add_variable(pc->sg_info[i].hate_var))-1;
}
if ((i = pc->checkskill(sd,RG_PLAGIARISM)) > 0) {
- sd->cloneskill_id = pc_readglobalreg(sd,script->add_str("CLONE_SKILL"));
+ sd->cloneskill_id = pc_readglobalreg(sd,script->add_variable("CLONE_SKILL"));
if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id)) > 0) {
sd->status.skill[idx].id = sd->cloneskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("CLONE_SKILL_LV"));
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_variable("CLONE_SKILL_LV"));
if (sd->status.skill[idx].lv > i)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
if ((i = pc->checkskill(sd,SC_REPRODUCE)) > 0) {
- sd->reproduceskill_id = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL"));
+ sd->reproduceskill_id = pc_readglobalreg(sd,script->add_variable("REPRODUCE_SKILL"));
if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id)) > 0) {
sd->status.skill[idx].id = sd->reproduceskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL_LV"));
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_variable("REPRODUCE_SKILL_LV"));
if( i < sd->status.skill[idx].lv)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
@@ -1370,30 +1487,43 @@ int pc_reg_received(struct map_session_data *sd)
if (sd->status.guild_id)
guild->member_joined(sd);
- // pet
- if (sd->status.pet_id > 0)
- intif->request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id);
-
- // Homunculus [albator]
- if( sd->status.hom_id > 0 )
- intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id);
- if( sd->status.mer_id > 0 )
- intif->mercenary_request(sd->status.mer_id, sd->status.char_id);
- if( sd->status.ele_id > 0 )
- intif->elemental_request(sd->status.ele_id, sd->status.char_id);
+ if (sd->state.standalone == 0 && sd->state.autotrade == 0) { // prevents loading pets, homunculi, mercenaries or elementals if the character doesn't have a client attached
+ if (sd->status.pet_id != 0)
+ intif->request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id);
+ if (sd->status.hom_id != 0)
+ intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id);
+ if (sd->status.mer_id != 0)
+ intif->mercenary_request(sd->status.mer_id, sd->status.char_id);
+ if (sd->status.ele_id != 0)
+ intif->elemental_request(sd->status.ele_id, sd->status.char_id);
+ }
map->addiddb(&sd->bl);
map->delnickdb(sd->status.char_id, sd->status.name);
if (!chrif->auth_finished(sd))
ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id);
+ // Restore any cooldowns
+ skill->cooldown_load(sd);
+ pc->itemcd_do(sd, true);
+
pc->load_combo(sd);
status_calc_pc(sd,SCO_FIRST|SCO_FORCE);
chrif->scdata_request(sd->status.account_id, sd->status.char_id);
+ if (sd->status.clan_id)
+ clan->member_online(sd, true);
+
+ //Auth is fully okay, update last_login
+ sd->status.last_login = time(NULL);
+
+ // Storage Request
+ intif->request_account_storage(sd);
+
intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
intif->request_questlog(sd);
+ intif->rodex_checkhasnew(sd);
if (sd->state.connect_new == 0 && sd->fd) { //Character already loaded map! Gotta trigger LoadEndAck manually.
sd->state.connect_new = 1;
@@ -1401,7 +1531,7 @@ int pc_reg_received(struct map_session_data *sd)
}
if (pc_isinvisible(sd)) {
- sd->vd.class_ = INVISIBLE_CLASS;
+ sd->vd.class = INVISIBLE_CLASS;
clif->message(sd->fd, msg_sd(sd,11)); // Invisible: On
// decrement the number of pvp players on the map
map->list[sd->bl.m].users_pvp--;
@@ -1416,15 +1546,19 @@ int pc_reg_received(struct map_session_data *sd)
if( npc->motd ) /* [Ind/Hercules] */
script->run(npc->motd->u.scr.script, 0, sd->bl.id, npc->fake_nd->bl.id);
+ // Achievements [Smokexyz/Hercules]
+ intif->achievements_request(sd);
+
return 1;
}
-int pc_calc_skillpoint(struct map_session_data* sd) {
+static int pc_calc_skillpoint(struct map_session_data *sd)
+{
int i,inf2,skill_point=0;
nullpo_ret(sd);
- for (i = 1; i < MAX_SKILL; i++) {
+ for (i = 1; i < MAX_SKILL_DB; i++) {
int skill_lv = pc->checkskill2(sd,i);
if (skill_lv > 0) {
inf2 = skill->dbs->db[i].inf2;
@@ -1442,71 +1576,85 @@ int pc_calc_skillpoint(struct map_session_data* sd) {
return skill_point;
}
-/*==========================================
- * Calculation of skill level.
- *------------------------------------------*/
-int pc_calc_skilltree(struct map_session_data *sd)
+static void pc_calc_skilltree_clear(struct map_session_data *sd)
{
- int i,id=0,flag;
- int c=0;
+ int i;
- nullpo_ret(sd);
- i = pc->calc_skilltree_normalize_job(sd);
- c = pc->mapid2jobid(i, sd->status.sex);
- if( c == -1 )
- { //Unable to normalize job??
- ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
- return 1;
- }
- c = pc->class2idx(c);
+ nullpo_retv(sd);
- for( i = 0; i < MAX_SKILL; i++ ) {
- if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
+ for (i = 0; i < MAX_SKILL_DB; i++) {
+ if (sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
- if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) {
- switch( skill->dbs->db[i].nameid ) {
+ if (sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
+ switch (skill->dbs->db[i].nameid) {
case NV_TRICKDEAD:
- 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;
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_NOVICE) {
+ sd->status.skill[i].id = 0;
+ sd->status.skill[i].lv = 0;
+ sd->status.skill[i].flag = 0;
}
break;
}
}
}
+}
+
+/*==========================================
+ * Calculation of skill level.
+ *------------------------------------------*/
+static int pc_calc_skilltree(struct map_session_data *sd)
+{
+ nullpo_ret(sd);
+ uint32 job = pc->calc_skilltree_normalize_job(sd);
+ int class = pc->mapid2jobid(job, sd->status.sex);
+ if (class == -1) {
+ //Unable to normalize job??
+ ShowError("pc_calc_skilltree: Unable to normalize job %u for character %s (%d:%d)\n", job, sd->status.name, sd->status.account_id, sd->status.char_id);
+ return 1;
+ }
+ int classidx = pc->class2idx(class);
- for( i = 0; i < MAX_SKILL; i++ ) {
- if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
- { // Restore original level of skills after deleting earned skills.
+ pc->calc_skilltree_clear(sd);
+
+ for (int i = 0; i < MAX_SKILL_DB; i++) {
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
+ // Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
- if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU )
- { //Enable Bard/Dancer spirit linked skills.
- if( sd->status.sex )
- { //Link dancer skills to bard.
- // i can be < 8?
- if( sd->status.skill[i-8].lv < 10 )
- continue;
- sd->status.skill[i].id = skill->dbs->db[i].nameid;
- sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
- sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
- } else { //Link bard skills to dancer.
- if( sd->status.skill[i].lv < 10 )
- continue;
- // i can be < 8?
- sd->status.skill[i-8].id = skill->dbs->db[i-8].nameid;
- sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
- sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
+ if (sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER
+ && ((skill->dbs->db[i].nameid >= BA_WHISTLE && skill->dbs->db[i].nameid <= BA_APPLEIDUN)
+ || (skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU))
+ ) {
+ //Enable Bard/Dancer spirit linked skills.
+ int linked_nameid = skill->get_linked_song_dance_id(skill->dbs->db[i].nameid);
+ if (linked_nameid == 0) {
+ Assert_report("Linked bard/dance skill not found");
+ continue;
}
+ int copy_from_index;
+ int copy_to_index;
+ if (sd->status.sex == SEX_MALE && skill->dbs->db[i].nameid >= BA_WHISTLE && skill->dbs->db[i].nameid <= BA_APPLEIDUN) {
+ copy_from_index = i;
+ copy_to_index = skill->get_index(linked_nameid);
+ } else {
+ copy_from_index = skill->get_index(linked_nameid);
+ copy_to_index = i;
+ }
+ if (copy_from_index < copy_to_index)
+ continue; // Copy only after the source skill has been filled into the tree
+ if (sd->status.skill[copy_from_index].lv < 10)
+ continue; // Copy only if the linked skill has been mastered
+ sd->status.skill[copy_to_index].id = skill->dbs->db[copy_to_index].nameid;
+ sd->status.skill[copy_to_index].lv = sd->status.skill[copy_from_index].lv; // Set the level to the same as the linking skill
+ sd->status.skill[copy_to_index].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
}
if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
- for( i = 0; i < MAX_SKILL; i++ ) {
+ for (int i = 0; i < MAX_SKILL_DB; i++) {
switch(skill->dbs->db[i].nameid) {
/**
* Dummy skills must be added here otherwise they'll be displayed in the,
@@ -1538,18 +1686,20 @@ int pc_calc_skilltree(struct map_session_data *sd)
return 0;
}
+ bool changed = false;
do {
- flag = 0;
- for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++) {
- int idx = pc->skill_tree[c][i].idx;
+ changed = false;
+ int id;
+ for (int i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
+ int idx = pc->skill_tree[classidx][i].idx;
bool satisfied = true;
if (sd->status.skill[idx].id > 0)
continue; //Skill already known.
if (!battle_config.skillfree) {
int j;
- for (j = 0; j < VECTOR_LENGTH(pc->skill_tree[c][i].need); j++) {
- struct skill_tree_requirement *req = &VECTOR_INDEX(pc->skill_tree[c][i].need, j);
+ for (j = 0; j < VECTOR_LENGTH(pc->skill_tree[classidx][i].need); j++) {
+ struct skill_tree_requirement *req = &VECTOR_INDEX(pc->skill_tree[classidx][i].need, j);
int level;
if (sd->status.skill[req->idx].id == 0
|| sd->status.skill[req->idx].flag == SKILL_FLAG_TEMPORARY
@@ -1564,8 +1714,8 @@ int pc_calc_skilltree(struct map_session_data *sd)
break;
}
}
- if (sd->status.job_level < pc->skill_tree[c][i].joblv) {
- int jobid = pc->mapid2jobid(sd->class_, sd->status.sex); // need to get its own skilltree
+ if (sd->status.job_level < (int)pc->skill_tree[classidx][i].joblv) {
+ int jobid = pc->mapid2jobid(sd->job, sd->status.sex); // need to get its own skilltree
if (jobid > -1) {
if (!pc->skill_tree[pc->class2idx(jobid)][i].inherited)
satisfied = false; // job level requirement wasn't satisfied
@@ -1590,22 +1740,36 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[idx].lv = 1; // need to manually specify a skill level
sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
}
- flag = 1; // skill list has changed, perform another pass
+ changed = true; // skill list has changed, perform another pass
}
}
- } while(flag);
+ } while (changed);
+
+ pc->calc_skilltree_bonus(sd, classidx);
+
+ return 0;
+}
+
+static void pc_calc_skilltree_bonus(struct map_session_data *sd, int classidx)
+{
+ int i;
+ int id = 0;
+
+ nullpo_retv(sd);
+ Assert_retv(classidx >= 0 && classidx < CLASS_COUNT);
//
- if( c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && sd->status.skill_point == 0 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
- {
- /* Taekwon Ranger Bonus Skill Tree
+ if (classidx > 0 && (sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON
+ && sd->status.base_level >= 90 && sd->status.skill_point == 0
+ && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0) {
+ /* Taekwon Ranker Bonus Skill Tree
============================================
- Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
- (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
- (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */
- for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) {
- int idx = pc->skill_tree[c][i].idx;
+ for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
+ int idx = pc->skill_tree[classidx][i].idx;
if( (skill->dbs->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
continue; //Do not include Quest/Wedding skills.
@@ -1616,15 +1780,13 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Remember original level
}
- sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_);
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class);
}
}
-
- return 0;
}
//Checks if you can learn a new skill after having leveled up a skill.
-void pc_check_skilltree(struct map_session_data *sd, int skill_id)
+static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
{
int i,id=0,flag;
int c=0;
@@ -1632,6 +1794,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if(battle_config.skillfree)
return; //Function serves no purpose if this is set
+ nullpo_retv(sd);
i = pc->calc_skilltree_normalize_job(sd);
c = pc->mapid2jobid(i, sd->status.sex);
if (c == -1) { //Unable to normalize job??
@@ -1667,8 +1830,8 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if (!satisfied)
continue;
- if (sd->status.job_level < pc->skill_tree[c][i].joblv) {
- int jobid = pc->mapid2jobid(sd->class_, sd->status.sex); // need to get its own skilltree
+ if (sd->status.job_level < (int)pc->skill_tree[c][i].joblv) {
+ int jobid = pc->mapid2jobid(sd->job, sd->status.sex); // need to get its own skilltree
if (jobid > -1) {
if (!pc->skill_tree[pc->class2idx(jobid)][i].inherited)
continue;
@@ -1694,10 +1857,11 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
// Make sure all the skills are in the correct condition
// before persisting to the backend.. [MouseJstr]
-int pc_clean_skilltree(struct map_session_data *sd)
+static int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
- for (i = 0; i < MAX_SKILL; i++){
+ nullpo_ret(sd);
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
@@ -1711,76 +1875,73 @@ int pc_clean_skilltree(struct map_session_data *sd)
return 0;
}
-int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
+static int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
{
int skill_point, novice_skills;
- int c = sd->class_;
+ uint16 job;
+ nullpo_ret(sd);
+ job = sd->job;
if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
- return c;
+ return job;
skill_point = pc->calc_skillpoint(sd);
- novice_skills = pc->max_level[pc->class2idx(JOB_NOVICE)][1] - 1;
+ novice_skills = pc->dbs->class_exp_table[pc->class2idx(JOB_NOVICE)][CLASS_EXP_TABLE_JOB]->max_level - 1;
sd->sktree.second = sd->sktree.third = 0;
- // limit 1st class and above to novice job levels
- if(skill_point < novice_skills) {
- c = MAPID_NOVICE;
- }
- // limit 2nd class and above to first class job levels (super novices are exempt)
- else if ((sd->class_&JOBL_2) && (sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
- {
+ if (skill_point < novice_skills && (sd->job & MAPID_BASEMASK) != MAPID_SUMMONER) {
+ // limit 1st class and above to novice job levels
+ job = MAPID_NOVICE;
+ } else if ((sd->job & JOBL_2) != 0 && (sd->job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ // limit 2nd class and above to first class job levels (super novices are exempt)
// regenerate change_level_2nd
- if (!sd->change_level_2nd)
- {
- if (sd->class_&JOBL_THIRD)
- {
+ if (sd->change_level_2nd == 0) {
+ if ((sd->job & JOBL_THIRD) != 0) {
// if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd
- if (!sd->change_level_3rd)
- sd->change_level_2nd = pc->max_level[pc->class2idx(pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1];
- else
+ if (sd->change_level_3rd == 0) {
+ sd->change_level_2nd = pc->dbs->class_exp_table[pc->class2idx(pc->mapid2jobid(sd->job & MAPID_UPPERMASK, sd->status.sex))][CLASS_EXP_TABLE_JOB]->max_level;
+ } else {
sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- (sd->change_level_3rd - 1)
- novice_skills;
- }
- else
- {
+ }
+ } else {
sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- novice_skills;
}
- pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
+ pc_setglobalreg(sd, script->add_variable("jobchange_level"), sd->change_level_2nd);
}
if (skill_point < novice_skills + (sd->change_level_2nd - 1)) {
- c &= MAPID_BASEMASK;
+ job &= MAPID_BASEMASK;
sd->sktree.second = ( novice_skills + (sd->change_level_2nd - 1) ) - skill_point;
- } else if(sd->class_&JOBL_THIRD) { // limit 3rd class to 2nd class/trans job levels
+ } else if ((sd->job & JOBL_THIRD) != 0) { // limit 3rd class to 2nd class/trans job levels
// regenerate change_level_3rd
- if (!sd->change_level_3rd) {
+ if (sd->change_level_3rd == 0) {
sd->change_level_3rd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- (sd->change_level_2nd - 1)
- novice_skills;
- pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
+ pc_setglobalreg(sd, script->add_variable("jobchange_level_3rd"), sd->change_level_3rd);
}
if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) {
- c &= MAPID_UPPERMASK;
+ job &= MAPID_UPPERMASK;
sd->sktree.third = (novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) - skill_point;
}
}
}
// restore non-limiting flags
- c |= sd->class_&(JOBL_UPPER|JOBL_BABY);
+ job |= sd->job & (JOBL_UPPER|JOBL_BABY);
- return c;
+ return job;
}
/*==========================================
@@ -1790,7 +1951,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
* 2: overweight 90%
* It's assumed that SC_WEIGHTOVER50 and SC_WEIGHTOVER90 are only started/stopped here.
*/
-int pc_updateweightstatus(struct map_session_data *sd)
+static int pc_updateweightstatus(struct map_session_data *sd)
{
int old_overweight;
int new_overweight;
@@ -1821,37 +1982,40 @@ int pc_updateweightstatus(struct map_session_data *sd)
return 0;
}
-int pc_disguise(struct map_session_data *sd, int class_) {
- if (class_ == -1 && sd->disguise == -1)
+static int pc_disguise(struct map_session_data *sd, int class)
+{
+ nullpo_ret(sd);
+ if (class == -1 && sd->disguise == -1)
return 0;
- if (class_ >= 0 && sd->disguise == class_)
+ if (class >= 0 && sd->disguise == class)
return 0;
if (pc_isinvisible(sd)) { //Character is invisible. Stealth class-change. [Skotlex]
- sd->disguise = class_; //viewdata is set on uncloaking.
+ sd->disguise = class; //viewdata is set on uncloaking.
return 2;
}
if (sd->bl.prev != NULL) {
- if( class_ == -1 && sd->disguise == sd->status.class_ ) {
+ if (class == -1 && sd->disguise == sd->status.class) {
clif->clearunit_single(-sd->bl.id,CLR_OUTSIGHT,sd->fd);
- } else if ( class_ != sd->status.class_ ) {
+ } else if (class != sd->status.class) {
pc_stop_walking(sd, STOPWALKING_FLAG_NONE);
clif->clearunit_area(&sd->bl, CLR_OUTSIGHT);
}
}
- if (class_ == -1) {
+ if (class == -1) {
sd->disguise = -1;
- class_ = sd->status.class_;
- } else
- sd->disguise = class_;
+ class = sd->status.class;
+ } else {
+ sd->disguise = class;
+ }
- status->set_viewdata(&sd->bl, class_);
+ status->set_viewdata(&sd->bl, class);
clif->changeoption(&sd->bl);
// We need to update the client so it knows that a costume is being used
if( sd->sc.option&OPTION_COSTUME ) {
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class);
clif->changelook(&sd->bl,LOOK_WEAPON,0);
clif->changelook(&sd->bl,LOOK_SHIELD,0);
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
@@ -1859,13 +2023,13 @@ int pc_disguise(struct map_session_data *sd, int class_) {
if (sd->bl.prev != NULL) {
clif->spawn(&sd->bl);
- if (class_ == sd->status.class_ && pc_iscarton(sd)) {
+ if (class == sd->status.class && pc_iscarton(sd)) {
//It seems the cart info is lost on undisguise.
- clif->cartlist(sd);
+ clif->cartList(sd);
clif->updatestatus(sd,SP_CARTINFO);
}
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
if (cd != NULL)
clif->dispchat(cd,0);
@@ -1874,13 +2038,15 @@ int pc_disguise(struct map_session_data *sd, int class_) {
return 1;
}
-int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id)
+static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, int card_id)
{
int i;
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv )
@@ -1910,13 +2076,15 @@ int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, s
return 1;
}
-int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id)
+static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, int card_id)
{
int i;
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
; // each autospell works independently
@@ -1949,9 +2117,11 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
* @retval 1 on success.
* @retval 0 on failure.
*/
-int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration)
+static int pc_bonus_addeff(struct s_addeffect *effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration)
{
int i;
+
+ nullpo_ret(effect);
if (!(flag&(ATF_SHORT|ATF_LONG)))
flag|=ATF_SHORT|ATF_LONG; //Default range: both
if (!(flag&(ATF_TARGET|ATF_SELF)))
@@ -1979,8 +2149,11 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16
return 1;
}
-int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target) {
+static int pc_bonus_addeff_onskill(struct s_addeffectonskill *effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target)
+{
int i;
+
+ nullpo_ret(effect);
for( i = 0; i < max && effect[i].skill; i++ ) {
if( effect[i].id == id && effect[i].skill == skill_id && effect[i].target == target ) {
effect[i].rate += rate;
@@ -1998,9 +2171,12 @@ int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_
return 1;
}
-int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race_mask, int rate) {
+static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, int id, bool is_group, int race_mask, int rate)
+{
int i;
+ nullpo_ret(drop);
+ Assert_ret(is_group || id > 0);
//Apply config rate adjustment settings.
if (rate >= 0) { //Absolute drop.
if (battle_config.item_rate_adddrop != 100)
@@ -2015,17 +2191,14 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
if (rate > -1)
rate = -1;
}
- for(i = 0; i < max && (drop[i].id || drop[i].group); i++) {
- if (((id && drop[i].id == id) || (group && drop[i].group == group))
- && race_mask != RCMASK_NONE
- ) {
+ for (i = 0; i < max && (drop[i].id != 0 || drop[i].is_group); i++) {
+ if (drop[i].id == id && race_mask != RCMASK_NONE) {
drop[i].race |= race_mask;
if (drop[i].rate > 0 && rate > 0) {
//Both are absolute rates.
if (drop[i].rate < rate)
drop[i].rate = rate;
- } else
- if(drop[i].rate < 0 && rate < 0) {
+ } else if (drop[i].rate < 0 && rate < 0) {
//Both are relative rates.
if (drop[i].rate > rate)
drop[i].rate = rate;
@@ -2039,15 +2212,18 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
return 0;
}
drop[i].id = id;
- drop[i].group = group;
+ drop[i].is_group = is_group;
drop[i].race |= race_mask;
drop[i].rate = rate;
return 1;
}
-int pc_addautobonus(struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) {
+static int pc_addautobonus(struct s_autobonus *bonus, char max, const char *bonus_script, short rate, unsigned int dur, short flag, const char *other_script, unsigned int pos, bool onskill)
+{
int i;
+ nullpo_ret(bonus);
+ nullpo_ret(bonus_script);
ARR_FIND(0, max, i, bonus[i].rate == 0);
if( i == max )
{
@@ -2080,10 +2256,11 @@ int pc_addautobonus(struct s_autobonus *bonus,char max,const char *bonus_script,
return 1;
}
-int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,char max,bool restore)
+static int pc_delautobonus(struct map_session_data *sd, struct s_autobonus *autobonus, char max, bool restore)
{
int i;
nullpo_ret(sd);
+ nullpo_ret(autobonus);
for( i = 0; i < max; i++ )
{
@@ -2117,7 +2294,7 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c
return 0;
}
-int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
+static int pc_exeautobonus(struct map_session_data *sd, struct s_autobonus *autobonus)
{
nullpo_ret(sd);
nullpo_ret(autobonus);
@@ -2137,7 +2314,8 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
return 0;
}
-int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) {
+static int pc_endautobonus(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
struct s_autobonus *autobonus = (struct s_autobonus *)data;
@@ -2150,11 +2328,12 @@ int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate, short flag)
+static int pc_bonus_addele(struct map_session_data *sd, unsigned char ele, short rate, short flag)
{
int i;
struct weapon_data* wd;
+ nullpo_ret(sd);
wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon);
ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0);
@@ -2184,10 +2363,11 @@ int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate,
return 0;
}
-int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate, short flag)
+static int pc_bonus_subele(struct map_session_data *sd, unsigned char ele, short rate, short flag)
{
int i;
+ nullpo_ret(sd);
ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0);
if (i == MAX_PC_BONUS)
@@ -2229,7 +2409,8 @@ int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate,
/*==========================================
* Add a bonus(type) to player sd
*------------------------------------------*/
-int pc_bonus(struct map_session_data *sd,int type,int val) {
+static int pc_bonus(struct map_session_data *sd, int type, int val)
+{
struct status_data *bst;
int bonus;
int i;
@@ -2345,7 +2526,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
}
switch (sd->state.lr_flag) {
case 2:
- switch (sd->status.weapon) {
+ switch (sd->weapontype) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
@@ -2412,7 +2593,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
case SP_ATTACKRANGE:
switch (sd->state.lr_flag) {
case 2:
- switch (sd->status.weapon) {
+ switch (sd->weapontype) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
@@ -2673,7 +2854,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG]
if(sd->state.lr_flag != 2) {
sd->special_state.intravision = 1;
- clif->status_change(&sd->bl, SI_CLAIRVOYANCE, 1, 0, 0, 0, 0);
+ clif->status_change(&sd->bl, status->get_sc_icon(SC_CLAIRVOYANCE), status->get_sc_relevant_bl_types(SC_CLAIRVOYANCE), 1, 0, 0, 0, 0);
}
break;
case SP_NO_KNOCKBACK:
@@ -2878,7 +3059,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
#endif
case SP_ADD_MONSTER_DROP_CHAINITEM:
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, map->race_id2mask(RC_ALL), 10000);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), val, true, map->race_id2mask(RC_ALL), 10000);
break;
case SP_ADDMAXWEIGHT:
if (sd->state.lr_flag != 2)
@@ -2895,7 +3076,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
/*==========================================
* Player bonus (type) with args type2 and val, called trough bonus2 (npc)
*------------------------------------------*/
-int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
+static int pc_bonus2(struct map_session_data *sd, int type, int type2, int val)
{
int i;
@@ -3453,7 +3634,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
break;
case SP_ADD_MONSTER_DROP_ITEM:
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, map->race_id2mask(RC_ALL), val);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, false, map->race_id2mask(RC_ALL), val);
break;
case SP_SP_LOSS_RATE:
if(sd->state.lr_flag != 2) {
@@ -3659,7 +3840,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
break;
}
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, race_mask, 10000);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, true, race_mask, 10000);
}
break;
#ifdef RENEWAL
@@ -3685,7 +3866,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
return 0;
}
-int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
+static int pc_bonus3(struct map_session_data *sd, int type, int type2, int type3, int val)
{
int i;
nullpo_ret(sd);
@@ -3699,12 +3880,12 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
break;
}
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, race_mask, val);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, false, race_mask, val);
}
break;
case SP_ADD_CLASS_DROP_ITEM:
if(sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, -type3, val);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, false, -type3, val);
break;
case SP_AUTOSPELL:
if(sd->state.lr_flag != 2)
@@ -3859,7 +4040,8 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
return 0;
}
-int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) {
+static int pc_bonus4(struct map_session_data *sd, int type, int type2, int type3, int type4, int val)
+{
int i;
nullpo_ret(sd);
@@ -3954,7 +4136,8 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
return 0;
}
-int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val) {
+static int pc_bonus5(struct map_session_data *sd, int type, int type2, int type3, int type4, int type5, int val)
+{
nullpo_ret(sd);
switch(type){
@@ -3988,9 +4171,9 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
* Grants a player a given skill.
* Flag values: @see enum pc_skill_flag
*------------------------------------------*/
-int pc_skill(struct map_session_data *sd, int id, int level, int flag)
+static int pc_skill(struct map_session_data *sd, int id, int level, int flag)
{
- uint16 index = 0;
+ int index = 0;
nullpo_ret(sd);
if (!(index = skill->get_index(id))) {
@@ -4023,7 +4206,7 @@ int pc_skill(struct map_session_data *sd, int id, int level, int flag)
if( sd->status.skill[index].id == id ) {
if( sd->status.skill[index].lv >= level )
return 0;
- if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
+ if (sd->status.skill[index].flag == SKILL_FLAG_PERMANENT) // Non-granted skill, store its level.
sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv;
} else {
sd->status.skill[index].id = id;
@@ -4067,13 +4250,13 @@ int pc_skill(struct map_session_data *sd, int id, int level, int flag)
* @param idx_equip The target equipment's inventory index.
* @retval true if the card can be inserted.
*/
-bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_equip)
+static bool pc_can_insert_card_into(struct map_session_data *sd, int idx_card, int idx_equip)
{
int i;
nullpo_ret(sd);
- if (idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL)
+ if (idx_equip < 0 || idx_equip >= sd->status.inventorySize || sd->inventory_data[idx_equip] == NULL)
return false; //Invalid item index.
if (sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1)
return false; // target item missing
@@ -4093,7 +4276,7 @@ bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_
ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0);
if (i == sd->inventory_data[idx_equip]->slot)
return false; // no free slots
- return true;
+ return true;
}
/**
@@ -4103,17 +4286,17 @@ bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_
* @param idx_card The card's inventory index.
* @retval true if the card can be inserted.
*/
-bool pc_can_insert_card(struct map_session_data* sd, int idx_card)
+static bool pc_can_insert_card(struct map_session_data *sd, int idx_card)
{
nullpo_ret(sd);
- if (idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL)
+ if (idx_card < 0 || idx_card >= sd->status.inventorySize || sd->inventory_data[idx_card] == NULL)
return false; //Invalid card index.
if (sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1)
return false; // target card missing
if (sd->inventory_data[idx_card]->type != IT_CARD)
return false; // must be a card
- return true;
+ return true;
}
/*==========================================
@@ -4122,7 +4305,7 @@ bool pc_can_insert_card(struct map_session_data* sd, int idx_card)
* 0 = fail
* 1 = success
*------------------------------------------*/
-int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
+static int pc_insert_card(struct map_session_data *sd, int idx_card, int idx_equip)
{
int nameid;
@@ -4164,11 +4347,9 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
/*==========================================
* Update buying value by skills
*------------------------------------------*/
-int pc_modifybuyvalue(struct map_session_data *sd, int orig_value)
+static int pc_modifybuyvalue(struct map_session_data *sd, int orig_value)
{
int skill_lv, rate1 = 0, rate2 = 0;
- if (orig_value <= 0)
- return 0;
if ((skill_lv=pc->checkskill(sd,MC_DISCOUNT)) > 0) // merchant discount
rate1 = 5+skill_lv*2-((skill_lv==10)? 1:0);
if ((skill_lv=pc->checkskill(sd,RG_COMPULSION)) > 0) // rogue discount
@@ -4177,25 +4358,25 @@ int pc_modifybuyvalue(struct map_session_data *sd, int orig_value)
rate1 = rate2;
if (rate1 != 0)
orig_value = apply_percentrate(orig_value, 100-rate1, 100);
- if (orig_value < 1)
- orig_value = 1;
+
+ if (orig_value < battle_config.min_item_buy_price)
+ orig_value = battle_config.min_item_buy_price;
return orig_value;
}
/*==========================================
* Update selling value by skills
*------------------------------------------*/
-int pc_modifysellvalue(struct map_session_data *sd, int orig_value)
+static int pc_modifysellvalue(struct map_session_data *sd, int orig_value)
{
int skill_lv, rate = 0;
- if (orig_value <= 0)
- return 0;
if ((skill_lv=pc->checkskill(sd,MC_OVERCHARGE)) > 0) //OverCharge
rate = 5+skill_lv*2-((skill_lv==10)? 1:0);
if (rate != 0)
orig_value = apply_percentrate(orig_value, 100+rate, 100);
- if (orig_value < 1)
- orig_value = 1;
+
+ if (orig_value < battle_config.min_item_sell_price)
+ orig_value = battle_config.min_item_sell_price;
return orig_value;
}
@@ -4203,9 +4384,8 @@ int pc_modifysellvalue(struct map_session_data *sd, int orig_value)
* Checking if we have enough place on inventory for new item
* Make sure to take 30k as limit (for client I guess)
*------------------------------------------*/
-int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
+static int pc_checkadditem(struct map_session_data *sd, int nameid, int amount)
{
- int i;
struct item_data* data;
nullpo_ret(sd);
@@ -4221,7 +4401,7 @@ int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
if( data->stack.inventory && amount > data->stack.amount )
return ADDITEM_OVERAMOUNT;
- for(i=0;i<MAX_INVENTORY;i++){
+ for(int i = 0; i < sd->status.inventorySize; i++) {
// FIXME: This does not consider the checked item's cards, thus could check a wrong slot for stackability.
if(sd->status.inventory[i].nameid==nameid){
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
@@ -4237,13 +4417,12 @@ int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
* Return number of available place in inventory
* Each non stackable item will reduce place by 1
*------------------------------------------*/
-int pc_inventoryblank(struct map_session_data *sd)
+static int pc_inventoryblank(struct map_session_data *sd)
{
- int i,b;
-
nullpo_ret(sd);
+ int b = 0;
- for(i=0,b=0;i<MAX_INVENTORY;i++){
+ for (int i = 0; i < sd->status.inventorySize; i++) {
if(sd->status.inventory[i].nameid==0)
b++;
}
@@ -4254,7 +4433,7 @@ int pc_inventoryblank(struct map_session_data *sd)
/*==========================================
* attempts to remove zeny from player (sd)
*------------------------------------------*/
-int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
+static int pc_payzeny(struct map_session_data *sd, int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
{
nullpo_retr(-1,sd);
@@ -4271,59 +4450,70 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
sd->status.zeny -= zeny;
clif->updatestatus(sd,SP_ZENY);
- if(!tsd) tsd = sd;
- logs->zeny(sd, type, tsd, -zeny);
- if( zeny > 0 && sd->state.showzeny ) {
- char output[255];
- sprintf(output, "Removed %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ if (zeny > 0) {
+ achievement->validate_zeny(sd, -zeny); // Achievements [Smokexyz/Hercules]
+ logs->zeny(sd, type, tsd ? tsd : sd, -zeny);
+
+ if (sd->state.showzeny) {
+ char output[255];
+ sprintf(output, msg_sd(sd, 885), zeny); // Removed %dz.
+ clif_disp_onlyself(sd, output);
+ }
}
return 0;
}
-/*==========================================
- * Cash Shop
- *------------------------------------------*/
-int pc_paycash(struct map_session_data *sd, int price, int points)
+/**
+ * Calculates leftover cashpoints and kafrapoints when buying an item from cashshop
+ *
+ * @param price Price of the item.
+ * @param points Provided kafra points.
+ *
+ * @return points Leftover kafra points.
+ */
+//Changed Kafrapoints calculation. [Normynator]
+static int pc_paycash(struct map_session_data *sd, int price, int points)
{
int cash;
- nullpo_retr(-1,sd);
+ int mempoints;
+ nullpo_retr(-1, sd);
- points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB
- if( price < 0 || points < 0 )
- {
+ points = cap_value(points, -MAX_ZENY, MAX_ZENY); //prevent command UB
+ if (price < 0 || points < 0) {
ShowError("pc_paycash: Paying negative points (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id);
return -2;
}
- if( points > price )
- {
+ if (points > price) {
ShowWarning("pc_paycash: More kafra points provided than needed (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id);
- points = price;
+ points = points - price;
+ mempoints = price;
+ cash = 0;
+ } else {
+ cash = price - points;
+ mempoints = points;
+ points = 0;
}
- cash = price-points;
-
- if( sd->cashPoints < cash || sd->kafraPoints < points )
- {
+ if (sd->cashPoints < cash || sd->kafraPoints < mempoints) {
ShowError("pc_paycash: Not enough points (cash=%d, kafra=%d) to cover the price (cash=%d, kafra=%d) (account_id=%d, char_id=%d).\n", sd->cashPoints, sd->kafraPoints, cash, points, sd->status.account_id, sd->status.char_id);
return -1;
}
- pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints-cash);
- pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints-points);
+ pc_setaccountreg(sd, script->add_variable("#CASHPOINTS"), sd->cashPoints - cash);
+ pc_setaccountreg(sd, script->add_variable("#KAFRAPOINTS"), sd->kafraPoints - mempoints);
- if( battle_config.cashshop_show_points )
- {
+ if (battle_config.cashshop_show_points) {
char output[128];
sprintf(output, msg_sd(sd,504), points, cash, sd->kafraPoints, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
- return cash+points;
+
+ return points;
}
-int pc_getcash(struct map_session_data *sd, int cash, int points)
+static int pc_getcash(struct map_session_data *sd, int cash, int points)
{
char output[128];
nullpo_retr(-1,sd);
@@ -4338,12 +4528,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
cash = MAX_ZENY-sd->cashPoints;
}
- pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints+cash);
+ pc_setaccountreg(sd, script->add_variable("#CASHPOINTS"), sd->cashPoints+cash);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,505), cash, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return cash;
}
@@ -4361,12 +4551,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
points = MAX_ZENY-sd->kafraPoints;
}
- pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints+points);
+ pc_setaccountreg(sd, script->add_variable("#KAFRAPOINTS"), sd->kafraPoints+points);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,506), points, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return points;
}
@@ -4382,7 +4572,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
* Attempts to give zeny to player (sd)
* tsd (optional) from who for log (if null take sd)
*------------------------------------------*/
-int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
+static int pc_getzeny(struct map_session_data *sd, int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
{
nullpo_retr(-1,sd);
@@ -4399,12 +4589,15 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
sd->status.zeny += zeny;
clif->updatestatus(sd,SP_ZENY);
- if(!tsd) tsd = sd;
- logs->zeny(sd, type, tsd, zeny);
- if( zeny > 0 && sd->state.showzeny ) {
- char output[255];
- sprintf(output, "Gained %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ if (zeny > 0) {
+ achievement->validate_zeny(sd, zeny); // Achievements [Smokexyz/Hercules]
+ logs->zeny(sd, type, tsd ? tsd : sd, zeny);
+
+ if (sd->state.showzeny) {
+ char output[255];
+ sprintf(output, msg_sd(sd, 886), zeny); // Gained %dz.
+ clif_disp_onlyself(sd, output);
+ }
}
return 0;
@@ -4421,12 +4614,13 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
* @return the inventory index of the first instance of the requested item.
* @retval INDEX_NOT_FOUND if the item wasn't found.
*/
-int pc_search_inventory(struct map_session_data *sd, int item_id) {
+static int pc_search_inventory(struct map_session_data *sd, int item_id)
+{
int i;
nullpo_retr(INDEX_NOT_FOUND, sd);
- ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0) );
- return ( i < MAX_INVENTORY ) ? i : INDEX_NOT_FOUND;
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0));
+ return (i < sd->status.inventorySize) ? i : INDEX_NOT_FOUND;
}
/*==========================================
@@ -4441,7 +4635,7 @@ int pc_search_inventory(struct map_session_data *sd, int item_id) {
* 6 = ?
* 7 = stack limitation
*------------------------------------------*/
-int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
+static int pc_additem(struct map_session_data *sd, const struct item *item_data, int amount, e_log_pick_type log_type)
{
struct item_data *data;
int i;
@@ -4488,11 +4682,11 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
}
}
- i = MAX_INVENTORY;
+ i = sd->status.inventorySize;
// Stackable | Non Rental
if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) {
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
if( sd->status.inventory[i].nameid == item_data->nameid &&
sd->status.inventory[i].bound == item_data->bound &&
sd->status.inventory[i].expire_time == 0 &&
@@ -4507,7 +4701,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
}
}
- if ( i >= MAX_INVENTORY ) {
+ if (i >= sd->status.inventorySize) {
i = pc->search_inventory(sd,0);
if (i == INDEX_NOT_FOUND)
return 4;
@@ -4522,6 +4716,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
sd->status.inventory[i].amount = amount;
sd->inventory_data[i] = data;
clif->additem(sd,i,amount,0);
+
}
if( ( !itemdb->isstackable2(data) || data->flag.force_serial || data->type == IT_CASH) && !item_data->unique_id )
@@ -4529,22 +4724,34 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]);
+ achievement->validate_item_get(sd, sd->status.inventory[i].nameid, sd->status.inventory[i].amount); // Achievements [Smokexyz/Hercules]
+
sd->weight += w;
clif->updatestatus(sd,SP_WEIGHT);
+
+ // auto-favorite
+ if (data->flag.auto_favorite > 0) {
+ sd->status.inventory[i].favorite = 1;
+ clif->favorite_item(sd, i);
+ }
+
//Auto-equip
if(data->flag.autoequip)
pc->equipitem(sd, i, data->equip);
/* rental item check */
- if( item_data->expire_time ) {
- if( time(NULL) > item_data->expire_time ) {
- pc->rental_expire(sd,i);
+ if (item_data->expire_time > 0) {
+ if (time(NULL) > item_data->expire_time) {
+ pc->rental_expire(sd, i);
} else {
- int seconds = (int)( item_data->expire_time - time(NULL) );
+ int seconds = (int)(item_data->expire_time - time(NULL));
clif->rental_time(sd->fd, sd->status.inventory[i].nameid, seconds);
pc->inventory_rental_add(sd, seconds);
+ if (data->rental_start_script != NULL)
+ script->run_item_rental_start_script(sd, data, 0);
}
}
+ quest->questinfo_refresh(sd);
return 0;
}
@@ -4560,9 +4767,10 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
* 0 = success
* 1 = invalid itemid or negative amount
*------------------------------------------*/
-int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type)
+static int pc_delitem(struct map_session_data *sd, int n, int amount, int type, short reason, e_log_pick_type log_type)
{
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < sd->status.inventorySize);
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL)
return 1;
@@ -4571,16 +4779,26 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas
sd->status.inventory[n].amount -= amount;
sd->weight -= sd->inventory_data[n]->weight*amount ;
+
+ // It's here because the data would most likely get zeroed in following if [Hemagx]
+ struct item_data *itd = sd->inventory_data[n];
+ bool is_rental = (sd->status.inventory[n].expire_time > 0) ? true : false;
+
if( sd->status.inventory[n].amount <= 0 ){
if(sd->status.inventory[n].equip)
pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0]));
sd->inventory_data[n] = NULL;
}
+
+ if (is_rental && itd->rental_end_script != NULL)
+ script->run_item_rental_end_script(sd, itd, 0);
+
if(!(type&1))
clif->delitem(sd,n,amount,reason);
if(!(type&2))
clif->updatestatus(sd,SP_WEIGHT);
+ quest->questinfo_refresh(sd);
return 0;
}
@@ -4591,11 +4809,11 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas
* 0 = fail
* 1 = success
*------------------------------------------*/
-int pc_dropitem(struct map_session_data *sd,int n,int amount)
+static int pc_dropitem(struct map_session_data *sd, int n, int amount)
{
nullpo_retr(1, sd);
- if(n < 0 || n >= MAX_INVENTORY)
+ if(n < 0 || n >= sd->status.inventorySize)
return 0;
if(amount <= 0)
@@ -4604,23 +4822,23 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
if(sd->status.inventory[n].nameid <= 0 ||
sd->status.inventory[n].amount <= 0 ||
sd->status.inventory[n].amount < amount ||
- sd->state.trading || sd->state.vending ||
+ sd->state.trading || sd->state.vending || sd->state.prevend ||
!sd->inventory_data[n] //pc->delitem would fail on this case.
)
return 0;
if( map->list[sd->bl.m].flag.nodrop ) {
- clif->message (sd->fd, msg_sd(sd,271));
- return 0; //Can't drop items in nodrop mapflag maps.
+ clif->message (sd->fd, msg_sd(sd,271)); // You can't drop items in this map
+ return 0;
}
if( !pc->candrop(sd,&sd->status.inventory[n]) )
{
- clif->message (sd->fd, msg_sd(sd,263));
+ clif->message (sd->fd, msg_sd(sd,263)); // This item cannot be dropped.
return 0;
}
- if (!map->addflooritem(&sd->bl, &sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2))
+ if (!map->addflooritem(&sd->bl, &sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2, false))
return 0;
pc->delitem(sd, n, amount, 1, DELITEM_NORMAL, LOG_TYPE_PICKDROP_PLAYER);
@@ -4634,7 +4852,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
* 0 = fail
* 1 = success
*------------------------------------------*/
-int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
+static int pc_takeitem(struct map_session_data *sd, struct flooritem_data *fitem)
{
int flag=0;
int64 tick = timer->gettick();
@@ -4700,12 +4918,13 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
* 0 = no
* 1 = yes
*------------------------------------------*/
-int pc_isUseitem(struct map_session_data *sd,int n)
+static int pc_isUseitem(struct map_session_data *sd, int n)
{
struct item_data *item;
int nameid;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < sd->status.inventorySize);
item = sd->inventory_data[n];
nameid = sd->status.inventory[n].nameid;
@@ -4719,33 +4938,73 @@ int pc_isUseitem(struct map_session_data *sd,int n)
return 0;
if ((item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override)) {
- clif->msgtable(sd, MSG_ITEM_NEED_STANDING);
+ clif->msgtable(sd, MSG_CANT_USE_WHEN_SITDOWN);
//clif->messagecolor_self(sd->fd, COLOR_WHITE, msg_txt(1474));
return 0; // You cannot use this item while sitting.
}
- if (sd->state.storage_flag != STORAGE_FLAG_CLOSED && item->type != IT_CASH) {
- clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1475));
- return 0; // You cannot use this item while storage is open.
- }
-
switch( nameid ) { // TODO: Is there no better way to handle this, other than hardcoding item IDs?
case ITEMID_ANODYNE:
- if( map_flag_gvg2(sd->bl.m) )
- return 0;
- /* Fall through */
- case ITEMID_ALOEBERA:
- if( pc_issit(sd) )
+ if (map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
+
+ case ITEMID_GIANT_FLY_WING: {
+ struct party_data *p;
+
+ if (!sd->status.party_id) {
+#if PACKETVER >= 20061030
+ clif->msgtable(sd, MSG_CANNOT_PARTYCALL);
+#endif
+ break;
+ }
+
+ if ((p = party->search(sd->status.party_id)) != NULL) {
+ int i;
+ int16 m;
+
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd);
+
+ if (i == MAX_PARTY || !p->party.member[i].leader) {
+#if PACKETVER >= 20061030
+ clif->msgtable(sd, MSG_CANNOT_PARTYCALL);
+#endif
+ break;
+ }
+
+ m = sd->bl.m;
+
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd && p->data[i].sd != sd && p->data[i].sd->bl.m == m);
+
+ if (i == MAX_PARTY || pc_isdead(p->data[i].sd)) {
+#if PACKETVER >= 20061030
+ clif->msgtable(sd, MSG_NO_PARTYMEM_ON_THISMAP);
+#endif
+ break;
+ }
+ }
+ }
+ FALLTHROUGH
case ITEMID_WING_OF_FLY:
- case ITEMID_GIANT_FLY_WING:
- if( map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) {
- clif->skill_mapinfomessage(sd,0);
+ case ITEMID_N_FLY_WING:
+ case ITEMID_C_WING_OF_FLY:
+ if (map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 0);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 49));
+#endif
return 0;
}
/* Fall through */
case ITEMID_WING_OF_BUTTERFLY:
+ case ITEMID_N_BUTTERFLY_WING:
case ITEMID_DUN_TELE_SCROLL1:
case ITEMID_DUN_TELE_SCROLL2:
case ITEMID_WOB_RUNE: // Yellow Butterfly Wing
@@ -4757,34 +5016,27 @@ int pc_isUseitem(struct map_session_data *sd,int n)
clif->message(sd->fd, msg_sd(sd,863)); // "Duel: Can't use this item in duel."
return 0;
}
- if( nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn )
+ if (nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 0);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 49));
+#endif
return 0;
+ }
break;
case ITEMID_BRANCH_OF_DEAD_TREE:
case ITEMID_RED_POUCH_OF_SURPRISE:
case ITEMID_BLOODY_DEAD_BRANCH:
case ITEMID_PORING_BOX:
- if( map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m) )
- return 0;
- break;
- case ITEMID_BUBBLE_GUM:
- case ITEMID_COMP_BUBBLE_GUM:
- if( sd->sc.data[SC_CASH_RECEIVEITEM] )
- return 0;
- break;
- case ITEMID_BATTLE_MANUAL:
- case ITEMID_COMP_BATTLE_MANUAL:
- case ITEMID_THICK_MANUAL50:
- case ITEMID_NOBLE_NAMEPLATE:
- case ITEMID_BATTLE_MANUAL25:
- case ITEMID_BATTLE_MANUAL100:
- case ITEMID_BATTLE_MANUAL_X3:
- if( sd->sc.data[SC_CASH_PLUSEXP] )
- return 0;
- break;
- case ITEMID_JOB_MANUAL50:
- if( sd->sc.data[SC_CASH_PLUSONLYJOBEXP] )
+ if (map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
// Mercenary Items
@@ -4804,28 +5056,23 @@ int pc_isUseitem(struct map_session_data *sd,int n)
break;
case ITEMID_NEURALIZER:
- if( !map->list[sd->bl.m].flag.reset )
+ if (!map->list[sd->bl.m].flag.reset) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
}
if( nameid >= ITEMID_BOW_MERCENARY_SCROLL1 && nameid <= ITEMID_SPEARMERCENARY_SCROLL10 && sd->md != NULL ) // Mercenary Scrolls
return 0;
- /**
- * Only Rune Knights may use runes
- **/
- if( itemdb_is_rune(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
- return 0;
- /**
- * Only GCross may use poisons
- **/
- else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS )
- return 0;
-
if( item->package || item->group ) {
if (pc_is90overweight(sd)) {
- clif->msgtable(sd, MSG_ITEM_CANT_OBTAIN_WEIGHT);
+ clif->msgtable(sd, MSG_CANT_GET_ITEM_BECAUSE_WEIGHT);
return 0;
}
if (!pc->inventoryblank(sd)) {
@@ -4838,42 +5085,62 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
//Required level check
- if (item->elv && sd->status.base_level < (unsigned int)item->elv) {
- clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL);
+ if (item->elv && sd->status.base_level < item->elv) {
+#if PACKETVER >= 20100525
+ clif->msgtable(sd, MSG_CANNOT_USE_ITEM_LEVEL);
+#endif
return 0;
}
- if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) {
- clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL);
+ if (item->elvmax && sd->status.base_level > item->elvmax) {
+#if PACKETVER >= 20100525
+ clif->msgtable(sd, MSG_CANNOT_USE_ITEM_LEVEL);
+#endif
return 0;
}
//Not equipable by class. [Skotlex]
- if (!(
- (1ULL<<(sd->class_&MAPID_BASEMASK)) &
- (item->class_base[(sd->class_&JOBL_2_1) ? 1 : ((sd->class_&JOBL_2_2) ? 2 : 0)])
- ))
+ if (((1ULL << (sd->job & MAPID_BASEMASK)) & (item->class_base[(sd->job & JOBL_2_1) ? 1 : ((sd->job & JOBL_2_2) ? 2 : 0)])) == 0)
return 0;
//Not usable by upper class. [Haru]
while( 1 ) {
// Normal classes (no upper, no baby, no third classes)
- if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
+ if ((item->class_upper & ITEMUPPER_NORMAL) != 0) {
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) == 0)
+ break;
+ }
+ if ((item->class_upper & ITEMUPPER_UPPER) != 0) {
#ifdef RENEWAL
- // Upper classes (no third classes)
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD) ) break;
+ // Upper classes (no third classes)
+ if ((sd->job & JOBL_UPPER) != 0 && (sd->job&JOBL_THIRD) == 0)
+ break;
#else
- //pre-re has no use for the extra, so we maintain the previous for backwards compatibility
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
+ //pre-re has no use for the extra, so we maintain the previous for backwards compatibility
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD)) != 0)
+ break;
#endif
+ }
// Baby classes (no third classes)
- if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD) ) break;
+ if ((item->class_upper & ITEMUPPER_BABY) != 0) {
+ if ((sd->job & JOBL_BABY) != 0 && (sd->job&JOBL_THIRD) == 0)
+ break;
+ }
// Third classes (no upper, no baby classes)
- if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)) ) break;
+ if ((item->class_upper & ITEMUPPER_THIRD) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & (JOBL_UPPER|JOBL_BABY)) == 0)
+ break;
+ }
// Upper third classes
- if( item->class_upper&ITEMUPPER_THURDUPPER && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER ) break;
+ if ((item->class_upper & ITEMUPPER_THIRDUPPER) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & JOBL_UPPER) != 0)
+ break;
+ }
// Baby third classes
- if( item->class_upper&ITEMUPPER_THIRDBABY && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY ) break;
+ if ((item->class_upper & ITEMUPPER_THIRDBABY) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & JOBL_BABY) != 0)
+ break;
+ }
return 0;
}
@@ -4886,24 +5153,35 @@ int pc_isUseitem(struct map_session_data *sd,int n)
* 0 = fail
* 1 = success
*------------------------------------------*/
-int pc_useitem(struct map_session_data *sd,int n) {
+static int pc_useitem(struct map_session_data *sd, int n)
+{
int64 tick = timer->gettick();
int amount, nameid, i;
bool removeItem = false;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < sd->status.inventorySize);
- if( sd->npc_id || sd->state.workinprogress&1 ){
- /* TODO: add to clif->messages enum */
-#ifdef RENEWAL
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
+ if (sd->npc_id || sd->state.workinprogress & 1) {
+#if PACKETVER >= 20110308
+ clif->msgtable(sd, MSG_BUSY);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_WHITE, msg_sd(sd, 48));
#endif
return 0;
}
+ if (battle_config.storage_use_item == 1 && sd->state.storage_flag != STORAGE_FLAG_CLOSED) {
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 1475));
+ return 0; // You cannot use this item while storage is open.
+ }
+
if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 )
return 0;
+ if (sd->block_action.useitem) // *pcblock script command
+ return 0;
+
if( !pc->isUseitem(sd,n) )
return 0;
@@ -4927,18 +5205,17 @@ int pc_useitem(struct map_session_data *sd,int n) {
sd->sc.data[SC_DEEP_SLEEP] ||
sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
sd->sc.data[SC_COLD] ||
+ sd->sc.data[SC_SUHIDE] ||
pc_ismuted(&sd->sc, MANNER_NOITEM)
))
return 0;
- //Prevent mass item usage. [Skotlex]
- if( DIFF_TICK(sd->canuseitem_tick, tick) > 0 ||
- (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0)
- )
+ // Prevent mass item usage. [Skotlex]
+ if (DIFF_TICK(sd->canuseitem_tick, tick) > 0)
return 0;
/* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */
- if( sd->inventory_data[n]->flag.delay_consume && nameid != ITEMID_REINS_OF_MOUNT ) {
+ if (sd->inventory_data[n]->flag.delay_consume && nameid != ITEMID_BOARDING_HALTER) {
if( sd->sc.data[SC_ALL_RIDING] )
return 0;
else if( pc_issit(sd) )
@@ -4951,21 +5228,27 @@ int pc_useitem(struct map_session_data *sd,int n) {
if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status->check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
return 0;
- if( sd->inventory_data[n]->delay > 0 ) {
- ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid );
- if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
- ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
- if( i < MAX_ITEMDELAYS ) {
- if( sd->item_delay[i].nameid ) {// found
- if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
- int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000);
- clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, e_tick + 1); // [%d] seconds left until you can use
+ if (sd->inventory_data[n]->delay > 0) {
+ ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid);
+ if (i == MAX_ITEMDELAYS) /* item not found. try first empty now */
+ ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == 0);
+ if (i < MAX_ITEMDELAYS) {
+ if (sd->item_delay[i].nameid != 0) {// found
+ if (DIFF_TICK(sd->item_delay[i].tick, tick) > 0) {
+ int delay_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick) / 1000);
+#if PACKETVER >= 20101123
+ clif->msgtable_num(sd, MSG_ITEM_REUSE_LIMIT_SECOND, delay_tick + 1); // [%d] seconds left until you can use
+#else
+ char delay_msg[100];
+ sprintf(delay_msg, msg_sd(sd, 26), delay_tick + 1);
+ clif->messagecolor_self(sd->fd, COLOR_YELLOW, delay_msg); // [%d] seconds left until you can use
+#endif
return 0; // Delay has not expired yet
}
} else {// not yet used item (all slots are initially empty)
sd->item_delay[i].nameid = nameid;
}
- if (!(nameid == ITEMID_REINS_OF_MOUNT && pc_hasmount(sd)))
+ if (!(nameid == ITEMID_BOARDING_HALTER && pc_hasmount(sd)))
sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
} else {// should not happen
ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id);
@@ -4982,9 +5265,21 @@ int pc_useitem(struct map_session_data *sd,int n) {
/* on restricted maps the item is consumed but the effect is not used */
for(i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++) {
if( map->list[sd->bl.m].zone->disabled_items[i] == nameid ) {
- clif->msgtable(sd, MSG_ITEM_CANT_USE_AREA); // This item cannot be used within this area
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50));
+#endif
if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) {
clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true);
+
+ // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, there is a chance to don't consume the scroll. [Kenpachi]
+ if ((nameid == ITEMID_EARTH_SCROLL_1_3 || nameid == ITEMID_EARTH_SCROLL_1_5)
+ && sd->sc.count > 0 && sd->sc.data[SC_EARTHSCROLL] != NULL
+ && rnd() % 100 > sd->sc.data[SC_EARTHSCROLL]->val2) {
+ return 0;
+ }
+
pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME);
}
return 0;
@@ -5013,34 +5308,58 @@ int pc_useitem(struct map_session_data *sd,int n) {
}
}
- if(sd->status.inventory[n].card[0]==CARD0_CREATE &&
- pc->famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
- {
+ if (sd->status.inventory[n].card[0] == CARD0_CREATE
+ && pc->fame_rank(MakeDWord(sd->status.inventory[n].card[2], sd->status.inventory[n].card[3]), RANKTYPE_ALCHEMIST) > 0) {
script->potion_flag = 2; // Famous player's potions have 50% more efficiency
if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE)
script->potion_flag = 3; //Even more effective potions.
}
- //Update item use time.
+ // Update item use time.
sd->canuseitem_tick = tick + battle_config.item_use_interval;
- if( itemdb_iscashfood(nameid) )
- sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval;
script->run_use_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
script->potion_flag = 0;
+ // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, there is a chance to don't consume the scroll. [Kenpachi]
+ if ((nameid == ITEMID_EARTH_SCROLL_1_3 || nameid == ITEMID_EARTH_SCROLL_1_5) && sd->sc.count > 0
+ && sd->sc.data[SC_EARTHSCROLL] != NULL && rnd() % 100 > sd->sc.data[SC_EARTHSCROLL]->val2) {
+ removeItem = false;
+ }
+
if (removeItem)
pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME);
return 1;
}
+/**
+ * Unsets a character's auto-cast related data.
+ *
+ * @param sd The character's session data.
+ * @return 0 if parameter sd is NULL, otherwise 1.
+ */
+static int pc_autocast_clear(struct map_session_data *sd)
+{
+ nullpo_ret(sd);
+
+ sd->autocast.type = AUTOCAST_NONE;
+ sd->autocast.skill_id = 0;
+ sd->autocast.skill_lv = 0;
+ sd->autocast.itemskill_conditions_checked = false;
+ sd->autocast.itemskill_check_conditions = false;
+ sd->autocast.itemskill_instant_cast = false;
+ sd->autocast.itemskill_cast_on_self = false;
+
+ return 1;
+}
+
/*==========================================
* Add item on cart for given index.
* Return:
* 0 = success
* 1 = fail
*------------------------------------------*/
-int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
+static int pc_cart_additem(struct map_session_data *sd, struct item *item_data, int amount, e_log_pick_type log_type)
{
struct item_data *data;
int i,w;
@@ -5059,7 +5378,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
if (!itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd))) {
// Check item trade restrictions
- clif->message (sd->fd, msg_sd(sd,264));
+ clif->message (sd->fd, msg_sd(sd,264)); // This item cannot be stored.
return 1;/* TODO: there is no official response to this? */
}
@@ -5109,9 +5428,11 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
* 0 = success
* 1 = fail
*------------------------------------------*/
-int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) {
+static int pc_cart_delitem(struct map_session_data *sd, int n, int amount, int type, e_log_pick_type log_type)
+{
struct item_data * data;
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < MAX_CART);
if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb->exists(sd->status.cart[n].nameid)) )
return 1;
@@ -5138,19 +5459,19 @@ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_
* 0 = fail
* 1 = succes
*------------------------------------------*/
-int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
+static int pc_putitemtocart(struct map_session_data *sd, int idx, int amount)
{
struct item *item_data;
int flag;
nullpo_ret(sd);
- if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex]
+ if (idx < 0 || idx >= sd->status.inventorySize) //Invalid index check [Skotlex]
return 1;
item_data = &sd->status.inventory[idx];
- if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending )
+ if (item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending || sd->state.prevend)
return 1;
if( (flag = pc->cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 )
@@ -5165,11 +5486,12 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
* -1 = itemid not found or no amount found
* x = remaining itemid on cart after get
*------------------------------------------*/
-int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
+static int pc_cartitem_amount(struct map_session_data *sd, int idx, int amount)
{
struct item* item_data;
nullpo_retr(-1, sd);
+ Assert_retr(-1, idx >= 0 && idx < MAX_CART);
item_data = &sd->status.cart[idx];
if( item_data->nameid == 0 || item_data->amount == 0 )
@@ -5184,7 +5506,7 @@ int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
* 0 = player not found or (FIXME) succes (from pc->cart_delitem)
* 1 = failure
*------------------------------------------*/
-int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
+static int pc_getitemfromcart(struct map_session_data *sd, int idx, int amount)
{
struct item *item_data;
int flag;
@@ -5196,22 +5518,25 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
item_data=&sd->status.cart[idx];
- if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending )
+ if (item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending || sd->state.prevend)
return 1;
- if((flag = pc->additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0)
+ if ((flag = pc->additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0)
return pc->cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE);
return flag;
}
-void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
+
+static void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type)
+{
int i;
+ nullpo_retv(sd);
switch( type ) {
/* both restricted to inventory */
case IBT_PARTY:
case IBT_CHARACTER:
- for( i = 0; i < MAX_INVENTORY; i++ ){
+ for (i = 0; i < sd->status.inventorySize; i++ ) {
if( sd->status.inventory[i].bound == type ) {
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_SKILLUSE, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag?
}
@@ -5223,7 +5548,7 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
case IBT_GUILD: {
struct guild_storage *gstor = idb_get(gstorage->db,sd->status.guild_id);
- for( i = 0; i < MAX_INVENTORY; i++ ){
+ for (i = 0; i < sd->status.inventorySize; i++ ) {
if(sd->status.inventory[i].bound == type) {
if( gstor )
gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount);
@@ -5239,7 +5564,7 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
/*==========================================
* Display item stolen msg to player sd
*------------------------------------------*/
-int pc_show_steal(struct block_list *bl,va_list ap)
+static int pc_show_steal(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL, *tsd = NULL;
int itemid;
@@ -5256,9 +5581,9 @@ int pc_show_steal(struct block_list *bl,va_list ap)
nullpo_ret(sd);
if((item=itemdb->exists(itemid))==NULL)
- sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid);
+ sprintf(output, msg_sd(sd, 887), sd->status.name, itemid); // %s stole an Unknown Item (id: %i).
else
- sprintf(output,"%s stole %s.",sd->status.name,item->jname);
+ sprintf(output, msg_sd(sd, 888), sd->status.name, item->jname); // %s stole %s.
clif->message(tsd->fd, output);
return 0;
@@ -5269,7 +5594,7 @@ int pc_show_steal(struct block_list *bl,va_list ap)
* 0 = fail
* 1 = succes
*------------------------------------------*/
-int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skill_lv)
+static int pc_steal_item(struct map_session_data *sd, struct block_list *bl, uint16 skill_lv)
{
int i,itemid,flag;
int rate;
@@ -5304,15 +5629,17 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
// Try dropping one item, in the order from first to last possible slot.
// Droprate is affected by the skill success rate.
- for (i = 0; i < MAX_STEAL_DROP; i++) {
+ for (i = 0; i < MAX_MOB_DROP; i++) {
if (md->db->dropitem[i].nameid == 0)
continue;
if ((data = itemdb->exists(md->db->dropitem[i].nameid)) == NULL)
continue;
+ if (data->type == IT_CARD)
+ continue;
if (rnd() % 10000 < apply_percentrate(md->db->dropitem[i].p, rate, 100))
break;
}
- if (i == MAX_STEAL_DROP)
+ if (i == MAX_MOB_DROP)
return 0;
itemid = md->db->dropitem[i].nameid;
@@ -5336,26 +5663,21 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
//Logs items, Stolen from mobs [Lupus]
logs->pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item, data);
- //A Rare Steal Global Announce by Lupus
- if(md->db->dropitem[i].p<=battle_config.rare_drop_announce) {
- char message[128];
- sprintf (message, msg_txt(542), sd->status.name, md->db->jname, data->jname, (float)md->db->dropitem[i].p / 100);
- //MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
- }
return 1;
}
/**
* Steals zeny from a monster through the RG_STEALCOIN skill.
*
- * @param sd Source character
- * @param target Target monster
+ * @param sd Source character
+ * @param target Target monster
+ * @param skill_lv Skill Level
*
* @return Amount of stolen zeny (0 in case of failure)
- **/
-int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
- int rate, skill_lv;
+ */
+static int pc_steal_coin(struct map_session_data *sd, struct block_list *target, uint16 skill_lv)
+{
+ int rate;
struct mob_data *md = BL_CAST(BL_MOB, target);
if (sd == NULL || md == NULL)
@@ -5367,7 +5689,6 @@ int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
if (mob_is_treasure(md))
return 0;
- skill_lv = pc->checkskill(sd, RG_STEALCOIN);
rate = skill_lv * 10 + (sd->status.base_level - md->level) * 2 + sd->battle_status.dex / 2 + sd->battle_status.luk / 2;
if(rnd()%1000 < rate) {
int amount = md->level * skill_lv / 10 + md->level * 8 + rnd()%(md->level * 2 + 1); // mob_lv * skill_lv / 10 + random [mob_lv*8; mob_lv*10]
@@ -5379,233 +5700,295 @@ int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
return 0;
}
-/*==========================================
- * Set's a player position.
- * Return values:
- * 0 - Success.
- * 1 - Invalid map index.
- * 2 - Map not in this map-server, and failed to locate alternate map-server.
- *------------------------------------------*/
-int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype) {
- int16 m;
+/**
+ * Sets a character's position.
+ *
+ * @param sd The related character.
+ * @param map_index The target map's index.
+ * @param x The target x-coordinate.
+ * @param y The target y-coordinate.
+ * @param clrtype The unit clear type, which should be used.
+ * @retval 0 Success.
+ * @retval 1 Invalid map index.
+ * @retval 2 Map not in this map-server, and failed to locate alternative map-server.
+ * @retval 3 No character data. (Parameter sd is a NULL pointer.)
+ * @retval 4 Character is jailed.
+ *
+ **/
+static int pc_setpos(struct map_session_data *sd, unsigned short map_index, int x, int y, enum clr_type clrtype)
+{
+ nullpo_retr(3, sd);
- nullpo_ret(sd);
+ int map_id = map->mapindex2mapid(map_index);
- if( !map_index || !mapindex_id2name(map_index) || ( m = map->mapindex2mapid(map_index) ) == -1 ) {
- ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", map_index);
+ if (map_index == 0 || !mapindex_id2name(map_index) || map_id == INDEX_NOT_FOUND) {
+ ShowDebug("pc_setpos: Passed mapindex %d is invalid!\n", map_index);
return 1;
}
- if( pc_isdead(sd) ) { //Revive dead people before warping them
+ if (pc_isdead(sd)) { // Revive dead character before warping.
pc->setstand(sd);
- pc->setrestartvalue(sd,1);
+ pc->setrestartvalue(sd, 1);
}
- if( map->list[m].flag.src4instance ) {
- struct party_data *p;
+ if (map->list[map_id].flag.src4instance != 0) {
bool stop = false;
- int i = 0, j = 0;
- if( sd->instances ) {
- for( i = 0; i < sd->instances; i++ ) {
- if( sd->instance[i] >= 0 ) {
- ARR_FIND(0, instance->list[sd->instance[i]].num_map, j, map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[sd->instance[i]].map[j]].custom_name);
- if( j != instance->list[sd->instance[i]].num_map )
+ if (sd->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < sd->instances; i++) {
+ if (sd->instance[i] >= 0) {
+ ARR_FIND(0, instance->list[sd->instance[i]].num_map, j,
+ map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == map_id
+ && !map->list[instance->list[sd->instance[i]].map[j]].custom_name);
+
+ if (j != instance->list[sd->instance[i]].num_map)
break;
}
}
- if( i != sd->instances ) {
- m = instance->list[sd->instance[i]].map[j];
- map_index = map_id2index(m);
+
+ if (i != sd->instances) {
+ map_id = instance->list[sd->instance[i]].map[j];
+ map_index = map_id2index(map_id);
stop = true;
}
}
- if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances ) {
- for( i = 0; i < p->instances; i++ ) {
- if( p->instance[i] >= 0 ) {
- ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[p->instance[i]].map[j]].custom_name);
- if( j != instance->list[p->instance[i]].num_map )
+
+ struct party_data *p = party->search(sd->status.party_id);
+
+ if (!stop && sd->status.party_id != 0 && p != NULL && p->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < p->instances; i++) {
+ if (p->instance[i] >= 0) {
+ ARR_FIND(0, instance->list[p->instance[i]].num_map, j,
+ map->list[instance->list[p->instance[i]].map[j]].instance_src_map == map_id
+ && !map->list[instance->list[p->instance[i]].map[j]].custom_name);
+
+ if (j != instance->list[p->instance[i]].num_map)
break;
}
}
- if( i != p->instances ) {
- m = instance->list[p->instance[i]].map[j];
- map_index = map_id2index(m);
+
+ if (i != p->instances) {
+ map_id = instance->list[p->instance[i]].map[j];
+ map_index = map_id2index(map_id);
stop = true;
}
}
- if ( !stop && sd->status.guild_id && sd->guild && sd->guild->instances ) {
- for( i = 0; i < sd->guild->instances; i++ ) {
- if( sd->guild->instance[i] >= 0 ) {
- ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j, map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[sd->guild->instance[i]].map[j]].custom_name);
- if( j != instance->list[sd->guild->instance[i]].num_map )
+
+ if (!stop && sd->status.guild_id != 0 && sd->guild != NULL && sd->guild->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < sd->guild->instances; i++) {
+ if (sd->guild->instance[i] >= 0) {
+ ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j,
+ map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == map_id
+ && !map->list[instance->list[sd->guild->instance[i]].map[j]].custom_name);
+
+ if (j != instance->list[sd->guild->instance[i]].num_map)
break;
}
}
- if( i != sd->guild->instances ) {
- m = instance->list[sd->guild->instance[i]].map[j];
- map_index = map_id2index(m);
- //stop = true; Uncomment if adding new checks
+
+ if (i != sd->guild->instances) {
+ map_id = instance->list[sd->guild->instance[i]].map[j];
+ map_index = map_id2index(map_id);
+ //stop = true; Uncomment when adding new checks.
}
}
- /* we hit a instance, if empty we populate the spawn data */
- if( map->list[m].instance_id >= 0 && instance->list[map->list[m].instance_id].respawn.map == 0 &&
- instance->list[map->list[m].instance_id].respawn.x == 0 &&
- instance->list[map->list[m].instance_id].respawn.y == 0) {
- instance->list[map->list[m].instance_id].respawn.map = map_index;
- instance->list[map->list[m].instance_id].respawn.x = x;
- instance->list[map->list[m].instance_id].respawn.y = y;
+ // We hit an instance. If empty we populate the spawn data.
+ if (map->list[map_id].instance_id >= 0 && instance->list[map->list[map_id].instance_id].respawn.map == 0
+ && instance->list[map->list[map_id].instance_id].respawn.x == 0
+ && instance->list[map->list[map_id].instance_id].respawn.y == 0) {
+ instance->list[map->list[map_id].instance_id].respawn.map = map_index;
+ instance->list[map->list[map_id].instance_id].respawn.x = x;
+ instance->list[map->list[map_id].instance_id].respawn.y = y;
}
}
- sd->state.changemap = (sd->mapindex != map_index);
+ sd->state.changemap = (sd->mapindex != map_index) ? 1 : 0;
sd->state.warping = 1;
sd->state.workinprogress = 0;
- if( sd->state.changemap ) { // Misc map-changing settings
- int i;
+
+ if (sd->state.changemap != 0) { // Miscellaneous map-changing settings.
sd->state.pmap = sd->bl.m;
- for (i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
+ for (int i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
struct script_queue *queue = script->queue(VECTOR_INDEX(sd->script_queues, i));
- if (queue && queue->event_mapchange[0] != '\0') {
- pc->setregstr(sd, script->add_str("@Queue_Destination_Map$"), map->list[m].name);
+
+ if (queue != NULL && queue->event_mapchange[0] != '\0') {
+ pc->setregstr(sd, script->add_variable("@Queue_Destination_Map$"), map->list[map_id].name);
npc->event(sd, queue->event_mapchange, 0);
}
}
- if( map->list[m].cell == (struct mapcell *)0xdeadbeaf )
- map->cellfromcache(&map->list[m]);
- if (sd->sc.count) { // Cancel some map related stuff.
- if (sd->sc.data[SC_JAILED])
- return 1; //You may not get out!
+ if (map->list[map_id].cell == (struct mapcell *)0xdeadbeaf)
+ map->cellfromcache(&map->list[map_id]);
+
+ if (sd->sc.count != 0) { // Cancel some map related stuff.
+ if (sd->sc.data[SC_JAILED] != NULL)
+ return 4; // You may not get out!
+
status_change_end(&sd->bl, SC_CASH_BOSS_ALARM, INVALID_TIMER);
status_change_end(&sd->bl, SC_WARM, INVALID_TIMER);
status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
- status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);//Will later check if this is needed. [Rytech]
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER); // Will later check if this is needed. [Rytech]
status_change_end(&sd->bl, SC_NEUTRALBARRIER, INVALID_TIMER);
status_change_end(&sd->bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
status_change_end(&sd->bl, SC_STEALTHFIELD, INVALID_TIMER);
- if (sd->sc.data[SC_KNOWLEDGE]) {
+
+ if (sd->sc.data[SC_KNOWLEDGE] != NULL) {
struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
+
if (sce->timer != INVALID_TIMER)
timer->delete(sce->timer, status->change_timer);
- sce->timer = timer->add(timer->gettick() + skill->get_time(SG_KNOWLEDGE, sce->val1), status->change_timer, sd->bl.id, SC_KNOWLEDGE);
+
+ sce->timer = timer->add(timer->gettick() + skill->get_time(SG_KNOWLEDGE, sce->val1),
+ status->change_timer, sd->bl.id, SC_KNOWLEDGE);
}
+
status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER);
status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
- for( i = 0; i < EQI_MAX; i++ ) {
- if( sd->equip_index[ i ] >= 0 )
- if( !pc->isequip( sd , sd->equip_index[ i ] ) )
- pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
+
+ for (int i = 0; i < EQI_MAX; i++) {
+ if (sd->equip_index[i] >= 0 && pc->isequip(sd , sd->equip_index[i]) == 0)
+ pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
}
- if (battle_config.clear_unit_onwarp&BL_PC)
+
+ if ((battle_config.clear_unit_onwarp & BL_PC) != 0)
skill->clear_unitgroup(&sd->bl);
- party->send_dot_remove(sd); //minimap dot fix [Kevin]
+
+ party->send_dot_remove(sd); // Minimap dot fix. [Kevin]
guild->send_dot_remove(sd);
bg->send_dot_remove(sd);
- if (sd->regen.state.gc)
+
+ if (sd->regen.state.gc != 0)
sd->regen.state.gc = 0;
- // make sure vending is allowed here
- if (sd->state.vending && map->list[m].flag.novending) {
- clif->message (sd->fd, msg_sd(sd,276)); // "You can't open a shop on this map"
+
+ // Make sure that vending is allowed here.
+ if (sd->state.vending != 0 && map->list[map_id].flag.novending != 0) {
+ clif->message(sd->fd, msg_sd(sd, 276)); // "You can't open a shop on this map"
vending->close(sd);
}
- if (map->list[sd->bl.m].channel) {
- channel->leave(map->list[sd->bl.m].channel,sd);
- }
+ if (sd->mapindex != 0 && map->list[sd->bl.m].channel != NULL) // Only if the character is already on a map.
+ channel->leave(map->list[sd->bl.m].channel, sd);
}
- if( m < 0 ) {
+ if (map_id < 0) {
uint32 ip;
uint16 port;
- //if can't find any map-servers, just abort setting position.
- if(!sd->mapindex || map->mapname2ipport(map_index,&ip,&port))
+
+ // If can't find any map-servers, just abort setting position.
+ if (sd->mapindex == 0 || map->mapname2ipport(map_index, &ip, &port) != 0)
return 2;
- if (sd->npc_id)
+ if (sd->npc_id != 0)
npc->event_dequeue(sd);
+
npc->script_event(sd, NPCE_LOGOUT);
- //remove from map, THEN change x/y coordinates
- unit->remove_map_pc(sd,clrtype);
+
+ // Remove from map, THEN change x/y coordinates.
+ unit->remove_map_pc(sd, clrtype);
+
+ if (battle_config.player_warp_keep_direction == 0)
+ sd->ud.dir = 0; /// Make character facing north.
+
sd->mapindex = map_index;
- sd->bl.x=x;
- sd->bl.y=y;
+ sd->bl.x= x;
+ sd->bl.y= y;
pc->clean_skilltree(sd);
- chrif->save(sd,2);
- chrif->changemapserver(sd, ip, (short)port);
+ chrif->save(sd, 2);
+ chrif->changemapserver(sd, ip, port);
- //Free session data from this map server [Kevin]
+ // Free session data from this map server. [Kevin]
unit->free_pc(sd);
return 0;
}
- if( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) {
- ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(map_index),x,y);
- x = y = 0; // make it random
+ if (x < 0 || x >= map->list[map_id].xs || y < 0 || y >= map->list[map_id].ys) { // Invalid coordinates. Randomize them.
+ ShowError("pc_setpos: Attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id,
+ mapindex_id2name(map_index), x, y);
+ x = 0;
+ y = 0;
}
- if( x == 0 && y == 0 ) {// pick a random walkable cell
+ if (x == 0 && y == 0) { // Pick a random walkable cell.
do {
- x=rnd()%(map->list[m].xs-2)+1;
- y=rnd()%(map->list[m].ys-2)+1;
- } while(map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS));
+ x = rnd() % (map->list[map_id].xs - 2) + 1;
+ y = rnd() % (map->list[map_id].ys - 2) + 1;
+ } while(map->getcell(map_id, &sd->bl, x, y, CELL_CHKNOPASS) != 0);
}
- if (sd->state.vending && map->getcell(m, &sd->bl, x, y, CELL_CHKNOVENDING)) {
- clif->message (sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell."
+ if (sd->state.vending != 0 && map->getcell(map_id, &sd->bl, x, y, CELL_CHKNOVENDING) != 0) {
+ clif->message(sd->fd, msg_sd(sd, 204)); // "You can't open a shop on this cell."
vending->close(sd);
}
- if(sd->bl.prev != NULL){
- unit->remove_map_pc(sd,clrtype);
- clif->changemap(sd,m,x,y); // [MouseJstr]
- } else if(sd->state.active)
- //Tag player for rewarping after map-loading is done. [Skotlex]
- sd->state.rewarp = 1;
+ if (battle_config.player_warp_keep_direction == 0)
+ sd->ud.dir = 0; // Make character facing north.
+
+ if (sd->bl.prev != NULL) {
+ unit->remove_map_pc(sd, clrtype);
+ clif->changemap(sd, map_id, x, y); // [MouseJstr]
+ } else if (sd->state.active != 0) {
+ sd->state.rewarp = 1; // Tag character for re-warping after map-loading is done. [Skotlex]
+ }
sd->mapindex = map_index;
- sd->bl.m = m;
- sd->bl.x = sd->ud.to_x = x;
- sd->bl.y = sd->ud.to_y = y;
+ sd->bl.m = map_id;
+ sd->bl.x = x;
+ sd->bl.y = y;
+ sd->ud.to_x = x;
+ sd->ud.to_y = y;
- if( sd->status.guild_id > 0 && map->list[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris]
+ if (sd->status.guild_id > 0 && map->list[map_id].flag.gvg_castle != 0) { // Double regeneration in guild castle. [Valaris]
struct guild_castle *gc = guild->mapindex2gc(sd->mapindex);
- if(gc && gc->guild_id == sd->status.guild_id)
+
+ if (gc != NULL && gc->guild_id == sd->status.guild_id)
sd->regen.state.gc = 1;
}
- if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) {
- sd->pd->bl.m = m;
- sd->pd->bl.x = sd->pd->ud.to_x = x;
- sd->pd->bl.y = sd->pd->ud.to_y = y;
+ if (sd->status.pet_id > 0 && sd->pd != NULL && sd->pd->pet.intimate > PET_INTIMACY_NONE) {
+ sd->pd->bl.m = map_id;
+ sd->pd->bl.x = x;
+ sd->pd->bl.y = y;
+ sd->pd->ud.to_x = x;
+ sd->pd->ud.to_y = y;
sd->pd->ud.dir = sd->ud.dir;
}
- if( homun_alive(sd->hd) ) {
- sd->hd->bl.m = m;
- sd->hd->bl.x = sd->hd->ud.to_x = x;
- sd->hd->bl.y = sd->hd->ud.to_y = y;
+ if (homun_alive(sd->hd)) {
+ sd->hd->bl.m = map_id;
+ sd->hd->bl.x = x;
+ sd->hd->bl.y = y;
+ sd->hd->ud.to_x = x;
+ sd->hd->ud.to_y = y;
sd->hd->ud.dir = sd->ud.dir;
}
- if( sd->md ) {
- sd->md->bl.m = m;
- sd->md->bl.x = sd->md->ud.to_x = x;
- sd->md->bl.y = sd->md->ud.to_y = y;
+ if (sd->md != NULL) {
+ sd->md->bl.m = map_id;
+ sd->md->bl.x = x;
+ sd->md->bl.y = y;
+ sd->md->ud.to_x = x;
+ sd->md->ud.to_y = y;
sd->md->ud.dir = sd->ud.dir;
}
- /* given autotrades have no clients you have to trigger this manually otherwise they get stuck in memory limbo bugreport:7495 */
- if( sd->state.autotrade )
- clif->pLoadEndAck(0,sd);
+ // Given autotrades have no clients. You have to trigger this manually, otherwise they get stuck in memory limbo. (bugreport:7495)
+ if (sd->state.autotrade != 0)
+ clif->pLoadEndAck(0, sd);
return 0;
}
@@ -5617,7 +6000,8 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
* 0 = fail or FIXME success (from pc->setpos)
* x(1|2) = fail
*------------------------------------------*/
-int pc_randomwarp(struct map_session_data *sd, clr_type type) {
+static int pc_randomwarp(struct map_session_data *sd, enum clr_type type)
+{
int x,y,i=0;
int16 m;
@@ -5643,7 +6027,8 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type) {
* Records a memo point at sd's current position
* pos - entry to replace, (-1: shift oldest entry out)
*------------------------------------------*/
-int pc_memo(struct map_session_data* sd, int pos) {
+static int pc_memo(struct map_session_data *sd, int pos)
+{
int skill_lv;
nullpo_ret(sd);
@@ -5693,8 +6078,9 @@ int pc_memo(struct map_session_data* sd, int pos) {
/*==========================================
* Return player sd skill_lv learned for given skill
*------------------------------------------*/
-int pc_checkskill(struct map_session_data *sd,uint16 skill_id) {
- uint16 index = 0;
+static int pc_checkskill(struct map_session_data *sd, uint16 skill_id)
+{
+ int index = 0;
if(sd == NULL) return 0;
if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) {
struct guild *g;
@@ -5712,9 +6098,11 @@ int pc_checkskill(struct map_session_data *sd,uint16 skill_id) {
return 0;
}
-int pc_checkskill2(struct map_session_data *sd,uint16 index) {
- if(sd == NULL) return 0;
- if(index >= ARRAYLENGTH(sd->status.skill) ) {
+static int pc_checkskill2(struct map_session_data *sd, uint16 index)
+{
+ if (sd == NULL)
+ return 0;
+ if (index >= MAX_SKILL_DB) {
ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id);
return 0;
}
@@ -5737,7 +6125,7 @@ int pc_checkskill2(struct map_session_data *sd,uint16 index) {
* Return
* 0 - No status found or all done
*------------------------------------------*/
-int pc_checkallowskill(struct map_session_data *sd)
+static int pc_checkallowskill(struct map_session_data *sd)
{
const enum sc_type scw_list[] = {
SC_TWOHANDQUICKEN,
@@ -5777,11 +6165,11 @@ int pc_checkallowskill(struct map_session_data *sd)
status_change_end(&sd->bl, scw_list[i], INVALID_TIMER);
}
- if(sd->sc.data[SC_STRUP] && sd->status.weapon)
+ if(sd->sc.data[SC_STRUP] && sd->weapontype != W_FIST)
// Spurt requires bare hands (feet, in fact xD)
status_change_end(&sd->bl, SC_STRUP, INVALID_TIMER);
- if(sd->status.shield <= 0) { // Skills requiring a shield
+ if (!sd->has_shield) { // Skills requiring a shield
for (i = 0; i < ARRAYLENGTH(scs_list); i++)
if(sd->sc.data[scs_list[i]])
status_change_end(&sd->bl, scs_list[i], INVALID_TIMER);
@@ -5795,7 +6183,7 @@ int pc_checkallowskill(struct map_session_data *sd)
* -1 : mean nothing equiped
* idx : (this index could be used in inventory to found item_data)
*------------------------------------------*/
-int pc_checkequip(struct map_session_data *sd,int pos)
+static int pc_checkequip(struct map_session_data *sd, int pos)
{
int i;
@@ -5813,10 +6201,9 @@ int pc_checkequip(struct map_session_data *sd,int pos)
* Convert's from the client's lame Job ID system
* to the map server's 'makes sense' system. [Skotlex]
*------------------------------------------*/
-int pc_jobid2mapid(unsigned short b_class)
+static int pc_jobid2mapid(int class)
{
- switch(b_class)
- {
+ switch (class) {
//Novice And 1-1 Jobs
case JOB_NOVICE: return MAPID_NOVICE;
case JOB_SWORDMAN: return MAPID_SWORDMAN;
@@ -5832,6 +6219,7 @@ int pc_jobid2mapid(unsigned short b_class)
case JOB_XMAS: return MAPID_XMAS;
case JOB_SUMMER: return MAPID_SUMMER;
case JOB_GANGSI: return MAPID_GANGSI;
+ case JOB_SUMMONER: return MAPID_SUMMONER;
//2-1 Jobs
case JOB_SUPER_NOVICE: return MAPID_SUPER_NOVICE;
case JOB_KNIGHT: return MAPID_KNIGHT;
@@ -5955,10 +6343,9 @@ int pc_jobid2mapid(unsigned short b_class)
}
//Reverts the map-style class id to the client-style one.
-int pc_mapid2jobid(unsigned short class_, int sex)
+static int pc_mapid2jobid(unsigned int class, int sex)
{
- switch(class_)
- {
+ switch (class) {
//Novice And 1-1 Jobs
case MAPID_NOVICE: return JOB_NOVICE;
case MAPID_SWORDMAN: return JOB_SWORDMAN;
@@ -5974,6 +6361,7 @@ int pc_mapid2jobid(unsigned short class_, int sex)
case MAPID_XMAS: return JOB_XMAS;
case MAPID_SUMMER: return JOB_SUMMER;
case MAPID_GANGSI: return JOB_GANGSI;
+ case MAPID_SUMMONER: return JOB_SUMMONER;
//2-1 Jobs
case MAPID_SUPER_NOVICE: return JOB_SUPER_NOVICE;
case MAPID_KNIGHT: return JOB_KNIGHT;
@@ -6092,9 +6480,9 @@ int pc_mapid2jobid(unsigned short class_, int sex)
/*====================================================
* This function return the name of the job (by [Yor])
*----------------------------------------------------*/
-const char* job_name(int class_)
+static const char *job_name(int class)
{
- switch (class_) {
+ switch (class) {
case JOB_NOVICE: // 550
case JOB_SWORDMAN: // 551
case JOB_MAGE: // 552
@@ -6102,7 +6490,7 @@ const char* job_name(int class_)
case JOB_ACOLYTE: // 554
case JOB_MERCHANT: // 555
case JOB_THIEF: // 556
- return msg_txt(550 - JOB_NOVICE+class_);
+ return msg_txt(550 - JOB_NOVICE + class);
case JOB_KNIGHT: // 557
case JOB_PRIEST: // 558
@@ -6110,7 +6498,7 @@ const char* job_name(int class_)
case JOB_BLACKSMITH: // 560
case JOB_HUNTER: // 561
case JOB_ASSASSIN: // 562
- return msg_txt(557 - JOB_KNIGHT+class_);
+ return msg_txt(557 - JOB_KNIGHT + class);
case JOB_KNIGHT2:
return msg_txt(557);
@@ -6122,7 +6510,7 @@ const char* job_name(int class_)
case JOB_ALCHEMIST: // 567
case JOB_BARD: // 568
case JOB_DANCER: // 569
- return msg_txt(563 - JOB_CRUSADER+class_);
+ return msg_txt(563 - JOB_CRUSADER + class);
case JOB_CRUSADER2:
return msg_txt(563);
@@ -6132,7 +6520,7 @@ const char* job_name(int class_)
case JOB_GUNSLINGER: // 572
case JOB_NINJA: // 573
case JOB_XMAS: // 574
- return msg_txt(570 - JOB_WEDDING+class_);
+ return msg_txt(570 - JOB_WEDDING + class);
case JOB_SUMMER:
return msg_txt(621);
@@ -6144,7 +6532,7 @@ const char* job_name(int class_)
case JOB_ACOLYTE_HIGH: // 579
case JOB_MERCHANT_HIGH: // 580
case JOB_THIEF_HIGH: // 581
- return msg_txt(575 - JOB_NOVICE_HIGH+class_);
+ return msg_txt(575 - JOB_NOVICE_HIGH + class);
case JOB_LORD_KNIGHT: // 582
case JOB_HIGH_PRIEST: // 583
@@ -6152,7 +6540,7 @@ const char* job_name(int class_)
case JOB_WHITESMITH: // 585
case JOB_SNIPER: // 586
case JOB_ASSASSIN_CROSS: // 587
- return msg_txt(582 - JOB_LORD_KNIGHT+class_);
+ return msg_txt(582 - JOB_LORD_KNIGHT + class);
case JOB_LORD_KNIGHT2:
return msg_txt(582);
@@ -6164,7 +6552,7 @@ const char* job_name(int class_)
case JOB_CREATOR: // 592
case JOB_CLOWN: // 593
case JOB_GYPSY: // 594
- return msg_txt(588 - JOB_PALADIN + class_);
+ return msg_txt(588 - JOB_PALADIN + class);
case JOB_PALADIN2:
return msg_txt(588);
@@ -6176,7 +6564,7 @@ const char* job_name(int class_)
case JOB_BABY_ACOLYTE: // 599
case JOB_BABY_MERCHANT: // 600
case JOB_BABY_THIEF: // 601
- return msg_txt(595 - JOB_BABY + class_);
+ return msg_txt(595 - JOB_BABY + class);
case JOB_BABY_KNIGHT: // 602
case JOB_BABY_PRIEST: // 603
@@ -6184,7 +6572,7 @@ const char* job_name(int class_)
case JOB_BABY_BLACKSMITH: // 605
case JOB_BABY_HUNTER: // 606
case JOB_BABY_ASSASSIN: // 607
- return msg_txt(602 - JOB_BABY_KNIGHT + class_);
+ return msg_txt(602 - JOB_BABY_KNIGHT + class);
case JOB_BABY_KNIGHT2:
return msg_txt(602);
@@ -6196,7 +6584,7 @@ const char* job_name(int class_)
case JOB_BABY_ALCHEMIST: // 612
case JOB_BABY_BARD: // 613
case JOB_BABY_DANCER: // 614
- return msg_txt(608 - JOB_BABY_CRUSADER + class_);
+ return msg_txt(608 - JOB_BABY_CRUSADER + class);
case JOB_BABY_CRUSADER2:
return msg_txt(608);
@@ -6215,7 +6603,7 @@ const char* job_name(int class_)
case JOB_GANGSI: // 622
case JOB_DEATH_KNIGHT: // 623
case JOB_DARK_COLLECTOR: // 624
- return msg_txt(622 - JOB_GANGSI+class_);
+ return msg_txt(622 - JOB_GANGSI + class);
case JOB_RUNE_KNIGHT: // 625
case JOB_WARLOCK: // 626
@@ -6223,7 +6611,7 @@ const char* job_name(int class_)
case JOB_ARCH_BISHOP: // 628
case JOB_MECHANIC: // 629
case JOB_GUILLOTINE_CROSS: // 630
- return msg_txt(625 - JOB_RUNE_KNIGHT+class_);
+ return msg_txt(625 - JOB_RUNE_KNIGHT + class);
case JOB_RUNE_KNIGHT_T: // 656
case JOB_WARLOCK_T: // 657
@@ -6231,7 +6619,7 @@ const char* job_name(int class_)
case JOB_ARCH_BISHOP_T: // 659
case JOB_MECHANIC_T: // 660
case JOB_GUILLOTINE_CROSS_T: // 661
- return msg_txt(656 - JOB_RUNE_KNIGHT_T+class_);
+ return msg_txt(656 - JOB_RUNE_KNIGHT_T + class);
case JOB_ROYAL_GUARD: // 631
case JOB_SORCERER: // 632
@@ -6240,7 +6628,7 @@ const char* job_name(int class_)
case JOB_SURA: // 635
case JOB_GENETIC: // 636
case JOB_SHADOW_CHASER: // 637
- return msg_txt(631 - JOB_ROYAL_GUARD+class_);
+ return msg_txt(631 - JOB_ROYAL_GUARD + class);
case JOB_ROYAL_GUARD_T: // 662
case JOB_SORCERER_T: // 663
@@ -6249,7 +6637,7 @@ const char* job_name(int class_)
case JOB_SURA_T: // 666
case JOB_GENETIC_T: // 667
case JOB_SHADOW_CHASER_T: // 668
- return msg_txt(662 - JOB_ROYAL_GUARD_T+class_);
+ return msg_txt(662 - JOB_ROYAL_GUARD_T + class);
case JOB_RUNE_KNIGHT2:
return msg_txt(625);
@@ -6288,7 +6676,7 @@ const char* job_name(int class_)
case JOB_BABY_SURA: // 648
case JOB_BABY_GENETIC: // 649
case JOB_BABY_CHASER: // 650
- return msg_txt(638 - JOB_BABY_RUNE+class_);
+ return msg_txt(638 - JOB_BABY_RUNE + class);
case JOB_BABY_RUNE2:
return msg_txt(638);
@@ -6304,21 +6692,25 @@ const char* job_name(int class_)
case JOB_SUPER_NOVICE_E: // 651
case JOB_SUPER_BABY_E: // 652
- return msg_txt(651 - JOB_SUPER_NOVICE_E+class_);
+ return msg_txt(651 - JOB_SUPER_NOVICE_E + class);
case JOB_KAGEROU: // 653
case JOB_OBORO: // 654
- return msg_txt(653 - JOB_KAGEROU+class_);
+ return msg_txt(653 - JOB_KAGEROU + class);
case JOB_REBELLION:
return msg_txt(655);
+ case JOB_SUMMONER:
+ return msg_txt(669);
+
default:
return msg_txt(620); // "Unknown Job"
}
}
-int pc_check_job_name(const char *name) {
+static int pc_check_job_name(const char *name)
+{
int i, len;
struct {
const char *name;
@@ -6438,8 +6830,10 @@ int pc_check_job_name(const char *name) {
{ "Kagerou", JOB_KAGEROU },
{ "Oboro", JOB_OBORO },
{ "Rebellion", JOB_REBELLION },
+ { "Summoner", JOB_SUMMONER },
};
+ nullpo_retr(-1, name);
len = ARRAYLENGTH(names);
ARR_FIND(0, len, i, strcmpi(names[i].name, name) == 0);
@@ -6450,7 +6844,8 @@ int pc_check_job_name(const char *name) {
return names[i].id;
}
-int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_follow_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
struct block_list *tbl;
@@ -6488,7 +6883,7 @@ int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pc_stop_following (struct map_session_data *sd)
+static int pc_stop_following(struct map_session_data *sd)
{
nullpo_ret(sd);
@@ -6504,8 +6899,10 @@ int pc_stop_following (struct map_session_data *sd)
return 0;
}
-int pc_follow(struct map_session_data *sd,int target_id) {
+static int pc_follow(struct map_session_data *sd, int target_id)
+{
struct block_list *bl = map->id2bl(target_id);
+ nullpo_retr(1, sd);
if (bl == NULL /*|| bl->type != BL_PC*/)
return 1;
if (sd->followtimer != INVALID_TIMER)
@@ -6517,21 +6914,24 @@ int pc_follow(struct map_session_data *sd,int target_id) {
return 0;
}
-int pc_checkbaselevelup(struct map_session_data *sd) {
- unsigned int next = pc->nextbaseexp(sd);
+static int pc_checkbaselevelup(struct map_session_data *sd)
+{
+ uint64 next = pc->nextbaseexp(sd);
+ nullpo_ret(sd);
if (!next || sd->status.base_exp < next)
return 0;
do {
+ int status_points = 0;
sd->status.base_exp -= next;
//Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex]
if(!battle_config.multi_level_up && sd->status.base_exp > next-1)
sd->status.base_exp = next-1;
- next = pc->gets_status_point(sd->status.base_level);
- sd->status.base_level ++;
- sd->status.status_point += next;
+ status_points = pc->gets_status_point(sd->status.base_level);
+ sd->status.base_level++;
+ sd->status.status_point += status_points;
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
@@ -6545,41 +6945,55 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
status_calc_pc(sd,SCO_FORCE);
status_percent_heal(&sd->bl,100,100);
- if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
- sc_start(NULL,&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1));
- sc_start(NULL,&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1));
- sc_start(NULL,&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1));
- sc_start(NULL,&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1));
- sc_start(NULL,&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1));
- if (sd->state.snovice_dead_flag)
- sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
- } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
- sc_start(NULL,&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000);
- sc_start(NULL,&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000);
- }
+ pc->checkbaselevelup_sc(sd);
clif->misceffect(&sd->bl,0);
npc->script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
- if(sd->status.party_id)
+ if (sd->status.party_id)
party->send_levelup(sd);
pc->baselevelchanged(sd);
+
+ quest->questinfo_refresh(sd);
+
+ achievement->validate_stats(sd, SP_BASELEVEL, sd->status.base_level);
+
return 1;
}
-void pc_baselevelchanged(struct map_session_data *sd) {
+static void pc_checkbaselevelup_sc(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
+ sc_start(NULL, &sd->bl, status->skill2sc(PR_KYRIE), 100, 1, skill->get_time(PR_KYRIE, 1));
+ sc_start(NULL, &sd->bl, status->skill2sc(PR_IMPOSITIO), 100, 1, skill->get_time(PR_IMPOSITIO, 1));
+ sc_start(NULL, &sd->bl, status->skill2sc(PR_MAGNIFICAT), 100, 1, skill->get_time(PR_MAGNIFICAT, 1));
+ sc_start(NULL, &sd->bl, status->skill2sc(PR_GLORIA), 100, 1, skill->get_time(PR_GLORIA, 1));
+ sc_start(NULL, &sd->bl, status->skill2sc(PR_SUFFRAGIUM), 100, 1, skill->get_time(PR_SUFFRAGIUM, 1));
+ if (sd->state.snovice_dead_flag)
+ sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
+ } else if ((sd->job & MAPID_BASEMASK) == MAPID_TAEKWON) {
+ sc_start(NULL, &sd->bl, status->skill2sc(AL_INCAGI), 100, 10, 600000);
+ sc_start(NULL, &sd->bl, status->skill2sc(AL_BLESSING), 100, 10, 600000);
+ }
+}
+
+static void pc_baselevelchanged(struct map_session_data *sd)
+{
int i;
+ nullpo_retv(sd);
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
- if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax )
+ if (sd->inventory_data[sd->equip_index[i]]->elvmax != 0 && sd->status.base_level > sd->inventory_data[ sd->equip_index[i] ]->elvmax)
pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
}
}
-int pc_checkjoblevelup(struct map_session_data *sd)
+static int pc_checkjoblevelup(struct map_session_data *sd)
{
- unsigned int next = pc->nextjobexp(sd);
+ uint64 next = pc->nextjobexp(sd);
nullpo_ret(sd);
if(!next || sd->status.job_exp < next)
@@ -6591,8 +7005,8 @@ int pc_checkjoblevelup(struct map_session_data *sd)
if(!battle_config.multi_level_up && sd->status.job_exp > next-1)
sd->status.job_exp = next-1;
- sd->status.job_level ++;
- sd->status.skill_point ++;
+ sd->status.job_level++;
+ sd->status.skill_point++;
} while ((next=pc->nextjobexp(sd)) > 0 && sd->status.job_exp >= next);
@@ -6603,44 +7017,88 @@ int pc_checkjoblevelup(struct map_session_data *sd)
status_calc_pc(sd,SCO_FORCE);
clif->misceffect(&sd->bl,1);
if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd))
- clif->status_change(&sd->bl,SI_DEVIL1, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
+ clif->status_change(&sd->bl, status->get_sc_icon(SC_DEVIL1), status->get_sc_relevant_bl_types(SC_DEVIL1), 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
npc->script_event(sd, NPCE_JOBLVUP);
+
+ quest->questinfo_refresh(sd);
+
+ achievement->validate_stats(sd, SP_BASELEVEL, sd->status.job_level);
+
return 1;
}
/**
* 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);
+static void pc_calcexp(struct map_session_data *sd, uint64 *base_exp, uint64 *job_exp, struct block_list *src)
+{
+ int buff_ratio = 0, buff_job_ratio = 0, race_ratio = 0, pk_ratio = 0;
+ int64 jexp, bexp;
+
+ nullpo_retv(sd);
+ nullpo_retv(base_exp);
+ nullpo_retv(job_exp);
+
+ jexp = *job_exp;
+ bexp = *base_exp;
+
+ if (src != NULL) {
+ const struct status_data *st = status->get_status_data(src);
+
+#ifdef RENEWAL_EXP //should happen first before we caluclate any modifiers
+ if (src->type == BL_MOB) {
+ const struct mob_data *md = BL_UCAST(BL_MOB, src);
+ int re_mod;
+ re_mod = pc->level_penalty_mod(md->level - sd->status.base_level, md->status.race, md->status.mode, 1);
+ jexp = apply_percentrate64(jexp, re_mod, 100);
+ bexp = apply_percentrate64(bexp, re_mod, 100);
+ }
+#endif
- if (sd->expaddrace[st->race])
- bonus += sd->expaddrace[st->race];
- bonus += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ //Race modifier
+ if (sd->expaddrace[st->race])
+ race_ratio += sd->expaddrace[st->race];
+ race_ratio += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ }
- if (battle_config.pk_mode
- && (int)(status->get_lv(src) - sd->status.base_level) >= 20)
- bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
- if (sd->sc.data[SC_CASH_PLUSEXP])
- bonus += sd->sc.data[SC_CASH_PLUSEXP]->val1;
- if (sd->sc.data[SC_OVERLAPEXPUP])
- bonus += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ //PK modifier
+ /* this doesn't exist in Aegis, instead there's a CrazyKiller check which double all EXP from this point */
+ if (battle_config.pk_mode && status->get_lv(src) - sd->status.base_level >= 20)
+ pk_ratio += 15; // pk_mode additional exp if monster >20 levels [Valaris]
- *base_exp = (unsigned int) cap_value(*base_exp + apply_percentrate64(*base_exp, bonus, 100), 1, UINT_MAX);
+ //Buffs modifier
+ if (sd->sc.data[SC_CASH_PLUSEXP]) {
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ buff_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ }
+ if (sd->sc.data[SC_OVERLAPEXPUP]) {
+ buff_job_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ buff_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ }
if (sd->sc.data[SC_CASH_PLUSONLYJOBEXP])
- bonus += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
- *job_exp = (unsigned int) cap_value(*job_exp + apply_percentrate64(*job_exp, bonus, 100), 1, UINT_MAX);
+ //Applying Race and PK modifier First then Premium (Perment modifier) and finally buff modifier
+ jexp += apply_percentrate64(jexp, race_ratio, 100);
+ jexp += apply_percentrate64(jexp, pk_ratio, 100);
+
+ bexp += apply_percentrate64(bexp, race_ratio, 100);
+ bexp += apply_percentrate64(bexp, pk_ratio, 100);
- if (sd->status.mod_exp != 100) {
- *base_exp = (unsigned int) cap_value(apply_percentrate64(*base_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
- *job_exp = (unsigned int) cap_value(apply_percentrate64(*job_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
+ if (sd->status.mod_exp != 100) {
+ jexp = apply_percentrate64(jexp, sd->status.mod_exp, 100);
+ bexp = apply_percentrate64(bexp, sd->status.mod_exp, 100);
}
+
+ bexp += apply_percentrate64(bexp, buff_ratio, 100);
+ jexp += apply_percentrate64(jexp, buff_ratio + buff_job_ratio, 100);
+
+ *job_exp = cap_value(jexp, 1, UINT64_MAX);
+ *base_exp = cap_value(bexp, 1, UINT64_MAX);
}
/**
@@ -6649,44 +7107,46 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in
* @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;
+static bool pc_gainexp(struct map_session_data *sd, struct block_list *src, uint64 base_exp, uint64 job_exp, bool is_quest)
+{
+ float nextbp = 0, nextjp = 0;
+ uint64 nextb = 0, nextj = 0;
nullpo_ret(sd);
- if(sd->bl.prev == NULL || pc_isdead(sd))
+ if (sd->bl.prev == NULL || pc_isdead(sd))
return false;
- if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
+ if (!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
return false; // no exp on pvp maps
- if( pc_has_permission(sd,PC_PERM_DISABLE_EXP) )
+ if (pc_has_permission(sd,PC_PERM_DISABLE_EXP))
return false;
- if(sd->status.guild_id>0)
- base_exp-=guild->payexp(sd,base_exp);
+ if (src)
+ pc->calcexp(sd, &base_exp, &job_exp, src);
- if(src) pc->calcexp(sd, &base_exp, &job_exp, src);
+ if (sd->status.guild_id > 0)
+ base_exp -= guild->payexp(sd, base_exp);
nextb = pc->nextbaseexp(sd);
nextj = pc->nextjobexp(sd);
- if(sd->state.showexp || battle_config.max_exp_gain_rate){
+ if (sd->state.showexp || battle_config.max_exp_gain_rate) {
if (nextb > 0)
nextbp = (float) base_exp / (float) nextb;
if (nextj > 0)
nextjp = (float) job_exp / (float) nextj;
- if(battle_config.max_exp_gain_rate) {
+ if (battle_config.max_exp_gain_rate) {
if (nextbp > battle_config.max_exp_gain_rate/1000.) {
//Note that this value should never be greater than the original
//base_exp, therefore no overflow checks are needed. [Skotlex]
- base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb);
+ base_exp = (uint64)(battle_config.max_exp_gain_rate / 1000. * nextb);
if (sd->state.showexp)
nextbp = (float) base_exp / (float) nextb;
}
if (nextjp > battle_config.max_exp_gain_rate/1000.) {
- job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj);
+ job_exp = (uint64)(battle_config.max_exp_gain_rate / 1000. * nextj);
if (sd->state.showexp)
nextjp = (float) job_exp / (float) nextj;
}
@@ -6696,23 +7156,23 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
// 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)
+ nextb = nextb ? UINT64_MAX : pc->thisbaseexp(sd);
+ if (sd->status.base_exp > nextb - base_exp)
sd->status.base_exp = nextb;
else
sd->status.base_exp += base_exp;
pc->checkbaselevelup(sd);
- clif->updatestatus(sd,SP_BASEEXP);
+ clif->updatestatus(sd, SP_BASEEXP);
}
if (job_exp) {
- nextj = nextj?UINT_MAX:pc->thisjobexp(sd);
- if(sd->status.job_exp > nextj - job_exp)
+ nextj = nextj ? UINT64_MAX : pc->thisjobexp(sd);
+ if (sd->status.job_exp > nextj - job_exp)
sd->status.job_exp = nextj;
else
sd->status.job_exp += job_exp;
pc->checkjoblevelup(sd);
- clif->updatestatus(sd,SP_JOBEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
}
#if PACKETVER >= 20091027
@@ -6725,8 +7185,14 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
if(sd->state.showexp) {
char output[256];
sprintf(output,
- "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
- clif_disp_onlyself(sd,output,strlen(output));
+ msg_sd(sd, 889), // Experience Gained Base:%"PRIu64" (%.2f%%) Job:%"PRIu64" (%.2f%%)
+ base_exp, nextbp * (float)100, job_exp, nextjp * (float)100);
+ clif_disp_onlyself(sd, output);
+ }
+
+ // Share master EXP to homunculus
+ if (sd->hd != NULL && battle_config.hom_bonus_exp_from_master > 0) {
+ homun->gainexp(sd->hd, apply_percentrate((int)base_exp, battle_config.hom_bonus_exp_from_master, 100));
}
return true;
@@ -6735,14 +7201,18 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
/*==========================================
* Returns max level for this character.
*------------------------------------------*/
-unsigned int pc_maxbaselv(struct map_session_data *sd)
+static int pc_maxbaselv(const struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][0];
+ nullpo_ret(sd);
+
+ return pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_BASE]->max_level;
}
-unsigned int pc_maxjoblv(struct map_session_data *sd)
+static int pc_maxjoblv(const struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][1];
+ nullpo_ret(sd);
+
+ return pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_JOB]->max_level;
}
/*==========================================
@@ -6750,23 +7220,37 @@ unsigned int pc_maxjoblv(struct map_session_data *sd)
*------------------------------------------*/
//Base exp needed for next level.
-unsigned int pc_nextbaseexp(struct map_session_data *sd)
+static uint64 pc_nextbaseexp(const struct map_session_data *sd)
{
+ const struct class_exp_group *exp_group = NULL;
+
nullpo_ret(sd);
- if(sd->status.base_level>=pc->maxbaselv(sd) || sd->status.base_level<=0)
+ if (sd->status.base_level >= pc->maxbaselv(sd) || sd->status.base_level <= 0)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-1];
+ exp_group = pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_BASE];
+
+ nullpo_ret(exp_group);
+
+ return VECTOR_INDEX(exp_group->exp, sd->status.base_level >= exp_group->max_level ? 0 : sd->status.base_level - 1);
}
//Base exp needed for this level.
-unsigned int pc_thisbaseexp(struct map_session_data *sd)
+static uint64 pc_thisbaseexp(const struct map_session_data *sd)
{
- if(sd->status.base_level>pc->maxbaselv(sd) || sd->status.base_level<=1)
+ const struct class_exp_group *exp_group = NULL;
+
+ nullpo_ret(sd);
+
+ if (sd->status.base_level > pc->maxbaselv(sd) || sd->status.base_level <= 1)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-2];
+ exp_group = pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_BASE];
+
+ nullpo_ret(exp_group);
+
+ return VECTOR_INDEX(exp_group->exp, sd->status.base_level - 2);
}
/*==========================================
@@ -6777,25 +7261,39 @@ unsigned int pc_thisbaseexp(struct map_session_data *sd)
*------------------------------------------*/
//Job exp needed for next level.
-unsigned int pc_nextjobexp(struct map_session_data *sd)
+static uint64 pc_nextjobexp(const struct map_session_data *sd)
{
+ const struct class_exp_group *exp_group = NULL;
+
nullpo_ret(sd);
- if(sd->status.job_level>=pc->maxjoblv(sd) || sd->status.job_level<=0)
+ if (sd->status.job_level >= pc->maxjoblv(sd) || sd->status.job_level <= 0)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-1];
+
+ exp_group = pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_JOB];
+
+ nullpo_ret(exp_group);
+
+ return VECTOR_INDEX(exp_group->exp, sd->status.job_level >= exp_group->max_level ? 0 : sd->status.job_level - 1);
}
//Job exp needed for this level.
-unsigned int pc_thisjobexp(struct map_session_data *sd)
+static uint64 pc_thisjobexp(const struct map_session_data *sd)
{
- if(sd->status.job_level>pc->maxjoblv(sd) || sd->status.job_level<=1)
+ const struct class_exp_group *exp_group = NULL;
+
+ nullpo_ret(sd);
+
+ if (sd->status.job_level > pc->maxjoblv(sd) || sd->status.job_level <= 1)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-2];
+
+ exp_group = pc->dbs->class_exp_table[pc->class2idx(sd->status.class)][CLASS_EXP_TABLE_JOB];
+
+ return VECTOR_INDEX(exp_group->exp, sd->status.job_level - 2);
}
/// Returns the value of the specified stat.
-int pc_getstat(struct map_session_data* sd, int type)
+static int pc_getstat(struct map_session_data *sd, int type)
{
nullpo_retr(-1, sd);
@@ -6813,7 +7311,7 @@ int pc_getstat(struct map_session_data* sd, int type)
/// Sets the specified stat to the specified value.
/// Returns the new value.
-int pc_setstat(struct map_session_data* sd, int type, int val)
+static int pc_setstat(struct map_session_data *sd, int type, int val)
{
nullpo_retr(-1, sd);
@@ -6828,11 +7326,13 @@ int pc_setstat(struct map_session_data* sd, int type, int val)
return -1;
}
+ achievement->validate_stats(sd, type, val); // Achievements [Smokexyz/Hercules]
+
return val;
}
// Calculates the number of status points PC gets when leveling up (from level to level+1)
-int pc_gets_status_point(int level)
+static int pc_gets_status_point(int level)
{
if (battle_config.use_statpoint_table) //Use values from "db/statpoint.txt"
return (pc->statp[level+1] - pc->statp[level]);
@@ -6843,7 +7343,7 @@ int pc_gets_status_point(int level)
/// Returns the number of stat points needed to change the specified stat by val.
/// If val is negative, returns the number of stat points that would be needed to
/// raise the specified stat from (current value - val) to current value.
-int pc_need_status_point(struct map_session_data* sd, int type, int val)
+static int pc_need_status_point(struct map_session_data *sd, int type, int val)
{
int low, high, sp = 0;
@@ -6878,7 +7378,8 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val)
* @param type Stat to verify.
* @return Maximum value the stat could grow by.
*/
-int pc_maxparameterincrease(struct map_session_data* sd, int type) {
+static int pc_maxparameterincrease(struct map_session_data *sd, int type)
+{
int base, final, status_points = sd->status.status_point;
base = final = pc->getstat(sd, type);
@@ -6908,35 +7409,35 @@ int pc_maxparameterincrease(struct map_session_data* sd, int type) {
* @retval true if the stat was increased by any amount.
* @retval false if there were no changes.
*/
-bool pc_statusup(struct map_session_data* sd, int type, int increase) {
- int max_increase = 0, current = 0, needed_points = 0, final_value = 0;
-
+static bool pc_statusup(struct map_session_data *sd, int type, int increase)
+{
nullpo_ret(sd);
+ int realIncrease = increase;
// check conditions
- if (type < SP_STR || type > SP_LUK || increase <= 0) {
- clif->statusupack(sd, type, 0, 0);
+ if (type < SP_STR || type > SP_LUK || realIncrease <= 0) {
+ clif->statusupack(sd, type, 0, increase);
return false;
}
// check limits
- current = pc->getstat(sd, type);
- max_increase = pc->maxparameterincrease(sd, type);
- increase = cap_value(increase, 0, max_increase); // cap to the maximum status points available
- if (increase <= 0 || current + increase > pc_maxparameter(sd)) {
- clif->statusupack(sd, type, 0, 0);
+ int current = pc->getstat(sd, type);
+ int max_increase = pc->maxparameterincrease(sd, type);
+ realIncrease = cap_value(realIncrease, 0, max_increase); // cap to the maximum status points available
+ if (realIncrease <= 0 || current + realIncrease > pc_maxparameter(sd)) {
+ clif->statusupack(sd, type, 0, increase);
return false;
}
// check status points
- needed_points = pc->need_status_point(sd, type, increase);
+ int needed_points = pc->need_status_point(sd, type, realIncrease);
if (needed_points < 0 || needed_points > sd->status.status_point) { // Sanity check
- clif->statusupack(sd, type, 0, 0);
+ clif->statusupack(sd, type, 0, increase);
return false;
}
// set new values
- final_value = pc->setstat(sd, type, current + increase);
+ int final_value = pc->setstat(sd, type, current + realIncrease);
sd->status.status_point -= needed_points;
status_calc_pc(sd, SCO_NONE);
@@ -6967,7 +7468,7 @@ bool pc_statusup(struct map_session_data* sd, int type, int increase) {
* @return the stat increase amount.
* @retval 0 if no changes were made.
*/
-int pc_statusup2(struct map_session_data* sd, int type, int val)
+static int pc_statusup2(struct map_session_data *sd, int type, int val)
{
int max, need;
nullpo_ret(sd);
@@ -7002,8 +7503,9 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
* Update skill_lv for player sd
* Skill point allocation
*------------------------------------------*/
-int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
- uint16 index = 0;
+static int pc_skillup(struct map_session_data *sd, uint16 skill_id)
+{
+ int index = 0;
nullpo_ret(sd);
if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) {
@@ -7022,13 +7524,14 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
if( sd->status.skill_point > 0 &&
sd->status.skill[index].id &&
sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
- sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class_) )
+ sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class) )
{
sd->status.skill[index].lv++;
sd->status.skill_point--;
if( !skill->dbs->db[index].inf )
status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
- else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ else if (sd->status.skill_point == 0 && (sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON
+ && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0)
pc->calc_skilltree(sd); // Required to grant all TK Ranger skills.
else
pc->check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
@@ -7039,13 +7542,18 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
clif->updatestatus(sd,SP_CARTINFO);
if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
clif->skillinfoblock(sd);
- } else if( battle_config.skillup_limit ){
- if (sd->sktree.second)
- clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB1, sd->sktree.second);
- else if (sd->sktree.third)
- clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB2, sd->sktree.third);
- else if (pc->calc_skillpoint(sd) < 9) /* TODO: official response? */
+ } else if (battle_config.skillup_limit) {
+ if (sd->sktree.second != 0) {
+#if PACKETVER >= 20090805
+ clif->msgtable_num(sd, MSG_UPGRADESKILLERROR_MORE_FIRSTJOBSKILL, sd->sktree.second);
+#endif
+ } else if (sd->sktree.third != 0) {
+#if PACKETVER >= 20091013
+ clif->msgtable_num(sd, MSG_UPGRADESKILLERROR_MORE_SECONDJOBSKILL, sd->sktree.third);
+#endif
+ } else if (pc->calc_skillpoint(sd) < 9) { /* TODO: official response? */
clif->messagecolor_self(sd->fd, COLOR_RED, "You need the basic skills");
+ }
}
return 0;
}
@@ -7053,14 +7561,14 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
/*==========================================
* /allskill
*------------------------------------------*/
-int pc_allskillup(struct map_session_data *sd)
+static int pc_allskillup(struct map_session_data *sd)
{
int i;
nullpo_ret(sd);
- for(i=0;i<MAX_SKILL;i++){
- if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
if (sd->status.skill[i].lv == 0)
@@ -7070,7 +7578,7 @@ int pc_allskillup(struct map_session_data *sd)
if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex]
//and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
- for(i=0;i<MAX_SKILL;i++){
+ for (i = 0; i < MAX_SKILL_DB; i++) {
switch( skill->dbs->db[i].nameid ) {
case SG_DEVIL:
case MO_TRIPLEATTACK:
@@ -7084,8 +7592,8 @@ int pc_allskillup(struct map_session_data *sd)
}
} else {
int id;
- for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class_)][i].id) > 0; i++) {
- int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][i].idx;
+ for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class)][i].id) > 0; i++) {
+ int idx = pc->skill_tree[pc->class2idx(sd->status.class)][i].idx;
int inf2 = skill->dbs->db[idx].inf2;
if (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
@@ -7095,7 +7603,7 @@ int pc_allskillup(struct map_session_data *sd)
continue; //Cannot be learned normally.
sd->status.skill[idx].id = id;
- sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class); // celest
}
}
status_calc_pc(sd,SCO_NONE);
@@ -7108,7 +7616,7 @@ int pc_allskillup(struct map_session_data *sd)
/*==========================================
* /resetlvl
*------------------------------------------*/
-int pc_resetlvl(struct map_session_data* sd,int type)
+static int pc_resetlvl(struct map_session_data *sd, int type)
{
int i;
@@ -7132,7 +7640,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
sd->status.int_=1;
sd->status.dex=1;
sd->status.luk=1;
- if(sd->status.class_ == JOB_NOVICE_HIGH) {
+ if (sd->status.class == JOB_NOVICE_HIGH) {
sd->status.status_point=100; // not 88 [celest]
// give platinum skills upon changing
pc->skill(sd, NV_FIRSTAID, 1, SKILL_GRANT_PERMANENT);
@@ -7196,7 +7704,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
/*==========================================
* /resetstate
*------------------------------------------*/
-int pc_resetstate(struct map_session_data* sd)
+static int pc_resetstate(struct map_session_data *sd)
{
nullpo_ret(sd);
@@ -7204,12 +7712,12 @@ int pc_resetstate(struct map_session_data* sd)
// New statpoint table used here - Dexity
if (sd->status.base_level > MAX_LEVEL) {
//pc->statp[] goes out of bounds, can't reset!
- ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%u) is greater than the max level supported (%d)\n",
+ ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n",
sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL);
return 0;
}
- sd->status.status_point = pc->statp[sd->status.base_level] + ((sd->class_&JOBL_UPPER) ? 52 : 0); // extra 52+48=100 stat points
+ sd->status.status_point = pc->statp[sd->status.base_level] + ((sd->job & JOBL_UPPER) != 0 ? 52 : 0); // extra 52+48=100 stat points
}
else
{
@@ -7250,7 +7758,7 @@ int pc_resetstate(struct map_session_data* sd)
if( sd->mission_mobid ) { //bugreport:2200
sd->mission_mobid = 0;
sd->mission_count = 0;
- pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), 0);
+ pc_setglobalreg(sd,script->add_variable("TK_MISSION_ID"), 0);
}
status_calc_pc(sd,SCO_NONE);
@@ -7262,12 +7770,12 @@ int pc_resetstate(struct map_session_data* sd)
* /resetskill
* @param flag: @see enum pc_resetskill_flag
*------------------------------------------*/
-int pc_resetskill(struct map_session_data* sd, int flag)
+static int pc_resetskill(struct map_session_data *sd, int flag)
{
int i, inf2, skill_point=0;
nullpo_ret(sd);
- if( flag&PCRESETSKILL_CHSEX && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER )
+ if (flag&PCRESETSKILL_CHSEX && (sd->job & MAPID_UPPERMASK) != MAPID_BARDDANCER)
return 0;
if( !(flag&PCRESETSKILL_RECOUNT) ) { //Remove stuff lost when resetting skills.
@@ -7275,11 +7783,11 @@ int pc_resetskill(struct map_session_data* sd, int flag)
/**
* It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway)
**/
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON))
return 0;
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);
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_DEVIL1));
i = sd->sc.option;
if( i&OPTION_RIDING && pc->checkskill(sd, KN_RIDING) )
i &= ~OPTION_RIDING;
@@ -7291,7 +7799,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
i &= ~OPTION_WUG;
if( i&OPTION_WUGRIDER && pc->checkskill(sd, RA_WUGRIDER) )
i &= ~OPTION_WUGRIDER;
- if( i&OPTION_MADOGEAR && ( sd->class_&MAPID_THIRDMASK ) == MAPID_MECHANIC )
+ if (i&OPTION_MADOGEAR && (sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC)
i &= ~OPTION_MADOGEAR;
#ifndef NEW_CARTS
if( i&OPTION_CART && pc->checkskill(sd, MC_PUSHCART) )
@@ -7304,13 +7812,13 @@ int pc_resetskill(struct map_session_data* sd, int flag)
pc->setoption(sd, i);
if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) )
- homun->vaporize(sd, HOM_ST_REST);
+ homun->vaporize(sd, HOM_ST_REST, true);
+
+ if ((sd->sc.data[SC_SPRITEMABLE] && pc->checkskill(sd, SU_SPRITEMABLE)))
+ status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
}
- for( i = 1; i < MAX_SKILL; i++ ) {
- // FIXME: We're looping on i = [1..MAX_SKILL-1] (which makes sense as index for sd->status.skill[]) but then we're using the
- // same i to access skill->dbs->db[], and especially to check skill_ischangesex(). This is wrong.
- uint16 skill_id = 0;
+ for (i = 1; i < MAX_SKILL_DB; i++) {
int lv = sd->status.skill[i].lv;
if (lv < 1) continue;
@@ -7319,17 +7827,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills.
continue;
- skill_id = skill->dbs->db[i].nameid;
-
- // Don't reset trick dead if not a novice/baby
- if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) {
- sd->status.skill[i].lv = 0;
- sd->status.skill[i].flag = 0;
- continue;
- }
-
- // do not reset basic skill
- if( skill_id == NV_BASIC && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE )
+ if (pc->resetskill_job(sd, i))
continue;
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
@@ -7384,10 +7882,34 @@ int pc_resetskill(struct map_session_data* sd, int flag)
return skill_point;
}
+static bool pc_resetskill_job(struct map_session_data *sd, int index)
+{
+ uint16 skill_id;
+
+ nullpo_retr(false, sd);
+ Assert_retr(false, index >= 0 && index < MAX_SKILL_DB);
+
+ skill_id = skill->dbs->db[index].nameid;
+
+ // Don't reset trick dead if not a novice/baby
+ if (skill_id == NV_TRICKDEAD && (sd->job & MAPID_UPPERMASK) != MAPID_NOVICE) {
+ sd->status.skill[index].lv = 0;
+ sd->status.skill[index].flag = 0;
+ return true;
+ }
+
+ // do not reset basic skill
+ if (skill_id == NV_BASIC && (sd->job & MAPID_UPPERMASK) != MAPID_NOVICE)
+ return true;
+ if (skill_id == SU_BASIC_SKILL && (sd->job & MAPID_BASEMASK) != MAPID_SUMMONER)
+ return true;
+ return false;
+}
+
/*==========================================
* /resetfeel [Komurka]
*------------------------------------------*/
-int pc_resetfeel(struct map_session_data* sd)
+static int pc_resetfeel(struct map_session_data *sd)
{
int i;
nullpo_ret(sd);
@@ -7396,25 +7918,25 @@ int pc_resetfeel(struct map_session_data* sd)
{
sd->feel_map[i].m = -1;
sd->feel_map[i].index = 0;
- pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),0);
+ pc_setglobalreg(sd,script->add_variable(pc->sg_info[i].feel_var),0);
}
return 0;
}
-int pc_resethate(struct map_session_data* sd)
+static int pc_resethate(struct map_session_data *sd)
{
int i;
nullpo_ret(sd);
for (i = 0; i < MAX_PC_FEELHATE; i++) {
sd->hate_mob[i] = -1;
- pc_setglobalreg(sd,script->add_str(pc->sg_info[i].hate_var),0);
+ pc_setglobalreg(sd,script->add_variable(pc->sg_info[i].hate_var),0);
}
return 0;
}
-int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id)
+static int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id)
{
int i, bonus = 0;
nullpo_ret(sd);
@@ -7428,28 +7950,49 @@ int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id)
return bonus;
}
-int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id) {
+static int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id)
+{
int i, bonus = sd->bonus.add_heal_rate;
- if( bonus ) {
- switch( skill_id ) {
- case AL_HEAL: if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break;
- case PR_SANCTUARY: if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break;
- case AM_POTIONPITCHER: if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break;
- case CR_SLIMPITCHER: if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break;
- case BA_APPLEIDUN: if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break;
+ if (bonus) {
+ switch (skill_id) {
+ case AL_HEAL:
+ if ((battle_config.skill_add_heal_rate & 1) == 0)
+ bonus = 0;
+ break;
+ case PR_SANCTUARY:
+ if ((battle_config.skill_add_heal_rate & 2) == 0)
+ bonus = 0;
+ break;
+ case AM_POTIONPITCHER:
+ if ((battle_config.skill_add_heal_rate & 4) == 0)
+ bonus = 0;
+ break;
+ case CR_SLIMPITCHER:
+ if ((battle_config.skill_add_heal_rate & 8) == 0)
+ bonus = 0;
+ break;
+ case BA_APPLEIDUN:
+ if ((battle_config.skill_add_heal_rate & 16) == 0)
+ bonus = 0;
+ break;
+ case AB_HIGHNESSHEAL:
+ if ((battle_config.skill_add_heal_rate & 32) == 0)
+ bonus = 0;
+ break;
}
}
ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_id);
- if( i < ARRAYLENGTH(sd->skillheal) )
+ if (i < ARRAYLENGTH(sd->skillheal))
bonus += sd->skillheal[i].val;
return bonus;
}
-int pc_skillheal2_bonus(struct map_session_data *sd, uint16 skill_id) {
+static int pc_skillheal2_bonus(struct map_session_data *sd, uint16 skill_id)
+{
int i, bonus = sd->bonus.add_heal2_rate;
ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_id);
@@ -7460,7 +8003,7 @@ int pc_skillheal2_bonus(struct map_session_data *sd, uint16 skill_id) {
return bonus;
}
-void pc_respawn(struct map_session_data* sd, clr_type clrtype)
+static void pc_respawn(struct map_session_data *sd, enum clr_type clrtype)
{
if( !pc_isdead(sd) )
return; // not applicable
@@ -7473,7 +8016,8 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
clif->resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
}
-int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
if( sd != NULL )
{
@@ -7487,7 +8031,7 @@ int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Invoked when a player has received damage
*------------------------------------------*/
-void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp)
+static void pc_damage(struct map_session_data *sd, struct block_list *src, unsigned int hp, unsigned int sp)
{
if (sp) clif->updatestatus(sd,SP_SP);
if (hp) clif->updatestatus(sd,SP_HP);
@@ -7509,163 +8053,192 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support )
pet->target_check(sd,src,1);
- if( sd->status.ele_id > 0 )
+ if (sd->status.ele_id != 0 && sd->ed != NULL)
elemental->set_target(sd,src);
- sd->canlog_tick = timer->gettick();
+ if (battle_config.prevent_logout_trigger & PLT_DAMAGE)
+ sd->canlog_tick = timer->gettick();
+
+ // Achievements [Smokexyz/Hercules]
+ if (src != NULL) {
+ if (src->type == BL_PC)
+ achievement->validate_pc_damage(BL_UCAST(BL_PC, src), sd, hp);
+ else if (src->type == BL_MOB)
+ achievement->validate_mob_damage(sd, hp, true);
+ }
}
-/*==========================================
- * Invoked when a player has negative current hp
- *------------------------------------------*/
-int pc_dead(struct map_session_data *sd,struct block_list *src) {
- int i=0,j=0;
- int64 tick = timer->gettick();
+/**
+ * Invoked when a character died.
+ *
+ * @param sd The died character.
+ * @param src The unit which caused the death.
+ * @retval 0 Death canceled.
+ * @retval 1 Standard death.
+ * @retval 9 Died in PVP/GVG/BG.
+ *
+ **/
+static int pc_dead(struct map_session_data *sd, struct block_list *src)
+{
+ nullpo_ret(sd);
- nullpo_retr(0, sd);
+ for (int i = 0; i < MAX_PC_DEVOTION; i++) {
+ if (sd->devotion[i] != 0) {
+ struct map_session_data *devsd = map->id2sd(sd->devotion[i]);
- for (j = 0; j < MAX_PC_DEVOTION; j++) {
- if (sd->devotion[j]) {
- struct map_session_data *devsd = map->id2sd(sd->devotion[j]);
- if (devsd)
+ if (devsd != NULL)
status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
- sd->devotion[j] = 0;
+
+ sd->devotion[i] = 0;
}
}
- if(sd->status.pet_id > 0 && sd->pd) {
+ if (sd->status.pet_id > 0 && sd->pd != NULL) {
struct pet_data *pd = sd->pd;
- if( !map->list[sd->bl.m].flag.noexppenalty ) {
+
+ if (map->list[sd->bl.m].flag.noexppenalty == 0) {
pet->set_intimate(pd, pd->pet.intimate - pd->petDB->die);
- if( pd->pet.intimate < 0 )
- pd->pet.intimate = 0;
- clif->send_petdata(sd,sd->pd,1,pd->pet.intimate);
+ clif->send_petdata(sd, sd->pd, 1, pd->pet.intimate);
}
- if( sd->pd->target_id ) // Unlock all targets...
+
+ if (sd->pd->target_id != 0) // Unlock all targets.
pet->unlocktarget(sd->pd);
}
- if (sd->status.hom_id > 0){
- if(battle_config.homunculus_auto_vapor && sd->hd)
- homun->vaporize(sd, HOM_ST_REST);
- }
+ if (sd->status.hom_id > 0 && sd->hd != NULL && battle_config.homunculus_auto_vapor != 0)
+ homun->vaporize(sd, HOM_ST_REST, true);
- if( sd->md )
- mercenary->delete(sd->md, 3); // Your mercenary soldier has ran away.
+ if (sd->md != NULL)
+ mercenary->delete(sd->md, 3); // Your mercenary soldier ran away.
- if( sd->ed )
+ if (sd->ed != NULL)
elemental->delete(sd->ed, 0);
- // Leave duel if you die [LuzZza]
- if(battle_config.duel_autoleave_when_die) {
- if(sd->duel_group > 0)
+ if (battle_config.duel_autoleave_when_die != 0) { // Leave duel if character died. [LuzZza]
+ if (sd->duel_group > 0)
duel->leave(sd->duel_group, sd);
- if(sd->duel_invite > 0)
+ if (sd->duel_invite > 0)
duel->reject(sd->duel_invite, sd);
}
- if (sd->npc_id && sd->st && sd->st->state != RUN)
+ if (sd->npc_id != 0 && sd->st != NULL && sd->st->state != RUN)
npc->event_dequeue(sd);
- pc_setglobalreg(sd,script->add_str("PC_DIE_COUNTER"),sd->die_counter+1);
- pc->setparam(sd, SP_KILLERRID, src?src->id:0);
+ pc_setglobalreg(sd, script->add_variable("PC_DIE_COUNTER"), sd->die_counter + 1);
+ pc->setparam(sd, SP_KILLERRID, (src != NULL) ? src->id : 0);
- if( sd->bg_id ) {/* TODO: purge when bgqueue is deemed ok */
- struct battleground_data *bgd;
- if( (bgd = bg->team_search(sd->bg_id)) != NULL && bgd->die_event[0] )
+ if (sd->bg_id != 0) { //TODO: Purge when bgqueue is deemed ok.
+ struct battleground_data *bgd = bg->team_search(sd->bg_id);
+
+ if (bgd != NULL && bgd->die_event[0] != '\0')
npc->event(sd, bgd->die_event, 0);
}
- for (i = 0; i < VECTOR_LENGTH(sd->script_queues); i++ ) {
+ for (int i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
struct script_queue *queue = script->queue(VECTOR_INDEX(sd->script_queues, i));
- if (queue && queue->event_death[0] != '\0')
+
+ if (queue != NULL && queue->event_death[0] != '\0')
npc->event(sd, queue->event_death, 0);
}
- npc->script_event(sd,NPCE_DIE);
+ npc->script_event(sd, NPCE_DIE);
- // Clear anything NPC-related when you die and was interacting with one.
- if ( (sd->npc_id || sd->npc_shopid) && sd->state.dialog) {
- if (sd->state.using_fake_npc) {
+ // Clear anything NPC-related if character died while interacting with one.
+ if ((sd->npc_id != 0 || sd->npc_shopid != 0) && sd->state.dialog != 0) {
+ if (sd->state.using_fake_npc != 0) {
clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
sd->state.using_fake_npc = 0;
}
- if (sd->state.menu_or_input)
+
+ if (sd->state.menu_or_input != 0)
sd->state.menu_or_input = 0;
- if (sd->npc_menu)
+
+ if (sd->npc_menu != 0)
sd->npc_menu = 0;
sd->npc_id = 0;
sd->npc_shopid = 0;
- if (sd->st && sd->st->state != END)
+
+ if (sd->st != NULL && sd->st->state != END)
sd->st->state = END;
}
- /* e.g. not killed through pc->damage */
- if( pc_issit(sd) ) {
- clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT);
- }
+ // E.g. not killed through pc->damage().
+ if (pc_issit(sd))
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT));
pc_setdead(sd);
- //Reset menu skills/item skills
- if (sd->skillitem)
- sd->skillitem = sd->skillitemlv = 0;
- if (sd->menuskill_id)
- sd->menuskill_id = sd->menuskill_val = 0;
- //Reset ticks.
- sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0;
-
- if ( sd->spiritball )
+ clif->party_dead_notification(sd);
+
+ pc->autocast_clear(sd); // Unset auto-cast data.
+
+ if (sd->menuskill_id != 0) { // Reset menu skills.
+ sd->menuskill_id = 0;
+ sd->menuskill_val = 0;
+ }
+
+ // Reset ticks.
+ sd->hp_loss.tick = 0;
+ sd->sp_loss.tick = 0;
+ sd->hp_regen.tick = 0;
+ sd->sp_regen.tick = 0;
+
+ if (sd->spiritball != 0)
pc->delspiritball(sd, sd->spiritball, 0);
+
if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
pc->del_charm(sd, sd->charm_count, sd->charm_type);
+ int64 tick = timer->gettick();
+
if (src != NULL) {
switch (src->type) {
- case BL_MOB:
- {
- struct mob_data *md = BL_UCAST(BL_MOB, src);
- if (md->target_id==sd->bl.id)
- mob->unlocktarget(md,tick);
- if (battle_config.mobs_level_up && md->status.hp
- && (unsigned int)md->level < pc->maxbaselv(sd)
- && !md->guardian_data && md->special_state.ai == AI_NONE// Guardians/summons should not level. [Skotlex]
- ) {
- // monster level up [Valaris]
- clif->misceffect(&md->bl,0);
- md->level++;
- status_calc_mob(md, SCO_NONE);
- status_percent_heal(src,10,0);
-
- if( battle_config.show_mob_info&4 )
- {// update name with new level
- clif->charnameack(0, &md->bl);
- }
- }
- src = battle->get_master(src); // Maybe Player Summon
+ case BL_MOB: {
+ struct mob_data *md = BL_UCAST(BL_MOB, src);
+
+ if (md->target_id == sd->bl.id)
+ mob->unlocktarget(md, tick);
+
+ if (battle_config.mobs_level_up != 0 && md->status.hp != 0 && md->level < pc->maxbaselv(sd)
+ && md->guardian_data == NULL && md->special_state.ai == AI_NONE) { // Guardians/summons should not level up. [Skotlex]
+ /// Monster level up. [Valaris]
+ clif->misceffect(&md->bl, 0);
+ md->level++;
+ status_calc_mob(md, SCO_NONE);
+ status_percent_heal(src, 10, 0);
+
+ if ((battle_config.show_mob_info & 4) != 0)
+ clif->blname_ack(0, &md->bl); // Update name with new level.
}
+
+ src = battle->get_master(src); // Maybe character summon.
break;
- case BL_PET: //Pass on to master...
- src = &BL_UCAST(BL_PET, src)->msd->bl;
+ }
+ case BL_PET:
+ src = &BL_UCAST(BL_PET, src)->msd->bl; // Pass on to master.
break;
- case BL_HOM:
- src = &BL_UCAST(BL_HOM, src)->master->bl;
+ case BL_HOM:
+ src = &BL_UCAST(BL_HOM, src)->master->bl; // Pass on to master.
break;
- case BL_MER:
- src = &BL_UCAST(BL_MER, src)->master->bl;
+ case BL_MER:
+ src = &BL_UCAST(BL_MER, src)->master->bl; // Pass on to master.
break;
}
}
if (src != NULL && src->type == BL_PC) {
struct map_session_data *ssd = BL_UCAST(BL_PC, src);
+
pc->setparam(ssd, SP_KILLEDRID, sd->bl.id);
npc->script_event(ssd, NPCE_KILLPC);
+ achievement->validate_pc_kill(ssd, sd);
- if (battle_config.pk_mode&2) {
+ if ((battle_config.pk_mode & 2) != 0) {
ssd->status.manner -= 5;
- if(ssd->status.manner < 0)
- sc_start(NULL,src,SC_NOCHAT,100,0,0);
+
+ if (ssd->status.manner < 0)
+ sc_start(NULL, src, SC_NOCHAT, 100, 0, 0);
+
#if 0
// PK/Karma system code (not enabled yet) [celest]
// originally from Kade Online, so i don't know if any of these is correct ^^;
@@ -7677,14 +8250,15 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
// If player killed was more evil
sd->status.karma--;
ssd->status.karma--;
- }
- else if (sd->status.karma < ssd->status.karma) // If player killed was more good
+ } else if (sd->status.karma < ssd->status.karma) { // If player killed was more good
ssd->status.karma++;
+ }
// or the PK System way...
if (sd->status.karma > 0) // player killed is dishonourable?
ssd->status.karma--; // honour points earned
+
sd->status.karma++; // honour points lost
// To-do: Receive exp on certain occasions
@@ -7692,136 +8266,156 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
}
- if( battle_config.bone_drop==2
- || (battle_config.bone_drop==1 && map->list[sd->bl.m].flag.pvp)
- ) {
+ if (battle_config.bone_drop == 2 || (battle_config.bone_drop == 1 && map->list[sd->bl.m].flag.pvp != 0)) {
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid=ITEMID_SKULL_;
- item_tmp.identify=1;
- item_tmp.card[0]=CARD0_CREATE;
- item_tmp.card[1]=0;
- item_tmp.card[2]=GetWord(sd->status.char_id,0); // CharId
- item_tmp.card[3]=GetWord(sd->status.char_id,1);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
- }
-
- // activate Steel body if a super novice dies at 99+% exp [celest]
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
- unsigned int next = pc->nextbaseexp(sd);
- if( next == 0 ) next = pc->thisbaseexp(sd);
- if( get_percentage(sd->status.base_exp,next) >= 99 ) {
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = ITEMID_SKULL_;
+ item_tmp.identify = 1;
+ item_tmp.card[0] = CARD0_CREATE;
+ item_tmp.card[1] = 0;
+ item_tmp.card[2] = GetWord(sd->status.char_id, 0);
+ item_tmp.card[3] = GetWord(sd->status.char_id, 1);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
+ }
+
+ // Activate Steel Body if a Super Novice dies at 99+% EXP. [celest]
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->state.snovice_dead_flag == 0) {
+ uint64 next = pc->nextbaseexp(sd);
+
+ if (next == 0)
+ next = pc->thisbaseexp(sd);
+
+ if (get_percentage64(sd->status.base_exp, next) >= 99) {
sd->state.snovice_dead_flag = 1;
pc->setstand(sd);
status_percent_heal(&sd->bl, 100, 100);
clif->resurrection(&sd->bl, 1);
- if(battle_config.pc_invincible_time)
+
+ if (battle_config.pc_invincible_time != 0)
pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
- sc_start(NULL,&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
- if(map_flag_gvg2(sd->bl.m))
+
+ sc_start(NULL, &sd->bl, status->skill2sc(MO_STEELBODY), 100, 1, skill->get_time(MO_STEELBODY, 1));
+
+ if (map_flag_gvg2(sd->bl.m))
pc->respawn_timer(INVALID_TIMER, timer->gettick(), sd->bl.id, 0);
+
return 0;
}
}
- // changed penalty options, added death by player if pk_mode [Valaris]
- if( battle_config.death_penalty_type
- && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
- && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
- && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
- ) {
+ if (battle_config.death_penalty_type != 0 && pc->isDeathPenaltyJob(sd->job) && !map_flag_gvg2(sd->bl.m)
+ && map->list[sd->bl.m].flag.noexppenalty == 0 && sd->sc.data[SC_BABY] == NULL
+ && sd->sc.data[SC_CASH_DEATHPENALTY] == NULL && !pc->auto_exp_insurance(sd)) {
if (battle_config.death_penalty_base > 0) {
unsigned int base_penalty = 0;
+ int rate = battle_config.death_penalty_base;
+
switch (battle_config.death_penalty_type) {
- case 1:
- base_penalty = (unsigned int) apply_percentrate64(pc->nextbaseexp(sd), battle_config.death_penalty_base, 10000);
- break;
- case 2:
- base_penalty = (unsigned int) apply_percentrate64(sd->status.base_exp, battle_config.death_penalty_base, 10000);
- break;
+ case 1:
+ base_penalty = (unsigned int)apply_percentrate64(pc->nextbaseexp(sd), rate, 10000);
+ break;
+ case 2:
+ base_penalty = (unsigned int)apply_percentrate64(sd->status.base_exp, rate, 10000);
+ break;
}
if (base_penalty != 0) {
- if (battle_config.pk_mode && src && src->type==BL_PC)
- base_penalty*=2;
- if( sd->status.mod_death != 100 )
+ if (battle_config.pk_mode != 0 && src != NULL && src->type == BL_PC)
+ base_penalty *= 2;
+
+ if (sd->status.mod_death != 100)
base_penalty = base_penalty * sd->status.mod_death / 100;
+
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
- clif->updatestatus(sd,SP_BASEEXP);
+ clif->updatestatus(sd, SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0) {
+ if (battle_config.death_penalty_job > 0) {
unsigned int job_penalty = 0;
+ int rate = battle_config.death_penalty_job;
switch (battle_config.death_penalty_type) {
- case 1:
- job_penalty = (unsigned int) apply_percentrate64(pc->nextjobexp(sd), battle_config.death_penalty_job, 10000);
- break;
- case 2:
- job_penalty = (unsigned int) apply_percentrate64(sd->status.job_exp, battle_config.death_penalty_job, 10000);
- break;
+ case 1:
+ job_penalty = (unsigned int)apply_percentrate64(pc->nextjobexp(sd), rate, 10000);
+ break;
+ case 2:
+ job_penalty = (unsigned int)apply_percentrate64(sd->status.job_exp, rate, 10000);
+ break;
}
if (job_penalty != 0) {
- if (battle_config.pk_mode && src && src->type==BL_PC)
- job_penalty*=2;
- if( sd->status.mod_death != 100 )
+ if (battle_config.pk_mode != 0 && src != NULL && src->type == BL_PC)
+ job_penalty *= 2;
+
+ if (sd->status.mod_death != 100)
job_penalty = job_penalty * sd->status.mod_death / 100;
+
sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
- clif->updatestatus(sd,SP_JOBEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
}
}
- if (battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
+ if (battle_config.zeny_penalty > 0 && map->list[sd->bl.m].flag.nozenypenalty == 0) {
int zeny_penalty = apply_percentrate(sd->status.zeny, battle_config.zeny_penalty, 10000);
+
if (zeny_penalty != 0)
pc->payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
}
}
- if(map->list[sd->bl.m].flag.pvp_nightmaredrop) {
- // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
- for(j=0;j<map->list[sd->bl.m].drop_list_count;j++){
- int id = map->list[sd->bl.m].drop_list[j].drop_id;
- int type = map->list[sd->bl.m].drop_list[j].drop_type;
- int per = map->list[sd->bl.m].drop_list[j].drop_per;
- if(id == 0)
+ if (map->list[sd->bl.m].flag.pvp_nightmaredrop != 0) {
+ // Moved this outside so it works when PVP isn't enabled and during pk mode. [Ancyker]
+ for (int i = 0; i < map->list[sd->bl.m].drop_list_count; i++) {
+ int id = map->list[sd->bl.m].drop_list[i].drop_id;
+ int type = map->list[sd->bl.m].drop_list[i].drop_type;
+ int per = map->list[sd->bl.m].drop_list[i].drop_per;
+
+ if (id == 0)
continue;
- if(id == -1){
- int eq_num=0,eq_n[MAX_INVENTORY],k;
- memset(eq_n,0,sizeof(eq_n));
- for(i=0;i<MAX_INVENTORY;i++){
- if( (type == 1 && !sd->status.inventory[i].equip)
- || (type == 2 && sd->status.inventory[i].equip)
- || type == 3)
- {
- ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 );
- if( k < MAX_INVENTORY )
- eq_n[k] = i;
+
+ if (id == -1) {
+ int eq_num = 0;
+ int eq_n[MAX_INVENTORY];
+
+ memset(eq_n, 0, sizeof(eq_n));
+
+ for (int j = 0; j < sd->status.inventorySize; j++) {
+ bool is_equipped = (sd->status.inventory[j].equip != 0);
+
+ if ((type == 1 && !is_equipped) || (type == 2 && is_equipped) || type == 3) {
+ int k;
+
+ ARR_FIND(0, sd->status.inventorySize, k, eq_n[k] <= 0);
+
+ if (k < sd->status.inventorySize)
+ eq_n[k] = j;
eq_num++;
}
}
- if(eq_num > 0){
- int n = eq_n[rnd()%eq_num];
- if(rnd()%10000 < per){
- if(sd->status.inventory[n].equip)
+
+ if (eq_num > 0) {
+ int n = eq_n[rnd() % eq_num];
+
+ if (rnd() % 10000 < per) {
+ if (sd->status.inventory[n].equip != 0)
pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
- pc->dropitem(sd,n,1);
+
+ pc->dropitem(sd, n, 1);
}
}
- }
- else if(id > 0){
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid == id
- && rnd()%10000 < per
- && ((type == 1 && !sd->status.inventory[i].equip)
- || (type == 2 && sd->status.inventory[i].equip)
- || type == 3) ){
- if(sd->status.inventory[i].equip)
- pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
- pc->dropitem(sd,i,1);
+ } else if (id > 0) {
+ for (int j = 0; j < sd->status.inventorySize; j++) {
+ bool is_equipped = (sd->status.inventory[j].equip != 0);
+
+ if (((type == 1 && !is_equipped) || (type == 2 && is_equipped) || type == 3)
+ && sd->status.inventory[j].nameid == id && rnd() % 10000 < per) {
+ if (is_equipped)
+ pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
+
+ pc->dropitem(sd, j, 1);
break;
}
}
@@ -7829,52 +8423,64 @@ 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)
- ) {
+ // Remove autotrade to prevent autotrading from save point.
+ if ((map->list[sd->bl.m].flag.pvp != 0 || map->list[sd->bl.m].flag.gvg != 0)
+ && (sd->state.standalone != 0 || sd->state.autotrade != 0)) {
sd->state.autotrade = 0;
sd->state.standalone = 0;
- pc->autotrade_update(sd,PAUC_REMOVE);
+ 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 ) {
+ // Disable certain PVP functions on pk_mode. [Valaris]
+ if (map->list[sd->bl.m].flag.pvp != 0 && battle_config.pk_mode == 0
+ && map->list[sd->bl.m].flag.pvp_nocalcrank == 0) {
sd->pvp_point -= 5;
sd->pvp_lost++;
+
if (src != NULL && src->type == BL_PC) {
struct map_session_data *ssd = BL_UCAST(BL_PC, src);
+
ssd->pvp_point++;
ssd->pvp_won++;
}
- if( sd->pvp_point < 0 )
- {
- timer->add(tick+1, pc->respawn_timer,sd->bl.id,0);
+
+ if (sd->pvp_point < 0) {
+ timer->add(tick + 1, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
}
}
- //GvG
- if( map_flag_gvg2(sd->bl.m) ) {
- timer->add(tick+1, pc->respawn_timer, sd->bl.id, 0);
+
+ // GVG
+ if (map_flag_gvg2(sd->bl.m)) {
+ timer->add(tick + 1, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
- } else if( sd->bg_id ) {
+ }
+
+ if (sd->bg_id != 0) {
struct battleground_data *bgd = bg->team_search(sd->bg_id);
- if( bgd && bgd->mapindex > 0 ) { // Respawn by BG
- timer->add(tick+1000, pc->respawn_timer, sd->bl.id, 0);
+
+ if (bgd != NULL && bgd->mapindex > 0) { // Respawn by BG.
+ timer->add(tick + 1000, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
}
}
- //Reset "can log out" tick.
- if( battle_config.prevent_logout )
+ // Reset "can log out" tick.
+ if (battle_config.prevent_logout != 0)
sd->canlog_tick = timer->gettick() - battle_config.prevent_logout;
return 1;
}
-void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
+static bool pc_isDeathPenaltyJob(uint16 job)
+{
+ return (job & MAPID_UPPERMASK) != MAPID_NOVICE; // only novices will receive no penalty
+}
+
+static void pc_revive(struct map_session_data *sd, unsigned int hp, unsigned int sp)
+{
+ nullpo_retv(sd);
if(hp) clif->updatestatus(sd,SP_HP);
if(sp) clif->updatestatus(sd,SP_SP);
@@ -7894,9 +8500,9 @@ void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
/*==========================================
* script reading pc status registry
*------------------------------------------*/
-int pc_readparam(struct map_session_data* sd,int type)
+static int64 pc_readparam(const struct map_session_data *sd, int type)
{
- int val = 0;
+ int64 val = 0;
nullpo_ret(sd);
@@ -7904,12 +8510,13 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_SKILLPOINT: val = sd->status.skill_point; break;
case SP_STATUSPOINT: val = sd->status.status_point; break;
case SP_ZENY: val = sd->status.zeny; break;
+ case SP_BANKVAULT: val = sd->status.bank_vault; break;
case SP_BASELEVEL: val = sd->status.base_level; break;
case SP_JOBLEVEL: val = sd->status.job_level; break;
- case SP_CLASS: val = sd->status.class_; break;
- case SP_BASEJOB: val = pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
- case SP_UPPER: val = (sd->class_&JOBL_UPPER) ? 1 : ((sd->class_&JOBL_BABY) ? 2 : 0); break;
- case SP_BASECLASS: val = pc->mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
+ case SP_CLASS: val = sd->status.class; break;
+ case SP_BASEJOB: val = pc->mapid2jobid(sd->job & MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
+ case SP_UPPER: val = (sd->job & JOBL_UPPER) != 0 ? 1 : ((sd->job & JOBL_BABY) != 0 ? 2 : 0); break;
+ case SP_BASECLASS: val = pc->mapid2jobid(sd->job & MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
case SP_SEX: val = sd->status.sex; break;
case SP_WEIGHT: val = sd->weight; break;
case SP_MAXWEIGHT: val = sd->max_weight; break;
@@ -7948,11 +8555,15 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_FLEE1: val = sd->battle_status.flee; break;
case SP_FLEE2: val = sd->battle_status.flee2; break;
case SP_DEFELE: val = sd->battle_status.def_ele; break;
-#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
+#ifdef RENEWAL_CAST
+ val = sd->bonus.varcastrate;
+ break;
+#else
+ FALLTHROUGH
#endif
case SP_CASTRATE:
- val = sd->castrate+=val;
+ val = sd->castrate;
break;
case SP_MAXHPRATE: val = sd->hprate; break;
case SP_MAXSPRATE: val = sd->sprate; break;
@@ -8035,7 +8646,6 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_FIXCASTRATE: val = sd->bonus.fixcastrate; break;
case SP_ADD_FIXEDCAST: val = sd->bonus.add_fixcast; break;
#ifdef RENEWAL_CAST
- case SP_VARCASTRATE: val = sd->bonus.varcastrate; break;
case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break;
#endif
}
@@ -8046,21 +8656,22 @@ int pc_readparam(struct map_session_data* sd,int type)
/*==========================================
* script set pc status registry
*------------------------------------------*/
-int pc_setparam(struct map_session_data *sd,int type,int val)
+static int pc_setparam(struct map_session_data *sd, int type, int64 val)
{
+ int delta;
nullpo_ret(sd);
switch(type){
case SP_BASELEVEL:
- if ((unsigned int)val > pc->maxbaselv(sd)) //Capping to max
+ if (val > pc->maxbaselv(sd)) //Capping to max
val = pc->maxbaselv(sd);
- if ((unsigned int)val > sd->status.base_level) {
+ if (val > sd->status.base_level) {
int stat = 0, i;
- for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++)
+ for (i = 0; i < val - sd->status.base_level; i++)
stat += pc->gets_status_point(sd->status.base_level + i);
sd->status.status_point += stat;
}
- sd->status.base_level = (unsigned int)val;
+ sd->status.base_level = (int32)val;
sd->status.base_exp = 0;
// clif->updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTBASEEXP);
@@ -8073,12 +8684,13 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
break;
case SP_JOBLEVEL:
- if ((unsigned int)val >= sd->status.job_level) {
- if ((unsigned int)val > pc->maxjoblv(sd)) val = pc->maxjoblv(sd);
- sd->status.skill_point += val - sd->status.job_level;
+ if (val >= sd->status.job_level) {
+ if (val > pc->maxjoblv(sd))
+ val = pc->maxjoblv(sd);
+ sd->status.skill_point += (int)val - sd->status.job_level;
clif->updatestatus(sd, SP_SKILLPOINT);
}
- sd->status.job_level = (unsigned int)val;
+ sd->status.job_level = (int32)val;
sd->status.job_exp = 0;
// clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTJOBEXP);
@@ -8086,17 +8698,30 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
status_calc_pc(sd, SCO_FORCE);
break;
case SP_SKILLPOINT:
- sd->status.skill_point = val;
+ sd->status.skill_point = (int32)val;
break;
case SP_STATUSPOINT:
- sd->status.status_point = val;
+ sd->status.status_point = (int32)val;
break;
case SP_ZENY:
if( val < 0 )
return 0;// can't set negative zeny
- logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY)));
- sd->status.zeny = cap_value(val, 0, MAX_ZENY);
+ logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value((int32)val, 0, MAX_ZENY)));
+ sd->status.zeny = cap_value((int32)val, 0, MAX_ZENY);
break;
+ case SP_BANKVAULT:
+ val = cap_value(val, 0, MAX_BANK_ZENY);
+ delta = ((int32)val - sd->status.bank_vault);
+ sd->status.bank_vault = (int32)val;
+ if (map->save_settings & 256) {
+ chrif->save(sd, 0); // send to char server
+ }
+ if (delta > 0) {
+ clif->bank_deposit(sd, BDA_SUCCESS);
+ } else if (delta < 0) {
+ clif->bank_withdraw(sd, BWA_SUCCESS);
+ }
+ return 1; // the vault uses a different packet
case SP_BASEEXP:
if(pc->nextbaseexp(sd) > 0) {
sd->status.base_exp = val;
@@ -8113,16 +8738,16 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
break;
case SP_WEIGHT:
- sd->weight = val;
+ sd->weight = (int32)val;
break;
case SP_MAXWEIGHT:
- sd->max_weight = val;
+ sd->max_weight = (int32)val;
break;
case SP_HP:
- sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp);
+ sd->battle_status.hp = cap_value((int32)val, 1, (int)sd->battle_status.max_hp);
break;
case SP_MAXHP:
- sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp);
+ sd->battle_status.max_hp = cap_value((int32)val, 1, battle_config.max_hp);
if( sd->battle_status.max_hp < sd->battle_status.hp )
{
@@ -8131,10 +8756,10 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
break;
case SP_SP:
- sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp);
+ sd->battle_status.sp = cap_value((int32)val, 0, (int)sd->battle_status.max_sp);
break;
case SP_MAXSP:
- sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp);
+ sd->battle_status.max_sp = cap_value((int32)val, 1, battle_config.max_sp);
if( sd->battle_status.max_sp < sd->battle_status.sp )
{
@@ -8143,28 +8768,28 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
break;
case SP_STR:
- sd->status.str = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.str = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_AGI:
- sd->status.agi = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.agi = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_VIT:
- sd->status.vit = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.vit = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_INT:
- sd->status.int_ = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.int_ = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_DEX:
- sd->status.dex = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.dex = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_LUK:
- sd->status.luk = cap_value(val, 1, pc_maxparameter(sd));
+ sd->status.luk = cap_value((int)val, 1, pc_maxparameter(sd));
break;
case SP_KARMA:
- sd->status.karma = val;
+ sd->status.karma = (int)val;
break;
case SP_MANNER:
- sd->status.manner = val;
+ sd->status.manner = (int)val;
if( val < 0 )
sc_start(NULL, &sd->bl, SC_NOCHAT, 100, 0, 0);
else {
@@ -8173,28 +8798,28 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
return 1; // status_change_start/status_change_end already sends packets warning the client
case SP_FAME:
- sd->status.fame = val;
+ sd->status.fame = (int32)val;
break;
case SP_KILLERRID:
- sd->killerrid = val;
+ sd->killerrid = (int32)val;
return 1;
case SP_KILLEDRID:
- sd->killedrid = val;
+ sd->killedrid = (int32)val;
return 1;
case SP_SLOTCHANGE:
- sd->status.slotchange = val;
+ sd->status.slotchange = (int32)val;
return 1;
case SP_CHARRENAME:
- sd->status.rename = val;
+ sd->status.rename = (int32)val;
return 1;
case SP_MOD_EXP:
- sd->status.mod_exp = val;
+ sd->status.mod_exp = (int32)val;
return 1;
case SP_MOD_DROP:
- sd->status.mod_drop = val;
+ sd->status.mod_drop = (int32)val;
return 1;
case SP_MOD_DEATH:
- sd->status.mod_death = val;
+ sd->status.mod_death = (int32)val;
return 1;
default:
ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
@@ -8208,8 +8833,9 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
/*==========================================
* HP/SP Healing. If flag is passed, the heal type is through clif->heal, otherwise update status.
*------------------------------------------*/
-void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type)
+static void pc_heal(struct map_session_data *sd, unsigned int hp, unsigned int sp, int type)
{
+ nullpo_retv(sd);
if (type) {
if (hp)
clif->heal(sd->fd,SP_HP,hp);
@@ -8229,10 +8855,11 @@ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int ty
* Heal player hp and/or sp linearly.
* Calculate bonus by status.
*------------------------------------------*/
-int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
+static int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp)
{
int bonus, tmp;
+ nullpo_ret(sd);
if(hp) {
int i;
bonus = 100 + (sd->battle_status.vit<<1)
@@ -8263,6 +8890,10 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
// 2014 Halloween Event : Pumpkin Bonus
if ( sd->sc.data[SC_MTF_PUMPKIN] && itemid == ITEMID_PUMPKIN )
hp += (int)(hp * sd->sc.data[SC_MTF_PUMPKIN]->val1/100);
+
+ // Activation Potion
+ if (sd->sc.data[SC_VITALIZE_POTION] != NULL)
+ hp += hp * sd->sc.data[SC_VITALIZE_POTION]->val3 / 100;
}
if(sp) {
bonus = 100 + (sd->battle_status.int_<<1)
@@ -8299,16 +8930,19 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
if( sd->sc.data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
+ if (sd->sc.data[SC_BITESCAR]) {
+ hp = 0;
+ }
}
- return status->heal(&sd->bl, hp, sp, 1);
+ return status->heal(&sd->bl, hp, sp, STATUS_HEAL_FORCED);
}
/*==========================================
* HP/SP Recovery
* Heal player hp nad/or sp by rate
*------------------------------------------*/
-int pc_percentheal(struct map_session_data *sd,int hp,int sp)
+static int pc_percentheal(struct map_session_data *sd, int hp, int sp)
{
nullpo_ret(sd);
@@ -8343,7 +8977,7 @@ int pc_percentheal(struct map_session_data *sd,int hp,int sp)
return 0;
}
-int jobchange_killclone(struct block_list *bl, va_list ap)
+static int jobchange_killclone(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
int flag = va_arg(ap, int);
@@ -8361,46 +8995,45 @@ int jobchange_killclone(struct block_list *bl, va_list ap)
* Called when player changes job
* Rewrote to make it tidider [Celest]
*------------------------------------------*/
-int pc_jobchange(struct map_session_data *sd,int job, int upper)
+static int pc_jobchange(struct map_session_data *sd, int class, int upper)
{
int i, fame_flag=0;
- int b_class, idx = 0;
+ int job, idx = 0;
nullpo_ret(sd);
- if (job < 0)
+ if (class < 0)
return 1;
//Normalize job.
- b_class = pc->jobid2mapid(job);
- if (b_class == -1)
+ job = pc->jobid2mapid(class);
+ if (job == -1)
return 1;
switch (upper) {
case 1:
- b_class|= JOBL_UPPER;
+ job |= JOBL_UPPER;
break;
case 2:
- b_class|= JOBL_BABY;
+ job |= JOBL_BABY;
break;
}
//This will automatically adjust bard/dancer classes to the correct gender
//That is, if you try to jobchange into dancer, it will turn you to bard.
- job = pc->mapid2jobid(b_class, sd->status.sex);
- if (job == -1)
+ class = pc->mapid2jobid(job, sd->status.sex);
+ if (class == -1)
return 1;
- if ((unsigned short)b_class == sd->class_)
+ if ((uint16)job == sd->job)
return 1; //Nothing to change.
- // changing from 1st to 2nd job
- if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ if ((job & JOBL_2) != 0 && (sd->job & JOBL_2) == 0 && (job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ // changing from 1st to 2nd job
sd->change_level_2nd = sd->status.job_level;
- pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
- }
- // changing from 2nd to 3rd job
- else if((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) {
+ pc_setglobalreg(sd, script->add_variable("jobchange_level"), sd->change_level_2nd);
+ } else if((job & JOBL_THIRD) != 0 && (sd->job & JOBL_THIRD) == 0) {
+ // changing from 2nd to 3rd job
sd->change_level_3rd = sd->status.job_level;
- pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
+ pc_setglobalreg(sd, script->add_variable("jobchange_level_3rd"), sd->change_level_3rd);
}
if(sd->cloneskill_id) {
@@ -8412,8 +9045,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->cloneskill_id);
}
sd->cloneskill_id = 0;
- pc_setglobalreg(sd, script->add_str("CLONE_SKILL"), 0);
- pc_setglobalreg(sd, script->add_str("CLONE_SKILL_LV"), 0);
+ pc_setglobalreg(sd, script->add_variable("CLONE_SKILL"), 0);
+ pc_setglobalreg(sd, script->add_variable("CLONE_SKILL_LV"), 0);
}
if(sd->reproduceskill_id) {
@@ -8425,14 +9058,14 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->reproduceskill_id);
}
sd->reproduceskill_id = 0;
- pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL"),0);
- pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL_LV"),0);
+ pc_setglobalreg(sd, script->add_variable("REPRODUCE_SKILL"),0);
+ pc_setglobalreg(sd, script->add_variable("REPRODUCE_SKILL_LV"),0);
}
- if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.
- const int class_ = pc->class2idx(sd->status.class_);
+ if ((job & MAPID_UPPERMASK) != (sd->job & MAPID_UPPERMASK)) { //Things to remove when changing class tree.
+ const int class_idx = pc->class2idx(sd->status.class);
short id;
- for(i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[class_][i].id) > 0; i++) {
+ for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[class_idx][i].id) > 0; i++) {
//Remove status specific to your current tree skills.
enum sc_type sc = status->skill2sc(id);
if (sc > SC_COMMON_MAX && sd->sc.data[sc])
@@ -8440,14 +9073,18 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
}
}
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (b_class&MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (job & MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
/* going off star glad lineage, reset feel to not store no-longer-used vars in the database */
pc->resetfeel(sd);
}
- sd->status.class_ = job;
- fame_flag = pc->famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
- sd->class_ = (unsigned short)b_class;
+ sd->status.class = class;
+ {
+ int fame_list_type = pc->famelist_type(sd->job);
+ if (fame_list_type != RANKTYPE_UNKNOWN)
+ fame_flag = pc->fame_rank(sd->status.char_id, fame_list_type);
+ }
+ sd->job = (uint16)job;
sd->status.job_level=1;
sd->status.job_exp=0;
@@ -8476,8 +9113,15 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if (sd->disguise != -1)
pc->disguise(sd, -1);
- status->set_viewdata(&sd->bl, job);
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
+ // Fix atcommand @jobchange when the player changing from 3rd job having alternate body style into non-3rd job, crashing the client
+ if (pc->has_second_costume(sd) == false) {
+ sd->status.body = 0;
+ sd->vd.body_style = 0;
+ clif->changelook(&sd->bl, LOOK_BODY2, sd->vd.body_style);
+ }
+
+ status->set_viewdata(&sd->bl, class);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
if(sd->vd.cloth_color)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
if (sd->vd.body_style)
@@ -8496,7 +9140,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
//Remove peco/cart/falcon
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) || (sd->job & MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT))
i&=~OPTION_RIDING;
if( i&OPTION_FALCON && !pc->checkskill(sd, HT_FALCON) )
i&=~OPTION_FALCON;
@@ -8519,7 +9163,10 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc->setoption(sd, i);
if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN))
- homun->vaporize(sd, HOM_ST_REST);
+ homun->vaporize(sd, HOM_ST_REST, true);
+
+ if ((sd->sc.data[SC_SPRITEMABLE] && pc->checkskill(sd, SU_SPRITEMABLE)))
+ status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
@@ -8527,14 +9174,15 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
status_calc_pc(sd,SCO_FORCE);
pc->checkallowskill(sd);
pc->equiplookall(sd);
+ pc->update_job_and_level(sd);
//if you were previously famous, not anymore.
- if (fame_flag) {
+ if (fame_flag != 0) {
chrif->save(sd,0);
chrif->buildfamelist();
} else if (sd->status.fame > 0) {
//It may be that now they are famous?
- switch (sd->class_&MAPID_UPPERMASK) {
+ switch (sd->job & MAPID_UPPERMASK) {
case MAPID_BLACKSMITH:
case MAPID_ALCHEMIST:
case MAPID_TAEKWON:
@@ -8543,6 +9191,9 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
break;
}
}
+ quest->questinfo_refresh(sd);
+
+ achievement->validate_jobchange(sd); // Achievements [Smokexyz/Hercules]
return 0;
}
@@ -8550,16 +9201,16 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
/*==========================================
* Tell client player sd has change equipement
*------------------------------------------*/
-int pc_equiplookall(struct map_session_data *sd)
+static int pc_equiplookall(struct map_session_data *sd)
{
nullpo_ret(sd);
clif->changelook(&sd->bl,LOOK_WEAPON,0);
clif->changelook(&sd->bl,LOOK_SHOES,0);
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- clif->changelook(&sd->bl,LOOK_ROBE, sd->status.robe);
+ clif->changelook(&sd->bl, LOOK_HEAD_BOTTOM, sd->status.look.head_bottom);
+ clif->changelook(&sd->bl, LOOK_HEAD_TOP, sd->status.look.head_top);
+ clif->changelook(&sd->bl, LOOK_HEAD_MID, sd->status.look.head_mid);
+ clif->changelook(&sd->bl, LOOK_ROBE, sd->status.look.robe);
return 0;
}
@@ -8567,15 +9218,15 @@ int pc_equiplookall(struct map_session_data *sd)
/*==========================================
* Tell client player sd has change look (hair,equip...)
*------------------------------------------*/
-int pc_changelook(struct map_session_data *sd,int type,int val)
+static int pc_changelook(struct map_session_data *sd, int type, int val)
{
nullpo_ret(sd);
switch(type){
case LOOK_BASE:
status->set_viewdata(&sd->bl, val);
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class);
+ clif->changelook(&sd->bl, LOOK_WEAPON, sd->status.look.weapon);
if (sd->vd.cloth_color)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
if (sd->vd.body_style)
@@ -8594,16 +9245,16 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
}
break;
case LOOK_WEAPON:
- sd->status.weapon=val;
+ sd->status.look.weapon = val;
break;
case LOOK_HEAD_BOTTOM:
- sd->status.head_bottom=val;
+ sd->status.look.head_bottom = val;
break;
case LOOK_HEAD_TOP:
- sd->status.head_top=val;
+ sd->status.look.head_top = val;
break;
case LOOK_HEAD_MID:
- sd->status.head_mid=val;
+ sd->status.look.head_mid = val;
break;
case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex]
val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
@@ -8621,12 +9272,12 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
sd->status.clothes_color=val;
break;
case LOOK_SHIELD:
- sd->status.shield=val;
+ sd->status.look.shield = val;
break;
case LOOK_SHOES:
break;
case LOOK_ROBE:
- sd->status.robe = val;
+ sd->status.look.robe = val;
break;
case LOOK_BODY2:
val = cap_value(val, MIN_BODY_STYLE, MAX_BODY_STYLE);
@@ -8637,10 +9288,76 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
return 0;
}
+/**
+ * Hides a character.
+ *
+ * @param sd The character to hide.
+ * @param show_msg Whether to show message to the character or not.
+ *
+ **/
+static void pc_hide(struct map_session_data *sd, bool show_msg)
+{
+ nullpo_retv(sd);
+
+ clif->clearunit_area(&sd->bl, CLR_OUTSIGHT);
+ sd->sc.option |= OPTION_INVISIBLE;
+ sd->vd.class = INVISIBLE_CLASS;
+
+ if (show_msg)
+ clif->message(sd->fd, atcommand->msgsd(sd, 11)); // Invisible: On
+
+ // Decrement the number of pvp players on the map.
+ map->list[sd->bl.m].users_pvp--;
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && map->list[sd->bl.m].flag.pvp_nocalcrank == 0
+ && sd->pvp_timer != INVALID_TIMER) { // Unregister the player for ranking.
+ timer->delete(sd->pvp_timer, pc->calc_pvprank_timer);
+ sd->pvp_timer = INVALID_TIMER;
+ }
+
+ clif->changeoption(&sd->bl);
+}
+
+/**
+ * Unhides a character.
+ *
+ * @param sd The character to unhide.
+ * @param show_msg Whether to show message to the character or not.
+ *
+ **/
+static void pc_unhide(struct map_session_data *sd, bool show_msg)
+{
+ nullpo_retv(sd);
+
+ sd->sc.option &= ~OPTION_INVISIBLE;
+
+ if (sd->disguise != -1)
+ status->set_viewdata(&sd->bl, sd->disguise);
+ else
+ status->set_viewdata(&sd->bl, sd->status.class);
+
+ if (show_msg)
+ clif->message(sd->fd, atcommand->msgsd(sd, 10)); // Invisible: Off
+
+ // Increment the number of pvp players on the map.
+ map->list[sd->bl.m].users_pvp++;
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && map->list[sd->bl.m].flag.pvp_nocalcrank == 0) // Register the player for ranking.
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+
+ // bugreport:2266
+ map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
+
+ if (sd->disguise != -1)
+ clif->spawn_unit(&sd->bl, AREA_WOS);
+
+ clif->changeoption(&sd->bl);
+}
+
/*==========================================
* Give an option (type) to player (sd) and display it to client
*------------------------------------------*/
-int pc_setoption(struct map_session_data *sd,int type)
+static int pc_setoption(struct map_session_data *sd, int type)
{
int p_type, new_look=0;
nullpo_ret(sd);
@@ -8648,21 +9365,27 @@ int pc_setoption(struct map_session_data *sd,int type)
//Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex]
sd->sc.option=type;
- clif->changeoption(&sd->bl);
+
+ if ((p_type & OPTION_INVISIBLE) != 0 && (type & OPTION_INVISIBLE) == 0) // Unhide character.
+ pc->unhide(sd, false);
+ else if ((p_type & OPTION_INVISIBLE) == 0 && (type & OPTION_INVISIBLE) != 0) // Hide character.
+ pc->hide(sd, false);
+ else
+ clif->changeoption(&sd->bl);
if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc->checkskill(sd,RK_DRAGONTRAINING) > 0) ) {
// Mounting
- clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_RIDING, 0, 0, 0);
+ clif->sc_load(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_RIDING), 0, 0, 0);
status_calc_pc(sd,SCO_NONE);
} else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON) ) {
// Dismount
- clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_RIDING);
+ clif->sc_end(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_RIDING));
status_calc_pc(sd,SCO_NONE);
}
#ifndef NEW_CARTS
if( type&OPTION_CART && !( p_type&OPTION_CART ) ) { //Cart On
- clif->cartlist(sd);
+ clif->cartList(sd);
clif->updatestatus(sd, SP_CARTINFO);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
status_calc_pc(sd,SCO_NONE); //Apply speed penalty.
@@ -8676,15 +9399,15 @@ int pc_setoption(struct map_session_data *sd,int type)
#endif
if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON
- clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_FALCON, 0, 0, 0);
+ clif->sc_load(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_FALCON), 0, 0, 0);
else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF
- clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_FALCON);
+ clif->sc_end(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_FALCON));
if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
- clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0);
+ clif->sc_load(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_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);
+ clif->sc_end(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_WUGRIDER));
status_calc_pc(sd,SCO_NONE);
}
@@ -8720,8 +9443,8 @@ int pc_setoption(struct map_session_data *sd,int type)
return 0; //Disguises break sprite changes
if (new_look < 0) { //Restore normal look.
- status->set_viewdata(&sd->bl, sd->status.class_);
- new_look = sd->vd.class_;
+ status->set_viewdata(&sd->bl, sd->status.class);
+ new_look = sd->vd.class;
}
pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks.
@@ -8738,7 +9461,8 @@ int pc_setoption(struct map_session_data *sd,int type)
/*==========================================
* Give player a cart
*------------------------------------------*/
-int pc_setcart(struct map_session_data *sd,int type) {
+static int pc_setcart(struct map_session_data *sd, int type)
+{
#ifndef NEW_CARTS
int cart[6] = {OPTION_NOTHING,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
int option;
@@ -8768,10 +9492,10 @@ int pc_setcart(struct map_session_data *sd,int type) {
break;
default:/* everything else is an allowed ID so we can move on */
if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */
- clif->cartlist(sd);
+ clif->cartList(sd);
clif->updatestatus(sd, SP_CARTINFO);
sc_start(NULL,&sd->bl, SC_PUSH_CART, 100, type, 0);
- clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0);
+ clif->sc_load(&sd->bl, sd->bl.id, AREA, status->get_sc_icon(SC_ON_PUSH_CART), type, 0, 0);
if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
sd->sc.data[SC_PUSH_CART]->val1 = type;
break;
@@ -8801,8 +9525,9 @@ int pc_setcart(struct map_session_data *sd,int type) {
* @param sd Target player.
* @param flag New state.
**/
-void pc_setfalcon(struct map_session_data *sd, bool flag)
+static void pc_setfalcon(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd,HT_FALCON) > 0) // add falcon if he have the skill
pc->setoption(sd,sd->sc.option|OPTION_FALCON);
@@ -8819,8 +9544,9 @@ void pc_setfalcon(struct map_session_data *sd, bool flag)
* @param sd Target player.
* @param flag New state.
**/
-void pc_setridingpeco(struct map_session_data *sd, bool flag)
+static void pc_setridingpeco(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, KN_RIDING))
pc->setoption(sd, sd->sc.option|OPTION_RIDING);
@@ -8836,14 +9562,23 @@ void pc_setridingpeco(struct map_session_data *sd, bool flag)
*
* @param sd Target player.
* @param flag New state.
+ * @param mtype Type of the mado gear.
**/
-void pc_setmadogear(struct map_session_data *sd, bool flag)
+static void pc_setmadogear(struct map_session_data *sd, bool flag, enum mado_type mtype)
{
+ nullpo_retv(sd);
+ Assert_retv(mtype >= MADO_ROBOT && mtype < MADO_MAX);
+
if (flag) {
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC)
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
+#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106
+ sc_start(&sd->bl, &sd->bl, SC_MADOGEAR, 100, (int)mtype, INFINITE_DURATION);
+#endif
+ }
} else if (pc_ismadogear(sd)) {
pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
+ // pc->setoption resets status effects when changing mado, no need to re do it here.
}
}
@@ -8855,8 +9590,9 @@ void pc_setmadogear(struct map_session_data *sd, bool flag)
* @param sd Target player.
* @param type New state. This must be a valid OPTION_DRAGON* or 0.
**/
-void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
+static void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
{
+ nullpo_retv(sd);
if (type&OPTION_DRAGON) {
// Ensure only one dragon is set at a time.
if (type&OPTION_DRAGON1)
@@ -8887,8 +9623,9 @@ void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
* @param sd Target player.
* @param flag New state.
**/
-void pc_setridingwug(struct map_session_data *sd, bool flag)
+static void pc_setridingwug(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, RA_WUGRIDER) > 0)
pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER);
@@ -8905,7 +9642,8 @@ void pc_setridingwug(struct map_session_data *sd, bool flag)
* 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 ) {
+static bool pc_can_attack(struct map_session_data *sd, int target_id)
+{
nullpo_retr(false, sd);
if( sd->sc.data[SC_BASILICA] ||
@@ -8919,7 +9657,8 @@ bool pc_can_attack( struct map_session_data *sd, int target_id ) {
(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] )
+ sd->sc.data[SC_FALLENEMPIRE] ||
+ sd->block_action.attack)
return false;
return true;
@@ -8930,12 +9669,14 @@ bool pc_can_attack( struct map_session_data *sd, int target_id ) {
* Called from clif_parse_GlobalMessage and clif_parse_WisMessage
* @retval true Can talk
**/
-bool pc_can_talk( struct map_session_data *sd ) {
+static 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) ||
- pc_ismuted(&sd->sc, MANNER_NOCHAT) )
+ pc_ismuted(&sd->sc, MANNER_NOCHAT) ||
+ sd->block_action.chat)
return false;
return true;
@@ -8944,7 +9685,7 @@ bool pc_can_talk( struct map_session_data *sd ) {
/*==========================================
* Check if player can drop an item
*------------------------------------------*/
-int pc_candrop(struct map_session_data *sd, struct item *item)
+static int pc_candrop(struct map_session_data *sd, struct item *item)
{
if( item && (item->expire_time || (item->bound && !pc_can_give_bound_items(sd))) )
return 0;
@@ -8955,15 +9696,19 @@ int pc_candrop(struct map_session_data *sd, struct item *item)
/**
* For '@type' variables (temporary numeric char reg)
**/
-int pc_readreg(struct map_session_data* sd, int64 reg) {
+static int pc_readreg(struct map_session_data *sd, int64 reg)
+{
+ nullpo_ret(sd);
return i64db_iget(sd->regs.vars, reg);
}
/**
* For '@type' variables (temporary numeric char reg)
**/
-void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
+static void pc_setreg(struct map_session_data *sd, int64 reg, int val)
+{
unsigned int index = script_getvaridx(reg);
+ nullpo_retv(sd);
if( val ) {
i64db_iput(sd->regs.vars, reg, val);
if( index )
@@ -8978,9 +9723,11 @@ void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
/**
* For '@type$' variables (temporary string char reg)
**/
-char* pc_readregstr(struct map_session_data* sd, int64 reg) {
+static char *pc_readregstr(struct map_session_data *sd, int64 reg)
+{
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
p = i64db_get(sd->regs.vars, reg);
return p ? p->value : NULL;
@@ -8988,11 +9735,14 @@ char* pc_readregstr(struct map_session_data* sd, int64 reg) {
/**
* For '@type$' variables (temporary string char reg)
**/
-void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
+static void pc_setregstr(struct map_session_data *sd, int64 reg, const char *str)
+{
struct script_reg_str *p = NULL;
unsigned int index = script_getvaridx(reg);
struct DBData prev;
+ nullpo_retv(sd);
+ nullpo_retv(str);
if( str[0] ) {
p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
@@ -9025,9 +9775,11 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
* - '#type' (permanent numeric account reg)
* - '##type' (permanent numeric account reg2)
**/
-int pc_readregistry(struct map_session_data *sd, int64 reg) {
+static int pc_readregistry(struct map_session_data *sd, int64 reg)
+{
struct script_reg_num *p = NULL;
+ nullpo_ret(sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9046,9 +9798,11 @@ int pc_readregistry(struct map_session_data *sd, int64 reg) {
* - '#type$' (permanent str account reg)
* - '##type$' (permanent str account reg2)
**/
-char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
+static char *pc_readregistry_str(struct map_session_data *sd, int64 reg)
+{
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry_str: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9067,16 +9821,18 @@ char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
* - '#type' (permanent numeric account reg)
* - '##type' (permanent numeric account reg2)
**/
-int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
+static int pc_setregistry(struct map_session_data *sd, int64 reg, int val)
+{
struct script_reg_num *p = NULL;
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
/* SAAD! those things should be stored elsewhere e.g. char ones in char table, the cash ones in account_data table! */
switch( regname[0] ) {
default: //Char reg
if( !strcmp(regname,"PC_DIE_COUNTER") && sd->die_counter != val ) {
- int i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
+ int i = (!sd->die_counter && (sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
sd->die_counter = val;
if( i )
status_calc_pc(sd,SCO_NONE); // Lost the bonus.
@@ -9142,11 +9898,14 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
* - '#type$' (permanent str account reg)
* - '##type$' (permanent str account reg2)
**/
-int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val) {
+static int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
+{
struct script_reg_str *p = NULL;
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
+ nullpo_ret(val);
if ( !pc->reg_load && !sd->vars_ok ) {
ShowError("pc_setregistry_str : refusing to set %s until vars are received.\n", regname);
return 0;
@@ -9196,7 +9955,8 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
/*==========================================
* Exec eventtimer for player sd (retrieved from map_session (id))
*------------------------------------------*/
-int pc_eventtimer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_eventtimer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd=map->id2sd(id);
char *p = (char *)data;
int i;
@@ -9220,10 +9980,11 @@ int pc_eventtimer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Add eventtimer for player sd ?
*------------------------------------------*/
-int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
+static int pc_addeventtimer(struct map_session_data *sd, int tick, const char *name)
{
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER );
if( i == MAX_EVENTTIMER )
@@ -9238,12 +9999,13 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
/*==========================================
* Del eventtimer for player sd ?
*------------------------------------------*/
-int pc_deleventtimer(struct map_session_data *sd,const char *name)
+static int pc_deleventtimer(struct map_session_data *sd, const char *name)
{
char* p = NULL;
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
if (sd->eventcount <= 0)
return 0;
@@ -9268,7 +10030,7 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
/*==========================================
* Update eventtimer count for player sd
*------------------------------------------*/
-int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick)
+static int pc_addeventtimercount(struct map_session_data *sd, const char *name, int tick)
{
int i;
@@ -9287,7 +10049,7 @@ int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick)
/*==========================================
* Remove all eventtimer for player sd
*------------------------------------------*/
-int pc_cleareventtimer(struct map_session_data *sd)
+static int pc_cleareventtimer(struct map_session_data *sd)
{
int i;
@@ -9307,11 +10069,14 @@ int pc_cleareventtimer(struct map_session_data *sd)
return 0;
}
/* called when a item with combo is worn */
-int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
+static int pc_checkcombo(struct map_session_data *sd, struct item_data *data)
+{
int i, j, k, z;
int index, success = 0;
struct pc_combos *combo;
+ nullpo_ret(sd);
+ nullpo_ret(data);
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
@@ -9384,9 +10149,12 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
}
/* called when a item with combo is removed */
-int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
+static int pc_removecombo(struct map_session_data *sd, struct item_data *data)
+{
int i, retval = 0;
+ nullpo_ret(sd);
+ nullpo_ret(data);
if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
@@ -9429,8 +10197,10 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
return retval;
}
-int pc_load_combo(struct map_session_data *sd) {
+static int pc_load_combo(struct map_session_data *sd)
+{
int i, ret = 0;
+ nullpo_ret(sd);
for( i = 0; i < EQI_MAX; i++ ) {
struct item_data *id = NULL;
int idx = sd->equip_index[i];
@@ -9455,429 +10225,477 @@ int pc_load_combo(struct map_session_data *sd) {
}
/**
-* Equip item at given position.
-* @param sd the affected player structure. Must be checked before.
-* @param id item structure for equip. Must be checked before.
-* @param n inventory item position. Must be checked before.
-* @param pos slot position. Must be checked before.
-**/
-void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int n, int pos)
+ * Equip item at given position.
+ * @param sd the affected player structure. Must be checked before.
+ * @param id item structure for equip. Must be checked before.
+ * @param n inventory item position. Must be checked before.
+ * @param pos slot position. Must be checked before.
+ */
+static void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int n, int pos)
{
+ nullpo_retv(sd);
if ((!map_no_view(sd->bl.m,EQP_SHADOW_WEAPON) && pos & EQP_SHADOW_WEAPON) ||
(pos & EQP_HAND_R)) {
- if(id)
- sd->weapontype1 = id->look;
- else
- sd->weapontype1 = 0;
+ if (id != NULL) {
+ sd->weapontype1 = id->subtype;
+ sd->status.look.weapon = id->view_sprite;
+ } else {
+ sd->weapontype1 = W_FIST;
+ sd->status.look.weapon = 0;
+ }
pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ clif->changelook(&sd->bl, LOOK_WEAPON, sd->status.look.weapon);
}
if ((!map_no_view(sd->bl.m,EQP_SHADOW_SHIELD) && pos & EQP_SHADOW_SHIELD) ||
(pos & EQP_HAND_L)) {
- if (id) {
- if(id->type == IT_WEAPON) {
- sd->status.shield = 0;
- sd->weapontype2 = id->look;
- } else if(id->type == IT_ARMOR) {
- sd->status.shield = id->look;
- sd->weapontype2 = 0;
+ if (id != NULL) {
+ if (id->type == IT_WEAPON) {
+ sd->has_shield = false;
+ sd->status.look.shield = 0;
+ sd->weapontype2 = id->subtype;
+ } else if (id->type == IT_ARMOR) {
+ sd->has_shield = true;
+ sd->status.look.shield = id->view_sprite;
+ sd->weapontype2 = W_FIST;
}
- } else
- sd->status.shield = sd->weapontype2 = 0;
+ } else {
+ sd->has_shield = false;
+ sd->status.look.shield = 0;
+ sd->weapontype2 = W_FIST;
+ }
pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ clif->changelook(&sd->bl, LOOK_SHIELD, sd->status.look.shield);
}
//Added check to prevent sending the same look on multiple slots ->
//causes client to redraw item on top of itself. (suggested by Lupus)
if (!map_no_view(sd->bl.m,EQP_HEAD_LOW) && pos & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID)))
- sd->status.head_bottom = id->look;
+ sd->status.look.head_bottom = id->view_sprite;
else
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ sd->status.look.head_bottom = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_BOTTOM, sd->status.look.head_bottom);
}
if (!map_no_view(sd->bl.m,EQP_HEAD_TOP) && pos & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
if (id)
- sd->status.head_top = id->look;
+ sd->status.look.head_top = id->view_sprite;
else
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ sd->status.look.head_top = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_TOP, sd->status.look.head_top);
}
if (!map_no_view(sd->bl.m,EQP_HEAD_MID) && pos & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
if (id && !(pos&EQP_HEAD_TOP))
- sd->status.head_mid = id->look;
+ sd->status.look.head_mid = id->view_sprite;
else
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ sd->status.look.head_mid = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_MID, sd->status.look.head_mid);
}
if (!map_no_view(sd->bl.m,EQP_COSTUME_HEAD_TOP) && pos & EQP_COSTUME_HEAD_TOP) {
if (id){
- sd->status.head_top = id->look;
+ sd->status.look.head_top = id->view_sprite;
} else
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ sd->status.look.head_top = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_TOP, sd->status.look.head_top);
}
if (!map_no_view(sd->bl.m,EQP_COSTUME_HEAD_MID) && pos & EQP_COSTUME_HEAD_MID) {
if(id && !(pos&EQP_HEAD_TOP)){
- sd->status.head_mid = id->look;
+ sd->status.look.head_mid = id->view_sprite;
} else
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ sd->status.look.head_mid = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_MID, sd->status.look.head_mid);
}
if (!map_no_view(sd->bl.m,EQP_COSTUME_HEAD_LOW) && pos & EQP_COSTUME_HEAD_LOW) {
if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){
- sd->status.head_bottom = id->look;
+ sd->status.look.head_bottom = id->view_sprite;
} else
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ sd->status.look.head_bottom = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_BOTTOM, sd->status.look.head_bottom);
}
if (!map_no_view(sd->bl.m,EQP_SHOES) && pos & EQP_SHOES)
clif->changelook(&sd->bl,LOOK_SHOES,0);
if (!map_no_view(sd->bl.m,EQP_GARMENT) && pos&EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
- sd->status.robe = id ? id->look : 0;
- clif->changelook(&sd->bl, LOOK_ROBE, sd->status.robe);
+ sd->status.look.robe = id ? id->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_ROBE, sd->status.look.robe);
}
if (!map_no_view(sd->bl.m,EQP_COSTUME_GARMENT) && pos & EQP_COSTUME_GARMENT) {
- sd->status.robe = id ? id->look : 0;
- clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
+ sd->status.look.robe = id ? id->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_ROBE, sd->status.look.robe);
}
}
-/*==========================================
- * Equip item on player sd at req_pos from inventory index n
- * Return:
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
-int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
+/**
+ * Attempts to equip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @param req_pos The equipment slot, where the item should be equipped. (See enum equip_pos.)
+ * @return 0 on failure, 1 on success.
+ *
+ **/
+static int pc_equipitem(struct map_session_data *sd, int n, int req_pos)
{
- int i,pos,flag=0,iflag;
- struct item_data *id;
-
nullpo_ret(sd);
- if( n < 0 || n >= MAX_INVENTORY ) {
- clif->equipitemack(sd,0,0,EIA_FAIL);
+ if (n < 0 || n >= sd->status.inventorySize) {
+ clif->equipitemack(sd, 0, 0, EIA_FAIL);
return 0;
}
- if( DIFF_TICK(sd->canequip_tick,timer->gettick()) > 0 )
- {
- clif->equipitemack(sd,n,0,EIA_FAIL);
+ // If the character is in berserk mode, the item can't be equipped.
+ if (sd->sc.count != 0 && (sd->sc.data[SC_BERSERK] != NULL || sd->sc.data[SC_NO_SWITCH_EQUIP] != NULL)) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
}
- id = sd->inventory_data[n];
- pos = pc->equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
+ if (battle_config.battle_log != 0)
+ ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, sd->status.inventory[n].equip,
+ (unsigned int)req_pos);
- if(battle_config.battle_log)
- ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, (unsigned int)(id ? id->equip : 0), (unsigned int)req_pos);
- if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
- // FIXME: pc->isequip: equip level failure uses 2 instead of 0
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ if (DIFF_TICK(sd->canequip_tick, timer->gettick()) > 0) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
}
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])
- {
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ int pos = pc->equippoint(sd, n); // With a few exceptions, item should go in all specified slots.
+
+ if (pc->isequip(sd,n) == 0 || (pos & req_pos) == 0 || sd->status.inventory[n].equip != 0
+ || (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
+ }
+
+ if (sd->inventory_data[n]->flag.bindonequip != 0 && sd->status.inventory[n].bound == 0) {
+ sd->status.inventory[n].bound = IBT_CHARACTER;
+ clif->notify_bounditem(sd, n);
}
- /* won't fail from this point onwards */
- if( id->flag.bindonequip && !sd->status.inventory[n].bound ) {
- sd->status.inventory[n].bound = (unsigned char)IBT_CHARACTER;
- clif->notify_bounditem(sd,n);
- }
-
- if(pos == EQP_ACC) { //Accesories should only go in one of the two,
- pos = req_pos&EQP_ACC;
- if (pos == EQP_ACC) //User specified both slots..
- pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
- } else if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
- pos = (req_pos&EQP_ARMS);
- if (pos == EQP_ARMS) //User specified both slots, pick one for them.
- pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
- } else if(pos == EQP_SHADOW_ACC) { //Accesories should only go in one of the two,
- pos = req_pos&EQP_SHADOW_ACC;
- if (pos == EQP_SHADOW_ACC) //User specified both slots..
- pos = sd->equip_index[EQI_SHADOW_ACC_R] >= 0 ? EQP_SHADOW_ACC_L : EQP_SHADOW_ACC_R;
- } else if( pos == EQP_SHADOW_ARMS && id->equip == EQP_SHADOW_WEAPON) { //Dual wield capable weapon.
- pos = (req_pos&EQP_SHADOW_ARMS);
- if (pos == EQP_SHADOW_ARMS) //User specified both slots, pick one for them.
- pos = sd->equip_index[EQI_SHADOW_WEAPON] >= 0 ? EQP_SHADOW_SHIELD : EQP_SHADOW_WEAPON;
- }
-
- if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) {
- //Update skill-block range database when weapon range changes. [Skotlex]
- i = sd->equip_index[EQI_HAND_R];
- if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped
+ if (pos == EQP_ACC) { // Accesories should only go in one of the two.
+ pos = req_pos & EQP_ACC;
+
+ if (pos == EQP_ACC) // User specified both slots.
+ pos = (sd->equip_index[EQI_ACC_R] >= 0) ? EQP_ACC_L : EQP_ACC_R;
+ } else if (pos == EQP_ARMS && sd->inventory_data[n]->equip == EQP_HAND_R) { // Dual wield capable weapon.
+ pos = req_pos & EQP_ARMS;
+
+ if (pos == EQP_ARMS) // User specified both slots, pick one for them.
+ pos = (sd->equip_index[EQI_HAND_R] >= 0) ? EQP_HAND_L : EQP_HAND_R;
+ } else if (pos == EQP_SHADOW_ACC) { // Accesories should only go in one of the two,
+ pos = req_pos & EQP_SHADOW_ACC;
+
+ if (pos == EQP_SHADOW_ACC) // User specified both slots.
+ pos = (sd->equip_index[EQI_SHADOW_ACC_R] >= 0) ? EQP_SHADOW_ACC_L : EQP_SHADOW_ACC_R;
+ } else if (pos == EQP_SHADOW_ARMS && sd->inventory_data[n]->equip == EQP_SHADOW_WEAPON) { // Dual wield capable weapon.
+ pos = req_pos & EQP_SHADOW_ARMS;
+
+ if (pos == EQP_SHADOW_ARMS) // User specified both slots, pick one for them.
+ pos = (sd->equip_index[EQI_SHADOW_WEAPON] >= 0) ? EQP_SHADOW_SHIELD : EQP_SHADOW_WEAPON;
+ }
+
+ int flag = 0;
+
+ // Update skill-block range database when weapon range changes. [Skotlex]
+ if ((pos & EQP_HAND_R) != 0 && (battle_config.use_weapon_skill_range & BL_PC) != 0) {
+ int idx = sd->equip_index[EQI_HAND_R];
+
+ if (idx < 0 || sd->inventory_data[idx] == NULL) // No data, or no weapon equipped.
flag = 1;
else
- flag = id->range != sd->inventory_data[i]->range;
+ flag = (sd->inventory_data[n]->range != sd->inventory_data[idx]->range) ? 1 : 0;
}
- for(i=0;i<EQI_MAX;i++) {
- if(pos & pc->equip_pos[i]) {
- if(sd->equip_index[i] >= 0) //Slot taken, remove item from there.
+ for (int i = 0; i < EQI_MAX; i++) {
+ if ((pos & pc->equip_pos[i]) != 0) {
+ if (sd->equip_index[i] >= 0) // Slot taken, remove item from there.
pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
sd->equip_index[i] = n;
}
}
- if(pos==EQP_AMMO){
- clif->arrowequip(sd,n);
- clif->arrow_fail(sd,3);
+ if (pos == EQP_AMMO) {
+ clif->arrowequip(sd, n);
+ clif->arrow_fail(sd, 3);
+ } else {
+ clif->equipitemack(sd, n, pos, EIA_SUCCESS);
}
- else
- clif->equipitemack(sd,n,pos,EIA_SUCCESS);
- sd->status.inventory[n].equip=pos;
+ sd->status.inventory[n].equip = pos;
+ pc->equipitem_pos(sd, sd->inventory_data[n], n, pos);
+ pc->checkallowskill(sd); // Check if status changes should be halted.
- pc->equipitem_pos(sd, id, n, pos);
+ int iflag = sd->npc_item_flag;
- pc->checkallowskill(sd); //Check if status changes should be halted.
- iflag = sd->npc_item_flag;
+ // Check for combos. (MUST be done before status->calc_pc()!)
+ if (sd->inventory_data[n]->combos_count != 0)
+ pc->checkcombo(sd, sd->inventory_data[n]);
- /* check for combos (MUST be before status_calc_pc) */
- if( id->combos_count )
- pc->checkcombo(sd,id);
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < id->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ if (!itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int i = 0; i < sd->inventory_data[n]->slot; i++) {
+ if (sd->status.inventory[n].card[i] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if( data->combos_count )
- pc->checkcombo(sd,data);
- }
+
+ struct item_data *data = itemdb->exists(sd->status.inventory[n].card[i]);
+
+ if (data != NULL && data->combos_count != 0)
+ pc->checkcombo(sd, data);
}
}
- status_calc_pc(sd,SCO_NONE);
- if (flag) //Update skill data
+ status_calc_pc(sd, SCO_NONE);
+
+ if (flag != 0) // Update skill data.
clif->skillinfoblock(sd);
+
+ // Execute equip script. [Skotlex]
+ struct item_data *equip_data = sd->inventory_data[n];
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
- //OnEquip script [Skotlex]
- if (id->equip_script)
- script->run_item_equip_script(sd, id, npc->fake_nd->bl.id);
+ if (equip_data->equip_script != NULL) {
+ int idx;
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < id->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_equip_script(sd, equip_data, npc->fake_nd->bl.id);
+ }
+
+ struct item *equip = &sd->status.inventory[n];
+
+ if (!itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if (data->equip_script)
- script->run_item_equip_script(sd, data, npc->fake_nd->bl.id);
+
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->equip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_equip_script(sd, card_data, npc->fake_nd->bl.id);
}
}
}
+
sd->npc_item_flag = iflag;
return 1;
}
/**
-* Unrquip item ad given position.
-* @param sd the affected player structure. Must be checked before.
-* @param n inventory item position. Must be checked before.
-* @param pos slot position. Must be checked before.
-**/
-void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
+ * Unequip an item at the given position.
+ * @param sd the affected player structure. Must be checked before.
+ * @param n inventory item position. Must be checked before.
+ * @param pos slot position. Must be checked before.
+ */
+static void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
{
+ nullpo_retv(sd);
if (pos & EQP_HAND_R) {
- sd->weapontype1 = 0;
- sd->status.weapon = sd->weapontype2;
+ sd->weapontype1 = W_FIST;
pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ sd->status.look.weapon = 0;
+ clif->changelook(&sd->bl, LOOK_WEAPON, sd->status.look.weapon);
if (!battle_config.dancing_weaponswitch_fix)
status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing.
}
if (pos & EQP_HAND_L) {
- sd->status.shield = sd->weapontype2 = 0;
+ sd->has_shield = false;
+ sd->status.look.shield = 0;
+ sd->weapontype2 = W_FIST;
pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ clif->changelook(&sd->bl, LOOK_SHIELD, sd->status.look.shield);
}
if (pos & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ sd->status.look.head_bottom = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_BOTTOM, sd->status.look.head_bottom);
}
if (pos & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ sd->status.look.head_top = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_TOP, sd->status.look.head_top);
}
if (pos & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ sd->status.look.head_mid = 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_MID, sd->status.look.head_mid);
}
if (pos & EQP_COSTUME_HEAD_TOP) {
- sd->status.head_top = ( pc->checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_TOP)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ sd->status.look.head_top = ( pc->checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_TOP)]->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_TOP, sd->status.look.head_top);
}
if (pos & EQP_COSTUME_HEAD_MID) {
- sd->status.head_mid = ( pc->checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_MID)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ sd->status.look.head_mid = ( pc->checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_MID)]->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_MID, sd->status.look.head_mid);
}
if (pos & EQP_COSTUME_HEAD_LOW) {
- sd->status.head_bottom = ( pc->checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_LOW)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ sd->status.look.head_bottom = ( pc->checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_LOW)]->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_HEAD_BOTTOM, sd->status.look.head_bottom);
}
if (pos & EQP_SHOES)
clif->changelook(&sd->bl,LOOK_SHOES,0);
if (pos & EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
- sd->status.robe = 0;
+ sd->status.look.robe = 0;
clif->changelook(&sd->bl, LOOK_ROBE, 0);
}
if (pos & EQP_COSTUME_GARMENT) {
- sd->status.robe = ( pc->checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_GARMENT)]->look : 0;
- clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
+ sd->status.look.robe = ( pc->checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_GARMENT)]->view_sprite : 0;
+ clif->changelook(&sd->bl, LOOK_ROBE, sd->status.look.robe);
}
}
-/*==========================================
- * Called when attemting to unequip an item from player
- * type: @see enum pc_unequipitem_flag
- * Return:
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
-int pc_unequipitem(struct map_session_data *sd,int n,int flag)
+/**
+ * Attempts to unequip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @param flag Modifier for additional actions. (See enum pc_unequipitem_flag.)
+ * @return 0 on failure, 1 on success.
+ *
+ **/
+static int pc_unequipitem(struct map_session_data *sd, int n, int flag)
{
- int i,iflag;
- bool status_cacl = false;
- int pos;
nullpo_ret(sd);
- if( n < 0 || n >= MAX_INVENTORY ) {
- clif->unequipitemack(sd,0,0,UIA_FAIL);
+ if (n < 0 || n >= sd->status.inventorySize) {
+ clif->unequipitemack(sd, 0, 0, UIA_FAIL);
return 0;
}
- // if player is berserk then cannot unequip
- if (!(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) )
- {
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ // If the character is in berserk mode, the item can't be unequipped.
+ if (sd->sc.count != 0 && (sd->sc.data[SC_BERSERK] != NULL || sd->sc.data[SC_NO_SWITCH_EQUIP] != NULL)
+ && (flag & PCUNEQUIPITEM_FORCE) == 0) {
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if( !(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] )
- {
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ if ((flag & PCUNEQUIPITEM_FORCE) == 0 && sd->sc.count != 0 && sd->sc.data[SC_KYOUGAKU] != NULL) {
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if(battle_config.battle_log)
+ if (battle_config.battle_log != 0)
ShowInfo("unequip %d %x:%x\n", n, (unsigned int)(pc->equippoint(sd, n)), sd->status.inventory[n].equip);
- if(!sd->status.inventory[n].equip){ //Nothing to unequip
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ if (sd->status.inventory[n].equip == 0) { // Nothing to unequip.
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- for(i=0;i<EQI_MAX;i++) {
- if(sd->status.inventory[n].equip & pc->equip_pos[i])
+
+ for (int i = 0; i < EQI_MAX; i++) {
+ if ((sd->status.inventory[n].equip & pc->equip_pos[i]) != 0)
sd->equip_index[i] = -1;
}
- pos = sd->status.inventory[n].equip;
- pc->unequipitem_pos(sd, n, pos);
+ int pos = sd->status.inventory[n].equip;
- clif->unequipitemack(sd,n,pos,UIA_SUCCESS);
+ pc->unequipitem_pos(sd, n, pos);
+ clif->unequipitemack(sd, n, pos, UIA_SUCCESS);
- if((pos & EQP_ARMS) &&
- sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
- skill->enchant_elemental_end(&sd->bl,-1);
+ if ((pos & EQP_ARMS) != 0 && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST
+ && (sd->sc.data[SC_TK_SEVENWIND] == NULL || sd->sc.data[SC_ASPERSIO] != NULL)) { // Check for Seven Wind. (But not level seven!)
+ skill->enchant_elemental_end(&sd->bl, -1);
+ }
- if(pos & EQP_ARMOR) {
- // On Armor Change...
+ if ((pos & EQP_ARMOR) != 0) {
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
}
- if( sd->state.autobonus&pos )
- sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
+#ifdef RENEWAL
+ if (battle->bc->bow_unequip_arrow != 0 && (pos & EQP_ARMS) != 0 && sd->equip_index[EQI_AMMO] > 0)
+ pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE);
+#endif
- sd->status.inventory[n].equip=0;
- iflag = sd->npc_item_flag;
+ if ((sd->state.autobonus & pos) != 0) // Check for activated autobonus. [Inkfish]
+ sd->state.autobonus &= ~sd->status.inventory[n].equip;
- /* check for combos (MUST be before status_calc_pc) */
- if ( sd->inventory_data[n] ) {
- if( sd->inventory_data[n]->combos_count ) {
- if( pc->removecombo(sd,sd->inventory_data[n]) )
- status_cacl = true;
- } if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ sd->status.inventory[n].equip = 0;
+
+ bool status_calc = false;
+ int iflag = sd->npc_item_flag;
+
+ // Check for combos. (MUST be done before status->calc_pc()!)
+ if (sd->inventory_data[n] != NULL) {
+ if (sd->inventory_data[n]->combos_count != 0 && pc->removecombo(sd, sd->inventory_data[n]) != 0)
+ status_calc = true;
+
+ if (!itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int i = 0; i < sd->inventory_data[n]->slot; i++) {
+ if (sd->status.inventory[n].card[i] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if( data->combos_count ) {
- if( pc->removecombo(sd,data) )
- status_cacl = true;
- }
- }
+
+ struct item_data *data = itemdb->exists(sd->status.inventory[n].card[i]);
+
+ if (data != NULL && data->combos_count != 0 && pc->removecombo(sd, data) != 0)
+ status_calc = true;
}
}
+
+ // Check item options.
+ for (int i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ if (sd->status.inventory[n].option[i].index <= 0)
+ continue;
+
+ if (itemdb->option_exists(sd->status.inventory[n].option[i].index) == NULL)
+ continue;
+
+ status_calc = true;
+ }
}
- if(flag&PCUNEQUIPITEM_RECALC || status_cacl) {
+ if ((flag & PCUNEQUIPITEM_RECALC) != 0 || status_calc) {
pc->checkallowskill(sd);
- status_calc_pc(sd,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
}
- if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele))
+ if (sd->sc.data[SC_CRUCIS] != NULL && !battle->check_undead(sd->battle_status.race, sd->battle_status.def_ele))
status_change_end(&sd->bl, SC_CRUCIS, INVALID_TIMER);
- //OnUnEquip script [Skotlex]
- if (sd->inventory_data[n]) {
- if (sd->inventory_data[n]->unequip_script) {
- if ( battle_config.unequip_restricted_equipment & 1 ) {
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid);
- if ( i == map->list[sd->bl.m].zone->disabled_items_count )
- script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
- }
- else
- script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
+ // Execute unequip script. [Skotlex]
+ if (sd->inventory_data[n] != NULL) {
+ struct item_data *equip_data = sd->inventory_data[n];
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
+
+ if (equip_data->unequip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_unequip_script(sd, equip_data, npc->fake_nd->bl.id);
}
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+
+ struct item *equip = &sd->status.inventory[n];
+
+ if (!itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if ( data->unequip_script ) {
- if ( battle_config.unequip_restricted_equipment & 2 ) {
- int j;
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]);
- if ( j == map->list[sd->bl.m].zone->disabled_items_count )
- script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
- }
- else
- script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
- }
- }
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->unequip_script != NULL) {
+ int idx;
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_unequip_script(sd, card_data, npc->fake_nd->bl.id);
+ }
}
}
}
+
sd->npc_item_flag = iflag;
return 1;
@@ -9887,105 +10705,114 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
* Checking if player (sd) have unauthorize, invalide item
* on inventory, cart, equiped for the map (item_noequip)
*------------------------------------------*/
-int pc_checkitem(struct map_session_data *sd)
+static int pc_checkitem(struct map_session_data *sd)
{
int i, calc_flag = 0;
nullpo_ret(sd);
- if (sd->state.vending) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
+ if (sd->state.vending == 1) // Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
return 0;
- if (sd->state.itemcheck) { // check for invalid(ated) items
- int id;
- for (i = 0; i < MAX_INVENTORY; i++) {
- id = sd->status.inventory[i].nameid;
+ if (sd->itemcheck != PCCHECKITEM_NONE) { // check for invalid(ated) items
+ int id = 0;
- if (!id)
- continue;
+ if (sd->itemcheck & PCCHECKITEM_INVENTORY) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
+ if ((id = sd->status.inventory[i].nameid) == 0)
+ continue;
- if (!itemdb_available(id)) {
- ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_INV_INVALID);
- continue;
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id);
+ pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_INV_INVALID);
+ continue;
+ }
+
+ if (sd->status.inventory[i].unique_id == 0 && !itemdb->isstackable(id))
+ sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
}
- if (!sd->status.inventory[i].unique_id && !itemdb->isstackable(id))
- sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
+ sd->itemcheck &= ~PCCHECKITEM_INVENTORY;
}
- for( i = 0; i < MAX_CART; i++ ) {
- id = sd->status.cart[i].nameid;
+ if (sd->itemcheck & PCCHECKITEM_CART) {
+ for (i = 0; i < MAX_CART; i++) {
+ if ((id = sd->status.cart[i].nameid) == 0)
+ continue;
- if (!id)
- continue;
+ if( !itemdb_available(id) ) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id);
+ pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_CART_INVALID);
+ continue;
+ }
- if( !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id);
- pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_CART_INVALID);
- continue;
+ if (sd->status.cart[i].unique_id == 0 && !itemdb->isstackable(id))
+ sd->status.cart[i].unique_id = itemdb->unique_id(sd);
}
- if ( !sd->status.cart[i].unique_id && !itemdb->isstackable(id) )
- sd->status.cart[i].unique_id = itemdb->unique_id(sd);
+ sd->itemcheck &= ~PCCHECKITEM_CART;
}
- for( i = 0; i < MAX_STORAGE; i++ ) {
- id = sd->status.storage.items[i].nameid;
+ if (sd->itemcheck & PCCHECKITEM_STORAGE && sd->storage.received == true) {
+ for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) {
+ struct item *it = &VECTOR_INDEX(sd->storage.item, i);
- if (!id)
- continue;
+ if ((id = it->nameid) == 0)
+ continue;
- if( id && !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, sd->status.storage.items[i].amount, sd->status.char_id);
- storage->delitem(sd, i, sd->status.storage.items[i].amount);
- storage->close(sd);
- continue;
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, it->amount, sd->status.char_id);
+ storage->delitem(sd, i, it->amount);
+ continue;
+ }
+
+ if (it->unique_id == 0 && itemdb->isstackable(id) == 0)
+ it->unique_id = itemdb->unique_id(sd);
}
- if ( !sd->status.storage.items[i].unique_id && !itemdb->isstackable(id) )
- sd->status.storage.items[i].unique_id = itemdb->unique_id(sd);
+ storage->close(sd);
+
+ sd->itemcheck &= ~PCCHECKITEM_STORAGE;
}
- if (sd->guild) {
+ if (sd->guild && sd->itemcheck & PCCHECKITEM_GSTORAGE) {
struct guild_storage *guild_storage = idb_get(gstorage->db,sd->guild->guild_id);
if (guild_storage) {
- for( i = 0; i < MAX_GUILD_STORAGE; i++ ) {
- id = guild_storage->items[i].nameid;
-
- if (!id)
+ for (i = 0; i < MAX_GUILD_STORAGE; i++) {
+ if ((id = guild_storage->items[i].nameid) == 0)
continue;
- if( !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from guild storage (amount=%d, char_id=%d, guild_id=%d).\n", id, guild_storage->items[i].amount, sd->status.char_id, sd->guild->guild_id);
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from guild storage (amount=%d, char_id=%d, guild_id=%d).\n", id, guild_storage->items[i].amount, sd->status.char_id, sd->guild->guild_id);
gstorage->delitem(sd, guild_storage, i, guild_storage->items[i].amount);
gstorage->close(sd); // force closing
continue;
}
- if (!guild_storage->items[i].unique_id && !itemdb->isstackable(id))
+ if (guild_storage->items[i].unique_id == 0 && !itemdb->isstackable(id))
guild_storage->items[i].unique_id = itemdb->unique_id(sd);
}
}
+
+ sd->itemcheck &= ~PCCHECKITEM_GSTORAGE;
}
- sd->state.itemcheck = 0;
}
- for( i = 0; i < MAX_INVENTORY; i++) {
+ for (i = 0; i < sd->status.inventorySize; i++) {
- if( sd->status.inventory[i].nameid == 0 )
+ if (sd->status.inventory[i].nameid == 0)
continue;
- if( !sd->status.inventory[i].equip )
+ if (sd->status.inventory[i].equip == 0)
continue;
- if( sd->status.inventory[i].equip&~pc->equippoint(sd,i) ) {
+ if (sd->status.inventory[i].equip & ~pc->equippoint(sd,i)) {
pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
calc_flag = 1;
continue;
}
- if (battle_config.unequip_restricted_equipment&1) {
+ if (battle_config.unequip_restricted_equipment & 1) {
int j;
for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) {
if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid) {
@@ -9995,7 +10822,7 @@ int pc_checkitem(struct map_session_data *sd)
}
}
- if (battle_config.unequip_restricted_equipment&2) {
+ if (battle_config.unequip_restricted_equipment & 2) {
if (!itemdb_isspecial(sd->status.inventory[i].card[0])) {
int j, slot;
for (slot = 0; slot < MAX_SLOTS; slot++) {
@@ -10011,9 +10838,9 @@ int pc_checkitem(struct map_session_data *sd)
}
- if( calc_flag && sd->state.active ) {
+ if (calc_flag != 0 && sd->state.active == 1) {
pc->checkallowskill(sd);
- status_calc_pc(sd,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
}
return 0;
@@ -10022,7 +10849,7 @@ int pc_checkitem(struct map_session_data *sd)
/*==========================================
* Update PVP rank for sd1 in cmp to sd2
*------------------------------------------*/
-int pc_calc_pvprank_sub(struct block_list *bl, va_list ap)
+static int pc_calc_pvprank_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd1 = NULL;
struct map_session_data *sd2 = va_arg(ap,struct map_session_data *);
@@ -10045,9 +10872,11 @@ int pc_calc_pvprank_sub(struct block_list *bl, va_list ap)
* Calculate new rank beetween all present players (map->foreachinarea)
* and display result
*------------------------------------------*/
-int pc_calc_pvprank(struct map_session_data *sd) {
+static int pc_calc_pvprank(struct map_session_data *sd)
+{
int old;
struct map_data *m;
+ nullpo_ret(sd);
m=&map->list[sd->bl.m];
old=sd->pvp_rank;
sd->pvp_rank=1;
@@ -10059,7 +10888,8 @@ int pc_calc_pvprank(struct map_session_data *sd) {
/*==========================================
* Calculate next sd ranking calculation from config
*------------------------------------------*/
-int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd;
sd=map->id2sd(id);
@@ -10083,7 +10913,7 @@ int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
* partner_id = yes
* 0 = no
*------------------------------------------*/
-int pc_ismarried(struct map_session_data *sd)
+static int pc_ismarried(struct map_session_data *sd)
{
if(sd == NULL)
return -1;
@@ -10098,14 +10928,19 @@ int pc_ismarried(struct map_session_data *sd)
* -1 = fail
* 0 = success
*------------------------------------------*/
-int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
+static int pc_marriage(struct map_session_data *sd, struct map_session_data *dstsd)
{
if(sd == NULL || dstsd == NULL ||
sd->status.partner_id > 0 || dstsd->status.partner_id > 0 ||
- (sd->class_&JOBL_BABY) || (dstsd->class_&JOBL_BABY))
+ (sd->job & JOBL_BABY) != 0 || (dstsd->job & JOBL_BABY) != 0)
return -1;
sd->status.partner_id = dstsd->status.char_id;
dstsd->status.partner_id = sd->status.char_id;
+
+ // Achievements [Smokexyz/Hercules]
+ achievement->validate_marry(sd);
+ achievement->validate_marry(dstsd);
+
return 0;
}
@@ -10115,7 +10950,7 @@ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
* -1 = fail
* 0 = success
*------------------------------------------*/
-int pc_divorce(struct map_session_data *sd)
+static int pc_divorce(struct map_session_data *sd)
{
struct map_session_data *p_sd;
int i;
@@ -10137,11 +10972,14 @@ int pc_divorce(struct map_session_data *sd)
// Both players online, lets do the divorce manually
sd->status.partner_id = 0;
p_sd->status.partner_id = 0;
- for( i = 0; i < MAX_INVENTORY; i++ )
+ for (i = 0; i < sd->status.inventorySize; i++)
{
- if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F )
+ if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
- if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F )
+ }
+ for (i = 0; i < p_sd->status.inventorySize; i++)
+ {
+ if (p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
}
@@ -10154,7 +10992,8 @@ int pc_divorce(struct map_session_data *sd)
/*==========================================
* Get sd partner charid. (Married partner)
*------------------------------------------*/
-struct map_session_data *pc_get_partner(struct map_session_data *sd) {
+static struct map_session_data *pc_get_partner(struct map_session_data *sd)
+{
if (sd && pc->ismarried(sd))
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.partner_id);
@@ -10165,8 +11004,9 @@ struct map_session_data *pc_get_partner(struct map_session_data *sd) {
/*==========================================
* Get sd father charid. (Need to be baby)
*------------------------------------------*/
-struct map_session_data *pc_get_father(struct map_session_data *sd) {
- if (sd && sd->class_&JOBL_BABY && sd->status.father > 0)
+static struct map_session_data *pc_get_father(struct map_session_data *sd)
+{
+ if (sd && (sd->job & JOBL_BABY) != 0 && sd->status.father > 0)
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.father);
@@ -10176,8 +11016,9 @@ struct map_session_data *pc_get_father(struct map_session_data *sd) {
/*==========================================
* Get sd mother charid. (Need to be baby)
*------------------------------------------*/
-struct map_session_data *pc_get_mother(struct map_session_data *sd) {
- if (sd && sd->class_&JOBL_BABY && sd->status.mother > 0)
+static struct map_session_data *pc_get_mother(struct map_session_data *sd)
+{
+ if (sd && (sd->job & JOBL_BABY) != 0 && sd->status.mother > 0)
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.mother);
@@ -10187,7 +11028,8 @@ struct map_session_data *pc_get_mother(struct map_session_data *sd) {
/*==========================================
* Get sd children charid. (Need to be married)
*------------------------------------------*/
-struct map_session_data *pc_get_child(struct map_session_data *sd) {
+static struct map_session_data *pc_get_child(struct map_session_data *sd)
+{
if (sd && pc->ismarried(sd) && sd->status.child > 0)
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.child);
@@ -10198,10 +11040,11 @@ struct map_session_data *pc_get_child(struct map_session_data *sd) {
/*==========================================
* Set player sd to bleed. (losing hp and/or sp each diff_tick)
*------------------------------------------*/
-void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
+static void pc_bleeding(struct map_session_data *sd, unsigned int diff_tick)
{
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if( pc_isdead(sd) )
return;
@@ -10232,9 +11075,11 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
//Character regen. Flag is used to know which types of regen can take place.
//&1: HP regen
//&2: SP regen
-void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
+static void pc_regen(struct map_session_data *sd, unsigned int diff_tick)
+{
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if (sd->hp_regen.value) {
sd->hp_regen.tick += diff_tick;
while (sd->hp_regen.tick >= sd->hp_regen.rate) {
@@ -10252,7 +11097,7 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
}
if (hp > 0 || sp > 0)
- status->heal(&sd->bl, hp, sp, 0);
+ status->heal(&sd->bl, hp, sp, STATUS_HEAL_DEFAULT);
return;
}
@@ -10260,7 +11105,8 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
/*==========================================
* Memo player sd savepoint. (map,x,y)
*------------------------------------------*/
-int pc_setsavepoint(struct map_session_data *sd, short map_index, int x, int y) {
+static int pc_setsavepoint(struct map_session_data *sd, short map_index, int x, int y)
+{
nullpo_ret(sd);
sd->status.save_point.map = map_index;
@@ -10273,7 +11119,8 @@ int pc_setsavepoint(struct map_session_data *sd, short map_index, int x, int y)
/*==========================================
* Save 1 player data at autosave intervall
*------------------------------------------*/
-int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
+static int pc_autosave(int tid, int64 tick, int id, intptr_t data)
+{
int interval;
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -10311,9 +11158,11 @@ int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
+static int pc_daynight_timer_sub(struct map_session_data *sd, va_list ap)
+{
+ nullpo_ret(sd);
if (sd->state.night != map->night_flag && map->list[sd->bl.m].flag.nightenabled) { //Night/day state does not match.
- clif->status_change(&sd->bl, SI_SKE, map->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
+ clif->status_change(&sd->bl, status->get_sc_icon(SC_SKE), status->get_sc_relevant_bl_types(SC_SKE), map->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
sd->state.night = map->night_flag;
return 1;
}
@@ -10323,7 +11172,8 @@ int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
* timer to do the day [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
+static int map_day_timer(int tid, int64 tick, int id, intptr_t data)
+{
char tmp_soutput[1024];
if (data == 0 && battle_config.day_duration <= 0) // if we want a day
@@ -10335,7 +11185,7 @@ int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 0; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60), sizeof(tmp_soutput)); // The day has arrived!
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ clif->broadcast(NULL, tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT, ALL_CLIENT);
return 0;
}
@@ -10343,7 +11193,8 @@ int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
* timer to do the night [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
+static int map_night_timer(int tid, int64 tick, int id, intptr_t data)
+{
char tmp_soutput[1024];
if (data == 0 && battle_config.night_duration <= 0) // if we want a night
@@ -10355,27 +11206,35 @@ int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 1; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59), sizeof(tmp_soutput)); // The night has fallen...
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ clif->broadcast(NULL, tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT, ALL_CLIENT);
return 0;
}
-void pc_setstand(struct map_session_data *sd) {
+static void pc_setstand(struct map_session_data *sd)
+{
nullpo_retv(sd);
status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
- clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT);
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT));
//Reset sitting tick.
sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;
- sd->state.dead_sit = sd->vd.dead_sit = 0;
+ if (pc_isdead(sd)) {
+ sd->state.dead_sit = sd->vd.dead_sit = 0;
+ clif->party_dead_notification(sd);
+ } else {
+ sd->state.dead_sit = sd->vd.dead_sit = 0;
+ }
}
/**
* Mechanic (MADO GEAR)
**/
-void pc_overheat(struct map_session_data *sd, int val) {
+static void pc_overheat(struct map_session_data *sd, int val)
+{
int heat = val, skill_lv,
limit[] = { 10, 20, 28, 46, 66 };
+ nullpo_retv(sd);
if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] )
return; // already burning
@@ -10397,10 +11256,11 @@ void pc_overheat(struct map_session_data *sd, int val) {
/**
* Check if player is autolooting given itemID.
*/
-bool pc_isautolooting(struct map_session_data *sd, int nameid)
+static bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
int i = 0;
+ nullpo_ret(sd);
if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
return true;
@@ -10417,7 +11277,8 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid)
* @param sd Player map session data
* @param command Command name with @/# and without params
*/
-bool pc_can_use_command(struct map_session_data *sd, const char *command) {
+static bool pc_can_use_command(struct map_session_data *sd, const char *command)
+{
return atcommand->can_use(sd,command);
}
@@ -10426,7 +11287,7 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) {
*
* @see TimerFunc
*/
-int pc_charm_timer(int tid, int64 tick, int id, intptr_t data)
+static int pc_charm_timer(int tid, int64 tick, int id, intptr_t data)
{
struct map_session_data *sd = map->id2sd(id);
int i;
@@ -10467,7 +11328,7 @@ int pc_charm_timer(int tid, int64 tick, int id, intptr_t data)
* @param max Maximum amount of charms to add.
* @param type Charm type (@see spirit_charm_types)
*/
-void pc_add_charm(struct map_session_data *sd, int interval, int max, int type)
+static void pc_add_charm(struct map_session_data *sd, int interval, int max, enum spirit_charm_types type)
{
int tid, i;
@@ -10509,7 +11370,7 @@ void pc_add_charm(struct map_session_data *sd, int interval, int max, int type)
* @param count Amount of charms to remove.
* @param type Type of charm to remove.
*/
-void pc_del_charm(struct map_session_data *sd, int count, int type)
+static void pc_del_charm(struct map_session_data *sd, int count, enum spirit_charm_types type)
{
int i;
@@ -10556,7 +11417,7 @@ void pc_del_charm(struct map_session_data *sd, int count, int type)
* @param type Modifier type (1=exp 2=itemdrop)
* @return The percent rate modifier (100 = 100%)
*/
-int pc_level_penalty_mod(int diff, unsigned char race, uint32 mode, int type)
+static int pc_level_penalty_mod(int diff, unsigned char race, uint32 mode, int type)
{
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int rate = 100, i;
@@ -10585,61 +11446,10 @@ int pc_level_penalty_mod(int diff, unsigned char race, uint32 mode, int type)
return 100;
#endif
}
-int pc_split_str(char *str,char **val,int num)
-{
- int i;
-
- for (i=0; i<num && str; i++){
- val[i] = str;
- str = strchr(str,',');
- if (str && i<num-1) //Do not remove a trailing comma.
- *str++=0;
- }
- return i;
-}
-int pc_split_atoi(char* str, int* val, char sep, int max)
+static bool pc_read_skill_job_skip(short skill_id, int job_id)
{
- int i,j;
- for (i=0; i<max; i++) {
- if (!str) break;
- val[i] = atoi(str);
- str = strchr(str,sep);
- if (str)
- *str++=0;
- }
- //Zero up the remaining.
- for(j=i; j < max; j++)
- val[j] = 0;
- return i;
-}
-
-int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
-{
- static int warning=0;
- int i,j;
- for (i=0; i<max; i++) {
- double f;
- if (!str) break;
- f = atof(str);
- if (f < 0)
- val[i] = 0;
- else if (f > UINT_MAX) {
- val[i] = UINT_MAX;
- if (!warning) {
- warning = 1;
- ShowWarning("pc_readdb (exp.txt): Required exp per level is capped to %u\n", UINT_MAX);
- }
- } else
- val[i] = (unsigned int)f;
- str = strchr(str,sep);
- if (str)
- *str++=0;
- }
- //Zero up the remaining.
- for(j=i; j < max; j++)
- val[j] = 0;
- return i;
+ return skill_id == NV_TRICKDEAD && ((pc->jobid2mapid(job_id) & (MAPID_BASEMASK | JOBL_2)) != MAPID_NOVICE); // skip trickdead for non-novices
}
/**
@@ -10655,7 +11465,7 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
*
* @author [Ind/Hercules]
*/
-void pc_read_skill_tree(void)
+static void pc_read_skill_tree(void)
{
struct config_t skill_tree_conf;
struct config_setting_t *skt = NULL;
@@ -10722,8 +11532,8 @@ void pc_read_skill_tree(void)
ShowWarning("pc_read_skill_tree: '%s' can't inherit '%s', skill tree is full!\n", job_name, ijob_name);
break;
}
- if (src->id == NV_TRICKDEAD && ((pc->jobid2mapid(job_id)&(MAPID_BASEMASK | JOBL_2)) != MAPID_NOVICE))
- continue; // skip trickdead for non-novices
+ if (pc->read_skill_job_skip(src->id, job_id))
+ continue;
dst = &pc->skill_tree[job_idx][cur];
dst->inherited = 1;
if (dst->id == 0) {
@@ -10852,7 +11662,7 @@ void pc_read_skill_tree(void)
/**
* Clears the skill tree and frees any allocated memory.
*/
-void pc_clear_skill_tree(void)
+static void pc_clear_skill_tree(void)
{
int i;
for (i = 0; i < CLASS_COUNT; i++) {
@@ -10866,10 +11676,12 @@ void pc_clear_skill_tree(void)
memset(pc->skill_tree, 0, sizeof(pc->skill_tree));
}
-bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
+static bool pc_readdb_levelpenalty(char *fields[], int columns, int current)
+{
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int type, race, diff;
+ nullpo_retr(false, fields);
type = atoi(fields[0]);
race = atoi(fields[1]);
diff = atoi(fields[2]);
@@ -10894,93 +11706,131 @@ bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
return true;
}
-/*==========================================
- * pc DB reading.
- * exp.txt - required experience values
- * skill_tree.txt - skill tree for every class
- * attr_fix.txt - elemental adjustment table
- *------------------------------------------*/
-int pc_readdb(void) {
- int i,j,k;
- unsigned int count = 0;
- FILE *fp;
- char line[24000],*p;
+static bool pc_read_exp_db_sub_class(struct config_setting_t *t, bool base)
+{
+ struct class_exp_group entry = { { 0 } };
+ struct config_setting_t *exp_t = NULL;
+ int maxlv = 0;
- //reset
- memset(pc->exp_table,0,sizeof(pc->exp_table));
- memset(pc->max_level,0,sizeof(pc->max_level));
+ nullpo_retr(false, t);
- sprintf(line, "%s/"DBPATH"exp.txt", map->db_path);
+ safestrncpy(entry.name, config_setting_name(t), SCRIPT_VARNAME_LENGTH);
- fp=fopen(line, "r");
- if(fp==NULL){
- ShowError("can't read %s\n", line);
- return 1;
+ if (libconfig->setting_lookup_int(t, "MaxLevel", &maxlv) == 0
+ || (maxlv <= 0 || maxlv > MAX_LEVEL)) {
+ ShowError("pc_read_exp_db_sub_class: Invalid max %s level '%d' set for entry '%s'. Defaulting to %d...", base ? "base" : "job", maxlv, entry.name, MAX_LEVEL);
+ maxlv = MAX_LEVEL;
}
- while(fgets(line, sizeof(line), fp)) {
- int jobs[CLASS_COUNT], job_count, job, job_id;
- int type;
- unsigned int ui,maxlv;
- char *split[4];
- if(line[0]=='/' && line[1]=='/')
- continue;
- if (pc_split_str(line,split,4) < 4)
- continue;
- job_count = pc_split_atoi(split[1],jobs,':',CLASS_COUNT);
- if (job_count < 1)
- continue;
- job_id = jobs[0];
- if (!pc->db_checkid(job_id)) {
- ShowError("pc_readdb: Invalid job ID %d.\n", job_id);
- continue;
- }
- type = atoi(split[2]);
- if (type < 0 || type > 1) {
- ShowError("pc_readdb: Invalid type %d (must be 0 for base levels, 1 for job levels).\n", type);
- continue;
- }
- maxlv = atoi(split[0]);
- if (maxlv > MAX_LEVEL) {
- ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%d).\n ", maxlv, job_id, MAX_LEVEL);
- maxlv = MAX_LEVEL;
+ entry.max_level = maxlv;
+
+ if ((exp_t = libconfig->setting_lookup(t, "Exp")) != NULL && config_setting_is_array(exp_t)) {
+ int j = 0;
+
+ VECTOR_ENSURE(entry.exp, maxlv - 2, 10);
+
+ if (libconfig->setting_length(exp_t) > maxlv - 1) {
+ ShowWarning("pc_read_exp_db_sub_class: Exp table length (%d) for %s exp group '%s' exceeds specified max level %d. Skipping remaining entries...\n", libconfig->setting_length(exp_t), base ? "base" : "job", entry.name, maxlv);
}
- count++;
- job = jobs[0] = pc->class2idx(job_id);
- //We send one less and then one more because the last entry in the exp array should hold 0.
- pc->max_level[job][type] = pc_split_atoui(split[3], pc->exp_table[job][type],',',maxlv-1)+1;
- //Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
- //The reasoning behind the -2 is this... if the max level is 5, then the array
- //should look like this:
- //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
- while ((ui = pc->max_level[job][type]) >= 2 && pc->exp_table[job][type][ui-2] <= 0)
- pc->max_level[job][type]--;
- if (pc->max_level[job][type] < maxlv) {
- ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, pc->max_level[job][type]);
+
+ while (j < libconfig->setting_length(exp_t) && j <= maxlv - 2)
+ VECTOR_PUSH(entry.exp, libconfig->setting_get_int64_elem(exp_t, j++));
+
+ if (j - 1 < maxlv - 2) {
+ ShowError("pc_read_exp_db_sub_class: Specified max %d for group '%s', but that group's %s exp table only goes up to level %d.\n", maxlv, entry.name, base ? "base" : "job", VECTOR_LENGTH(entry.exp));
ShowInfo("Filling the missing values with the last exp entry.\n");
- //Fill the requested values with the last entry.
- ui = (pc->max_level[job][type] <= 2? 0: pc->max_level[job][type]-2);
- for (; ui+2 < maxlv; ui++)
- pc->exp_table[job][type][ui] = pc->exp_table[job][type][ui-1];
- pc->max_level[job][type] = maxlv;
- }
- //ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
- for (i = 1; i < job_count; i++) {
- job_id = jobs[i];
- if (!pc->db_checkid(job_id)) {
- ShowError("pc_readdb: Invalid job ID %d.\n", job_id);
- continue;
- }
- job = pc->class2idx(job_id);
- memcpy(pc->exp_table[job][type], pc->exp_table[jobs[0]][type], sizeof(pc->exp_table[0][0]));
- pc->max_level[job][type] = maxlv;
- //ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
+ while (j++ <= maxlv - 2)
+ VECTOR_PUSH(entry.exp, VECTOR_LAST(entry.exp));
}
+ } else {
+ ShowError("pc_read_exp_db_sub_class: Invalid or non-existent 'Exp' field set for %s level entry '%s'. Skipping...\n", entry.name, base ? "base" : "job");
+ return false;
}
- fclose(fp);
- pc->validate_levels();
- ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,map->db_path,"exp.txt");
- count = 0;
+
+ VECTOR_ENSURE(pc->class_exp_groups[base ? CLASS_EXP_TABLE_BASE : CLASS_EXP_TABLE_JOB], 1, 1);
+ VECTOR_PUSH(pc->class_exp_groups[base ? CLASS_EXP_TABLE_BASE : CLASS_EXP_TABLE_JOB], entry);
+ return true;
+}
+
+/**
+ * Description: Helper function to read a root configuration in the exp_group_db.conf file.
+ * @param[in] t pointer to the root config setting
+ * @param[in] base boolean switch determining whether to read either base or job exp.
+ * @return total number of valid entries read from the setting.
+ */
+static int pc_read_exp_db_sub(struct config_setting_t *t, bool base)
+{
+ int i = 0, entry_count = 0;
+ struct config_setting_t *tt = NULL;
+
+ nullpo_ret(t);
+
+ while ((tt = libconfig->setting_get_elem(t, i++)) != NULL) {
+ pc->read_exp_db_sub_class(tt, base);
+ entry_count++;
+ }
+
+ return entry_count;
+}
+
+/**
+ * Description: Initiates reading of the exp_group_db.conf.
+ * @return true success, false on failure.
+ */
+static bool pc_read_exp_db(void)
+{
+ struct config_t exp_db_conf;
+ struct config_setting_t *edb = NULL;
+ int entry_count = 0;
+ char config_filename[256];
+
+ libconfig->format_db_path(DBPATH"exp_group_db.conf", config_filename, sizeof(config_filename));
+
+ if (!libconfig->load_file(&exp_db_conf, config_filename))
+ return false;
+
+ if ((edb = libconfig->setting_lookup(exp_db_conf.root, "base_exp_group_db")) != NULL) {
+ entry_count += pc->read_exp_db_sub(edb, true);
+ } else {
+ ShowError("pc_read_exp_db: Error reading base exp group db in '%s'.\n", config_filename);
+ libconfig->destroy(&exp_db_conf);
+ return false;
+ }
+
+ if ((edb = libconfig->setting_lookup(exp_db_conf.root, "job_exp_group_db")) != NULL) {
+ entry_count += pc->read_exp_db_sub(edb, false);
+ } else {
+ ShowError("pc_read_exp_db: Error reading job exp group db in '%s'.\n", config_filename);
+ libconfig->destroy(&exp_db_conf);
+ return false;
+ }
+
+ libconfig->destroy(&exp_db_conf);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entry_count, config_filename);
+
+ return true;
+}
+
+/*==========================================
+ * PC DB reading.
+ * exp_group_db.conf - required experience values
+ * skill_tree.txt - skill tree for every class
+ * attr_fix.txt - elemental adjustment table
+ *------------------------------------------*/
+static int pc_readdb(void)
+{
+ int i,j,k;
+ unsigned int count = 0;
+ FILE *fp;
+ char line[24000],*p;
+
+ /**
+ * Read and load into memory, the exp_group_db.conf file.
+ */
+ pc->clear_exp_groups();
+ pc->read_exp_db();
+
// Reset and read skilltree
pc->clear_skill_tree();
pc->read_skill_tree();
@@ -11014,18 +11864,18 @@ int pc_readdb(void) {
ShowError("can't read %s\n", line);
return 1;
}
- while(fgets(line, sizeof(line), fp))
- {
+ while (fgets(line, sizeof(line), fp)) {
char *split[10];
int lv,n;
- if(line[0]=='/' && line[1]=='/')
+ if (line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<3 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
+ for (j = 0, p = line; j < 3 && p != NULL; j++) {
+ split[j] = p;
+ p = strchr(p,',');
+ if (p != NULL)
+ *p++ = 0;
}
- if( j < 2 )
+ if (j < 2)
continue;
lv=atoi(split[0]);
@@ -11037,8 +11887,8 @@ int pc_readdb(void) {
if(line[0]=='/' && line[1]=='/')
continue;
- for ( j = ELE_NEUTRAL, p = line; j<n && j<ELE_MAX && p; j++ ) {
- while(*p==32 && *p>0)
+ for (j = ELE_NEUTRAL, p = line; j < n && j < ELE_MAX && p != NULL; j++) {
+ while (*p == ' ')
p++;
battle->attr_fix_table[lv-1][i][j]=atoi(p);
#ifndef RENEWAL
@@ -11046,7 +11896,8 @@ int pc_readdb(void) {
battle->attr_fix_table[lv-1][i][j] = 0;
#endif
p=strchr(p,',');
- if(p) *p++=0;
+ if (p != NULL)
+ *p++ = 0;
}
i++;
@@ -11093,25 +11944,41 @@ int pc_readdb(void) {
return 0;
}
-void pc_validate_levels(void) {
+static bool pc_job_is_dummy(int job)
+{
+ if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2
+ || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER
+ || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2
+ || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2
+ || job == JOB_STAR_GLADIATOR2
+ || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2)
+ || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2))
+ return true;
+ return false;
+}
+
+static void pc_validate_levels(void)
+{
int i;
int j;
for (i = 0; i < JOB_MAX; i++) {
if (!pc->db_checkid(i)) continue;
- if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER)
+ if (pc->job_is_dummy(i))
continue; //Classes that do not need exp tables.
j = pc->class2idx(i);
- if (!pc->max_level[j][0])
- ShowWarning("Class %s (%d) does not has a base exp table.\n", pc->job_name(i), i);
- if (!pc->max_level[j][1])
- ShowWarning("Class %s (%d) does not has a job exp table.\n", pc->job_name(i), i);
+ if (pc->dbs->class_exp_table[j][CLASS_EXP_TABLE_BASE] == NULL)
+ ShowWarning("Class %s (%d - %d) does not have a base exp table.\n", pc->job_name(i), i, j);
+ if (pc->dbs->class_exp_table[j][CLASS_EXP_TABLE_JOB] == NULL)
+ ShowWarning("Class %s (%d - %d) does not have a job exp table.\n", pc->job_name(i), i, j);
}
}
-void pc_itemcd_do(struct map_session_data *sd, bool load) {
+static void pc_itemcd_do(struct map_session_data *sd, bool load)
+{
int i,cursor = 0;
struct item_cd* cd = NULL;
+ nullpo_retv(sd);
if( load ) {
if( !(cd = idb_get(pc->itemcd_db, sd->status.char_id)) ) {
// no skill cooldown is associated with this character
@@ -11142,8 +12009,12 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
return;
}
-void pc_bank_deposit(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.bank_vault;
+static void pc_bank_deposit(struct map_session_data *sd, int money)
+{
+ unsigned int limit_check;
+
+ nullpo_retv(sd);
+ limit_check = money + sd->status.bank_vault;
if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
clif->bank_deposit(sd,BDA_OVERFLOW);
@@ -11162,9 +12033,12 @@ void pc_bank_deposit(struct map_session_data *sd, int money) {
clif->bank_deposit(sd,BDA_SUCCESS);
}
}
-void pc_bank_withdraw(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.zeny;
+static void pc_bank_withdraw(struct map_session_data *sd, int money)
+{
+ unsigned int limit_check;
+ nullpo_retv(sd);
+ limit_check = money + sd->status.zeny;
if (money <= 0) {
clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
return;
@@ -11187,7 +12061,9 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) {
}
}
/* status change data arrived from char-server */
-void pc_scdata_received(struct map_session_data *sd) {
+static void pc_scdata_received(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
pc->inventory_rentals(sd);
clif->show_modifiers(sd);
@@ -11195,7 +12071,7 @@ void pc_scdata_received(struct map_session_data *sd) {
time_t exp_time = sd->expiration_time;
char tmpstr[1024];
strftime(tmpstr, sizeof(tmpstr) - 1, msg_sd(sd,501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
- clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1);
+ clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, (int)strlen(tmpstr));
pc->expire_check(sd);
}
@@ -11206,7 +12082,8 @@ void pc_scdata_received(struct map_session_data *sd) {
pc->autotrade_start(sd);
}
}
-int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
if( !sd ) return 0;
@@ -11222,7 +12099,8 @@ int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
}
/* This timer exists only when a character with an expire timer > 24h is online */
/* It loops through online players once an hour to check whether a new < 24h is available */
-int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -11235,7 +12113,9 @@ 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) {
+static void pc_expire_check(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
/* ongoing timer */
if( sd->expiration_tid != INVALID_TIMER )
return;
@@ -11255,7 +12135,7 @@ void pc_expire_check(struct map_session_data *sd) {
/**
* Loads autotraders
***/
-void pc_autotrade_load(void)
+static void pc_autotrade_load(void)
{
char *data;
@@ -11288,11 +12168,13 @@ void pc_autotrade_load(void)
/**
* Loads vending data and sets it up, is triggered when char server data that pc_autotrade_load requested arrives
**/
-void pc_autotrade_start(struct map_session_data *sd) {
+static void pc_autotrade_start(struct map_session_data *sd)
+{
unsigned int count = 0;
int i;
char *data;
+ nullpo_retv(sd);
if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `itemkey`,`amount`,`price` FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
Sql_ShowDebug(map->mysql_handle);
@@ -11334,9 +12216,11 @@ void pc_autotrade_start(struct map_session_data *sd) {
/**
* Perform a autotrade action
**/
-void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) {
+static void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action)
+{
int i;
+ nullpo_retv(sd);
/* either way, this goes down */
if( action != PAUC_START ) {
if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
@@ -11362,7 +12246,7 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update
))
Sql_ShowDebug(map->mysql_handle);
}
- /* yes we want it to fall */
+ FALLTHROUGH
case PAUC_REFRESH:
for( i = 0; i < sd->vend_num; i++ ) {
if( sd->vending[i].amount == 0 )
@@ -11383,13 +12267,15 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update
/**
* Handles characters upon @autotrade usage
**/
-void pc_autotrade_prepare(struct map_session_data *sd) {
+static void pc_autotrade_prepare(struct map_session_data *sd)
+{
struct autotrade_vending *data;
int i, cursor = 0;
int account_id, char_id;
char title[MESSAGE_SIZE];
unsigned char sex;
+ nullpo_retv(sd);
CREATE(data, struct autotrade_vending, 1);
memcpy(data->vending, sd->vending, sizeof(sd->vending));
@@ -11432,10 +12318,12 @@ void pc_autotrade_prepare(struct map_session_data *sd) {
/**
* Prepares autotrade data from pc->at_db from a player that has already returned from char server
**/
-void pc_autotrade_populate(struct map_session_data *sd) {
+static void pc_autotrade_populate(struct map_session_data *sd)
+{
struct autotrade_vending *data;
int i, j, k, cursor = 0;
+ nullpo_retv(sd);
if( !(data = idb_get(pc->at_db,sd->status.char_id)) )
return;
@@ -11475,14 +12363,15 @@ void pc_autotrade_populate(struct map_session_data *sd) {
/**
* @see DBApply
*/
-int pc_autotrade_final(union DBKey key, struct DBData *data, va_list ap)
+static int pc_autotrade_final(union DBKey key, struct DBData *data, va_list ap)
{
struct autotrade_vending* at_v = DB->data2ptr(data);
+ nullpo_ret(at_v);
HPM->data_store_destroy(&at_v->hdata);
return 0;
}
-void pc_update_idle_time(struct map_session_data* sd, enum e_battle_config_idletime type)
+static void pc_update_idle_time(struct map_session_data *sd, enum e_battle_config_idletime type)
{
nullpo_retv(sd);
if (battle_config.idletime_criteria&type)
@@ -11490,16 +12379,17 @@ void pc_update_idle_time(struct map_session_data* sd, enum e_battle_config_idlet
}
//Checks if the given class value corresponds to a player class. [Skotlex]
-//JOB_NOVICE isn't checked for class_ is supposed to be unsigned
-bool pc_db_checkid(unsigned int class_)
+//JOB_NOVICE isn't checked for class is supposed to be unsigned
+static bool pc_db_checkid(int class)
{
- return class_ < JOB_MAX_BASIC
- || (class_ >= JOB_NOVICE_HIGH && class_ <= JOB_DARK_COLLECTOR )
- || (class_ >= JOB_RUNE_KNIGHT && class_ <= JOB_MECHANIC_T2 )
- || (class_ >= JOB_BABY_RUNE && class_ <= JOB_BABY_MECHANIC2 )
- || (class_ >= JOB_SUPER_NOVICE_E && class_ <= JOB_SUPER_BABY_E )
- || (class_ >= JOB_KAGEROU && class_ <= JOB_OBORO )
- || (class_ >= JOB_REBELLION && class_ < JOB_MAX );
+ return class < JOB_MAX_BASIC
+ || (class >= JOB_NOVICE_HIGH && class <= JOB_DARK_COLLECTOR )
+ || (class >= JOB_RUNE_KNIGHT && class <= JOB_MECHANIC_T2 )
+ || (class >= JOB_BABY_RUNE && class <= JOB_BABY_MECHANIC2 )
+ || (class >= JOB_SUPER_NOVICE_E && class <= JOB_SUPER_BABY_E )
+ || (class >= JOB_KAGEROU && class <= JOB_OBORO )
+ || (class == JOB_REBELLION)
+ || (class >= JOB_SUMMONER && class < JOB_MAX );
}
/**
@@ -11507,16 +12397,266 @@ bool pc_db_checkid(unsigned int class_)
* @param sd map_session_data of Player
* @return index of magnifer, INDEX_NOT_FOUND if it is not found
*/
-int pc_have_magnifier(struct map_session_data *sd)
+static int pc_have_magnifier(struct map_session_data *sd)
{
int n;
- n = pc->search_inventory(sd, ITEMID_MAGNIFIER);
+ n = pc->search_inventory(sd, ITEMID_SPECTACLES);
if (n == INDEX_NOT_FOUND)
- n = pc->search_inventory(sd, ITEMID_NOVICE_MAGNIFIER);
+ n = pc->search_inventory(sd, ITEMID_N_MAGNIFIER);
return n;
}
-void do_final_pc(void) {
+/**
+ * checks if player have any item that listed in item chain
+ * @param sd map_session_data of Player
+ * @param chain_cache_id cache id of item chain
+ * @return index of inventory, INDEX_NOT_FOUND if it is not found
+ */
+static int pc_have_item_chain(struct map_session_data *sd, enum e_chain_cache chain_cache_id)
+{
+ nullpo_retr(INDEX_NOT_FOUND, sd);
+ Assert_retr(INDEX_NOT_FOUND, chain_cache_id >= ECC_ORE && chain_cache_id < ECC_MAX);
+
+ int chain_id = itemdb->chain_cache[chain_cache_id];
+
+ for (int n = 0; n < itemdb->chains[chain_id].qty; n++) {
+ struct item_chain_entry *entry = &itemdb->chains[chain_id].items[n];
+ int index = pc->search_inventory(sd, entry->id);
+ if (index != INDEX_NOT_FOUND)
+ return index;
+ }
+
+ return INDEX_NOT_FOUND;
+}
+
+/**
+ * Checks if player have basic skills learned.
+ * @param sd Player Data
+ * @param level Required Level of Novice Skill
+ * @return bool true, if requirement is satisfied
+ */
+static bool pc_check_basicskill(struct map_session_data *sd, int level)
+{
+ if (pc->checkskill(sd, NV_BASIC) >= level || pc->checkskill(sd, SU_BASIC_SKILL))
+ return true;
+ return false;
+}
+
+/**
+ * Verifies a chat message, searching for atcommands, checking if the sender
+ * character can chat, and updating the idle timer.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ * @return Whether the message is a valid chat message.
+ */
+static bool pc_process_chat_message(struct map_session_data *sd, const char *message)
+{
+ nullpo_retr(false, sd);
+ if (atcommand->exec(sd->fd, sd, message, true)) {
+ return false;
+ }
+
+ if (!pc->can_talk(sd)) {
+ return false;
+ }
+
+ if (battle_config.min_chat_delay != 0) {
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
+ return false;
+ }
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
+ }
+
+ pc->update_idle_time(sd, BCIDLE_CHAT);
+
+ return true;
+}
+
+/**
+ * Checks a chat message, scanning for the Super Novice prayer sequence.
+ *
+ * If a match is found, the angel is invoked or the counter is incremented as
+ * appropriate.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ */
+static void pc_check_supernovice_call(struct map_session_data *sd, const char *message)
+{
+ uint64 next = pc->nextbaseexp(sd);
+ int percent = 0;
+
+ nullpo_retv(sd);
+ nullpo_retv(message);
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
+ return;
+ if (next == 0)
+ next = pc->thisbaseexp(sd);
+ if (next == 0)
+ return;
+
+ // 0%, 10%, 20%, ...
+ percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
+ if ((battle_config.snovice_call_type != 0 || percent != 0) && (percent%100) == 0) {
+ // 10.0%, 20.0%, ..., 90.0%
+ switch (sd->state.snovice_call_flag) {
+ case 0:
+ if (strstr(message, msg_txt(1479))) // "Dear angel, can you hear my voice?"
+ sd->state.snovice_call_flag = 1;
+ break;
+ case 1:
+ {
+ char buf[256];
+ snprintf(buf, 256, msg_txt(1480), sd->status.name);
+ if (strstr(message, buf)) // "I am %s Super Novice~"
+ sd->state.snovice_call_flag = 2;
+ }
+ break;
+ case 2:
+ if (strstr(message, msg_txt(1481))) // "Help me out~ Please~ T_T"
+ sd->state.snovice_call_flag = 3;
+ break;
+ case 3:
+ sc_start(NULL, &sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
+ sd->state.snovice_call_flag = 0;
+ break;
+ }
+ }
+}
+
+/**
+ * Sends a message t all online GMs having the specified permission.
+ *
+ * @param sender_name Sender character name.
+ * @param permission The required permission to receive this message.
+ * @param message The message body.
+ *
+ * @return The amount of characters the message was delivered to.
+ */
+// The transmission of GM only Wisp/Page from server to inter-server
+static int pc_wis_message_to_gm(const char *sender_name, int permission, const char *message)
+{
+ nullpo_ret(sender_name);
+ nullpo_ret(message);
+ int mes_len = (int)strlen(message) + 1; // + null
+ int count = 0;
+
+ // information is sent to all online GM
+ map->foreachpc(pc->wis_message_to_gm_sub, permission, sender_name, message, mes_len, &count);
+
+ return count;
+}
+
+/**
+ * Helper function for pc_wis_message_to_gm().
+ */
+static int pc_wis_message_to_gm_sub(struct map_session_data *sd, va_list va)
+{
+ nullpo_ret(sd);
+
+ int permission = va_arg(va, int);
+ if (!pc_has_permission(sd, permission))
+ return 0;
+
+ const char *sender_name = va_arg(va, const char *);
+ const char *message = va_arg(va, const char *);
+ int len = va_arg(va, int);
+ int *count = va_arg(va, int *);
+
+ nullpo_ret(sender_name);
+ nullpo_ret(message);
+ nullpo_ret(count);
+
+ clif->wis_message(sd->fd, sender_name, message, len);
+ ++*count;
+ return 1;
+}
+
+static void pc_update_job_and_level(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ if (sd->status.party_id) {
+ struct party_data *p;
+ int i;
+
+ if ((p = party->search(sd->status.party_id)) != NULL) {
+ ARR_FIND(0, MAX_PARTY, i, p->party.member[i].char_id == sd->status.char_id);
+ if (i < MAX_PARTY) {
+ p->party.member[i].lv = sd->status.base_level;
+ clif->party_job_and_level(sd);
+ }
+ }
+ }
+}
+
+static void pc_clear_exp_groups(void)
+{
+ int i, k, size;
+ for (k = 0; k < 2; k++) {
+ size = VECTOR_LENGTH(pc->class_exp_groups[k]);
+
+ for (i = 0; i < size; i++)
+ VECTOR_CLEAR(VECTOR_INDEX(pc->class_exp_groups[k], i).exp);
+ VECTOR_CLEAR(pc->class_exp_groups[k]);
+ }
+}
+
+static void pc_init_exp_groups(void)
+{
+ int i;
+ for (i = 0; i < 2; i++) {
+ VECTOR_INIT(pc->class_exp_groups[i]);
+ }
+}
+
+static bool pc_has_second_costume(struct map_session_data *sd)
+{
+ nullpo_retr(false, sd);
+
+// FIXME: JOB_SUPER_NOVICE_E(4190) is not supposed to be 3rd Job. (Issue#2383)
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & MAPID_BASEMASK) != MAPID_NOVICE)
+ return true;
+ return false;
+}
+
+static bool pc_expandInventory(struct map_session_data *sd, int adjustSize)
+{
+ nullpo_retr(false, sd);
+ const int invSize = sd->status.inventorySize;
+ if (adjustSize > MAX_INVENTORY || invSize + adjustSize <= FIXED_INVENTORY_SIZE || invSize + adjustSize > MAX_INVENTORY) {
+ clif->inventoryExpandResult(sd, EXPAND_INVENTORY_RESULT_MAX_SIZE);
+ return false;
+ }
+ if (pc_isdead(sd) || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->chat_id != 0 || sd->state.trading || sd->state.storage_flag || sd->state.prevend) {
+ clif->inventoryExpandResult(sd, EXPAND_INVENTORY_RESULT_OTHER_WORK);
+ return false;
+ }
+ sd->status.inventorySize += adjustSize;
+ clif->inventoryExpansionInfo(sd);
+ return true;
+}
+
+static bool pc_auto_exp_insurance(struct map_session_data *sd)
+{
+ nullpo_retr(false, sd);
+
+ int item_position = pc->have_item_chain(sd, ECC_NEO_INSURANCE);
+ if (item_position == INDEX_NOT_FOUND)
+ return false;
+
+ pc->delitem(sd, item_position, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME);
+#if PACKETVER >= 20100914
+ clif->msgtable(sd, MSG_NOTIFY_NEO_INSURANCE_ITEM_USE);
+#endif
+ return true;
+}
+
+static void do_final_pc(void)
+{
+
db_destroy(pc->itemcd_db);
pc->at_db->destroy(pc->at_db,pc->autotrade_final);
@@ -11524,6 +12664,8 @@ void do_final_pc(void) {
pc->clear_skill_tree();
+ pc->clear_exp_groups();
+
ers_destroy(pc->sc_display_ers);
ers_destroy(pc->num_reg_ers);
ers_destroy(pc->str_reg_ers);
@@ -11531,13 +12673,15 @@ void do_final_pc(void) {
return;
}
-void do_init_pc(bool minimal) {
+static void do_init_pc(bool minimal)
+{
if (minimal)
return;
pc->itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
pc->at_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ pc->init_exp_groups();
pc->readdb();
timer->add_func_list(pc->invincible_timer, "pc_invincible_timer");
@@ -11578,12 +12722,14 @@ void do_init_pc(bool minimal) {
ers_chunk_size(pc->num_reg_ers, 300);
ers_chunk_size(pc->str_reg_ers, 50);
}
+
/*=====================================
-* Default Functions : pc.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void pc_defaults(void) {
+ * Default Functions : pc.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void pc_defaults(void)
+{
const struct sg_data sg_info[MAX_PC_FEELHATE] = {
{ SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun },
{ SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
@@ -11592,6 +12738,7 @@ void pc_defaults(void) {
unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO, EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L };
pc = &pc_s;
+ pc->dbs = &exptables;
/* vars */
pc->at_db = NULL;
@@ -11637,6 +12784,7 @@ void pc_defaults(void) {
pc->isequip = pc_isequip;
pc->equippoint = pc_equippoint;
+ pc->item_equippoint = pc_item_equippoint;
pc->setinventorydata = pc_setinventorydata;
pc->checkskill = pc_checkskill;
@@ -11645,6 +12793,8 @@ void pc_defaults(void) {
pc->checkequip = pc_checkequip;
pc->calc_skilltree = pc_calc_skilltree;
+ pc->calc_skilltree_bonus = pc_calc_skilltree_bonus;
+ pc->calc_skilltree_clear = pc_calc_skilltree_clear;
pc->calc_skilltree_normalize_job = pc_calc_skilltree_normalize_job;
pc->clean_skilltree = pc_clean_skilltree;
@@ -11707,6 +12857,7 @@ void pc_defaults(void) {
pc->maxbaselv = pc_maxbaselv;
pc->maxjoblv = pc_maxjoblv;
pc->checkbaselevelup = pc_checkbaselevelup;
+ pc->checkbaselevelup_sc = pc_checkbaselevelup_sc;
pc->checkjoblevelup = pc_checkjoblevelup;
pc->gainexp = pc_gainexp;
pc->nextbaseexp = pc_nextbaseexp;
@@ -11723,6 +12874,7 @@ void pc_defaults(void) {
pc->resetlvl = pc_resetlvl;
pc->resetstate = pc_resetstate;
pc->resetskill = pc_resetskill;
+ pc->resetskill_job = pc_resetskill_job;
pc->resetfeel = pc_resetfeel;
pc->resethate = pc_resethate;
pc->equipitem = pc_equipitem;
@@ -11731,6 +12883,7 @@ void pc_defaults(void) {
pc->unequipitem_pos = pc_unequipitem_pos;
pc->checkitem = pc_checkitem;
pc->useitem = pc_useitem;
+ pc->autocast_clear = pc_autocast_clear;
pc->skillatk_bonus = pc_skillatk_bonus;
pc->skillheal_bonus = pc_skillheal_bonus;
@@ -11743,6 +12896,8 @@ void pc_defaults(void) {
pc->itemheal = pc_itemheal;
pc->percentheal = pc_percentheal;
pc->jobchange = pc_jobchange;
+ pc->hide = pc_hide;
+ pc->unhide = pc_unhide;
pc->setoption = pc_setoption;
pc->setcart = pc_setcart;
pc->setfalcon = pc_setfalcon;
@@ -11797,13 +12952,19 @@ void pc_defaults(void) {
pc->delinvincibletimer = pc_delinvincibletimer;
pc->addspiritball = pc_addspiritball;
+ pc->addspiritball_sub = pc_addspiritball_sub;
pc->delspiritball = pc_delspiritball;
+ pc->delspiritball_sub = pc_delspiritball_sub;
pc->addfame = pc_addfame;
- pc->famerank = pc_famerank;
+ pc->fame_rank = pc_fame_rank;
+ pc->famelist_type = pc_famelist_type;
pc->set_hate_mob = pc_set_hate_mob;
pc->getmaxspiritball = pc_getmaxspiritball;
pc->readdb = pc_readdb;
+ pc->read_exp_db = pc_read_exp_db;
+ pc->read_exp_db_sub = pc_read_exp_db_sub;
+ pc->read_exp_db_sub_class = pc_read_exp_db_sub_class;
pc->map_day_timer = map_day_timer; // by [yor]
pc->map_night_timer = map_night_timer; // by [yor]
// Rental System
@@ -11850,12 +13011,17 @@ void pc_defaults(void) {
pc->autosave = pc_autosave;
pc->follow_timer = pc_follow_timer;
pc->read_skill_tree = pc_read_skill_tree;
+ pc->read_skill_job_skip = pc_read_skill_job_skip;
pc->clear_skill_tree = pc_clear_skill_tree;
pc->isUseitem = pc_isUseitem;
pc->show_steal = pc_show_steal;
pc->checkcombo = pc_checkcombo;
pc->calcweapontype = pc_calcweapontype;
pc->removecombo = pc_removecombo;
+ pc->update_job_and_level = pc_update_job_and_level;
+ pc->clear_exp_groups = pc_clear_exp_groups;
+ pc->init_exp_groups = pc_init_exp_groups;
+ pc->job_is_dummy = pc_job_is_dummy;
pc->bank_withdraw = pc_bank_withdraw;
pc->bank_deposit = pc_bank_deposit;
@@ -11871,6 +13037,11 @@ void pc_defaults(void) {
pc->db_checkid = pc_db_checkid;
pc->validate_levels = pc_validate_levels;
+ pc->check_supernovice_call = pc_check_supernovice_call;
+ pc->process_chat_message = pc_process_chat_message;
+ pc->wis_message_to_gm = pc_wis_message_to_gm;
+ pc->wis_message_to_gm_sub = pc_wis_message_to_gm_sub;
+
/**
* Autotrade persistency [Ind/Hercules <3]
**/
@@ -11883,6 +13054,14 @@ void pc_defaults(void) {
pc->check_job_name = pc_check_job_name;
pc->update_idle_time = pc_update_idle_time;
-
+
pc->have_magnifier = pc_have_magnifier;
+ pc->have_item_chain = pc_have_item_chain;
+
+ pc->check_basicskill = pc_check_basicskill;
+
+ pc->isDeathPenaltyJob = pc_isDeathPenaltyJob;
+ pc->has_second_costume = pc_has_second_costume;
+ pc->expandInventory = pc_expandInventory;
+ pc->auto_exp_insurance = pc_auto_exp_insurance;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index a702b44bc..e560df549 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "map/log.h" // struct e_log_pick_type
#include "map/map.h" // RC_MAX, ELE_MAX
#include "map/pc_groups.h" // GroupSettings
+#include "map/rodex.h"
#include "map/script.h" // struct reg_db
#include "map/searchstore.h" // struct s_search_store_info
#include "map/status.h" // enum sc_type, OPTION_*
@@ -36,7 +37,7 @@
#include "common/db.h"
#include "common/ers.h" // struct eri
#include "common/hercules.h"
-#include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS
+#include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS, struct s_achievement
/**
* Defines
@@ -73,6 +74,14 @@ enum equip_index {
EQI_MAX
};
+enum prevent_logout_trigger {
+ PLT_NONE = 0x0,
+ PLT_LOGIN = 0x1,
+ PLT_ATTACK = 0x2,
+ PLT_SKILL = 0x4,
+ PLT_DAMAGE = 0x8
+};
+
enum pc_unequipitem_flag {
PCUNEQUIPITEM_NONE = 0x0, ///< Just unequip
PCUNEQUIPITEM_RECALC = 0x1, ///< Recalculate status after unequipping
@@ -86,6 +95,14 @@ enum pc_resetskill_flag {
PCRESETSKILL_CHSEX = 0x4, // just reset the skills if the player class is a bard/dancer type (for changesex.)
};
+enum pc_checkitem_types {
+ PCCHECKITEM_NONE = 0x0,
+ PCCHECKITEM_INVENTORY = 0x1,
+ PCCHECKITEM_CART = 0x2,
+ PCCHECKITEM_STORAGE = 0x4,
+ PCCHECKITEM_GSTORAGE = 0x8
+};
+
struct weapon_data {
int atkmods[3];
BEGIN_ZEROED_BLOCK; // all the variables within this block get zero'ed in each call of status_calc_pc
@@ -100,22 +117,23 @@ BEGIN_ZEROED_BLOCK; // all the variables within this block get zero'ed in each c
int addrace2[RC2_MAX];
int addsize[3];
struct drain_data {
- short rate;
- short per;
- short value;
+ int rate;
+ int per;
+ int value;
unsigned type:1;
} hp_drain[RC_MAX], sp_drain[RC_MAX];
struct {
- short class_, rate;
+ int class_, rate;
} add_dmg[MAX_PC_BONUS];
struct {
- short flag, rate;
+ int flag, rate;
unsigned char ele;
} addele2[MAX_PC_BONUS];
END_ZEROED_BLOCK;
};
struct s_autospell {
- short id, lv, rate, card_id, flag;
+ int id, lv, rate, flag;
+ int card_id;
bool lock; // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed
};
/// AddEff bonus data
@@ -129,19 +147,20 @@ struct s_addeffect {
};
struct s_addeffectonskill {
enum sc_type id;
- short rate, skill;
+ int rate, skill;
unsigned char target;
};
struct s_add_drop {
- short id, group;
+ bool is_group;
+ int id;
int race, rate;
};
struct s_autobonus {
- short rate,atk_type;
+ int rate,atk_type;
unsigned int duration;
char *bonus_script, *other_script;
int active;
- unsigned short pos;
+ unsigned int pos;
};
enum npc_timeout_type {
NPCT_INPUT = 0,
@@ -151,7 +170,18 @@ enum npc_timeout_type {
struct pc_combos {
struct script_code *bonus;/* the script of the combo */
- unsigned short id;/* this combo id */
+ int id; /* this combo id */
+};
+
+/** Auto-cast related data. **/
+struct autocast_data {
+ enum autocast_type type; // The auto-cast type.
+ int skill_id; // The auto-cast skill ID.
+ int skill_lv; // The auto-cast skill level.
+ bool itemskill_conditions_checked; // Used by itemskill() script command, to prevent second check of conditions after target was selected.
+ bool itemskill_check_conditions; // Used by itemskill() script command, to check skill conditions and consume them.
+ bool itemskill_instant_cast; // Used by itemskill() script command, to cast skill instantaneously.
+ bool itemskill_cast_on_self; // Used by itemskill() script command, to forcefully cast skill on invoking character.
};
struct map_session_data {
@@ -162,6 +192,7 @@ struct map_session_data {
struct status_change sc;
struct regen_data regen;
struct regen_data_sub sregen, ssregen;
+ struct autocast_data autocast;
//NOTE: When deciding to add a flag to state or special_state, take into consideration that state is preserved in
//status_calc_pc, while special_state is recalculated in each call. [Skotlex]
struct {
@@ -175,8 +206,6 @@ struct map_session_data {
unsigned int rest : 1;
unsigned int storage_flag : 2; // @see enum storage_flag
unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
- unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
- unsigned int autocast : 1; // Autospell flag [Inkfish]
unsigned int autotrade : 2; //By Fantik
unsigned int showdelay :1;
unsigned int showexp :1;
@@ -184,10 +213,8 @@ struct map_session_data {
unsigned int noask :1; // [LuzZza]
unsigned int trading :1; //[Skotlex] is 1 only after a trade has started.
unsigned int deal_locked :2; //1: Clicked on OK. 2: Clicked on TRADE
- unsigned int monster_ignore :1; // for monsters to ignore a character [Valaris] [zzo]
unsigned int size :2; // for tiny/large types
unsigned int night :1; //Holds whether or not the player currently has the SI_NIGHT effect on. [Skotlex]
- unsigned int blockedmove :1;
unsigned int using_fake_npc :1;
unsigned int rewarp :1; //Signals that a player should warp as soon as he is done loading a map. [Skotlex]
unsigned int killer : 1;
@@ -202,11 +229,11 @@ struct map_session_data {
unsigned int changemap : 1;
unsigned int callshop : 1; // flag to indicate that a script used callshop; on a shop
short pmap; // Previous map on Map Change
- unsigned short autoloot;
- unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
- unsigned short autoloottype;
+ unsigned int autoloot;
+ int autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
+ unsigned int autoloottype;
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
- unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
+ unsigned int autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
unsigned int gmaster_flag : 1;
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
unsigned int warping : 1;//states whether you're in the middle of a warp processing
@@ -217,10 +244,12 @@ struct map_session_data {
unsigned int hold_recalc : 1;
unsigned int snovice_call_flag : 3; //Summon Angel (stage 1~3)
unsigned int hpmeter_visible : 1;
- unsigned int itemcheck : 1;
unsigned int standalone : 1;/* [Ind/Hercules <3] */
unsigned int loggingout : 1;
unsigned int warp_clean : 1;
+ unsigned int refine_ui : 1;
+ unsigned int npc_unloaded : 1; ///< The player is talking with an unloaded NPCs (respawned tombstones)
+ unsigned int lapine_ui : 1;
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -235,7 +264,7 @@ struct map_session_data {
unsigned int bonus_coma : 1;
} special_state;
int login_id1, login_id2;
- unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
+ uint16 job; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
/// Groups & permissions
int group_id;
@@ -243,7 +272,9 @@ struct map_session_data {
unsigned int extra_temp_permissions; /* permissions from @addperm */
struct mmo_charstatus status;
- struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
+ struct item_data *inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
+ struct storage_data storage; ///< Account Storage
+ enum pc_checkitem_types itemcheck;
short equip_index[EQI_MAX];
unsigned int weight,max_weight;
int cart_weight,cart_num,cart_weight_max;
@@ -255,10 +286,13 @@ struct map_session_data {
int npc_item_flag; //Marks the npc_id with which you can change equipments during interactions with said npc (see script command enable_itemuse)
int npc_menu; // internal variable, used in npc menu handling
int npc_amount;
+ int npc_amount_min;
+ int npc_amount_max;
+ int npc_input_capped_range;
struct script_state *st;
char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine
int npc_timer_id; //For player attached npc timers. [Skotlex]
- unsigned int chatID;
+ int chat_id;
int64 idletime;
struct {
int npc_id;
@@ -270,11 +304,10 @@ struct map_session_data {
int followtimer; // [MouseJstr]
int followtarget;
time_t emotionlasttime; // to limit flood with emotion packets
- short skillitem,skillitemlv;
uint16 skill_id_old,skill_lv_old;
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
- bool blockskill[MAX_SKILL];
+ bool blockskill[MAX_SKILL_DB];
int cloneskill_id, reproduceskill_id;
int menuskill_id, menuskill_val, menuskill_val2;
int invincible_timer;
@@ -287,11 +320,14 @@ struct map_session_data {
int64 cansendmail_tick; /// Mail System Flood Protection
int64 ks_floodprotect_tick; /// [Kill Steal Protection]
struct {
- short nameid;
+ int nameid;
int64 tick;
} item_delay[MAX_ITEMDELAYS]; // [Paradox924X]
- short weapontype1,weapontype2;
- short disguise; // [Valaris]
+ bool has_shield; ///< Whether the character is wearing a shield.
+ int16 weapontype; ///< Weapon type considering both hands (@see enum weapon_type).
+ int16 weapontype1; ///< Weapon type in the right/primary hand (@see enum weapon_type).
+ int16 weapontype2; ///< Weapon type in the left/secondary hand (@see enum weapon_type).
+ int disguise; // [Valaris]
struct weapon_data right_weapon, left_weapon;
BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of status_calc_pc()
@@ -316,9 +352,9 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st
int expaddrace[RC_MAX];
int ignore_mdef[RC_MAX];
int ignore_def[RC_MAX];
- short sp_gain_race[RC_MAX];
- short sp_gain_race_attack[RC_MAX];
- short hp_gain_race_attack[RC_MAX];
+ int sp_gain_race[RC_MAX];
+ int sp_gain_race_attack[RC_MAX];
+ int hp_gain_race_attack[RC_MAX];
#ifdef RENEWAL
int race_tolerance[RC_MAX];
#endif
@@ -326,16 +362,16 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st
struct s_addeffect addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS];
struct s_addeffectonskill addeff3[MAX_PC_BONUS];
struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills.
- unsigned short id;
- short val;
+ unsigned int id;
+ int val;
} skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS], skillfixcastrate[MAX_PC_BONUS];
struct {
- short value;
+ int value;
int rate;
int tick;
} hp_loss, sp_loss, hp_regen, sp_regen;
struct {
- short class_, rate;
+ int class_, rate;
} add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS];
struct s_add_drop add_drop[MAX_PC_BONUS];
struct {
@@ -343,11 +379,11 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st
int rate;
} itemhealrate[MAX_PC_BONUS];
struct {
- short flag, rate;
+ int flag, rate;
unsigned char ele;
} subele2[MAX_PC_BONUS];
struct {
- short value;
+ int value;
int rate, tick;
} def_set_race[RC_MAX], mdef_set_race[RC_MAX];
struct {
@@ -373,17 +409,17 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st
int itemhealrate2; // [Epoque] Increase heal rate of all healing items.
int shieldmdef;//royal guard's
unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex]
- short splash_range, splash_add_range;
- short add_steal_rate;
- short add_heal_rate, add_heal2_rate;
- short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
- short hp_vanish_rate;
- short hp_vanish_per, hp_vanish_trigger;
- short sp_vanish_rate;
- short sp_vanish_per, sp_vanish_trigger;
- unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest]
- unsigned short unbreakable_equip; //100% break resistance on certain equipment
- unsigned short unstripable_equip;
+ int splash_range, splash_add_range;
+ int add_steal_rate;
+ int add_heal_rate, add_heal2_rate;
+ int sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
+ int hp_vanish_rate;
+ int hp_vanish_per, hp_vanish_trigger;
+ int sp_vanish_rate;
+ int sp_vanish_per, sp_vanish_trigger;
+ unsigned int unbreakable; // chance to prevent ANY equipment breaking [celest]
+ unsigned int unbreakable_equip; //100% break resistance on certain equipment
+ unsigned int unstripable_equip;
int fixcastrate,varcastrate;
int add_fixcast,add_varcast;
int ematk; // matk bonus from equipment
@@ -398,22 +434,22 @@ END_ZEROED_BLOCK;
int matk_rate;
int critical_rate,hit_rate,flee_rate,flee2_rate,def_rate,def2_rate,mdef_rate,mdef2_rate;
int itemid;
- short itemindex; //Used item's index in sd->inventory [Skotlex]
- short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo]
- short spiritball, spiritball_old;
+ int itemindex; //Used item's index in sd->inventory [Skotlex]
+ int catch_target_class;
+ int spiritball, spiritball_old;
int spirit_timer[MAX_SPIRITBALL];
- short charm_count;
- int charm_type;
+ int charm_count;
+ enum spirit_charm_types charm_type;
int charm_timer[MAX_SPIRITCHARM];
unsigned char potion_success_counter; //Potion successes in row counter
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
- short mission_mobid; //Stores the target mob_id for TK_MISSION
+ int mission_mobid; //Stores the target mob_id for TK_MISSION
int die_counter; //Total number of times you've died
int devotion[MAX_PC_DEVOTION]; //Stores the account IDs of chars devoted to.
int trade_partner;
struct {
struct {
- short index, amount;
+ int index, amount;
} item[10];
int zeny, weight;
} deal;
@@ -422,6 +458,7 @@ END_ZEROED_BLOCK;
int party_invite, party_invite_account; // for handling party invitation (holds party id and account id)
int adopt_invite; // Adoption
struct guild *guild;/* [Ind/Hercules] speed everything up */
+ struct clan *clan;
int guild_invite,guild_invite_account;
int guild_emblem_id,guild_alliance,guild_alliance_account;
short guild_x,guild_y; // For guildmate position display. [Skotlex] should be short [zzo]
@@ -443,23 +480,24 @@ END_ZEROED_BLOCK;
struct {
int m; //-1 - none, other: map index corresponding to map name.
- unsigned short index; //map index
+ unsigned int index; //map index
} feel_map[MAX_PC_FEELHATE];// 0 - Sun; 1 - Moon; 2 - Stars
- short hate_mob[MAX_PC_FEELHATE];
+ int hate_mob[MAX_PC_FEELHATE];
int pvp_timer;
- short pvp_point;
- unsigned short pvp_rank, pvp_lastusers;
- unsigned short pvp_won, pvp_lost;
+ int pvp_point;
+ unsigned int pvp_rank, pvp_lastusers;
+ unsigned int pvp_won, pvp_lost;
char eventqueue[MAX_EVENTQUEUE][EVENT_NAME_LENGTH];
int eventtimer[MAX_EVENTTIMER];
- unsigned short eventcount; // [celest]
+ unsigned int eventcount; // [celest]
- unsigned char change_level_2nd; // job level when changing from 1st to 2nd class [jobchange_level in global_reg_value]
- unsigned char change_level_3rd; // job level when changing from 2nd to 3rd class [jobchange_level_3rd in global_reg_value]
+ int change_level_2nd; // job level when changing from 1st to 2nd class [jobchange_level in global_reg_value]
+ int change_level_3rd; // job level when changing from 2nd to 3rd class [jobchange_level_3rd in global_reg_value]
char fakename[NAME_LENGTH]; // fake names [Valaris]
+ int fakename_options; // Fake name display options.
int duel_group; // duel vars [LuzZza]
int duel_invite;
@@ -476,12 +514,20 @@ END_ZEROED_BLOCK;
// Mail System [Zephyrus]
struct {
- short nameid;
+ int nameid;
int index, amount, zeny;
struct mail_data inbox;
bool changed; // if true, should sync with charserver on next mailbox request
} mail;
+ // RoDEX
+ struct {
+ struct rodex_message tmp;
+ struct rodex_maillist messages;
+ int total;
+ bool new_mail;
+ } rodex;
+
// Quest log system
int num_quests; ///< Number of entries in quest_log
int avail_quests; ///< Number of Q_ACTIVE and Q_INACTIVE entries in quest log (index of the first Q_COMPLETE entry)
@@ -527,11 +573,10 @@ END_ZEROED_BLOCK;
int shadowform_id;
/* [Ind/Hercules] */
- struct channel_data **channels;
- unsigned char channel_count;
+ VECTOR_DECL(struct channel_data *) channels;
struct channel_data *gcbind;
unsigned char fontcolor;
- unsigned int fontcolor_tid;
+ int fontcolor_tid;
int64 hchsysch_tick;
/* [Ind/Hercules] */
@@ -564,7 +609,7 @@ END_ZEROED_BLOCK;
/* */
struct {
- unsigned int second,third;
+ int second, third;
} sktree;
/**
@@ -588,6 +633,26 @@ END_ZEROED_BLOCK;
const char* delunit_prevfile;
int delunit_prevline;
+ // HatEffect
+ VECTOR_DECL(int) hatEffectId;
+
+ struct {
+ unsigned move : 1;
+ unsigned attack : 1;
+ unsigned skill : 1;
+ unsigned useitem : 1;
+ unsigned chat : 1;
+ unsigned immune : 1;
+ unsigned sitstand : 1;
+ unsigned commands : 1;
+ unsigned npc : 1;
+ } block_action;
+
+ /* Achievement System */
+ struct char_achievements achievement;
+ bool achievements_received;
+ // Title
+ VECTOR_DECL(int) title_ids;
};
#define EQP_WEAPON EQP_HAND_R
@@ -610,19 +675,21 @@ END_ZEROED_BLOCK;
#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->bc->idle_no_share )
+#define pc_isidle(sd) ( (sd)->chat_id != 0 || (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 )
+#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
+#define pc_cant_act_except_lapine(sd) ((sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1)
/* equals pc_cant_act except it doesn't check for chat rooms */
-#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
+#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
-#define pc_setchatid(sd,n) ( (sd)->chatID = n )
+#define pc_setchatid(sd,n) ( (sd)->chat_id = (n) )
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
#define pc_iscloaking(sd) ( !((sd)->sc.option&OPTION_CHASEWALK) && ((sd)->sc.option&OPTION_CLOAK) )
#define pc_ischasewalk(sd) ( (sd)->sc.option&OPTION_CHASEWALK )
-#define pc_ismuted(sc,type) ( (sc)->data[SC_NOCHAT] && (sc)->data[SC_NOCHAT]->val1&(type) )
+#define pc_ismuted(sc, type) ( (sc)->data[SC_NOCHAT] != NULL && (battle_config.manner_system & (type)) != 0 )
+#define pc_isvending(sd) ((sd)->state.vending || (sd)->state.prevend || (sd)->state.buyingstore)
#ifdef NEW_CARTS
#define pc_iscarton(sd) ( (sd)->sc.data[SC_PUSH_CART] )
@@ -635,12 +702,13 @@ END_ZEROED_BLOCK;
#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_&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) \
+ ((sd)->job & MAPID_BASEMASK) == MAPID_SUMMONER ? battle->bc->max_summoner_parameter : \
+ ( ((sd)->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO \
+ || ((sd)->job & MAPID_UPPERMASK) == MAPID_REBELLION \
+ || ((sd)->job & MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E \
+ ) ? battle->bc->max_extended_parameter : ((sd)->job & JOBL_THIRD) ? \
+ (((sd)->job & JOBL_BABY) ? battle->bc->max_baby_third_parameter : battle->bc->max_third_parameter ) : \
+ (((sd)->job & JOBL_BABY) ? battle->bc->max_baby_parameter : battle->bc->max_parameter) \
)
/// Generic check for mounts
#define pc_hasmount(sd) ( (sd)->sc.option&(OPTION_RIDING|OPTION_WUGRIDER|OPTION_DRAGON|OPTION_MADOGEAR) )
@@ -658,8 +726,13 @@ END_ZEROED_BLOCK;
#define pc_stop_attack(sd) (unit->stop_attack(&(sd)->bl))
//Weapon check considering dual wielding.
-#define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_SINGLE_WEAPON_TYPE? \
- 1<<(sd)->status.weapon:(1<<(sd)->weapontype1)|(1<<(sd)->weapontype2)|(1<<(sd)->status.weapon)))
+#define pc_check_weapontype(sd, type) ( \
+ (type) & ( \
+ (sd)->weapontype < MAX_SINGLE_WEAPON_TYPE ? \
+ 1 << (sd)->weapontype : \
+ (1 << (sd)->weapontype1) | (1 << (sd)->weapontype2) \
+ ) \
+ )
// clientside display macros (values to the left/right of the "+")
#ifdef RENEWAL
@@ -715,24 +788,24 @@ END_ZEROED_BLOCK;
#define pc_can_give_bound_items(sd) ( pc_has_permission((sd),PC_PERM_TRADE_BOUND) )
struct skill_tree_requirement {
- short id;
+ int id;
unsigned short idx;
unsigned char lv;
};
struct skill_tree_entry {
- short id;
+ int id;
unsigned short idx;
unsigned char max;
unsigned char joblv;
- short inherited;
+ int inherited;
VECTOR_DECL(struct skill_tree_requirement) need;
}; // Celest
struct sg_data {
- short anger_id;
- short bless_id;
- short comfort_id;
+ int anger_id;
+ int bless_id;
+ int comfort_id;
char feel_var[NAME_LENGTH];
char hate_var[NAME_LENGTH];
bool (*day_func)(void);
@@ -748,7 +821,7 @@ enum { ADDITEM_EXIST , ADDITEM_NEW , ADDITEM_OVERAMOUNT };
**/
struct item_cd {
int64 tick[MAX_ITEMDELAYS];//tick
- short nameid[MAX_ITEMDELAYS];//skill id
+ int nameid[MAX_ITEMDELAYS];//skill id
};
enum e_pc_autotrade_update_action {
@@ -777,6 +850,24 @@ struct autotrade_vending {
struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
+struct class_exp_group {
+ char name[SCRIPT_VARNAME_LENGTH];
+ int max_level;
+ VECTOR_DECL(uint64) exp;
+};
+
+/**
+* Exp types
+*/
+enum class_exp_type {
+ CLASS_EXP_TABLE_BASE,
+ CLASS_EXP_TABLE_JOB
+};
+
+struct class_exp_tables {
+ struct class_exp_group *class_exp_table[CLASS_COUNT][2];
+};
+
/*=====================================
* Interface : pc.h
* Generated by HerculesInterfaceMaker
@@ -794,8 +885,6 @@ struct pc_interface {
/* */
BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */
- unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL];
- unsigned int max_level[CLASS_COUNT][2];
unsigned int statp[MAX_LEVEL+1];
unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1];
/* */
@@ -805,6 +894,8 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta
struct fame_list taekwon_fame_list[MAX_FAME_LIST];
END_ZEROED_BLOCK; /* End */
+ struct class_exp_tables *dbs;
+ VECTOR_DECL(struct class_exp_group) class_exp_groups[2];
unsigned int equip_pos[EQI_MAX];
struct sg_data sg_info[MAX_PC_FEELHATE];
/* */
@@ -823,7 +914,7 @@ END_ZEROED_BLOCK; /* End */
void (*final) (void);
struct map_session_data* (*get_dummy_sd) (void);
- int (*class2idx) (int class_);
+ int (*class2idx) (int class);
bool (*can_talk) (struct map_session_data *sd);
bool (*can_attack) ( struct map_session_data *sd, int target_id );
@@ -833,7 +924,7 @@ END_ZEROED_BLOCK; /* End */
int (*setrestartvalue) (struct map_session_data *sd,int type);
int (*makesavestatus) (struct map_session_data *sd);
- void (*respawn) (struct map_session_data* sd, clr_type clrtype);
+ void (*respawn) (struct map_session_data* sd, enum clr_type clrtype);
int (*setnewpc) (struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd);
bool (*authok) (struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers);
void (*authfail) (struct map_session_data *sd);
@@ -841,6 +932,7 @@ END_ZEROED_BLOCK; /* End */
int (*isequip) (struct map_session_data *sd,int n);
int (*equippoint) (struct map_session_data *sd,int n);
+ int (*item_equippoint) (struct map_session_data *sd, struct item_data* id);
int (*setinventorydata) (struct map_session_data *sd);
int (*checkskill) (struct map_session_data *sd,uint16 skill_id);
@@ -849,19 +941,21 @@ END_ZEROED_BLOCK; /* End */
int (*checkequip) (struct map_session_data *sd,int pos);
int (*calc_skilltree) (struct map_session_data *sd);
+ void (*calc_skilltree_clear) (struct map_session_data *sd);
+ void (*calc_skilltree_bonus) (struct map_session_data *sd, int classidx);
int (*calc_skilltree_normalize_job) (struct map_session_data *sd);
int (*clean_skilltree) (struct map_session_data *sd);
- int (*setpos) (struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype);
+ int (*setpos) (struct map_session_data* sd, unsigned short map_index, int x, int y, enum clr_type clrtype);
int (*setsavepoint) (struct map_session_data *sd, short map_index, int x, int y);
- int (*randomwarp) (struct map_session_data *sd,clr_type type);
+ int (*randomwarp) (struct map_session_data *sd, enum clr_type type);
int (*memo) (struct map_session_data* sd, int pos);
int (*checkadditem) (struct map_session_data *sd,int nameid,int amount);
int (*inventoryblank) (struct map_session_data *sd);
int (*search_inventory) (struct map_session_data *sd,int item_id);
int (*payzeny) (struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
- int (*additem) (struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
+ int (*additem) (struct map_session_data *sd, const struct item *item_data, int amount, e_log_pick_type log_type);
int (*getzeny) (struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
int (*delitem) (struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type);
@@ -884,7 +978,7 @@ END_ZEROED_BLOCK; /* End */
int (*updateweightstatus) (struct map_session_data *sd);
- int (*addautobonus) (struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
+ int (*addautobonus) (struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned int pos,bool onskill);
int (*exeautobonus) (struct map_session_data* sd,struct s_autobonus *bonus);
int (*endautobonus) (int tid, int64 tick, int id, intptr_t data);
int (*delautobonus) (struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore);
@@ -901,7 +995,7 @@ END_ZEROED_BLOCK; /* End */
bool (*can_insert_card_into) (struct map_session_data* sd, int idx_card, int idx_equip);
int (*steal_item) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv);
- int (*steal_coin) (struct map_session_data *sd,struct block_list *bl);
+ int (*steal_coin) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv);
int (*modifybuyvalue) (struct map_session_data *sd,int orig_value);
int (*modifysellvalue) (struct map_session_data *sd,int orig_value);
@@ -909,15 +1003,16 @@ END_ZEROED_BLOCK; /* End */
int (*follow) (struct map_session_data *sd, int target_id); // [MouseJstr]
int (*stop_following) (struct map_session_data *sd);
- unsigned int (*maxbaselv) (struct map_session_data *sd);
- unsigned int (*maxjoblv) (struct map_session_data *sd);
+ int (*maxbaselv) (const struct map_session_data *sd);
+ int (*maxjoblv) (const struct map_session_data *sd);
int (*checkbaselevelup) (struct map_session_data *sd);
+ void (*checkbaselevelup_sc) (struct map_session_data *sd);
int (*checkjoblevelup) (struct map_session_data *sd);
- 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);
- unsigned int (*thisjobexp) (struct map_session_data *sd);
+ bool (*gainexp) (struct map_session_data *sd, struct block_list *src, uint64 base_exp, uint64 job_exp, bool is_quest);
+ uint64 (*nextbaseexp) (const struct map_session_data *sd);
+ uint64 (*thisbaseexp) (const struct map_session_data *sd);
+ uint64 (*nextjobexp) (const struct map_session_data *sd);
+ uint64 (*thisjobexp) (const struct map_session_data *sd);
int (*gets_status_point) (int level);
int (*need_status_point) (struct map_session_data *sd,int type,int val);
int (*maxparameterincrease) (struct map_session_data* sd, int type);
@@ -928,6 +1023,7 @@ END_ZEROED_BLOCK; /* End */
int (*resetlvl) (struct map_session_data *sd,int type);
int (*resetstate) (struct map_session_data *sd);
int (*resetskill) (struct map_session_data *sd, int flag);
+ bool (*resetskill_job) (struct map_session_data *sd, int index);
int (*resetfeel) (struct map_session_data *sd);
int (*resethate) (struct map_session_data *sd);
int (*equipitem) (struct map_session_data *sd,int n,int req_pos);
@@ -936,6 +1032,7 @@ END_ZEROED_BLOCK; /* End */
void (*unequipitem_pos) (struct map_session_data *sd, int n, int pos);
int (*checkitem) (struct map_session_data *sd);
int (*useitem) (struct map_session_data *sd,int n);
+ int (*autocast_clear) (struct map_session_data *sd);
int (*skillatk_bonus) (struct map_session_data *sd, uint16 skill_id);
int (*skillheal_bonus) (struct map_session_data *sd, uint16 skill_id);
@@ -947,19 +1044,21 @@ END_ZEROED_BLOCK; /* End */
void (*heal) (struct map_session_data *sd,unsigned int hp,unsigned int sp, int type);
int (*itemheal) (struct map_session_data *sd,int itemid, int hp,int sp);
int (*percentheal) (struct map_session_data *sd,int hp,int sp);
- int (*jobchange) (struct map_session_data *sd,int job, int upper);
+ int (*jobchange) (struct map_session_data *sd, int class, int upper);
+ void (*hide) (struct map_session_data *sd, bool show_msg);
+ void (*unhide) (struct map_session_data *sd, bool show_msg);
int (*setoption) (struct map_session_data *sd,int type);
int (*setcart) (struct map_session_data* sd, int type);
void (*setfalcon) (struct map_session_data *sd, bool flag);
void (*setridingpeco) (struct map_session_data *sd, bool flag);
- void (*setmadogear) (struct map_session_data *sd, bool flag);
+ void (*setmadogear) (struct map_session_data *sd, bool flag, enum mado_type mtype);
void (*setridingdragon) (struct map_session_data *sd, unsigned int type);
void (*setridingwug) (struct map_session_data *sd, bool flag);
int (*changelook) (struct map_session_data *sd,int type,int val);
int (*equiplookall) (struct map_session_data *sd);
- int (*readparam) (struct map_session_data *sd,int type);
- int (*setparam) (struct map_session_data *sd,int type,int val);
+ int64 (*readparam) (const struct map_session_data *sd, int type);
+ int (*setparam) (struct map_session_data *sd, int type, int64 val);
int (*readreg) (struct map_session_data *sd, int64 reg);
void (*setreg) (struct map_session_data *sd, int64 reg,int val);
char * (*readregstr) (struct map_session_data *sd, int64 reg);
@@ -991,22 +1090,28 @@ END_ZEROED_BLOCK; /* End */
void (*setstand) (struct map_session_data *sd);
int (*candrop) (struct map_session_data *sd,struct item *item);
- int (*jobid2mapid) (unsigned short b_class); // Skotlex
- int (*mapid2jobid) (unsigned short class_, int sex); // Skotlex
+ int (*jobid2mapid) (int class); // Skotlex
+ int (*mapid2jobid) (unsigned int class_, int sex); // Skotlex
- const char * (*job_name) (int class_);
+ const char * (*job_name) (int class);
void (*setinvincibletimer) (struct map_session_data* sd, int val);
void (*delinvincibletimer) (struct map_session_data* sd);
int (*addspiritball) (struct map_session_data *sd,int interval,int max);
+ int (*addspiritball_sub) (struct map_session_data *sd);
int (*delspiritball) (struct map_session_data *sd,int count,int type);
+ int (*delspiritball_sub) (struct map_session_data *sd);
int (*getmaxspiritball) (struct map_session_data *sd, int min);
- void (*addfame) (struct map_session_data *sd,int count);
- unsigned char (*famerank) (int char_id, int job);
+ void (*addfame) (struct map_session_data *sd, int ranktype, int count);
+ int (*fame_rank) (int char_id, int ranktype);
+ int (*famelist_type) (uint16 job_mapid);
int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl);
int (*readdb) (void);
+ bool (*read_exp_db) (void);
+ int (*read_exp_db_sub) (struct config_setting_t *conf, bool base);
+ bool (*read_exp_db_sub_class) (struct config_setting_t *t, bool base);
int (*map_day_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
int (*map_night_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
// Rental System
@@ -1014,7 +1119,7 @@ END_ZEROED_BLOCK; /* End */
int (*inventory_rental_clear) (struct map_session_data *sd);
void (*inventory_rental_add) (struct map_session_data *sd, int seconds);
- int (*disguise) (struct map_session_data *sd, int class_);
+ int (*disguise) (struct map_session_data *sd, int class);
bool (*isautolooting) (struct map_session_data *sd, int nameid);
void (*overheat) (struct map_session_data *sd, int val);
@@ -1025,8 +1130,8 @@ END_ZEROED_BLOCK; /* End */
int (*load_combo) (struct map_session_data *sd);
- void (*add_charm) (struct map_session_data *sd, int interval, int max, int type);
- void (*del_charm) (struct map_session_data *sd, int count, int type);
+ void (*add_charm) (struct map_session_data *sd, int interval, int max, enum spirit_charm_types type);
+ void (*del_charm) (struct map_session_data *sd, int count, enum spirit_charm_types type);
void (*baselevelchanged) (struct map_session_data *sd);
int (*level_penalty_mod) (int diff, unsigned char race, uint32 mode, int type);
@@ -1037,12 +1142,12 @@ END_ZEROED_BLOCK; /* End */
int (*check_banding) ( struct block_list *bl, va_list ap );
int (*inventory_rental_end) (int tid, int64 tick, int id, intptr_t data);
void (*check_skilltree) (struct map_session_data *sd, int skill_id);
- int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id);
- int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id);
+ int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, int card_id);
+ int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, int card_id);
int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration);
int (*bonus_addeff_onskill) (struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target);
- int (*bonus_item_drop) (struct s_add_drop *drop, const short max, short id, short group, int race, int rate);
- void (*calcexp) (struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src);
+ int (*bonus_item_drop) (struct s_add_drop *drop, const short max, int id, bool is_group, int race, int rate);
+ void (*calcexp) (struct map_session_data *sd, uint64 *base_exp, uint64 *job_exp, struct block_list *src);
int (*respawn_timer) (int tid, int64 tick, int id, intptr_t data);
int (*jobchange_killclone) (struct block_list *bl, va_list ap);
int (*getstat) (struct map_session_data* sd, int type);
@@ -1054,6 +1159,7 @@ END_ZEROED_BLOCK; /* End */
int (*autosave) (int tid, int64 tick, int id, intptr_t data);
int (*follow_timer) (int tid, int64 tick, int id, intptr_t data);
void (*read_skill_tree) (void);
+ bool (*read_skill_job_skip) (short skill_id, int job_id);
void (*clear_skill_tree) (void);
int (*isUseitem) (struct map_session_data *sd,int n);
int (*show_steal) (struct block_list *bl,va_list ap);
@@ -1073,9 +1179,13 @@ END_ZEROED_BLOCK; /* End */
int (*global_expiration_timer) (int tid, int64 tick, int id, intptr_t data);
void (*expire_check) (struct map_session_data *sd);
- bool (*db_checkid) (unsigned int class_);
+ bool (*db_checkid) (int class);
void (*validate_levels) (void);
+ void (*update_job_and_level) (struct map_session_data *sd);
+ void (*clear_exp_groups) (void);
+ void (*init_exp_groups) (void);
+ bool (*job_is_dummy) (int job);
/**
* Autotrade persistency [Ind/Hercules <3]
@@ -1089,8 +1199,19 @@ END_ZEROED_BLOCK; /* End */
int (*check_job_name) (const char *name);
void (*update_idle_time) (struct map_session_data* sd, enum e_battle_config_idletime type);
-
+
int (*have_magnifier) (struct map_session_data *sd);
+ int (*have_item_chain) (struct map_session_data *sd, enum e_chain_cache chain_cache_id);
+
+ bool (*process_chat_message) (struct map_session_data *sd, const char *message);
+ int (*wis_message_to_gm) (const char *sender_name, int permission, const char *message);
+ int (*wis_message_to_gm_sub) (struct map_session_data *sd, va_list va);
+ void (*check_supernovice_call) (struct map_session_data *sd, const char *message);
+ bool (*check_basicskill) (struct map_session_data *sd, int level);
+ bool (*isDeathPenaltyJob) (uint16 job);
+ bool (*has_second_costume) (struct map_session_data *sd);
+ bool (*expandInventory) (struct map_session_data *sd, int adjustSize);
+ bool (*auto_exp_insurance) (struct map_session_data *sd);
};
#ifdef HERCULES_CORE
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index ccda34b1c..9149aa6e4 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,7 +36,7 @@
static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd()
-struct pc_groups_interface pcg_s;
+static struct pc_groups_interface pcg_s;
struct pc_groups_interface *pcg;
/**
@@ -44,7 +44,7 @@ struct pc_groups_interface *pcg;
* Used in dummy map sessions.
* @see pc_get_dummy_sd()
*/
-GroupSettings* pc_group_get_dummy_group(void)
+static GroupSettings *pc_group_get_dummy_group(void)
{
return &dummy_group;
}
@@ -53,7 +53,7 @@ GroupSettings* pc_group_get_dummy_group(void)
* @retval NULL if not found
* @private
*/
-static inline GroupSettings* name2group(const char* group_name)
+static inline GroupSettings *name2group(const char *group_name)
{
return strdb_get(pcg->name_db, group_name);
}
@@ -62,7 +62,8 @@ static inline GroupSettings* name2group(const char* group_name)
* Loads group configuration from config file into memory.
* @private
*/
-static void read_config(void) {
+static void read_config(void)
+{
struct config_t pc_group_config;
struct config_setting_t *groups = NULL;
const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name
@@ -308,8 +309,9 @@ static void read_config(void) {
* @param group group
* @param permission permission to check
*/
-bool pc_group_has_permission(GroupSettings *group, unsigned int permission)
+static bool pc_group_has_permission(GroupSettings *group, unsigned int permission)
{
+ nullpo_retr(false, group);
return ((group->e_permissions&permission) != 0);
}
@@ -317,8 +319,9 @@ bool pc_group_has_permission(GroupSettings *group, unsigned int permission)
* Checks if commands used by player group should be logged
* @param group group
*/
-bool pc_group_should_log_commands(GroupSettings *group)
+static bool pc_group_should_log_commands(GroupSettings *group)
{
+ nullpo_retr(true, group);
return group->log_commands;
}
@@ -327,7 +330,7 @@ bool pc_group_should_log_commands(GroupSettings *group)
* @param group_id group id
* @returns true if group exists, false otherwise
*/
-bool pc_group_exists(int group_id)
+static bool pc_group_exists(int group_id)
{
return idb_exists(pcg->db, group_id);
}
@@ -335,7 +338,7 @@ bool pc_group_exists(int group_id)
/**
* @retval NULL if not found
*/
-GroupSettings* pc_group_id2group(int group_id)
+static GroupSettings *pc_group_id2group(int group_id)
{
return idb_get(pcg->db, group_id);
}
@@ -346,8 +349,9 @@ GroupSettings* pc_group_id2group(int group_id)
* @return group name
* @public
*/
-const char* pc_group_get_name(GroupSettings *group)
+static const char *pc_group_get_name(GroupSettings *group)
{
+ nullpo_retr(NULL, group);
return group->name;
}
@@ -357,8 +361,9 @@ const char* pc_group_get_name(GroupSettings *group)
* @return group level
* @public
*/
-int pc_group_get_level(GroupSettings *group)
+static int pc_group_get_level(GroupSettings *group)
{
+ nullpo_ret(group);
return group->level;
}
@@ -368,8 +373,9 @@ int pc_group_get_level(GroupSettings *group)
* @return group index
* @public
*/
-int pc_group_get_idx(GroupSettings *group)
+static int pc_group_get_idx(GroupSettings *group)
{
+ nullpo_ret(group);
return group->index;
}
@@ -377,9 +383,11 @@ int pc_group_get_idx(GroupSettings *group)
* Insert a new permission
* @return inserted key or 0 upon failure.
**/
-unsigned int pc_groups_add_permission(const char *name) {
+static unsigned int pc_groups_add_permission(const char *name)
+{
uint64 key = 0x1;
unsigned char i;
+ nullpo_ret(name);
for(i = 0; i < pcg->permission_count; i++) {
if( strcmpi(name,pcg->permissions[i].name) == 0 ) {
@@ -408,7 +416,8 @@ unsigned int pc_groups_add_permission(const char *name) {
* Initialize PC Groups: allocate DBMaps and read config.
* @public
*/
-void do_init_pc_groups(void) {
+static void do_init_pc_groups(void)
+{
const struct {
const char *name;
unsigned int permission;
@@ -440,6 +449,7 @@ void do_init_pc_groups(void) {
{ "disable_store", PC_PERM_DISABLE_STORE },
{ "disable_exp", PC_PERM_DISABLE_EXP },
{ "disable_skill_usage", PC_PERM_DISABLE_SKILL_USAGE },
+ { "bypass_nostorage", PC_PERM_BYPASS_NOSTORAGE },
};
unsigned char i, len = ARRAYLENGTH(pc_g_defaults);
@@ -468,6 +478,7 @@ void do_init_pc_groups(void) {
static int group_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
GroupSettings *group = DB->data2ptr(data);
+ nullpo_ret(group);
if (group->name)
aFree(group->name);
return 0;
@@ -477,7 +488,7 @@ static int group_db_clear_sub(union DBKey key, struct DBData *data, va_list args
* Finalize PC Groups: free DBMaps and config.
* @public
*/
-void do_final_pc_groups(void)
+static void do_final_pc_groups(void)
{
if (pcg->db != NULL)
pcg->db->destroy(pcg->db, group_db_clear_sub);
@@ -499,7 +510,8 @@ void do_final_pc_groups(void)
* Used in @reloadatcommand
* @public
*/
-void pc_groups_reload(void) {
+static void pc_groups_reload(void)
+{
struct map_session_data *sd = NULL;
struct s_mapiterator *iter;
@@ -521,7 +533,8 @@ void pc_groups_reload(void) {
/**
* Connect Interface
**/
-void pc_groups_defaults(void) {
+void pc_groups_defaults(void)
+{
pcg = &pcg_s;
/* */
pcg->db = NULL;
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index 27eac7284..0a8cfce86 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,6 +57,7 @@ enum e_pc_permission {
PC_PERM_DISABLE_STORE = 0x1000000,
PC_PERM_DISABLE_EXP = 0x2000000,
PC_PERM_DISABLE_SKILL_USAGE = 0x4000000,
+ PC_PERM_BYPASS_NOSTORAGE = 0x8000000,
};
// Cached config settings for quick lookup
diff --git a/src/map/pet.c b/src/map/pet.c
index e2b257e10..299de42c7 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
#include "config/core.h" // DBPATH
#include "pet.h"
+#include "map/achievement.h"
#include "map/atcommand.h" // msg_txt()
#include "map/battle.h"
#include "map/chrif.h"
@@ -39,6 +40,7 @@
#include "map/skill.h"
#include "map/status.h"
#include "map/unit.h"
+#include "common/conf.h"
#include "common/db.h"
#include "common/ers.h"
#include "common/memmgr.h"
@@ -53,57 +55,110 @@
#include <stdlib.h>
#include <string.h>
-struct pet_interface pet_s;
+static struct pet_interface pet_s;
struct pet_interface *pet;
#define MIN_PETTHINKTIME 100
-int pet_hungry_val(struct pet_data *pd)
+/**
+ * Gets a pet's hunger value, depending it's hunger level.
+ * This value is only used in clif_parse_LoadEndAck() when calling clif_pet_emotion().
+ *
+ * @param pd The pet.
+ * @return The pet's hunger value.
+ *
+ **/
+static int pet_hungry_val(struct pet_data *pd)
{
nullpo_ret(pd);
- if(pd->pet.hungry > 90)
+ if (pd->pet.hungry > PET_HUNGER_SATISFIED)
return 4;
- else if(pd->pet.hungry > 75)
+ else if (pd->pet.hungry > PET_HUNGER_NEUTRAL)
return 3;
- else if(pd->pet.hungry > 25)
+ else if (pd->pet.hungry > PET_HUNGER_HUNGRY)
return 2;
- else if(pd->pet.hungry > 10)
+ else if (pd->pet.hungry > PET_HUNGER_VERY_HUNGRY)
return 1;
else
return 0;
}
-void pet_set_intimate(struct pet_data *pd, int value)
+/**
+ * Sets a pet's hunger value.
+ *
+ * @param pd The pet.
+ * @param value The pet's new hunger value.
+ *
+ **/
+static void pet_set_hunger(struct pet_data *pd, int value)
{
- int intimate;
- struct map_session_data *sd;
+ nullpo_retv(pd);
+ pd->pet.hungry = cap_value(value, PET_HUNGER_STARVING, PET_HUNGER_STUFFED);
+}
+
+/**
+ * Sets a pet's intimacy value.
+ * Deletes the pet if its intimacy value reaches PET_INTIMACY_NONE (0).
+ *
+ * @param pd The pet.
+ * @param value The pet's new intimacy value.
+ *
+ **/
+static void pet_set_intimate(struct pet_data *pd, int value)
+{
nullpo_retv(pd);
- intimate = pd->pet.intimate;
- sd = pd->msd;
+ nullpo_retv(pd->msd);
+
+ pd->pet.intimate = cap_value(value, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+
+ struct map_session_data *sd = pd->msd;
+
+ status_calc_pc(sd, SCO_NONE);
- pd->pet.intimate = value;
- if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
- status_calc_pc(sd,SCO_NONE);
+ if (pd->pet.intimate == PET_INTIMACY_NONE) { /// Pet is lost. Delete the egg.
+ int i;
+
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET
+ && pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1],
+ sd->status.inventory[i].card[2]));
+
+ if (i != sd->status.inventorySize)
+ pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG);
+ }
}
-int pet_create_egg(struct map_session_data *sd, int item_id)
+/**
+ * Creates a pet egg.
+ *
+ * @param sd The character who tries to create the pet egg.
+ * @param item_id The pet egg's item ID.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
+static int pet_create_egg(struct map_session_data *sd, int item_id)
{
+ nullpo_ret(sd);
+
int pet_id = pet->search_petDB_index(item_id, PET_EGG);
- if (pet_id < 0) return 0; //No pet egg here.
- if (!pc->inventoryblank(sd)) return 0; // Inventory full
+
+ if (pet_id == INDEX_NOT_FOUND) // No pet egg here.
+ return 0;
+
+ if (pc->inventoryblank(sd) == 0) // Inventory full.
+ return 0;
+
sd->catch_target_class = pet->db[pet_id].class_;
- intif->create_pet(sd->status.account_id, sd->status.char_id,
- (short)pet->db[pet_id].class_,
- (short)mob->db(pet->db[pet_id].class_)->lv,
- (short)pet->db[pet_id].EggID, 0,
- (short)pet->db[pet_id].intimate,
- 100, 0, 1, pet->db[pet_id].jname);
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID, 0,
+ (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1, pet->db[pet_id].jname);
+
return 1;
}
-int pet_unlocktarget(struct pet_data *pd)
+static int pet_unlocktarget(struct pet_data *pd)
{
nullpo_ret(pd);
@@ -116,7 +171,9 @@ int pet_unlocktarget(struct pet_data *pd)
/*==========================================
* Pet Attack Skill [Skotlex]
*------------------------------------------*/
-int pet_attackskill(struct pet_data *pd, int target_id) {
+static int pet_attackskill(struct pet_data *pd, int target_id)
+{
+ nullpo_ret(pd);
if (!battle_config.pet_status_support || !pd->a_skill ||
(battle_config.pet_equip_required && !pd->pet.equip))
return 0;
@@ -144,50 +201,46 @@ int pet_attackskill(struct pet_data *pd, int target_id) {
return 0;
}
-int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) {
- struct pet_data *pd;
- int rate;
+/**
+ * Checks if a pet can attack a target.
+ *
+ * @param sd The pet's master.
+ * @param bl The pet's target.
+ * @param type 0 - Support master when attacking. Not 0 - Support master when being attacked.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
+static int pet_target_check(struct map_session_data *sd, struct block_list *bl, int type)
+{
+ nullpo_ret(sd);
+ nullpo_ret(sd->pd);
+ nullpo_ret(bl);
+ Assert_ret(sd->pd->msd == NULL || sd->pd->msd->pd == sd->pd);
- pd = sd->pd;
+ struct pet_data *pd = sd->pd;
- Assert_ret(pd->msd == 0 || pd->msd->pd == pd);
+ if ((type == 0 && pd->petDB->attack_rate == 0) || (type != 0 && pd->petDB->defence_attack_rate == 0))
+ return 0; // If base rate is 0, there's nothing to do.
- if( bl == NULL || bl->type != BL_MOB || bl->prev == NULL
- || pd->pet.intimate < battle_config.pet_support_min_friendly
- || pd->pet.hungry < 1
- || pd->pet.class_ == status->get_class(bl))
- return 0;
-
- if( pd->bl.m != bl->m
- || !check_distance_bl(&pd->bl, bl, pd->db->range2))
+ if (bl->type != BL_MOB || bl->prev == NULL || pd->pet.intimate < battle_config.pet_support_min_friendly
+ || pd->pet.hungry <= PET_HUNGER_STARVING || pd->pet.class_ == status->get_class(bl)
+ || pd->bl.m != bl->m || !check_distance_bl(&pd->bl, bl, pd->db->range2)
+ || status->check_skilluse(&pd->bl, bl, 0, 0) == 0) {
return 0;
+ }
- if (!status->check_skilluse(&pd->bl, bl, 0, 0))
- return 0;
+ int rate = ((type == 0) ? pd->petDB->attack_rate : pd->petDB->defence_attack_rate) * pd->rate_fix / 1000;
- if(!type) {
- rate = pd->petDB->attack_rate;
- rate = rate * pd->rate_fix/1000;
- if(pd->petDB->attack_rate > 0 && rate <= 0)
- rate = 1;
- } else {
- rate = pd->petDB->defence_attack_rate;
- rate = rate * pd->rate_fix/1000;
- if(pd->petDB->defence_attack_rate > 0 && rate <= 0)
- rate = 1;
- }
- if(rnd()%10000 < rate)
- {
- if(pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate)
- pd->target_id = bl->id;
- }
+ if (rnd() % 10000 < max(rate, 1) && (pd->target_id == 0 || rnd() % 10000 < pd->petDB->change_target_rate))
+ pd->target_id = bl->id;
return 0;
}
+
/*==========================================
* Pet SC Check [Skotlex]
*------------------------------------------*/
-int pet_sc_check(struct map_session_data *sd, int type)
+static int pet_sc_check(struct map_session_data *sd, int type)
{
struct pet_data *pd;
@@ -206,56 +259,77 @@ int pet_sc_check(struct map_session_data *sd, int type)
return 0;
}
-int pet_hungry(int tid, int64 tick, int id, intptr_t data) {
- struct map_session_data *sd;
- struct pet_data *pd;
- int interval;
+/**
+ * Updates a pet's hunger value and timer and updates the pet's intimacy value if starving.
+ *
+ * @param tid The timer ID.
+ * @param tick The base amount of ticks to add to the pet's hunger timer. (The timer's current ticks when calling this fuction.)
+ * @param id The pet master's account ID.
+ * @param data Unused.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_hungry(int tid, int64 tick, int id, intptr_t data)
+{
+ struct map_session_data *sd = map->id2sd(id);
- sd=map->id2sd(id);
- if(!sd)
+ if (sd == NULL || sd->status.pet_id == 0 || sd->pd == NULL)
return 1;
- if(!sd->status.pet_id || !sd->pd)
- return 1;
+ struct pet_data *pd = sd->pd;
- pd = sd->pd;
- if(pd->pet_hungry_timer != tid){
- ShowError("pet_hungry_timer %d != %d\n",pd->pet_hungry_timer,tid);
+ /**
+ * If HungerDelay is 0, there's nothing to do.
+ * Actually this shouldn't happen, since the timer wasn't added in pet_data_init(), but just to be sure...
+ *
+ **/
+ if (pd->petDB->hungry_delay == 0) {
+ pet->hungry_timer_delete(pd);
return 0;
}
+
+ if (pd->pet_hungry_timer != tid) {
+ ShowError("pet_hungry: pet_hungry_timer %d != %d\n", pd->pet_hungry_timer, tid);
+ return 1;
+ }
+
pd->pet_hungry_timer = INVALID_TIMER;
- if (pd->pet.intimate <= 0)
- return 1; //You lost the pet already, the rest is irrelevant.
+ if (pd->pet.intimate <= PET_INTIMACY_NONE)
+ return 1; // You lost the pet already, the rest is irrelevant.
- pd->pet.hungry--;
- if( pd->pet.hungry < 0 )
- {
+ pet->set_hunger(pd, pd->pet.hungry - pd->petDB->hunger_decrement);
+
+ // Pet auto-feed.
+ if (battle_config.feature_enable_pet_autofeed == 1) {
+ if (pd->petDB->autofeed == 1 && pd->pet.autofeed == 1 && pd->pet.hungry <= PET_HUNGER_HUNGRY)
+ pet->food(sd, pd);
+ }
+
+ int interval = pd->petDB->hungry_delay;
+
+ if (pd->pet.hungry == PET_HUNGER_STARVING) {
pet_stop_attack(pd);
- pd->pet.hungry = 0;
- pet->set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease);
- if( pd->pet.intimate <= 0 )
- {
- pd->pet.intimate = 0;
+ pet->set_intimate(pd, pd->pet.intimate - pd->petDB->starving_decrement);
+
+ if (pd->pet.intimate == PET_INTIMACY_NONE)
pd->status.speed = pd->db->status.speed;
- }
+
status_calc_pet(pd, SCO_NONE);
- clif->send_petdata(sd,pd,1,pd->pet.intimate);
+ clif->send_petdata(sd, pd, 1, pd->pet.intimate);
+
+ if (pd->petDB->starving_delay > 0)
+ interval = pd->petDB->starving_delay;
}
- clif->send_petdata(sd,pd,2,pd->pet.hungry);
- if(battle_config.pet_hungry_delay_rate != 100)
- interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
- else
- interval = pd->petDB->hungry_delay;
- if(interval <= 0)
- interval = 1;
- pd->pet_hungry_timer = timer->add(tick+interval,pet->hungry,sd->bl.id,0);
+ clif->send_petdata(sd, pd, 2, pd->pet.hungry);
+ interval = interval * battle_config.pet_hungry_delay_rate / 100;
+ pd->pet_hungry_timer = timer->add(tick + max(interval, 1), pet->hungry, sd->bl.id, 0);
return 0;
}
-int search_petDB_index(int key,int type)
+static int search_petDB_index(int key, int type)
{
int i;
@@ -276,7 +350,7 @@ int search_petDB_index(int key,int type)
return -1;
}
-int pet_hungry_timer_delete(struct pet_data *pd)
+static int pet_hungry_timer_delete(struct pet_data *pd)
{
nullpo_ret(pd);
if(pd->pet_hungry_timer != INVALID_TIMER) {
@@ -287,40 +361,69 @@ int pet_hungry_timer_delete(struct pet_data *pd)
return 1;
}
-int pet_performance(struct map_session_data *sd, struct pet_data *pd)
+/**
+ * Makes a pet start performing/dancing.
+ *
+ * @param sd Unused.
+ * @param pd The pet.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
+static int pet_performance(struct map_session_data *sd, struct pet_data *pd)
{
+ nullpo_ret(pd);
+
int val;
- if (pd->pet.intimate > 900)
- val = (pd->petDB->s_perfor > 0)? 4:3;
- else if(pd->pet.intimate > 750) //TODO: this is way too high
+ if (pd->pet.intimate > PET_INTIMACY_LOYAL)
+ val = (pd->petDB->s_perfor > 0) ? 4 : 3;
+ else if (pd->pet.intimate > PET_INTIMACY_CORDIAL) //TODO: This is way too high.
val = 2;
else
val = 1;
- pet_stop_walking(pd,STOPWALKING_FLAG_NONE | (2000<<8)); // Stop walking for 2000ms
- clif->send_petdata(NULL, pd, 4, rnd()%val + 1);
- pet->lootitem_drop(pd,NULL);
+ pet_stop_walking(pd, STOPWALKING_FLAG_NONE | (2000 << 8)); // Stop walking for 2 seconds.
+ clif->send_petdata(NULL, pd, 4, rnd() % val + 1);
+ pet->lootitem_drop(pd, NULL);
+
return 1;
}
-int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
+static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
{
- struct item tmp_item;
- int flag;
+ int i;
+ nullpo_retr(1, sd);
+ nullpo_retr(1, pd);
pet->lootitem_drop(pd,sd);
- memset(&tmp_item,0,sizeof(tmp_item));
- tmp_item.nameid = pd->petDB->EggID;
- tmp_item.identify = 1;
- tmp_item.card[0] = CARD0_PET;
- tmp_item.card[1] = GetWord(pd->pet.pet_id,0);
- tmp_item.card[2] = GetWord(pd->pet.pet_id,1);
- tmp_item.card[3] = pd->pet.rename_flag;
- if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_EGG))) {
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+
+ // Pet Evolution
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET &&
+ pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]));
+
+ if (i != sd->status.inventorySize) {
+ sd->status.inventory[i].attribute &= ~ATTR_BROKEN;
+ sd->status.inventory[i].bound = IBT_NONE;
+ } else {
+ // The pet egg wasn't found: it was probably hatched with the old system that deleted the egg.
+ struct item tmp_item = {0};
+ int flag;
+
+ tmp_item.nameid = pd->petDB->EggID;
+ tmp_item.identify = 1;
+ tmp_item.card[0] = CARD0_PET;
+ tmp_item.card[1] = GetWord(pd->pet.pet_id, 0);
+ tmp_item.card[2] = GetWord(pd->pet.pet_id, 1);
+ tmp_item.card[3] = pd->pet.rename_flag;
+ if ((flag = pc->additem(sd, &tmp_item, 1, LOG_TYPE_EGG)) != 0) {
+ clif->additem(sd, 0, 0, flag);
+ map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
+ }
}
+#if PACKETVER >= 20180704
+ clif->inventoryList(sd);
+ clif->send_petdata(sd, pd, 6, 0);
+#endif
pd->pet.incubate = 1;
unit->free(&pd->bl,CLR_OUTSIGHT);
@@ -330,83 +433,87 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
return 1;
}
-int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo)
+/**
+ * Initializes a pet.
+ *
+ * @param sd The pet's master.
+ * @param petinfo The pet's status data.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo)
{
- struct pet_data *pd;
- int i=0,interval=0;
-
nullpo_retr(1, sd);
- Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd);
+ nullpo_retr(1, petinfo);
+ Assert_retr(1, sd->status.pet_id == 0 || sd->pd == NULL || sd->pd->msd == sd);
- if(sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->char_id) {
+ if (sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->char_id) {
sd->status.pet_id = 0;
return 1;
}
+
if (sd->status.pet_id != petinfo->pet_id) {
- if (sd->status.pet_id) {
- //Wrong pet?? Set incubate to no and send it back for saving.
+ if (sd->status.pet_id != 0) { // Wrong pet? Set incubate to no and send it back for saving.
petinfo->incubate = 1;
- intif->save_petdata(sd->status.account_id,petinfo);
+ intif->save_petdata(sd->status.account_id, petinfo);
sd->status.pet_id = 0;
return 1;
}
- //The pet_id value was lost? odd... restore it.
- sd->status.pet_id = petinfo->pet_id;
+
+ sd->status.pet_id = petinfo->pet_id; // The pet_id value was lost? Odd... Restore it.
}
- i = pet->search_petDB_index(petinfo->class_,PET_CLASS);
- if(i < 0) {
+ int i = pet->search_petDB_index(petinfo->class_, PET_CLASS);
+
+ if (i == INDEX_NOT_FOUND) {
sd->status.pet_id = 0;
return 1;
}
+
+ struct pet_data *pd;
+
CREATE(pd, struct pet_data, 1);
- pd->bl.type = BL_PET;
- pd->bl.id = npc->get_new_npc_id();
+ memcpy(&pd->pet, petinfo, sizeof(struct s_pet));
sd->pd = pd;
-
pd->msd = sd;
pd->petDB = &pet->db[i];
- pd->db = mob->db(petinfo->class_);
- memcpy(&pd->pet, petinfo, sizeof(struct s_pet));
- status->set_viewdata(&pd->bl, petinfo->class_);
+ pd->db = mob->db(pd->petDB->class_);
+ pd->bl.type = BL_PET;
+ pd->bl.id = npc->get_new_npc_id();
+ status->set_viewdata(&pd->bl, pd->petDB->class_);
unit->dataset(&pd->bl);
pd->ud.dir = sd->ud.dir;
-
pd->bl.m = sd->bl.m;
pd->bl.x = sd->bl.x;
pd->bl.y = sd->bl.y;
unit->calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
pd->bl.x = pd->ud.to_x;
pd->bl.y = pd->ud.to_y;
-
map->addiddb(&pd->bl);
- status_calc_pet(pd,SCO_FIRST);
-
+ status_calc_pet(pd, SCO_FIRST);
pd->last_thinktime = timer->gettick();
pd->state.skillbonus = 0;
- if( battle_config.pet_status_support )
- script->run_pet(pet->db[i].pet_script,0,sd->bl.id,0);
+ if (pd->petDB->pet_script != NULL && battle_config.pet_status_support == 1)
+ script->run_pet(pd->petDB->pet_script, 0, sd->bl.id, 0);
- if( pd->petDB ) {
- if( pd->petDB->equip_script )
- status_calc_pc(sd,SCO_NONE);
+ if (pd->petDB->equip_script != NULL)
+ status_calc_pc(sd, SCO_NONE);
- if( battle_config.pet_hungry_delay_rate != 100 )
- interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
- else
- interval = pd->petDB->hungry_delay;
+ pd->pet_hungry_timer = INVALID_TIMER;
+
+ if (pd->petDB->hungry_delay > 0) {
+ int interval = pd->petDB->hungry_delay * battle_config.pet_hungry_delay_rate / 100;
+ pd->pet_hungry_timer = timer->add(timer->gettick() + max(interval, 1), pet->hungry, sd->bl.id, 0);
}
- if( interval <= 0 )
- interval = 1;
- pd->pet_hungry_timer = timer->add(timer->gettick() + interval, pet->hungry, sd->bl.id, 0);
return 0;
}
-int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
+static int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
{
nullpo_retr(1, sd);
+ nullpo_retr(1, petinfo);
Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd);
if(sd->status.pet_id && petinfo->incubate == 1) {
@@ -432,6 +539,9 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
clif->spawn(&sd->pd->bl);
clif->send_petdata(sd,sd->pd, 0,0);
clif->send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style);
+#if PACKETVER >= 20180704
+ clif->send_petdata(sd, sd->pd, 6, 1);
+#endif
clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
clif->send_petstatus(sd);
}
@@ -440,9 +550,11 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
return 0;
}
-int pet_recv_petdata(int account_id,struct s_pet *p,int flag) {
+static int pet_recv_petdata(int account_id, struct s_pet *p, int flag)
+{
struct map_session_data *sd;
+ nullpo_retr(1, p);
sd = map->id2sd(account_id);
if(sd == NULL)
return 1;
@@ -452,19 +564,23 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) {
}
if(p->incubate == 1) {
int i;
- //Delete egg from inventory. [Skotlex]
- for (i = 0; i < MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].card[0] == CARD0_PET &&
- p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]))
- break;
- }
- if(i >= MAX_INVENTORY) {
+ // Get Egg Index
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET &&
+ p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]));
+
+ if(i == sd->status.inventorySize) {
ShowError("pet_recv_petdata: Hatching pet (%d:%s) aborted, couldn't find egg in inventory for removal!\n",p->pet_id, p->name);
sd->status.pet_id = 0;
return 1;
}
- if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg.
- pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG);
+
+
+ if (!pet->birth_process(sd,p)) {
+ // Pet Evolution, Hide the egg by setting broken attribute (0x2) [Asheraf]
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ // bind the egg to the character to avoid moving it via forged packets [Asheraf]
+ sd->status.inventory[i].bound = IBT_CHARACTER;
+ }
} else {
pet->data_init(sd,p);
if(sd->pd && sd->bl.prev != NULL) {
@@ -480,11 +596,11 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) {
return 0;
}
-int pet_select_egg(struct map_session_data *sd,short egg_index)
+static int pet_select_egg(struct map_session_data *sd, int egg_index)
{
nullpo_ret(sd);
- if(egg_index < 0 || egg_index >= MAX_INVENTORY)
+ if (egg_index < 0 || egg_index >= sd->status.inventorySize)
return 0; //Forged packet!
if(sd->status.inventory[egg_index].card[0] == CARD0_PET)
@@ -495,7 +611,7 @@ int pet_select_egg(struct map_session_data *sd,short egg_index)
return 0;
}
-int pet_catch_process1(struct map_session_data *sd,int target_class)
+static int pet_catch_process1(struct map_session_data *sd, int target_class)
{
nullpo_ret(sd);
@@ -505,53 +621,66 @@ int pet_catch_process1(struct map_session_data *sd,int target_class)
return 0;
}
-int pet_catch_process2(struct map_session_data* sd, int target_id) {
- struct mob_data *md = NULL;
- struct block_list *bl = NULL;
- int i = 0, pet_catch_rate = 0;
-
+/**
+ * Begins the actual process of catching a monster.
+ *
+ * @param sd The character who tries to catch the monster.
+ * @param target_id The monster ID of the pet, which the character tries to catch.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_catch_process2(struct map_session_data *sd, int target_id)
+{
nullpo_retr(1, sd);
- bl = map->id2bl(target_id); // TODO: Why does this not use map->id2md?
- md = BL_CAST(BL_MOB, bl);
- if (md == NULL || md->bl.prev == NULL) {
- // Invalid inputs/state, abort capture.
- clif->pet_roulette(sd,0);
+ struct mob_data *md = BL_CAST(BL_MOB, map->id2bl(target_id)); //TODO: Why does this not use map->id2md?
+
+ if (md == NULL || md->bl.prev == NULL) { // Invalid inputs/state, abort capture.
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
- sd->itemid = sd->itemindex = -1;
+ sd->itemid = -1;
+ sd->itemindex = -1;
return 1;
}
- //FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage]
+ //FIXME: Delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume. [ultramage]
- i = pet->search_petDB_index(md->class_,PET_CLASS);
- //catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex]
- if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS))
+ // catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex]
+ if (sd->catch_target_class == 0 && (md->status.mode & MD_BOSS) == 0)
sd->catch_target_class = md->class_;
- if(i < 0 || sd->catch_target_class != md->class_) {
- clif->emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them.
- clif->pet_roulette(sd,0);
+
+ int i = pet->search_petDB_index(md->class_, PET_CLASS);
+
+ if (i == INDEX_NOT_FOUND || sd->catch_target_class != md->class_) {
+ clif->emotion(&md->bl, E_AG); // Mob will do /ag if wrong lure is used on it.
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
return 1;
}
- pet_catch_rate = (pet->db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.max_hp))/100;
+ int pet_catch_rate;
+ int capture = pet->db[i].capture;
+ int mob_hp_perc = get_percentage(md->status.hp, md->status.max_hp);
- if(pet_catch_rate < 1) pet_catch_rate = 1;
- if(battle_config.pet_catch_rate != 100)
- pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100;
+ if (battle_config.pet_catch_rate_official_formula == 1) {
+ pet_catch_rate = capture * (100 - mob_hp_perc) / 100 + capture;
+ } else {
+ int lvl_diff_mod = (sd->status.base_level - md->level) * 30;
+ int char_luk_mod = sd->battle_status.luk * 20;
+ pet_catch_rate = (capture + lvl_diff_mod + char_luk_mod) * (200 - mob_hp_perc) / 100;
+ }
- if(rnd()%10000 < pet_catch_rate)
- {
- unit->remove_map(&md->bl,CLR_OUTSIGHT,ALC_MARK);
+ pet_catch_rate = cap_value(pet_catch_rate, 1, 10000) * battle_config.pet_catch_rate / 100;
+
+ if (rnd() % 10000 < pet_catch_rate) {
+ unit->remove_map(&md->bl, CLR_OUTSIGHT, ALC_MARK);
status_kill(&md->bl);
- clif->pet_roulette(sd,1);
- intif->create_pet(sd->status.account_id,sd->status.char_id,pet->db[i].class_,mob->db(pet->db[i].class_)->lv,
- pet->db[i].EggID,0,pet->db[i].intimate,100,0,1,pet->db[i].jname);
- }
- else
- {
- clif->pet_roulette(sd,0);
+ clif->pet_roulette(sd, 1);
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[i].class_, mob->db(pet->db[i].class_)->lv,
+ pet->db[i].EggID, 0, pet->db[i].intimate, PET_HUNGER_STUFFED, 0, 1, pet->db[i].jname);
+ achievement->validate_taming(sd, pet->db[i].class_);
+ } else {
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
}
@@ -567,7 +696,8 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) {
* 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 ) {
+static bool pet_get_egg(int account_id, int pet_class, int pet_id)
+{
struct map_session_data *sd;
struct item tmp_item;
int i = 0, ret = 0;
@@ -601,56 +731,67 @@ bool pet_get_egg(int account_id, short pet_class, int pet_id ) {
tmp_item.card[3] = 0; //New pets are not named.
if((ret = pc->additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) {
clif->additem(sd,0,0,ret);
- map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
return true;
}
-int pet_menu(struct map_session_data *sd,int menunum)
+/**
+ * Performs selected pet menu option.
+ *
+ * @param sd The pet's master.
+ * @param menunum The selected menu option.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_menu(struct map_session_data *sd, int menunum)
{
- struct item_data *egg_id;
- nullpo_ret(sd);
- if (sd->pd == NULL)
- return 1;
+ nullpo_retr(1, sd);
+ nullpo_retr(1, sd->pd);
- //You lost the pet already.
- if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incubate)
- return 1;
+ if (sd->status.pet_id == 0 || sd->pd->pet.intimate <= PET_INTIMACY_NONE || sd->pd->pet.incubate != 0)
+ return 1; // You lost the pet already.
+
+ struct item_data *egg_id = itemdb->exists(sd->pd->petDB->EggID);
- egg_id = itemdb->exists(sd->pd->petDB->EggID);
- if (egg_id) {
- if ((egg_id->flag.trade_restriction&ITR_NODROP) && !pc->inventoryblank(sd)) {
- clif->message(sd->fd, msg_sd(sd,451)); // You can't return your pet because your inventory is full.
+ if (egg_id != NULL) {
+ if ((egg_id->flag.trade_restriction & ITR_NODROP) != 0 && pc->inventoryblank(sd) == 0) {
+ clif->message(sd->fd, msg_sd(sd, 451)); // You can't return your pet because your inventory is full.
return 1;
}
}
- switch(menunum) {
- case 0:
- clif->send_petstatus(sd);
- break;
- case 1:
- pet->food(sd, sd->pd);
- break;
- case 2:
- pet->performance(sd, sd->pd);
- break;
- case 3:
- pet->return_egg(sd, sd->pd);
- break;
- case 4:
- pet->unequipitem(sd, sd->pd);
- break;
+ switch (menunum) {
+ case 0:
+ clif->send_petstatus(sd);
+ break;
+ case 1:
+ pet->food(sd, sd->pd);
+ break;
+ case 2:
+ pet->performance(sd, sd->pd);
+ break;
+ case 3:
+ pet->return_egg(sd, sd->pd);
+ break;
+ case 4:
+ pet->unequipitem(sd, sd->pd);
+ break;
+ default: ;
+ ShowError("pet_menu: Unexpected menu option: %d\n", menunum);
+ return 1;
}
+
return 0;
}
-int pet_change_name(struct map_session_data *sd, const char *name)
+static int pet_change_name(struct map_session_data *sd, const char *name)
{
int i;
struct pet_data *pd;
nullpo_retr(1, sd);
+ nullpo_retr(1, name);
pd = sd->pd;
if((pd == NULL) || (pd->pet.rename_flag == 1 && !battle_config.pet_rename))
@@ -664,11 +805,14 @@ int pet_change_name(struct map_session_data *sd, const char *name)
return intif_rename_pet(sd, name);
}
-int pet_change_name_ack(struct map_session_data *sd, const char *name, int flag)
+static int pet_change_name_ack(struct map_session_data *sd, const char *name, int flag)
{
- struct pet_data *pd = sd->pd;
+ struct pet_data *pd;
char *newname = NULL;
- if (!pd) return 0;
+ nullpo_ret(sd);
+ nullpo_ret(name);
+ pd = sd->pd;
+ if (pd == NULL) return 0;
newname = aStrndup(name, NAME_LENGTH-1);
normalize_name(newname, " ");//bugreport:3032 // FIXME[Haru]: This should be normalized by the inter-server (so that it's const here)
@@ -681,14 +825,15 @@ int pet_change_name_ack(struct map_session_data *sd, const char *name, int flag)
}
safestrncpy(pd->pet.name, newname, NAME_LENGTH);
aFree(newname);
- clif->charnameack (0,&pd->bl);
+ clif->blname_ack(0,&pd->bl);
pd->pet.rename_flag = 1;
clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
clif->send_petstatus(sd);
return 1;
}
-int pet_equipitem(struct map_session_data *sd,int index) {
+static int pet_equipitem(struct map_session_data *sd, int index)
+{
struct pet_data *pd;
int nameid;
@@ -720,10 +865,13 @@ int pet_equipitem(struct map_session_data *sd,int index) {
return 0;
}
-int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
+static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
+{
struct item tmp_item;
int nameid,flag;
+ nullpo_retr(1, sd);
+ nullpo_retr(1, pd);
if(pd->pet.equip == 0)
return 1;
@@ -736,7 +884,7 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
tmp_item.identify = 1;
if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_CONSUME))) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
if( battle_config.pet_equip_required )
{ // Skotlex: halt support timers if needed
@@ -759,52 +907,61 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
return 0;
}
-int pet_food(struct map_session_data *sd, struct pet_data *pd) {
- int i, food_id;
+/**
+ * Feeds a pet and updates its intimacy value.
+ *
+ * @param sd The pet's master.
+ * @param pd The pet.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_food(struct map_session_data *sd, struct pet_data *pd)
+{
+ nullpo_retr(1, sd);
+ nullpo_retr(1, pd);
- food_id = pd->petDB->FoodID;
- i = pc->search_inventory(sd, food_id);
- if(i == INDEX_NOT_FOUND) {
- clif->pet_food(sd, food_id, 0);
+ int i = pc->search_inventory(sd, pd->petDB->FoodID);
+
+ if (i == INDEX_NOT_FOUND) {
+ clif->pet_food(sd, pd->petDB->FoodID, 0);
return 1;
}
+
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME);
- if (pd->pet.hungry > 90) {
- pet->set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
- } else {
- int add_intimate = 0;
- if (battle_config.pet_friendly_rate != 100)
- add_intimate = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100;
- else
- add_intimate = pd->petDB->r_hungry;
- if (pd->pet.hungry > 75) {
- add_intimate = add_intimate >> 1;
- if (add_intimate <= 0)
- add_intimate = 1;
- }
- pet->set_intimate(pd, pd->pet.intimate + add_intimate);
- }
- if (pd->pet.intimate <= 0) {
- pd->pet.intimate = 0;
+ int intimacy = 0;
+
+ if (pd->pet.hungry >= PET_HUNGER_STUFFED)
+ intimacy -= pd->petDB->r_full; // Decrease intimacy by OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_SATISFIED)
+ intimacy -= pd->petDB->r_full / 2; // Decrease intimacy by 50% of OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_NEUTRAL)
+ intimacy -= pd->petDB->r_full * 5 / 100; // Decrease intimacy by 5% of OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_HUNGRY)
+ intimacy += pd->petDB->r_hungry * 75 / 100; // Increase intimacy by 75% of FeedIncrement.
+ else if (pd->pet.hungry > PET_HUNGER_VERY_HUNGRY)
+ intimacy += pd->petDB->r_hungry; // Increase intimacy by FeedIncrement.
+ else
+ intimacy += pd->petDB->r_hungry / 2; // Increase intimacy by 50% of FeedIncrement.
+
+ intimacy = intimacy * battle_config.pet_friendly_rate / 100;
+ pet->set_intimate(pd, pd->pet.intimate + intimacy);
+
+ if (pd->pet.intimate == PET_INTIMACY_NONE) {
pet_stop_attack(pd);
pd->status.speed = pd->db->status.speed;
- } else if (pd->pet.intimate > 1000) {
- pd->pet.intimate = 1000;
}
- status_calc_pet(pd, SCO_NONE);
- pd->pet.hungry += pd->petDB->fullness;
- if( pd->pet.hungry > 100 )
- pd->pet.hungry = 100;
- clif->send_petdata(sd,pd,2,pd->pet.hungry);
- clif->send_petdata(sd,pd,1,pd->pet.intimate);
- clif->pet_food(sd,pd->petDB->FoodID,1);
+ status_calc_pet(pd, SCO_NONE);
+ pet->set_hunger(pd, pd->pet.hungry + pd->petDB->fullness);
+ clif->send_petdata(sd, pd, 2, pd->pet.hungry);
+ clif->send_petdata(sd, pd, 1, pd->pet.intimate);
+ clif->pet_food(sd, pd->petDB->FoodID, 1);
return 0;
}
-int pet_randomwalk(struct pet_data *pd, int64 tick)
+static int pet_randomwalk(struct pet_data *pd, int64 tick)
{
nullpo_ret(pd);
Assert_ret(pd->msd == 0 || pd->msd->pd == pd);
@@ -818,7 +975,8 @@ int pet_randomwalk(struct pet_data *pd, int64 tick)
int r=rnd();
int x=pd->bl.x+r%(d*2+1)-d;
int y=pd->bl.y+r/(d*2+1)%(d*2+1)-d;
- if(map->getcell (pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&pd->bl, x, y, 0)) {
+ if (map->getcell(pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) != 0
+ && unit->walk_toxy(&pd->bl, x, y, 0) == 0) {
pd->move_fail_count=0;
break;
}
@@ -845,133 +1003,159 @@ int pet_randomwalk(struct pet_data *pd, int64 tick)
return 0;
}
-int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick) {
- struct block_list *target = NULL;
+/**
+ * Performs pet's AI actions. (Moving, attacking, etc.)
+ *
+ * @param pd The pet.
+ * @param sd The pet's master.
+ * @param tick Timestamp of last support.
+ * @return Always 0.
+ *
+ **/
+static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick)
+{
+ nullpo_ret(pd);
+ nullpo_ret(pd->bl.prev);
+ nullpo_ret(sd);
+ nullpo_ret(sd->bl.prev);
- if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL)
+ if (DIFF_TICK(tick, pd->last_thinktime) < MIN_PETTHINKTIME)
return 0;
- if(DIFF_TICK(tick,pd->last_thinktime) < MIN_PETTHINKTIME)
- return 0;
- pd->last_thinktime=tick;
+ pd->last_thinktime = tick;
- if(pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m)
+ if (pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m)
return 0;
- if(pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2)
- return 0; //No thinking when you just started to walk.
+ if (pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2)
+ return 0; // No thinking when you just started to walk.
- if(pd->pet.intimate <= 0) {
- //Pet should just... well, random walk.
- pet->randomwalk(pd,tick);
+ if (pd->pet.intimate <= PET_INTIMACY_NONE) {
+ pet->randomwalk(pd, tick); // Pet should just... well, random walk.
return 0;
}
- if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) {
- //Master too far, chase.
- if(pd->target_id)
+ if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) { // Master too far away. Chase him.
+ if (pd->target_id != 0)
pet->unlocktarget(pd);
- if(pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id)
- return 0; //Already walking to him
+
+ if (pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id)
+ return 0; // Already walking to him.
+
if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0)
- return 0; //Can't move yet.
- pd->status.speed = (sd->battle_status.speed>>1);
- if(pd->status.speed <= 0)
- pd->status.speed = 1;
- if (!unit->walktobl(&pd->bl, &sd->bl, 3, 0))
- pet->randomwalk(pd,tick);
+ return 0; // Can't move yet.
+
+ pd->status.speed = max(sd->battle_status.speed / 2, MIN_WALK_SPEED);
+
+ if (unit->walktobl(&pd->bl, &sd->bl, 3, 0) == 0)
+ pet->randomwalk(pd, tick);
+
return 0;
}
- //Return speed to normal.
- if (pd->status.speed != pd->petDB->speed) {
+ if (pd->status.speed != pd->petDB->speed) { // Reset speed to normal.
if (pd->ud.walktimer != INVALID_TIMER)
- return 0; //Wait until the pet finishes walking back to master.
+ return 0; // Wait until the pet finishes walking back to master.
+
pd->status.speed = pd->petDB->speed;
- pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1;
+ pd->ud.state.speed_changed = 1;
+ pd->ud.state.change_walk_target = 1;
}
- if (pd->target_id) {
- target= map->id2bl(pd->target_id);
- if (!target || pd->bl.m != target->m || status->isdead(target)
- || !check_distance_bl(&pd->bl, target, pd->db->range3)
- ) {
+ struct block_list *target = NULL;
+
+ if (pd->target_id != 0) {
+ target = map->id2bl(pd->target_id);
+
+ if (target == NULL || pd->bl.m != target->m || status->isdead(target) == 1
+ || !check_distance_bl(&pd->bl, target, pd->db->range3)) {
target = NULL;
pet->unlocktarget(pd);
}
}
- if(!target && pd->loot && pd->msd && pc_has_permission(pd->msd, PC_PERM_TRADE) && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) {
- //Use half the pet's range of sight.
- map->foreachinrange(pet->ai_sub_hard_lootsearch,&pd->bl,
- pd->db->range2/2, BL_ITEM,pd,&target);
+ if (target == NULL && pd->loot != NULL && pd->msd != NULL && pc_has_permission(pd->msd, PC_PERM_TRADE)
+ && pd->loot->count < pd->loot->max && DIFF_TICK(tick, pd->ud.canact_tick) > 0) { // Use half the pet's range of sight.
+ map->foreachinrange(pet->ai_sub_hard_lootsearch, &pd->bl, pd->db->range2 / 2, BL_ITEM, pd, &target);
}
- if (!target) {
- //Just walk around.
+ if (target == NULL) { // Just walk around.
if (check_distance_bl(&sd->bl, &pd->bl, 3))
- return 0; //Already next to master.
+ return 0; // Already next to master.
- if(pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3))
- return 0; //Already walking to him
+ if (pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x, pd->ud.to_y, 3))
+ return 0; // Already walking to him.
unit->calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
- if(!unit->walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0))
- pet->randomwalk(pd,tick);
+
+ if (unit->walk_toxy(&pd->bl, pd->ud.to_x, pd->ud.to_y, 0) != 0)
+ pet->randomwalk(pd, tick);
return 0;
}
- if(pd->ud.target == target->id &&
- (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
- return 0; //Target already locked.
+ if (pd->ud.target == target->id && (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
+ return 0; // Target already locked.
+
+ if (target->type != BL_ITEM) { // Target is enemy. Chase or attack it.
+ if (!battle->check_range(&pd->bl, target, pd->status.rhw.range)) { // Chase enemy.
+ if (unit->walktobl(&pd->bl, target, pd->status.rhw.range, 2) == 0) // Enemy is unreachable.
+ pet->unlocktarget(pd);
- if (target->type != BL_ITEM)
- { //enemy targetted
- if(!battle->check_range(&pd->bl,target,pd->status.rhw.range)) {
- //Chase
- if(!unit->walktobl(&pd->bl, target, pd->status.rhw.range, 2))
- pet->unlocktarget(pd); //Unreachable target.
return 0;
}
- //Continuous attack.
- unit->attack(&pd->bl, pd->target_id, 1);
- } else {
- //Item Targeted, attempt loot
- if (!check_distance_bl(&pd->bl, target, 1)) {
- //Out of range
- if(!unit->walktobl(&pd->bl, target, 1, 1)) //Unreachable target.
+
+ unit->attack(&pd->bl, pd->target_id, 1); // Start/continue attacking.
+ } else { // Target is item. Attempt looting.
+ if (!check_distance_bl(&pd->bl, target, 1)) { // Item is out of range.
+ if (unit->walktobl(&pd->bl, target, 1, 1) == 0) // Item is unreachable.
pet->unlocktarget(pd);
+
return 0;
- } else{
+ }
+
+ if (pd->loot->count < pd->loot->max) {
struct flooritem_data *fitem = BL_UCAST(BL_ITEM, target);
- if(pd->loot->count < pd->loot->max){
- memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0]));
- pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount;
- map->clearflooritem(target);
- }
- //Target is unlocked regardless of whether it was picked or not.
- pet->unlocktarget(pd);
+
+ 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);
}
+
+ pet->unlocktarget(pd); // Target is unlocked regardless of whether the item was picked or not.
}
+
return 0;
}
-int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) {
- int64 tick = va_arg(ap,int64);
- if(sd->status.pet_id && sd->pd)
- pet->ai_sub_hard(sd->pd,sd,tick);
+/**
+ * Calls pet_ai_sub_hard() for a character's pet if conditions are fulfilled.
+ *
+ * @param sd The character.
+ * @param ap Additional arguments. In this case only the time stamp of pet AI timer execution.
+ * @return Always 0.
+ *
+ **/
+static int pet_ai_sub_foreachclient(struct map_session_data *sd, va_list ap)
+{
+ nullpo_ret(sd);
+
+ int64 tick = va_arg(ap, int64);
+
+ if (sd->bl.prev != NULL && sd->status.pet_id != 0 && sd->pd != NULL && sd->pd->bl.prev != NULL)
+ pet->ai_sub_hard(sd->pd, sd, tick);
return 0;
}
-int pet_ai_hard(int tid, int64 tick, int id, intptr_t data) {
+static int pet_ai_hard(int tid, int64 tick, int id, intptr_t data)
+{
map->foreachpc(pet->ai_sub_foreachclient,tick);
return 0;
}
-int pet_ai_sub_hard_lootsearch(struct block_list *bl, va_list ap)
+static int pet_ai_sub_hard_lootsearch(struct block_list *bl, va_list ap)
{
struct pet_data *pd = va_arg(ap,struct pet_data *);
struct block_list **target = va_arg(ap,struct block_list**);
@@ -999,7 +1183,8 @@ int pet_ai_sub_hard_lootsearch(struct block_list *bl, va_list ap)
return 0;
}
-int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
+static int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data)
+{
struct item_drop_list *list;
struct item_drop *ditem;
list=(struct item_drop_list *)data;
@@ -1008,7 +1193,7 @@ int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
struct item_drop *ditem_prev;
map->addflooritem(NULL, &ditem->item_data, ditem->item_data.amount,
list->m, list->x, list->y,
- list->first_charid, list->second_charid, list->third_charid, 0);
+ list->first_charid, list->second_charid, list->third_charid, 0, false);
ditem_prev = ditem;
ditem = ditem->next;
ers_free(pet->item_drop_ers, ditem_prev);
@@ -1017,7 +1202,7 @@ int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
+static int pet_lootitem_drop(struct pet_data *pd, struct map_session_data *sd)
{
int i,flag=0;
struct item_drop_list *dlist;
@@ -1063,58 +1248,70 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
return 1;
}
-/*==========================================
- * 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;
- int bonus;
- int duration = 0;
+/**
+ * Applies pet's stat bonuses to its master. (See petskillbonus() script command.)
+ *
+ * @param tid The timer ID
+ * @param tick The base amount of ticks to add to the pet's bonus timer. (The timer's current ticks when calling this fuction.)
+ * @param id The pet's master's account ID.
+ * @param data Unused.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
+static int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct map_session_data *sd = map->id2sd(id);
- if(sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL)
+ if (sd == NULL || sd->pd == NULL || sd->pd->bonus == NULL)
return 1;
- pd=sd->pd;
+ struct pet_data *pd = sd->pd;
- if(pd->bonus->timer != tid) {
- ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
+ if (pd->bonus->timer != tid) {
+ ShowError("pet_skill_bonus_timer %d != %d\n", pd->bonus->timer, tid);
pd->bonus->timer = INVALID_TIMER;
- return 0;
+ return 1;
}
- // determine the time for the next timer
- if (pd->state.skillbonus && pd->bonus->delay > 0) {
+ int bonus;
+ int duration;
+
+ // Determine the time for the next timer.
+ if (pd->state.skillbonus == 1 && pd->bonus->delay > 0) {
bonus = 0;
- duration = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again
- } else if (pd->pet.intimate) {
+ duration = pd->bonus->delay * 1000; // The duration until pet bonuses will be reactivated again.
+ } else if (pd->pet.intimate > PET_INTIMACY_NONE) {
bonus = 1;
- duration = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect
- } else { //Lost pet...
+ duration = pd->bonus->duration * 1000; // The duration for pet bonuses to be in effect.
+ } else { // Lost pet...
pd->bonus->timer = INVALID_TIMER;
- return 0;
+ return 1;
}
if (pd->state.skillbonus != bonus) {
pd->state.skillbonus = bonus;
status_calc_pc(sd, SCO_NONE);
}
- // wait for the next timer
- pd->bonus->timer=timer->add(tick+duration,pet->skill_bonus_timer,sd->bl.id,0);
+
+ // Wait for the next timer.
+ pd->bonus->timer = timer->add(tick + duration, pet->skill_bonus_timer, sd->bl.id, 0);
+
return 0;
}
/*==========================================
* pet recovery skills [Valaris] / Rewritten by [Skotlex]
*------------------------------------------*/
-int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
+static int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd=map->id2sd(id);
struct pet_data *pd;
if(sd==NULL || sd->pd == NULL || sd->pd->recovery == NULL)
return 1;
- pd=sd->pd;
+ pd = sd->pd;
+ nullpo_retr(1, pd);
if(pd->recovery->timer != tid) {
ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid);
@@ -1137,7 +1334,8 @@ int pet_recovery_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) {
+static 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;
struct status_data *st;
@@ -1146,6 +1344,7 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
return 1;
pd=sd->pd;
+ nullpo_retr(1, pd);
if(pd->s_skill->timer != tid) {
ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid);
@@ -1179,151 +1378,366 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-/**
- * Loads (or reloads) the pet database.
- */
-int read_petdb(void)
+static void pet_read_db(void)
{
const char *filename[] = {
- DBPATH"pet_db.txt",
- "pet_db2.txt",
+ DBPATH"pet_db.conf",
+ "pet_db2.conf"
};
- int i,j;
+ int i;
- // Remove any previous scripts in case reloaddb was invoked.
- for (j = 0; j < MAX_PET_DB; j++) {
- if (pet->db[j].pet_script) {
- script->free_code(pet->db[j].pet_script);
- pet->db[j].pet_script = NULL;
- }
- if (pet->db[j].equip_script) {
- script->free_code(pet->db[j].equip_script);
- pet->db[j].equip_script = NULL;
+ pet->read_db_clear();
+
+ for (i = 0; i < ARRAYLENGTH(filename); ++i) {
+ pet->read_db_libconfig(filename[i], i > 0 ? true : false);
+ }
+}
+
+static int pet_read_db_libconfig(const char *filename, bool ignore_missing)
+{
+ struct config_t pet_db_conf;
+ struct config_setting_t *pdb;
+ struct config_setting_t *t;
+ char filepath[256];
+ bool duplicate[MAX_MOB_DB] = { 0 };
+ int i = 0, count = 0;
+
+ nullpo_ret(filename);
+
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
+
+ if (!exists(filepath)) {
+ if (!ignore_missing) {
+ ShowError("pet_read_db_libconfig: can't find file %s\n", filepath);
}
+ return 0;
}
- // clear database
- memset(pet->db,0,sizeof(pet->db));
+ if (!libconfig->load_file(&pet_db_conf, filepath))
+ return 0;
+
+ if ((pdb = libconfig->setting_get_member(pet_db_conf.root, "pet_db")) == NULL) {
+ ShowError("can't read %s\n", filepath);
+ return 0;
+ }
+
+ while ((t = libconfig->setting_get_elem(pdb, i++))) {
+ int pet_id = pet->read_db_sub(t, i - 1, filename);
- j = 0; // entry counter
- for (i = 0; i < ARRAYLENGTH(filename); i++) {
- char line[1024];
- int lines, entries;
- FILE *fp;
-
- sprintf(line, "%s/%s", map->db_path, filename[i]);
- fp=fopen(line,"r");
- if (fp == NULL) {
- if (i == 0)
- ShowError("can't read %s\n",line);
+ if (pet_id <= 0 || pet_id >= MAX_MOB_DB)
continue;
+
+ if (duplicate[pet_id]) {
+ ShowWarning("pet_read_db_libconfig:%s: duplicate entry of ID #%d\n", filename, pet_id);
+ } else {
+ duplicate[pet_id] = true;
}
- lines = entries = 0;
- while (fgets(line, sizeof(line), fp) && j < MAX_PET_DB) {
- char *str[22], *p;
- int nameid, k;
- lines++;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
- memset(str, 0, sizeof(str));
- p = line;
- while (ISSPACE(*p))
- ++p;
- if (*p == '\0')
- continue; // empty line
- for (k = 0; k < 20; ++k) {
- str[k] = p;
- p = strchr(p,',');
- if (p == NULL)
- break; // comma not found
- *p = '\0';
- ++p;
- }
+ count++;
+ }
+ libconfig->destroy(&pet_db_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
- if (p == NULL) {
- ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
- continue;
- }
+ return count;
+}
- // Pet Script
- if (*p != '{') {
- ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
- continue;
- }
+/**
+ * Reads a single pet from DB.
+ *
+ * @param it The libconfig settings block, which contains the pet's data.
+ * @param n The pet's index in pet->db[].
+ * @param source The pet DB's file name.
+ * @return 0 on failure, the pet's ID on success.
+ *
+ **/
+static int pet_read_db_sub(struct config_setting_t *it, int n, const char *source)
+{
+ nullpo_ret(it);
+ nullpo_ret(source);
+ Assert_ret(n >= 0 && n < MAX_PET_DB);
- str[20] = p;
- p = strstr(p+1,"},");
- if (p == NULL) {
- ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
- continue;
- }
- p[1] = '\0';
- p += 2;
+ int i32 = 0;
+
+ if (libconfig->setting_lookup_int(it, "Id", &i32) == CONFIG_FALSE) {
+ ShowWarning("pet_read_db_sub: Missing Id in \"%s\", entry #%d, skipping.\n", source, n);
+ return 0;
+ }
+
+ if (mob->db_checkid(i32) == 0) {
+ ShowWarning("pet_read_db_sub: Invalid Id in \"%s\", entry #%d, skipping.\n", source, n);
+ return 0;
+ }
+
+ pet->db[n].class_ = i32;
+ safestrncpy(pet->db[n].name, mob->db(i32)->sprite, sizeof(pet->db[n].name));
+
+ const char *str;
+
+ if (libconfig->setting_lookup_string(it, "Name", &str) == CONFIG_FALSE || *str == '\0') {
+ ShowWarning("pet_read_db_sub: Missing Name in pet %d of \"%s\", skipping.\n",
+ pet->db[n].class_, source);
+ return 0;
+ }
+
+ safestrncpy(pet->db[n].jname, str, sizeof(pet->db[n].jname));
+
+ if (libconfig->setting_lookup_string(it, "EggItem", &str) == CONFIG_FALSE || *str == '\0') {
+ ShowWarning("pet_read_db_sub: Missing EggItem in pet %d of \"%s\", skipping.\n",
+ pet->db[n].class_, source);
+ return 0;
+ }
+
+ struct item_data *data;
+
+ if ((data = itemdb->name2id(str)) == NULL) {
+ ShowWarning("pet_read_db_sub: Invalid EggItem '%s' in pet %d of \"%s\", skipping.\n",
+ str, pet->db[n].class_, source);
+ return 0;
+ }
+
+ pet->db[n].EggID = data->nameid;
+
+ if (libconfig->setting_lookup_string(it, "TamingItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid TamingItem '%s' in pet %d of \"%s\", defaulting to 0.\n",
+ str, pet->db[n].class_, source);
+ else
+ pet->db[n].itemID = data->nameid;
+ }
+
+ pet->db[n].FoodID = 537;
+
+ if (libconfig->setting_lookup_string(it, "FoodItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid FoodItem '%s' in pet %d of \"%s\", defaulting to Pet_Food (ID=537).\n",
+ str, pet->db[n].class_, source);
+ else
+ pet->db[n].FoodID = data->nameid;
+ }
+
+ if (libconfig->setting_lookup_string(it, "AccessoryItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid AccessoryItem '%s' in pet %d of \"%s\", defaulting to 0.\n",
+ str, pet->db[n].class_, source);
+ else
+ pet->db[n].AcceID = data->nameid;
+ }
+
+ int ret = libconfig->setting_lookup_int(it, "FoodEffectiveness", &i32);
+ pet->db[n].fullness = (ret == CONFIG_FALSE) ? 80 : cap_value(i32, 1, PET_HUNGER_STUFFED);
+
+ ret = libconfig->setting_lookup_int(it, "HungerDelay", &i32);
+ pet->db[n].hungry_delay = (ret == CONFIG_FALSE) ? 60000 : cap_value(1000 * i32, 0, INT_MAX);
+
+ ret = libconfig->setting_lookup_int(it, "HungerDecrement", &i32);
+ pet->db[n].hunger_decrement = (ret == CONFIG_FALSE) ? 1 : cap_value(i32, PET_HUNGER_STARVING, PET_HUNGER_STUFFED - 1);
+
+ if (pet->db[n].hunger_decrement == PET_HUNGER_STARVING)
+ pet->db[n].hungry_delay = 0;
+
+ /**
+ * Preventively set default intimacy values here, just in case that 'Intimacy' block is not defined,
+ * or pet_read_db_sub_intimacy() fails execution.
+ *
+ **/
+ pet->db[n].intimate = PET_INTIMACY_NEUTRAL;
+ pet->db[n].r_hungry = 10;
+ pet->db[n].r_full = 100;
+ pet->db[n].die = 20;
+ pet->db[n].starving_delay = min(20000, pet->db[n].hungry_delay);
+ pet->db[n].starving_decrement = 20;
+
+ struct config_setting_t *t;
- // Equip Script
- if (*p != '{') {
- ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
- continue;
+ if ((t = libconfig->setting_get_member(it, "Intimacy")) != NULL && config_setting_is_group(t))
+ pet->read_db_sub_intimacy(n, t);
+
+ ret = libconfig->setting_lookup_int(it, "CaptureRate", &i32);
+ pet->db[n].capture = (ret == CONFIG_FALSE) ? 1000 : cap_value(i32, 1, 10000);
+
+ ret = libconfig->setting_lookup_int(it, "Speed", &i32);
+ pet->db[n].speed = (ret == CONFIG_FALSE) ? DEFAULT_WALK_SPEED : cap_value(i32, MIN_WALK_SPEED, MAX_WALK_SPEED);
+
+ if ((t = libconfig->setting_get_member(it, "SpecialPerformance")) != NULL
+ && (i32 = libconfig->setting_get_bool(t)) != 0) {
+ pet->db[n].s_perfor = (char)i32;
+ }
+
+ if ((t = libconfig->setting_get_member(it, "TalkWithEmotes")) != NULL
+ && (i32 = libconfig->setting_get_bool(t)) != 0) {
+ pet->db[n].talk_convert_class = i32;
+ }
+
+ ret = libconfig->setting_lookup_int(it, "AttackRate", &i32);
+ pet->db[n].attack_rate = (ret == CONFIG_FALSE) ? 300 : cap_value(i32, 0, 10000);
+
+ ret = libconfig->setting_lookup_int(it, "DefendRate", &i32);
+ pet->db[n].defence_attack_rate = (ret == CONFIG_FALSE) ? 300 : cap_value(i32, 0, 10000);
+
+ ret = libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32);
+ pet->db[n].change_target_rate = (ret == CONFIG_FALSE) ? 800 : cap_value(i32, 0, 10000);
+
+ if ((t = libconfig->setting_get_member(it, "AutoFeed")) != NULL && (i32 = libconfig->setting_get_bool(t)) != 0)
+ pet->db[n].autofeed = i32;
+
+ pet->db[n].pet_script = NULL;
+ if (libconfig->setting_lookup_string(it, "PetScript", &str) == CONFIG_TRUE && *str != '\0')
+ pet->db[n].pet_script = script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL);
+
+ pet->db[n].equip_script = NULL;
+ if (libconfig->setting_lookup_string(it, "EquipScript", &str) == CONFIG_TRUE && *str != '\0')
+ pet->db[n].equip_script = script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL);
+
+ if ((t = libconfig->setting_get_member(it, "Evolve")) != NULL && config_setting_is_group(t))
+ pet->read_db_sub_evolution(t, n);
+
+ return pet->db[n].class_;
+}
+
+/**
+ * Read Pet Evolution Database [Dastgir/Hercules]
+ * @param t libconfig setting
+ * @param n Pet DB Index
+ */
+static void pet_read_db_sub_evolution(struct config_setting_t *t, int n)
+{
+ struct config_setting_t *pett;
+ int i = 0;
+ const char *str = NULL;
+
+ nullpo_retv(t);
+ Assert_retv(n >= 0 && n < MAX_PET_DB);
+
+ VECTOR_INIT(pet->db[n].evolve_data);
+
+ while ((pett = libconfig->setting_get_elem(t, i))) {
+ if (config_setting_is_group(pett)) {
+ struct pet_evolve_data ped;
+ struct item_data *data;
+ struct config_setting_t *item;
+ int j = 0, i32 = 0;
+
+ str = config_setting_name(pett);
+
+ if (!(data = itemdb->name2id(str))) {
+ ShowWarning("pet_read_evolve_db_sub: Invalid Egg '%s' in Pet #%d, skipping.\n", str, pet->db[n].class_);
+ return;
+ } else {
+ ped.petEggId = data->nameid;
}
- str[21] = p;
- nameid = atoi(str[0]);
- if (nameid <= 0)
- continue;
+ VECTOR_INIT(ped.items);
+
+ while ((item = libconfig->setting_get_elem(pett, j))) {
+ struct itemlist_entry list = { 0 };
+ int quantity = 0;
+
+ str = config_setting_name(item);
+ data = itemdb->search_name(str);
+
+ if (!data) {
+ ShowWarning("pet_read_evolve_db_sub: required item %s not found in egg %d\n", str, ped.petEggId);
+ j++;
+ continue;
+ }
+
+ list.id = data->nameid;
+
+ if (mob->get_const(item, &i32) && i32 >= 0) {
+ quantity = i32;
+ }
+
+ if (quantity <= 0) {
+ ShowWarning("pet_read_evolve_db_sub: invalid quantity %d for egg %d\n", quantity, ped.petEggId);
+ j++;
+ continue;
+ }
+
+ list.amount = quantity;
+
+ VECTOR_ENSURE(ped.items, 1, 1);
+ VECTOR_PUSH(ped.items, list);
+
+ j++;
- if (!mob->db_checkid(nameid)) {
- ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
- continue;
}
- pet->db[j].class_ = nameid;
- safestrncpy(pet->db[j].name,str[1],NAME_LENGTH);
- safestrncpy(pet->db[j].jname,str[2],NAME_LENGTH);
- pet->db[j].itemID=atoi(str[3]);
- pet->db[j].EggID=atoi(str[4]);
- pet->db[j].AcceID=atoi(str[5]);
- pet->db[j].FoodID=atoi(str[6]);
- pet->db[j].fullness=atoi(str[7]);
- pet->db[j].hungry_delay=atoi(str[8])*1000;
- pet->db[j].r_hungry=atoi(str[9]);
- if (pet->db[j].r_hungry <= 0)
- pet->db[j].r_hungry=1;
- pet->db[j].r_full=atoi(str[10]);
- pet->db[j].intimate=atoi(str[11]);
- pet->db[j].die=atoi(str[12]);
- pet->db[j].capture=atoi(str[13]);
- pet->db[j].speed=atoi(str[14]);
- pet->db[j].s_perfor=(char)atoi(str[15]);
- pet->db[j].talk_convert_class=atoi(str[16]);
- pet->db[j].attack_rate=atoi(str[17]);
- pet->db[j].defence_attack_rate=atoi(str[18]);
- pet->db[j].change_target_rate=atoi(str[19]);
- pet->db[j].pet_script = NULL;
- pet->db[j].equip_script = NULL;
-
- if (*str[20])
- pet->db[j].pet_script = 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, NULL);
-
- j++;
- entries++;
+ VECTOR_ENSURE(pet->db[n].evolve_data, 1, 1);
+ VECTOR_PUSH(pet->db[n].evolve_data, ped);
+ }
+ i++;
+ }
+}
+
+/**
+ * Reads a pet's intimacy data from DB.
+ *
+ * @param idx The pet's index in pet->db[].
+ * @param t The libconfig settings block, which contains the pet's intimacy data.
+ * @return false on failure, true on success.
+ *
+ **/
+static bool pet_read_db_sub_intimacy(int idx, struct config_setting_t *t)
+{
+ nullpo_retr(false, t);
+ Assert_retr(false, idx >= 0 && idx < MAX_PET_DB);
+
+ int i32 = 0;
+
+ if (libconfig->setting_lookup_int(t, "Initial", &i32) == CONFIG_TRUE)
+ pet->db[idx].intimate = cap_value(i32, PET_INTIMACY_AWKWARD, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "FeedIncrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].r_hungry = cap_value(i32, PET_INTIMACY_AWKWARD, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "OverFeedDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].r_full = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "OwnerDeathDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].die = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "StarvingDelay", &i32) == CONFIG_TRUE)
+ pet->db[idx].starving_delay = cap_value(1000 * i32, 0, pet->db[idx].hungry_delay);
+
+ if (libconfig->setting_lookup_int(t, "StarvingDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].starving_decrement = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+
+ if (pet->db[idx].starving_decrement == PET_INTIMACY_NONE)
+ pet->db[idx].starving_delay = 0;
+
+ return true;
+}
+
+static void pet_read_db_clear(void)
+{
+ int i;
+
+ // Remove any previous scripts in case reloaddb was invoked.
+ for (i = 0; i < MAX_PET_DB; i++) {
+ int j;
+ if (pet->db[i].pet_script) {
+ script->free_code(pet->db[i].pet_script);
+ pet->db[i].pet_script = NULL;
+ }
+ if (pet->db[i].equip_script) {
+ script->free_code(pet->db[i].equip_script);
+ pet->db[i].equip_script = NULL;
}
- if (j >= MAX_PET_DB)
- ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB);
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]);
+ for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) {
+ VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items);
+ }
+ VECTOR_CLEAR(pet->db[i].evolve_data);
}
- return 0;
+ memset(pet->db, 0, sizeof(pet->db));
+ return;
}
/*==========================================
* Initialization process relationship skills
*------------------------------------------*/
-int do_init_pet(bool minimal) {
+static int do_init_pet(bool minimal)
+{
if (minimal)
return 0;
@@ -1343,11 +1757,12 @@ int do_init_pet(bool minimal) {
return 0;
}
-int do_final_pet(void)
+static int do_final_pet(void)
{
int i;
for( i = 0; i < MAX_PET_DB; i++ )
{
+ int j;
if( pet->db[i].pet_script )
{
script->free_code(pet->db[i].pet_script);
@@ -1358,12 +1773,20 @@ int do_final_pet(void)
script->free_code(pet->db[i].equip_script);
pet->db[i].equip_script = NULL;
}
+
+ /* Pet Evolution [Dastgir/Hercules] */
+ for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) {
+ VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items);
+ }
+ VECTOR_CLEAR(pet->db[i].evolve_data);
}
ers_destroy(pet->item_drop_ers);
ers_destroy(pet->item_drop_list_ers);
+
return 0;
}
-void pet_defaults(void) {
+void pet_defaults(void)
+{
pet = &pet_s;
memset(pet->db,0,sizeof(pet->db));
@@ -1374,6 +1797,7 @@ void pet_defaults(void) {
pet->final = do_final_pet;
pet->hungry_val = pet_hungry_val;
+ pet->set_hunger = pet_set_hunger;
pet->set_intimate = pet_set_intimate;
pet->create_egg = pet_create_egg;
pet->unlocktarget = pet_unlocktarget;
@@ -1408,5 +1832,12 @@ void pet_defaults(void) {
pet->skill_bonus_timer = pet_skill_bonus_timer;
pet->recovery_timer = pet_recovery_timer;
pet->skill_support_timer = pet_skill_support_timer;
- pet->read_db = read_petdb;
+
+ pet->read_db = pet_read_db;
+ pet->read_db_libconfig = pet_read_db_libconfig;
+ pet->read_db_sub = pet_read_db_sub;
+ pet->read_db_sub_intimacy = pet_read_db_sub_intimacy;
+ pet->read_db_clear = pet_read_db_clear;
+
+ pet->read_db_sub_evolution = pet_read_db_sub_evolution;
}
diff --git a/src/map/pet.h b/src/map/pet.h
index 79cbeddae..fa37e896a 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,13 +30,19 @@
#define MAX_PET_DB 300
#define MAX_PETLOOT_SIZE 30
+/** Pet Evolution [Dastgir/Hercules] */
+struct pet_evolve_data {
+ int petEggId;
+ VECTOR_DECL(struct itemlist_entry) items;
+};
+
struct s_pet_db {
- short class_;
+ int class_;
char name[NAME_LENGTH],jname[NAME_LENGTH];
- short itemID;
- short EggID;
- short AcceID;
- short FoodID;
+ int itemID;
+ int EggID;
+ int AcceID;
+ int FoodID;
int fullness;
int hungry_delay;
int r_hungry;
@@ -50,8 +56,15 @@ struct s_pet_db {
int attack_rate;
int defence_attack_rate;
int change_target_rate;
+ int autofeed;
+ int hunger_decrement;
+ int starving_delay;
+ int starving_decrement;
struct script_code *equip_script;
struct script_code *pet_script;
+
+ /* Pet Evolution */
+ VECTOR_DECL(struct pet_evolve_data) evolve_data;
};
enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD };
@@ -127,11 +140,13 @@ struct pet_interface {
struct s_pet_db db[MAX_PET_DB];
struct eri *item_drop_ers; //For loot drops delay structures.
struct eri *item_drop_list_ers;
+
/* */
int (*init) (bool minimal);
int (*final) (void);
/* */
int (*hungry_val) (struct pet_data *pd);
+ void (*set_hunger) (struct pet_data *pd, int value);
void (*set_intimate) (struct pet_data *pd, int value);
int (*create_egg) (struct map_session_data *sd, int item_id);
int (*unlocktarget) (struct pet_data *pd);
@@ -146,10 +161,10 @@ struct pet_interface {
int (*data_init) (struct map_session_data *sd, struct s_pet *petinfo);
int (*birth_process) (struct map_session_data *sd, struct s_pet *petinfo);
int (*recv_petdata) (int account_id, struct s_pet *p, int flag);
- int (*select_egg) (struct map_session_data *sd, short egg_index);
+ int (*select_egg) (struct map_session_data *sd, int egg_index);
int (*catch_process1) (struct map_session_data *sd, int target_class);
int (*catch_process2) (struct map_session_data *sd, int target_id);
- bool (*get_egg) (int account_id, short pet_class, int pet_id );
+ bool (*get_egg) (int account_id, int 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);
@@ -166,7 +181,16 @@ struct pet_interface {
int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data);
int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data);
int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*read_db) (void);
+
+ void (*read_db) (void);
+ int (*read_db_libconfig) (const char *filename, bool ignore_missing);
+ int (*read_db_sub) (struct config_setting_t *it, int n, const char *source);
+ bool (*read_db_sub_intimacy) (int idx, struct config_setting_t *t);
+ void (*read_db_clear) (void);
+
+ /* Pet Evolution [Dastgir/Hercules] */
+ void (*read_db_sub_evolution) (struct config_setting_t *t, int n);
+
};
#ifdef HERCULES_CORE
diff --git a/src/map/quest.c b/src/map/quest.c
index 79328ae9d..217acfa19 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,10 +25,12 @@
#include "map/battle.h"
#include "map/chrif.h"
#include "map/clif.h"
+#include "map/homunculus.h"
#include "map/intif.h"
#include "map/itemdb.h"
#include "map/log.h"
#include "map/map.h"
+#include "map/mercenary.h"
#include "map/mob.h"
#include "map/npc.h"
#include "map/party.h"
@@ -52,8 +54,8 @@
#include <string.h>
#include <time.h>
-struct quest_interface quest_s;
-struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database
+static struct quest_interface quest_s;
+static struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database
struct quest_interface *quest;
@@ -63,7 +65,8 @@ struct quest_interface *quest;
* @param quest_id ID to lookup
* @return Quest entry (equals to &quest->dummy if the ID is invalid)
*/
-struct quest_db *quest_db(int quest_id) {
+static struct quest_db *quest_db(int quest_id)
+{
if (quest_id < 0 || quest_id >= MAX_QUEST_DB || quest->db_data[quest_id] == NULL)
return &quest->dummy;
return quest->db_data[quest_id];
@@ -75,12 +78,13 @@ struct quest_db *quest_db(int quest_id) {
* @param sd Player's data
* @return 0 in case of success, nonzero otherwise (i.e. the player has no quests)
*/
-int quest_pc_login(struct map_session_data *sd)
+static int quest_pc_login(struct map_session_data *sd)
{
#if PACKETVER < 20141022
int i;
#endif
+ nullpo_retr(1, sd);
if(sd->avail_quests == 0)
return 1;
@@ -102,32 +106,35 @@ int quest_pc_login(struct map_session_data *sd)
*
* New quest will be added as Q_ACTIVE.
*
- * @param sd Player's data
- * @param quest_id ID of the quest to add.
+ * @param sd Player's data
+ * @param quest_id ID of the quest to add.
+ * @param time_limit Custom time, in UNIX epoch, for this quest
* @return 0 in case of success, nonzero otherwise
*/
-int quest_add(struct map_session_data *sd, int quest_id)
+static int quest_add(struct map_session_data *sd, int quest_id, unsigned int time_limit)
{
int n;
struct quest_db *qi = quest->db(quest_id);
- if( qi == &quest->dummy ) {
+ nullpo_retr(-1, sd);
+ if (qi == &quest->dummy) {
ShowError("quest_add: quest %d not found in DB.\n", quest_id);
return -1;
}
- if( quest->check(sd, quest_id, HAVEQUEST) >= 0 ) {
+ if (quest->check(sd, quest_id, HAVEQUEST) >= 0) {
ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
n = sd->avail_quests; // Insertion point
+ Assert_retr(-1, sd->avail_quests <= sd->num_quests);
sd->num_quests++;
sd->avail_quests++;
RECREATE(sd->quest_log, struct quest, sd->num_quests);
- if( sd->avail_quests != sd->num_quests ) {
+ if (sd->avail_quests != sd->num_quests) {
// The character has some completed quests, make room before them so that they will stay at the end of the array
memmove(&sd->quest_log[n+1], &sd->quest_log[n], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
}
@@ -135,17 +142,24 @@ int quest_add(struct map_session_data *sd, int quest_id)
memset(&sd->quest_log[n], 0, sizeof(struct quest));
sd->quest_log[n].quest_id = qi->id;
- if( qi->time )
+ if (time_limit != 0)
+ sd->quest_log[n].time = time_limit;
+ else if (qi->time != 0)
sd->quest_log[n].time = (unsigned int)(time(NULL) + qi->time);
sd->quest_log[n].state = Q_ACTIVE;
sd->save_quest = true;
clif->quest_add(sd, &sd->quest_log[n]);
+#if PACKETVER >= 20150513
+ clif->quest_notify_objective(sd, &sd->quest_log[n]);
+#else
clif->quest_update_objective(sd, &sd->quest_log[n]);
+#endif
+ quest->questinfo_refresh(sd);
- if( map->save_settings&64 )
- chrif->save(sd,0);
+ if ((map->save_settings & 64) != 0)
+ chrif->save(sd, 0);
return 0;
}
@@ -158,11 +172,12 @@ int quest_add(struct map_session_data *sd, int quest_id)
* @param qid2 New quest to add
* @return 0 in case of success, nonzero otherwise
*/
-int quest_change(struct map_session_data *sd, int qid1, int qid2)
+static int quest_change(struct map_session_data *sd, int qid1, int qid2)
{
int i;
struct quest_db *qi = quest->db(qid2);
+ nullpo_retr(-1, sd);
if( qi == &quest->dummy ) {
ShowError("quest_change: quest %d not found in DB.\n", qid2);
return -1;
@@ -194,11 +209,15 @@ int quest_change(struct map_session_data *sd, int qid1, int qid2)
clif->quest_delete(sd, qid1);
clif->quest_add(sd, &sd->quest_log[i]);
+#if PACKETVER >= 20150513
+ clif->quest_notify_objective(sd, &sd->quest_log[i]);
+#else
clif->quest_update_objective(sd, &sd->quest_log[i]);
+#endif
+ quest->questinfo_refresh(sd);
if( map->save_settings&64 )
chrif->save(sd,0);
-
return 0;
}
@@ -209,10 +228,11 @@ int quest_change(struct map_session_data *sd, int qid1, int qid2)
* @param quest_id ID of the quest to remove
* @return 0 in case of success, nonzero otherwise
*/
-int quest_delete(struct map_session_data *sd, int quest_id)
+static int quest_delete(struct map_session_data *sd, int quest_id)
{
int i;
+ nullpo_retr(-1, sd);
//Search for quest
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
@@ -237,6 +257,7 @@ int quest_delete(struct map_session_data *sd, int quest_id)
sd->save_quest = true;
clif->quest_delete(sd, quest_id);
+ quest->questinfo_refresh(sd);
if( map->save_settings&64 )
chrif->save(sd,0);
@@ -252,7 +273,7 @@ int quest_delete(struct map_session_data *sd, int quest_id)
* int Party ID
* int Mob ID
*/
-int quest_update_objective_sub(struct block_list *bl, va_list ap)
+static int quest_update_objective_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
int party_id = va_arg(ap, int);
@@ -279,10 +300,11 @@ int quest_update_objective_sub(struct block_list *bl, va_list ap)
* @param sd Character's data
* @param mob_id Monster ID
*/
-void quest_update_objective(struct map_session_data *sd, int mob_id)
+static void quest_update_objective(struct map_session_data *sd, int mob_id)
{
int i,j;
+ nullpo_retv(sd);
for (i = 0; i < sd->avail_quests; i++) {
struct quest_db *qi = NULL;
@@ -334,10 +356,11 @@ void quest_update_objective(struct map_session_data *sd, int mob_id)
* @param qs New quest state
* @return 0 in case of success, nonzero otherwise
*/
-int quest_update_status(struct map_session_data *sd, int quest_id, enum quest_state qs)
+static int quest_update_status(struct map_session_data *sd, int quest_id, enum quest_state qs)
{
int i;
+ nullpo_retr(-1, sd);
ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id);
if( i == sd->avail_quests ) {
ShowError("quest_update_status: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id);
@@ -362,6 +385,7 @@ int quest_update_status(struct map_session_data *sd, int quest_id, enum quest_st
}
clif->quest_delete(sd, quest_id);
+ quest->questinfo_refresh(sd);
if( map->save_settings&64 )
chrif->save(sd,0);
@@ -384,10 +408,11 @@ int quest_update_status(struct map_session_data *sd, int quest_id, enum quest_st
* 1 if the quest's timeout has expired
* 0 otherwise
*/
-int quest_check(struct map_session_data *sd, int quest_id, enum quest_check_type type)
+static int quest_check(struct map_session_data *sd, int quest_id, enum quest_check_type type)
{
int i;
+ nullpo_retr(-1, sd);
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
if (i == sd->num_quests)
return -1;
@@ -425,12 +450,13 @@ int quest_check(struct map_session_data *sd, int quest_id, enum quest_check_type
* @return The parsed quest entry.
* @retval NULL in case of errors.
*/
-struct quest_db *quest_read_db_sub(struct config_setting_t *cs, int n, const char *source)
+static struct quest_db *quest_read_db_sub(struct config_setting_t *cs, int n, const char *source)
{
struct quest_db *entry = NULL;
struct config_setting_t *t = NULL;
int i32 = 0, quest_id;
const char *str = NULL;
+ nullpo_retr(NULL, cs);
/*
* Id: Quest ID [int]
* Name: Quest Name [string]
@@ -524,7 +550,7 @@ struct quest_db *quest_read_db_sub(struct config_setting_t *cs, int n, const cha
*
* @return Number of loaded quests, or -1 if the file couldn't be read.
*/
-int quest_read_db(void)
+static int quest_read_db(void)
{
char filepath[256];
struct config_t quest_db_conf;
@@ -532,7 +558,7 @@ int quest_read_db(void)
int i = 0, count = 0;
const char *filename = "quest_db.conf";
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&quest_db_conf, filepath))
return -1;
@@ -559,7 +585,7 @@ int quest_read_db(void)
count++;
}
libconfig->destroy(&quest_db_conf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
return count;
}
@@ -571,7 +597,8 @@ int quest_read_db(void)
* @see map->foreachpc
* @param ap Ignored
*/
-int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
+static int quest_reload_check_sub(struct map_session_data *sd, va_list ap)
+{
int i, j;
nullpo_ret(sd);
@@ -600,7 +627,8 @@ int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
/**
* Clears the quest database for shutdown or reload.
*/
-void quest_clear_db(void) {
+static void quest_clear_db(void)
+{
int i;
for (i = 0; i < MAX_QUEST_DB; i++) {
@@ -615,12 +643,297 @@ void quest_clear_db(void) {
}
}
+/*
+* Limit the questinfo icon id to avoid client problems
+*/
+static int quest_questinfo_validate_icon(int icon)
+{
+#if PACKETVER >= 20170315
+ if (icon < 0 || (icon > 10 && icon != 9999))
+ icon = 9999;
+#elif PACKETVER >= 20120410
+ if (icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
+ icon = 9999; // Default to nothing if icon id is invalid.
+#else
+ if (icon < 0 || icon > 7)
+ icon = 0;
+ else
+ icon = icon + 1;
+#endif
+ return icon;
+}
+
+/**
+ * Refresh the questinfo bubbles on the player map.
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ */
+static void quest_questinfo_refresh(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ for (int i = 0; i < VECTOR_LENGTH(map->list[sd->bl.m].qi_list); i++) {
+ struct npc_data *nd = VECTOR_INDEX(map->list[sd->bl.m].qi_list, i);
+
+ int j;
+ ARR_FIND(0, VECTOR_LENGTH(nd->qi_data), j, quest->questinfo_validate(sd, &VECTOR_INDEX(nd->qi_data, j)) == true);
+ if (j != VECTOR_LENGTH(nd->qi_data)) {
+ struct questinfo *qi = &VECTOR_INDEX(nd->qi_data, j);
+ clif->quest_show_event(sd, &nd->bl, qi->icon, qi->color);
+ } else {
+#if PACKETVER >= 20120410
+ clif->quest_show_event(sd, &nd->bl, 9999, 0);
+#else
+ clif->quest_show_event(sd, &nd->bl, 0, 0);
+#endif
+ }
+ }
+}
+
+/**
+ * Validate all possible conditions required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if conditions are correct.
+ * @retval false if one condition or more are in-correct.
+ */
+static bool quest_questinfo_validate(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+ if (qi->hasJob && quest->questinfo_validate_job(sd, qi) == false)
+ return false;
+ if (qi->sex_enabled && quest->questinfo_validate_sex(sd, qi) == false)
+ return false;
+ if ((qi->base_level.min != 0 || qi->base_level.max != 0) && quest->questinfo_validate_baselevel(sd, qi) == false)
+ return false;
+ if ((qi->job_level.min != 0 || qi->job_level.max != 0) && quest->questinfo_validate_joblevel(sd, qi) == false)
+ return false;
+ if (VECTOR_LENGTH(qi->items) > 0 && quest->questinfo_validate_items(sd, qi) == false)
+ return false;
+ if (qi->homunculus.level != 0 && quest->questinfo_validate_homunculus_level(sd, qi) == false)
+ return false;
+ if (qi->homunculus.class_ != 0 && quest->questinfo_validate_homunculus_type(sd, qi) == false)
+ return false;
+ if (VECTOR_LENGTH(qi->quest_requirement) > 0 && quest->questinfo_validate_quests(sd, qi) == false)
+ return false;
+ if (qi->mercenary_class != 0 && quest->questinfo_validate_mercenary_class(sd, qi) == false)
+ return false;
+ return true;
+}
+
+/**
+ * Validate job required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player job is matching the required.
+ * @retval false if player job is NOT matching the required.
+ */
+static bool quest_questinfo_validate_job(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+ if (sd->status.class == qi->job)
+ return true;
+ return false;
+}
+
+/**
+ * Validate sex required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player sex is matching the required.
+ * @retval false if player sex is NOT matching the required.
+ */
+static bool quest_questinfo_validate_sex(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+ if (sd->status.sex == qi->sex)
+ return true;
+ return false;
+}
+
+/**
+ * Validate base level required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player base level is included in the required level range.
+ * @retval false if player base level is NOT included in the required level range.
+ */
+static bool quest_questinfo_validate_baselevel(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+ if (sd->status.base_level >= qi->base_level.min && sd->status.base_level <= qi->base_level.max)
+ return true;
+ return false;
+}
+
+/**
+ * Validate job level required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player job level is included in the required level range.
+ * @retval false if player job level is NOT included in the required level range.
+ */
+static bool quest_questinfo_validate_joblevel(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+ if (sd->status.job_level >= qi->job_level.min && sd->status.job_level <= qi->job_level.max)
+ return true;
+ return false;
+}
+
+/**
+ * Validate items list required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player have all the items required.
+ * @retval false if player is missing one or more of the items required.
+ */
+static bool quest_questinfo_validate_items(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+
+ for (int i = 0; i < VECTOR_LENGTH(qi->items); i++) {
+ struct questinfo_itemreq *item = &VECTOR_INDEX(qi->items, i);
+ int count = 0;
+ for (int j = 0; j < sd->status.inventorySize; j++) {
+ if (sd->status.inventory[j].nameid == item->nameid)
+ count += sd->status.inventory[j].amount;
+ }
+ if (count < item->min || count > item->max)
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validate minimal homunculus level required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if homunculus level >= the required value.
+ * @retval false if homunculus level smaller than the required value.
+ */
+static bool quest_questinfo_validate_homunculus_level(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+
+ if (sd->hd == NULL)
+ return false;
+ if (!homun_alive(sd->hd))
+ return false;
+ if (sd->hd->homunculus.level < qi->homunculus.level)
+ return false;
+ return true;
+}
+
+/**
+ * Validate homunculus type required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player's homunculus is matching the required.
+ * @retval false if player's homunculus is NOT matching the required.
+ */
+static bool quest_questinfo_validate_homunculus_type(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+
+ if (sd->hd == NULL)
+ return false;
+ if (!homun_alive(sd->hd))
+ return false;
+ if (homun->class2type(sd->hd->homunculus.class_) != qi->homunculus_type)
+ return false;
+ return true;
+}
+
+/**
+ * Validate quest list required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player have all the quests required.
+ * @retval false if player is missing one or more of the quests required.
+ */
+static bool quest_questinfo_validate_quests(struct map_session_data *sd, struct questinfo *qi)
+{
+ int i;
+
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+
+ for (i = 0; i < VECTOR_LENGTH(qi->quest_requirement); i++) {
+ struct questinfo_qreq *quest_requirement = &VECTOR_INDEX(qi->quest_requirement, i);
+ int quest_progress = quest->check(sd, quest_requirement->id, HAVEQUEST);
+ if (quest_progress == -1)
+ quest_progress = 0;
+ else if (quest_progress == 0 || quest_progress == 1)
+ quest_progress = 1;
+ else
+ quest_progress = 2;
+ if (quest_progress != quest_requirement->state)
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Validate mercenary class required for the questinfo
+ *
+ * @param sd session data.
+ * @param qi questinfo data.
+ *
+ * @retval true if player have a mercenary with the given class.
+ * @retval false if player does NOT have a mercenary with the given class.
+ */
+static bool quest_questinfo_validate_mercenary_class(struct map_session_data *sd, struct questinfo *qi)
+{
+ nullpo_retr(false, sd);
+ nullpo_retr(false, qi);
+
+ if (sd->md == NULL)
+ return false;
+
+ if (sd->md->mercenary.class_ != qi->mercenary_class)
+ return false;
+
+ return true;
+}
+
/**
* Initializes the quest interface.
*
* @param minimal Run in minimal mode (skips most of the loading)
*/
-void do_init_quest(bool minimal) {
+static void do_init_quest(bool minimal)
+{
if (minimal)
return;
@@ -630,14 +943,16 @@ void do_init_quest(bool minimal) {
/**
* Finalizes the quest interface before shutdown.
*/
-void do_final_quest(void) {
+static void do_final_quest(void)
+{
quest->clear();
}
/**
* Reloads the quest database.
*/
-void do_reload_quest(void) {
+static void do_reload_quest(void)
+{
quest->clear();
quest->read_db();
@@ -649,7 +964,8 @@ void do_reload_quest(void) {
/**
* Initializes default values for the quest interface.
*/
-void quest_defaults(void) {
+void quest_defaults(void)
+{
quest = &quest_s;
quest->db_data = db_data;
@@ -672,4 +988,17 @@ void quest_defaults(void) {
quest->clear = quest_clear_db;
quest->read_db = quest_read_db;
quest->read_db_sub = quest_read_db_sub;
+
+ quest->questinfo_validate_icon = quest_questinfo_validate_icon;
+ quest->questinfo_refresh = quest_questinfo_refresh;
+ quest->questinfo_validate = quest_questinfo_validate;
+ quest->questinfo_validate_job = quest_questinfo_validate_job;
+ quest->questinfo_validate_sex = quest_questinfo_validate_sex;
+ quest->questinfo_validate_baselevel = quest_questinfo_validate_baselevel;
+ quest->questinfo_validate_joblevel = quest_questinfo_validate_joblevel;
+ quest->questinfo_validate_items = quest_questinfo_validate_items;
+ quest->questinfo_validate_homunculus_level = quest_questinfo_validate_homunculus_level;
+ quest->questinfo_validate_homunculus_type = quest_questinfo_validate_homunculus_type;
+ quest->questinfo_validate_quests = quest_questinfo_validate_quests;
+ quest->questinfo_validate_mercenary_class = quest_questinfo_validate_mercenary_class;
}
diff --git a/src/map/quest.h b/src/map/quest.h
index e0768ef40..f83bb7d73 100644
--- a/src/map/quest.h
+++ b/src/map/quest.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
struct block_list;
struct config_setting_t;
struct map_session_data;
+struct questinfo;
#define MAX_QUEST_DB (60355+1) // Highest quest ID + 1
@@ -59,6 +60,39 @@ enum quest_check_type {
HUNTING, ///< Check if the given hunting quest's requirements have been met
};
+struct questinfo_qreq {
+ int id;
+ int state;
+};
+
+struct questinfo_itemreq {
+ int nameid;
+ int min;
+ int max;
+};
+
+struct questinfo {
+ unsigned short icon;
+ unsigned char color;
+ bool hasJob;
+ unsigned int job;/* perhaps a mapid mask would be most flexible? */
+ bool sex_enabled;
+ int sex;
+ struct {
+ int min;
+ int max;
+ } base_level;
+ struct {
+ int min;
+ int max;
+ } job_level;
+ VECTOR_DECL(struct questinfo_itemreq) items;
+ struct s_homunculus homunculus;
+ int homunculus_type;
+ VECTOR_DECL(struct questinfo_qreq) quest_requirement;
+ int mercenary_class;
+};
+
struct quest_interface {
struct quest_db **db_data; ///< Quest database
struct quest_db dummy; ///< Dummy entry for invalid quest lookups
@@ -69,7 +103,7 @@ struct quest_interface {
/* */
struct quest_db *(*db) (int quest_id);
int (*pc_login) (struct map_session_data *sd);
- int (*add) (struct map_session_data *sd, int quest_id);
+ int (*add) (struct map_session_data *sd, int quest_id, unsigned int time_limit);
int (*change) (struct map_session_data *sd, int qid1, int qid2);
int (*delete) (struct map_session_data *sd, int quest_id);
int (*update_objective_sub) (struct block_list *bl, va_list ap);
@@ -79,6 +113,19 @@ struct quest_interface {
void (*clear) (void);
int (*read_db) (void);
struct quest_db *(*read_db_sub) (struct config_setting_t *cs, int n, const char *source);
+
+ int (*questinfo_validate_icon) (int icon);
+ void (*questinfo_refresh) (struct map_session_data *sd);
+ bool (*questinfo_validate) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_job) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_sex) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_baselevel) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_joblevel) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_items) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_homunculus_level) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_homunculus_type) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_quests) (struct map_session_data *sd, struct questinfo *qi);
+ bool (*questinfo_validate_mercenary_class) (struct map_session_data *sd, struct questinfo *qi);
};
#ifdef HERCULES_CORE
diff --git a/src/map/refine.c b/src/map/refine.c
new file mode 100644
index 000000000..f6c855cea
--- /dev/null
+++ b/src/map/refine.c
@@ -0,0 +1,669 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2019-2020 Hercules Dev Team
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define HERCULES_CORE
+
+#include "refine.p.h"
+#include "common/cbasetypes.h"
+#include "common/nullpo.h"
+#include "common/random.h"
+#include "common/showmsg.h"
+#include "common/strlib.h"
+#include "common/utils.h"
+#include "map/itemdb.h"
+#include "map/map.h"
+#include "map/pc.h"
+#include "map/script.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/** @file
+* Implementation of the refine interface.
+*/
+
+static struct refine_interface refine_s;
+static struct refine_interface_private refine_p;
+static struct refine_interface_dbs refine_dbs;
+struct refine_interface *refine;
+
+/// @copydoc refine_interface::refinery_refine_request()
+static void refine_refinery_refine_request(struct map_session_data *sd, int item_index, int material_id, bool use_blacksmith_blessing)
+{
+ nullpo_retv(sd);
+
+ if (item_index < 0 || item_index >= sd->status.inventorySize)
+ return;
+
+ if (!refine->p->is_refinable(sd, item_index))
+ return;
+
+ int weapon_level = itemdb_wlv(sd->status.inventory[item_index].nameid);
+ int refine_level = sd->status.inventory[item_index].refine;
+ int i = 0;
+ const struct s_refine_requirement *req = &refine->p->dbs->refine_info[weapon_level].refine_requirements[refine_level];
+ ARR_FIND(0, req->req_count, i, req->req[i].nameid == material_id);
+
+ if (i == req->req_count)
+ return;
+
+ if (use_blacksmith_blessing && req->blacksmith_blessing == 0)
+ return;
+
+ if (sd->status.zeny < req->req[i].cost)
+ return;
+
+ if (use_blacksmith_blessing) {
+ int count = 0;
+ for (int k = 0; k < sd->status.inventorySize; ++k) {
+ if (sd->status.inventory[k].nameid == ITEMID_BLACKSMITH_BLESSING)
+ count += sd->status.inventory[k].amount;
+ }
+
+ if (count < req->blacksmith_blessing)
+ return;
+ }
+
+ int idx;
+ if ((idx = pc->search_inventory(sd, req->req[i].nameid)) == INDEX_NOT_FOUND)
+ return;
+
+ if (use_blacksmith_blessing) {
+ int amount = req->blacksmith_blessing;
+ for (int k = 0; k < sd->status.inventorySize; ++k) {
+ if (sd->status.inventory[k].nameid != ITEMID_BLACKSMITH_BLESSING)
+ continue;
+
+ int delamount = (amount < sd->status.inventory[k].amount) ? amount : sd->status.inventory[k].amount;
+ if (pc->delitem(sd, k, delamount, 0, DELITEM_NORMAL, LOG_TYPE_REFINE) != 0)
+ break;
+
+ amount -= delamount;
+ if (amount == 0)
+ break;
+ }
+ }
+
+ if (pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_REFINE) != 0)
+ return;
+
+ if (pc->payzeny(sd, req->req[i].cost, LOG_TYPE_REFINE, NULL) != 0)
+ return;
+
+ int refine_chance = refine->get_refine_chance(weapon_level, refine_level, req->req[i].type);
+ if (rnd() % 100 >= refine_chance) {
+ clif->misceffect(&sd->bl, 2);
+
+ int failure_behabior = (use_blacksmith_blessing) ? REFINE_FAILURE_BEHAVIOR_KEEP : req->req[i].failure_behavior;
+ switch (failure_behabior) {
+ case REFINE_FAILURE_BEHAVIOR_KEEP:
+ clif->refine(sd->fd, 1, 0, sd->status.inventory[item_index].refine);
+ refine->refinery_add_item(sd, item_index);
+ break;
+ case REFINE_FAILURE_BEHAVIOR_DOWNGRADE:
+ sd->status.inventory[item_index].refine -= 1;
+ sd->status.inventory[item_index].refine = cap_value(sd->status.inventory[item_index].refine, 0, MAX_REFINE);
+ clif->refine(sd->fd, 2, item_index, sd->status.inventory[item_index].refine);
+ logs->pick_pc(sd, LOG_TYPE_REFINE, 1, &sd->status.inventory[item_index], sd->inventory_data[item_index]);
+ refine->refinery_add_item(sd, item_index);
+ break;
+ case REFINE_FAILURE_BEHAVIOR_DESTROY:
+ default:
+ clif->refine(sd->fd, 1, item_index, sd->status.inventory[item_index].refine);
+ pc->delitem(sd, item_index, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_REFINE);
+ break;
+ }
+
+ if ((req->announce & REFINE_ANNOUNCE_FAILURE) != 0)
+ clif->announce_refine_status(sd, sd->status.inventory[item_index].nameid, sd->status.inventory[item_index].refine, false, ALL_CLIENT);
+ } else {
+ sd->status.inventory[item_index].refine += 1;
+ sd->status.inventory[item_index].refine = cap_value(sd->status.inventory[item_index].refine, 0, MAX_REFINE);
+
+ clif->misceffect(&sd->bl, 3);
+ clif->refine(sd->fd, 0, item_index, sd->status.inventory[item_index].refine);
+ logs->pick_pc(sd, LOG_TYPE_REFINE, 1, &sd->status.inventory[item_index], sd->inventory_data[item_index]);
+ refine->refinery_add_item(sd, item_index);
+
+ if ((req->announce & REFINE_ANNOUNCE_SUCCESS) != 0)
+ clif->announce_refine_status(sd, sd->status.inventory[item_index].nameid, sd->status.inventory[item_index].refine, true, ALL_CLIENT);
+ }
+}
+
+/// @copydoc refine_interface::refinery_add_item()
+static void refine_refinery_add_item(struct map_session_data *sd, int item_index)
+{
+ nullpo_retv(sd);
+
+ if (item_index < 0 || item_index >= sd->status.inventorySize)
+ return;
+
+ if (!refine->p->is_refinable(sd, item_index))
+ return;
+
+ int weapon_level = itemdb_wlv(sd->status.inventory[item_index].nameid);
+ int refine_level = sd->status.inventory[item_index].refine;
+ clif->AddItemRefineryUIAck(sd, item_index, &refine->p->dbs->refine_info[weapon_level].refine_requirements[refine_level]);
+}
+
+/// @copydoc refine_interface_private::is_refinable()
+static bool refine_is_refinable(struct map_session_data *sd, int item_index)
+{
+ nullpo_retr(false, sd);
+ Assert_retr(false, item_index >= 0 && item_index < sd->status.inventorySize);
+
+ if (sd->status.inventory[item_index].nameid == 0)
+ return false;
+
+ struct item_data *itd = itemdb->search(sd->status.inventory[item_index].nameid);
+
+ if (itd == &itemdb->dummy)
+ return false;
+
+ if (itd->type != IT_WEAPON && itd->type != IT_ARMOR)
+ return false;
+
+ if (itd->flag.no_refine == 1)
+ return false;
+
+ if (sd->status.inventory[item_index].identify == 0)
+ return false;
+
+ if (sd->status.inventory[item_index].refine >= MAX_REFINE || sd->status.inventory[item_index].expire_time > 0)
+ return false;
+
+ if ((sd->status.inventory[item_index].attribute & ATTR_BROKEN) != 0)
+ return false;
+
+ return true;
+}
+
+/// @copydoc refine_interface::get_randombonus_max()
+static int refine_get_randombonus_max(enum refine_type equipment_type, int refine_level)
+{
+ Assert_ret((int)equipment_type >= REFINE_TYPE_ARMOR && equipment_type < REFINE_TYPE_MAX);
+ Assert_ret(refine_level > 0 && refine_level <= MAX_REFINE);
+
+ return refine->p->dbs->refine_info[equipment_type].randombonus_max[refine_level - 1];
+}
+
+/// @copydoc refine_interface::get_bonus()
+static int refine_get_bonus(enum refine_type equipment_type, int refine_level)
+{
+ Assert_ret((int)equipment_type >= REFINE_TYPE_ARMOR && equipment_type < REFINE_TYPE_MAX);
+ Assert_ret(refine_level > 0 && refine_level <= MAX_REFINE);
+
+ return refine->p->dbs->refine_info[equipment_type].bonus[refine_level - 1];
+}
+
+/// @copydoc refine_interface::get_refine_chance()
+static int refine_get_refine_chance(enum refine_type wlv, int refine_level, enum refine_chance_type type)
+{
+ Assert_ret((int)wlv >= REFINE_TYPE_ARMOR && wlv < REFINE_TYPE_MAX);
+
+ if (refine_level < 0 || refine_level >= MAX_REFINE)
+ return 0;
+
+ if (type >= REFINE_CHANCE_TYPE_MAX)
+ return 0;
+
+ return refine->p->dbs->refine_info[wlv].chance[type][refine_level];
+}
+
+/// @copydoc refine_interface_private::announce_behavior_string2enum()
+static bool refine_announce_behavior_string2enum(const char *str, unsigned int *result)
+{
+ nullpo_retr(false, str);
+ nullpo_retr(false, result);
+
+ if (strcasecmp(str, "Success") == 0)
+ *result = REFINE_ANNOUNCE_SUCCESS;
+ else if (strcasecmp(str, "Failure") == 0)
+ *result = REFINE_ANNOUNCE_FAILURE;
+ else if (strcasecmp(str, "Always") == 0)
+ *result = REFINE_ANNOUNCE_ALWAYS;
+ else
+ return false;
+
+ return true;
+}
+
+/// @copydoc refine_interface_private::failure_behavior_string2enum()
+static bool refine_failure_behavior_string2enum(const char *str, enum refine_ui_failure_behavior *result)
+{
+ nullpo_retr(false, str);
+ nullpo_retr(false, result);
+
+ if (strcasecmp(str, "Destroy") == 0)
+ *result = REFINE_FAILURE_BEHAVIOR_DESTROY;
+ else if (strcasecmp(str, "Keep") == 0)
+ *result = REFINE_FAILURE_BEHAVIOR_KEEP;
+ else if (strcasecmp(str, "Downgrade") == 0)
+ *result = REFINE_FAILURE_BEHAVIOR_DOWNGRADE;
+ else
+ return false;
+
+ return true;
+}
+
+/// @copydoc refine_interface_private::readdb_refinery_ui_settings_items()
+static bool refine_readdb_refinery_ui_settings_items(const struct config_setting_t *elem, struct s_refine_requirement *req, const char *name, const char *source)
+{
+ nullpo_retr(false, elem);
+ nullpo_retr(false, req);
+ nullpo_retr(false, name);
+ nullpo_retr(false, source);
+ Assert_retr(false, req->req_count < MAX_REFINE_REQUIREMENTS);
+
+ const char *aegis_name = config_setting_name(elem);
+ struct item_data *itd;
+
+ if ((itd = itemdb->search_name(aegis_name)) == NULL) {
+ ShowWarning("refine_readdb_requirements_items: Invalid item '%s' passed to requirements of '%s' in \"%s\" skipping...\n", aegis_name, name, source);
+ return false;
+ }
+
+ for (int i = 0; i < req->req_count; ++i) {
+ if (req->req[i].nameid == itd->nameid) {
+ ShowWarning("refine_readdb_requirements_items: Duplicated item '%s' passed to requirements of '%s' in \"%s\" skipping...\n", aegis_name, name, source);
+ return false;
+ }
+ }
+
+ const char *type_string = NULL;
+ if (libconfig->setting_lookup_string(elem, "Type", &type_string) == CONFIG_FALSE) {
+ ShowWarning("refine_readdb_requirements_items: no type passed to item '%s' of requirements of '%s' in \"%s\" skipping...\n", aegis_name, name, source);
+ return false;
+ }
+
+ int type;
+ if (!script->get_constant(type_string, &type)) {
+ ShowWarning("refine_readdb_requirements_items: invalid type '%s' passed to item '%s' of requirements of '%s' in \"%s\" skipping...\n", type_string, aegis_name, name, source);
+ return false;
+ }
+
+ int cost = 0;
+ if (libconfig->setting_lookup_int(elem, "Cost", &cost) == CONFIG_TRUE) {
+ if (cost < 1) {
+ ShowWarning("refine_readdb_requirements_items: invalid cost value %d passed to item '%s' of requirements of '%s' in \"%s\" defaulting to 0...\n", cost, aegis_name, name, source);
+ cost = 0;
+ }
+ }
+
+ enum refine_ui_failure_behavior behavior = REFINE_FAILURE_BEHAVIOR_DESTROY;
+ const char *behavior_string = NULL;
+ if (libconfig->setting_lookup_string(elem, "FailureBehavior", &behavior_string) != CONFIG_FALSE) {
+ if (!refine->p->failure_behavior_string2enum(behavior_string, &behavior)) {
+ ShowWarning("refine_readdb_requirements_items: invalid failure behavior value %s passed to item '%s' of requirements of '%s' in \"%s\" defaulting to 'Destroy'...\n", behavior_string, aegis_name, name, source);
+ }
+ }
+
+ req->req[req->req_count].nameid = itd->nameid;
+ req->req[req->req_count].type = type;
+ req->req[req->req_count].cost = cost;
+ req->req[req->req_count].failure_behavior = behavior;
+ req->req_count++;
+
+ return true;
+}
+
+/// @copydoc refine_interface_private::readdb_refinery_ui_settings_sub()
+static bool refine_readdb_refinery_ui_settings_sub(const struct config_setting_t *elem, int type, const char *name, const char *source)
+{
+ nullpo_retr(false, elem);
+ nullpo_retr(false, name);
+ nullpo_retr(false, source);
+ Assert_retr(0, type >= REFINE_TYPE_ARMOR && type < REFINE_TYPE_MAX);
+
+ struct config_setting_t *level_t;
+ bool levels[MAX_REFINE] = {0};
+
+ if ((level_t = libconfig->setting_get_member(elem, "Level")) == NULL) {
+ ShowWarning("refine_readdb_requirements_sub: a requirements element missing level field for entry '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ if (config_setting_is_scalar(level_t)) {
+ if (!config_setting_is_number(level_t)) {
+ ShowWarning("refine_readdb_requirements_sub: expected 'Level' field to be an integer '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ int refine_level = libconfig->setting_get_int(level_t);
+ if (refine_level < 1 || refine_level > MAX_REFINE) {
+ ShowWarning("refine_readdb_requirements_sub: Invalid 'Level' given value %d expected a value between %d and %d '%s' in \"%s\" skipping...\n", refine_level, 1, MAX_REFINE, name, source);
+ return false;
+ }
+
+ levels[refine_level - 1] = true;
+ } else if (config_setting_is_aggregate(level_t)) {
+ if (libconfig->setting_length(level_t) != 2) {
+ ShowWarning("refine_readdb_requirements_sub: invalid length for Level array, expected 2 found %d for entry '%s' in \"%s\" skipping...\n", libconfig->setting_length(level_t), name, source);
+ return false;
+ }
+
+ int levels_range[2];
+ const struct config_setting_t *level_entry = NULL;
+ int i = 0,
+ k = 0;
+ while ((level_entry = libconfig->setting_get_elem(level_t, i++)) != NULL) {
+ if (!config_setting_is_number(level_entry)) {
+ ShowWarning("refine_readdb_requirements_sub: expected 'Level' array field to be an integer '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ levels_range[k] = libconfig->setting_get_int(level_entry);
+ if (levels_range[k] < 1 || levels_range[k] > MAX_REFINE) {
+ ShowWarning("refine_readdb_requirements_sub: Invalid 'Level' given value %d expected a value between %d and %d in entry'%s' in \"%s\" skipping...\n", levels_range[k], 1, MAX_REFINE, name, source);
+ return false;
+ }
+
+ ++k;
+ }
+
+ if (!(levels_range[0] < levels_range[1])) {
+ ShowWarning("refine_readdb_requirements_sub: Invalid 'Level' range was given low %d high %d in entry'%s' in \"%s\" skipping...\n", levels_range[0], levels_range[1], name, source);
+ return false;
+ }
+
+ for (i = levels_range[0] - 1; i < levels_range[1]; ++i) {
+ levels[i] = true;
+ }
+ }
+
+ struct s_refine_requirement req = {0};
+ if (libconfig->setting_lookup_int(elem, "BlacksmithBlessing", &req.blacksmith_blessing) == CONFIG_TRUE) {
+ if (req.blacksmith_blessing < 1 || req.blacksmith_blessing > INT8_MAX) {
+ ShowWarning("refine_readdb_requirements_sub: Invalid 'BlacksmithBlessing' amount was given value %d expected a value between %d and %d in entry'%s' in \"%s\" defaulting to 0...\n", req.blacksmith_blessing, 1, INT8_MAX, name, source);
+ req.blacksmith_blessing = 0;
+ }
+ }
+
+ req.announce = 0;
+ const char *announce_behavior = NULL;
+ if (libconfig->setting_lookup_string(elem, "Announce", &announce_behavior) != CONFIG_FALSE) {
+ if (!refine->p->announce_behavior_string2enum(announce_behavior, &req.announce)) {
+ ShowWarning("refine_readdb_requirements_sub: invalid announce behavior value '%s' in entry '%s' in \"%s\" defaulting to not announce...\n", announce_behavior, name, source);
+ }
+ }
+
+ struct config_setting_t *items_t;
+ if ((items_t = libconfig->setting_get_member(elem, "Items")) == NULL) {
+ ShowWarning("refine_readdb_requirements_sub: a requirements element missing Items element for entry '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ if (libconfig->setting_length(items_t) < 1) {
+ ShowWarning("refine_readdb_requirements_sub: an Items element containing no items passed for entry '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ int loaded_items = 0;
+ for (int i = 0; i < libconfig->setting_length(items_t); ++i) {
+ if (req.req_count >= MAX_REFINE_REQUIREMENTS) {
+ ShowWarning("refine_readdb_requirements_sub: Too many items passed to requirements maximum possible items is %d entry '%s' in \"%s\" skipping...\n", MAX_REFINE_REQUIREMENTS, name, source);
+ continue;
+ }
+
+ struct config_setting_t *item_t = libconfig->setting_get_elem(items_t, i);
+
+ if (!refine->p->readdb_refinery_ui_settings_items(item_t, &req, name, source))
+ continue;
+
+ loaded_items++;
+ }
+
+ if (loaded_items == 0) {
+ ShowWarning("refine_readdb_requirements_sub: no valid items for requirements is passed for entry '%s' in \"%s\" skipping...\n", name, source);
+ return false;
+ }
+
+ for (int i = 0; i < MAX_REFINE; ++i) {
+ if (!levels[i])
+ continue;
+
+ refine->p->dbs->refine_info[type].refine_requirements[i] = req;
+ }
+
+ return true;
+}
+
+/// @copydoc refine_interface_private::readdb_refinery_ui_settings()
+static int refine_readdb_refinery_ui_settings(const struct config_setting_t *r, int type, const char *name, const char *source)
+{
+ nullpo_retr(0, r);
+ nullpo_retr(0, name);
+ nullpo_retr(0, source);
+ Assert_retr(0, type >= REFINE_TYPE_ARMOR && type < REFINE_TYPE_MAX);
+
+ int i = 0;
+ const struct config_setting_t *elem = NULL;
+ while ((elem = libconfig->setting_get_elem(r, i++)) != NULL) {
+ refine->p->readdb_refinery_ui_settings_sub(elem, type, name, source);
+ }
+
+ int retval = 0;
+ for (i = 0; i < MAX_REFINE; ++i) {
+ if (refine->p->dbs->refine_info[type].refine_requirements[i].req_count > 0)
+ retval++;
+ }
+
+ return retval;
+}
+
+/// @copydoc refine_interface_private::readdb_refine_libconfig_sub()
+static int refine_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source)
+{
+ struct config_setting_t *rate = NULL;
+ int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0;
+ char lv[4];
+ nullpo_ret(r);
+ nullpo_ret(name);
+ nullpo_ret(source);
+
+ if (strncmp(name, "Armors", 6) == 0) {
+ type = REFINE_TYPE_ARMOR;
+ } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) {
+ ShowError("status_readdb_refine_libconfig_sub: Invalid key name for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+ if (type < REFINE_TYPE_ARMOR || type >= REFINE_TYPE_MAX) {
+ ShowError("status_readdb_refine_libconfig_sub: Out of range level for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+
+ struct config_setting_t *refinery_ui_settings;
+ if ((refinery_ui_settings = libconfig->setting_get_member(r, "RefineryUISettings")) == NULL) {
+ ShowWarning("status_readdb_refine_libconfig_sub: Missing Requirements for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+
+ if (refine->p->readdb_refinery_ui_settings(refinery_ui_settings, type, name, source) != MAX_REFINE) {
+ ShowWarning("status_readdb_refine_libconfig_sub: Not all refine levels have requrements entry for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+
+ if (!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) {
+ ShowWarning("status_readdb_refine_libconfig_sub: Missing StatsPerLevel for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+ if (!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) {
+ ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusStartLevel for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+ if (!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) {
+ ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusValue for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+
+ if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) {
+ bool duplicate[MAX_REFINE];
+ int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE];
+ int chance[REFINE_CHANCE_TYPE_MAX][MAX_REFINE];
+
+ memset(&duplicate, 0, sizeof(duplicate));
+ memset(&bonus, 0, sizeof(bonus));
+ memset(&rnd_bonus, 0, sizeof(rnd_bonus));
+
+ for (int i = 0; i < REFINE_CHANCE_TYPE_MAX; i++)
+ for (int j = 0; j < MAX_REFINE; j++)
+ chance[i][j] = 100; // default value for all rates.
+
+ struct config_setting_t *t = NULL;
+ for (int i = 0; (t = libconfig->setting_get_elem(rate, i)) != NULL && config_setting_is_group(t); ++i) {
+ int level = 0, i32;
+ char *rlvl = config_setting_name(t);
+ memset(&lv, 0, sizeof(lv));
+
+ if (!strspn(&rlvl[strlen(rlvl) - 1], "0123456789") || (level = atoi(strncpy(lv, rlvl + 2, 3))) <= 0) {
+ ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source);
+ continue;
+ }
+
+ if (level <= 0 || level > MAX_REFINE) {
+ ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source);
+ continue;
+ }
+
+ level--;
+
+ if (duplicate[level]) {
+ ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source);
+ } else {
+ duplicate[level] = true;
+ }
+
+ if (libconfig->setting_lookup_int(t, "NormalChance", &i32) != 0)
+ chance[REFINE_CHANCE_TYPE_NORMAL][level] = i32;
+ else
+ chance[REFINE_CHANCE_TYPE_NORMAL][level] = 100;
+
+ if (libconfig->setting_lookup_int(t, "EnrichedChance", &i32) != 0)
+ chance[REFINE_CHANCE_TYPE_ENRICHED][level] = i32;
+ else
+ chance[REFINE_CHANCE_TYPE_ENRICHED][level] = level > 10 ? 0 : 100; // enriched ores up to +10 only.
+
+ if (libconfig->setting_lookup_int(t, "EventNormalChance", &i32) != 0)
+ chance[REFINE_CHANCE_TYPE_E_NORMAL][level] = i32;
+ else
+ chance[REFINE_CHANCE_TYPE_E_NORMAL][level] = 100;
+
+ if (libconfig->setting_lookup_int(t, "EventEnrichedChance", &i32) != 0)
+ chance[REFINE_CHANCE_TYPE_E_ENRICHED][level] = i32;
+ else
+ chance[REFINE_CHANCE_TYPE_E_ENRICHED][level] = level > 10 ? 0 : 100; // enriched ores up to +10 only.
+
+ if (libconfig->setting_lookup_int(t, "Bonus", &i32) != 0)
+ bonus[level] += i32;
+
+ if (level >= rnd_bonus_lv - 1)
+ rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2);
+ }
+ for (int i = 0; i < MAX_REFINE; i++) {
+ refine->p->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_NORMAL][i] = chance[REFINE_CHANCE_TYPE_NORMAL][i];
+ refine->p->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_E_NORMAL][i] = chance[REFINE_CHANCE_TYPE_E_NORMAL][i];
+ refine->p->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_ENRICHED][i] = chance[REFINE_CHANCE_TYPE_ENRICHED][i];
+ refine->p->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_E_ENRICHED][i] = chance[REFINE_CHANCE_TYPE_E_ENRICHED][i];
+ refine->p->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i];
+ bonus[i] += bonus_per_level + (i > 0 ? bonus[i - 1] : 0);
+ refine->p->dbs->refine_info[type].bonus[i] = bonus[i];
+ }
+ } else {
+ ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source);
+ return 0;
+ }
+
+ return type + 1;
+}
+
+/// @copydoc refine_interface_private::readdb_refine_libconfig()
+static int refine_readdb_refine_libconfig(const char *filename)
+{
+ nullpo_retr(0, filename);
+
+ bool duplicate[REFINE_TYPE_MAX];
+ struct config_t refine_db_conf;
+ struct config_setting_t *r;
+ char filepath[256];
+ int i = 0, count = 0;
+
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
+ if (!libconfig->load_file(&refine_db_conf, filepath))
+ return 0;
+
+ memset(&duplicate, 0, sizeof(duplicate));
+
+ while((r = libconfig->setting_get_elem(refine_db_conf.root, i++))) {
+ char *name = config_setting_name(r);
+ int type = refine->p->readdb_refine_libconfig_sub(r, name, filename);
+ if (type != 0) {
+ if (duplicate[type - 1]) {
+ ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename);
+ } else {
+ duplicate[type - 1] = true;
+ }
+ count++;
+ }
+ }
+ libconfig->destroy(&refine_db_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+
+ return count;
+}
+
+/// @copydoc refine_interface::init()
+static int refine_init(bool minimal)
+{
+ if (minimal)
+ return 0;
+
+ refine->p->readdb_refine_libconfig(DBPATH"refine_db.conf");
+ return 0;
+}
+
+/// @copydoc refine_interface::final()
+static void refine_final(void)
+{
+}
+
+void refine_defaults(void)
+{
+ refine = &refine_s;
+ refine->p = &refine_p;
+ refine->p->dbs = &refine_dbs;
+
+ refine->p->readdb_refine_libconfig = refine_readdb_refine_libconfig;
+ refine->p->readdb_refine_libconfig_sub = refine_readdb_refine_libconfig_sub;
+ refine->p->announce_behavior_string2enum = refine_announce_behavior_string2enum;
+ refine->p->failure_behavior_string2enum = refine_failure_behavior_string2enum;
+ refine->p->readdb_refinery_ui_settings_items = refine_readdb_refinery_ui_settings_items;
+ refine->p->readdb_refinery_ui_settings_sub = refine_readdb_refinery_ui_settings_sub;
+ refine->p->readdb_refinery_ui_settings = refine_readdb_refinery_ui_settings;
+ refine->p->is_refinable = refine_is_refinable;
+
+ refine->init = refine_init;
+ refine->final = refine_final;
+ refine->refinery_refine_request = refine_refinery_refine_request;
+ refine->refinery_add_item = refine_refinery_add_item;
+ refine->get_refine_chance = refine_get_refine_chance;
+ refine->get_bonus = refine_get_bonus;
+ refine->get_randombonus_max = refine_get_randombonus_max;
+}
diff --git a/src/map/refine.h b/src/map/refine.h
new file mode 100644
index 000000000..bb3790a45
--- /dev/null
+++ b/src/map/refine.h
@@ -0,0 +1,148 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2019-2020 Hercules Dev Team
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MAP_REFINE_H
+#define MAP_REFINE_H
+
+/** @file
+ * Refine Interface.
+ **/
+#include "common/hercules.h"
+#include "common/mmo.h"
+
+/* Defines */
+/**
+* Max Refine available to your server
+* Changing this limit requires edits to refine_db.conf
+**/
+#ifdef RENEWAL
+ #define MAX_REFINE 20
+#else
+ #define MAX_REFINE 10
+#endif
+
+/* Forward Declarations */
+struct refine_interface_private;
+
+/* Enums */
+enum refine_type {
+ REFINE_TYPE_ARMOR = 0,
+ REFINE_TYPE_WEAPON1 = 1,
+ REFINE_TYPE_WEAPON2 = 2,
+ REFINE_TYPE_WEAPON3 = 3,
+ REFINE_TYPE_WEAPON4 = 4,
+#ifndef REFINE_TYPE_MAX
+ REFINE_TYPE_MAX = 5
+#endif
+};
+
+enum refine_chance_type {
+ REFINE_CHANCE_TYPE_NORMAL = 0, // Normal Chance
+ REFINE_CHANCE_TYPE_ENRICHED = 1, // Enriched Ore Chance
+ REFINE_CHANCE_TYPE_E_NORMAL = 2, // Event Normal Ore Chance
+ REFINE_CHANCE_TYPE_E_ENRICHED = 3, // Event Enriched Ore Chance
+ REFINE_CHANCE_TYPE_MAX
+};
+
+enum refine_ui_failure_behavior {
+ REFINE_FAILURE_BEHAVIOR_DESTROY,
+ REFINE_FAILURE_BEHAVIOR_KEEP,
+ REFINE_FAILURE_BEHAVIOR_DOWNGRADE
+};
+
+/* Structure */
+struct s_refine_requirement {
+ int blacksmith_blessing;
+ int req_count;
+ unsigned int announce;
+
+ struct {
+ int nameid;
+ int cost;
+ enum refine_chance_type type;
+ enum refine_ui_failure_behavior failure_behavior;
+ } req[MAX_REFINE_REQUIREMENTS];
+};
+
+/**
+ * Refine Interface
+ **/
+struct refine_interface {
+ struct refine_interface_private *p;
+
+ /**
+ * Initialize refine system
+ * @param minimal sets refine system to minimal mode in which it won't load or initialize itself
+ * @return returns 0 in-case of success 1 otherwise
+ **/
+ int (*init)(bool minimal);
+
+ /**
+ * Finalize refine system
+ **/
+ void (*final)(void);
+
+ /**
+ * Get the chance to upgrade a piece of equipment.
+ * @param wlv The weapon type of the item to refine (see see enum refine_type)
+ * @param refine The target refine level
+ * @return The chance to refine the item, in percent (0~100)
+ **/
+ int (*get_refine_chance) (enum refine_type wlv, int refine_level, enum refine_chance_type type);
+
+ /**
+ * Gets the attack/deffense bonus for the given equipment type and refine level
+ * @param equipment_type the equipment type
+ * @param refine_level the equipment refine level
+ * @return returns the bonus from refine db
+ **/
+ int (*get_bonus) (enum refine_type equipment_type, int refine_level);
+
+ /**
+ * Gets the maximum attack/deffense random bonus for the given equipment type and refine level
+ * @param equipment_type the equipment type
+ * @param refine_level the equipment refine level
+ * @return returns the bonus from refine db
+ **/
+ int(*get_randombonus_max) (enum refine_type equipment_type, int refine_level);
+
+ /**
+ * Validates and send Item addition packet to the client for refinery UI
+ * @param sd player session data.
+ * @param item_index the requested item index in inventory.
+ **/
+ void (*refinery_add_item) (struct map_session_data *sd, int item_index);
+
+ /**
+ * Processes an refine request through Refinery UI
+ * @param sd player session data
+ * @param item_index the index of the requested item
+ * @param material_id the refine material chosen by player
+ * @param use_blacksmith_blessing sets either if blacksmith blessing is requested to be used or not
+ **/
+ void (*refinery_refine_request) (struct map_session_data *sd, int item_index, int material_id, bool use_blacksmith_blessing);
+};
+
+#ifdef HERCULES_CORE
+void refine_defaults(void);
+#endif
+
+HPShared struct refine_interface *refine;
+#endif
diff --git a/src/map/refine.p.h b/src/map/refine.p.h
new file mode 100644
index 000000000..5dbed2afc
--- /dev/null
+++ b/src/map/refine.p.h
@@ -0,0 +1,144 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2019-2020 Hercules Dev Team
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MAP_REFINE_P_H
+#define MAP_REFINE_P_H
+
+/** @file
+ * Private header for the refine interface.
+ **/
+
+#include "refine.h"
+#include "common/conf.h"
+/* Enums */
+enum refine_announce_condition {
+ REFINE_ANNOUNCE_SUCCESS = 0x1,
+ REFINE_ANNOUNCE_FAILURE = 0x2,
+ REFINE_ANNOUNCE_ALWAYS = REFINE_ANNOUNCE_SUCCESS | REFINE_ANNOUNCE_FAILURE,
+};
+
+/* Structures */
+struct s_refine_info {
+ int chance[REFINE_CHANCE_TYPE_MAX][MAX_REFINE]; //< success chance
+ int bonus[MAX_REFINE]; //< cumulative fixed bonus damage
+ int randombonus_max[MAX_REFINE]; //< cumulative maximum random bonus damage
+ struct s_refine_requirement refine_requirements[MAX_REFINE]; //< The requirements used for refinery UI
+};
+
+struct refine_interface_dbs {
+ struct s_refine_info refine_info[REFINE_TYPE_MAX];
+};
+
+/**
+ * Refine Private Interface
+ **/
+struct refine_interface_private {
+ struct refine_interface_dbs *dbs;
+
+ /**
+ * Processes a refine_db.conf entry.
+ *
+ * @param r Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary)
+ * @param n Ordinal number of the entry, to be displayed in case of
+ * validation errors.
+ * @param source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return # of the validated entry, or 0 in case of failure.
+ **/
+ int (*readdb_refine_libconfig_sub) (struct config_setting_t *r, const char *name, const char *source);
+
+ /**
+ * Reads from a libconfig-formatted refine_db.conf file.
+ *
+ * @param *filename File name, relative to the database path.
+ * @return The number of found entries.
+ **/
+ int (*readdb_refine_libconfig) (const char *filename);
+
+ /**
+ * Converts refine database announce behvaior string to enum refine_announce_condition
+ * @param str the string to convert
+ * @param result pointer to where the converted value will be held
+ * @return true on success, false otherwise.
+ **/
+ bool (*announce_behavior_string2enum) (const char *str, unsigned int *result);
+
+ /**
+ * Converts refine database failure behvaior string to enum refine_ui_failure_behavior
+ * @param str the string to convert
+ * @param result pointer to where the converted value will be held
+ * @return true on success, false otherwise.
+ **/
+ bool (*failure_behavior_string2enum) (const char *str, enum refine_ui_failure_behavior *result);
+
+ /**
+ * Processes a refine_db.conf RefineryUISettings items entry.
+ *
+ * @param elem Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary)
+ * @param req a pointer to requirements struct to fill with the item data
+ * @param name the current element name
+ * @param source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return true on success, false otherwise.
+ **/
+ bool (*readdb_refinery_ui_settings_items) (const struct config_setting_t *elem, struct s_refine_requirement *req, const char *name, const char *source);
+
+ /**
+ * Processes a refine_db.conf RefineryUISettings entry.
+ *
+ * @param elem Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary)
+ * @param type the type index in refine database to fill the data
+ * @param name the current element name
+ * @param source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return true on success, false otherwise.
+ **/
+ bool (*readdb_refinery_ui_settings_sub) (const struct config_setting_t *elem, int type, const char *name, const char *source);
+
+ /**
+ * Reads a refine_db.conf RefineryUISettings entry and sends it to be processed.
+ *
+ * @param r Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary)
+ * @param type the type index in refine database to fill the data
+ * @param name the current element name
+ * @param source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return true on success, false otherwise.
+ **/
+ int (*readdb_refinery_ui_settings) (const struct config_setting_t *r, int type, const char *name, const char *source);
+
+ /**
+ * Checks if a given item in player's inventory is refineable.
+ * @param sd player session data.
+ * @param item_index the item index in player's inventory.
+ * @return true if item is refineable, false otherwise.
+ **/
+ bool (*is_refinable) (struct map_session_data *sd, int item_index);
+};
+
+#endif
diff --git a/src/map/rodex.c b/src/map/rodex.c
new file mode 100644
index 000000000..1ebed0623
--- /dev/null
+++ b/src/map/rodex.c
@@ -0,0 +1,683 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017-2020 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#define HERCULES_CORE
+
+#include "rodex.h"
+
+#include "map/battle.h"
+#include "map/date.h"
+#include "map/intif.h"
+#include "map/itemdb.h"
+#include "map/pc.h"
+
+#include "common/nullpo.h"
+#include "common/sql.h"
+#include "common/memmgr.h"
+
+
+// NOTE : These values are hardcoded into the client
+// Cost of each Attached Item
+#define ATTACHITEM_COST 2500
+// Percent of Attached Zeny that will be paid as Tax
+#define ATTACHZENY_TAX 2
+// Maximun number of messages that can be sent in one day
+#define DAILY_MAX_MAILS 100
+
+static struct rodex_interface rodex_s;
+struct rodex_interface *rodex;
+
+/// Checks if RoDEX System is enabled in the server
+/// Returns true if it's enabled, false otherwise
+static bool rodex_isenabled(void)
+{
+ if (battle_config.feature_rodex == 1)
+ return true;
+
+ return false;
+}
+
+/// Checks and refreshes the user daily number of Stamps
+/// @param sd : The player who's being checked
+static void rodex_refresh_stamps(struct map_session_data *sd)
+{
+ int today = date_get_date();
+ nullpo_retv(sd);
+
+ // Note : Weirdly, iRO starts this with maximum messages of the day and decrements
+ // but our clients starts this at 0 and increments
+ if (sd->sc.data[SC_DAILYSENDMAILCNT] == NULL) {
+ sc_start2(NULL, &sd->bl, SC_DAILYSENDMAILCNT, 100, today, 0, INFINITE_DURATION);
+ } else {
+ int sc_date = sd->sc.data[SC_DAILYSENDMAILCNT]->val1;
+ if (sc_date != today) {
+ sc_start2(NULL, &sd->bl, SC_DAILYSENDMAILCNT, 100, today, 0, INFINITE_DURATION);
+ }
+ }
+}
+
+/// Attaches an item to a message being written
+/// @param sd : The player who's writting
+/// @param idx : the inventory idx of the item
+/// @param amount : Amount of the item to be attached
+static void rodex_add_item(struct map_session_data *sd, int16 idx, int16 amount)
+{
+ int i;
+ bool is_stack = false;
+
+ nullpo_retv(sd);
+
+ if (idx < 0 || idx >= sd->status.inventorySize) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ if (amount < 0 || amount > sd->status.inventory[idx].amount) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ if (!pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||
+ !itemdb_canmail(&sd->status.inventory[idx], pc_get_group_level(sd)) ||
+ (sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd))) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_NOT_TRADEABLE);
+ return;
+ }
+
+ if (itemdb->isstackable(sd->status.inventory[idx].nameid) == 1) {
+ for (i = 0; i < RODEX_MAX_ITEM; ++i) {
+ if (sd->rodex.tmp.items[i].idx == idx) {
+ if (sd->status.inventory[idx].nameid == sd->rodex.tmp.items[i].item.nameid &&
+ sd->status.inventory[idx].unique_id == sd->rodex.tmp.items[i].item.unique_id) {
+ is_stack = true;
+ break;
+ }
+ }
+ }
+
+ if (i == RODEX_MAX_ITEM && sd->rodex.tmp.items_count < RODEX_MAX_ITEM) {
+ ARR_FIND(0, RODEX_MAX_ITEM, i, sd->rodex.tmp.items[i].idx == 0);
+ }
+ } else if (sd->rodex.tmp.items_count < RODEX_MAX_ITEM) {
+ ARR_FIND(0, RODEX_MAX_ITEM, i, sd->rodex.tmp.items[i].idx == 0);
+ } else {
+ i = RODEX_MAX_ITEM;
+ }
+
+ if (i == RODEX_MAX_ITEM) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_NO_SPACE);
+ return;
+ }
+
+ if (sd->rodex.tmp.items[i].item.amount + amount > sd->status.inventory[idx].amount) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ if (sd->rodex.tmp.weight + sd->inventory_data[idx]->weight * amount > RODEX_WEIGHT_LIMIT) {
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ sd->rodex.tmp.items[i].idx = idx;
+ sd->rodex.tmp.weight += sd->inventory_data[idx]->weight * amount;
+ if (is_stack == false) {
+ sd->rodex.tmp.items[i].item = sd->status.inventory[idx];
+ sd->rodex.tmp.items[i].item.amount = amount;
+ sd->rodex.tmp.items_count++;
+ } else {
+ sd->rodex.tmp.items[i].item.amount += amount;
+ }
+ sd->rodex.tmp.type |= MAIL_TYPE_ITEM;
+
+ clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_SUCCESS);
+}
+
+/// Removes an item attached to a message being writen
+/// @param sd : The player who's writting the message
+/// @param idx : The index of the item
+/// @param amount : How much to remove
+static void rodex_remove_item(struct map_session_data *sd, int16 idx, int16 amount)
+{
+ int i;
+ struct item *it;
+ struct item_data *itd;
+
+ nullpo_retv(sd);
+ Assert_retv(idx >= 0 && idx < sd->status.inventorySize);
+
+ for (i = 0; i < RODEX_MAX_ITEM; ++i) {
+ if (sd->rodex.tmp.items[i].idx == idx)
+ break;
+ }
+
+ if (i == RODEX_MAX_ITEM) {
+ clif->rodex_remove_item_result(sd, idx, -1);
+ return;
+ }
+
+ it = &sd->rodex.tmp.items[i].item;
+
+ if (amount <= 0 || amount > it->amount) {
+ clif->rodex_remove_item_result(sd, idx, -1);
+ return;
+ }
+
+ itd = itemdb->search(it->nameid);
+
+ if (amount == it->amount) {
+ sd->rodex.tmp.weight -= itd->weight * amount;
+ sd->rodex.tmp.items_count--;
+ if (sd->rodex.tmp.items_count < 1) {
+ sd->rodex.tmp.type &= ~MAIL_TYPE_ITEM;
+ }
+ memset(&sd->rodex.tmp.items[i], 0x0, sizeof(sd->rodex.tmp.items[0]));
+ clif->rodex_remove_item_result(sd, idx, 0);
+ return;
+ }
+
+ it->amount -= amount;
+ sd->rodex.tmp.weight -= itd->weight * amount;
+
+ clif->rodex_remove_item_result(sd, idx, it->amount);
+}
+
+/// Request if character with given name exists and returns information about him
+/// @param sd : The player who's requesting
+/// @param name : The name of the character to check
+/// @param base_level : Reference to return the character base level, if he exists
+/// @param char_id : Reference to return the character id, if he exists
+/// @param class : Reference to return the character class id, if he exists
+static void rodex_check_player(struct map_session_data *sd, const char *name, int *base_level, int *char_id, int *class)
+{
+ intif->rodex_checkname(sd, name);
+}
+
+/// Sends a Mail to an character
+/// @param sd : The player who's sending
+/// @param receiver_name : The name of the character who's receiving the message
+/// @param body : Mail message
+/// @param title : Mail Title
+/// @param zeny : Amount of zeny attached
+/// Returns result code:
+/// RODEX_SEND_MAIL_SUCCESS = 0,
+/// RODEX_SEND_MAIL_FATAL_ERROR = 1,
+/// RODEX_SEND_MAIL_COUNT_ERROR = 2,
+/// RODEX_SEND_MAIL_ITEM_ERROR = 3,
+/// RODEX_SEND_MAIL_RECEIVER_ERROR = 4
+static int rodex_send_mail(struct map_session_data *sd, const char *receiver_name, const char *body, const char *title, int64 zeny)
+{
+ int i;
+ int64 total_zeny;
+
+ nullpo_retr(RODEX_SEND_MAIL_FATAL_ERROR, sd);
+ nullpo_retr(RODEX_SEND_MAIL_FATAL_ERROR, receiver_name);
+ nullpo_retr(RODEX_SEND_MAIL_FATAL_ERROR, body);
+ nullpo_retr(RODEX_SEND_MAIL_FATAL_ERROR, title);
+
+ if (!rodex->isenabled() || sd->npc_id > 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_FATAL_ERROR;
+ }
+
+ if (zeny < 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_FATAL_ERROR;
+ }
+
+ total_zeny = zeny + sd->rodex.tmp.items_count * ATTACHITEM_COST + (2 * zeny)/100;
+
+ if (strcmp(receiver_name, sd->rodex.tmp.receiver_name) != 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_RECEIVER_ERROR;
+ }
+
+ if (total_zeny > sd->status.zeny || total_zeny < 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_FATAL_ERROR;
+ }
+
+ rodex_refresh_stamps(sd);
+
+ if (sd->sc.data[SC_DAILYSENDMAILCNT] != NULL) {
+ if (sd->sc.data[SC_DAILYSENDMAILCNT]->val2 >= DAILY_MAX_MAILS) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_COUNT_ERROR;
+ }
+
+ sc_start2(NULL, &sd->bl, SC_DAILYSENDMAILCNT, 100, sd->sc.data[SC_DAILYSENDMAILCNT]->val1, sd->sc.data[SC_DAILYSENDMAILCNT]->val2 + 1, INFINITE_DURATION);
+ } else {
+ sc_start2(NULL, &sd->bl, SC_DAILYSENDMAILCNT, 100, date_get_date(), 1, INFINITE_DURATION);
+ }
+
+ for (i = 0; i < RODEX_MAX_ITEM; i++) {
+ int16 idx = sd->rodex.tmp.items[i].idx;
+ int j;
+ struct item *tmpItem = &sd->rodex.tmp.items[i].item;
+ struct item *invItem = &sd->status.inventory[idx];
+
+ if (tmpItem->nameid == 0)
+ continue;
+
+ if (tmpItem->nameid != invItem->nameid ||
+ tmpItem->unique_id != invItem->unique_id ||
+ tmpItem->refine != invItem->refine ||
+ tmpItem->attribute != invItem->attribute ||
+ tmpItem->expire_time != invItem->expire_time ||
+ tmpItem->bound != invItem->bound ||
+ tmpItem->amount > invItem->amount ||
+ tmpItem->amount < 1) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_ITEM_ERROR;
+ }
+ for (j = 0; j < MAX_SLOTS; j++) {
+ if (tmpItem->card[j] != invItem->card[j]) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_ITEM_ERROR;
+ }
+ }
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) {
+ if (tmpItem->option[j].index != invItem->option[j].index ||
+ tmpItem->option[j].value != invItem->option[j].value ||
+ tmpItem->option[j].param != invItem->option[j].param) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_ITEM_ERROR;
+ }
+ }
+ }
+
+ if (total_zeny > 0 && pc->payzeny(sd, (int)total_zeny, LOG_TYPE_MAIL, NULL) != 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_FATAL_ERROR;
+ }
+
+ for (i = 0; i < RODEX_MAX_ITEM; i++) {
+ int16 idx = sd->rodex.tmp.items[i].idx;
+
+ if (sd->rodex.tmp.items[i].item.nameid == 0) {
+ continue;
+ }
+
+ if (pc->delitem(sd, idx, sd->rodex.tmp.items[i].item.amount, 0, DELITEM_NORMAL, LOG_TYPE_MAIL) != 0) {
+ rodex->clean(sd, 1);
+ return RODEX_SEND_MAIL_ITEM_ERROR;
+ }
+ }
+
+ sd->rodex.tmp.zeny = zeny;
+ sd->rodex.tmp.is_read = false;
+ sd->rodex.tmp.is_deleted = false;
+ sd->rodex.tmp.send_date = (int)time(NULL);
+ sd->rodex.tmp.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+ if (strlen(sd->rodex.tmp.body) > 0)
+ sd->rodex.tmp.type |= MAIL_TYPE_TEXT;
+ if (sd->rodex.tmp.zeny > 0)
+ sd->rodex.tmp.type |= MAIL_TYPE_ZENY;
+ sd->rodex.tmp.sender_id = sd->status.char_id;
+ safestrncpy(sd->rodex.tmp.sender_name, sd->status.name, NAME_LENGTH);
+ safestrncpy(sd->rodex.tmp.title, title, RODEX_TITLE_LENGTH);
+ safestrncpy(sd->rodex.tmp.body, body, RODEX_BODY_LENGTH);
+
+ intif->rodex_sendmail(&sd->rodex.tmp);
+ return RODEX_SEND_MAIL_SUCCESS; // this will not inform client of the success yet. (see rodex_send_mail_result)
+}
+
+/// The result of a message send, called by char-server
+/// @param ssd : Sender's sd
+/// @param rsd : Receiver's sd
+/// @param result : Message sent (true) or failed (false)
+static void rodex_send_mail_result(struct map_session_data *ssd, struct map_session_data *rsd, bool result)
+{
+ if (ssd != NULL) {
+ rodex->clean(ssd, 1);
+ if (result == false) {
+ clif->rodex_send_mail_result(ssd->fd, ssd, RODEX_SEND_MAIL_FATAL_ERROR);
+ return;
+ }
+
+ clif->rodex_send_mail_result(ssd->fd, ssd, RODEX_SEND_MAIL_SUCCESS);
+ }
+
+ if (rsd != NULL) {
+ clif->rodex_icon(rsd->fd, true);
+ clif_disp_onlyself(rsd, "You've got a new mail!");
+ }
+ return;
+}
+
+/// Retrieves one message from character
+/// @param sd : Character
+/// @param mail_id : Mail ID that's being retrieved
+/// Returns the message
+static struct rodex_message *rodex_get_mail(struct map_session_data *sd, int64 mail_id)
+{
+ int i;
+ struct rodex_message *msg;
+ int char_id;
+
+ nullpo_retr(NULL, sd);
+
+ ARR_FIND(0, VECTOR_LENGTH(sd->rodex.messages), i, VECTOR_INDEX(sd->rodex.messages, i).id == mail_id);
+ if (i == VECTOR_LENGTH(sd->rodex.messages))
+ return NULL;
+
+ msg = &VECTOR_INDEX(sd->rodex.messages, i);
+
+ char_id = sd->status.char_id;
+
+ if ((msg->is_deleted == true)
+ || (msg->expire_date < time(NULL) && ((msg->receiver_accountid > 0) || (msg->receiver_id == char_id && msg->sender_id != char_id)))
+ || (msg->expire_date + RODEX_EXPIRE < time(NULL))
+ )
+ return NULL;
+
+ return msg;
+}
+
+/// Request to read a mail by its ID
+/// @param sd : Who's reading
+/// @param mail_id : Mail ID to be read
+static void rodex_read_mail(struct map_session_data *sd, int64 mail_id)
+{
+ struct rodex_message *msg;
+
+ nullpo_retv(sd);
+
+ msg = rodex->get_mail(sd, mail_id);
+ nullpo_retv(msg);
+
+ if (msg->opentype == RODEX_OPENTYPE_RETURN) {
+ if (msg->sender_read == false) {
+ intif->rodex_updatemail(sd, msg->id, 0, 4);
+ msg->sender_read = true;
+ }
+ } else {
+ if (msg->is_read == false) {
+ intif->rodex_updatemail(sd, msg->id, 0, 0);
+ msg->is_read = true;
+ }
+ }
+
+ clif->rodex_read_mail(sd, msg->opentype, msg);
+}
+
+/// Deletes a mail
+/// @param sd : Who's deleting
+/// @param mail_id : Mail ID to be deleted
+static void rodex_delete_mail(struct map_session_data *sd, int64 mail_id)
+{
+ struct rodex_message *msg;
+
+ nullpo_retv(sd);
+
+ msg = rodex->get_mail(sd, mail_id);
+ nullpo_retv(msg);
+
+ msg->is_deleted = true;
+ intif->rodex_updatemail(sd, msg->id, 0, 3);
+
+ clif->rodex_delete_mail(sd, msg->opentype, msg->id);
+}
+
+/// give requested zeny from message to player
+static void rodex_getZenyAck(struct map_session_data *sd, int64 mail_id, int8 opentype, int64 zeny)
+{
+ nullpo_retv(sd);
+ if (zeny <= 0) {
+ clif->rodex_request_zeny(sd, opentype, mail_id, RODEX_GET_ZENY_FATAL_ERROR);
+ return;
+ }
+
+ if (pc->getzeny(sd, (int)zeny, LOG_TYPE_MAIL, NULL) != 0) {
+ clif->rodex_request_zeny(sd, opentype, mail_id, RODEX_GET_ZENY_FATAL_ERROR);
+ return;
+ }
+
+ clif->rodex_request_zeny(sd, opentype, mail_id, RODEX_GET_ZENY_SUCCESS);
+}
+
+/// Gets attached zeny
+/// @param sd : Who's getting
+/// @param mail_id : Mail ID that we're getting zeny from
+static void rodex_get_zeny(struct map_session_data *sd, int8 opentype, int64 mail_id)
+{
+ nullpo_retv(sd);
+
+ struct rodex_message *msg = rodex->get_mail(sd, mail_id);
+
+ if (msg == NULL) {
+ clif->rodex_request_zeny(sd, opentype, mail_id, RODEX_GET_ZENY_FATAL_ERROR);
+ return;
+ }
+
+ if ((int64)sd->status.zeny + msg->zeny > MAX_ZENY) {
+ clif->rodex_request_zeny(sd, opentype, mail_id, RODEX_GET_ZENY_LIMIT_ERROR);
+ return;
+ }
+
+ msg->type &= ~MAIL_TYPE_ZENY;
+ msg->zeny = 0;
+ intif->rodex_updatemail(sd, mail_id, opentype, 1);
+}
+
+// give requested items from message to player
+static void rodex_getItemsAck(struct map_session_data *sd, int64 mail_id, int8 opentype, int count, const struct rodex_item *items)
+{
+ nullpo_retv(sd);
+ nullpo_retv(items);
+
+ for (int i = 0; i < count; ++i) {
+ const struct item *it = &items[i].item;
+
+ if (it->nameid == 0) {
+ continue;
+ }
+
+ if (pc->additem(sd, it, it->amount, LOG_TYPE_MAIL) != 0) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR);
+ return;
+ }
+ }
+
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEMS_SUCCESS);
+}
+
+/// Gets attached item
+/// @param sd : Who's getting
+/// @param mail_id : Mail ID that we're getting items from
+static void rodex_get_items(struct map_session_data *sd, int8 opentype, int64 mail_id)
+{
+ nullpo_retv(sd);
+
+ int weight = 0;
+ int empty_slots = 0;
+
+ struct rodex_message *msg = rodex->get_mail(sd, mail_id);
+
+ if (msg == NULL) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ if (msg->items_count < 1) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FATAL_ERROR);
+ return;
+ }
+
+ for (int i = 0; i < RODEX_MAX_ITEM; ++i) {
+ if (msg->items[i].item.nameid != 0) {
+ weight += itemdb->search(msg->items[i].item.nameid)->weight * msg->items[i].item.amount;
+ }
+ }
+
+ if ((sd->weight + weight > sd->max_weight)) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR);
+ return;
+ }
+
+ int required_slots = msg->items_count;
+ for (int i = 0; i < sd->status.inventorySize; ++i) {
+ if (sd->status.inventory[i].nameid == 0) {
+ empty_slots++;
+ } else if (itemdb->isstackable(sd->status.inventory[i].nameid) == 1) {
+ int j;
+ ARR_FIND(0, msg->items_count, j, sd->status.inventory[i].nameid == msg->items[j].item.nameid);
+ if (j < msg->items_count) {
+ struct item_data *idata = itemdb->search(sd->status.inventory[i].nameid);
+
+ if ((idata->stack.inventory && sd->status.inventory[i].amount + msg->items[j].item.amount > idata->stack.amount) ||
+ sd->status.inventory[i].amount + msg->items[j].item.amount > MAX_AMOUNT) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR);
+ return;
+ }
+
+ required_slots--;
+ }
+ }
+ }
+
+ if (empty_slots < required_slots) {
+ clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR);
+ return;
+ }
+
+ msg->type &= ~MAIL_TYPE_ITEM;
+ msg->items_count = 0;
+ intif->rodex_updatemail(sd, mail_id, opentype, 2);
+}
+
+/// Cleans user's RoDEX related data
+/// - should be called everytime we're going to stop using rodex in this character
+/// @param sd : Target to clean
+/// @param flag :
+/// 0 - clear everything
+/// 1 - clear tmp only
+static void rodex_clean(struct map_session_data *sd, int8 flag)
+{
+ nullpo_retv(sd);
+
+ if (flag == 0)
+ VECTOR_CLEAR(sd->rodex.messages);
+
+ memset(&sd->rodex.tmp, 0x0, sizeof(sd->rodex.tmp));
+}
+
+/// User request to open rodex, load mails from char-server
+/// @param sd : Who's requesting
+/// @param open_type : Box Type (see RODEX_OPENTYPE)
+static void rodex_open(struct map_session_data *sd, int8 open_type, int64 first_mail_id)
+{
+#if PACKETVER >= 20170419
+ const int type = 1;
+#else
+ const int type = 0;
+#endif
+ nullpo_retv(sd);
+ if (open_type == RODEX_OPENTYPE_ACCOUNT && battle_config.feature_rodex_use_accountmail == false)
+ open_type = RODEX_OPENTYPE_MAIL;
+
+ intif->rodex_requestinbox(sd->status.char_id, sd->status.account_id, type, open_type, first_mail_id);
+}
+
+/// User request to read next page of mails
+/// @param sd : Who's requesting
+/// @param open_type : Box Type (see RODEX_OPENTYPE)
+/// @param last_mail_id : The last mail from the current page
+static void rodex_next_page(struct map_session_data *sd, int8 open_type, int64 last_mail_id)
+{
+ int64 msg_count, page_start = 0;
+ nullpo_retv(sd);
+
+ if (open_type == RODEX_OPENTYPE_ACCOUNT && battle_config.feature_rodex_use_accountmail == false) {
+ // Should not happen
+ open_type = RODEX_OPENTYPE_MAIL;
+ rodex->open(sd, open_type, 0);
+ return;
+ }
+
+ msg_count = VECTOR_LENGTH(sd->rodex.messages);
+
+ if (last_mail_id > 0) {
+ // Find where the page starts
+ ARR_FIND(0, msg_count, page_start, VECTOR_INDEX(sd->rodex.messages, page_start).id == last_mail_id);
+ if (page_start > 0 && page_start < msg_count) {
+ --page_start; // Valid page, get first item of next page
+ } else {
+ page_start = msg_count - 1; // Should not happen, invalid lower_id given
+ }
+ clif->rodex_send_maillist(sd->fd, sd, open_type, page_start);
+ }
+}
+
+/// User's request to refresh his mail box
+/// @param sd : Who's requesting
+/// @param open_type : Box Type (See RODEX_OPENTYPE)
+/// @param first_mail_id : The first mail id known by client, currently unused
+static void rodex_refresh(struct map_session_data *sd, int8 open_type, int64 first_mail_id)
+{
+ nullpo_retv(sd);
+ if (open_type == RODEX_OPENTYPE_ACCOUNT && battle_config.feature_rodex_use_accountmail == false)
+ open_type = RODEX_OPENTYPE_MAIL;
+
+ // Some clients sends the first mail id it currently has and expects to receive
+ // a list of newer mails, other clients sends first mail id as 0 and expects
+ // to receive the first page (as if opening the box)
+ if (first_mail_id > 0) {
+ intif->rodex_requestinbox(sd->status.char_id, sd->status.account_id, 1, open_type, first_mail_id);
+ } else {
+ intif->rodex_requestinbox(sd->status.char_id, sd->status.account_id, 0, open_type, first_mail_id);
+ }
+}
+
+static void do_init_rodex(bool minimal)
+{
+ if (minimal)
+ return;
+}
+
+static void do_final_rodex(void)
+{
+
+}
+
+void rodex_defaults(void)
+{
+ rodex = &rodex_s;
+
+ rodex->init = do_init_rodex;
+ rodex->final = do_final_rodex;
+
+ rodex->open = rodex_open;
+ rodex->next_page = rodex_next_page;
+ rodex->refresh = rodex_refresh;
+ rodex->isenabled = rodex_isenabled;
+ rodex->add_item = rodex_add_item;
+ rodex->remove_item = rodex_remove_item;
+ rodex->check_player = rodex_check_player;
+ rodex->send_mail = rodex_send_mail;
+ rodex->send_mail_result = rodex_send_mail_result;
+ rodex->get_mail = rodex_get_mail;
+ rodex->read_mail = rodex_read_mail;
+ rodex->delete_mail = rodex_delete_mail;
+ rodex->get_zeny = rodex_get_zeny;
+ rodex->get_items = rodex_get_items;
+ rodex->clean = rodex_clean;
+ rodex->getZenyAck = rodex_getZenyAck;
+ rodex->getItemsAck = rodex_getItemsAck;
+}
diff --git a/src/map/rodex.h b/src/map/rodex.h
new file mode 100644
index 000000000..6a1621657
--- /dev/null
+++ b/src/map/rodex.h
@@ -0,0 +1,87 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2017-2020 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_RODEX_H
+#define MAP_RODEX_H
+
+#include "common/mmo.h"
+#include "common/hercules.h"
+
+#define RODEX_WEIGHT_LIMIT (2000 * 10)
+
+struct rodex_message;
+
+enum rodex_add_item {
+ RODEX_ADD_ITEM_SUCCESS = 0,
+ RODEX_ADD_ITEM_WEIGHT_ERROR = 1,
+ RODEX_ADD_ITEM_FATAL_ERROR = 2,
+ RODEX_ADD_ITEM_NO_SPACE = 3,
+ RODEX_ADD_ITEM_NOT_TRADEABLE = 4,
+};
+
+enum rodex_send_mail {
+ RODEX_SEND_MAIL_SUCCESS = 0,
+ RODEX_SEND_MAIL_FATAL_ERROR = 1,
+ RODEX_SEND_MAIL_COUNT_ERROR = 2,
+ RODEX_SEND_MAIL_ITEM_ERROR = 3,
+ RODEX_SEND_MAIL_RECEIVER_ERROR = 4
+};
+
+enum rodex_get_zeny {
+ RODEX_GET_ZENY_SUCCESS = 0,
+ RODEX_GET_ZENY_FATAL_ERROR = 1,
+ RODEX_GET_ZENY_LIMIT_ERROR = 2
+};
+
+enum rodex_get_items {
+ RODEX_GET_ITEMS_SUCCESS = 0,
+ RODEX_GET_ITEM_FATAL_ERROR = 1,
+ RODEX_GET_ITEM_FULL_ERROR = 2,
+};
+
+struct rodex_interface {
+ void (*init) (bool minimal);
+ void (*final) (void);
+
+ bool (*isenabled) (void);
+ void (*open) (struct map_session_data *sd, int8 open_type, int64 first_mail_id);
+ void (*next_page) (struct map_session_data *sd, int8 open_type, int64 last_mail_id);
+ void (*refresh) (struct map_session_data *sd, int8 open_type, int64 first_mail_id);
+ void (*add_item) (struct map_session_data *sd, int16 idx, int16 amount);
+ void (*remove_item) (struct map_session_data *sd, int16 idx, int16 amount);
+ void (*check_player) (struct map_session_data *sd, const char *name, int *base_level, int *char_id, int *class);
+ int (*send_mail) (struct map_session_data *sd, const char *receiver_name, const char *body, const char *title, int64 zeny);
+ void (*send_mail_result) (struct map_session_data *ssd, struct map_session_data *rsd, bool result);
+ struct rodex_message *(*get_mail) (struct map_session_data *sd, int64 mail_id);
+ void (*read_mail) (struct map_session_data *sd, int64 mail_id);
+ void (*get_zeny) (struct map_session_data *sd, int8 opentype, int64 mail_id);
+ void (*get_items) (struct map_session_data *sd, int8 opentype, int64 mail_id);
+ void (*delete_mail) (struct map_session_data *sd, int64 mail_id);
+ void (*clean) (struct map_session_data *sd, int8 flag);
+ void (*getZenyAck) (struct map_session_data *sd, int64 mail_id, int8 opentype, int64 zeny);
+ void (*getItemsAck) (struct map_session_data *sd, int64 mail_id, int8 opentype, int count, const struct rodex_item *items);
+};
+
+#ifdef HERCULES_CORE
+void rodex_defaults(void);
+#endif
+
+HPShared struct rodex_interface *rodex;
+
+#endif
diff --git a/src/map/script.c b/src/map/script.c
index 007c6e0e1..45c954dc0 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,9 @@
#include "map/channel.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
+#include "map/date.h"
#include "map/elemental.h"
#include "map/guild.h"
#include "map/homunculus.h"
@@ -41,6 +43,7 @@
#include "map/map.h"
#include "map/mapreg.h"
#include "map/mercenary.h"
+#include "map/messages.h"
#include "map/mob.h"
#include "map/npc.h"
#include "map/party.h"
@@ -49,11 +52,13 @@
#include "map/pet.h"
#include "map/pet.h"
#include "map/quest.h"
+#include "map/refine.h"
#include "map/skill.h"
#include "map/status.h"
#include "map/status.h"
#include "map/storage.h"
#include "map/unit.h"
+#include "map/achievement.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/db.h"
@@ -80,42 +85,28 @@
#include <sys/time.h>
#endif
-struct script_interface script_s;
+static struct script_interface script_s;
struct script_interface *script;
-static inline int GETVALUE(const unsigned char* buf, int i) {
- return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0));
-}
-static inline void SETVALUE(unsigned char* buf, int i, int n) {
- buf[i] = GetByte(n, 0);
- buf[i+1] = GetByte(n, 1);
- buf[i+2] = GetByte(n, 2);
-}
-
-static inline void script_string_buf_ensure(struct script_string_buf *buf, size_t ensure) {
- if( buf->pos+ensure >= buf->size ) {
- do {
- buf->size += 512;
- } while ( buf->pos+ensure >= buf->size );
- RECREATE(buf->ptr, char, buf->size);
- }
-}
-
-static inline void script_string_buf_addb(struct script_string_buf *buf,uint8 b) {
- if( buf->pos+1 >= buf->size ) {
- buf->size += 512;
- RECREATE(buf->ptr, char, buf->size);
- }
- buf->ptr[buf->pos++] = b;
+static inline int GETVALUE(const struct script_buf *buf, int i) __attribute__((nonnull (1)));
+static inline int GETVALUE(const struct script_buf *buf, int i)
+{
+ Assert_ret(VECTOR_LENGTH(*buf) > i + 2);
+ return (int)MakeDWord(MakeWord(VECTOR_INDEX(*buf, i), VECTOR_INDEX(*buf, i+1)),
+ MakeWord(VECTOR_INDEX(*buf, i+2), 0));
}
-static inline void script_string_buf_destroy(struct script_string_buf *buf) {
- if( buf->ptr )
- aFree(buf->ptr);
- memset(buf,0,sizeof(struct script_string_buf));
+static inline void SETVALUE(struct script_buf *buf, int i, int n) __attribute__((nonnull (1)));
+static inline void SETVALUE(struct script_buf *buf, int i, int n)
+{
+ Assert_retv(VECTOR_LENGTH(*buf) > i + 2);
+ VECTOR_INDEX(*buf, i) = GetByte(n, 0);
+ VECTOR_INDEX(*buf, i+1) = GetByte(n, 1);
+ VECTOR_INDEX(*buf, i+2) = GetByte(n, 2);
}
-const char* script_op2name(int op) {
+static const char *script_op2name(int op)
+{
#define RETURN_OP_NAME(type) case type: return #type
switch( op ) {
RETURN_OP_NAME(C_NOP);
@@ -151,6 +142,7 @@ const char* script_op2name(int op) {
RETURN_OP_NAME(C_ADD);
RETURN_OP_NAME(C_SUB);
RETURN_OP_NAME(C_MUL);
+ RETURN_OP_NAME(C_POW);
RETURN_OP_NAME(C_DIV);
RETURN_OP_NAME(C_MOD);
RETURN_OP_NAME(C_NEG);
@@ -173,9 +165,10 @@ const char* script_op2name(int op) {
}
#ifdef SCRIPT_DEBUG_DUMP_STACK
-static void script_dump_stack(struct script_state* st)
+static void script_dump_stack(struct script_state *st)
{
int i;
+ nullpo_retv(st);
ShowMessage("\tstart = %d\n", st->start);
ShowMessage("\tend = %d\n", st->end);
ShowMessage("\tdefsp = %d\n", st->stack->defsp);
@@ -215,9 +208,11 @@ static void script_dump_stack(struct script_state* st)
#endif
/// Reports on the console the src of a script error.
-void script_reportsrc(struct script_state *st) {
+static void script_reportsrc(struct script_state *st)
+{
struct block_list* bl;
+ nullpo_retv(st);
if( st->oid == 0 )
return; //Can't report source.
@@ -245,7 +240,7 @@ void script_reportsrc(struct script_state *st) {
}
/// Reports on the console information about the script data.
-void script_reportdata(struct script_data* data)
+static void script_reportdata(struct script_data *data)
{
if( data == NULL )
return;
@@ -287,7 +282,7 @@ void script_reportdata(struct script_data* data)
}
/// Reports on the console information about the current built-in function.
-void script_reportfunc(struct script_state* st)
+static void script_reportfunc(struct script_state *st)
{
int params, id;
struct script_data* data;
@@ -322,8 +317,9 @@ void script_reportfunc(struct script_state* st)
/*==========================================
* Output error message
*------------------------------------------*/
-static void disp_error_message2(const char *mes,const char *pos,int report) analyzer_noreturn;
-static void disp_error_message2(const char *mes,const char *pos,int report) {
+static void disp_error_message2(const char *mes, const char *pos, int report) __attribute__((nonnull (1))) analyzer_noreturn;
+static void disp_error_message2(const char *mes, const char *pos, int report)
+{
script->error_msg = aStrdup(mes);
script->error_pos = pos;
script->error_report = report;
@@ -331,12 +327,13 @@ static void disp_error_message2(const char *mes,const char *pos,int report) {
}
#define disp_error_message(mes,pos) (disp_error_message2((mes),(pos),1))
-void disp_warning_message(const char *mes, const char *pos) {
+static void disp_warning_message(const char *mes, const char *pos)
+{
script->warning(script->parser_current_src,script->parser_current_file,script->parser_current_line,mes,pos);
}
/// Checks event parameter validity
-void check_event(struct script_state *st, const char *evt)
+static void check_event(struct script_state *st, const char *evt)
{
if( evt && evt[0] && !stristr(evt, "::On") )
{
@@ -348,9 +345,11 @@ void check_event(struct script_state *st, const char *evt)
/*==========================================
* Hashes the input string
*------------------------------------------*/
-unsigned int calc_hash(const char* p) {
+static unsigned int calc_hash(const char *p)
+{
unsigned int h;
+ nullpo_ret(p);
#if defined(SCRIPT_HASH_DJB2)
h = 5381;
while( *p ) // hash*33 + c
@@ -382,10 +381,12 @@ unsigned int calc_hash(const char* p) {
/*==========================================
* Hashes the input string in a case insensitive way
*------------------------------------------*/
-unsigned int calc_hash_ci(const char* p) {
+static unsigned int calc_hash_ci(const char *p)
+{
unsigned int h = 0;
#ifdef ENABLE_CASE_CHECK
+ nullpo_ret(p);
#if defined(SCRIPT_HASH_DJB2)
h = 5381;
while( *p ) // hash*33 + c
@@ -420,14 +421,14 @@ unsigned int calc_hash_ci(const char* p) {
*------------------------------------------*/
/// Looks up string using the provided id.
-const char* script_get_str(int id)
+static const char *script_get_str(int id)
{
Assert_retr(NULL, id >= LABEL_START && id < script->str_size);
return script->str_buf+script->str_data[id].str;
}
/// Returns the uid of the string, or -1.
-int script_search_str(const char* p)
+static int script_search_str(const char *p)
{
int i;
@@ -440,8 +441,10 @@ int script_search_str(const char* p)
return -1;
}
-void script_casecheck_clear_sub(struct casecheck_data *ccd) {
+static void script_casecheck_clear_sub(struct casecheck_data *ccd)
+{
#ifdef ENABLE_CASE_CHECK
+ nullpo_retv(ccd);
if (ccd->str_data) {
aFree(ccd->str_data);
ccd->str_data = NULL;
@@ -458,19 +461,22 @@ void script_casecheck_clear_sub(struct casecheck_data *ccd) {
#endif // ENABLE_CASE_CHECK
}
-void script_global_casecheck_clear(void) {
+static void script_global_casecheck_clear(void)
+{
script_casecheck_clear_sub(&script->global_casecheck);
}
-void script_local_casecheck_clear(void) {
+static void script_local_casecheck_clear(void)
+{
script_casecheck_clear_sub(&script->local_casecheck);
}
-const char *script_casecheck_add_str_sub(struct casecheck_data *ccd, const char *p)
+static const char *script_casecheck_add_str_sub(struct casecheck_data *ccd, const char *p)
{
#ifdef ENABLE_CASE_CHECK
int len;
int h = script->calc_hash_ci(p);
+ nullpo_retr(NULL, ccd);
if (ccd->str_hash[h] == 0) {
//empty bucket, add new node here
ccd->str_hash[h] = ccd->str_num;
@@ -522,17 +528,19 @@ const char *script_casecheck_add_str_sub(struct casecheck_data *ccd, const char
return NULL;
}
-const char *script_global_casecheck_add_str(const char *p) {
+static const char *script_global_casecheck_add_str(const char *p)
+{
return script_casecheck_add_str_sub(&script->global_casecheck, p);
}
-const char *script_local_casecheck_add_str(const char *p) {
+static const char *script_local_casecheck_add_str(const char *p)
+{
return script_casecheck_add_str_sub(&script->local_casecheck, p);
}
/// Stores a copy of the string and returns its id.
/// If an identical string is already present, returns its id instead.
-int script_add_str(const char* p)
+static int script_add_str(const char *p)
{
int len, h = script->calc_hash(p);
#ifdef ENABLE_CASE_CHECK
@@ -606,22 +614,39 @@ int script_add_str(const char* p)
return script->str_num++;
}
-/// Appends 1 byte to the script buffer.
-void add_scriptb(int a)
+static int script_add_variable(const char *varname)
{
- if( script->pos+1 >= script->size )
- {
- script->size += SCRIPT_BLOCK_SIZE;
- RECREATE(script->buf,unsigned char,script->size);
+ int key = script->search_str(varname);
+
+ if (key < 0) {
+ key = script->add_str(varname);
+ script->str_data[key].type = C_NAME;
}
- script->buf[script->pos++] = (uint8)(a);
+
+ return key;
}
-/// Appends a c_op value to the script buffer.
-/// The value is variable-length encoded into 8-bit blocks.
-/// The encoding scheme is ( 01?????? )* 00??????, LSB first.
-/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
-void add_scriptc(int a)
+/**
+ * Appends 1 byte to the script buffer.
+ *
+ * @param a The byte to append.
+ */
+static void add_scriptb(int a)
+{
+ VECTOR_ENSURE(script->buf, 1, SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSH(script->buf, (uint8)a);
+}
+
+/**
+ * Appends a c_op value to the script buffer.
+ *
+ * The value is variable-length encoded into 8-bit blocks.
+ * The encoding scheme is ( 01?????? )* 00??????, LSB first.
+ * All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+ *
+ * @param a The value to append.
+ */
+static void add_scriptc(int a)
{
while( a >= 0x40 )
{
@@ -632,11 +657,16 @@ void add_scriptc(int a)
script->addb(a);
}
-/// Appends an integer value to the script buffer.
-/// The value is variable-length encoded into 8-bit blocks.
-/// The encoding scheme is ( 11?????? )* 10??????, LSB first.
-/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
-void add_scripti(int a)
+/**
+ * Appends an integer value to the script buffer.
+ *
+ * The value is variable-length encoded into 8-bit blocks.
+ * The encoding scheme is ( 11?????? )* 10??????, LSB first.
+ * All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+ *
+ * @param a The value to append.
+ */
+static void add_scripti(int a)
{
while( a >= 0x40 )
{
@@ -646,12 +676,12 @@ void add_scripti(int a)
script->addb(a|0x80);
}
-/// Appends a script->str_data object (label/function/variable/integer) to the script buffer.
-
-///
-/// @param l The id of the script->str_data entry
-// Maximum up to 16M
-void add_scriptl(int l)
+/**
+ * Appends a script->str_data object (label/function/variable/integer) to the script buffer.
+ *
+ * @param l The id of the script->str_data entry (Maximum up to 16M)
+ */
+static void add_scriptl(int l)
{
int backpatch = script->str_data[l].backpatch;
@@ -667,7 +697,7 @@ void add_scriptl(int l)
case C_USERFUNC:
// Embedded data backpatch there is a possibility of label
script->addc(C_NAME);
- script->str_data[l].backpatch = script->pos;
+ script->str_data[l].backpatch = VECTOR_LENGTH(script->buf);
script->addb(backpatch);
script->addb(backpatch>>8);
script->addb(backpatch>>16);
@@ -689,7 +719,7 @@ void add_scriptl(int l)
/*==========================================
* Resolve the label
*------------------------------------------*/
-void set_label(int l,int pos, const char* script_pos)
+static void set_label(int l, int pos, const char *script_pos)
{
int i;
@@ -705,15 +735,15 @@ void set_label(int l,int pos, const char* script_pos)
script->str_data[l].type=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
script->str_data[l].label=pos;
for (i = script->str_data[l].backpatch; i >= 0 && i != 0x00ffffff; ) {
- int next = GETVALUE(script->buf,i);
- script->buf[i-1]=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
- SETVALUE(script->buf,i,pos);
+ int next = GETVALUE(&script->buf, i);
+ VECTOR_INDEX(script->buf, i-1) = (script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
+ SETVALUE(&script->buf, i, pos);
i = next;
}
}
/// Skips spaces and/or comments.
-const char* script_skip_space(const char* p)
+static const char *script_skip_space(const char *p)
{
if( p == NULL )
return NULL;
@@ -752,7 +782,9 @@ const char* script_skip_space(const char* p)
/// Skips a word.
/// A word consists of undercores and/or alphanumeric characters,
/// and valid variable prefixes/postfixes.
-const char* skip_word(const char* p) {
+static const char *skip_word(const char *p)
+{
+ nullpo_retr(NULL, p);
// prefix
switch( *p ) {
case '@':// temporary char variable
@@ -767,7 +799,7 @@ const char* skip_word(const char* p) {
p += ( p[1] == '@' ? 2 : 1 ); break;
}
- while( ISALNUM(*p) || *p == '_' || *p == '\'' )
+ while (ISALNUM(*p) || *p == '_')
++p;
// postfix
@@ -779,10 +811,12 @@ const char* skip_word(const char* p) {
/// Adds a word to script->str_data.
/// @see skip_word
/// @see script->add_str
-int add_word(const char* p) {
+static int add_word(const char *p)
+{
size_t len;
int i;
+ nullpo_retr(0, p);
// Check for a word
len = script->skip_word(p) - p;
if( len == 0 )
@@ -804,33 +838,32 @@ int add_word(const char* p) {
/// Parses a function call.
/// The argument list can have parenthesis or not.
/// The number of arguments is checked.
-static
-const char* parse_callfunc(const char* p, int require_paren, int is_custom)
+static const char *parse_callfunc(const char *p, int require_paren, int is_custom)
{
const char *p2;
char *arg = NULL;
char null_arg = '\0';
int func;
- bool nested_call = false, macro = false;
+ bool macro = false;
+ nullpo_retr(NULL, p);
// is need add check for arg null pointer below?
func = script->add_word(p);
- if( script->str_data[func].type == C_FUNC ) {
- /** only when unset (-1), valid values are >= 0 **/
- if( script->syntax.last_func == -1 )
- script->syntax.last_func = script->str_data[func].val;
- else { //Nested function call
- script->syntax.nested_call++;
- nested_call = true;
-
- if( script->str_data[func].val == script->buildin_lang_macro_offset ) {
+ if (script->str_data[func].type == C_FUNC) {
+ script->syntax.nested_call++;
+ if (script->syntax.last_func != -1) {
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
script->syntax.lang_macro_active = true;
macro = true;
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
+ script->syntax.lang_macro_fmtstring_active = true;
+ macro = true;
}
}
if( !macro ) {
// buildin function
+ script->syntax.last_func = script->str_data[func].val;
script->addl(func);
script->addc(C_ARG);
}
@@ -919,30 +952,29 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
disp_error_message("parse_callfunc: expected ')' to close argument list",p);
++p;
- if( script->str_data[func].val == script->buildin_lang_macro_offset )
+ if (script->str_data[func].val == script->buildin_lang_macro_offset)
script->syntax.lang_macro_active = false;
+ else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset)
+ script->syntax.lang_macro_fmtstring_active = false;
}
- if( nested_call )
- script->syntax.nested_call--;
-
- if( !script->syntax.nested_call )
- script->syntax.last_func = -1;
-
- if( !macro )
+ if (!macro) {
+ if (0 == --script->syntax.nested_call)
+ script->syntax.last_func = -1;
script->addc(C_FUNC);
+ }
return p;
}
/// Processes end of logical script line.
/// @param first When true, only fix up scheduling data is initialized
/// @param p Script position for error reporting in set_label
-void parse_nextline(bool first, const char* p)
+static void parse_nextline(bool first, const char *p)
{
if( !first )
{
script->addc(C_EOL); // mark end of line for stack cleanup
- script->set_label(LABEL_NEXTLINE, script->pos, p); // fix up '-' labels
+ script->set_label(LABEL_NEXTLINE, VECTOR_LENGTH(script->buf), p); // fix up '-' labels
}
// initialize data for new '-' label fix up scheduling
@@ -955,7 +987,7 @@ void parse_nextline(bool first, const char* p)
* Pushes a variable into stack, processing its array index if needed.
* @see parse_variable
*/
-void parse_variable_sub_push(int word, const char *p2)
+static void parse_variable_sub_push(int word, const char *p2)
{
if( p2 ) {
const char* p3 = NULL;
@@ -986,13 +1018,14 @@ void parse_variable_sub_push(int word, const char *p2)
/// Parse a variable assignment using the direct equals operator
/// @param p script position where the function should run from
/// @return NULL if not a variable assignment, the new position otherwise
-const char* parse_variable(const char* p)
+static const char *parse_variable(const char *p)
{
int word;
c_op type = C_NOP;
const char *p2 = NULL;
const char *var = p;
+ nullpo_retr(NULL, p);
if( ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PRE, true) ) // pre ++
|| ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PRE, true) ) // pre --
) {
@@ -1030,6 +1063,7 @@ const char* parse_variable(const char* p)
|| ( p[0] == '|' && p[1] == '=' && (type = C_OR, true) ) // |=
|| ( p[0] == '&' && p[1] == '=' && (type = C_AND, true) ) // &=
|| ( p[0] == '*' && p[1] == '=' && (type = C_MUL, true) ) // *=
+ || ( p[0] == '*' && p[1] == '*' && p[2] == '=' && (type = C_POW, true) ) // **=
|| ( p[0] == '/' && p[1] == '=' && (type = C_DIV, true) ) // /=
|| ( p[0] == '%' && p[1] == '=' && (type = C_MOD, true) ) // %=
|| ( p[0] == '+' && p[1] == '+' && (type = C_ADD_POST, true) ) // post ++
@@ -1053,6 +1087,7 @@ const char* parse_variable(const char* p)
case C_L_SHIFT: // <<=
case C_R_SHIFT: // >>=
+ case C_POW: // **=
p = script->skip_space( &p[3] );
break;
@@ -1066,6 +1101,8 @@ const char* parse_variable(const char* p)
}
// push the set function onto the stack
+ script->syntax.nested_call++;
+ script->syntax.last_func = script->str_data[script->buildin_set_ref].val;
script->addl(script->buildin_set_ref);
script->addc(C_ARG);
@@ -1117,6 +1154,8 @@ const char* parse_variable(const char* p)
// close the script by appending the function operator
script->addc(C_FUNC);
+ if (--script->syntax.nested_call == 0)
+ script->syntax.last_func = -1;
// push the buffer from the method
return p;
@@ -1135,7 +1174,8 @@ const char* parse_variable(const char* p)
* @param p Pointer to the string to check
* @return Whether the string is a number literal
*/
-bool is_number(const char *p) {
+static bool is_number(const char *p)
+{
const char *np;
if (!p)
return false;
@@ -1159,13 +1199,22 @@ bool is_number(const char *p) {
}
/**
+ * Duplicates a script string into the script string list.
*
- **/
-int script_string_dup(char *str) {
- size_t len = strlen(str);
+ * Grows the script string list as needed.
+ *
+ * @param str The string to insert.
+ * @return the string position in the script string list.
+ */
+static int script_string_dup(char *str)
+{
+ int len;
int pos = script->string_list_pos;
- while( pos+len+1 >= script->string_list_size ) {
+ nullpo_retr(pos, str);
+ len = (int)strlen(str);
+
+ while (pos+len+1 >= script->string_list_size) {
script->string_list_size += (1024*1024)/2;
RECREATE(script->string_list,char,script->string_list_size);
}
@@ -1179,240 +1228,214 @@ int script_string_dup(char *str) {
/*==========================================
* Analysis section
*------------------------------------------*/
-const char* parse_simpleexpr(const char *p)
+static const char *parse_simpleexpr(const char *p)
{
p=script->skip_space(p);
- if(*p==';' || *p==',')
+ nullpo_retr(NULL, p);
+ if (*p == ';' || *p == ',')
disp_error_message("parse_simpleexpr: unexpected end of expression",p);
- if(*p=='(') {
- int i = script->syntax.curly_count-1;
- if (i >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST)
- ++script->syntax.curly[i].count;
- p=script->parse_subexpr(p+1,-1);
- p=script->skip_space(p);
- if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST
- && script->syntax.curly[i].flag == ARGLIST_UNDEFINED && --script->syntax.curly[i].count == 0
- ) {
- if( *p == ',' ) {
- script->syntax.curly[i].flag = ARGLIST_PAREN;
- return p;
- } else {
- script->syntax.curly[i].flag = ARGLIST_NO_PAREN;
- }
- }
- if( *p != ')' )
- disp_error_message("parse_simpleexpr: unmatched ')'",p);
- ++p;
- } else if(is_number(p)) {
- char *np;
- long long lli;
- while(*p == '0' && ISDIGIT(p[1])) p++; // Skip leading zeros, we don't support octal literals
- lli=strtoll(p,&np,0);
- if( lli < INT_MIN ) {
- lli = INT_MIN;
- script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN",p);
- } else if( lli > INT_MAX ) {
- lli = INT_MAX;
- script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX",p);
- }
- script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
- p=np;
- } else if(*p=='"') {
- struct string_translation *st = NULL;
- const char *start_point = p;
- bool duplicate = true;
- struct script_string_buf *sbuf = &script->parse_simpleexpr_str;
-
- do {
- p++;
- while( *p && *p != '"' ) {
- if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) {
- char buf[8];
- size_t len = sv->skip_escaped_c(p) - p;
- size_t n = sv->unescape_c(buf, p, len);
- if( n != 1 )
- ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
- p += len;
- script_string_buf_addb(sbuf, *buf);
- continue;
- } else if( *p == '\n' ) {
- disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
- }
- script_string_buf_addb(sbuf, *p++);
- }
- if(!*p)
- disp_error_message("parse_simpleexpr: unexpected end of file @ string",p);
- p++; //'"'
- p = script->skip_space(p);
- } while( *p && *p == '"' );
-
- script_string_buf_addb(sbuf, 0);
-
- if (!(script->syntax.translation_db && (st = strdb_get(script->syntax.translation_db, sbuf->ptr)) != NULL)) {
- script->addc(C_STR);
-
- if( script->pos+sbuf->pos >= script->size ) {
- do {
- script->size += SCRIPT_BLOCK_SIZE;
- } while( script->pos+sbuf->pos >= script->size );
- RECREATE(script->buf,unsigned char,script->size);
- }
+ if (*p == '(') {
+ return script->parse_simpleexpr_paren(p);
+ } else if (is_number(p)) {
+ return script->parse_simpleexpr_number(p);
+ } else if(*p == '"') {
+ return script->parse_simpleexpr_string(p);
+ } else {
+ return script->parse_simpleexpr_name(p);
+ }
+}
- memcpy(script->buf+script->pos, sbuf->ptr, sbuf->pos);
- script->pos += sbuf->pos;
+static const char *parse_simpleexpr_paren(const char *p)
+{
+ int i = script->syntax.curly_count - 1;
+ nullpo_retr(NULL, p);
+ if (i >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST)
+ ++script->syntax.curly[i].count;
+ p = script->parse_subexpr(p + 1, -1);
+ p = script->skip_space(p);
+ if ((i = script->syntax.curly_count - 1) >= 0
+ && script->syntax.curly[i].type == TYPE_ARGLIST
+ && script->syntax.curly[i].flag == ARGLIST_UNDEFINED
+ && --script->syntax.curly[i].count == 0
+ ) {
+ if (*p == ',') {
+ script->syntax.curly[i].flag = ARGLIST_PAREN;
+ return p;
} else {
- int expand = sizeof(int) + sizeof(uint8);
- unsigned char j;
- unsigned int st_cursor = 0;
+ script->syntax.curly[i].flag = ARGLIST_NO_PAREN;
+ }
+ }
+ if (*p != ')')
+ disp_error_message("parse_simpleexpr: unmatched ')'", p);
- script->addc(C_LSTR);
+ return p + 1;
+}
- expand += (sizeof(char*) + sizeof(uint8)) * st->translations;
+static const char *parse_simpleexpr_number(const char *p)
+{
+ char *np = NULL;
+ long long lli;
- while( script->pos+expand >= script->size ) {
- script->size += SCRIPT_BLOCK_SIZE;
- RECREATE(script->buf,unsigned char,script->size);
- }
+ nullpo_retr(NULL, p);
+ while (*p == '0' && ISDIGIT(p[1]))
+ p++; // Skip leading zeros, we don't support octal literals
- *((int *)(&script->buf[script->pos])) = st->string_id;
- *((uint8 *)(&script->buf[script->pos + sizeof(int)])) = st->translations;
+ lli = strtoll(p, &np, 0);
+ if (lli < INT_MIN) {
+ lli = INT_MIN;
+ script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN", p);
+ } else if (lli > INT_MAX) {
+ lli = INT_MAX;
+ script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX", p);
+ }
+ script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
- script->pos += sizeof(int) + sizeof(uint8);
+ return np;
+}
- for(j = 0; j < st->translations; j++) {
- *((uint8 *)(&script->buf[script->pos])) = RBUFB(st->buf, st_cursor);
- *((char **)(&script->buf[script->pos+sizeof(uint8)])) = &st->buf[st_cursor + sizeof(uint8)];
- script->pos += sizeof(char*) + sizeof(uint8);
- st_cursor += sizeof(uint8);
- while(st->buf[st_cursor++]);
- st_cursor += sizeof(uint8);
- }
- }
+static const char *parse_simpleexpr_string(const char *p)
+{
+ const char *start_point = p;
- /* When exporting we don't know what is a translation and what isn't */
- if( script->lang_export_fp && sbuf->pos > 1 ) {//sbuf->pos will always be at least 1 because of the '\0'
- if( !script->syntax.strings ) {
- script->syntax.strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0);
+ nullpo_retr(NULL, p);
+ do {
+ p++;
+ while (*p != '\0' && *p != '"') {
+ if ((unsigned char)p[-1] <= 0x7e && *p == '\\') {
+ char buf[8];
+ size_t len = sv->skip_escaped_c(p) - p;
+ size_t n = sv->unescape_c(buf, p, len);
+ if (n != 1)
+ ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
+ p += len;
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, buf[0]);
+ continue;
}
-
- if( !strdb_exists(script->syntax.strings,sbuf->ptr) ) {
- strdb_put(script->syntax.strings, sbuf->ptr, NULL);
- duplicate = false;
+ if (*p == '\n') {
+ disp_error_message("parse_simpleexpr: unexpected newline @ string", p);
}
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, *p++);
}
+ if (*p == '\0')
+ disp_error_message("parse_simpleexpr: unexpected end of file @ string", p);
+ p++; //'"'
+ p = script->skip_space(p);
+ } while (*p != '\0' && *p == '"');
- if( script->lang_export_fp && !duplicate &&
- ( ( ( script->syntax.last_func == script->buildin_mes_offset ||
- script->syntax.last_func == script->buildin_select_offset ) && !script->syntax.nested_call
- ) || script->syntax.lang_macro_active ) ) {
- const char *line_start = start_point;
- const char *line_end = start_point;
- struct script_string_buf *lbuf = &script->lang_export_line_buf;
- struct script_string_buf *ubuf = &script->lang_export_unescaped_buf;
- size_t line_length, cursor;
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, '\0');
- while( line_start > script->parser_current_src ) {
- if( *line_start != '\n' )
- line_start--;
- else
- break;
- }
+ script->add_translatable_string(&script->parse_simpleexpr_strbuf, start_point);
- while( *line_end != '\n' && *line_end != '\0' )
- line_end++;
+ VECTOR_TRUNCATE(script->parse_simpleexpr_strbuf);
- line_length = (size_t)(line_end - line_start);
- if( line_length > 0 ) {
- script_string_buf_ensure(lbuf,line_length + 1);
+ return p;
+}
- memcpy(lbuf->ptr, line_start, line_length);
- lbuf->pos = line_length;
- script_string_buf_addb(lbuf, 0);
+static const char *parse_simpleexpr_name(const char *p)
+{
+ int l;
+ const char *pv = NULL;
- normalize_name(lbuf->ptr, "\r\n\t ");
- }
+ // label , register , function etc
+ if (script->skip_word(p) == p)
+ disp_error_message("parse_simpleexpr: unexpected character", p);
- for(cursor = 0; cursor < sbuf->pos; cursor++) {
- if( sbuf->ptr[cursor] == '"' )
- script_string_buf_addb(ubuf, '\\');
- script_string_buf_addb(ubuf, sbuf->ptr[cursor]);
- }
- script_string_buf_addb(ubuf, 0);
-
- fprintf(script->lang_export_fp, "#: %s\n"
- "# %s\n"
- "msgctxt \"%s\"\n"
- "msgid \"%s\"\n"
- "msgstr \"\"\n",
- script->parser_current_file ? script->parser_current_file : "Unknown File",
- lbuf->ptr,
- script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC",
- ubuf->ptr
- );
- lbuf->pos = 0;
- ubuf->pos = 0;
+ l = script->add_word(p);
+ if (script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) {
+ return script->parse_callfunc(p,1,0);
+#ifdef SCRIPT_CALLFUNC_CHECK
+ } else {
+ const char *name = script->get_str(l);
+ if (strdb_get(script->userfunc_db,name) != NULL) {
+ return script->parse_callfunc(p, 1, 1);
}
- sbuf->pos = 0;
+#endif
+ }
+
+ if ((pv = script->parse_variable(p)) != NULL) {
+ // successfully processed a variable assignment
+ return pv;
+ }
+
+ if (script->str_data[l].type == C_INT && script->str_data[l].deprecated) {
+ disp_warning_message("This constant is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", p);
+ }
+
+ p = script->skip_word(p);
+ if (*p == '[') {
+ // array(name[i] => getelementofarray(name,i) )
+ script->addl(script->buildin_getelementofarray_ref);
+ script->addc(C_ARG);
+ script->addl(l);
+
+ p = script->parse_subexpr(p + 1, -1);
+ p = script->skip_space(p);
+ if (*p != ']')
+ disp_error_message("parse_simpleexpr: unmatched ']'", p);
+ ++p;
+ script->addc(C_FUNC);
+ } else if (script->str_data[l].type == C_INT) {
+ script->addc(C_NAME);
+ script->addb(l);
+ script->addb(l >> 8);
+ script->addb(l >> 16);
} else {
- int l;
- const char* pv;
+ script->addl(l);
+ }
- // label , register , function etc
- if(script->skip_word(p)==p)
- disp_error_message("parse_simpleexpr: unexpected character",p);
+ return p;
+}
- l=script->add_word(p);
- if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) {
- return script->parse_callfunc(p,1,0);
-#ifdef SCRIPT_CALLFUNC_CHECK
- } else {
- const char* name = script->get_str(l);
- if( strdb_get(script->userfunc_db,name) != NULL ) {
- return script->parse_callfunc(p,1,1);
- }
-#endif
- }
+static void script_add_translatable_string(const struct script_string_buf *string, const char *start_point)
+{
+ struct string_translation *st = NULL;
- if( (pv = script->parse_variable(p)) ) {
- // successfully processed a variable assignment
- return pv;
- }
+ nullpo_retv(string);
+ if (script->syntax.translation_db == NULL
+ || (st = strdb_get(script->syntax.translation_db, VECTOR_DATA(*string))) == NULL) {
+ script->addc(C_STR);
- if (script->str_data[l].type == C_INT && script->str_data[l].deprecated) {
- disp_warning_message("This constant is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", p);
- }
+ VECTOR_ENSURE(script->buf, VECTOR_LENGTH(*string), SCRIPT_BLOCK_SIZE);
- p=script->skip_word(p);
- if( *p == '[' ) {
- // array(name[i] => getelementofarray(name,i) )
- script->addl(script->buildin_getelementofarray_ref);
- script->addc(C_ARG);
- script->addl(l);
+ VECTOR_PUSHARRAY(script->buf, VECTOR_DATA(*string), VECTOR_LENGTH(*string));
+ } else {
+ unsigned char u;
+ int st_cursor = 0;
- p=script->parse_subexpr(p+1,-1);
- p=script->skip_space(p);
- if( *p != ']' )
- disp_error_message("parse_simpleexpr: unmatched ']'",p);
- ++p;
- script->addc(C_FUNC);
- } else {
- script->addl(l);
- }
+ script->addc(C_LSTR);
- }
+ VECTOR_ENSURE(script->buf, (int)(sizeof(st->string_id) + sizeof(st->translations)), SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSHARRAY(script->buf, (void *)&st->string_id, sizeof(st->string_id));
+ VECTOR_PUSHARRAY(script->buf, (void *)&st->translations, sizeof(st->translations));
- return p;
+ for (u = 0; u != st->translations; u++) {
+ struct string_translation_entry *entry = (void *)(st->buf+st_cursor);
+ char *stringptr = &entry->string[0];
+ st_cursor += sizeof(*entry);
+ VECTOR_ENSURE(script->buf, (int)(sizeof(entry->lang_id) + sizeof(char *)), SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSHARRAY(script->buf, (void *)&entry->lang_id, sizeof(entry->lang_id));
+ VECTOR_PUSHARRAY(script->buf, (void *)&stringptr, sizeof(stringptr));
+ st_cursor += sizeof(uint8); // FIXME: What are we skipping here?
+ while (st->buf[st_cursor++] != 0)
+ (void)0; // Skip string
+ st_cursor += sizeof(uint8); // FIXME: What are we skipping here?
+ }
+ }
}
/*==========================================
* Analysis of the expression
*------------------------------------------*/
-const char* script_parse_subexpr(const char* p,int limit)
+static const char *script_parse_subexpr(const char *p, int limit)
{
int op,opl,len;
+ nullpo_retr(NULL, p);
p=script->skip_space(p);
if( *p == '-' ) {
@@ -1435,8 +1458,9 @@ const char* script_parse_subexpr(const char* p,int limit)
p=script->skip_space(p);
while((
(op=C_OP3, opl=0, len=1,*p=='?') // ?:
- || (op=C_ADD, opl=9, len=1,*p=='+') // +
- || (op=C_SUB, opl=9, len=1,*p=='-') // -
+ || (op=C_ADD, opl=9, len=1,*p=='+' && p[1]!='+') // +
+ || (op=C_SUB, opl=9, len=1,*p=='-' && p[1]!='-') // -
+ || (op=C_POW, opl=11,len=2,*p=='*' && p[1]=='*') // **
|| (op=C_MUL, opl=10,len=1,*p=='*') // *
|| (op=C_DIV, opl=10,len=1,*p=='/') // /
|| (op=C_MOD, opl=10,len=1,*p=='%') // %
@@ -1476,8 +1500,9 @@ const char* script_parse_subexpr(const char* p,int limit)
/*==========================================
* Evaluation of the expression
*------------------------------------------*/
-const char* parse_expr(const char *p)
+static const char *parse_expr(const char *p)
{
+ nullpo_retr(NULL, p);
switch(*p) {
case ')': case ';': case ':': case '[': case ']':
case '}':
@@ -1490,10 +1515,11 @@ const char* parse_expr(const char *p)
/*==========================================
* Analysis of the line
*------------------------------------------*/
-const char* parse_line(const char* p)
+static const char *parse_line(const char *p)
{
const char* p2;
+ nullpo_retr(NULL, p);
p=script->skip_space(p);
if(*p==';') {
//Close decision for if(); for(); while();
@@ -1552,8 +1578,9 @@ const char* parse_line(const char* p)
}
// { ... } Closing process
-const char* parse_curly_close(const char* p)
+static const char *parse_curly_close(const char *p)
{
+ nullpo_retr(NULL, p);
if(script->syntax.curly_count <= 0) {
disp_error_message("parse_curly_close: unexpected string",p);
return p + 1;
@@ -1582,7 +1609,7 @@ const char* parse_curly_close(const char* p)
// You are here labeled
sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if(script->syntax.curly[pos].flag) {
//Exists default
@@ -1595,7 +1622,7 @@ const char* parse_curly_close(const char* p)
// Label end
sprintf(label,"__SW%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
linkdb_final(&script->syntax.curly[pos].case_label); // free the list of case label
script->syntax.curly_count--;
//Closing decision if, for , while
@@ -1610,10 +1637,11 @@ const char* parse_curly_close(const char* p)
// Syntax-related processing
// break, case, continue, default, do, for, function,
// if, switch, while ? will handle this internally.
-const char* parse_syntax(const char* p)
+static const char *parse_syntax(const char *p)
{
const char *p2 = script->skip_word(p);
+ nullpo_retr(NULL, p);
switch(*p) {
case 'B':
case 'b':
@@ -1674,7 +1702,7 @@ const char* parse_syntax(const char* p)
// You are here labeled
sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
//Decision statement switch
p = script->skip_space(p2);
@@ -1714,7 +1742,7 @@ const char* parse_syntax(const char* p)
// Label after the completion of FALLTHRU
sprintf(label, "__SW%x_%xJ", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
// check duplication of case label [Rayce]
if(linkdb_search(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v)) != NULL)
@@ -1781,7 +1809,7 @@ const char* parse_syntax(const char* p)
}
sprintf(label, "__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Skip to the next link w/o condition
sprintf(label, "goto __SW%x_%x;", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count + 1);
@@ -1792,7 +1820,7 @@ const char* parse_syntax(const char* p)
// The default label
sprintf(label, "__SW%x_DEF", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly[script->syntax.curly_count - 1].flag = 1;
script->syntax.curly[pos].count++;
@@ -1810,7 +1838,7 @@ const char* parse_syntax(const char* p)
// Label of the (do) form here
sprintf(label, "__DO%x_BGN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count++;
return p;
}
@@ -1841,7 +1869,7 @@ const char* parse_syntax(const char* p)
// Form the start of label decision
sprintf(label, "__FR%x_J", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
p=script->skip_space(p);
if(*p == ';') {
@@ -1870,7 +1898,7 @@ const char* parse_syntax(const char* p)
// Labels to form the next loop
sprintf(label, "__FR%x_NXT", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Process the next time you enter the loop
// A ')' last for; flag to be treated as'
@@ -1889,7 +1917,7 @@ const char* parse_syntax(const char* p)
// Loop start labeling
sprintf(label, "__FR%x_BGN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
return p;
} else if( p2 - p == 8 && strncmp(p, "function", 8) == 0 ) {
// internal script function
@@ -1939,9 +1967,9 @@ const char* parse_syntax(const char* p)
if( script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
{
script->str_data[l].type = C_USERFUNC;
- script->set_label(l, script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(l,script->pos);
+ script->label_add(l, VECTOR_LENGTH(script->buf));
}
else
disp_error_message("parse_syntax:function: function name is invalid", func_name);
@@ -2021,7 +2049,7 @@ const char* parse_syntax(const char* p)
// Form the start of label decision
sprintf(label, "__WL%x_NXT", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Skip to the end point if the condition is false
sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
@@ -2039,10 +2067,12 @@ const char* parse_syntax(const char* p)
return NULL;
}
-const char* parse_syntax_close(const char *p) {
+static const char *parse_syntax_close(const char *p)
+{
// If (...) for (...) hoge (); as to make sure closed closed once again
int flag;
+ nullpo_retr(NULL, p);
do {
p = script->parse_syntax_close_sub(p,&flag);
} while(flag);
@@ -2052,7 +2082,7 @@ const char* parse_syntax_close(const char *p) {
// Close judgment if, for, while, of do
// flag == 1 : closed
// flag == 0 : not closed
-const char* parse_syntax_close_sub(const char* p,int* flag)
+static const char *parse_syntax_close_sub(const char *p, int *flag)
{
char label[256];
int pos = script->syntax.curly_count - 1;
@@ -2078,7 +2108,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the location
sprintf(label, "__IF%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly[pos].count++;
p = script->skip_space(p);
@@ -2116,7 +2146,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the final location
sprintf(label, "__IF%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if(script->syntax.curly[pos].flag == 1) {
// Because the position of the pointer is the same if not else for this
return bp;
@@ -2129,7 +2159,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// (Come here continue) to form the label here
sprintf(label, "__DO%x_NXT", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
// Skip to the end point if the condition is false
@@ -2164,7 +2194,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Form label of the end point conditions
sprintf(label, "__DO%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
p = script->skip_space(p);
if(*p != ';') {
disp_error_message("parse_syntax: need ';'",p);
@@ -2186,7 +2216,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// End for labeling
sprintf(label, "__FR%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else if(script->syntax.curly[pos].type == TYPE_WHILE) {
@@ -2202,7 +2232,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// End while labeling
sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else if(script->syntax.curly[pos].type == TYPE_USERFUNC) {
@@ -2215,7 +2245,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the location
sprintf(label, "__FN%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else {
@@ -2225,10 +2255,11 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
}
/// Retrieves the value of a constant.
-bool script_get_constant(const char* name, int* value)
+static bool script_get_constant(const char *name, int *value)
{
int n = script->search_str(name);
+ nullpo_retr(false, value);
if( n == -1 || script->str_data[n].type != C_INT )
{// not found or not a constant
return false;
@@ -2242,11 +2273,11 @@ bool script_get_constant(const char* name, int* value)
}
/// Creates new constant or parameter with given value.
-void script_set_constant(const char *name, int value, bool is_parameter, bool is_deprecated)
+static void script_set_constant(const char *name, int value, bool is_parameter, bool is_deprecated)
{
int n = script->add_str(name);
- if( script->str_data[n].type == C_NOP ) {// new
+ if (script->str_data[n].type == C_NOP) {
script->str_data[n].type = is_parameter ? C_PARAM : C_INT;
script->str_data[n].val = value;
script->str_data[n].deprecated = is_deprecated ? 1 : 0;
@@ -2257,7 +2288,7 @@ void script_set_constant(const char *name, int value, bool is_parameter, bool is
}
}
/* adds data to a existent constant in the database, inserted normally via parse */
-void script_set_constant2(const char *name, int value, bool is_parameter, bool is_deprecated)
+static void script_set_constant2(const char *name, int value, bool is_parameter, bool is_deprecated)
{
int n = script->add_str(name);
@@ -2290,7 +2321,7 @@ void script_set_constant2(const char *name, int value, bool is_parameter, bool i
/**
* Loads the constants database from constants.conf
*/
-void read_constdb(void)
+static void read_constdb(bool reload)
{
struct config_t constants_conf;
char filepath[256];
@@ -2298,7 +2329,7 @@ void read_constdb(void)
struct config_setting_t *t;
int i = 0;
- sprintf(filepath, "%s/constants.conf", map->db_path);
+ safesnprintf(filepath, 256, "%s/constants.conf", map->db_path);
if (!libconfig->load_file(&constants_conf, filepath))
return;
@@ -2309,7 +2340,6 @@ void read_constdb(void)
}
while ((t = libconfig->setting_get_elem(cdb, i++))) {
- bool is_parameter = false;
bool is_deprecated = false;
int value = 0;
const char *name = config_setting_name(t);
@@ -2340,10 +2370,6 @@ void read_constdb(void)
continue;
}
value = i32;
- if (libconfig->setting_lookup_bool(t, "Parameter", &i32)) {
- if (i32 != 0)
- is_parameter = true;
- }
if (libconfig->setting_lookup_bool(t, "Deprecated", &i32)) {
if (i32 != 0)
is_deprecated = true;
@@ -2351,9 +2377,13 @@ void read_constdb(void)
} else {
value = libconfig->setting_get_int(t);
}
- if (is_parameter)
- ShowWarning("read_constdb: Defining parameters in the constants configuration is deprecated and will no longer be possible in a future version. Parameters should be defined in source. (parameter = '%s')\n", name);
- script->set_constant(name, value, is_parameter, is_deprecated);
+
+ if (reload) {
+ int n = script->add_str(name);
+ script->str_data[n].type = C_NOP; // ensures it will be overwritten
+ }
+
+ script->set_constant(name, value, false, is_deprecated);
}
script->constdb_comment(NULL);
libconfig->destroy(&constants_conf);
@@ -2366,12 +2396,12 @@ void read_constdb(void)
*
* @param comment The comment to set (NULL to unset)
*/
-void script_constdb_comment(const char *comment)
+static void script_constdb_comment(const char *comment)
{
(void)comment;
}
-void script_load_parameters(void)
+static void script_load_parameters(void)
{
int i = 0;
struct {
@@ -2391,6 +2421,7 @@ void script_load_parameters(void)
{"SkillPoint", SP_SKILLPOINT},
{"Class", SP_CLASS},
{"Zeny", SP_ZENY},
+ {"BankVault", SP_BANKVAULT},
{"Sex", SP_SEX},
{"NextBaseExp", SP_NEXTBASEEXP},
{"NextJobExp", SP_NEXTJOBEXP},
@@ -2425,7 +2456,7 @@ void script_load_parameters(void)
/*==========================================
* Display emplacement line of script
*------------------------------------------*/
-const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line)
+static const char *script_print_line(StringBuf *buf, const char *p, const char *mark, int line)
{
int i, mark_pos = 0, tabstop = TAB_SIZE;
if( p == NULL || !p[0] ) return NULL;
@@ -2464,7 +2495,8 @@ const char* script_print_line(StringBuf* buf, const char* p, const char* mark, i
#undef update_tabstop
#define CONTEXTLINES 3
-void script_errorwarning_sub(StringBuf *buf, const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
+static void script_errorwarning_sub(StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos)
+{
// Find the line where the error occurred
int j;
int line = start_line;
@@ -2500,7 +2532,8 @@ void script_errorwarning_sub(StringBuf *buf, const char* src, const char* file,
}
#undef CONTEXTLINES
-void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
+static void script_error(const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos)
+{
StringBuf buf;
StrBuf->Init(&buf);
@@ -2512,7 +2545,8 @@ void script_error(const char* src, const char* file, int start_line, const char*
StrBuf->Destroy(&buf);
}
-void script_warning(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
+static void script_warning(const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos)
+{
StringBuf buf;
StrBuf->Init(&buf);
@@ -2526,7 +2560,8 @@ 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, int *retval) {
+static 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;
@@ -2544,9 +2579,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->parse_cleanup_timer_id = timer->add(timer->gettick() + 10, script->parse_cleanup_timer, 0, 0);
}
- if( script->syntax.strings ) /* used only when generating translation file */
- db_destroy(script->syntax.strings);
-
memset(&script->syntax,0,sizeof(script->syntax));
script->syntax.last_func = -1;/* as valid values are >= 0 */
if( script->parser_current_npc_name ) {
@@ -2556,11 +2588,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->syntax.translation_db = strdb_get(script->translation_db, script->parser_current_npc_name);
}
- if( !script->buf ) {
- script->buf = (unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
- script->size = SCRIPT_BLOCK_SIZE;
- }
- script->pos=0;
+ VECTOR_TRUNCATE(script->buf);
script->parse_nextline(true, NULL);
// who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
@@ -2574,7 +2602,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
if( script->error_report )
script->error(src,file,line,script->error_msg,script->error_pos);
aFree( script->error_msg );
- script->pos = 0;
+ VECTOR_TRUNCATE(script->buf);
for(i=LABEL_START;i<script->str_num;i++)
if(script->str_data[i].type == C_NOP) script->str_data[i].type = C_NAME;
for(i=0; i<size; i++)
@@ -2594,9 +2622,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
p=script->skip_space(p);
if( options&SCRIPT_IGNORE_EXTERNAL_BRACKETS )
{// does not require brackets around the script
- if( *p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
- {// empty script and can return NULL
- script->pos = 0;
+ if (*p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) {
+ // empty script and can return NULL
+ VECTOR_TRUNCATE(script->buf);
#ifdef ENABLE_CASE_CHECK
script->local_casecheck.clear();
script->parser_current_src = NULL;
@@ -2614,9 +2642,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
if (retval) *retval = EXIT_FAILURE;
}
p = script->skip_space(p+1);
- if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
- {// empty script and can return NULL
- script->pos = 0;
+ if (*p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) {
+ // empty script and can return NULL
+ VECTOR_TRUNCATE(script->buf);
#ifdef ENABLE_CASE_CHECK
script->local_casecheck.clear();
script->parser_current_src = NULL;
@@ -2648,9 +2676,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
tmpp=script->skip_space(script->skip_word(p));
if(*tmpp==':' && !(strncmp(p,"default:",8) == 0 && p + 7 == tmpp)) {
i=script->add_word(p);
- script->set_label(i,script->pos,p);
+ script->set_label(i, VECTOR_LENGTH(script->buf), p);
if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(i,script->pos);
+ script->label_add(i, VECTOR_LENGTH(script->buf));
p=tmpp+1;
p=script->skip_space(p);
continue;
@@ -2672,8 +2700,8 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->str_data[i].type=C_NAME;
script->str_data[i].label=i;
for (j = script->str_data[i].backpatch; j >= 0 && j != 0x00ffffff; ) {
- int next = GETVALUE(script->buf,j);
- SETVALUE(script->buf,j,i);
+ int next = GETVALUE(&script->buf, j);
+ SETVALUE(&script->buf, j, i);
j = next;
}
} else if(script->str_data[i].type == C_USERFUNC) {
@@ -2690,37 +2718,39 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
}
#ifdef SCRIPT_DEBUG_DISP
- for(i=0;i<script->pos;i++) {
- if((i&15)==0) ShowMessage("%04x : ",i);
- ShowMessage("%02x ",script->buf[i]);
- if((i&15)==15) ShowMessage("\n");
+ for (i = 0; i < VECTOR_LENGTH(script->buf); i++) {
+ if ((i&15) == 0)
+ ShowMessage("%04x : ",i);
+ ShowMessage("%02x ", VECTOR_INDEX(script->buf, i));
+ if ((i&15) == 15)
+ ShowMessage("\n");
}
ShowMessage("\n");
#endif
#ifdef SCRIPT_DEBUG_DISASM
i = 0;
- while(i < script->pos) {
- int j = i;
- c_op op = script->get_com(script->buf,&i);
+ while (i < VECTOR_LENGTH(script->buf)) {
+ c_op op = script->get_com(&script->buf, &i);
+ int j = i; // Note: i is modified in the line above.
ShowMessage("%06x %s", i, script->op2name(op));
- j = i;
- switch(op) {
+
+ switch (op) {
case C_INT:
- ShowMessage(" %d", script->get_num(script->buf,&i));
+ ShowMessage(" %d", script->get_num(&script->buf, &i));
break;
case C_POS:
- ShowMessage(" 0x%06x", *(int*)(script->buf+i)&0xffffff);
+ ShowMessage(" 0x%06x", *(int*)(&VECTOR_INDEX(script->buf, i))&0xffffff);
i += 3;
break;
case C_NAME:
- j = (*(int*)(script->buf+i)&0xffffff);
+ j = (*(int*)(&VECTOR_INDEX(script->buf, i))&0xffffff);
ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : script->get_str(j));
i += 3;
break;
case C_STR:
- j = (int)strlen((char*)script->buf + i);
- ShowMessage(" %s", script->buf + i);
+ j = (int)strlen((char*)&VECTOR_INDEX(script->buf, i));
+ ShowMessage(" %s", &VECTOR_INDEX(script->buf, i));
i += j+1;
break;
}
@@ -2729,9 +2759,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
#endif
CREATE(code,struct script_code,1);
- code->script_buf = (unsigned char *)aMalloc(script->pos*sizeof(unsigned char));
- memcpy(code->script_buf, script->buf, script->pos);
- code->script_size = script->pos;
+ VECTOR_INIT(code->script_buf);
+ VECTOR_ENSURE(code->script_buf, VECTOR_LENGTH(script->buf), 1);
+ VECTOR_PUSHARRAY(code->script_buf, VECTOR_DATA(script->buf), VECTOR_LENGTH(script->buf));
code->local.vars = NULL;
code->local.arrays = NULL;
#ifdef ENABLE_CASE_CHECK
@@ -2745,9 +2775,10 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
/// Returns the player attached to this script, identified by the rid.
/// If there is no player attached, the script is terminated.
-struct map_session_data *script_rid2sd(struct script_state *st)
+static struct map_session_data *script_rid2sd(struct script_state *st)
{
struct map_session_data *sd;
+ nullpo_retr(NULL, st);
if( !( sd = map->id2sd(st->rid) ) ) {
ShowError("script_rid2sd: fatal error ! player not attached!\n");
script->reportfunc(st);
@@ -2757,7 +2788,7 @@ struct map_session_data *script_rid2sd(struct script_state *st)
return sd;
}
-struct map_session_data *script_id2sd(struct script_state *st, int account_id)
+static struct map_session_data *script_id2sd(struct script_state *st, int account_id)
{
struct map_session_data *sd;
if ((sd = map->id2sd(account_id)) == NULL) {
@@ -2768,7 +2799,7 @@ struct map_session_data *script_id2sd(struct script_state *st, int account_id)
return sd;
}
-struct map_session_data *script_charid2sd(struct script_state *st, int char_id)
+static struct map_session_data *script_charid2sd(struct script_state *st, int char_id)
{
struct map_session_data *sd;
if ((sd = map->charid2sd(char_id)) == NULL) {
@@ -2779,10 +2810,10 @@ struct map_session_data *script_charid2sd(struct script_state *st, int char_id)
return sd;
}
-struct map_session_data *script_nick2sd(struct script_state *st, const char *name)
+static struct map_session_data *script_nick2sd(struct script_state *st, const char *name)
{
struct map_session_data *sd;
- if ((sd = map->nick2sd(name)) == NULL) {
+ if ((sd = map->nick2sd(name, false)) == NULL) {
ShowWarning("script_nick2sd: Player name '%s' not found!\n", name);
script->reportfunc(st);
script->reportsrc(st);
@@ -2790,14 +2821,26 @@ struct map_session_data *script_nick2sd(struct script_state *st, const char *nam
return sd;
}
-char *get_val_npcscope_str(struct script_state* st, struct reg_db *n, struct script_data* data) {
+static char *get_val_npcscope_str(struct script_state *st, struct reg_db *n, struct script_data *data)
+{
if (n)
return (char*)i64db_get(n->vars, reference_getuid(data));
else
return NULL;
}
-char *get_val_instance_str(struct script_state* st, const char* name, struct script_data* data) {
+static char *get_val_pc_ref_str(struct script_state *st, struct reg_db *n, struct script_data *data)
+{
+ struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, n);
+
+ p = i64db_get(n->vars, reference_getuid(data));
+ return p ? p->value : NULL;
+}
+
+static char *get_val_instance_str(struct script_state *st, const char *name, struct script_data *data)
+{
+ nullpo_retr(NULL, st);
if (st->instance_id >= 0) {
return (char*)i64db_get(instance->list[st->instance_id].regs.vars, reference_getuid(data));
} else {
@@ -2806,14 +2849,25 @@ char *get_val_instance_str(struct script_state* st, const char* name, struct scr
}
}
-int get_val_npcscope_num(struct script_state* st, struct reg_db *n, struct script_data* data) {
+static int get_val_npcscope_num(struct script_state *st, struct reg_db *n, struct script_data *data)
+{
if (n)
return (int)i64db_iget(n->vars, reference_getuid(data));
else
return 0;
}
-int get_val_instance_num(struct script_state* st, const char* name, struct script_data* data) {
+static int get_val_pc_ref_num(struct script_state *st, struct reg_db *n, struct script_data *data)
+{
+ struct script_reg_num *p = NULL;
+ nullpo_retr(0, n);
+
+ p = i64db_get(n->vars, reference_getuid(data));
+ return p ? p->value : 0;
+}
+
+static int get_val_instance_num(struct script_state *st, const char *name, struct script_data *data)
+{
if (st->instance_id >= 0)
return (int)i64db_iget(instance->list[st->instance_id].regs.vars, reference_getuid(data));
else {
@@ -2829,13 +2883,14 @@ int get_val_instance_num(struct script_state* st, const char* name, struct scrip
* @param data[in,out] variable/constant.
* @return pointer to data, for convenience.
*/
-struct script_data *get_val(struct script_state* st, struct script_data* data) {
+static struct script_data *get_val(struct script_state *st, struct script_data *data)
+{
const char* name;
char prefix;
char postfix;
struct map_session_data *sd = NULL;
- if( !data_isreference(data) )
+ if (!data_isreference(data))
return data;// not a variable/constant
name = reference_getname(data);
@@ -2849,11 +2904,10 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
return data;
}
- //##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS]
- if( !reference_toconstant(data) && not_server_variable(prefix) ) {
+ if (((reference_tovariable(data) && not_server_variable(prefix)) || reference_toparam(data)) && reference_getref(data) == NULL) {
sd = script->rid2sd(st);
- if( sd == NULL ) {// needs player attached
- if( postfix == '$' ) {// string variable
+ if (sd == NULL) {// needs player attached
+ if (postfix == '$') {// string variable
ShowWarning("script_get_val: cannot access player variable '%s', defaulting to \"\"\n", name);
data->type = C_CONSTSTR;
data->u.str = "";
@@ -2871,32 +2925,44 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
const char *str = NULL;
switch (prefix) {
- case '@':
+ case '@':
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else {
str = pc->readregstr(sd, data->u.num);
- break;
- case '$':
- str = mapreg->readregstr(data->u.num);
- break;
- case '#':
- if (name[1] == '#')
- str = pc_readaccountreg2str(sd, data->u.num);// global
- else
- str = pc_readaccountregstr(sd, data->u.num);// local
- break;
- case '.':
- if (data->ref)
- str = script->get_val_ref_str(st, data->ref, data);
- else if (name[1] == '@')
- str = script->get_val_scope_str(st, &st->stack->scope, data);
- else
- str = script->get_val_npc_str(st, &st->script->local, data);
- break;
- case '\'':
- str = script->get_val_instance_str(st, name, data);
- break;
- default:
+ }
+ break;
+ case '$':
+ str = mapreg->readregstr(data->u.num);
+ break;
+ case '#':
+ if (data->ref) {
+ str = script->get_val_pc_ref_str(st, data->ref, data);
+ } else if (name[1] == '#') {
+ str = pc_readaccountreg2str(sd, data->u.num);// global
+ } else {
+ str = pc_readaccountregstr(sd, data->u.num);// local
+ }
+ break;
+ case '.':
+ if (data->ref) {
+ str = script->get_val_ref_str(st, data->ref, data);
+ } else if (name[1] == '@') {
+ str = script->get_val_scope_str(st, &st->stack->scope, data);
+ } else {
+ str = script->get_val_npc_str(st, &st->script->local, data);
+ }
+ break;
+ case '\'':
+ str = script->get_val_instance_str(st, name, data);
+ break;
+ default:
+ if (data->ref) {
+ str = script->get_val_pc_ref_str(st, data->ref, data);
+ } else {
str = pc_readglobalreg_str(sd, data->u.num);
- break;
+ }
+ break;
}
if (str == NULL || str[0] == '\0') {
@@ -2916,36 +2982,48 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
data->u.num = reference_getconstant(data);
} else if( reference_toparam(data) ) {
data->u.num = pc->readparam(sd, reference_getparamtype(data));
- } else
- switch( prefix ) {
- case '@':
+ } else {
+ switch (prefix) {
+ case '@':
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else {
data->u.num = pc->readreg(sd, data->u.num);
- break;
- case '$':
- data->u.num = mapreg->readreg(data->u.num);
- break;
- case '#':
- if( name[1] == '#' )
- data->u.num = pc_readaccountreg2(sd, data->u.num);// global
- else
- data->u.num = pc_readaccountreg(sd, data->u.num);// local
- break;
- case '.':
- if (data->ref)
- data->u.num = script->get_val_ref_num(st, data->ref, data);
- else if (name[1] == '@')
- data->u.num = script->get_val_scope_num(st, &st->stack->scope, data);
- else
- data->u.num = script->get_val_npc_num(st, &st->script->local, data);
- break;
- case '\'':
- data->u.num = script->get_val_instance_num(st, name, data);
- break;
- default:
+ }
+ break;
+ case '$':
+ data->u.num = mapreg->readreg(data->u.num);
+ break;
+ case '#':
+ if (data->ref) {
+ data->u.num = script->get_val_pc_ref_num(st, data->ref, data);
+ } else if (name[1] == '#') {
+ data->u.num = pc_readaccountreg2(sd, data->u.num);// global
+ } else {
+ data->u.num = pc_readaccountreg(sd, data->u.num);// local
+ }
+ break;
+ case '.':
+ if (data->ref) {
+ data->u.num = script->get_val_ref_num(st, data->ref, data);
+ } else if (name[1] == '@') {
+ data->u.num = script->get_val_scope_num(st, &st->stack->scope, data);
+ } else {
+ data->u.num = script->get_val_npc_num(st, &st->script->local, data);
+ }
+ break;
+ case '\'':
+ data->u.num = script->get_val_instance_num(st, name, data);
+ break;
+ default:
+ if (data->ref) {
+ data->u.num = script->get_val_pc_ref_num(st, data->ref, data);
+ } else {
data->u.num = pc_readglobalreg(sd, data->u.num);
- break;
+ }
+ break;
}
-
+ }
}
data->ref = NULL;
@@ -2962,14 +3040,19 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
* @param ref[in] the container to look up the reference into.
* @return the retrieved value of the reference.
*/
-const void *get_val2(struct script_state *st, int64 uid, struct reg_db *ref)
+static const void *get_val2(struct script_state *st, int64 uid, struct reg_db *ref)
{
struct script_data* data;
+ nullpo_retr(NULL, st);
script->push_val(st->stack, C_NAME, uid, ref);
data = script_getdatatop(st, -1);
script->get_val(st, data);
if (data->type == C_INT) // u.num is int32 because it comes from script->get_val
return (const void *)h64BPTRSIZE((int32)data->u.num);
+ else if (data_isreference(data) && reference_toconstant(data))
+ return (const void *)h64BPTRSIZE((int32)reference_getconstant(data));
+ else if (data_isreference(data) && reference_toparam(data))
+ return (const void *)h64BPTRSIZE((int32)reference_getparamtype(data));
else
return (const void *)h64BPTRSIZE(data->u.str);
}
@@ -2977,16 +3060,21 @@ const void *get_val2(struct script_state *st, int64 uid, struct reg_db *ref)
* Because, currently, array members with key 0 are indifferenciable from normal variables, we should ensure its actually in
* Will be gone as soon as undefined var feature is implemented
**/
-void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref) {
+static void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref)
+{
const char *name = script->get_str(script_getvarid(uid));
- // is here st can be null pointer and st->rid is wrong?
- struct reg_db *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref);
+ struct reg_db *src = NULL;
bool insert = false;
- if (sd && !st) {
- /* when sd comes, st isn't available */
+ if (st == NULL) {
+ // Special case with no st available, only sd
+ nullpo_retv(sd);
+ src = script->array_src(NULL, sd, name, ref);
insert = true;
} else {
+ if (sd == NULL && st->rid != 0)
+ sd = map->id2sd(st->rid); // Retrieve the missing sd
+ src = script->array_src(st, sd, name, ref);
if( is_string_variable(name) ) {
const char *str = script->get_val2(st, uid, ref);
if (str != NULL && *str != '\0')
@@ -3020,7 +3108,8 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data *
/**
* Returns array size by ID
**/
-unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+static unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref)
+{
struct script_array *sa = NULL;
struct reg_db *src = script->array_src(st, sd, name, ref);
@@ -3032,7 +3121,8 @@ unsigned int script_array_size(struct script_state *st, struct map_session_data
/**
* Returns array's highest key (for that awful getarraysize implementation that doesn't really gets the array size)
**/
-unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+static unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref)
+{
struct script_array *sa = NULL;
struct reg_db *src = script->array_src(st, sd, name, ref);
@@ -3053,7 +3143,7 @@ unsigned int script_array_highest_key(struct script_state *st, struct map_sessio
}
return 0;
}
-int script_free_array_db(union DBKey key, struct DBData *data, va_list ap)
+static int script_free_array_db(union DBKey key, struct DBData *data, va_list ap)
{
struct script_array *sa = DB->data2ptr(data);
aFree(sa->members);
@@ -3063,7 +3153,10 @@ int script_free_array_db(union DBKey key, struct DBData *data, va_list ap)
/**
* Clears script_array and removes it from script->array_db
**/
-void script_array_delete(struct reg_db *src, struct script_array *sa) {
+static void script_array_delete(struct reg_db *src, struct script_array *sa)
+{
+ nullpo_retv(src);
+ nullpo_retv(sa);
aFree(sa->members);
idb_remove(src->arrays, sa->id);
ers_free(script->array_ers, sa);
@@ -3073,9 +3166,11 @@ void script_array_delete(struct reg_db *src, struct script_array *sa) {
*
* @param idx the index of the member in script_array struct list, not of the actual array member
**/
-void script_array_remove_member(struct reg_db *src, struct script_array *sa, unsigned int idx) {
+static void script_array_remove_member(struct reg_db *src, struct script_array *sa, unsigned int idx)
+{
unsigned int i, cursor;
+ nullpo_retv(sa);
/* its the only member left, no need to do anything other than delete the array data */
if( sa->size == 1 ) {
script->array_delete(src,sa);
@@ -3099,44 +3194,56 @@ void script_array_remove_member(struct reg_db *src, struct script_array *sa, uns
*
* @param idx the index of the array member being inserted
**/
-void script_array_add_member(struct script_array *sa, unsigned int idx) {
+static void script_array_add_member(struct script_array *sa, unsigned int idx)
+{
+ nullpo_retv(sa);
RECREATE(sa->members, unsigned int, ++sa->size);
-
sa->members[sa->size - 1] = idx;
}
/**
* Obtains the source of the array database for this type and scenario
* 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) {
+static 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;
+ nullpo_retr(NULL, name);
- switch( name[0] ) {
+ switch (name[0]) {
/* from player */
- default: /* char reg */
- case '@':/* temp char reg */
- case '#':/* account reg */
+ default: /* char reg */
+ case '@':/* temp char reg */
+ case '#':/* account reg */
+ if (ref != NULL) {
+ src = ref;
+ } else {
+ nullpo_retr(NULL, sd);
src = &sd->regs;
- break;
- case '$':/* map reg */
- src = &mapreg->regs;
- break;
- case '.':/* npc/script */
- if( ref )
- src = ref;
- else
- src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
- break;
- case '\'':/* instance */
- if( st->instance_id >= 0 ) {
- src = &instance->list[st->instance_id].regs;
- }
- break;
+ }
+ break;
+ case '$':/* map reg */
+ src = &mapreg->regs;
+ break;
+ case '.':/* npc/script */
+ if (ref != NULL) {
+ src = ref;
+ } else {
+ nullpo_retr(NULL, st);
+ src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
+ }
+ break;
+ case '\'':/* instance */
+ nullpo_retr(NULL, st);
+ if (st->instance_id >= 0) {
+ src = &instance->list[st->instance_id].regs;
+ }
+ break;
}
- if( src ) {
- if( !src->arrays )
+ if (src) {
+ if (!src->arrays) {
src->arrays = idb_alloc(DB_OPT_BASE);
+ }
return src;
}
return NULL;
@@ -3149,11 +3256,13 @@ struct reg_db *script_array_src(struct script_state *st, struct map_session_data
* @param num[in] Variable ID
* @param empty[in] Whether the modified member is empty (needs to be removed)
**/
-void script_array_update(struct reg_db *src, int64 num, bool empty) {
+static void script_array_update(struct reg_db *src, int64 num, bool empty)
+{
struct script_array *sa = NULL;
int id = script_getvarid(num);
unsigned int index = script_getvaridx(num);
+ nullpo_retv(src);
if (!src->arrays) {
src->arrays = idb_alloc(DB_OPT_BASE);
} else {
@@ -3189,10 +3298,11 @@ void script_array_update(struct reg_db *src, int64 num, bool empty) {
}
}
-void set_reg_npcscope_str(struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str)
+static void set_reg_npcscope_str(struct script_state *st, struct reg_db *n, int64 num, const char *name, const char *str)
{
if (n)
{
+ nullpo_retv(str);
if (str[0]) {
i64db_put(n->vars, num, aStrdup(str));
if (script_getvaridx(num))
@@ -3205,7 +3315,33 @@ void set_reg_npcscope_str(struct script_state* st, struct reg_db *n, int64 num,
}
}
-void set_reg_npcscope_num(struct script_state* st, struct reg_db *n, int64 num, const char* name, int val)
+static void set_reg_pc_ref_str(struct script_state *st, struct reg_db *n, int64 num, const char *name, const char *str)
+{
+ struct DBIterator *iter = db_iterator(map->pc_db);
+
+ for (struct map_session_data *sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) {
+ if (sd != NULL && n == &sd->regs) {
+ pc->setregistry_str(sd, num, str);
+ break;
+ }
+ }
+ dbi_destroy(iter);
+}
+
+static void set_reg_pc_ref_num(struct script_state *st, struct reg_db *n, int64 num, const char *name, int val)
+{
+ struct DBIterator *iter = db_iterator(map->pc_db);
+
+ for (struct map_session_data *sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) {
+ if (sd != NULL && n == &sd->regs) {
+ pc->setregistry(sd, num, val);
+ break;
+ }
+ }
+ dbi_destroy(iter);
+}
+
+static void set_reg_npcscope_num(struct script_state *st, struct reg_db *n, int64 num, const char *name, int val)
{
if (n) {
if (val != 0) {
@@ -3220,8 +3356,9 @@ void set_reg_npcscope_num(struct script_state* st, struct reg_db *n, int64 num,
}
}
-void set_reg_instance_str(struct script_state* st, int64 num, const char* name, const char *str)
+static void set_reg_instance_str(struct script_state *st, int64 num, const char *name, const char *str)
{
+ nullpo_retv(st);
if (st->instance_id >= 0) {
if (str[0]) {
i64db_put(instance->list[st->instance_id].regs.vars, num, aStrdup(str));
@@ -3238,8 +3375,9 @@ void set_reg_instance_str(struct script_state* st, int64 num, const char* name,
}
}
-void set_reg_instance_num(struct script_state* st, int64 num, const char* name, int val)
+static void set_reg_instance_num(struct script_state *st, int64 num, const char *name, int val)
{
+ nullpo_retv(st);
if (st->instance_id >= 0) {
if (val != 0) {
i64db_iput(instance->list[st->instance_id].regs.vars, num, val);
@@ -3270,59 +3408,93 @@ void set_reg_instance_num(struct script_state* st, int64 num, const char* name,
*
* TODO: return values are screwed up, have been for some time (reaad: years), e.g. some functions return 1 failure and success.
*------------------------------------------*/
-int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref)
+static int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref)
{
- char prefix = name[0];
+ char prefix;
+ nullpo_ret(name);
+ prefix = name[0];
+
+ if (script->str_data[script_getvarid(num)].type != C_NAME && script->str_data[script_getvarid(num)].type != C_PARAM) {
+ ShowError("script:set_reg: not a variable! '%s'\n", name);
+
+ // to avoid this don't do script->add_str(") without setting its type.
+ // either use script->add_variable() or manually set the type
+
+ if (st) {
+ script->reportsrc(st);
+ st->state = END;
+ }
+ return 0;
+ }
if (strlen(name) > SCRIPT_VARNAME_LENGTH) {
ShowError("script:set_reg: variable name too long. '%s'\n", name);
- script->reportsrc(st);
- st->state = END;
+ if (st) {
+ script->reportsrc(st);
+ st->state = END;
+ }
return 0;
}
- if( is_string_variable(name) ) {// string variable
+ if (is_string_variable(name)) {// string variable
const char *str = (const char*)value;
switch (prefix) {
- case '@':
+ case '@':
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else {
pc->setregstr(sd, num, str);
- return 1;
- case '$':
- return mapreg->setregstr(num, str);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2str(sd, num, str) :
- pc_setaccountregstr(sd, num, str);
- case '.':
- if (ref)
- script->set_reg_ref_str(st, ref, num, name, str);
- else if (name[1] == '@')
- script->set_reg_scope_str(st, &st->stack->scope, num, name, str);
- else
- script->set_reg_npc_str(st, &st->script->local, num, name, str);
- return 1;
- case '\'':
- set_reg_instance_str(st, num, name, str);
- return 1;
- default:
- return pc_setglobalreg_str(sd, num, str);
+ }
+ return 1;
+ case '$':
+ mapreg->setregstr(num, str);
+ return 1;
+ case '#':
+ if (ref) {
+ script->set_reg_pc_ref_str(st, ref, num, name, str);
+ } else if (name[1] == '#') {
+ pc_setaccountreg2str(sd, num, str);
+ } else {
+ pc_setaccountregstr(sd, num, str);
+ }
+ return 1;
+ case '.':
+ if (ref) {
+ script->set_reg_ref_str(st, ref, num, name, str);
+ } else if (name[1] == '@') {
+ script->set_reg_scope_str(st, &st->stack->scope, num, name, str);
+ } else {
+ script->set_reg_npc_str(st, &st->script->local, num, name, str);
+ }
+ return 1;
+ case '\'':
+ set_reg_instance_str(st, num, name, str);
+ return 1;
+ default:
+ if (ref) {
+ script->set_reg_pc_ref_str(st, ref, num, name, str);
+ } else {
+ pc_setglobalreg_str(sd, num, str);
+ }
+ return 1;
}
} else {// integer variable
// 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 ) {
+ 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);
// 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 )
+ if(st->state == CLOSE) {
clif->scriptclose(sd, st->oid);
+ }
}
return 0;
}
@@ -3330,44 +3502,74 @@ int set_reg(struct script_state *st, struct map_session_data *sd, int64 num, con
}
switch (prefix) {
- case '@':
+ case '@':
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else {
pc->setreg(sd, num, val);
- return 1;
- case '$':
- return mapreg->setreg(num, val);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2(sd, num, val) :
- pc_setaccountreg(sd, num, val);
- case '.':
- if (ref)
- script->set_reg_ref_num(st, ref, num, name, val);
- else if (name[1] == '@')
- script->set_reg_scope_num(st, &st->stack->scope, num, name, val);
- else
- script->set_reg_npc_num(st, &st->script->local, num, name, val);
- return 1;
- case '\'':
- set_reg_instance_num(st, num, name, val);
- return 1;
- default:
- return pc_setglobalreg(sd, num, val);
+ }
+ return 1;
+ case '$':
+ mapreg->setreg(num, val);
+ return 1;
+ case '#':
+ if (ref) {
+ script->set_reg_pc_ref_num(st, ref, num, name, val);
+ } else if (name[1] == '#') {
+ pc_setaccountreg2(sd, num, val);
+ } else {
+ pc_setaccountreg(sd, num, val);
+ }
+ return 1;
+ case '.':
+ if (ref) {
+ script->set_reg_ref_num(st, ref, num, name, val);
+ } else if (name[1] == '@') {
+ script->set_reg_scope_num(st, &st->stack->scope, num, name, val);
+ } else {
+ script->set_reg_npc_num(st, &st->script->local, num, name, val);
+ }
+ return 1;
+ case '\'':
+ set_reg_instance_num(st, num, name, val);
+ return 1;
+ default:
+ if (ref) {
+ script->set_reg_pc_ref_num(st, ref, num, name, val);
+ } else {
+ pc_setglobalreg(sd, num, val);
+ }
+ return 1;
}
}
}
-int set_var(struct map_session_data *sd, char *name, void *val)
+static int set_var(struct map_session_data *sd, char *name, void *val)
{
- return script->set_reg(NULL, sd, reference_uid(script->add_str(name),0), name, val, NULL);
+ int key = script->add_variable(name);
+
+ if (script->str_data[key].type != C_NAME) {
+ ShowError("script:setd_sub: `%s` is already used by something that is not a variable.\n", name);
+ return -1;
+ }
+
+ return script->set_reg(NULL, sd, reference_uid(key, 0), name, val, NULL);
}
-void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, const void *value, struct reg_db *ref)
+static void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, const void *value, struct reg_db *ref)
{
- script->set_reg(st, sd, reference_uid(script->add_str(varname),elem), varname, value, ref);
+ int key = script->add_variable(varname);
+
+ if (script->str_data[key].type != C_NAME) {
+ ShowError("script:setd_sub: `%s` is already used by something that is not a variable.\n", varname);
+ return;
+ }
+
+ script->set_reg(st, sd, reference_uid(key, elem), varname, value, ref);
}
/// Converts the data to a string
-const char *conv_str(struct script_state *st, struct script_data* data)
+static const char *conv_str(struct script_state *st, struct script_data *data)
{
script->get_val(st, data);
if (data_isstring(data)) {
@@ -3401,7 +3603,7 @@ const char *conv_str(struct script_state *st, struct script_data* data)
}
/// Converts the data to an int
-int conv_num(struct script_state *st, struct script_data *data)
+static int conv_num(struct script_state *st, struct script_data *data)
{
long num;
@@ -3459,7 +3661,9 @@ int conv_num(struct script_state *st, struct script_data *data)
//
/// Increases the size of the stack
-void stack_expand(struct script_stack* stack) {
+static void stack_expand(struct script_stack *stack)
+{
+ nullpo_retv(stack);
stack->sp_max += 64;
stack->stack_data = (struct script_data*)aRealloc(stack->stack_data,
stack->sp_max * sizeof(stack->stack_data[0]) );
@@ -3468,7 +3672,9 @@ void stack_expand(struct script_stack* stack) {
}
/// Pushes a value into the stack (with reference)
-struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref) {
+static struct script_data *push_val(struct script_stack *stack, enum c_op type, int64 val, struct reg_db *ref)
+{
+ nullpo_retr(NULL, stack);
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = type;
@@ -3479,8 +3685,9 @@ struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 v
}
/// Pushes a string into the stack
-struct script_data *push_str(struct script_stack *stack, char *str)
+static struct script_data *push_str(struct script_stack *stack, char *str)
{
+ nullpo_retr(NULL, stack);
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = C_STR;
@@ -3491,8 +3698,9 @@ struct script_data *push_str(struct script_stack *stack, char *str)
}
/// Pushes a constant string into the stack
-struct script_data *push_conststr(struct script_stack *stack, const char *str)
+static struct script_data *push_conststr(struct script_stack *stack, const char *str)
{
+ nullpo_retr(NULL, stack);
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = C_CONSTSTR;
@@ -3503,7 +3711,9 @@ struct script_data *push_conststr(struct script_stack *stack, const char *str)
}
/// Pushes a retinfo into the stack
-struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, struct reg_db *ref) {
+static struct script_data *push_retinfo(struct script_stack *stack, struct script_retinfo *ri, struct reg_db *ref)
+{
+ nullpo_retr(NULL, stack);
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
stack->stack_data[stack->sp].type = C_RETINFO;
@@ -3514,7 +3724,9 @@ struct script_data* push_retinfo(struct script_stack* stack, struct script_retin
}
/// Pushes a copy of the target position into the stack
-struct script_data* push_copy(struct script_stack* stack, int pos) {
+static struct script_data *push_copy(struct script_stack *stack, int pos)
+{
+ nullpo_retr(NULL, stack);
switch( stack->stack_data[pos].type ) {
case C_CONSTSTR:
return script->push_conststr(stack, stack->stack_data[pos].u.str);
@@ -3538,11 +3750,15 @@ struct script_data* push_copy(struct script_stack* stack, int pos) {
/// Removes the values in indexes [start,end[ from the stack.
/// Adjusts all stack pointers.
-void pop_stack(struct script_state* st, int start, int end) {
- struct script_stack* stack = st->stack;
+static void pop_stack(struct script_state *st, int start, int end)
+{
+ struct script_stack* stack;
struct script_data* data;
int i;
+ nullpo_retv(st);
+ stack = st->stack;
+
if( start < 0 )
start = 0;
if( end > stack->sp )
@@ -3607,7 +3823,7 @@ void pop_stack(struct script_state* st, int start, int end) {
/*==========================================
* Release script dependent variable, dependent variable of function
*------------------------------------------*/
-void script_free_vars(struct DBMap *var_storage)
+static void script_free_vars(struct DBMap *var_storage)
{
if( var_storage ) {
// destroy the storage construct containing the variables
@@ -3615,7 +3831,7 @@ void script_free_vars(struct DBMap *var_storage)
}
}
-void script_free_code(struct script_code* code)
+static void script_free_code(struct script_code *code)
{
nullpo_retv(code);
@@ -3624,7 +3840,7 @@ void script_free_code(struct script_code* code)
script->free_vars(code->local.vars);
if (code->local.arrays)
code->local.arrays->destroy(code->local.arrays,script->array_free_db);
- aFree(code->script_buf);
+ VECTOR_CLEAR(code->script_buf);
aFree(code);
}
@@ -3635,7 +3851,8 @@ void script_free_code(struct script_code* code)
/// @param rid Who is running the script (attached player)
/// @param oid Where the code is being run (npc 'object')
/// @return Script state
-struct script_state* script_alloc_state(struct script_code* rootscript, int pos, int rid, int oid) {
+static struct script_state *script_alloc_state(struct script_code *rootscript, int pos, int rid, int oid)
+{
struct script_state* st;
st = ers_alloc(script->st_ers, struct script_state);
@@ -3677,7 +3894,9 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos,
/// Frees a script state.
///
/// @param st Script state
-void script_free_state(struct script_state* st) {
+static void script_free_state(struct script_state *st)
+{
+ nullpo_retv(st);
if( idb_exists(script->st_db,st->id) ) {
struct map_session_data *sd = st->rid ? map->id2sd(st->rid) : NULL;
@@ -3738,7 +3957,9 @@ void script_free_state(struct script_state* st) {
* @param st[in] Script state.
* @param ref[in] Reference to be added.
*/
-void script_add_pending_ref(struct script_state *st, struct reg_db *ref) {
+static void script_add_pending_ref(struct script_state *st, struct reg_db *ref)
+{
+ nullpo_retv(st);
RECREATE(st->pending_refs, struct reg_db*, ++st->pending_ref_count);
st->pending_refs[st->pending_ref_count-1] = ref;
}
@@ -3749,37 +3970,37 @@ void script_add_pending_ref(struct script_state *st, struct reg_db *ref) {
/*==========================================
* Read command
*------------------------------------------*/
-c_op get_com(unsigned char *scriptbuf,int *pos)
+static c_op get_com(const struct script_buf *scriptbuf, int *pos)
{
int i = 0, j = 0;
- if(scriptbuf[*pos]>=0x80) {
+ if (VECTOR_INDEX(*scriptbuf, *pos) >= 0x80) {
return C_INT;
}
- while(scriptbuf[*pos]>=0x40) {
- i=scriptbuf[(*pos)++]<<j;
+ while (VECTOR_INDEX(*scriptbuf, *pos) >= 0x40) {
+ i = VECTOR_INDEX(*scriptbuf, (*pos)++) << j;
j+=6;
}
- return (c_op)(i+(scriptbuf[(*pos)++]<<j));
+ return (c_op)(i+(VECTOR_INDEX(*scriptbuf, (*pos)++)<<j));
}
/*==========================================
* Income figures
*------------------------------------------*/
-int get_num(unsigned char *scriptbuf,int *pos)
+static int get_num(const struct script_buf *scriptbuf, int *pos)
{
int i,j;
i=0; j=0;
- while(scriptbuf[*pos]>=0xc0) {
- i+=(scriptbuf[(*pos)++]&0x7f)<<j;
+ while (VECTOR_INDEX(*scriptbuf, *pos) >= 0xc0) {
+ i+= (VECTOR_INDEX(*scriptbuf, (*pos)++)&0x7f)<<j;
j+=6;
}
- return i+((scriptbuf[(*pos)++]&0x7f)<<j);
+ return i+((VECTOR_INDEX(*scriptbuf, (*pos)++)&0x7f)<<j);
}
/// Ternary operators
/// test ? if_true : if_false
-void op_3(struct script_state* st, int op)
+static void op_3(struct script_state *st, int op)
{
struct script_data* data;
int flag = 0;
@@ -3816,7 +4037,7 @@ void op_3(struct script_state* st, int op)
/// s1 RE_EQ s2 -> i
/// s1 RE_NE s2 -> i
/// s1 ADD s2 -> s
-void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
+static void op_2str(struct script_state *st, int op, const char *s1, const char *s2)
{
int a = 0;
@@ -3834,7 +4055,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
pcre *compiled_regex;
pcre_extra *extra_regex;
const char *pcre_error, *pcre_match;
- int pcre_erroroffset, offsetcount, i;
+ int pcre_erroroffset, offsetcount;
int offsets[256*3]; // (max_capturing_groups+1)*3
compiled_regex = libpcre->compile(s2, 0, &pcre_error, &pcre_erroroffset, NULL);
@@ -3875,13 +4096,14 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
return;
}
- if( op == C_RE_EQ ) {
- for( i = 0; i < offsetcount; i++ ) {
+ if (op == C_RE_EQ) {
+ int i;
+ for (i = 0; i < offsetcount; i++) {
libpcre->get_substring(s1, offsets, offsetcount, i, &pcre_match);
- mapreg->setregstr(reference_uid(script->add_str("$@regexmatch$"), i), pcre_match);
+ mapreg->setregstr(reference_uid(script->add_variable("$@regexmatch$"), i), pcre_match);
libpcre->free_substring(pcre_match);
}
- mapreg->setreg(script->add_str("$@regexmatchcount"), i);
+ mapreg->setreg(script->add_variable("$@regexmatchcount"), i);
a = offsetcount;
} else { // C_RE_NE
a = (offsetcount == 0);
@@ -3912,7 +4134,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
/// Binary number operators
/// i OP i -> i
-void op_2num(struct script_state* st, int op, int i1, int i2)
+static void op_2num(struct script_state *st, int op, int i1, int i2)
{
int ret;
int64 ret64;
@@ -3951,6 +4173,7 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
case C_ADD: ret = i1 + i2; ret64 = (int64)i1 + i2; break;
case C_SUB: ret = i1 - i2; ret64 = (int64)i1 - i2; break;
case C_MUL: ret = i1 * i2; ret64 = (int64)i1 * i2; break;
+ case C_POW: ret = (int)pow((double)i1, (double)i2); ret64 = (int64)pow((double)i1, (double)i2); break;
default:
ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script->op2name(op), i1, i2);
script->reportsrc(st);
@@ -3971,7 +4194,7 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
}
/// Binary operators
-void op_2(struct script_state *st, int op)
+static void op_2(struct script_state *st, int op)
{
struct script_data* left, leftref;
struct script_data* right;
@@ -4045,7 +4268,7 @@ void op_2(struct script_state *st, int op)
/// NEG i -> i
/// NOT i -> i
/// LNOT i -> i
-void op_1(struct script_state* st, int op)
+static void op_1(struct script_state *st, int op)
{
struct script_data* data;
int i1;
@@ -4083,10 +4306,17 @@ void op_1(struct script_state* st, int op)
///
/// @param st Script state whose stack arguments should be inspected.
/// @param func Built-in function for which the arguments are intended.
-void script_check_buildin_argtype(struct script_state* st, int func)
+static bool script_check_buildin_argtype(struct script_state *st, int func)
{
int idx, invalid = 0;
- char* sf = script->buildin[script->str_data[func].val];
+ char* sf;
+ if (script->str_data[func].val < 0 || script->str_data[func].val >= script->buildin_count) {
+ ShowDebug("Function: %s\n", script->get_str(func));
+ ShowError("Script data corruption detected!\n");
+ script->reportsrc(st);
+ return false;
+ }
+ sf = script->buildin[script->str_data[func].val];
for (idx = 2; script_hasdata(st, idx); idx++) {
struct script_data* data = script_getdata(st, idx);
@@ -4157,15 +4387,17 @@ void script_check_buildin_argtype(struct script_state* st, int func)
ShowDebug("Function: %s\n", script->get_str(func));
script->reportsrc(st);
}
+ return true;
}
/// Executes a buildin command.
/// Stack: C_NAME(<command>) C_ARG <arg0> <arg1> ... <argN>
-int run_func(struct script_state *st)
+static int run_func(struct script_state *st)
{
struct script_data* data;
int i,start_sp,end_sp,func;
+ nullpo_retr(1, st);
end_sp = st->stack->sp;// position after the last argument
for( i = end_sp-1; i > 0 ; --i )
if( st->stack->stack_data[i].type == C_ARG )
@@ -4194,7 +4426,11 @@ int run_func(struct script_state *st)
}
if( script->config.warn_func_mismatch_argtypes ) {
- script->check_buildin_argtype(st, func);
+ if (script->check_buildin_argtype(st, func) == false)
+ {
+ st->state = END;
+ return 1;
+ }
}
if(script->str_data[func].func) {
@@ -4249,7 +4485,8 @@ int run_func(struct script_state *st)
/*==========================================
* script execution
*------------------------------------------*/
-void run_script(struct script_code *rootscript, int pos, int rid, int oid) {
+static void run_script(struct script_code *rootscript, int pos, int rid, int oid)
+{
struct script_state *st;
if( rootscript == NULL || pos < 0 )
@@ -4263,7 +4500,7 @@ void run_script(struct script_code *rootscript, int pos, int rid, int oid) {
script->run_main(st);
}
-void script_stop_instances(struct script_code *code)
+static void script_stop_instances(struct script_code *code)
{
struct DBIterator *iter;
struct script_state* st;
@@ -4285,7 +4522,8 @@ void script_stop_instances(struct script_code *code)
/*==========================================
* Timer function for sleep
*------------------------------------------*/
-int run_script_timer(int tid, int64 tick, int id, intptr_t data) {
+static int run_script_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct script_state *st = idb_get(script->st_db,(int)data);
if( st ) {
struct map_session_data *sd = map->id2sd(st->rid);
@@ -4306,9 +4544,11 @@ int run_script_timer(int tid, int64 tick, int id, intptr_t data) {
///
/// @param st Script state to detach.
/// @param dequeue_event Whether to schedule any queued events, when there was no previous script.
-void script_detach_state(struct script_state* st, bool dequeue_event) {
+static void script_detach_state(struct script_state *st, bool dequeue_event)
+{
struct map_session_data* sd;
+ nullpo_retv(st);
if(st->rid && (sd = map->id2sd(st->rid))!=NULL) {
sd->st = st->bk_st;
sd->npc_id = st->bk_npcid;
@@ -4339,9 +4579,11 @@ void script_detach_state(struct script_state* st, bool dequeue_event) {
/// Attaches script state to possibly attached character and backups it's previous script, if any.
///
/// @param st Script state to attach.
-void script_attach_state(struct script_state* st) {
+static void script_attach_state(struct script_state *st)
+{
struct map_session_data* sd;
+ nullpo_retv(st);
if(st->rid && (sd = map->id2sd(st->rid))!=NULL)
{
if(st!=sd->st)
@@ -4370,14 +4612,19 @@ void script_attach_state(struct script_state* st) {
/*==========================================
* The main part of the script execution
*------------------------------------------*/
-void run_script_main(struct script_state *st) {
+static void run_script_main(struct script_state *st)
+{
int cmdcount = script->config.check_cmdcount;
int gotocount = script->config.check_gotocount;
struct map_session_data *sd;
struct script_stack *stack = st->stack;
struct npc_data *nd;
+ nullpo_retv(st);
script->attach_state(st);
+ if (st->state != END && Assert_chk(st->state == RUN || st->state == STOP || st->state == RERUNLINE)) {
+ st->state = END;
+ }
nd = map->id2nd(st->oid);
if( nd && nd->bl.m >= 0 )
@@ -4393,7 +4640,7 @@ void run_script_main(struct script_state *st) {
st->state = RUN;
while( st->state == RUN ) {
- enum c_op c = script->get_com(st->script->script_buf,&st->pos);
+ enum c_op c = script->get_com(&st->script->script_buf, &st->pos);
switch(c) {
case C_EOL:
if( stack->defsp > stack->sp )
@@ -4402,27 +4649,29 @@ void run_script_main(struct script_state *st) {
script->pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value)
break;
case C_INT:
- script->push_val(stack,C_INT,script->get_num(st->script->script_buf,&st->pos),NULL);
+ script->push_val(stack,C_INT,script->get_num(&st->script->script_buf, &st->pos), NULL);
break;
case C_POS:
case C_NAME:
- script->push_val(stack,c,GETVALUE(st->script->script_buf,st->pos),NULL);
+ script->push_val(stack,c,GETVALUE(&st->script->script_buf, st->pos), NULL);
st->pos+=3;
break;
case C_ARG:
script->push_val(stack,c,0,NULL);
break;
case C_STR:
- script->push_conststr(stack, (const char *)(st->script->script_buf+st->pos));
- while(st->script->script_buf[st->pos++]);
+ script->push_conststr(stack, (const char *)&VECTOR_INDEX(st->script->script_buf, st->pos));
+ while (VECTOR_INDEX(st->script->script_buf, st->pos++) != 0)
+ (void)0; // Skip string
break;
case C_LSTR:
{
- int string_id = *((int *)(&st->script->script_buf[st->pos]));
- uint8 translations = *((uint8 *)(&st->script->script_buf[st->pos+sizeof(int)]));
struct map_session_data *lsd = NULL;
-
- st->pos += sizeof(int) + sizeof(uint8);
+ uint8 translations = 0;
+ int string_id = *((int *)(&VECTOR_INDEX(st->script->script_buf, st->pos)));
+ st->pos += sizeof(string_id);
+ translations = *((uint8 *)(&VECTOR_INDEX(st->script->script_buf, st->pos)));
+ st->pos += sizeof(translations);
if( (!st->rid || !(lsd = map->id2sd(st->rid)) || !lsd->lang_id) && !map->default_lang_id )
script->push_conststr(stack, script->string_list+string_id);
@@ -4431,7 +4680,7 @@ void run_script_main(struct script_state *st) {
int offset = st->pos;
for(k = 0; k < translations; k++) {
- uint8 lang_id = *(uint8 *)(&st->script->script_buf[offset]);
+ uint8 lang_id = *(uint8 *)(&VECTOR_INDEX(st->script->script_buf, offset));
offset += sizeof(uint8);
if( lang_id == wlang_id )
break;
@@ -4440,7 +4689,7 @@ void run_script_main(struct script_state *st) {
if (k == translations)
script->push_conststr(stack, script->string_list+string_id);
else
- script->push_conststr(stack, *(const char**)(&st->script->script_buf[offset]) );
+ script->push_conststr(stack, *(const char**)(&VECTOR_INDEX(st->script->script_buf, offset)));
}
st->pos += ( ( sizeof(char*) + sizeof(uint8) ) * translations );
}
@@ -4470,6 +4719,7 @@ void run_script_main(struct script_state *st) {
case C_ADD:
case C_SUB:
case C_MUL:
+ case C_POW:
case C_DIV:
case C_MOD:
case C_EQ:
@@ -4548,58 +4798,62 @@ void run_script_main(struct script_state *st) {
}
}
-int script_config_read(char *cfgName) {
- int i;
- char line[1024],w1[1024],w2[1024];
- FILE *fp;
+/**
+ * Reads 'script_configuration' and initializes required variables.
+ *
+ * @param filename Path to configuration file.
+ * @param imported Whether the current config is imported from another file.
+ *
+ * @retval false in case of error.
+ */
+static bool script_config_read(const char *filename, bool imported)
+{
+ struct config_t config;
+ struct config_setting_t * setting = NULL;
+ const char *import = NULL;
+ bool retval = true;
- if( !( fp = fopen(cfgName,"r") ) ) {
- ShowError("File not found: %s\n", cfgName);
- return 1;
+ nullpo_retr(false, filename);
+
+ if (!libconfig->load_file(&config, filename))
+ return false;
+
+ if ((setting = libconfig->lookup(&config, "script_configuration")) == NULL) {
+ libconfig->destroy(&config);
+ if (imported)
+ return true;
+ ShowError("script_config_read: script_configuration was not found in %s!\n", filename);
+ return false;
}
- while (fgets(line, sizeof(line), fp)) {
- if (line[0] == '/' && line[1] == '/')
- continue;
- i = sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2);
- if(i!=2)
- continue;
- if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) {
- script->config.warn_func_mismatch_paramnum = config_switch(w2);
- }
- else if(strcmpi(w1,"check_cmdcount")==0) {
- script->config.check_cmdcount = config_switch(w2);
- }
- else if(strcmpi(w1,"check_gotocount")==0) {
- script->config.check_gotocount = config_switch(w2);
- }
- else if(strcmpi(w1,"input_min_value")==0) {
- script->config.input_min_value = config_switch(w2);
- }
- else if(strcmpi(w1,"input_max_value")==0) {
- script->config.input_max_value = config_switch(w2);
- }
- else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) {
- script->config.warn_func_mismatch_argtypes = config_switch(w2);
- }
- else if(strcmpi(w1,"import")==0) {
- script->config_read(w2);
- }
- else if(HPM->parseConf(w1, w2, HPCT_SCRIPT)) {
- ; // handled by plugin
+ libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_paramnum", &script->config.warn_func_mismatch_paramnum);
+ libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_argtypes", &script->config.warn_func_mismatch_argtypes);
+ libconfig->setting_lookup_int(setting, "check_cmdcount", &script->config.check_cmdcount);
+ libconfig->setting_lookup_int(setting, "check_gotocount", &script->config.check_gotocount);
+ libconfig->setting_lookup_int(setting, "input_min_value", &script->config.input_min_value);
+ libconfig->setting_lookup_int(setting, "input_max_value", &script->config.input_max_value);
+
+ if (!HPM->parse_conf(&config, filename, HPCT_SCRIPT, imported))
+ retval = false;
+
+ // import should overwrite any previous configuration, so it should be called last
+ if (libconfig->lookup_string(&config, "import", &import) == CONFIG_TRUE) {
+ if (strcmp(import, filename) == 0 || strcmp(import, map->SCRIPT_CONF_NAME) == 0) {
+ ShowWarning("script_config_read: Loop detected! Skipping 'import'...\n");
} else {
- ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
+ if (!script->config_read(import, true))
+ retval = false;
}
}
- fclose(fp);
- return 0;
+ libconfig->destroy(&config);
+ return retval;
}
/**
* @see DBApply
*/
-int db_script_free_code_sub(union DBKey key, struct DBData *data, va_list ap)
+static int db_script_free_code_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct script_code *code = DB->data2ptr(data);
if (code)
@@ -4607,7 +4861,7 @@ int db_script_free_code_sub(union DBKey key, struct DBData *data, va_list ap)
return 0;
}
-void script_run_autobonus(const char *autobonus, int id, int pos)
+static void script_run_autobonus(const char *autobonus, int id, int pos)
{
struct script_code *scriptroot = (struct script_code *)strdb_get(script->autobonus_db, autobonus);
@@ -4617,7 +4871,7 @@ void script_run_autobonus(const char *autobonus, int id, int pos)
}
}
-void script_add_autobonus(const char *autobonus)
+static 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, NULL);
@@ -4628,13 +4882,19 @@ void script_add_autobonus(const char *autobonus)
}
/// resets a temporary character array variable to given value
-void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value) {
+static void script_cleararray_pc(struct map_session_data *sd, const char *varname, void *value)
+{
struct script_array *sa = NULL;
struct reg_db *src = NULL;
unsigned int i, *list = NULL, size = 0;
int key;
- key = script->add_str(varname);
+ key = script->add_variable(varname);
+
+ if (script->str_data[key].type != C_NAME) {
+ ShowError("script:cleararray_pc: `%s` is already used by something that is not a variable.\n", varname);
+ return;
+ }
if( !(src = script->array_src(NULL,sd,varname,NULL) ) )
return;
@@ -4655,15 +4915,21 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void
/// sets a temporary character array variable element idx to given value
/// @param refcache Pointer to an int variable, which keeps a copy of the reference to varname and must be initialized to 0. Can be NULL if only one element is set.
-void script_setarray_pc(struct map_session_data* sd, const char* varname, uint32 idx, void* value, int* refcache) {
+static void script_setarray_pc(struct map_session_data *sd, const char *varname, uint32 idx, void *value, int *refcache)
+{
int key;
- if( idx >= SCRIPT_MAX_ARRAYSIZE ) {
+ if (idx > SCRIPT_MAX_ARRAYSIZE) {
ShowError("script_setarray_pc: Variable '%s' has invalid index '%u' (char_id=%d).\n", varname, idx, sd->status.char_id);
return;
}
- key = ( refcache && refcache[0] ) ? refcache[0] : script->add_str(varname);
+ key = ( refcache && refcache[0] ) ? refcache[0] : script->add_variable(varname);
+
+ if (script->str_data[key].type != C_NAME) {
+ ShowError("script:setarray_pc: `%s` is already used by something that is not a variable.\n", varname);
+ return;
+ }
script->set_reg(NULL,sd,reference_uid(key, idx),varname,value,NULL);
@@ -4675,10 +4941,11 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint32
/**
* Clears persistent variables from memory
**/
-int script_reg_destroy(union DBKey key, struct DBData *data, va_list ap)
+static int script_reg_destroy(union DBKey key, struct DBData *data, va_list ap)
{
struct script_reg_state *src;
+ nullpo_ret(data);
if( data->type != DB_DATA_PTR )/* got no need for those! */
return 0;
@@ -4699,7 +4966,10 @@ int script_reg_destroy(union DBKey key, struct DBData *data, va_list ap)
/**
* Clears a single persistent variable
**/
-void script_reg_destroy_single(struct map_session_data *sd, int64 reg, struct script_reg_state *data) {
+static void script_reg_destroy_single(struct map_session_data *sd, int64 reg, struct script_reg_state *data)
+{
+ nullpo_retv(sd);
+ nullpo_retv(data);
i64db_remove(sd->regs.vars, reg);
if( data->type ) {
@@ -4713,20 +4983,23 @@ void script_reg_destroy_single(struct map_session_data *sd, int64 reg, struct sc
ers_free(pc->num_reg_ers,(struct script_reg_num*)data);
}
}
-unsigned int *script_array_cpy_list(struct script_array *sa) {
+static unsigned int *script_array_cpy_list(struct script_array *sa)
+{
+ nullpo_retr(NULL, sa);
if( sa->size > script->generic_ui_array_size )
script->generic_ui_array_expand(sa->size);
memcpy(script->generic_ui_array, sa->members, sizeof(unsigned int)*sa->size);
return script->generic_ui_array;
}
-void script_generic_ui_array_expand (unsigned int plus) {
+static void script_generic_ui_array_expand(unsigned int plus)
+{
script->generic_ui_array_size += plus + 100;
RECREATE(script->generic_ui_array, unsigned int, script->generic_ui_array_size);
}
/*==========================================
* Destructor
*------------------------------------------*/
-void do_final_script(void)
+static void do_final_script(void)
{
int i;
struct DBIterator *iter;
@@ -4806,6 +5079,8 @@ void do_final_script(void)
aFree(script->str_buf);
for( i = 0; i < atcommand->binding_count; i++ ) {
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
}
@@ -4854,16 +5129,15 @@ void do_final_script(void)
script->clear_translations(false);
script->parser_clean_leftovers();
-
- if( script->lang_export_file )
- aFree(script->lang_export_file);
}
/**
*
**/
-uint8 script_add_language(const char *name) {
+static uint8 script_add_language(const char *name)
+{
uint8 lang_id = script->max_lang_id;
+ nullpo_ret(name);
RECREATE(script->languages, char *, ++script->max_lang_id);
script->languages[lang_id] = aStrdup(name);
@@ -4873,12 +5147,14 @@ uint8 script_add_language(const char *name) {
/**
* Goes thru db/translations.conf file
**/
-void script_load_translations(void) {
+static void script_load_translations(void)
+{
struct config_t translations_conf;
- const char *config_filename = "db/translations.conf"; // FIXME hardcoded name
+ char config_filename[256];
+ libconfig->format_db_path("translations.conf", config_filename, sizeof(config_filename));
struct config_setting_t *translations = NULL;
int i, size;
- uint32 total = 0;
+ int total = 0;
uint8 lang_id = 0, k;
if (map->minimal) // No translations in minimal mode
@@ -4914,25 +5190,23 @@ void script_load_translations(void) {
size = libconfig->setting_length(translations);
for(i = 0; i < size; i++) {
- const char *translation_file = libconfig->setting_get_string_elem(translations, i);
- script->load_translation(translation_file, ++lang_id, &total);
+ const char *translation_dir = libconfig->setting_get_string_elem(translations, i);
+ total += script->load_translation(translation_dir, ++lang_id);
}
libconfig->destroy(&translations_conf);
- if( total ) {
- struct DBIterator *main_iter, *sub_iter;
+ if (total != 0) {
+ struct DBIterator *main_iter;
struct DBMap *string_db;
struct string_translation *st = NULL;
- uint32 j = 0;
- CREATE(script->translation_buf, char *, total);
- script->translation_buf_size = total;
+ VECTOR_ENSURE(script->translation_buf, total, 1);
main_iter = db_iterator(script->translation_db);
- for( string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter) ) {
- sub_iter = db_iterator(string_db);
- for( st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter) ) {
- script->translation_buf[j++] = st->buf;
+ for (string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter)) {
+ struct DBIterator *sub_iter = db_iterator(string_db);
+ for (st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter)) {
+ VECTOR_PUSH(script->translation_buf, st->buf);
}
dbi_destroy(sub_iter);
}
@@ -4954,149 +5228,319 @@ void script_load_translations(void) {
}
/**
+ * Generates a language name from a translation directory name.
*
- **/
-const char * script_get_translation_file_name(const char *file) {
- static char file_name[200];
- int i, len = (int)strlen(file), last_bar = -1, last_dot = -1;
+ * @param directory The directory name.
+ * @return The corresponding translation name.
+ */
+static const char *script_get_translation_dir_name(const char *directory)
+{
+ const char *basename = NULL, *last_dot = NULL;
+
+ nullpo_retr("Unknown", directory);
- for(i = 0; i < len; i++) {
- if( file[i] == '/' || file[i] == '\\' )
- last_bar = i;
- else if ( file[i] == '.' )
- last_dot = i;
+ basename = strrchr(directory, '/');
+#ifdef WIN32
+ {
+ const char *basename_windows = strrchr(directory, '\\');
+ if (basename_windows > basename)
+ basename = basename_windows;
}
+#endif // WIN32
+ if (basename == NULL)
+ basename = directory;
+ else
+ basename++; // Skip slash
+ Assert_retr("Unknown", *basename != '\0');
+
+ last_dot = strrchr(basename, '.');
+ if (last_dot != NULL) {
+ static char dir_name[200];
+ if (last_dot == basename)
+ return basename + 1;
- if( last_bar != -1 || last_dot != -1 ) {
- if( last_bar != -1 && last_dot < last_bar )
- last_dot = -1;
- safestrncpy(file_name, file+(last_bar >= 0 ? last_bar+1 : 0), ( last_dot >= 0 ? ( last_bar >= 0 ? last_dot - last_bar : last_dot ) : sizeof(file_name) ));
- return file_name;
+ safestrncpy(dir_name, basename, last_dot - basename + 1);
+ return dir_name;
}
- return file;
+ return basename;
}
/**
- * Parses a individual translation file
- **/
-void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
- uint32 translations = 0;
+ * Parses and adds a translated string to the translations database.
+ *
+ * @param file Translations file being parsed (for error messages).
+ * @param lang_id Language ID being parsed.
+ * @param msgctxt Message context (i.e. NPC name)
+ * @param msgid Message ID (source string)
+ * @param msgstr Translated message
+ * @return success state
+ * @retval true if a new string was added.
+ */
+static bool script_load_translation_addstring(const char *file, uint8 lang_id, const char *msgctxt, const struct script_string_buf *msgid, const struct script_string_buf *msgstr)
+{
+ nullpo_retr(false, file);
+ nullpo_retr(false, msgctxt);
+ nullpo_retr(false, msgid);
+ nullpo_retr(false, msgstr);
+
+ if (VECTOR_LENGTH(*msgid) <= 1) {
+ // Empty ID (i.e. header) to be ignored
+ return false;
+ }
+
+ if (VECTOR_LENGTH(*msgstr) <= 1) {
+ // Empty (untranslated) string to be ignored
+ return false;
+ }
+
+ if (msgctxt[0] == '\0') {
+ // Missing context
+ ShowWarning("script_load_translation: Missing context for msgid '%s' in '%s'. Skipping.\n",
+ VECTOR_DATA(*msgid), file);
+ return false;
+ }
+
+ if (strcasecmp(msgctxt, "messages.conf") == 0) {
+ int i;
+ for (i = 0; i < MAX_MSG; i++) {
+ if (atcommand->msg_table[0][i] != NULL && strcmpi(atcommand->msg_table[0][i], VECTOR_DATA(*msgid)) == 0) {
+ if (atcommand->msg_table[lang_id][i] != NULL)
+ aFree(atcommand->msg_table[lang_id][i]);
+ atcommand->msg_table[lang_id][i] = aStrdup(VECTOR_DATA(*msgstr));
+ break;
+ }
+ }
+ } else {
+ int msgstr_len = VECTOR_LENGTH(*msgstr);
+ int inner_len = 1 + msgstr_len + 1; //uint8 lang_id + msgstr_len + '\0'
+ struct string_translation *st = NULL;
+ struct DBMap *string_db;
+
+ if ((string_db = strdb_get(script->translation_db, msgctxt)) == NULL) {
+ string_db = strdb_alloc(DB_OPT_DUP_KEY, 0);
+ strdb_put(script->translation_db, msgctxt, string_db);
+ }
+
+ if ((st = strdb_get(string_db, VECTOR_DATA(*msgid))) == NULL) {
+ CREATE(st, struct string_translation, 1);
+ st->string_id = script->string_dup(VECTOR_DATA(*msgid));
+ strdb_put(string_db, VECTOR_DATA(*msgid), st);
+ }
+ RECREATE(st->buf, uint8, st->len + inner_len);
+
+ WBUFB(st->buf, st->len) = lang_id;
+ safestrncpy(WBUFP(st->buf, st->len + 1), VECTOR_DATA(*msgstr), msgstr_len + 1);
+
+ st->translations++;
+ st->len += inner_len;
+ }
+ return true;
+}
+
+/**
+ * Parses an individual translation file.
+ *
+ * @param directory The directory structure to read.
+ * @param lang_id The language identifier.
+ * @return The amount of strings loaded.
+ */
+static int script_load_translation_file(const char *file, uint8 lang_id)
+{
char line[1024];
- char msgctxt[NAME_LENGTH*2+1] = { 0 };
- struct DBMap *string_db;
- size_t i;
+ char msgctxt[NAME_LENGTH*2+1] = "";
+ struct script_string_buf msgid, msgstr;
+ struct script_string_buf *msg_ptr;
+ int translations = 0;
+ int lineno = 0;
FILE *fp;
- struct script_string_buf msgid = { 0 }, msgstr = { 0 };
- if( !(fp = fopen(file,"rb")) ) {
+ nullpo_ret(file);
+
+ if ((fp = fopen(file,"rb")) == NULL) {
ShowError("load_translation: failed to open '%s' for reading\n",file);
- return;
+ return 0;
}
- script->add_language(script->get_translation_file_name(file));
- if( lang_id >= atcommand->max_message_table )
- atcommand->expand_message_table();
+ VECTOR_INIT(msgid);
+ VECTOR_INIT(msgstr);
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ int len = (int)strlen(line);
+ int i;
+ lineno++;
- while(fgets(line, sizeof(line), fp)) {
- size_t len = strlen(line), cursor = 0;
+ if (len <= 1) {
+ if (VECTOR_LENGTH(msgid) > 0 && VECTOR_LENGTH(msgstr) > 0) {
+ // Add string
+ if (script->load_translation_addstring(file, lang_id, msgctxt, &msgid, &msgstr))
+ translations++;
- if( len <= 1 )
+ msgctxt[0] = '\0';
+ VECTOR_TRUNCATE(msgid);
+ VECTOR_TRUNCATE(msgstr);
+ }
continue;
+ }
- if( line[0] == '#' )
+ if (line[0] == '#')
continue;
- if( strncasecmp(line,"msgctxt \"", 9) == 0 ) {
+ if (VECTOR_LENGTH(msgid) > 0) {
+ if (VECTOR_LENGTH(msgstr) > 0) {
+ msg_ptr = &msgstr;
+ } else {
+ msg_ptr = &msgid;
+ }
+ if (line[0] == '"') {
+ // Continuation line
+ (void)VECTOR_POP(*msg_ptr); // Pop final '\0'
+ for (i = 1; i < len - 2; i++) {
+ VECTOR_ENSURE(*msg_ptr, 1, 512);
+ if (line[i] == '\\' && line[i+1] == '"') {
+ VECTOR_PUSH(*msg_ptr, '"');
+ i++;
+ } else if (line[i] == '\\' && line[i+1] == 'r') {
+ VECTOR_PUSH(*msg_ptr, '\r');
+ i++;
+ } else {
+ VECTOR_PUSH(*msg_ptr, line[i]);
+ }
+ }
+ VECTOR_ENSURE(*msg_ptr, 1, 512);
+ VECTOR_PUSH(*msg_ptr, '\0');
+ continue;
+ }
+
+ }
+
+ if (strncasecmp(line,"msgctxt \"", 9) == 0) {
+ int cursor = 0;
msgctxt[0] = '\0';
- for(i = 9; i < len - 2; i++) {
- if( line[i] == '\\' && line[i+1] == '"' ) {
+ for (i = 9; i < len - 2; i++) {
+ if (line[i] == '\\' && line[i+1] == '"') {
msgctxt[cursor] = '"';
i++;
- } else
+ } else if (line[i] == '\\' && line[i+1] == 'r') {
+ msgctxt[cursor] = '\r';
+ i++;
+ } else {
msgctxt[cursor] = line[i];
- if( ++cursor >= sizeof(msgctxt) - 1 )
+ }
+ if (++cursor >= (int)sizeof(msgctxt) - 1)
break;
}
msgctxt[cursor] = '\0';
- } else if ( strncasecmp(line, "msgid \"", 7) == 0 ) {
- msgid.pos = 0;
- for(i = 7; i < len - 2; i++) {
- if( line[i] == '\\' && line[i+1] == '"' ) {
- script_string_buf_addb(&msgid, '"');
+
+ // New context, reset everything
+ VECTOR_TRUNCATE(msgid);
+ VECTOR_TRUNCATE(msgstr);
+ continue;
+ }
+
+ if (strncasecmp(line, "msgid \"", 7) == 0) {
+ VECTOR_TRUNCATE(msgid);
+ for (i = 7; i < len - 2; i++) {
+ VECTOR_ENSURE(msgid, 1, 512);
+ if (line[i] == '\\' && line[i+1] == '"') {
+ VECTOR_PUSH(msgid, '"');
+ i++;
+ } else if (line[i] == '\\' && line[i+1] == 'r') {
+ VECTOR_PUSH(msgid, '\r');
i++;
- } else
- script_string_buf_addb(&msgid, line[i]);
+ } else {
+ VECTOR_PUSH(msgid, line[i]);
+ }
}
- script_string_buf_addb(&msgid,0);
- } else if ( len > 9 && line[9] != '"' && strncasecmp(line, "msgstr \"",8) == 0 ) {
- msgstr.pos = 0;
- for(i = 8; i < len - 2; i++) {
- if( line[i] == '\\' && line[i+1] == '"' ) {
- script_string_buf_addb(&msgstr, '"');
+ VECTOR_ENSURE(msgid, 1, 512);
+ VECTOR_PUSH(msgid, '\0');
+
+ // New id, reset string if any
+ VECTOR_TRUNCATE(msgstr);
+ continue;
+ }
+
+ if (VECTOR_LENGTH(msgid) > 0 && strncasecmp(line, "msgstr \"", 8) == 0) {
+ VECTOR_TRUNCATE(msgstr);
+ for (i = 8; i < len - 2; i++) {
+ VECTOR_ENSURE(msgstr, 1, 512);
+ if (line[i] == '\\' && line[i+1] == '"') {
+ VECTOR_PUSH(msgstr, '"');
i++;
- } else
- script_string_buf_addb(&msgstr, line[i]);
+ } else if (line[i] == '\\' && line[i+1] == 'r') {
+ VECTOR_PUSH(msgstr, '\r');
+ i++;
+ } else {
+ VECTOR_PUSH(msgstr, line[i]);
+ }
}
- script_string_buf_addb(&msgstr,0);
+ VECTOR_ENSURE(msgstr, 1, 512);
+ VECTOR_PUSH(msgstr, '\0');
+
+ continue;
}
- if( msgctxt[0] && msgid.pos > 1 && msgstr.pos > 1 ) {
- size_t msgstr_len = msgstr.pos;
- unsigned int inner_len = 1 + (uint32)msgstr_len + 1; //uint8 lang_id + msgstr_len + '\0'
+ ShowWarning("script_load_translation: Unexpected input at '%s' in file '%s' line %d. Skipping.\n",
+ line, file, lineno);
+ }
- if( strcasecmp(msgctxt, "messages.conf") == 0 ) {
- int k;
+ // Add last string
+ if (VECTOR_LENGTH(msgid) > 0 && VECTOR_LENGTH(msgstr) > 0) {
+ if (script->load_translation_addstring(file, lang_id, msgctxt, &msgid, &msgstr))
+ translations++;
+ }
- for(k = 0; k < MAX_MSG; k++) {
- if( atcommand->msg_table[0][k] && strcmpi(atcommand->msg_table[0][k],msgid.ptr) == 0 ) {
- if( atcommand->msg_table[lang_id][k] )
- aFree(atcommand->msg_table[lang_id][k]);
- atcommand->msg_table[lang_id][k] = aStrdup(msgstr.ptr);
- break;
- }
- }
- } else {
- struct string_translation *st = NULL;
+ fclose(fp);
- if( !( string_db = strdb_get(script->translation_db, msgctxt) ) ) {
- string_db = strdb_alloc(DB_OPT_DUP_KEY, 0);
- strdb_put(script->translation_db, msgctxt, string_db);
- }
+ VECTOR_CLEAR(msgid);
+ VECTOR_CLEAR(msgstr);
- if( !(st = strdb_get(string_db, msgid.ptr) ) ) {
- CREATE(st, struct string_translation, 1);
- st->string_id = script->string_dup(msgid.ptr);
- strdb_put(string_db, msgid.ptr, st);
- }
- RECREATE(st->buf, char, st->len + inner_len);
+ return translations;
+}
- WBUFB(st->buf, st->len) = lang_id;
- safestrncpy(WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1);
+struct load_translation_data {
+ uint8 lang_id;
+ int translation_count;
+};
- st->translations++;
- st->len += inner_len;
- }
- msgctxt[0] = '\0';
- msgid.pos = msgstr.pos = 0;
- translations++;
- }
- }
+static void script_load_translation_sub(const char *filename, void *context)
+{
+ nullpo_retv(context);
- *total += translations;
+ struct load_translation_data *data = context;
- fclose(fp);
+ data->translation_count += script->load_translation_file(filename, data->lang_id);
+}
- script_string_buf_destroy(&msgid);
- script_string_buf_destroy(&msgstr);
+/**
+ * Loads a translations directory
+ *
+ * @param directory The directory structure to read.
+ * @param lang_id The language identifier.
+ * @return The amount of strings loaded.
+ */
+static int script_load_translation(const char *directory, uint8 lang_id)
+{
+ struct load_translation_data data = { 0 };
+ data.lang_id = lang_id;
+
+ nullpo_ret(directory);
+
+ script->add_language(script->get_translation_dir_name(directory));
+ if (lang_id >= atcommand->max_message_table)
+ atcommand->expand_message_table();
- ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", translations, file);
+ findfile(directory, ".po", script_load_translation_sub, &data);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", data.translation_count, directory);
+ return data.translation_count;
}
/**
*
**/
-void script_clear_translations(bool reload) {
+static void script_clear_translations(bool reload)
+{
uint32 i;
if( script->string_list )
@@ -5106,15 +5550,10 @@ void script_clear_translations(bool reload) {
script->string_list_pos = 0;
script->string_list_size = 0;
- if( script->translation_buf ) {
- for(i = 0; i < script->translation_buf_size; i++) {
- aFree(script->translation_buf[i]);
- }
- aFree(script->translation_buf);
+ while (VECTOR_LENGTH(script->translation_buf) > 0) {
+ aFree(VECTOR_POP(script->translation_buf));
}
-
- script->translation_buf = NULL;
- script->translation_buf_size = 0;
+ VECTOR_CLEAR(script->translation_buf);
if( script->languages ) {
for(i = 0; i < script->max_lang_id; i++)
@@ -5135,7 +5574,7 @@ void script_clear_translations(bool reload) {
/**
*
**/
-int script_translation_db_destroyer(union DBKey key, struct DBData *data, va_list ap)
+static int script_translation_db_destroyer(union DBKey key, struct DBData *data, va_list ap)
{
struct DBMap *string_db = DB->data2ptr(data);
@@ -5156,32 +5595,23 @@ int script_translation_db_destroyer(union DBKey key, struct DBData *data, va_lis
/**
*
**/
-void script_parser_clean_leftovers(void) {
- if( script->buf )
- aFree(script->buf);
-
- script->buf = NULL;
- script->size = 0;
+static void script_parser_clean_leftovers(void)
+{
+ VECTOR_CLEAR(script->buf);
if( script->translation_db ) {
script->translation_db->destroy(script->translation_db,script->translation_db_destroyer);
script->translation_db = NULL;
}
- if( script->syntax.strings ) { /* used only when generating translation file */
- db_destroy(script->syntax.strings);
- script->syntax.strings = NULL;
- }
-
- script_string_buf_destroy(&script->parse_simpleexpr_str);
- script_string_buf_destroy(&script->lang_export_line_buf);
- script_string_buf_destroy(&script->lang_export_unescaped_buf);
+ VECTOR_CLEAR(script->parse_simpleexpr_strbuf);
}
/**
* Performs cleanup after all parsing is processed
**/
-int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) {
+static int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data)
+{
script->parser_clean_leftovers();
script->parse_cleanup_timer_id = INVALID_TIMER;
@@ -5192,8 +5622,10 @@ int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Initialization
*------------------------------------------*/
-void do_init_script(bool minimal) {
+static void do_init_script(bool minimal)
+{
script->parse_cleanup_timer_id = INVALID_TIMER;
+ VECTOR_INIT(script->parse_simpleexpr_strbuf);
script->st_db = idb_alloc(DB_OPT_BASE);
script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
@@ -5210,7 +5642,7 @@ void do_init_script(bool minimal) {
VECTOR_INIT(script->hqi);
script->parse_builtin();
- script->read_constdb();
+ script->read_constdb(false);
script->load_parameters();
script->hardcoded_constants();
@@ -5221,7 +5653,7 @@ void do_init_script(bool minimal) {
script->load_translations();
}
-int script_reload(void)
+static int script_reload(void)
{
int i;
struct DBIterator *iter;
@@ -5243,6 +5675,8 @@ int script_reload(void)
script->label_count = 0;
for( i = 0; i < atcommand->binding_count; i++ ) {
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
}
@@ -5260,18 +5694,21 @@ int script_reload(void)
script->parse_cleanup_timer_id = INVALID_TIMER;
}
- mapreg->reload();
-
+ script->read_constdb(true);
itemdb->name_constants();
+ clan->set_constants();
+ mapreg->reload();
sysinfo->vcsrevision_reload();
return 0;
}
/* returns name of current function being run, from within the stack [Ind/Hercules] */
-const char *script_getfuncname(struct script_state *st) {
+static const char *script_getfuncname(struct script_state *st)
+{
struct script_data *data;
+ nullpo_retr(NULL, st);
data = &st->stack->stack_data[st->start];
if( data->type == C_NAME && script->str_data[data->u.num].type == C_FUNC )
@@ -5280,6 +5717,231 @@ const char *script_getfuncname(struct script_state *st) {
return NULL;
}
+/**
+ * Writes a string to a StringBuf by combining a format string and a set of
+ * arguments taken from the current script state (caller script function
+ * arguments).
+ *
+ * @param[in] st Script state (must have at least a string at index
+ * 'start').
+ * @param[in] start Index of the format string argument.
+ * @param[out] out Output string buffer (managed by the caller, must be
+ * already initialized)
+ * @retval false if an error occurs.
+ */
+static bool script_sprintf_helper(struct script_state *st, int start, struct StringBuf *out)
+{
+ const char *format = NULL;
+ const char *p = NULL, *np = NULL;
+ char *buf = NULL;
+ int buf_len = 0;
+ int lastarg = start;
+ int argc = script_lastdata(st) + 1;
+
+ nullpo_retr(-1, out);
+ Assert_retr(-1, start >= 2 && start <= argc);
+ Assert_retr(-1, script_hasdata(st, start));
+
+ p = format = script_getstr(st, start);
+
+ /*
+ * format-string = "" / *(text / placeholder)
+ * placeholder = "%%" / "%n" / std-placeholder
+ * std-placeholder = "%" [pos-parameter] [flags] [width] [precision] [length] type
+ * pos-parameter = number "$"
+ * flags = *("-" / "+" / "0" / SP)
+ * width = number / ("*" [pos-parameter])
+ * precision = "." (number / ("*" [pos-parameter]))
+ * length = "hh" / "h" / "l" / "ll" / "L" / "z" / "j" / "t"
+ * type = "d" / "i" / "u" / "f" / "F" / "e" / "E" / "g" / "G" / "x" / "X" / "o" / "s" / "c" / "p" / "a" / "A"
+ * number = digit-nonzero *DIGIT
+ * digit-nonzero = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
+ */
+
+ while ((np = strchr(p, '%')) != NULL) {
+ bool flag_plus = false, flag_minus = false, flag_zero = false, flag_space = false;
+ bool positional_arg = false;
+ int width = 0, nextarg = lastarg + 1, thisarg = nextarg;
+
+ if (p != np) {
+ int len = (int)(np - p + 1);
+ if (buf_len < len) {
+ RECREATE(buf, char, len);
+ buf_len = len;
+ }
+ safestrncpy(buf, p, len);
+ StrBuf->AppendStr(out, buf);
+ }
+ np++;
+
+ // placeholder = "%%" ; (special case)
+ if (*np == '%') {
+ StrBuf->AppendStr(out, "%");
+ p = np + 1;
+ continue;
+ }
+ // placeholder = "%n" ; (ignored)
+ if (*np == 'n') {
+ ShowWarning("script_sprintf_helper: Format %%n not supported! Skipping...\n");
+ script->reportsrc(st);
+ lastarg = nextarg;
+ p = np + 1;
+ continue;
+ }
+
+ // std-placeholder = "%" [pos-parameter] [flags] [width] [precision] [length] type
+
+ // pos-parameter = number "$"
+ if (ISDIGIT(*np) && *np != '0') {
+ const char *pp = np;
+ while (ISDIGIT(*pp))
+ pp++;
+ if (*pp == '$') {
+ thisarg = atoi(np) + start;
+ positional_arg = true;
+ np = pp + 1;
+ }
+ }
+
+ if (thisarg >= argc) {
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+
+ // flags = *("-" / "+" / "0" / SP)
+ while (true) {
+ if (*np == '-') {
+ flag_minus = true;
+ } else if (*np == '+') {
+ flag_plus = true;
+ } else if (*np == ' ') {
+ flag_space = true;
+ } else if (*np == '0') {
+ flag_zero = true;
+ } else {
+ break;
+ }
+ np++;
+ }
+
+ // width = number / ("*" [pos-parameter])
+ if (ISDIGIT(*np)) {
+ width = atoi(np);
+ while (ISDIGIT(*np))
+ np++;
+ } else if (*np == '*') {
+ bool positional_widtharg = false;
+ int width_arg;
+ np++;
+ // pos-parameter = number "$"
+ if (ISDIGIT(*np) && *np != '0') {
+ const char *pp = np;
+ while (ISDIGIT(*pp))
+ pp++;
+ if (*pp == '$') {
+ width_arg = atoi(np) + start;
+ positional_widtharg = true;
+ np = pp + 1;
+ }
+ }
+ if (!positional_widtharg) {
+ width_arg = nextarg;
+ nextarg++;
+ if (!positional_arg)
+ thisarg++;
+ }
+
+ if (width_arg >= argc || thisarg >= argc) {
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+ width = script_getnum(st, width_arg);
+ }
+
+ // precision = "." (number / ("*" [pos-parameter])) ; (not needed/implemented)
+
+ // length = "hh" / "h" / "l" / "ll" / "L" / "z" / "j" / "t" ; (not needed/implemented)
+
+ // type = "d" / "i" / "u" / "f" / "F" / "e" / "E" / "g" / "G" / "x" / "X" / "o" / "s" / "c" / "p" / "a" / "A"
+ if (buf_len < 16) {
+ RECREATE(buf, char, 16);
+ buf_len = 16;
+ }
+ {
+ int i = 0;
+ memset(buf, '\0', buf_len);
+ buf[i++] = '%';
+ if (flag_minus)
+ buf[i++] = '-';
+ if (flag_plus)
+ buf[i++] = '+';
+ else if (flag_space) // ignored if '+' is specified
+ buf[i++] = ' ';
+ if (flag_zero)
+ buf[i++] = '0';
+ if (width > 0)
+ safesnprintf(buf + i, buf_len - i - 1, "%d", width);
+ }
+ buf[(int)strlen(buf)] = *np;
+ switch (*np) {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'o':
+ // Piggyback printf
+ StrBuf->Printf(out, buf, script_getnum(st, thisarg));
+ break;
+ case 's':
+ // Piggyback printf
+ StrBuf->Printf(out, buf, script_getstr(st, thisarg));
+ break;
+ case 'c':
+ {
+ const char *str = script_getstr(st, thisarg);
+ // Piggyback printf
+ StrBuf->Printf(out, buf, str[0]);
+ }
+ break;
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'p':
+ case 'a':
+ case 'A':
+ ShowWarning("buildin_sprintf: Format %%%c not supported! Skipping...\n", *np);
+ script->reportsrc(st);
+ lastarg = nextarg;
+ p = np + 1;
+ continue;
+ default:
+ ShowError("buildin_sprintf: Invalid format string.\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+ lastarg = nextarg;
+ p = np + 1;
+ }
+
+ // Append the remaining part
+ if (p != NULL)
+ StrBuf->AppendStr(out, p);
+
+ if (buf != NULL)
+ aFree(buf);
+
+ return true;
+}
+
//-----------------------------------------------------------------------------
// buildin functions
//
@@ -5292,23 +5954,49 @@ const char *script_getfuncname(struct script_state *st) {
/// If a dialog doesn't exist yet, one is created.
///
/// mes "<message>";
-BUILDIN(mes)
+static BUILDIN(mes)
{
struct map_session_data *sd = script->rid2sd(st);
- if( sd == NULL )
+
+ if (sd == NULL)
return true;
- if( !script_hasdata(st, 3) ) {// only a single line detected in the script
+ if (script_hasdata(st, 2))
clif->scriptmes(sd, st->oid, script_getstr(st, 2));
- } else {// parse multiple lines as they exist
- int i;
+ else
+ clif->scriptmes(sd, st->oid, "");
- for( i = 2; script_hasdata(st, i); i++ ) {
- // send the message to the client
- clif->scriptmes(sd, st->oid, script_getstr(st, i));
- }
+ return true;
+}
+
+/**
+ * Appends a message to the npc dialog, applying format string conversions (see
+ * sprintf).
+ *
+ * If a dialog doesn't exist yet, one is created.
+ *
+ * @code
+ * mes "<message>";
+ * @endcode
+ */
+static BUILDIN(mesf)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ struct StringBuf buf;
+
+ if (sd == NULL)
+ return true;
+
+ StrBuf->Init(&buf);
+
+ if (!script->sprintf_helper(st, 2, &buf)) {
+ StrBuf->Destroy(&buf);
+ return false;
}
+ clif->scriptmes(sd, st->oid, StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
+
return true;
}
@@ -5316,7 +6004,7 @@ BUILDIN(mes)
/// The dialog text is cleared and the script continues when the button is pressed.
///
/// next;
-BUILDIN(next)
+static BUILDIN(next)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -5329,11 +6017,24 @@ BUILDIN(next)
return true;
}
+/// Clears the NPC dialog and continues the script without press next button.
+///
+/// mesclear();
+static BUILDIN(mesclear)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd != NULL)
+ clif->scriptclear(sd, st->oid);
+
+ return true;
+}
+
/// Ends the script and displays the button 'close' on the npc dialog.
/// The dialog is closed when the button is pressed.
///
/// close;
-BUILDIN(close)
+static BUILDIN(close)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -5348,7 +6049,7 @@ BUILDIN(close)
/// The dialog is closed and the script continues when the button is pressed.
///
/// close2;
-BUILDIN(close2)
+static BUILDIN(close2)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -5368,11 +6069,12 @@ BUILDIN(close2)
/// Counts the number of valid and total number of options in 'str'
/// If max_count > 0 the counting stops when that valid option is reached
/// total is incremented for each option (NULL is supported)
-int menu_countoptions(const char* str, int max_count, int* total)
+static int menu_countoptions(const char *str, int max_count, int *total)
{
int count = 0;
int bogus_total;
+ nullpo_ret(str);
if( total == NULL )
total = &bogus_total;
++(*total);
@@ -5417,7 +6119,7 @@ int menu_countoptions(const char* str, int max_count, int* total)
/// NOTE: the client closes the npc dialog when cancel is pressed
///
/// menu "<option_text>",<target_label>{,"<option_text>",<target_label>,...};
-BUILDIN(menu)
+static BUILDIN(menu)
{
int i;
const char* text;
@@ -5469,11 +6171,11 @@ BUILDIN(menu)
sd->state.menu_or_input = 1;
/* menus beyond this length crash the client (see bugreport:6402) */
- if( StrBuf->Length(&buf) >= 2047 ) {
+ if( StrBuf->Length(&buf) >= MAX_MENU_LENGTH - 1 ) {
struct npc_data * nd = map->id2nd(st->oid);
char* menu;
- CREATE(menu, char, 2048);
- safestrncpy(menu, StrBuf->Value(&buf), 2047);
+ CREATE(menu, char, MAX_MENU_LENGTH);
+ safestrncpy(menu, StrBuf->Value(&buf), MAX_MENU_LENGTH - 1);
ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
clif->scriptmenu(sd, st->oid, menu);
aFree(menu);
@@ -5482,13 +6184,13 @@ BUILDIN(menu)
StrBuf->Destroy(&buf);
- if( sd->npc_menu >= 0xff )
+ if( sd->npc_menu >= MAX_MENU_OPTIONS )
{// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow
- ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
+ ShowWarning("buildin_menu: Too many options specified (current=%d, max=%d).\n", sd->npc_menu, MAX_MENU_OPTIONS - 1);
script->reportsrc(st);
}
}
- else if( sd->npc_menu == 0xff )
+ else if( sd->npc_menu == MAX_MENU_OPTIONS )
{// Cancel was pressed
sd->state.menu_or_input = 0;
st->state = END;
@@ -5526,7 +6228,7 @@ BUILDIN(menu)
st->state = END;
return false;
}
- pc->setreg(sd, script->add_str("@menu"), menu);
+ pc->setreg(sd, script->add_variable("@menu"), menu);
st->pos = script_getnum(st, i + 1);
st->state = GOTO;
}
@@ -5539,7 +6241,7 @@ BUILDIN(menu)
/// select(<option_text>{,<option_text>,...}) -> <selected_option>
///
/// @see menu
-BUILDIN(select)
+static BUILDIN(select)
{
int i;
const char* text;
@@ -5570,11 +6272,11 @@ BUILDIN(select)
sd->state.menu_or_input = 1;
/* menus beyond this length crash the client (see bugreport:6402) */
- if( StrBuf->Length(&buf) >= 2047 ) {
+ if( StrBuf->Length(&buf) >= MAX_MENU_LENGTH - 1 ) {
struct npc_data * nd = map->id2nd(st->oid);
char* menu;
- CREATE(menu, char, 2048);
- safestrncpy(menu, StrBuf->Value(&buf), 2047);
+ CREATE(menu, char, MAX_MENU_LENGTH);
+ safestrncpy(menu, StrBuf->Value(&buf), MAX_MENU_LENGTH - 1);
ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
clif->scriptmenu(sd, st->oid, menu);
aFree(menu);
@@ -5582,107 +6284,31 @@ BUILDIN(select)
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
- if( sd->npc_menu >= 0xff ) {
- ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
+ if( sd->npc_menu >= MAX_MENU_OPTIONS ) {
+ ShowWarning("buildin_select: Too many options specified (current=%d, max=%d).\n", sd->npc_menu, MAX_MENU_OPTIONS - 1);
script->reportsrc(st);
}
- } else if( sd->npc_menu == 0xff ) {// Cancel was pressed
+ } else if(sd->npc_menu == MAX_MENU_OPTIONS) { // Cancel was pressed
sd->state.menu_or_input = 0;
- st->state = END;
- } else {// return selected option
- int menu = 0;
-
- sd->state.menu_or_input = 0;
- for( i = 2; i <= script_lastdata(st); ++i ) {
- text = script_getstr(st, i);
- sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
- if( sd->npc_menu <= 0 )
- break;// entry found
- }
- pc->setreg(sd, script->add_str("@menu"), menu);
- script_pushint(st, menu);
- st->state = RUN;
- }
- return true;
-}
-
-/// Displays a menu with options and returns the selected option.
-/// Behaves like 'menu' without the target labels, except when cancel is
-/// pressed.
-/// When cancel is pressed, the script continues and 255 is returned.
-///
-/// prompt(<option_text>{,<option_text>,...}) -> <selected_option>
-///
-/// @see menu
-BUILDIN(prompt)
-{
- int i;
- const char *text;
- struct map_session_data *sd = script->rid2sd(st);
- if (sd == NULL)
- return true;
-
-#ifdef SECURE_NPCTIMEOUT
- sd->npc_idle_type = NPCT_MENU;
-#endif
-
- if( sd->state.menu_or_input == 0 )
- {
- struct StringBuf buf;
-
- StrBuf->Init(&buf);
- sd->npc_menu = 0;
- for( i = 2; i <= script_lastdata(st); ++i )
- {
- text = script_getstr(st, i);
- if( sd->npc_menu > 0 )
- StrBuf->AppendStr(&buf, ":");
- StrBuf->AppendStr(&buf, text);
- sd->npc_menu += script->menu_countoptions(text, 0, NULL);
- }
-
- st->state = RERUNLINE;
- sd->state.menu_or_input = 1;
-
- /* menus beyond this length crash the client (see bugreport:6402) */
- if( StrBuf->Length(&buf) >= 2047 ) {
- struct npc_data * nd = map->id2nd(st->oid);
- char* menu;
- CREATE(menu, char, 2048);
- safestrncpy(menu, StrBuf->Value(&buf), 2047);
- ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf));
- clif->scriptmenu(sd, st->oid, menu);
- aFree(menu);
- } else
- clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
- StrBuf->Destroy(&buf);
- if( sd->npc_menu >= 0xff )
- {
- ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
- script->reportsrc(st);
+ if (strncmp(get_buildin_name(st), "prompt", 6) == 0) {
+ pc->setreg(sd, script->add_variable("@menu"), MAX_MENU_OPTIONS);
+ script_pushint(st, MAX_MENU_OPTIONS); // XXX: we should really be pushing -1 instead
+ st->state = RUN;
+ } else {
+ st->state = END;
}
- }
- else if( sd->npc_menu == 0xff )
- {// Cancel was pressed
- sd->state.menu_or_input = 0;
- pc->setreg(sd, script->add_str("@menu"), 0xff);
- script_pushint(st, 0xff);
- st->state = RUN;
- }
- else
- {// return selected option
+ } else {// return selected option
int menu = 0;
sd->state.menu_or_input = 0;
- for( i = 2; i <= script_lastdata(st); ++i )
- {
+ for( i = 2; i <= script_lastdata(st); ++i ) {
text = script_getstr(st, i);
sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
- pc->setreg(sd, script->add_str("@menu"), menu);
+ pc->setreg(sd, script->add_variable("@menu"), menu); // TODO: throw a deprecation warning for scripts using @menu
script_pushint(st, menu);
st->state = RUN;
}
@@ -5696,7 +6322,7 @@ BUILDIN(prompt)
/// Jumps to the target script label.
///
/// goto <label>;
-BUILDIN(goto)
+static BUILDIN(goto)
{
if( !data_islabel(script_getdata(st,2)) )
{
@@ -5714,7 +6340,7 @@ BUILDIN(goto)
/*==========================================
* user-defined function call
*------------------------------------------*/
-BUILDIN(callfunc)
+static BUILDIN(callfunc)
{
int i, j;
struct script_retinfo* ri;
@@ -5774,7 +6400,7 @@ BUILDIN(callfunc)
/*==========================================
* subroutine call
*------------------------------------------*/
-BUILDIN(callsub)
+static BUILDIN(callsub)
{
int i,j;
struct script_retinfo* ri;
@@ -5827,7 +6453,7 @@ BUILDIN(callsub)
/// If the argument doesn't exist
///
/// getarg(<index>{,<default_value>}) -> <value>
-BUILDIN(getarg)
+static BUILDIN(getarg)
{
struct script_retinfo* ri;
int idx;
@@ -5861,7 +6487,8 @@ BUILDIN(getarg)
///
/// return;
/// return <value>;
-BUILDIN(return) {
+static BUILDIN(return)
+{
st->state = RETFUNC;
if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp-1].type != C_RETINFO ) {
@@ -5911,7 +6538,7 @@ BUILDIN(return) {
/// If <min> is greater than <max>, their numbers are switched.
/// rand(<range>) -> <int>
/// rand(<min>,<max>) -> <int>
-BUILDIN(rand)
+static BUILDIN(rand)
{
int range;
int min;
@@ -5940,7 +6567,7 @@ BUILDIN(rand)
/*==========================================
* Warp sd to str,x,y or Random or SavePoint/Save
*------------------------------------------*/
-BUILDIN(warp)
+static BUILDIN(warp)
{
int ret;
int x,y;
@@ -5976,7 +6603,7 @@ BUILDIN(warp)
/*==========================================
* Warp a specified area
*------------------------------------------*/
-int buildin_areawarp_sub(struct block_list *bl, va_list ap)
+static int buildin_areawarp_sub(struct block_list *bl, va_list ap)
{
int x2,y2,x3,y3;
unsigned int index;
@@ -5996,6 +6623,9 @@ int buildin_areawarp_sub(struct block_list *bl, va_list ap)
pc->randomwarp(sd, CLR_TELEPORT);
} else if (x3 != 0 && y3 != 0) {
int max, tx, ty, j = 0;
+ int16 m;
+
+ m = map->mapindex2mapid(index);
// choose a suitable max number of attempts
if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 )
@@ -6006,7 +6636,7 @@ int buildin_areawarp_sub(struct block_list *bl, va_list ap)
tx = rnd()%(x3-x2+1)+x2;
ty = rnd()%(y3-y2+1)+y2;
j++;
- } while (map->getcell(index, bl, tx, ty, CELL_CHKNOPASS) && j < max);
+ } while (map->getcell(m, bl, tx, ty, CELL_CHKNOPASS) && j < max);
pc->setpos(sd, index, tx, ty, CLR_OUTSIGHT);
} else {
@@ -6014,7 +6644,7 @@ int buildin_areawarp_sub(struct block_list *bl, va_list ap)
}
return 0;
}
-BUILDIN(areawarp)
+static BUILDIN(areawarp)
{
int16 m, x0,y0,x1,y1, x2,y2,x3=0,y3=0;
unsigned int index;
@@ -6056,7 +6686,7 @@ BUILDIN(areawarp)
/*==========================================
* areapercentheal <map>,<x1>,<y1>,<x2>,<y2>,<hp>,<sp>
*------------------------------------------*/
-int buildin_areapercentheal_sub(struct block_list *bl, va_list ap)
+static int buildin_areapercentheal_sub(struct block_list *bl, va_list ap)
{
int hp = va_arg(ap, int);
int sp = va_arg(ap, int);
@@ -6070,7 +6700,8 @@ int buildin_areapercentheal_sub(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(areapercentheal) {
+static BUILDIN(areapercentheal)
+{
int hp,sp,m;
const char *mapname;
int x0,y0,x1,y1;
@@ -6096,7 +6727,8 @@ BUILDIN(areapercentheal) {
* another player npc-session.
* Using: warpchar "mapname",x,y,Char_ID;
*------------------------------------------*/
-BUILDIN(warpchar) {
+static BUILDIN(warpchar)
+{
int x,y,a;
const char *str;
struct map_session_data *sd;
@@ -6120,160 +6752,209 @@ BUILDIN(warpchar) {
return true;
}
-/*==========================================
- * Warpparty - [Fredzilla] [Paradox924X]
- * Syntax: warpparty "to_mapname",x,y,Party_ID,{"from_mapname"};
- * If 'from_mapname' is specified, only the party members on that map will be warped
- *------------------------------------------*/
-BUILDIN(warpparty)
+
+/**
+ * Warps a party to a specific/random map or save point.
+ *
+ * @code{.herc}
+ * warpparty("<to map name>", <x>, <y>, <party id>{{, <ignore mapflags>}, "<from map name>"{, <include leader>}});
+ * @endcode
+ *
+ **/
+static BUILDIN(warpparty)
{
- struct map_session_data *sd = NULL;
- struct map_session_data *pl_sd;
- struct party_data* p;
- int type;
- int map_index;
- int i;
+ const int p_id = script_getnum(st, 5);
+ struct party_data *p = party->search(p_id);
- const char* str = script_getstr(st,2);
- int x = script_getnum(st,3);
- int y = script_getnum(st,4);
- int p_id = script_getnum(st,5);
- const char* str2 = NULL;
- if ( script_hasdata(st,6) )
- str2 = script_getstr(st,6);
+ if (p == NULL) {
+ ShowError("script:%s: Party not found! (%d)\n", script->getfuncname(st), p_id);
+ script_pushint(st, 0);
+ return false;
+ }
- p = party->search(p_id);
- if(!p)
- return true;
+ const char *m_name_to = script_getstr(st, 2);
+ const int type = (strcmp(m_name_to, "Random") == 0) ? 0 :
+ (strcmp(m_name_to, "SavePointAll") == 0) ? 1 :
+ (strcmp(m_name_to, "SavePoint") == 0) ? 2 :
+ (strcmp(m_name_to, "Leader") == 0) ? 3 : 4;
+ int map_index = 0;
- type = ( strcmp(str,"Random")==0 ) ? 0
- : ( strcmp(str,"SavePointAll")==0 ) ? 1
- : ( strcmp(str,"SavePoint")==0 ) ? 2
- : ( strcmp(str,"Leader")==0 ) ? 3
- : 4;
+ if (type == 4 && (map_index = script->mapindexname2id(st, m_name_to)) == 0) {
+ ShowError("script:%s: Target map not found! (%s)\n", script->getfuncname(st), m_name_to);
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
- case 3:
- for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++);
- if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online
- return true;
- pl_sd = p->data[i].sd;
- map_index = pl_sd->mapindex;
- x = pl_sd->bl.x;
- y = pl_sd->bl.y;
- break;
- case 4:
- map_index = script->mapindexname2id(st,str);
- break;
- case 2:
- //"SavePoint" uses save point of the currently attached player
- if (( sd = script->rid2sd(st) ) == NULL )
- return true;
- /* Fall through */
- default:
- map_index = 0;
- break;
+ int x = script_getnum(st, 3);
+ int y = script_getnum(st, 4);
+ struct map_session_data *p_sd;
+
+ if (type == 3) {
+ int idx;
+
+ ARR_FIND(0, MAX_PARTY, idx, p->party.member[idx].leader == 1);
+
+ if (idx == MAX_PARTY || (p_sd = p->data[idx].sd) == NULL) {
+ ShowError("script:%s: Party leader not found!\n", script->getfuncname(st));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ map_index = p_sd->mapindex;
+ x = p_sd->bl.x;
+ y = p_sd->bl.y;
+ } else if (type == 2) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ ShowError("script:%s: No character attached for warp to save point!\n",
+ script->getfuncname(st));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ map_index = sd->status.save_point.map;
+ x = sd->status.save_point.x;
+ y = sd->status.save_point.y;
}
- for (i = 0; i < MAX_PARTY; i++) {
- if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id )
+ const int offset = (script_hasdata(st, 6) && script_isinttype(st, 6)) ? 1 : 0;
+ const bool ignore_mapflags = (offset == 1 && script_getnum(st, 6) != 0);
+ const char *m_name_from = script_hasdata(st, 6 + offset) ? script_getstr(st, 6 + offset) : NULL;
+ const bool include_leader = script_hasdata(st, 7 + offset) ? script_getnum(st, 7 + offset) : true;
+
+ if (m_name_from != NULL && script->mapindexname2id(st, m_name_from) == 0) {
+ ShowError("script:%s: Source map not found! (%s)\n", script->getfuncname(st), m_name_from);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ for (int i = 0; i < MAX_PARTY; i++) {
+ if ((p_sd = p->data[i].sd) == NULL || p_sd->status.party_id != p_id || pc_isdead(p_sd))
continue;
- if( str2 && strcmp(str2, map->list[pl_sd->bl.m].name) != 0 )
+ if (p->party.member[i].online == 0 || (!include_leader && p->party.member[i].leader == 1))
continue;
- if( pc_isdead(pl_sd) )
+ if (m_name_from != NULL && strcmp(m_name_from, map->list[p_sd->bl.m].name) != 0)
continue;
- switch( type )
- {
- case 0: // Random
- if(!map->list[pl_sd->bl.m].flag.nowarp)
- pc->randomwarp(pl_sd,CLR_TELEPORT);
- break;
- case 1: // SavePointAll
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
- break;
- case 2: // SavePoint
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
- break;
- case 3: // Leader
- case 4: // m,x,y
- if(!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
- pc->setpos(pl_sd,map_index,x,y,CLR_TELEPORT);
- break;
+ if (!ignore_mapflags) {
+ if (((type == 0 || type > 2) && map->list[p_sd->bl.m].flag.nowarp == 1) ||
+ (type > 0 && map->list[p_sd->bl.m].flag.noreturn == 1))
+ continue;
+ }
+
+ if (type == 1) {
+ map_index = p_sd->status.save_point.map;
+ x = p_sd->status.save_point.x;
+ y = p_sd->status.save_point.y;
}
+
+ if (type > 0)
+ pc->setpos(p_sd, map_index, x, y, CLR_TELEPORT);
+ else
+ pc->randomwarp(p_sd, CLR_TELEPORT);
}
+ script_pushint(st, 1);
return true;
}
-/*==========================================
- * Warpguild - [Fredzilla]
- * Syntax: warpguild "mapname",x,y,Guild_ID;
- *------------------------------------------*/
-BUILDIN(warpguild)
+
+/**
+ * Warps a guild to a specific/random map or save point.
+ *
+ * @code{.herc}
+ * warpguild("<to map name>", <x>, <y>, <guild id>{{, <ignore mapflags>}, "<from map name>"});
+ * @endcode
+ *
+ **/
+static BUILDIN(warpguild)
{
- struct map_session_data *sd = NULL;
- struct map_session_data *pl_sd;
- struct guild* g;
- struct s_mapiterator* iter;
- int type;
+ const int g_id = script_getnum(st, 5);
+ struct guild *g = guild->search(g_id);
- const char* str = script_getstr(st,2);
- int x = script_getnum(st,3);
- int y = script_getnum(st,4);
- int gid = script_getnum(st,5);
+ if (g == NULL) {
+ ShowError("script:%s: Guild not found! (%d)\n", script->getfuncname(st), g_id);
+ script_pushint(st, 0);
+ return false;
+ }
- g = guild->search(gid);
- if( g == NULL )
- return true;
+ const char *m_name_to = script_getstr(st, 2);
+ const int type = (strcmp(m_name_to, "Random") == 0) ? 0 :
+ (strcmp(m_name_to, "SavePointAll") == 0) ? 1 :
+ (strcmp(m_name_to, "SavePoint") == 0) ? 2 : 3;
+ int map_index = 0;
- type = ( strcmp(str,"Random")==0 ) ? 0
- : ( strcmp(str,"SavePointAll")==0 ) ? 1
- : ( strcmp(str,"SavePoint")==0 ) ? 2
- : 3;
+ if (type == 3 && (map_index = script->mapindexname2id(st, m_name_to)) == 0) {
+ ShowError("script:%s: Target map not found! (%s)\n", script->getfuncname(st), m_name_to);
+ script_pushint(st, 0);
+ return false;
+ }
- if( type == 2 && ( sd = script->rid2sd(st) ) == NULL )
- {// "SavePoint" uses save point of the currently attached player
- return true;
+ int x = script_getnum(st, 3);
+ int y = script_getnum(st, 4);
+
+ if (type == 2) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ ShowError("script:%s: No character attached for warp to save point!\n",
+ script->getfuncname(st));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ map_index = sd->status.save_point.map;
+ x = sd->status.save_point.x;
+ y = sd->status.save_point.y;
}
- iter = mapit_getallusers();
- for (pl_sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if( pl_sd->status.guild_id != gid )
+ const int offset = (script_hasdata(st, 6) && script_isinttype(st, 6)) ? 1 : 0;
+ const bool ignore_mapflags = (offset == 1 && script_getnum(st, 6) != 0);
+ const char *m_name_from = script_hasdata(st, 6 + offset) ? script_getstr(st, 6 + offset) : NULL;
+
+ if (m_name_from != NULL && script->mapindexname2id(st, m_name_from) == 0) {
+ ShowError("script:%s: Source map not found! (%s)\n", script->getfuncname(st), m_name_from);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ for (int i = 0; i < MAX_GUILD; i++) {
+ struct map_session_data *g_sd = g->member[i].sd;
+
+ if (g->member[i].online == 0 || g_sd == NULL || g_sd->status.guild_id != g_id || pc_isdead(g_sd))
continue;
- switch( type )
- {
- case 0: // Random
- if(!map->list[pl_sd->bl.m].flag.nowarp)
- pc->randomwarp(pl_sd,CLR_TELEPORT);
- break;
- case 1: // SavePointAll
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
- break;
- case 2: // SavePoint
- if(!map->list[pl_sd->bl.m].flag.noreturn)
- pc->setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
- break;
- case 3: // m,x,y
- if(!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
- pc->setpos(pl_sd,script->mapindexname2id(st,str),x,y,CLR_TELEPORT);
- break;
+ if (m_name_from != NULL && strcmp(m_name_from, map->list[g_sd->bl.m].name) != 0)
+ continue;
+
+ if (!ignore_mapflags) {
+ if (((type == 0 || type > 2) && map->list[g_sd->bl.m].flag.nowarp == 1) ||
+ (type > 0 && map->list[g_sd->bl.m].flag.noreturn == 1))
+ continue;
+ }
+
+ if (type == 1) {
+ map_index = g_sd->status.save_point.map;
+ x = g_sd->status.save_point.x;
+ y = g_sd->status.save_point.y;
}
+
+ if (type > 0)
+ pc->setpos(g_sd, map_index, x, y, CLR_TELEPORT);
+ else
+ pc->randomwarp(g_sd, CLR_TELEPORT);
}
- mapit->free(iter);
+ script_pushint(st, 1);
return true;
}
+
/*==========================================
* Force Heal a player (hp and sp)
*------------------------------------------*/
-BUILDIN(heal)
+static BUILDIN(heal)
{
int hp,sp;
struct map_session_data *sd = script->rid2sd(st);
@@ -6282,13 +6963,13 @@ BUILDIN(heal)
hp=script_getnum(st,2);
sp=script_getnum(st,3);
- status->heal(&sd->bl, hp, sp, 1);
+ status->heal(&sd->bl, hp, sp, STATUS_HEAL_FORCED);
return true;
}
/*==========================================
* Heal a player by item (get vit bonus etc)
*------------------------------------------*/
-BUILDIN(itemheal)
+static BUILDIN(itemheal)
{
struct map_session_data *sd;
int hp,sp;
@@ -6303,14 +6984,15 @@ BUILDIN(itemheal)
}
sd = script->rid2sd(st);
- if (!sd) return true;
+ if (sd == NULL)
+ return true;
pc->itemheal(sd,sd->itemid,hp,sp);
return true;
}
/*==========================================
*
*------------------------------------------*/
-BUILDIN(percentheal)
+static BUILDIN(percentheal)
{
int hp,sp;
struct map_session_data *sd;
@@ -6325,33 +7007,36 @@ BUILDIN(percentheal)
}
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;
#ifdef RENEWAL
if( sd->sc.data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
- pc->percentheal(sd,hp,sp);
+ if (sd->sc.data[SC_BITESCAR]) {
+ hp = 0;
+ }
+ pc->percentheal(sd, hp, sp);
return true;
}
/*==========================================
*
*------------------------------------------*/
-BUILDIN(jobchange)
+static BUILDIN(jobchange)
{
- int job, upper=-1;
+ int class, upper=-1;
- job=script_getnum(st,2);
+ class = script_getnum(st,2);
if( script_hasdata(st,3) )
upper=script_getnum(st,3);
- if (pc->db_checkid(job)) {
+ if (pc->db_checkid(class)) {
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- pc->jobchange(sd, job, upper);
+ pc->jobchange(sd, class, upper);
}
return true;
@@ -6360,66 +7045,67 @@ BUILDIN(jobchange)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(jobname)
+static BUILDIN(jobname)
{
- int class_=script_getnum(st,2);
- script_pushconststr(st, pc->job_name(class_));
+ int class = script_getnum(st,2);
+ script_pushconststr(st, pc->job_name(class));
return true;
}
-/// Get input from the player.
-/// For numeric inputs the value is capped to the range [min,max]. Returns 1 if
-/// the value was higher than 'max', -1 if lower than 'min' and 0 otherwise.
-/// For string inputs it returns 1 if the string was longer than 'max', -1 is
-/// shorter than 'min' and 0 otherwise.
-///
-/// input(<var>{,<min>{,<max>}}) -> <int>
-BUILDIN(input)
+/*
+ * Get input from the player.
+ * For numeric inputs the value is capped to the range [min,max]. Returns 1 if
+ * the value was higher than 'max', -1 if lower than 'min' and 0 otherwise.
+ * For string inputs it returns 1 if the string was longer than 'max', -1 is
+ * shorter than 'min' and 0 otherwise.
+ *
+ * input(<var>{,<min>{,<max>}}) -> <int>
+ */
+static BUILDIN(input)
{
- struct script_data* data;
- int64 uid;
- const char* name;
- int min;
- int max;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- data = script_getdata(st,2);
- if( !data_isreference(data) ) {
+ struct script_data *data = script_getdata(st, 2);
+ if (!data_isreference(data)) {
ShowError("script:input: not a variable\n");
script->reportdata(data);
st->state = END;
return false;
}
- uid = reference_getuid(data);
- name = reference_getname(data);
- min = (script_hasdata(st,3) ? script_getnum(st,3) : script->config.input_min_value);
- max = (script_hasdata(st,4) ? script_getnum(st,4) : script->config.input_max_value);
+
+ int64 uid = reference_getuid(data);
+ const char *name = reference_getname(data);
+ int min = (script_hasdata(st, 3) ? script_getnum(st, 3) : script->config.input_min_value);
+ int max = (script_hasdata(st, 4) ? script_getnum(st, 4) : script->config.input_max_value);
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_WAIT;
#endif
- if( !sd->state.menu_or_input ) {
+ if (!sd->state.menu_or_input) {
// first invocation, display npc input box
sd->state.menu_or_input = 1;
st->state = RERUNLINE;
- if( is_string_variable(name) )
- clif->scriptinputstr(sd,st->oid);
- else
- clif->scriptinput(sd,st->oid);
+ if (is_string_variable(name)) {
+ clif->scriptinputstr(sd, st->oid);
+ } else {
+ sd->npc_amount_min = min;
+ sd->npc_amount_max = max;
+ clif->scriptinput(sd, st->oid);
+ }
} else {
// take received text/value and store it in the designated variable
sd->state.menu_or_input = 0;
if (is_string_variable(name)) {
int len = (int)strlen(sd->npc_str);
- script->set_reg(st, sd, uid, name, sd->npc_str, script_getref(st,2));
+ script->set_reg(st, sd, uid, name, sd->npc_str, script_getref(st, 2));
script_pushint(st, (len > max ? 1 : len < min ? -1 : 0));
} else {
int amount = sd->npc_amount;
script->set_reg(st, sd, uid, name, (const void *)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2));
- script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0));
+ script_pushint(st, sd->npc_input_capped_range);
}
st->state = RUN;
}
@@ -6427,13 +7113,13 @@ BUILDIN(input)
}
// declare the copyarray method here for future reference
-BUILDIN(copyarray);
+static BUILDIN(copyarray);
/// Sets the value of a variable.
/// The value is converted to the type of the variable.
///
/// set(<variable>,<value>) -> <variable>
-BUILDIN(__setr)
+static BUILDIN(__setr)
{
struct map_session_data *sd = NULL;
struct script_data* data;
@@ -6441,6 +7127,7 @@ BUILDIN(__setr)
int64 num;
const char* name;
char prefix;
+ struct reg_db *ref;
data = script_getdata(st,2);
//datavalue = script_getdata(st,3);
@@ -6453,11 +7140,11 @@ BUILDIN(__setr)
num = reference_getuid(data);
name = reference_getname(data);
+ ref = reference_getref(data);
prefix = *name;
if (not_server_variable(prefix)) {
- sd = script->rid2sd(st);
- if (sd == NULL) {
+ if (ref == NULL && (sd = script->rid2sd(st)) == NULL) {
ShowError("script:set: no player attached for player variable '%s'\n", name);
return true;
}
@@ -6505,9 +7192,9 @@ BUILDIN(__setr)
}
if (is_string_variable(name))
- script->set_reg(st, sd, num, name, script_getstr(st, 3), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, script_getstr(st, 3), ref);
else
- script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), ref);
return true;
}
@@ -6520,7 +7207,7 @@ BUILDIN(__setr)
/// ex: setarray arr[1],1,2,3;
///
/// setarray <array variable>,<value1>{,<value2>...};
-BUILDIN(setarray)
+static BUILDIN(setarray)
{
struct script_data* data;
const char* name;
@@ -6570,7 +7257,7 @@ BUILDIN(setarray)
/// ex: cleararray arr[0],0,1;
///
/// cleararray <array variable>,<value>,<count>;
-BUILDIN(cleararray)
+static BUILDIN(cleararray)
{
struct script_data* data;
const char* name;
@@ -6618,7 +7305,7 @@ BUILDIN(cleararray)
/// ex: copyarray arr[0],arr[2],2;
///
/// copyarray <destination array variable>,<source array variable>,<count>;
-BUILDIN(copyarray)
+static BUILDIN(copyarray)
{
struct script_data* data1;
struct script_data* data2;
@@ -6705,7 +7392,7 @@ BUILDIN(copyarray)
/// ex: getarraysize(arr[3])
///
/// getarraysize(<array variable>) -> <int>
-BUILDIN(getarraysize)
+static BUILDIN(getarraysize)
{
struct script_data* data;
@@ -6722,17 +7409,33 @@ BUILDIN(getarraysize)
script_pushint(st, script->array_highest_key(st,st->rid ? script->rid2sd(st) : NULL,reference_getname(data),reference_getref(data)));
return true;
}
-int script_array_index_cmp(const void *a, const void *b)
+static int script_array_index_cmp(const void *a, const void *b)
{
return (*(const unsigned int *)a - *(const unsigned int *)b); // FIXME: Is the unsigned difference really intended here?
}
+static BUILDIN(getarrayindex)
+{
+ struct script_data *data = script_getdata(st, 2);
+
+ if (!data_isreference(data) || reference_toconstant(data))
+ {
+ ShowError("script:getarrayindex: not a variable\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;// not a variable
+ }
+
+ script_pushint(st, reference_getindex(data));
+ return true;
+}
+
/// Deletes count or all the elements in an array, from the starting index.
/// ex: deletearray arr[4],2;
///
/// deletearray <array variable>;
/// deletearray <array variable>,<count>;
-BUILDIN(deletearray)
+static BUILDIN(deletearray)
{
struct script_data* data;
const char* name;
@@ -6846,7 +7549,7 @@ BUILDIN(deletearray)
/// Equivalent to var[index].
///
/// getelementofarray(<array variable>,<index>) -> <variable reference>
-BUILDIN(getelementofarray)
+static BUILDIN(getelementofarray)
{
struct script_data* data;
int32 id;
@@ -6865,7 +7568,7 @@ BUILDIN(getelementofarray)
id = reference_getid(data);
i = script_getnum(st, 3);
- if (i < 0 || i >= SCRIPT_MAX_ARRAYSIZE) {
+ if (i < 0 || i > SCRIPT_MAX_ARRAYSIZE) {
ShowWarning("script:getelementofarray: index out of range (%"PRId64")\n", i);
script->reportdata(data);
script_pushnil(st);
@@ -6884,7 +7587,7 @@ BUILDIN(getelementofarray)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(setlook)
+static BUILDIN(setlook)
{
int type,val;
struct map_session_data *sd;
@@ -6901,7 +7604,7 @@ BUILDIN(setlook)
return true;
}
-BUILDIN(changelook)
+static BUILDIN(changelook)
{ // As setlook but only client side
int type,val;
struct map_session_data *sd;
@@ -6921,7 +7624,7 @@ BUILDIN(changelook)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(cutin)
+static BUILDIN(cutin)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -6934,7 +7637,7 @@ BUILDIN(cutin)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(viewpoint)
+static BUILDIN(viewpoint)
{
int type,x,y,id,color;
struct map_session_data *sd;
@@ -6957,8 +7660,8 @@ BUILDIN(viewpoint)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(countitem) {
- int nameid, i;
+static BUILDIN(countitem)
+{
int count = 0;
struct item_data* id = NULL;
@@ -6980,11 +7683,12 @@ BUILDIN(countitem) {
return false;
}
- nameid = id->nameid;
+ int nameid = id->nameid;
- for(i = 0; i < MAX_INVENTORY; i++)
- if(sd->status.inventory[i].nameid == nameid)
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].nameid == nameid)
count += sd->status.inventory[i].amount;
+ }
script_pushint(st,count);
return true;
@@ -6994,10 +7698,10 @@ BUILDIN(countitem) {
* countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus]
* returns number of items that meet the conditions
*------------------------------------------*/
-BUILDIN(countitem2) {
+static BUILDIN(countitem2)
+{
int nameid, iden, ref, attr, c1, c2, c3, c4;
int count = 0;
- int i;
struct item_data* id = NULL;
struct map_session_data *sd = script->rid2sd(st);
@@ -7022,12 +7726,12 @@ BUILDIN(countitem2) {
iden = script_getnum(st,3);
ref = script_getnum(st,4);
attr = script_getnum(st,5);
- c1 = (short)script_getnum(st,6);
- c2 = (short)script_getnum(st,7);
- c3 = (short)script_getnum(st,8);
- c4 = (short)script_getnum(st,9);
+ c1 = script_getnum(st,6);
+ c2 = script_getnum(st,7);
+ c3 = script_getnum(st,8);
+ c4 = script_getnum(st,9);
- for(i = 0; i < MAX_INVENTORY; i++)
+ for (int i = 0; i < sd->status.inventorySize; i++)
if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL &&
sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid &&
sd->status.inventory[i].identify == iden && sd->status.inventory[i].refine == ref &&
@@ -7042,13 +7746,72 @@ BUILDIN(countitem2) {
}
/*==========================================
+ * countnameditem(item ID, { <Char Name / ID> })
+ * returns number of named items.
+ *------------------------------------------*/
+static BUILDIN(countnameditem)
+{
+ int count = 0;
+ struct item_data* id = NULL;
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 3)) {
+ if (script_isstringtype(st, 3)) {
+ // Character name was given
+ sd = script->nick2sd(st, script_getstr(st, 3));
+ } else {
+ // Character ID was given
+ sd = script->charid2sd(st, script_getnum(st, 3));
+ }
+ } else {
+ // Use RID by default if no name was provided
+ sd = script->rid2sd(st);
+ }
+
+ // Player not attached
+ if (sd == NULL) {
+ return true;
+ }
+
+ if (script_isstringtype(st, 2)) {
+ // Get item from DB via item name
+ id = itemdb->search_name(script_getstr(st, 2));
+ } else {
+ // Get item from DB via item ID
+ id = itemdb->exists(script_getnum(st, 2));
+ }
+
+ if (id == NULL) {
+ ShowError("buildin_countnameditem: Invalid item '%s'.\n", script_getstr(st, 2)); // returns string, regardless of what it was
+ script_pushint(st, 0);
+ return false;
+ }
+
+ for (int i = 0; i < MAX_INVENTORY; i++) {
+ if (sd->status.inventory[i].nameid > 0 &&
+ sd->inventory_data[i] != NULL &&
+ sd->status.inventory[i].amount > 0 &&
+ sd->status.inventory[i].nameid == id->nameid &&
+ sd->status.inventory[i].card[0] == CARD0_CREATE &&
+ sd->status.inventory[i].card[2] == sd->status.char_id &&
+ sd->status.inventory[i].card[3] == sd->status.char_id >> 16)
+ {
+ count += sd->status.inventory[i].amount;
+ }
+ }
+
+ script_pushint(st, count);
+ return true;
+}
+
+/*==========================================
* Check if item with this amount can fit in inventory
* Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY)
* Return
* 0 : fail
* 1 : success (npc side only)
*------------------------------------------*/
-BUILDIN(checkweight)
+static BUILDIN(checkweight)
{
int slots, amount2=0;
unsigned int weight=0, i, nbargs;
@@ -7130,7 +7893,7 @@ BUILDIN(checkweight)
return true;
}
-BUILDIN(checkweight2)
+static BUILDIN(checkweight2)
{
//variable sub checkweight
int i=0, amount2=0, slots=0, weight=0;
@@ -7234,7 +7997,8 @@ BUILDIN(checkweight2)
* getitembound <item id>,<amount>,<type>{,<account ID>};
* getitembound "<item id>",<amount>,<type>{,<account ID>};
*------------------------------------------*/
-BUILDIN(getitem) {
+static BUILDIN(getitem)
+{
int nameid,amount,get_count,i,flag = 0, offset = 0;
struct item it;
struct map_session_data *sd;
@@ -7308,7 +8072,7 @@ BUILDIN(getitem) {
if ((flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) {
clif->additem(sd, 0, 0, flag);
if( pc->candrop(sd,&it) )
- map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
@@ -7319,7 +8083,7 @@ BUILDIN(getitem) {
/*==========================================
*
*------------------------------------------*/
-BUILDIN(getitem2)
+static BUILDIN(getitem2)
{
int nameid,amount,flag = 0, offset = 0;
int iden,ref,attr,c1,c2,c3,c4, bound = 0;
@@ -7357,10 +8121,10 @@ BUILDIN(getitem2)
iden=script_getnum(st,4);
ref=script_getnum(st,5);
attr=script_getnum(st,6);
- c1=(short)script_getnum(st,7);
- c2=(short)script_getnum(st,8);
- c3=(short)script_getnum(st,9);
- c4=(short)script_getnum(st,10);
+ c1 = script_getnum(st,7);
+ c2 = script_getnum(st,8);
+ c3 = script_getnum(st,9);
+ c4 = script_getnum(st,10);
if (bound && (itemdb_type(nameid) == IT_PETEGG || itemdb_type(nameid) == IT_PETARMOR)) {
ShowError("script_getitembound2: can't bind a pet egg/armor! Type=%d\n",bound);
@@ -7399,10 +8163,10 @@ BUILDIN(getitem2)
item_tmp.refine=ref;
item_tmp.attribute=attr;
item_tmp.bound=(unsigned char)bound;
- item_tmp.card[0]=(short)c1;
- item_tmp.card[1]=(short)c2;
- item_tmp.card[2]=(short)c3;
- item_tmp.card[3]=(short)c4;
+ item_tmp.card[0] = c1;
+ item_tmp.card[1] = c2;
+ item_tmp.card[2] = c3;
+ item_tmp.card[3] = c4;
//Check if it's stackable.
if (!itemdb->isstackable(nameid))
@@ -7416,7 +8180,7 @@ BUILDIN(getitem2)
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
clif->additem(sd, 0, 0, flag);
if( pc->candrop(sd,&item_tmp) )
- map->addflooritem(&sd->bl, &item_tmp, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
@@ -7429,7 +8193,8 @@ BUILDIN(getitem2)
* rentitem <item id>,<seconds>
* rentitem "<item name>",<seconds>
*------------------------------------------*/
-BUILDIN(rentitem) {
+static BUILDIN(rentitem)
+{
struct map_session_data *sd;
struct item it;
int seconds;
@@ -7477,7 +8242,8 @@ BUILDIN(rentitem) {
* Returned Qty is always 1, only works on equip-able
* equipment
*------------------------------------------*/
-BUILDIN(getnameditem) {
+static BUILDIN(getnameditem)
+{
int nameid;
struct item item_tmp;
struct map_session_data *sd, *tsd;
@@ -7517,12 +8283,12 @@ BUILDIN(getnameditem) {
}
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid=nameid;
- item_tmp.amount=1;
- item_tmp.identify=1;
- item_tmp.card[0]=CARD0_CREATE; //we don't use 255! because for example SIGNED WEAPON shouldn't get TOP10 BS Fame bonus [Lupus]
- item_tmp.card[2]=tsd->status.char_id;
- item_tmp.card[3]=tsd->status.char_id >> 16;
+ item_tmp.nameid = nameid;
+ item_tmp.amount = 1;
+ item_tmp.identify = 1;
+ item_tmp.card[0] = CARD0_CREATE; //we don't use 255! because for example SIGNED WEAPON shouldn't get TOP10 BS Fame bonus [Lupus]
+ item_tmp.card[2] = GetWord(tsd->status.char_id, 0);
+ item_tmp.card[3] = GetWord(tsd->status.char_id, 1);
if(pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT)) {
script_pushint(st,0);
return true; //Failed to add item, we will not drop if they don't fit
@@ -7536,7 +8302,8 @@ BUILDIN(getnameditem) {
* gets a random item ID from an item group [Skotlex]
* groupranditem group_num
*------------------------------------------*/
-BUILDIN(grouprandomitem) {
+static BUILDIN(grouprandomitem)
+{
struct item_data *data;
int nameid;
@@ -7566,7 +8333,7 @@ BUILDIN(grouprandomitem) {
/*==========================================
*
*------------------------------------------*/
-BUILDIN(makeitem)
+static BUILDIN(makeitem)
{
int nameid,amount;
int x,y,m;
@@ -7609,7 +8376,91 @@ BUILDIN(makeitem)
item_tmp.nameid = nameid;
item_tmp.identify=1;
- map->addflooritem(NULL, &item_tmp, amount, m, x, y, 0, 0, 0, 0);
+ map->addflooritem(NULL, &item_tmp, amount, m, x, y, 0, 0, 0, 0, false);
+
+ return true;
+}
+
+/*==========================================
+ * makeitem2 <item id>, <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>, {"<map name>", <X>, <Y>, <range>};
+ *------------------------------------------*/
+static BUILDIN(makeitem2)
+{
+ struct map_session_data *sd = NULL;
+ struct item_data *i_data;
+ int nameid = 0, amount;
+ int16 x, y, m = -1, range;
+ struct item item_tmp;
+
+ if (script_isstringtype(st, 2)) {
+ const char *name = script_getstr(st, 2);
+ struct item_data *item_data = itemdb->search_name(name);
+ if (item_data != NULL)
+ nameid = item_data->nameid;
+ } else {
+ nameid = script_getnum(st, 2);
+ }
+
+ i_data = itemdb->exists(nameid);
+ if (i_data == NULL) {
+ ShowError("makeitem2: Unknown item %d requested.\n", nameid);
+ return true;
+ }
+
+ if (script_hasdata(st, 11)) {
+ m = map->mapname2mapid(script_getstr(st, 11));
+ } else {
+ sd = script->rid2sd(st);
+ if (sd == NULL)
+ return true;
+ m = sd->bl.m;
+ }
+
+ if (m == -1) {
+ ShowError("makeitem2: Nonexistant map requested.\n");
+ return true;
+ }
+
+ x = (script_hasdata(st, 12) ? script_getnum(st, 12) : 0);
+ y = (script_hasdata(st, 13) ? script_getnum(st, 13) : 0);
+
+ // pick random position on map
+ if (x <= 0 || x >= map->list[m].xs || y <= 0 || y >= map->list[m].ys) {
+ sd = map->id2sd(st->rid);
+ if ((x < 0 || y < 0) && sd == NULL) {
+ x = 0;
+ y = 0;
+ map->search_freecell(NULL, m, &x, &y, -1, -1, 1);
+ } else {
+ range = (script_hasdata(st, 14) ? cap_value(script_getnum(st, 14), 1, battle_config.area_size) : 3);
+ map->search_freecell(&sd->bl, sd->bl.m, &x, &y, range, range, 0); // Locate spot next to player.
+ }
+ }
+
+ // if equip or weapon or egg type only drop one.
+ switch (i_data->type) {
+ case IT_ARMOR:
+ case IT_WEAPON:
+ case IT_PETARMOR:
+ case IT_PETEGG:
+ amount = 1;
+ break;
+ default:
+ amount = cap_value(script_getnum(st, 3), 1, MAX_AMOUNT);
+ break;
+ }
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = nameid;
+ item_tmp.identify = script_getnum(st, 4);
+ item_tmp.refine = cap_value(script_getnum(st, 5), 0, MAX_REFINE);
+ item_tmp.attribute = script_getnum(st, 6);
+ item_tmp.card[0] = script_getnum(st, 7);
+ item_tmp.card[1] = script_getnum(st, 8);
+ item_tmp.card[2] = script_getnum(st, 9);
+ item_tmp.card[3] = script_getnum(st, 10);
+
+ map->addflooritem(NULL, &item_tmp, amount, m, x, y, 0, 0, 0, 0, false);
return true;
}
@@ -7617,10 +8468,14 @@ BUILDIN(makeitem)
/// Counts / deletes the current item given by idx.
/// Used by buildin_delitem_search
/// Relies on all input data being already fully valid.
-void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items)
+static void buildin_delitem_delete(struct map_session_data *sd, int idx, int *amount, bool delete_items)
{
int delamount;
- struct item* inv = &sd->status.inventory[idx];
+ struct item* inv;
+
+ nullpo_retv(sd);
+ nullpo_retv(amount);
+ inv = &sd->status.inventory[idx];
delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount;
@@ -7641,12 +8496,14 @@ void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, b
/// Relies on all input data being already fully valid.
/// @param exact_match will also match item attributes and cards, not just name id
/// @return true when all items could be deleted, false when there were not enough items to delete
-bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match)
+static bool buildin_delitem_search(struct map_session_data *sd, struct item *it, bool exact_match)
{
bool delete_items = false;
int i, amount;
struct item* inv;
+ nullpo_retr(false, sd);
+ nullpo_retr(false, it);
// prefer always non-equipped items
it->equip = 0;
@@ -7748,7 +8605,7 @@ bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool e
///
/// delitem <item id>,<amount>{,<account id>}
/// delitem "<item name>",<amount>{,<account id>}
-BUILDIN(delitem)
+static BUILDIN(delitem)
{
struct map_session_data *sd;
struct item it;
@@ -7805,7 +8662,7 @@ BUILDIN(delitem)
///
/// delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
/// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
-BUILDIN(delitem2)
+static BUILDIN(delitem2)
{
struct map_session_data *sd;
struct item it;
@@ -7846,10 +8703,10 @@ BUILDIN(delitem2)
it.identify=script_getnum(st,4);
it.refine=script_getnum(st,5);
it.attribute=script_getnum(st,6);
- it.card[0]=(short)script_getnum(st,7);
- it.card[1]=(short)script_getnum(st,8);
- it.card[2]=(short)script_getnum(st,9);
- it.card[3]=(short)script_getnum(st,10);
+ it.card[0] = script_getnum(st, 7);
+ it.card[1] = script_getnum(st, 8);
+ it.card[2] = script_getnum(st, 9);
+ it.card[3] = script_getnum(st, 10);
if( it.amount <= 0 )
return true;// nothing to do
@@ -7865,10 +8722,52 @@ BUILDIN(delitem2)
return false;
}
+/**
+ * Deletes item at given index.
+ * delitem(<index>{, <amount{, <account id>}});
+ */
+static BUILDIN(delitemidx)
+{
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 4)) {
+ if ((sd = script->id2sd(st, script_getnum(st, 4))) == NULL) {
+ st->state = END;
+ return true;
+ }
+ } else {
+ if ((sd = script->rid2sd(st)) == NULL)
+ return true;
+ }
+
+ int i = script_getnum(st, 2);
+ if (i < 0 || i >= sd->status.inventorySize) {
+ ShowError("buildin_delitemidx: Index (%d) should be from 0-%d.\n", i, sd->status.inventorySize - 1);
+ st->state = END;
+ return false;
+ }
+
+ if (itemdb->exists(sd->status.inventory[i].nameid) == NULL)
+ ShowWarning("buildin_delitemidx: Deleting invalid Item ID (%d).\n", sd->status.inventory[i].nameid);
+
+ int amount = 0;
+ if (script_hasdata(st, 3)) {
+ if ((amount = script_getnum(st, 3)) > sd->status.inventory[i].amount)
+ amount = sd->status.inventory[i].amount;
+ } else {
+ amount = sd->status.inventory[i].amount;
+ }
+
+ if (amount > 0)
+ script->buildin_delitem_delete(sd, i, &amount, true);
+
+ return true;
+}
+
/*==========================================
* Enables/Disables use of items while in an NPC [Skotlex]
*------------------------------------------*/
-BUILDIN(enableitemuse)
+static BUILDIN(enableitemuse)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd != NULL)
@@ -7876,7 +8775,7 @@ BUILDIN(enableitemuse)
return true;
}
-BUILDIN(disableitemuse)
+static BUILDIN(disableitemuse)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd != NULL)
@@ -7888,23 +8787,71 @@ BUILDIN(disableitemuse)
* return the basic stats of sd
* chk pc->readparam for available type
*------------------------------------------*/
-BUILDIN(readparam) {
+static BUILDIN(readparam)
+{
int type;
struct map_session_data *sd;
+ struct script_data *data = script_getdata(st, 2);
- type=script_getnum(st,2);
- if (script_hasdata(st,3))
- sd = script->nick2sd(st, script_getstr(st,3));
- else
- sd=script->rid2sd(st);
+ if (reference_toparam(data)) {
+ type = reference_getparamtype(data);
+ } else {
+ type = script->conv_num(st, data);
+ }
+
+ if (script_hasdata(st, 3)) {
+ if (script_isstringtype(st, 3)) {
+ sd = script->nick2sd(st, script_getstr(st, 3));
+ } else {
+ sd = script->id2sd(st, script_getnum(st, 3));
+ }
+ } else {
+ sd = script->rid2sd(st);
+ }
if (sd == NULL) {
- script_pushint(st,-1);
+ script_pushint(st, -1);
return true;
}
- script_pushint(st,pc->readparam(sd,type));
+ script_pushint(st, pc->readparam(sd, type));
+ return true;
+}
+
+static BUILDIN(setparam)
+{
+ int type;
+ struct map_session_data *sd;
+ struct script_data *data = script_getdata(st, 2);
+ int val = script_getnum(st, 3);
+
+ if (data_isreference(data) && reference_toparam(data)) {
+ type = reference_getparamtype(data);
+ } else {
+ type = script->conv_num(st, data);
+ }
+
+ if (script_hasdata(st, 4)) {
+ if (script_isstringtype(st, 4)) {
+ sd = script->nick2sd(st, script_getstr(st, 4));
+ } else {
+ sd = script->id2sd(st, script_getnum(st, 4));
+ }
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return true;
+ }
+ if (pc->setparam(sd, type, val) == 0) {
+ script_pushint(st, 0);
+ return false;
+ }
+
+ script_pushint(st, 1);
return true;
}
@@ -7916,62 +8863,67 @@ BUILDIN(readparam) {
* 2 : guild_id
* 3 : account_id
* 4 : bg_id
+ * 5 : clan_id
*------------------------------------------*/
-BUILDIN(getcharid) {
- int num;
+static BUILDIN(getcharid)
+{
+ int num = script_getnum(st, 2);
struct map_session_data *sd;
- num = script_getnum(st,2);
- if( script_hasdata(st,3) )
- sd=map->nick2sd(script_getstr(st,3));
+ if (script_hasdata(st, 3))
+ sd = map->nick2sd(script_getstr(st, 3), false);
else
- sd=script->rid2sd(st);
+ sd = script->rid2sd(st);
- if(sd==NULL) {
- script_pushint(st,0); //return 0, according docs
+ if (sd == NULL) {
+ script_pushint(st, 0); //return 0, according docs
return true;
}
- switch( num ) {
- case 0: script_pushint(st,sd->status.char_id); break;
- case 1: script_pushint(st,sd->status.party_id); break;
- case 2: script_pushint(st,sd->status.guild_id); break;
- case 3: script_pushint(st,sd->status.account_id); break;
- case 4: script_pushint(st,sd->bg_id); break;
- default:
- ShowError("buildin_getcharid: invalid parameter (%d).\n", num);
- script_pushint(st,0);
- break;
+ switch (num) {
+ case 0:
+ script_pushint(st, sd->status.char_id);
+ break;
+ case 1:
+ script_pushint(st, sd->status.party_id);
+ break;
+ case 2:
+ script_pushint(st, sd->status.guild_id);
+ break;
+ case 3:
+ script_pushint(st, sd->status.account_id);
+ break;
+ case 4:
+ script_pushint(st, sd->bg_id);
+ break;
+ case 5:
+ script_pushint(st, sd->status.clan_id);
+ break;
+ default:
+ ShowError("buildin_getcharid: invalid parameter (%d).\n", num);
+ script_pushint(st, 0);
+ break;
}
return true;
}
+
/*==========================================
* returns the GID of an NPC
*------------------------------------------*/
-BUILDIN(getnpcid)
+static BUILDIN(getnpcid)
{
- int num = script_getnum(st,2);
- struct npc_data* nd = NULL;
-
- if( script_hasdata(st,3) )
- {// unique npc name
- if( ( nd = npc->name2id(script_getstr(st,3)) ) == NULL )
- {
- ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3));
- script_pushint(st,0);
- return false;
+ if (script_hasdata(st, 2)) {
+ if (script_isinttype(st, 2)) {
+ // Deprecate old form - getnpcid(<type>{, <"npc name">})
+ ShowWarning("buildin_getnpcid: Use of type is deprecated. Format - getnpcid({<\"npc name\">})\n");
+ script_pushint(st, 0);
+ } else {
+ struct npc_data *nd = npc->name2id(script_getstr(st, 2));
+ script_pushint(st, (nd != NULL) ? nd->bl.id : 0);
}
- }
-
- switch (num) {
- case 0:
- script_pushint(st,nd ? nd->bl.id : st->oid);
- break;
- default:
- ShowError("buildin_getnpcid: invalid parameter (%d).\n", num);
- script_pushint(st,0);
- return false;
+ } else {
+ script_pushint(st, st->oid);
}
return true;
@@ -7981,7 +8933,7 @@ BUILDIN(getnpcid)
* Return the name of the party_id
* null if not found
*------------------------------------------*/
-BUILDIN(getpartyname)
+static BUILDIN(getpartyname)
{
int party_id;
struct party_data* p;
@@ -8007,7 +8959,7 @@ BUILDIN(getpartyname)
* 1 : char_id des membres
* 2 : account_id des membres
*------------------------------------------*/
-BUILDIN(getpartymember)
+static BUILDIN(getpartymember)
{
struct party_data *p;
int j=0,type=0;
@@ -8023,19 +8975,19 @@ BUILDIN(getpartymember)
if(p->party.member[i].account_id) {
switch (type) {
case 2:
- mapreg->setreg(reference_uid(script->add_str("$@partymemberaid"), j),p->party.member[i].account_id);
+ mapreg->setreg(reference_uid(script->add_variable("$@partymemberaid"), j),p->party.member[i].account_id);
break;
case 1:
- mapreg->setreg(reference_uid(script->add_str("$@partymembercid"), j),p->party.member[i].char_id);
+ mapreg->setreg(reference_uid(script->add_variable("$@partymembercid"), j),p->party.member[i].char_id);
break;
default:
- mapreg->setregstr(reference_uid(script->add_str("$@partymembername$"), j),p->party.member[i].name);
+ mapreg->setregstr(reference_uid(script->add_variable("$@partymembername$"), j),p->party.member[i].name);
}
j++;
}
}
}
- mapreg->setreg(script->add_str("$@partymembercount"),j);
+ mapreg->setreg(script->add_variable("$@partymembercount"),j);
return true;
}
@@ -8044,7 +8996,7 @@ BUILDIN(getpartymember)
* Retrieves party leader. if flag is specified,
* return some of the leader data. Otherwise, return name.
*------------------------------------------*/
-BUILDIN(getpartyleader)
+static BUILDIN(getpartyleader)
{
int party_id, type = 0, i=0;
struct party_data *p;
@@ -8069,7 +9021,7 @@ BUILDIN(getpartyleader)
switch (type) {
case 1: script_pushint(st,p->party.member[i].account_id); break;
case 2: script_pushint(st,p->party.member[i].char_id); break;
- case 3: script_pushint(st,p->party.member[i].class_); break;
+ case 3: script_pushint(st,p->party.member[i].class); break;
case 4: script_pushstrcopy(st,mapindex_id2name(p->party.member[i].map)); break;
case 5: script_pushint(st,p->party.member[i].lv); break;
default: script_pushstrcopy(st,p->party.member[i].name); break;
@@ -8077,11 +9029,98 @@ BUILDIN(getpartyleader)
return true;
}
+enum guildinfo_type {
+ GUILDINFO_NAME,
+ GUILDINFO_ID,
+ GUILDINFO_LEVEL,
+ GUILDINFO_ONLINE,
+ GUILDINFO_AV_LEVEL,
+ GUILDINFO_MAX_MEMBERS,
+ GUILDINFO_EXP,
+ GUILDINFO_NEXT_EXP,
+ GUILDINFO_SKILL_POINTS,
+ GUILDINFO_MASTER_NAME,
+ GUILDINFO_MASTER_CID,
+};
+
+static BUILDIN(getguildinfo)
+{
+ struct guild *g = NULL;
+
+ if (script_hasdata(st, 3)) {
+ if (script_isstringtype(st, 3)) {
+ const char *guild_name = script_getstr(st, 3);
+ g = guild->searchname(guild_name);
+ } else {
+ int guild_id = script_getnum(st, 3);
+ g = guild->search(guild_id);
+ }
+ } else {
+ struct map_session_data *sd = script->rid2sd(st);
+ g = sd ? sd->guild : NULL;
+ }
+
+ enum guildinfo_type type = script_getnum(st, 2);
+
+ if (g == NULL) {
+ // guild does not exist
+ switch (type) {
+ case GUILDINFO_NAME:
+ case GUILDINFO_MASTER_NAME:
+ script_pushconststr(st, "");
+ break;
+ default:
+ script_pushint(st, -1);
+ }
+ } else {
+ switch (type) {
+ case GUILDINFO_NAME:
+ script_pushstrcopy(st, g->name);
+ break;
+ case GUILDINFO_ID:
+ script_pushint(st, g->guild_id);
+ break;
+ case GUILDINFO_LEVEL:
+ script_pushint(st, g->guild_lv);
+ break;
+ case GUILDINFO_ONLINE:
+ script_pushint(st, g->connect_member);
+ break;
+ case GUILDINFO_AV_LEVEL:
+ script_pushint(st, g->average_lv);
+ break;
+ case GUILDINFO_MAX_MEMBERS:
+ script_pushint(st, g->max_member);
+ break;
+ case GUILDINFO_EXP:
+ script_pushint(st, g->exp);
+ break;
+ case GUILDINFO_NEXT_EXP:
+ script_pushint(st, g->next_exp);
+ break;
+ case GUILDINFO_SKILL_POINTS:
+ script_pushint(st, g->skill_point);
+ break;
+ case GUILDINFO_MASTER_NAME:
+ script_pushstrcopy(st, g->member[0].name);
+ break;
+ case GUILDINFO_MASTER_CID:
+ script_pushint(st, g->member[0].char_id);
+ break;
+ default:
+ ShowError("script:getguildinfo: unknown info type!\n");
+ st->state = END;
+ return false;
+ }
+ }
+ return true;
+}
+
/*==========================================
* Return the name of the @guild_id
* null if not found
*------------------------------------------*/
-BUILDIN(getguildname)
+static BUILDIN(getguildname)
{
int guild_id;
struct guild* g;
@@ -8103,7 +9142,7 @@ BUILDIN(getguildname)
* Return the name of the guild master of @guild_id
* null if not found
*------------------------------------------*/
-BUILDIN(getguildmaster)
+static BUILDIN(getguildmaster)
{
int guild_id;
struct guild* g;
@@ -8121,7 +9160,7 @@ BUILDIN(getguildmaster)
return true;
}
-BUILDIN(getguildmasterid)
+static BUILDIN(getguildmasterid)
{
int guild_id;
struct guild* g;
@@ -8148,7 +9187,7 @@ BUILDIN(getguildmasterid)
* 1 : character ID
* 2 : account ID
*------------------------------------------*/
-BUILDIN(getguildmember)
+static BUILDIN(getguildmember)
{
struct guild *g = NULL;
int j = 0;
@@ -8165,20 +9204,77 @@ BUILDIN(getguildmember)
if ( g->member[i].account_id ) {
switch (type) {
case 2:
- mapreg->setreg(reference_uid(script->add_str("$@guildmemberaid"), j),g->member[i].account_id);
+ mapreg->setreg(reference_uid(script->add_variable("$@guildmemberaid"), j),g->member[i].account_id);
break;
case 1:
- mapreg->setreg(reference_uid(script->add_str("$@guildmembercid"), j), g->member[i].char_id);
+ mapreg->setreg(reference_uid(script->add_variable("$@guildmembercid"), j), g->member[i].char_id);
break;
default:
- mapreg->setregstr(reference_uid(script->add_str("$@guildmembername$"), j), g->member[i].name);
+ mapreg->setregstr(reference_uid(script->add_variable("$@guildmembername$"), j), g->member[i].name);
break;
}
j++;
}
}
}
- mapreg->setreg(script->add_str("$@guildmembercount"), j);
+ mapreg->setreg(script->add_variable("$@guildmembercount"), j);
+ return true;
+}
+
+/**
+ * getguildonline(<Guild ID>{, type})
+ * Returns amount of guild members online.
+**/
+
+enum script_getguildonline_types {
+ GUILD_ONLINE_ALL = 0,
+ GUILD_ONLINE_VENDOR,
+ GUILD_ONLINE_NO_VENDOR
+};
+
+BUILDIN(getguildonline)
+{
+ struct guild *g;
+ int guild_id = script_getnum(st, 2);
+ int type = GUILD_ONLINE_ALL, j = 0;
+
+ if ((g = guild->search(guild_id)) == NULL) {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ if (script_hasdata(st, 3)) {
+ type = script_getnum(st, 3);
+
+ if (type < GUILD_ONLINE_ALL || type > GUILD_ONLINE_NO_VENDOR) {
+ ShowWarning("buildin_getguildonline: Invalid type specified. Defaulting to GUILD_ONLINE_ALL.\n");
+ type = GUILD_ONLINE_ALL;
+ }
+ }
+
+ struct map_session_data *sd;
+ for (int i = 0; i < MAX_GUILD; i++) {
+ if (g->member[i].online && (sd = g->member[i].sd) != NULL) {
+ switch (type) {
+ case GUILD_ONLINE_VENDOR:
+ if (sd->state.vending > 0)
+ j++;
+ break;
+
+ case GUILD_ONLINE_NO_VENDOR:
+ if (sd->state.vending == 0)
+ j++;
+ break;
+
+ default:
+ j++;
+ break;
+ }
+ }
+ }
+
+ script_pushint(st, j);
+
return true;
}
@@ -8189,43 +9285,61 @@ BUILDIN(getguildmember)
* 1 : party_name or ""
* 2 : guild_name or ""
* 3 : map_name
+ * 4 : clan_name or ""
* - : ""
*------------------------------------------*/
-BUILDIN(strcharinfo)
+static BUILDIN(strcharinfo)
{
- int num;
+ struct clan *c;
struct guild* g;
struct party_data* p;
- struct map_session_data *sd = script->rid2sd(st);
- if (sd == NULL) //Avoid crashing....
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ if(script_hasdata(st, 3)) {
+ script_pushcopy(st, 3);
+ } else {
+ script_pushconststr(st, "");
+ }
return true;
+ }
- num=script_getnum(st,2);
- switch(num) {
- case 0:
- script_pushstrcopy(st,sd->status.name);
- break;
- case 1:
- if( ( p = party->search(sd->status.party_id) ) != NULL ) {
- script_pushstrcopy(st,p->party.name);
- } else {
- script_pushconststr(st,"");
- }
- break;
- case 2:
- if( ( g = sd->guild ) != NULL ) {
- script_pushstrcopy(st,g->name);
- } else {
- script_pushconststr(st,"");
- }
- break;
- case 3:
- script_pushconststr(st,map->list[sd->bl.m].name);
- break;
- default:
- ShowWarning("buildin_strcharinfo: unknown parameter.\n");
- script_pushconststr(st,"");
- break;
+ switch (script_getnum(st, 2)) {
+ case 0:
+ script_pushstrcopy(st, sd->status.name);
+ break;
+ case 1:
+ if ((p = party->search(sd->status.party_id)) != NULL) {
+ script_pushstrcopy(st, p->party.name);
+ } else {
+ script_pushconststr(st, "");
+ }
+ break;
+ case 2:
+ if ((g = sd->guild) != NULL) {
+ script_pushstrcopy(st, g->name);
+ } else {
+ script_pushconststr(st, "");
+ }
+ break;
+ case 3:
+ script_pushconststr(st, map->list[sd->bl.m].name);
+ break;
+ case 4:
+ if ((c = sd->clan) != NULL) {
+ script_pushstrcopy(st, c->name);
+ } else {
+ script_pushconststr(st, "");
+ }
+ break;
+ default:
+ ShowWarning("script:strcharinfo: unknown parameter.\n");
+ script_pushconststr(st, "");
}
return true;
@@ -8240,43 +9354,53 @@ BUILDIN(strcharinfo)
* 3 : ::str
* 4 : map name
*------------------------------------------*/
-BUILDIN(strnpcinfo)
+static BUILDIN(strnpcinfo)
{
- int num;
char *buf,*name=NULL;
- struct npc_data *nd = map->id2nd(st->oid);
+ struct npc_data *nd;
+
+ if (script_hasdata(st, 4))
+ nd = map->id2nd(script_getnum(st, 4));
+ else
+ nd = map->id2nd(st->oid);
+
if (nd == NULL) {
- script_pushconststr(st, "");
+ if (script_hasdata(st, 3)) {
+ script_pushcopy(st, 3);
+ } else {
+ script_pushconststr(st, "");
+ }
return true;
}
- num = script_getnum(st,2);
- switch(num) {
- case 0: // display name
+ switch (script_getnum(st,2)) {
+ case 0: // display name
+ name = aStrdup(nd->name);
+ break;
+ case 1: // visible part of display name
+ if ((buf = strchr(nd->name,'#')) != NULL) {
name = aStrdup(nd->name);
- break;
- case 1: // visible part of display name
- if((buf = strchr(nd->name,'#')) != NULL)
- {
- name = aStrdup(nd->name);
- name[buf - nd->name] = 0;
- } else // Return the name, there is no '#' present
- name = aStrdup(nd->name);
- break;
- case 2: // # fragment
- if((buf = strchr(nd->name,'#')) != NULL)
- name = aStrdup(buf+1);
- break;
- case 3: // unique name
- name = aStrdup(nd->exname);
- break;
- case 4: // map name
- if( nd->bl.m >= 0 ) // Only valid map indexes allowed (issue:8034)
- name = aStrdup(map->list[nd->bl.m].name);
- break;
+ name[buf - nd->name] = 0;
+ } else { // Return the name, there is no '#' present
+ name = aStrdup(nd->name);
+ }
+ break;
+ case 2: // # fragment
+ if ((buf = strchr(nd->name,'#')) != NULL) {
+ name = aStrdup(buf+1);
+ }
+ break;
+ case 3: // unique name
+ name = aStrdup(nd->exname);
+ break;
+ case 4: // map name
+ if (nd->bl.m >= 0) { // Only valid map indexes allowed (issue:8034)
+ name = aStrdup(map->list[nd->bl.m].name);
+ }
+ break;
}
- if(name)
+ if (name)
script_pushstr(st, name);
else
script_pushconststr(st, "");
@@ -8287,7 +9411,7 @@ BUILDIN(strnpcinfo)
/**
* charid2rid: Returns the RID associated to the given character ID
*/
-BUILDIN(charid2rid)
+static BUILDIN(charid2rid)
{
int cid = script_getnum(st, 2);
struct map_session_data *sd = map->charid2sd(cid);
@@ -8304,7 +9428,7 @@ BUILDIN(charid2rid)
/*==========================================
* GetEquipID(Pos); Pos: 1-SCRIPT_EQUIP_TABLE_SIZE
*------------------------------------------*/
-BUILDIN(getequipid)
+static BUILDIN(getequipid)
{
int i, num;
struct item_data* item;
@@ -8340,7 +9464,7 @@ BUILDIN(getequipid)
* Get the equipement name at pos
* return item jname or ""
*------------------------------------------*/
-BUILDIN(getequipname)
+static BUILDIN(getequipname)
{
int i, num;
struct item_data* item;
@@ -8375,16 +9499,18 @@ BUILDIN(getequipname)
/*==========================================
* getbrokenid [Valaris]
*------------------------------------------*/
-BUILDIN(getbrokenid)
+static BUILDIN(getbrokenid)
{
- int i,num,id=0,brokencounter=0;
+ int num,id=0,brokencounter=0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
num=script_getnum(st,2);
- for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].card[0] == CARD0_PET)
+ continue;
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
brokencounter++;
if(num==brokencounter) {
id=sd->status.inventory[i].nameid;
@@ -8401,15 +9527,17 @@ BUILDIN(getbrokenid)
/*==========================================
* getbrokencount
*------------------------------------------*/
-BUILDIN(getbrokencount)
+static BUILDIN(getbrokencount)
{
int i, counter = 0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].attribute)
+ for (i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].card[0] == CARD0_PET)
+ continue;
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0)
counter++;
}
@@ -8421,21 +9549,23 @@ BUILDIN(getbrokencount)
/*==========================================
* repair [Valaris]
*------------------------------------------*/
-BUILDIN(repair)
+static BUILDIN(repair)
{
- int i,num;
int repaircounter=0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- num=script_getnum(st,2);
- for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute) {
+ int num = script_getnum(st, 2);
+ for(int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].card[0] == CARD0_PET)
+ continue;
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
repaircounter++;
if(num==repaircounter) {
- sd->status.inventory[i].attribute=0;
- clif->equiplist(sd);
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
+ clif->equipList(sd);
clif->produce_effect(sd, 0, sd->status.inventory[i].nameid);
clif->misceffect(&sd->bl, 3);
break;
@@ -8449,18 +9579,21 @@ BUILDIN(repair)
/*==========================================
* repairall
*------------------------------------------*/
-BUILDIN(repairall)
+static BUILDIN(repairall)
{
- int i, repaircounter = 0;
+ int repaircounter = 0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- for(i = 0; i < MAX_INVENTORY; i++)
+ for (int i = 0; i < sd->status.inventorySize; i++)
{
- if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute)
+ if (sd->status.inventory[i].card[0] == CARD0_PET)
+ continue;
+ if (sd->status.inventory[i].nameid && (sd->status.inventory[i].attribute & ATTR_BROKEN) != 0)
{
- sd->status.inventory[i].attribute = 0;
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
clif->produce_effect(sd,0,sd->status.inventory[i].nameid);
repaircounter++;
}
@@ -8469,7 +9602,7 @@ BUILDIN(repairall)
if(repaircounter)
{
clif->misceffect(&sd->bl, 3);
- clif->equiplist(sd);
+ clif->equipList(sd);
}
return true;
@@ -8478,7 +9611,7 @@ BUILDIN(repairall)
/*==========================================
* Chk if player have something equiped at pos
*------------------------------------------*/
-BUILDIN(getequipisequiped)
+static BUILDIN(getequipisequiped)
{
int i = -1,num;
struct map_session_data *sd;
@@ -8505,7 +9638,7 @@ BUILDIN(getequipisequiped)
* 1 : true
* 0 : false
*------------------------------------------*/
-BUILDIN(getequipisenableref)
+static BUILDIN(getequipisenableref)
{
int i = -1,num;
struct map_session_data *sd;
@@ -8525,13 +9658,42 @@ BUILDIN(getequipisenableref)
return true;
}
+/**
+ * Checks if the equipped item allows options.
+ * *getequipisenableopt(<equipment_index>);
+ *
+ * @param equipment_index as the inventory index of the equipment.
+ * @return 1 on enabled 0 on disabled.
+ */
+static BUILDIN(getequipisenableopt)
+{
+ int i = -1, index = script_getnum(st, 2);
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, -1);
+ ShowError("buildin_getequipisenableopt: player is not attached!");
+ return false;
+ }
+
+ if (index > 0 && index <= ARRAYLENGTH(script->equip))
+ i = pc->checkequip(sd, script->equip[index - 1]);
+
+ if (i >=0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_options && !sd->status.inventory[i].expire_time)
+ script_pushint(st, 1);
+ else
+ script_pushint(st, 0);
+
+ return true;
+}
+
/*==========================================
* Chk if the item equiped at pos is identify (huh ?)
* return (npc)
* 1 : true
* 0 : false
*------------------------------------------*/
-BUILDIN(getequipisidentify)
+static BUILDIN(getequipisidentify)
{
int i = -1,num;
struct map_session_data *sd;
@@ -8552,27 +9714,29 @@ BUILDIN(getequipisidentify)
}
/*==========================================
- * Get the item refined value at pos
- * return (npc)
- * x : refine amount
- * 0 : false (not refined)
+ * Get the total refine amount of equip at given pos
+ * return total refine amount
*------------------------------------------*/
-BUILDIN(getequiprefinerycnt)
+static BUILDIN(getequiprefinerycnt)
{
- int i = -1,num;
- struct map_session_data *sd;
+ int total_refine = 0;
+ struct map_session_data* sd = script->rid2sd(st);
- num = script_getnum(st,2);
- sd = script->rid2sd(st);
- if( sd == NULL )
- return true;
+ if (sd != NULL)
+ {
+ int count = script_lastdata(st);
+ int script_equip_size = ARRAYLENGTH(script->equip);
+ for (int n = 2; n <= count; n++) {
+ int i = -1;
+ int num = script_getnum(st, n);
+ if (num > 0 && num <= script_equip_size)
+ i = pc->checkequip(sd, script->equip[num - 1]);
- if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
- if(i >= 0)
- script_pushint(st,sd->status.inventory[i].refine);
- else
- script_pushint(st,0);
+ if (i >= 0)
+ total_refine += sd->status.inventory[i].refine;
+ }
+ }
+ script_pushint(st, total_refine);
return true;
}
@@ -8584,7 +9748,7 @@ BUILDIN(getequiprefinerycnt)
* x : weapon level
* 0 : false
*------------------------------------------*/
-BUILDIN(getequipweaponlv)
+static BUILDIN(getequipweaponlv)
{
int i = -1,num;
struct map_session_data *sd;
@@ -8610,21 +9774,34 @@ BUILDIN(getequipweaponlv)
* x : refine chance
* 0 : false (max refine level or unequip..)
*------------------------------------------*/
-BUILDIN(getequippercentrefinery) {
- int i = -1,num;
+static BUILDIN(getequippercentrefinery)
+{
+ int i = -1, num;
struct map_session_data *sd;
+ int type = 0;
+
+ num = script_getnum(st, 2);
+ type = (script_hasdata(st, 3)) ? script_getnum(st, 3) : REFINE_CHANCE_TYPE_NORMAL;
- num = script_getnum(st,2);
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;
+ if (type < REFINE_CHANCE_TYPE_NORMAL || type >= REFINE_CHANCE_TYPE_MAX) {
+ ShowError("buildin_getequippercentrefinery: Invalid type (%d) provided!\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
- if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE)
- script_pushint(st,status->get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine));
+ i = pc->checkequip(sd, script->equip[num - 1]);
+
+ if (i >= 0 && sd->status.inventory[i].nameid != 0 && sd->status.inventory[i].refine < MAX_REFINE)
+ script_pushint(st,
+ refine->get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int) sd->status.inventory[i].refine, (enum refine_chance_type) type));
else
- script_pushint(st,0);
+ script_pushint(st, 0);
return true;
}
@@ -8632,7 +9809,7 @@ BUILDIN(getequippercentrefinery) {
/*==========================================
* Refine +1 item at pos and log and display refine
*------------------------------------------*/
-BUILDIN(successrefitem)
+static BUILDIN(successrefitem)
{
int i = -1 , num, up = 1;
struct map_session_data *sd;
@@ -8669,20 +9846,25 @@ BUILDIN(successrefitem)
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
clif->misceffect(&sd->bl,3);
+
+ achievement->validate_refine(sd, i, true); // Achievements [Smokexyz/Hercules]
+
+ /* The following check is exclusive to characters (possibly only whitesmiths)
+ * that create equipments and refine them to level 10. */
if(sd->status.inventory[i].refine == 10 &&
sd->status.inventory[i].card[0] == CARD0_FORGE &&
sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])
) { // Fame point system [DracoRPG]
switch (sd->inventory_data[i]->wlv) {
- case 1:
- pc->addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
- break;
- case 2:
- pc->addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point
- break;
- case 3:
- pc->addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point
- break;
+ case 1:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
+ break;
+ case 2:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point
+ break;
+ case 3:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point
+ break;
}
}
}
@@ -8693,7 +9875,7 @@ BUILDIN(successrefitem)
/*==========================================
* Show a failed Refine +1 attempt
*------------------------------------------*/
-BUILDIN(failedrefitem)
+static BUILDIN(failedrefitem)
{
int i=-1,num;
struct map_session_data *sd;
@@ -8706,6 +9888,9 @@ BUILDIN(failedrefitem)
if (num > 0 && num <= ARRAYLENGTH(script->equip))
i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
+ // Call before changing refine to 0.
+ achievement->validate_refine(sd, i, false);
+
sd->status.inventory[i].refine = 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //recalculate bonus
clif->refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure
@@ -8721,7 +9906,7 @@ BUILDIN(failedrefitem)
/*==========================================
* Downgrades an Equipment Part by -1 . [Masao]
*------------------------------------------*/
-BUILDIN(downrefitem)
+static BUILDIN(downrefitem)
{
int i = -1, num, down = 1;
struct map_session_data *sd;
@@ -8753,6 +9938,9 @@ BUILDIN(downrefitem)
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
+
+ achievement->validate_refine(sd, i, false); // Achievements [Smokexyz/Hercules]
+
clif->misceffect(&sd->bl,2);
}
@@ -8762,7 +9950,7 @@ BUILDIN(downrefitem)
/*==========================================
* Delete the item equipped at pos.
*------------------------------------------*/
-BUILDIN(delequip)
+static BUILDIN(delequip)
{
int i=-1,num;
struct map_session_data *sd;
@@ -8790,7 +9978,8 @@ BUILDIN(delequip)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(statusup) {
+static BUILDIN(statusup)
+{
int type;
struct map_session_data *sd;
@@ -8806,7 +9995,7 @@ BUILDIN(statusup) {
/*==========================================
*
*------------------------------------------*/
-BUILDIN(statusup2)
+static BUILDIN(statusup2)
{
int type,val;
struct map_session_data *sd;
@@ -8822,6 +10011,25 @@ BUILDIN(statusup2)
return true;
}
+
+/*==========================================
+* Returns the number of stat points needed to change the specified stat by val.
+* needed_status_point(<type>,<val>); [secretdataz]
+*------------------------------------------*/
+static BUILDIN(needed_status_point)
+{
+ int type = script_getnum(st, 2);
+ int val = script_getnum(st, 3);;
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ script_pushint(st, 0);
+ else
+ script_pushint(st, pc->need_status_point(sd, type, val));
+
+ return true;
+}
+
/// See 'doc/item_bonus.txt'
///
/// bonus <bonus type>,<val1>;
@@ -8829,7 +10037,8 @@ BUILDIN(statusup2)
/// bonus3 <bonus type>,<val1>,<val2>,<val3>;
/// bonus4 <bonus type>,<val1>,<val2>,<val3>,<val4>;
/// bonus5 <bonus type>,<val1>,<val2>,<val3>,<val4>,<val5>;
-BUILDIN(bonus) {
+static BUILDIN(bonus)
+{
int type;
int val1;
int val2 = 0;
@@ -8863,7 +10072,7 @@ BUILDIN(bonus) {
val1 = skill->name2id(script_getstr(st, 3));
break;
}
- // else fall through
+ FALLTHROUGH
default:
val1 = script_getnum(st,3);
break;
@@ -8911,7 +10120,8 @@ BUILDIN(bonus) {
return true;
}
-BUILDIN(autobonus) {
+static BUILDIN(autobonus)
+{
unsigned int dur;
short rate;
short atk_type = 0;
@@ -8920,7 +10130,7 @@ BUILDIN(autobonus) {
if (sd == NULL)
return true; // no player attached
- if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
+ if (status->current_equip_item_index < 0 || sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip)
return true;
rate = script_getnum(st,3);
@@ -8945,7 +10155,8 @@ BUILDIN(autobonus) {
return true;
}
-BUILDIN(autobonus2) {
+static BUILDIN(autobonus2)
+{
unsigned int dur;
short rate;
short atk_type = 0;
@@ -8954,7 +10165,7 @@ BUILDIN(autobonus2) {
if (sd == NULL)
return true; // no player attached
- if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
+ if (status->current_equip_item_index < 0 || sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip)
return true;
rate = script_getnum(st,3);
@@ -8979,7 +10190,8 @@ BUILDIN(autobonus2) {
return true;
}
-BUILDIN(autobonus3) {
+static BUILDIN(autobonus3)
+{
unsigned int dur;
short rate,atk_type;
const char *bonus_script, *other_script = NULL;
@@ -8987,7 +10199,7 @@ BUILDIN(autobonus3) {
if (sd == NULL)
return true; // no player attached
- if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
+ if (status->current_equip_item_index < 0 || sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip)
return true;
rate = script_getnum(st,3);
@@ -9021,7 +10233,8 @@ BUILDIN(autobonus3) {
/// skill <skill id>,<level>
/// skill "<skill name>",<level>,<flag>
/// skill "<skill name>",<level>
-BUILDIN(skill) {
+static BUILDIN(skill)
+{
int id;
int level;
int flag = SKILL_GRANT_TEMPORARY;
@@ -9047,7 +10260,8 @@ BUILDIN(skill) {
/// addtoskill "<skill name>",<amount>
///
/// @see skill
-BUILDIN(addtoskill) {
+static BUILDIN(addtoskill)
+{
int id;
int level;
int flag = SKILL_GRANT_TEMPSTACK;
@@ -9068,7 +10282,8 @@ BUILDIN(addtoskill) {
///
/// guildskill <skill id>,<amount>;
/// guildskill "<skill name>",<amount>;
-BUILDIN(guildskill) {
+static BUILDIN(guildskill)
+{
int skill_id, id, max_points;
int level;
@@ -9084,6 +10299,9 @@ BUILDIN(guildskill) {
skill_id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
level = script_getnum(st,3);
+ if (skill_id < GD_SKILLBASE || skill_id >= GD_MAX)
+ return true; // not guild skill
+
id = skill_id - GD_SKILLBASE;
max_points = guild->skill_get_max(skill_id);
@@ -9104,7 +10322,7 @@ BUILDIN(guildskill) {
///
/// getskilllv(<skill id>) -> <level>
/// getskilllv("<skill name>") -> <level>
-BUILDIN(getskilllv)
+static BUILDIN(getskilllv)
{
int id;
struct map_session_data *sd = script->rid2sd(st);
@@ -9121,7 +10339,8 @@ BUILDIN(getskilllv)
///
/// getgdskilllv(<guild id>,<skill id>) -> <level>
/// getgdskilllv(<guild id>,"<skill name>") -> <level>
-BUILDIN(getgdskilllv) {
+static BUILDIN(getgdskilllv)
+{
int guild_id;
uint16 skill_id;
struct guild* g;
@@ -9142,7 +10361,7 @@ BUILDIN(getgdskilllv) {
/// before allowing the basic actions.
///
/// basicskillcheck() -> <bool>
-BUILDIN(basicskillcheck)
+static BUILDIN(basicskillcheck)
{
script_pushint(st, battle_config.basic_skill_check);
return true;
@@ -9151,7 +10370,7 @@ BUILDIN(basicskillcheck)
/// Returns the GM level of the player.
///
/// getgmlevel() -> <level>
-BUILDIN(getgmlevel)
+static BUILDIN(getgmlevel)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -9165,7 +10384,8 @@ BUILDIN(getgmlevel)
/// set the group ID of the player.
/// setgroupid(<new group id>{,"<character name>"|<account id>})
/// return 1 on success, 0 if failed.
-BUILDIN(setgroupid) {
+static BUILDIN(setgroupid)
+{
struct map_session_data* sd = NULL;
int new_group = script_getnum(st, 2);
@@ -9188,21 +10408,31 @@ BUILDIN(setgroupid) {
/// Returns the group ID of the player.
///
-/// getgroupid() -> <int>
-BUILDIN(getgroupid)
+/// getgroupid({<account id>}) -> <int>
+static BUILDIN(getgroupid)
{
- struct map_session_data *sd = script->rid2sd(st);
- if (sd == NULL)
+ struct map_session_data *sd = NULL;
+
+ if (script_hasdata(st, 2)) {
+ sd = map->id2sd(script_getnum(st, 2));
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ if (sd == NULL) {
+ script_pushint(st, -1);
return true; // no player attached, report source
- script_pushint(st, pc_get_group_id(sd));
+ }
+ script_pushint(st, pc_get_group_id(sd));
return true;
}
/// Terminates the execution of this script instance.
///
/// end
-BUILDIN(end) {
+static BUILDIN(end)
+{
st->state = END;
/* are we stopping inside a function? */
@@ -9222,10 +10452,16 @@ BUILDIN(end) {
/// Checks if the player has that effect state (option).
///
/// checkoption(<option>) -> <bool>
-BUILDIN(checkoption)
+static BUILDIN(checkoption)
{
int option;
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
if (sd == NULL)
return true;// no player attached, report source
@@ -9241,10 +10477,16 @@ BUILDIN(checkoption)
/// Checks if the player is in that body state (opt1).
///
/// checkoption1(<opt1>) -> <bool>
-BUILDIN(checkoption1)
+static BUILDIN(checkoption1)
{
int opt1;
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
if (sd == NULL)
return true;// no player attached, report source
@@ -9260,10 +10502,16 @@ BUILDIN(checkoption1)
/// Checks if the player has that health state (opt2).
///
/// checkoption2(<opt2>) -> <bool>
-BUILDIN(checkoption2)
+static BUILDIN(checkoption2)
{
int opt2;
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
if (sd == NULL)
return true;// no player attached, report source
@@ -9283,11 +10531,17 @@ BUILDIN(checkoption2)
///
/// setoption <option>,<flag>;
/// setoption <option>;
-BUILDIN(setoption)
+static BUILDIN(setoption)
{
int option;
int flag = 1;
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
if (sd == NULL)
return true;// no player attached, report source
@@ -9316,7 +10570,7 @@ BUILDIN(setoption)
/// checkcart() -> <bool>
///
/// @author Valaris
-BUILDIN(checkcart)
+static BUILDIN(checkcart)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -9341,7 +10595,7 @@ BUILDIN(checkcart)
///
/// setcart <type>;
/// setcart;
-BUILDIN(setcart)
+static BUILDIN(setcart)
{
int type = 1;
struct map_session_data *sd = script->rid2sd(st);
@@ -9360,7 +10614,7 @@ BUILDIN(setcart)
/// checkfalcon() -> <bool>
///
/// @author Valaris
-BUILDIN(checkfalcon)
+static BUILDIN(checkfalcon)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -9379,7 +10633,7 @@ BUILDIN(checkfalcon)
///
/// setfalcon <flag>;
/// setfalcon;
-BUILDIN(setfalcon)
+static BUILDIN(setfalcon)
{
bool flag = true;
struct map_session_data *sd = script->rid2sd(st);
@@ -9416,7 +10670,7 @@ enum setmount_type {
* The exact returned values are the same used as flag in setmount, except for
* dragons, where SETMOUNT_TYPE_DRAGON is returned, regardless of color.
*/
-BUILDIN(checkmount)
+static BUILDIN(checkmount)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -9440,6 +10694,7 @@ BUILDIN(checkmount)
/**
* Mounts or dismounts a combat mount.
*
+ * setmount <flag>, <mtype>;
* setmount <flag>;
* setmount;
*
@@ -9458,8 +10713,10 @@ BUILDIN(checkmount)
* If an invalid value or no flag is specified, the appropriate mount is
* auto-detected. As a result of this, there is no need to specify a flag at
* all, unless it is a dragon color other than green.
+ *
+ * In newer clients you can specify the mado gear type though the mtype argument.
*/
-BUILDIN(setmount)
+static BUILDIN(setmount)
{
int flag = SETMOUNT_TYPE_AUTODETECT;
struct map_session_data *sd = script->rid2sd(st);
@@ -9470,6 +10727,12 @@ BUILDIN(setmount)
if (script_hasdata(st,2))
flag = script_getnum(st,2);
+ enum mado_type mtype = script_hasdata(st, 3) ? script_getnum(st, 3) : MADO_ROBOT;
+ if (mtype < MADO_ROBOT || mtype >= MADO_MAX) {
+ ShowError("script_setmount: Invalid mado type has been passed (%d).\n", flag);
+ return false;
+ }
+
// Color variants for Rune Knight dragon mounts.
if (flag != SETMOUNT_TYPE_NONE) {
if (flag < SETMOUNT_TYPE_AUTODETECT || flag >= SETMOUNT_TYPE_MAX) {
@@ -9477,7 +10740,7 @@ BUILDIN(setmount)
flag = SETMOUNT_TYPE_AUTODETECT;
}
// Sanity checks and auto-detection
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) {
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) {
if (pc->checkskill(sd, RK_DRAGONTRAINING)) {
// Rune Knight (Dragon)
unsigned int option;
@@ -9489,14 +10752,14 @@ BUILDIN(setmount)
OPTION_DRAGON1); // default value
pc->setridingdragon(sd, option);
}
- } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) {
+ } else if ((sd->job & MAPID_THIRDMASK) == MAPID_RANGER) {
// Ranger (Warg)
if (pc->checkskill(sd, RA_WUGRIDER))
pc->setridingwug(sd, true);
- } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) {
+ } else if ((sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
// Mechanic (Mado Gear)
if (pc->checkskill(sd, NC_MADOLICENCE))
- pc->setmadogear(sd, true);
+ pc->setmadogear(sd, true, mtype);
} else {
// Knight / Crusader (Peco Peco)
if (pc->checkskill(sd, KN_RIDING))
@@ -9510,7 +10773,7 @@ BUILDIN(setmount)
pc->setridingwug(sd, false);
}
if (pc_ismadogear(sd)) {
- pc->setmadogear(sd, false);
+ pc->setmadogear(sd, false, mtype);
}
if (pc_isridingpeco(sd)) {
pc->setridingpeco(sd, false);
@@ -9524,7 +10787,7 @@ BUILDIN(setmount)
///
/// checkwug() -> <bool>
///
-BUILDIN(checkwug)
+static BUILDIN(checkwug)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -9542,7 +10805,8 @@ BUILDIN(checkwug)
///
/// save "<map name>",<x>,<y>
/// savepoint "<map name>",<x>,<y>
-BUILDIN(savepoint) {
+static BUILDIN(savepoint)
+{
int x;
int y;
short mapid;
@@ -9564,7 +10828,9 @@ BUILDIN(savepoint) {
/*==========================================
* GetTimeTick(0: System Tick, 1: Time Second Tick)
*------------------------------------------*/
-BUILDIN(gettimetick) { /* Asgard Version */
+/* Asgard Version */
+static BUILDIN(gettimetick)
+{
int type;
time_t clock;
struct tm *t;
@@ -9597,7 +10863,9 @@ BUILDIN(gettimetick) { /* Asgard Version */
* 4: WeekDay 5: MonthDay 6: Month
* 7: Year
*------------------------------------------*/
-BUILDIN(gettime) { /* Asgard Version */
+/* Asgard Version */
+static BUILDIN(gettime)
+{
int type;
time_t clock;
struct tm *t;
@@ -9639,83 +10907,131 @@ BUILDIN(gettime) { /* Asgard Version */
return true;
}
-/*==========================================
+/*
* GetTimeStr("TimeFMT", Length);
- *------------------------------------------*/
-BUILDIN(gettimestr)
+ */
+static BUILDIN(gettimestr)
{
char *tmpstr;
const char *fmtstr;
int maxlen;
- time_t now = time(NULL);
+ time_t now;
- fmtstr=script_getstr(st,2);
- maxlen=script_getnum(st,3);
+ fmtstr = script_getstr(st, 2);
+ maxlen = script_getnum(st, 3);
- tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char));
- strftime(tmpstr,maxlen,fmtstr,localtime(&now));
- tmpstr[maxlen]='\0';
+ if (script_hasdata(st, 4)) {
+ int timestamp = script_getnum(st, 4);
+ if (timestamp < 0) {
+ ShowWarning("buildin_gettimestr: UNIX timestamp must be in positive value.\n");
+ return false;
+ }
+
+ now = (time_t)timestamp;
+ } else {
+ now = time(NULL);
+ }
+
+ tmpstr = (char *)aMalloc((maxlen +1)*sizeof(char));
+ strftime(tmpstr, maxlen, fmtstr, localtime(&now));
+ tmpstr[maxlen] = '\0';
- script_pushstr(st,tmpstr);
+ script_pushstr(st, tmpstr);
return true;
}
/*==========================================
* Open player storage
*------------------------------------------*/
-BUILDIN(openstorage)
+static BUILDIN(openstorage)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
+ return false;
+
+ if (sd->storage.received == false) {
+ script_pushint(st, 0);
+ ShowWarning("buildin_openstorage: Storage data for AID %d has not been loaded.\n", sd->bl.id);
+ return false;
+ }
+
+ // Mapflag preventing from openstorage here
+ if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nostorage & 2)) {
+ script_pushint(st, 0);
return true;
+ }
storage->open(sd);
+
+ script_pushint(st, 1); // success flag.
return true;
}
-BUILDIN(guildopenstorage)
+static BUILDIN(guildopenstorage)
{
int ret;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
+ // Mapflag preventing from openstorage here
+ if (!pc_has_permission(sd, PC_PERM_BYPASS_NOSTORAGE) && (map->list[sd->bl.m].flag.nogstorage & 2)) {
+ script_pushint(st, 1);
+ return true;
+ }
+
ret = gstorage->open(sd);
script_pushint(st,ret);
return true;
}
-/*==========================================
- * Make player use a skill trought item usage
- *------------------------------------------*/
-/// itemskill <skill id>,<level>{,flag
-/// itemskill "<skill name>",<level>{,flag
-BUILDIN(itemskill)
+/**
+ * Makes the attached character use a skill by using an item.
+ *
+ * @code{.herc}
+ * itemskill(<skill id>, <skill level>{, <flag>});
+ * itemskill("<skill name>", <skill level>{, <flag>});
+ * @endcode
+ *
+ */
+static BUILDIN(itemskill)
{
- int id;
- int lv;
struct map_session_data *sd = script->rid2sd(st);
+
if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER)
return true;
- id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
- lv = script_getnum(st,3);
-/* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
-#if 0
- if( !script_hasdata(st, 4) ) {
- if( !skill->check_condition_castbegin(sd,id,lv) || !skill->check_condition_castend(sd,id,lv) )
+ pc->autocast_clear(sd);
+ sd->autocast.type = AUTOCAST_ITEM;
+ sd->autocast.skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
+ sd->autocast.skill_lv = script_getnum(st, 3);
+
+ int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE;
+
+ sd->autocast.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS);
+
+ if (sd->autocast.itemskill_check_conditions) {
+ if (skill->check_condition_castbegin(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0
+ || skill->check_condition_castend(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0) {
+ pc->autocast_clear(sd);
return true;
+ }
+
+ sd->autocast.itemskill_conditions_checked = true;
}
-#endif
- sd->skillitem=id;
- sd->skillitemlv=lv;
- clif->item_skill(sd,id,lv);
+
+ sd->autocast.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST);
+ sd->autocast.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF);
+
+ clif->item_skill(sd, sd->autocast.skill_id, sd->autocast.skill_lv);
+
return true;
}
+
/*==========================================
* Attempt to create an item
*------------------------------------------*/
-BUILDIN(produce)
+static BUILDIN(produce)
{
int trigger;
struct map_session_data *sd = script->rid2sd(st);
@@ -9729,7 +11045,7 @@ BUILDIN(produce)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(cooking)
+static BUILDIN(cooking)
{
int trigger;
struct map_session_data *sd = script->rid2sd(st);
@@ -9743,7 +11059,7 @@ BUILDIN(cooking)
/*==========================================
* Create a pet
*------------------------------------------*/
-BUILDIN(makepet)
+static BUILDIN(makepet)
{
struct map_session_data *sd;
int id,pet_id;
@@ -9760,8 +11076,8 @@ BUILDIN(makepet)
if (pet_id >= 0 && sd) {
sd->catch_target_class = pet->db[pet_id].class_;
intif->create_pet(sd->status.account_id, sd->status.char_id,
- (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv,
- (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
+ pet->db[pet_id].class_, mob->db(pet->db[pet_id].class_)->lv,
+ pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
100, 0, 1, pet->db[pet_id].jname);
}
@@ -9770,7 +11086,7 @@ BUILDIN(makepet)
/*==========================================
* Give player exp base,job * quest_exp_rate/100
*------------------------------------------*/
-BUILDIN(getexp)
+static BUILDIN(getexp)
{
int base=0,job=0;
struct map_session_data *sd = script->rid2sd(st);
@@ -9794,7 +11110,7 @@ BUILDIN(getexp)
/*==========================================
* Gain guild exp [Celest]
*------------------------------------------*/
-BUILDIN(guildgetexp)
+static BUILDIN(guildgetexp)
{
int exp;
struct map_session_data *sd = script->rid2sd(st);
@@ -9813,7 +11129,7 @@ BUILDIN(guildgetexp)
/*==========================================
* Changes the guild master of a guild [Skotlex]
*------------------------------------------*/
-BUILDIN(guildchangegm)
+static BUILDIN(guildchangegm)
{
struct map_session_data *sd;
int guild_id;
@@ -9826,7 +11142,7 @@ BUILDIN(guildchangegm)
if (sd == NULL)
script_pushint(st,0);
else
- script_pushint(st,guild->gm_change(guild_id, sd));
+ script_pushint(st, guild->gm_change(guild_id, sd->status.char_id));
return true;
}
@@ -9839,7 +11155,7 @@ BUILDIN(guildchangegm)
* @amount : nb to spawn
* @event : event to attach to mob
*------------------------------------------*/
-BUILDIN(monster)
+static BUILDIN(monster)
{
const char *mapn = script_getstr(st,2);
int x = script_getnum(st,3);
@@ -9911,7 +11227,7 @@ BUILDIN(monster)
/*==========================================
* Request List of Monster Drops
*------------------------------------------*/
-BUILDIN(getmobdrops)
+static BUILDIN(getmobdrops)
{
int class_ = script_getnum(st,2);
int i, j = 0;
@@ -9932,13 +11248,13 @@ BUILDIN(getmobdrops)
if( itemdb->exists(monster->dropitem[i].nameid) == NULL )
continue;
- mapreg->setreg(reference_uid(script->add_str("$@MobDrop_item"), j), monster->dropitem[i].nameid);
- mapreg->setreg(reference_uid(script->add_str("$@MobDrop_rate"), j), monster->dropitem[i].p);
+ mapreg->setreg(reference_uid(script->add_variable("$@MobDrop_item"), j), monster->dropitem[i].nameid);
+ mapreg->setreg(reference_uid(script->add_variable("$@MobDrop_rate"), j), monster->dropitem[i].p);
j++;
}
- mapreg->setreg(script->add_str("$@MobDrop_count"), j);
+ mapreg->setreg(script->add_variable("$@MobDrop_count"), j);
script_pushint(st, 1);
return true;
@@ -9946,7 +11262,8 @@ BUILDIN(getmobdrops)
/*==========================================
* Same as monster but randomize location in x0,x1,y0,y1 area
*------------------------------------------*/
-BUILDIN(areamonster) {
+static BUILDIN(areamonster)
+{
const char *mapn = script_getstr(st,2);
int x0 = script_getnum(st,3);
int y0 = script_getnum(st,4);
@@ -10009,7 +11326,7 @@ BUILDIN(areamonster) {
/*==========================================
* KillMonster subcheck, verify if mob to kill ain't got an even to handle, could be force kill by allflag
*------------------------------------------*/
-int buildin_killmonster_sub_strip(struct block_list *bl, va_list ap)
+static int buildin_killmonster_sub_strip(struct block_list *bl, va_list ap)
{
//same fix but with killmonster instead - stripping events from mobs.
struct mob_data *md = NULL;
@@ -10032,7 +11349,7 @@ int buildin_killmonster_sub_strip(struct block_list *bl, va_list ap)
md->state.npc_killmonster = 0;
return 0;
}
-int buildin_killmonster_sub(struct block_list *bl, va_list ap)
+static int buildin_killmonster_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
char *event = va_arg(ap,char *);
@@ -10051,15 +11368,22 @@ int buildin_killmonster_sub(struct block_list *bl, va_list ap)
}
return 0;
}
-BUILDIN(killmonster) {
+static BUILDIN(killmonster)
+{
const char *mapname,*event;
int16 m,allflag=0;
mapname=script_getstr(st,2);
event=script_getstr(st,3);
- if(strcmp(event,"All")==0)
+
+ if (strcmpi(event, "all") == 0) {
+ if (strcmp(event, "all") != 0) {
+ ShowWarning("buildin_killmonster: \"%s\" deprecated! Please use \"all\" instead.\n", event);
+ script->reportsrc(st);
+ }
allflag = 1;
- else
+ } else {
script->check_event(st, event);
+ }
if( (m=map->mapname2mapid(mapname))<0 )
return true;
@@ -10080,23 +11404,25 @@ BUILDIN(killmonster) {
return true;
}
-int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap)
+static int buildin_killmonsterall_sub_strip(struct block_list *bl, va_list ap)
{ //Strips the event from the mob if it's killed the old method.
struct mob_data *md;
md = BL_CAST(BL_MOB, bl);
+ nullpo_ret(md);
if (md->npc_event[0])
md->npc_event[0] = 0;
status_kill(bl);
return 0;
}
-int buildin_killmonsterall_sub(struct block_list *bl,va_list ap)
+static int buildin_killmonsterall_sub(struct block_list *bl, va_list ap)
{
status_kill(bl);
return 0;
}
-BUILDIN(killmonsterall) {
+static BUILDIN(killmonsterall)
+{
const char *mapname;
int16 m;
mapname=script_getstr(st,2);
@@ -10118,11 +11444,27 @@ BUILDIN(killmonsterall) {
return true;
}
+static BUILDIN(killmonstergid)
+{
+ int mobgid = script_getnum(st, 2);
+ struct mob_data *md = map->id2md(mobgid);
+
+ if (md == NULL) {
+ ShowWarning("buildin_killmonstergid: Error in finding monster GID '%d' or the target is not a monster.\n", mobgid);
+ return false;
+ }
+
+ md->state.npc_killmonster = 1;
+ status_kill(&md->bl);
+ return true;
+}
+
/*==========================================
* Creates a clone of a player.
* clone map, x, y, event, char_id, master_id, mode, flag, duration
*------------------------------------------*/
-BUILDIN(clone) {
+static BUILDIN(clone)
+{
struct map_session_data *sd, *msd = NULL;
int char_id, master_id = 0, x, y, flag = 0, m;
uint32 mode = 0;
@@ -10170,7 +11512,7 @@ BUILDIN(clone) {
}
/*==========================================
*------------------------------------------*/
-BUILDIN(doevent)
+static BUILDIN(doevent)
{
const char* event = script_getstr(st,2);
struct map_session_data* sd;
@@ -10186,7 +11528,7 @@ BUILDIN(doevent)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(donpcevent)
+static BUILDIN(donpcevent)
{
const char* event = script_getstr(st,2);
script->check_event(st, event);
@@ -10201,61 +11543,311 @@ BUILDIN(donpcevent)
/*==========================================
*------------------------------------------*/
-BUILDIN(addtimer)
+static BUILDIN(addtimer)
{
- int tick = script_getnum(st,2);
+ int tick = script_getnum(st, 2);
const char* event = script_getstr(st, 3);
struct map_session_data *sd;
script->check_event(st, event);
- sd = script->rid2sd(st);
- if( sd == NULL )
- return true;
- if (!pc->addeventtimer(sd,tick,event)) {
- ShowWarning("buildin_addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n",sd->status.char_id,event);
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
return false;
}
+
+ if (!pc->addeventtimer(sd, tick, event)) {
+ ShowWarning("script:addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n", sd->status.char_id, event);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ script_pushint(st, 1);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(deltimer)
+static BUILDIN(deltimer)
{
const char *event;
struct map_session_data *sd;
event=script_getstr(st, 2);
- sd = script->rid2sd(st);
- if( sd == NULL )
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
return true;
script->check_event(st, event);
- pc->deleventtimer(sd,event);
+ pc->deleventtimer(sd, event);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(addtimercount)
+static BUILDIN(addtimercount)
{
const char *event;
int tick;
struct map_session_data *sd;
- event=script_getstr(st, 2);
- tick=script_getnum(st,3);
- sd = script->rid2sd(st);
- if( sd == NULL )
+ event = script_getstr(st, 2);
+ tick = script_getnum(st, 3);
+
+ if (script_hasdata(st, 4))
+ sd = map->id2sd(script_getnum(st, 4));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
return true;
script->check_event(st, event);
- pc->addeventtimercount(sd,event,tick);
+ pc->addeventtimercount(sd, event, tick);
+ return true;
+}
+
+enum gettimer_mode {
+ GETTIMER_COUNT = 0,
+ GETTIMER_TICK_NEXT = 1,
+ GETTIMER_TICK_LAST = 2,
+};
+
+static BUILDIN(gettimer)
+{
+ struct map_session_data *sd;
+ const struct TimerData *td;
+ int i;
+ int tick;
+ const char *event = NULL;
+ int val = 0;
+ bool first = true;
+ short mode = script_getnum(st, 2);
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
+ if (script_hasdata(st, 4)) {
+ event = script_getstr(st, 4);
+ script->check_event(st, event);
+ }
+
+ if (sd == NULL) {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ switch (mode) {
+ case GETTIMER_COUNT:
+ // get number of timers
+ for (i = 0; i < MAX_EVENTTIMER; i++) {
+ if (sd->eventtimer[i] != INVALID_TIMER) {
+ if (event != NULL) {
+ td = timer->get(sd->eventtimer[i]);
+ Assert_retr(false, td != NULL);
+
+ if (strcmp((char *)(td->data), event) == 0) {
+ val++;
+ }
+ } else {
+ val++;
+ }
+ }
+ }
+ break;
+ case GETTIMER_TICK_NEXT:
+ // get the number of tick before the next timer runs
+ for (i = 0; i < MAX_EVENTTIMER; i++) {
+ if (sd->eventtimer[i] != INVALID_TIMER) {
+ td = timer->get(sd->eventtimer[i]);
+ Assert_retr(false, td != NULL);
+ tick = max(0, DIFF_TICK32(td->tick, timer->gettick()));
+
+ if (event != NULL) {
+ if ((first == true || tick < val) && strcmp((char *)(td->data), event) == 0) {
+ val = tick;
+ first = false;
+ }
+ } else if (first == true || tick < val) {
+ val = tick;
+ first = false;
+ }
+ }
+ }
+ break;
+ case GETTIMER_TICK_LAST:
+ // get the number of ticks before the last timer runs
+ for (i = MAX_EVENTTIMER - 1; i >= 0; i--) {
+ if (sd->eventtimer[i] != INVALID_TIMER) {
+ td = timer->get(sd->eventtimer[i]);
+ Assert_retr(false, td != NULL);
+ tick = max(0, DIFF_TICK32(td->tick, timer->gettick()));
+
+ if (event != NULL) {
+ if (strcmp((char *)(td->data), event) == 0) {
+ val = max(val, tick);
+ }
+ } else {
+ val = max(val, tick);
+ }
+ }
+ }
+ break;
+ }
+
+ script_pushint(st, val);
+ return true;
+}
+
+static int buildin_getunits_sub(struct block_list *bl, va_list ap)
+{
+ struct script_state *st = va_arg(ap, struct script_state *);
+ struct map_session_data *sd = va_arg(ap, struct map_session_data *);
+ int32 id = va_arg(ap, int32);
+ uint32 start = va_arg(ap, uint32);
+ uint32 *count = va_arg(ap, uint32 *);
+ uint32 limit = va_arg(ap, uint32);
+ const char *name = va_arg(ap, const char *);
+ struct reg_db *ref = va_arg(ap, struct reg_db *);
+ enum bl_type type = va_arg(ap, enum bl_type);
+ uint32 index = start + *count;
+
+ if ((bl->type & type) == 0) {
+ return 0; // type mismatch => skip
+ }
+
+ if (index >= SCRIPT_MAX_ARRAYSIZE || *count >= limit) {
+ return -1;
+ }
+
+ script->set_reg(st, sd, reference_uid(id, index), name,
+ (const void *)h64BPTRSIZE(bl->id), ref);
+
+ (*count)++;
+ return 1;
+}
+
+static int buildin_getunits_sub_pc(struct map_session_data *sd, va_list ap)
+{
+ return buildin_getunits_sub(&sd->bl, ap);
+}
+
+static int buildin_getunits_sub_mob(struct mob_data *md, va_list ap)
+{
+ return buildin_getunits_sub(&md->bl, ap);
+}
+
+static int buildin_getunits_sub_npc(struct npc_data *nd, va_list ap)
+{
+ return buildin_getunits_sub(&nd->bl, ap);
+}
+
+static BUILDIN(getunits)
+{
+ const char *name;
+ int32 id;
+ uint32 start;
+ struct reg_db *ref;
+ enum bl_type type = script_getnum(st, 2);
+ struct script_data *data = script_getdata(st, 3);
+ uint32 count = 0;
+ uint32 limit = script_getnum(st, 4);
+ struct map_session_data *sd = NULL;
+
+ if (!data_isreference(data) || reference_toconstant(data)) {
+ ShowError("script:getunits: second argument must be a variable\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+
+ id = reference_getid(data);
+ start = reference_getindex(data);
+ name = reference_getname(data);
+ ref = reference_getref(data);
+
+ if (not_server_variable(*name)) {
+ sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return true; // player variable but no player attached
+ }
+ }
+
+ if (is_string_variable(name)) {
+ ShowError("script:getunits: second argument must be an integer variable\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+
+ if (limit < 1 || limit > SCRIPT_MAX_ARRAYSIZE) {
+ limit = SCRIPT_MAX_ARRAYSIZE;
+ }
+
+ if (script_hasdata(st, 5)) {
+ const char *mapname = script_getstr(st, 5);
+ int16 m = map->mapname2mapid(mapname);
+
+ if (m == -1) {
+ ShowError("script:getunits: Invalid map(%s) provided.\n", mapname);
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+
+ if (script_hasdata(st, 9)) {
+ int16 x1 = script_getnum(st, 6);
+ int16 y1 = script_getnum(st, 7);
+ int16 x2 = script_getnum(st, 8);
+ int16 y2 = script_getnum(st, 9);
+
+ map->forcountinarea(buildin_getunits_sub, m, x1, y1, x2, y2, limit, type,
+ st, sd, id, start, &count, limit, name, ref, type);
+ } else {
+ map->forcountinmap(buildin_getunits_sub, m, limit, type,
+ st, sd, id, start, &count, limit, name, ref, type);
+ }
+ } else {
+ // for faster lookup we try to reduce the scope of the search if possible
+ switch (type) {
+ case BL_PC:
+ map->foreachpc(buildin_getunits_sub_pc,
+ st, sd, id, start, &count, limit, name, ref, type);
+ break;
+ case BL_MOB:
+ map->foreachmob(buildin_getunits_sub_mob,
+ st, sd, id, start, &count, limit, name, ref, type);
+ break;
+ case BL_NPC:
+ map->foreachnpc(buildin_getunits_sub_npc,
+ st, sd, id, start, &count, limit, name, ref, type);
+ break;
+ default:
+ // fallback to global lookup (slowest option)
+ map->foreachiddb(buildin_getunits_sub,
+ st, sd, id, start, &count, limit, name, ref, type);
+ }
+ }
+
+ script_pushint(st, count);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(initnpctimer)
+static BUILDIN(initnpctimer)
{
struct npc_data *nd;
int flag = 0;
@@ -10300,7 +11892,7 @@ BUILDIN(initnpctimer)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(startnpctimer)
+static BUILDIN(startnpctimer)
{
struct npc_data *nd;
int flag = 0;
@@ -10343,7 +11935,8 @@ BUILDIN(startnpctimer)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(stopnpctimer) {
+static BUILDIN(stopnpctimer)
+{
struct npc_data *nd;
int flag = 0;
@@ -10381,7 +11974,7 @@ BUILDIN(stopnpctimer) {
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getnpctimer)
+static BUILDIN(getnpctimer)
{
struct npc_data *nd;
struct map_session_data *sd;
@@ -10419,7 +12012,7 @@ BUILDIN(getnpctimer)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(setnpctimer)
+static BUILDIN(setnpctimer)
{
int tick;
struct npc_data *nd;
@@ -10444,7 +12037,7 @@ BUILDIN(setnpctimer)
/*==========================================
* attaches the player rid to the timer [Celest]
*------------------------------------------*/
-BUILDIN(attachnpctimer)
+static BUILDIN(attachnpctimer)
{
struct map_session_data *sd;
struct npc_data *nd = map->id2nd(st->oid);
@@ -10473,7 +12066,8 @@ BUILDIN(attachnpctimer)
/*==========================================
* detaches a player rid from the timer [Celest]
*------------------------------------------*/
-BUILDIN(detachnpctimer) {
+static BUILDIN(detachnpctimer)
+{
struct npc_data *nd;
if( script_hasdata(st,2) )
@@ -10497,7 +12091,8 @@ BUILDIN(detachnpctimer) {
* it checks if there is a player attached to the current script. [Skotlex]
* If no, returns 0, if yes, returns the account_id of the attached player.
*------------------------------------------*/
-BUILDIN(playerattached) {
+static BUILDIN(playerattached)
+{
if(st->rid == 0 || map->id2sd(st->rid) == NULL)
script_pushint(st,0);
else
@@ -10506,8 +12101,21 @@ BUILDIN(playerattached) {
}
/*==========================================
+ * Used by OnTouchNPC: label to return monster GID
*------------------------------------------*/
-BUILDIN(announce) {
+static BUILDIN(mobattached)
+{
+ if (st->rid == 0 || map->id2md(st->rid) == NULL)
+ script_pushint(st, 0);
+ else
+ script_pushint(st, st->rid);
+ return true;
+}
+
+/*==========================================
+ *------------------------------------------*/
+static BUILDIN(announce)
+{
const char *mes = script_getstr(st,2);
int flag = script_getnum(st,3);
const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL;
@@ -10515,11 +12123,13 @@ BUILDIN(announce) {
int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize
int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign
int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY
+ size_t len = strlen(mes);
+ send_target target = ALL_CLIENT;
+ struct block_list *bl = NULL;
+ Assert_retr(false, len < INT_MAX);
if( flag&(BC_TARGET_MASK|BC_SOURCE_MASK) ) {
// Broadcast source or broadcast region defined
- send_target target;
- struct block_list *bl = NULL;
if (flag&BC_NPC) {
// If bc_npc flag is set, use NPC as broadcast source
bl = map->id2bl(st->oid);
@@ -10537,27 +12147,23 @@ BUILDIN(announce) {
case BC_SELF: target = SELF; break;
default: target = ALL_CLIENT; break; // BC_ALL
}
-
- if (fontColor)
- clif->broadcast2(bl, mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
- else
- clif->broadcast(bl, mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK, target);
- } else {
- if (fontColor)
- intif->broadcast2(mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
- else
- intif->broadcast(mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK);
}
+
+ if (fontColor)
+ clif->broadcast2(bl, mes, (int)len+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
+ else
+ clif->broadcast(bl, mes, (int)len+1, flag&BC_COLOR_MASK, target);
+
return true;
}
/*==========================================
*------------------------------------------*/
-int buildin_announce_sub(struct block_list *bl, va_list ap)
+static int buildin_announce_sub(struct block_list *bl, va_list ap)
{
- char *mes = va_arg(ap, char *);
+ const char *mes = va_arg(ap, const char *);
int len = va_arg(ap, int);
int type = va_arg(ap, int);
- char *fontColor = va_arg(ap, char *);
+ const char *fontColor = va_arg(ap, const char *);
short fontType = (short)va_arg(ap, int);
short fontSize = (short)va_arg(ap, int);
short fontAlign = (short)va_arg(ap, int);
@@ -10571,7 +12177,7 @@ int buildin_announce_sub(struct block_list *bl, va_list ap)
/* Runs item effect on attached character.
* itemeffect <item id>;
* itemeffect "<item name>"; */
-BUILDIN(itemeffect)
+static BUILDIN(itemeffect)
{
struct npc_data *nd;
struct item_data *item_data;
@@ -10604,7 +12210,8 @@ BUILDIN(itemeffect)
return true;
}
-BUILDIN(mapannounce) {
+static BUILDIN(mapannounce)
+{
const char *mapname = script_getstr(st,2);
const char *mes = script_getstr(st,3);
int flag = script_getnum(st,4);
@@ -10614,17 +12221,20 @@ BUILDIN(mapannounce) {
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
int16 m;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if ((m = map->mapname2mapid(mapname)) < 0)
return true;
map->foreachinmap(script->buildin_announce_sub, m, BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(areaannounce) {
+static BUILDIN(areaannounce)
+{
const char *mapname = script_getstr(st,2);
int x0 = script_getnum(st,3);
int y0 = script_getnum(st,4);
@@ -10638,18 +12248,21 @@ BUILDIN(areaannounce) {
int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign
int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY
int16 m;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if ((m = map->mapname2mapid(mapname)) < 0)
return true;
map->foreachinarea(script->buildin_announce_sub, m, x0, y0, x1, y1, BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getusers) {
+static BUILDIN(getusers)
+{
int flag, val = 0;
struct map_session_data* sd;
struct block_list* bl = NULL;
@@ -10685,7 +12298,7 @@ BUILDIN(getusers) {
/*==========================================
* Works like @WHO - displays all online users names in window
*------------------------------------------*/
-BUILDIN(getusersname)
+static BUILDIN(getusersname)
{
struct map_session_data *sd;
const struct map_session_data *pl_sd;
@@ -10714,7 +12327,7 @@ BUILDIN(getusersname)
/*==========================================
* getmapguildusers("mapname",guild ID) Returns the number guild members present on a map [Reddozen]
*------------------------------------------*/
-BUILDIN(getmapguildusers)
+static BUILDIN(getmapguildusers)
{
const char *str;
int16 m;
@@ -10742,7 +12355,8 @@ BUILDIN(getmapguildusers)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getmapusers) {
+static BUILDIN(getmapusers)
+{
const char *str;
int16 m;
str=script_getstr(st,2);
@@ -10755,14 +12369,15 @@ BUILDIN(getmapusers) {
}
/*==========================================
*------------------------------------------*/
-int buildin_getareausers_sub(struct block_list *bl,va_list ap)
+static int buildin_getareausers_sub(struct block_list *bl, va_list ap)
{
int *users=va_arg(ap,int *);
+ nullpo_ret(users);
(*users)++;
return 0;
}
-BUILDIN(getareausers)
+static BUILDIN(getareausers)
{
int16 m = -1, x0, y0, x1, y1;
int users = 0;
@@ -10822,7 +12437,7 @@ BUILDIN(getareausers)
/*==========================================
*------------------------------------------*/
-int buildin_getareadropitem_sub(struct block_list *bl, va_list ap)
+static int buildin_getareadropitem_sub(struct block_list *bl, va_list ap)
{
int item = va_arg(ap, int);
int *amount = va_arg(ap, int *);
@@ -10838,7 +12453,8 @@ int buildin_getareadropitem_sub(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(getareadropitem) {
+static BUILDIN(getareadropitem)
+{
const char *str;
int16 m,x0,y0,x1,y1;
int item,amount=0;
@@ -10870,7 +12486,7 @@ BUILDIN(getareadropitem) {
}
/*==========================================
*------------------------------------------*/
-BUILDIN(enablenpc)
+static BUILDIN(enablenpc)
{
const char *str;
str=script_getstr(st,2);
@@ -10879,7 +12495,7 @@ BUILDIN(enablenpc)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(disablenpc)
+static BUILDIN(disablenpc)
{
const char *str;
str=script_getstr(st,2);
@@ -10889,7 +12505,7 @@ BUILDIN(disablenpc)
/*==========================================
*------------------------------------------*/
-BUILDIN(hideoffnpc)
+static BUILDIN(hideoffnpc)
{
const char *str;
str=script_getstr(st,2);
@@ -10898,13 +12514,63 @@ BUILDIN(hideoffnpc)
}
/*==========================================
*------------------------------------------*/
-BUILDIN(hideonnpc)
+static BUILDIN(hideonnpc)
{
const char *str;
str=script_getstr(st,2);
npc->enable(str,4);
return true;
}
+/*==========================================
+ *------------------------------------------*/
+static BUILDIN(cloakonnpc)
+{
+ struct npc_data *nd = npc->name2id(script_getstr(st, 2));
+ if (nd == NULL) {
+ ShowError("buildin_cloakonnpc: invalid npc name '%s'.\n", script_getstr(st, 2));
+ return false;
+ }
+
+ if (script_hasdata(st, 3)) {
+ struct map_session_data *sd = map->id2sd(script_getnum(st, 3));
+ if (sd == NULL)
+ return false;
+
+ uint32 val = nd->option;
+ nd->option |= OPTION_CLOAK;
+ clif->changeoption_target(&nd->bl, &sd->bl, SELF);
+ nd->option = val;
+ } else {
+ nd->option |= OPTION_CLOAK;
+ clif->changeoption(&nd->bl);
+ }
+ return true;
+}
+/*==========================================
+ *------------------------------------------*/
+static BUILDIN(cloakoffnpc)
+{
+ struct npc_data *nd = npc->name2id(script_getstr(st, 2));
+ if (nd == NULL) {
+ ShowError("buildin_cloakoffnpc: invalid npc name '%s'.\n", script_getstr(st, 2));
+ return false;
+ }
+
+ if (script_hasdata(st, 3)) {
+ struct map_session_data *sd = map->id2sd(script_getnum(st, 3));
+ if (sd == NULL)
+ return false;
+
+ uint32 val = nd->option;
+ nd->option &= ~OPTION_CLOAK;
+ clif->changeoption_target(&nd->bl, &sd->bl, SELF);
+ nd->option = val;
+ } else {
+ nd->option &= ~OPTION_CLOAK;
+ clif->changeoption(&nd->bl);
+ }
+ return true;
+}
/* Starts a status effect on the target unit or on the attached player.
*
@@ -10913,7 +12579,7 @@ BUILDIN(hideonnpc)
* sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<rate,<flag>,{<unit_id>}};
* <flag>: @see enum scstart_flag
*/
-BUILDIN(sc_start)
+static BUILDIN(sc_start)
{
struct npc_data *nd = map->id2nd(st->oid);
struct block_list* bl;
@@ -10981,7 +12647,8 @@ BUILDIN(sc_start)
/// Ends one or all status effects on the target unit or on the attached player.
///
/// sc_end <effect_id>{,<unit_id>};
-BUILDIN(sc_end) {
+static BUILDIN(sc_end)
+{
struct block_list* bl;
int type;
@@ -11016,7 +12683,9 @@ BUILDIN(sc_end) {
}
//This should help status_change_end force disabling the SC in case it has no limit.
- sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0;
+ if (type != SC_BERSERK)
+ sce->val1 = 0; // SC_BERSERK requires skill_lv that's stored in sce->val1 when being removed [KirieZ]
+ sce->val2 = sce->val3 = sce->val4 = 0;
status_change_end(bl, (sc_type)type, INVALID_TIMER);
}
else
@@ -11028,7 +12697,8 @@ BUILDIN(sc_end) {
/*==========================================
* @FIXME atm will return reduced tick, 0 immune, 1 no tick
*------------------------------------------*/
-BUILDIN(getscrate) {
+static BUILDIN(getscrate)
+{
struct block_list *bl;
int type,rate;
@@ -11049,7 +12719,7 @@ BUILDIN(getscrate) {
/*==========================================
* getstatus <type>{, <info>};
*------------------------------------------*/
-BUILDIN(getstatus)
+static BUILDIN(getstatus)
{
int id, type;
struct map_session_data* sd = script->rid2sd(st);
@@ -11080,14 +12750,16 @@ BUILDIN(getstatus)
case 3: script_pushint(st, sd->sc.data[id]->val3); break;
case 4: script_pushint(st, sd->sc.data[id]->val4); break;
case 5:
- {
- const struct TimerData *td = timer->get(sd->sc.data[id]->timer);
+ if (sd->sc.data[id]->infinite_duration) {
+ script_pushint(st, INFINITE_DURATION);
+ } else {
+ const struct TimerData *td = timer->get(sd->sc.data[id]->timer);
- if (td != NULL) {
- // return the amount of time remaining
- script_pushint(st, (int)(td->tick - timer->gettick())); // TODO: change this to int64 when we'll support 64 bit script values
+ if (td != NULL) {
+ // return the amount of time remaining
+ script_pushint(st, (int)(td->tick - timer->gettick())); // TODO: change this to int64 when we'll support 64 bit script values
+ }
}
- }
break;
default: script_pushint(st, 1); break;
}
@@ -11098,17 +12770,26 @@ BUILDIN(getstatus)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(debugmes)
+static BUILDIN(debugmes)
{
- const char *str;
- str=script_getstr(st,2);
- ShowDebug("script debug : %d %d : %s\n",st->rid,st->oid,str);
+ struct StringBuf buf;
+ StrBuf->Init(&buf);
+
+ if (!script->sprintf_helper(st, 2, &buf)) {
+ StrBuf->Destroy(&buf);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ ShowDebug("script debug : %d %d : %s\n", st->rid, st->oid, StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
+ script_pushint(st, 1);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(catchpet)
+static BUILDIN(catchpet)
{
int pet_id;
struct map_session_data *sd;
@@ -11125,7 +12806,7 @@ BUILDIN(catchpet)
/*==========================================
* [orn]
*------------------------------------------*/
-BUILDIN(homunculus_evolution)
+static BUILDIN(homunculus_evolution)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11145,7 +12826,7 @@ BUILDIN(homunculus_evolution)
* Checks for vaporized morph state
* and deletes ITEMID_STRANGE_EMBRYO.
*------------------------------------------*/
-BUILDIN(homunculus_mutate)
+static BUILDIN(homunculus_mutate)
{
bool success = false;
struct map_session_data *sd = script->rid2sd(st);
@@ -11159,7 +12840,7 @@ BUILDIN(homunculus_mutate)
if (script_hasdata(st,2))
homun_id = script_getnum(st,2);
else
- homun_id = 6048 + (rnd() % 4);
+ homun_id = HOMID_EIRA + (rnd() % 4);
m_class = homun->class2type(sd->hd->homunculus.class_);
m_id = homun->class2type(homun_id);
@@ -11186,7 +12867,7 @@ BUILDIN(homunculus_mutate)
* Puts homunculus into morph state
* and gives ITEMID_STRANGE_EMBRYO.
*------------------------------------------*/
-BUILDIN(homunculus_morphembryo)
+static BUILDIN(homunculus_morphembryo)
{
bool success = false;
struct map_session_data *sd = script->rid2sd(st);
@@ -11208,7 +12889,7 @@ BUILDIN(homunculus_morphembryo)
clif->additem(sd, 0, 0, i);
clif->emotion(&sd->hd->bl, E_SWT);
} else {
- homun->vaporize(sd, HOM_ST_MORPH);
+ homun->vaporize(sd, HOM_ST_MORPH, true);
success = true;
}
} else {
@@ -11229,7 +12910,7 @@ BUILDIN(homunculus_morphembryo)
* 1 = Homunculus is vaporized (rest)
* 2 = Homunculus is in morph state
*------------------------------------------*/
-BUILDIN(homunculus_checkcall)
+static BUILDIN(homunculus_checkcall)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL || sd->hd == NULL)
@@ -11241,7 +12922,7 @@ BUILDIN(homunculus_checkcall)
}
// [Zephyrus]
-BUILDIN(homunculus_shuffle)
+static BUILDIN(homunculus_shuffle)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11254,24 +12935,24 @@ BUILDIN(homunculus_shuffle)
}
//These two functions bring the eA MAPID_* class functionality to scripts.
-BUILDIN(eaclass)
+static BUILDIN(eaclass)
{
- int class_;
+ int class;
if (script_hasdata(st,2)) {
- class_ = script_getnum(st,2);
+ class = script_getnum(st,2);
} else {
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- class_ = sd->status.class_;
+ class = sd->status.class;
}
- script_pushint(st,pc->jobid2mapid(class_));
+ script_pushint(st,pc->jobid2mapid(class));
return true;
}
-BUILDIN(roclass)
+static BUILDIN(roclass)
{
- int class_ =script_getnum(st,2);
+ int job = script_getnum(st,2);
int sex;
if (script_hasdata(st,3)) {
sex = script_getnum(st,3);
@@ -11282,14 +12963,14 @@ BUILDIN(roclass)
else
sex = 1; //Just use male when not found.
}
- script_pushint(st,pc->mapid2jobid(class_, sex));
+ script_pushint(st,pc->mapid2jobid(job, sex));
return true;
}
/*==========================================
* Tells client to open a hatching window, used for pet incubator
*------------------------------------------*/
-BUILDIN(birthpet)
+static BUILDIN(birthpet)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11312,7 +12993,7 @@ BUILDIN(birthpet)
* 3 : don't reset skill, blvl=1
* 4 : jlvl=0
*------------------------------------------*/
-BUILDIN(resetlvl)
+static BUILDIN(resetlvl)
{
int type=script_getnum(st,2);
struct map_session_data *sd = script->rid2sd(st);
@@ -11325,7 +13006,7 @@ BUILDIN(resetlvl)
/*==========================================
* Reset a player status point
*------------------------------------------*/
-BUILDIN(resetstatus)
+static BUILDIN(resetstatus)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11337,7 +13018,7 @@ BUILDIN(resetstatus)
/*==========================================
* script command resetskill
*------------------------------------------*/
-BUILDIN(resetskill)
+static BUILDIN(resetskill)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11349,7 +13030,7 @@ BUILDIN(resetskill)
/*==========================================
* Counts total amount of skill points.
*------------------------------------------*/
-BUILDIN(skillpointcount)
+static BUILDIN(skillpointcount)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -11361,7 +13042,7 @@ BUILDIN(skillpointcount)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(changebase)
+static BUILDIN(changebase)
{
struct map_session_data *sd = NULL;
int vclass;
@@ -11378,12 +13059,12 @@ BUILDIN(changebase)
if(vclass == JOB_WEDDING)
{
if (!battle_config.wedding_modifydisplay || //Do not show the wedding sprites
- sd->class_&JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore.
+ sd->job & JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore.
)
return true;
}
- if(sd->disguise == -1 && vclass != sd->vd.class_)
+ if (sd->disguise == -1 && vclass != sd->vd.class)
pc->changelook(sd,LOOK_BASE,vclass); //Updated client view. Base, Weapon and Cloth Colors.
return true;
@@ -11407,7 +13088,7 @@ static struct map_session_data *prepareChangeSex(struct script_state *st)
/*==========================================
* Unequip all item and request for a changesex to char-serv
*------------------------------------------*/
-BUILDIN(changesex)
+static BUILDIN(changesex)
{
struct map_session_data *sd = prepareChangeSex(st);
if (sd == NULL)
@@ -11419,7 +13100,7 @@ BUILDIN(changesex)
/*==========================================
* Unequip all items and change character sex [4144]
*------------------------------------------*/
-BUILDIN(changecharsex)
+static BUILDIN(changecharsex)
{
struct map_session_data *sd = prepareChangeSex(st);
if (sd == NULL)
@@ -11431,7 +13112,7 @@ BUILDIN(changecharsex)
/*==========================================
* Works like 'announce' but outputs in the common chat window
*------------------------------------------*/
-BUILDIN(globalmes)
+static BUILDIN(globalmes)
{
const char *name=NULL,*mes;
@@ -11459,7 +13140,7 @@ BUILDIN(globalmes)
/// Creates a waiting room (chat room) for this npc.
///
/// waitingroom "<title>",<limit>{,"<event>"{,<trigger>{,<zeny>{,<minlvl>{,<maxlvl>}}}}};
-BUILDIN(waitingroom)
+static BUILDIN(waitingroom)
{
struct npc_data* nd;
const char* title = script_getstr(st, 2);
@@ -11483,7 +13164,8 @@ BUILDIN(waitingroom)
///
/// delwaitingroom "<npc_name>";
/// delwaitingroom;
-BUILDIN(delwaitingroom) {
+static BUILDIN(delwaitingroom)
+{
struct npc_data* nd;
if( script_hasdata(st,2) )
nd = npc->name2id(script_getstr(st, 2));
@@ -11498,7 +13180,8 @@ BUILDIN(delwaitingroom) {
///
/// kickwaitingroomall "<npc_name>";
/// kickwaitingroomall;
-BUILDIN(waitingroomkickall) {
+static BUILDIN(waitingroomkickall)
+{
struct npc_data* nd;
struct chat_data* cd;
@@ -11516,7 +13199,8 @@ BUILDIN(waitingroomkickall) {
///
/// enablewaitingroomevent "<npc_name>";
/// enablewaitingroomevent;
-BUILDIN(enablewaitingroomevent) {
+static BUILDIN(enablewaitingroomevent)
+{
struct npc_data* nd;
struct chat_data* cd;
@@ -11534,7 +13218,8 @@ BUILDIN(enablewaitingroomevent) {
///
/// disablewaitingroomevent "<npc_name>";
/// disablewaitingroomevent;
-BUILDIN(disablewaitingroomevent) {
+static BUILDIN(disablewaitingroomevent)
+{
struct npc_data *nd;
struct chat_data *cd;
@@ -11566,7 +13251,7 @@ BUILDIN(disablewaitingroomevent) {
///
/// getwaitingroomstate(<type>,"<npc_name>") -> <info>
/// getwaitingroomstate(<type>) -> <info>
-BUILDIN(getwaitingroomstate)
+static BUILDIN(getwaitingroomstate)
{
const struct npc_data *nd;
const struct chat_data *cd;
@@ -11588,7 +13273,8 @@ BUILDIN(getwaitingroomstate)
case 0:
for (i = 0; i < cd->users; i++) {
struct map_session_data *sd = cd->usersd[i];
- mapreg->setreg(reference_uid(script->add_str("$@chatmembers"), i), sd->bl.id);
+ nullpo_retr(false, sd);
+ mapreg->setreg(reference_uid(script->add_variable("$@chatmembers"), i), sd->bl.id);
}
script_pushint(st, cd->users);
break;
@@ -11601,8 +13287,8 @@ BUILDIN(getwaitingroomstate)
case 32: script_pushint(st, (cd->users >= cd->limit)); break;
case 33: script_pushint(st, (cd->users >= cd->trigger)); break;
- case 34: script_pushint(st, cd->minLvl); break;
- case 35: script_pushint(st, cd->maxLvl); break;
+ case 34: script_pushint(st, cd->min_level); break;
+ case 35: script_pushint(st, cd->max_level); break;
case 36: script_pushint(st, cd->zeny); break;
default: script_pushint(st, -1); break;
}
@@ -11621,7 +13307,7 @@ BUILDIN(getwaitingroomstate)
///
/// warpwaitingpc "<map name>",<x>,<y>,<number of players>;
/// warpwaitingpc "<map name>",<x>,<y>;
-BUILDIN(warpwaitingpc)
+static BUILDIN(warpwaitingpc)
{
int x, y, i, n;
const char* map_name;
@@ -11643,6 +13329,7 @@ BUILDIN(warpwaitingpc)
for (i = 0; i < n && cd->users > 0; i++) {
struct map_session_data *sd = cd->usersd[0];
+ nullpo_retr(false, sd);
if (strcmp(map_name,"SavePoint") == 0 && map->list[sd->bl.m].flag.noteleport) {
// can't teleport on this map
break;
@@ -11657,7 +13344,7 @@ BUILDIN(warpwaitingpc)
pc->payzeny(sd, cd->zeny, LOG_TYPE_NPC, NULL);
}
- mapreg->setreg(reference_uid(script->add_str("$@warpwaitingpc"), i), sd->bl.id);
+ mapreg->setreg(reference_uid(script->add_variable("$@warpwaitingpc"), i), sd->bl.id);
if( strcmp(map_name,"Random") == 0 )
pc->randomwarp(sd,CLR_TELEPORT);
@@ -11666,7 +13353,7 @@ BUILDIN(warpwaitingpc)
else
pc->setpos(sd, script->mapindexname2id(st,map_name), x, y, CLR_OUTSIGHT);
}
- mapreg->setreg(script->add_str("$@warpwaitingpcnum"), i);
+ mapreg->setreg(script->add_variable("$@warpwaitingpcnum"), i);
return true;
}
@@ -11677,7 +13364,8 @@ BUILDIN(warpwaitingpc)
/// Detaches a character from a script.
///
/// @param st Script state to detach the character from.
-void script_detach_rid(struct script_state* st) {
+static void script_detach_rid(struct script_state *st)
+{
if(st->rid) {
script->detach_state(st, false);
st->rid = 0;
@@ -11687,7 +13375,8 @@ void script_detach_rid(struct script_state* st) {
/*==========================================
* Attach sd char id to script and detach current one if any
*------------------------------------------*/
-BUILDIN(attachrid) {
+static BUILDIN(attachrid)
+{
int rid = script_getnum(st,2);
if (map->id2sd(rid) != NULL) {
@@ -11703,7 +13392,7 @@ BUILDIN(attachrid) {
/*==========================================
* Detach script to rid
*------------------------------------------*/
-BUILDIN(detachrid)
+static BUILDIN(detachrid)
{
script->detach_rid(st);
return true;
@@ -11711,7 +13400,7 @@ BUILDIN(detachrid)
/*==========================================
* Chk if account connected, (and charid from account if specified)
*------------------------------------------*/
-BUILDIN(isloggedin)
+static BUILDIN(isloggedin)
{
struct map_session_data *sd = map->id2sd(script_getnum(st,2));
if (script_hasdata(st,3) && sd != NULL
@@ -11724,7 +13413,8 @@ BUILDIN(isloggedin)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(setmapflagnosave) {
+static BUILDIN(setmapflagnosave)
+{
int16 m,x,y;
unsigned short map_index;
const char *str,*str2;
@@ -11746,7 +13436,81 @@ BUILDIN(setmapflagnosave) {
return true;
}
-BUILDIN(getmapflag)
+enum mapinfo_info {
+ MAPINFO_NAME,
+ MAPINFO_ID,
+ MAPINFO_SIZE_X,
+ MAPINFO_SIZE_Y,
+ MAPINFO_ZONE,
+ MAPINFO_NPC_COUNT
+};
+
+static BUILDIN(getmapinfo)
+{
+ enum mapinfo_info mode = script_getnum(st, 2);
+ int16 m = -1;
+
+ if (script_hasdata(st, 3)) {
+ if (script_isstringtype(st, 3)) {
+ const char *str = script_getstr(st, 3);
+ m = map->mapindex2mapid(strdb_iget(mapindex->db, str));
+ } else {
+ m = script_getnum(st, 3);
+ }
+ } else {
+ struct block_list *bl = NULL;
+
+ if (st->oid) {
+ bl = map->id2bl(st->oid);
+ } else if (st->rid) {
+ bl = map->id2bl(st->rid);
+ }
+
+ if (bl == NULL) {
+ ShowError("buildin_getmapinfo: map not supplied and NPC/PC not attached!\n");
+ script_pushint(st, -3);
+ return false;
+ }
+
+ m = bl->m;
+ }
+
+ if (m < 0) {
+ // here we don't throw an error, so the command can be used
+ // to detect whether or not a map exists
+ script_pushint(st, -1);
+ return true;
+ }
+
+ switch (mode) {
+ case MAPINFO_NAME:
+ script_pushconststr(st, map->list[m].name);
+ break;
+ case MAPINFO_ID:
+ script_pushint(st, m);
+ break;
+ case MAPINFO_SIZE_X:
+ script_pushint(st, map->list[m].xs);
+ break;
+ case MAPINFO_SIZE_Y:
+ script_pushint(st, map->list[m].ys);
+ break;
+ case MAPINFO_ZONE:
+ script_pushstrcopy(st, map->list[m].zone->name);
+ break;
+ case MAPINFO_NPC_COUNT:
+ script_pushint(st, map->list[m].npc_num);
+ break;
+ default:
+ ShowError("buildin_getmapinfo: unknown option in second argument (%u).\n", mode);
+ script_pushint(st, -2);
+ return false;
+ }
+
+ return true;
+}
+
+static BUILDIN(getmapflag)
{
int16 m,i;
const char *str;
@@ -11808,14 +13572,19 @@ BUILDIN(getmapflag)
case MF_RESET: script_pushint(st,map->list[m].flag.reset); break;
case MF_NOTOMB: script_pushint(st,map->list[m].flag.notomb); break;
case MF_NOCASHSHOP: script_pushint(st,map->list[m].flag.nocashshop); break;
- case MF_NOVIEWID: script_pushint(st,map->list[m].flag.noviewid); break;
+ case MF_NOAUTOLOOT: script_pushint(st, map->list[m].flag.noautoloot); break;
+ case MF_NOVIEWID: script_pushint(st, map->list[m].flag.noviewid); break;
+ case MF_PAIRSHIP_STARTABLE: script_pushint(st, map->list[m].flag.pairship_startable); break;
+ case MF_PAIRSHIP_ENDABLE: script_pushint(st, map->list[m].flag.pairship_endable); break;
+ case MF_NOSTORAGE: script_pushint(st, map->list[m].flag.nostorage); break;
+ case MF_NOGSTORAGE: script_pushint(st, map->list[m].flag.nogstorage); break;
}
}
return true;
}
/* pvp timer handling */
-int script_mapflag_pvp_sub(struct block_list *bl, va_list ap)
+static int script_mapflag_pvp_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
@@ -11824,7 +13593,8 @@ int script_mapflag_pvp_sub(struct block_list *bl, va_list ap)
sd = BL_UCAST(BL_PC, bl);
if (sd->pvp_timer == INVALID_TIMER) {
- sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+ if (!map->list[sd->bl.m].flag.pvp_nocalcrank)
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -11836,7 +13606,8 @@ int script_mapflag_pvp_sub(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(setmapflag) {
+static BUILDIN(setmapflag)
+{
int16 m,i;
const char *str, *val2 = NULL;
int val=0;
@@ -11875,6 +13646,7 @@ BUILDIN(setmapflag) {
case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 1; break;
case MF_GVG: {
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
map->list[m].flag.gvg = 1;
clif->map_property_mapall(m, MAPPROPERTY_AGITZONE);
bl.type = BL_NUL;
@@ -11932,14 +13704,20 @@ BUILDIN(setmapflag) {
case MF_RESET: map->list[m].flag.reset = 1; break;
case MF_NOTOMB: map->list[m].flag.notomb = 1; break;
case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 1; break;
+ case MF_NOAUTOLOOT: map->list[m].flag.noautoloot = 1; break;
case MF_NOVIEWID: map->list[m].flag.noviewid = (val <= 0) ? EQP_NONE : val; break;
+ case MF_PAIRSHIP_STARTABLE: map->list[m].flag.pairship_startable = 1; break;
+ case MF_PAIRSHIP_ENDABLE: map->list[m].flag.pairship_endable = 1; break;
+ case MF_NOSTORAGE: map->list[m].flag.nostorage = cap_value(val, 0, 3); break;
+ case MF_NOGSTORAGE: map->list[m].flag.nogstorage = cap_value(val, 0, 3); break;
}
}
return true;
}
-BUILDIN(removemapflag) {
+static BUILDIN(removemapflag)
+{
int16 m,i;
const char *str;
@@ -11957,6 +13735,7 @@ BUILDIN(removemapflag) {
case MF_NOZENYPENALTY: map->list[m].flag.nozenypenalty = 0; break;
case MF_PVP: {
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
bl.type = BL_NUL;
bl.m = m;
map->list[m].flag.pvp = 0;
@@ -11968,6 +13747,7 @@ BUILDIN(removemapflag) {
case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 0; break;
case MF_GVG: {
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
bl.type = BL_NUL;
bl.m = m;
map->list[m].flag.gvg = 0;
@@ -12019,14 +13799,17 @@ BUILDIN(removemapflag) {
case MF_RESET: map->list[m].flag.reset = 0; break;
case MF_NOTOMB: map->list[m].flag.notomb = 0; break;
case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 0; break;
+ case MF_NOAUTOLOOT: map->list[m].flag.noautoloot = 0; break;
case MF_NOVIEWID: map->list[m].flag.noviewid = EQP_NONE; break;
+ case MF_NOSTORAGE: map->list[m].flag.nostorage = 0; break;
+ case MF_NOGSTORAGE: map->list[m].flag.nogstorage = 0; break;
}
}
return true;
}
-BUILDIN(pvpon)
+static BUILDIN(pvpon)
{
int16 m;
const char *str;
@@ -12034,6 +13817,7 @@ BUILDIN(pvpon)
struct s_mapiterator* iter;
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
str = script_getstr(st,2);
m = map->mapname2mapid(str);
if( m < 0 || map->list[m].flag.pvp )
@@ -12059,7 +13843,8 @@ BUILDIN(pvpon)
if( sd->bl.m != m || sd->pvp_timer != INVALID_TIMER )
continue; // not applicable
- sd->pvp_timer = timer->add(timer->gettick()+200,pc->calc_pvprank_timer,sd->bl.id,0);
+ if (!map->list[m].flag.pvp_nocalcrank)
+ sd->pvp_timer = timer->add(timer->gettick()+200,pc->calc_pvprank_timer,sd->bl.id,0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -12071,7 +13856,7 @@ BUILDIN(pvpon)
return true;
}
-int buildin_pvpoff_sub(struct block_list *bl, va_list ap)
+static int buildin_pvpoff_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
@@ -12087,11 +13872,13 @@ int buildin_pvpoff_sub(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(pvpoff) {
+static BUILDIN(pvpoff)
+{
int16 m;
const char *str;
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
str=script_getstr(st,2);
m = map->mapname2mapid(str);
if(m < 0 || !map->list[m].flag.pvp)
@@ -12111,7 +13898,8 @@ BUILDIN(pvpoff) {
return true;
}
-BUILDIN(gvgon) {
+static BUILDIN(gvgon)
+{
int16 m;
const char *str;
@@ -12120,6 +13908,7 @@ BUILDIN(gvgon) {
if(m >= 0 && !map->list[m].flag.gvg) {
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
if( !strdb_exists(map->zone_db,MAP_ZONE_GVG_NAME) ) {
ShowError("buildin_gvgon: zone_db missing '%s'\n",MAP_ZONE_GVG_NAME);
return true;
@@ -12135,7 +13924,8 @@ BUILDIN(gvgon) {
return true;
}
-BUILDIN(gvgoff) {
+static BUILDIN(gvgoff)
+{
int16 m;
const char *str;
@@ -12143,6 +13933,7 @@ BUILDIN(gvgoff) {
m = map->mapname2mapid(str);
if(m >= 0 && map->list[m].flag.gvg) {
struct block_list bl;
+ memset(&bl, 0, sizeof(bl));
map->zone_change2(m, map->list[m].prev_zone);
map->list[m].flag.gvg = 0;
clif->map_property_mapall(m, MAPPROPERTY_NOTHING);
@@ -12158,7 +13949,8 @@ BUILDIN(gvgoff) {
* emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name>
*------------------------------------------*/
//Optional second parameter added by [Skotlex]
-BUILDIN(emotion) {
+static BUILDIN(emotion)
+{
int type;
int player=0;
@@ -12187,7 +13979,7 @@ BUILDIN(emotion) {
return true;
}
-int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap)
+static int buildin_maprespawnguildid_sub_pc(struct map_session_data *sd, va_list ap)
{
int16 m=va_arg(ap,int);
int g_id=va_arg(ap,int);
@@ -12204,7 +13996,7 @@ int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap)
return 1;
}
-int buildin_maprespawnguildid_sub_mob(struct block_list *bl, va_list ap)
+static int buildin_maprespawnguildid_sub_mob(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
@@ -12218,7 +14010,8 @@ int buildin_maprespawnguildid_sub_mob(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(maprespawnguildid) {
+static BUILDIN(maprespawnguildid)
+{
const char *mapname=script_getstr(st,2);
int g_id=script_getnum(st,3);
int flag=script_getnum(st,4);
@@ -12235,28 +14028,32 @@ BUILDIN(maprespawnguildid) {
return true;
}
-BUILDIN(agitstart) {
+static BUILDIN(agitstart)
+{
if(map->agit_flag==1) return true; // Agit already Start.
map->agit_flag=1;
guild->agit_start();
return true;
}
-BUILDIN(agitend) {
+static BUILDIN(agitend)
+{
if(map->agit_flag==0) return true; // Agit already End.
map->agit_flag=0;
guild->agit_end();
return true;
}
-BUILDIN(agitstart2) {
+static BUILDIN(agitstart2)
+{
if(map->agit2_flag==1) return true; // Agit2 already Start.
map->agit2_flag=1;
guild->agit2_start();
return true;
}
-BUILDIN(agitend2) {
+static BUILDIN(agitend2)
+{
if(map->agit2_flag==0) return true; // Agit2 already End.
map->agit2_flag=0;
guild->agit2_end();
@@ -12266,7 +14063,8 @@ BUILDIN(agitend2) {
/*==========================================
* Returns whether woe is on or off.
*------------------------------------------*/
-BUILDIN(agitcheck) {
+static BUILDIN(agitcheck)
+{
script_pushint(st,map->agit_flag);
return true;
}
@@ -12274,7 +14072,8 @@ BUILDIN(agitcheck) {
/*==========================================
* Returns whether woese is on or off.
*------------------------------------------*/
-BUILDIN(agitcheck2) {
+static BUILDIN(agitcheck2)
+{
script_pushint(st,map->agit2_flag);
return true;
}
@@ -12282,7 +14081,7 @@ BUILDIN(agitcheck2) {
/// Sets the guild_id of this npc.
///
/// flagemblem <guild_id>;
-BUILDIN(flagemblem)
+static BUILDIN(flagemblem)
{
struct npc_data *nd;
int g_id = script_getnum(st,2);
@@ -12307,7 +14106,7 @@ BUILDIN(flagemblem)
return true;
}
-BUILDIN(getcastlename)
+static BUILDIN(getcastlename)
{
const char* mapname = mapindex->getmapname(script_getstr(st,2),NULL);
struct guild_castle* gc = guild->mapname2gc(mapname);
@@ -12316,7 +14115,7 @@ BUILDIN(getcastlename)
return true;
}
-BUILDIN(getcastledata)
+static BUILDIN(getcastledata)
{
const char *mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int index = script_getnum(st,3);
@@ -12359,7 +14158,7 @@ BUILDIN(getcastledata)
return true;
}
-BUILDIN(setcastledata)
+static BUILDIN(setcastledata)
{
const char *mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int index = script_getnum(st,3);
@@ -12382,7 +14181,7 @@ BUILDIN(setcastledata)
/* =====================================================================
* ---------------------------------------------------------------------*/
-BUILDIN(requestguildinfo)
+static BUILDIN(requestguildinfo)
{
int guild_id=script_getnum(st,2);
const char *event=NULL;
@@ -12399,7 +14198,7 @@ BUILDIN(requestguildinfo)
/// Returns the number of cards that have been compounded onto the specified equipped item.
/// getequipcardcnt(<equipment slot>);
-BUILDIN(getequipcardcnt)
+static BUILDIN(getequipcardcnt)
{
int i=-1,j,num;
struct map_session_data *sd;
@@ -12436,149 +14235,116 @@ BUILDIN(getequipcardcnt)
/// Removes all cards from the item found in the specified equipment slot of the invoking character,
/// and give them to the character. If any cards were removed in this manner, it will also show a success effect.
-/// successremovecards <slot>;
-BUILDIN(successremovecards)
+/// successremovecards(<slot>);
+static BUILDIN(successremovecards)
{
- int i=-1,c,cardflag=0;
+ int i = -1, c, cardflag = 0;
struct map_session_data *sd = script->rid2sd(st);
- int num = script_getnum(st,2);
+ int num = script_getnum(st, 2);
if (sd == NULL)
return true;
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
+ i = pc->checkequip(sd,script->equip[num - 1]);
- if (i < 0 || !sd->inventory_data[i]) {
+ if (i < 0 || sd->inventory_data[i] == NULL)
return true;
- }
- if(itemdb_isspecial(sd->status.inventory[i].card[0]))
+ if (itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
- for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
- if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item
+ for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) {
+ if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) {
int flag;
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+
cardflag = 1;
- item_tmp.nameid = sd->status.inventory[i].card[c];
+ item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
+ sd->status.inventory[i].card[c] = 0;
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- // get back the cart in inventory
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) {
+ clif->additem(sd, 0, 0, flag);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
if (cardflag == 1) {
- //if card was remove replace item with no card
- int flag, j;
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
-
- item_tmp.nameid = sd->status.inventory[i].nameid;
- item_tmp.identify = 1;
- item_tmp.refine = sd->status.inventory[i].refine;
- item_tmp.attribute = sd->status.inventory[i].attribute;
- item_tmp.expire_time = sd->status.inventory[i].expire_time;
- item_tmp.bound = sd->status.inventory[i].bound;
-
- for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
- item_tmp.card[j]=sd->status.inventory[i].card[j];
-
- pc->delitem(sd, i, 1, 0, DELITEM_MATERIALCHANGE, LOG_TYPE_SCRIPT);
- if ((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- //chk if can be spawn in inventory otherwise put on floor
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
- }
-
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
+ clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE);
+ clif->additem(sd, i, 1, 0);
+ pc->equipitem(sd, i, sd->status.inventory[i].equip);
clif->misceffect(&sd->bl,3);
}
return true;
}
/// Removes all cards from the item found in the specified equipment slot of the invoking character.
-/// failedremovecards <slot>, <type>;
+/// failedremovecards(<slot>, <type>);
/// <type>=0 : will destroy both the item and the cards.
/// <type>=1 : will keep the item, but destroy the cards.
/// <type>=2 : will keep the cards, but destroy the item.
-/// <type>=? : will just display the failure effect.
-BUILDIN(failedremovecards)
+/// <type>=3 : will just display the failure effect.
+static BUILDIN(failedremovecards)
{
- int i=-1,c,cardflag=0;
+ int i = -1, c, cardflag = 0;
+ int num = script_getnum(st, 2);
+ int typefail = script_getnum(st, 3);
struct map_session_data *sd = script->rid2sd(st);
- int num = script_getnum(st,2);
- int typefail = script_getnum(st,3);
if (sd == NULL)
return true;
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
+ i = pc->checkequip(sd, script->equip[num - 1]);
- if (i < 0 || !sd->inventory_data[i])
+ if (i < 0 || sd->inventory_data[i] == NULL)
return true;
- if(itemdb_isspecial(sd->status.inventory[i].card[0]))
+ if (itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
- for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
- if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {
+ for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) {
+ if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) {
cardflag = 1;
- if(typefail == 2) {// add cards to inventory, clear
+ if (typefail == 1)
+ sd->status.inventory[i].card[c] = 0;
+
+ if (typefail == 2) { // add cards to inventory, clear
int flag;
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
+ memset(&item_tmp, 0, sizeof(item_tmp));
- item_tmp.nameid = sd->status.inventory[i].card[c];
+ item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) {
+ clif->additem(sd, 0, 0, flag);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
}
if (cardflag == 1) {
- if (typefail == 0 || typefail == 2) {
- // destroy the item
+ if (typefail == 0 || typefail == 2) { // destroy the item
pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT);
} else if (typefail == 1) {
- // destroy the card
- int flag, j;
- struct item item_tmp;
-
- memset(&item_tmp,0,sizeof(item_tmp));
-
- item_tmp.nameid = sd->status.inventory[i].nameid;
- item_tmp.identify = 1;
- item_tmp.refine = sd->status.inventory[i].refine;
- item_tmp.attribute = sd->status.inventory[i].attribute;
- item_tmp.expire_time = sd->status.inventory[i].expire_time;
- item_tmp.bound = sd->status.inventory[i].bound;
-
- for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
- item_tmp.card[j]=sd->status.inventory[i].card[j];
-
- pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT);
-
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
- }
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
+ clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE);
+ clif->additem(sd, i, 1, 0);
+ pc->equipitem(sd, i, sd->status.inventory[i].equip);
}
- clif->misceffect(&sd->bl,2);
}
+ clif->misceffect(&sd->bl, 2);
return true;
}
@@ -12589,7 +14355,8 @@ BUILDIN(failedremovecards)
* improved by [Lance]
* ================================================================*/
// Added by RoVeRT
-BUILDIN(mapwarp) {
+static BUILDIN(mapwarp)
+{
int x,y,m,check_val=0,check_ID=0,i=0;
struct guild *g = NULL;
struct party_data *p = NULL;
@@ -12642,7 +14409,7 @@ BUILDIN(mapwarp) {
}
// Added by RoVeRT
-int buildin_mobcount_sub(struct block_list *bl, va_list ap)
+static int buildin_mobcount_sub(struct block_list *bl, va_list ap)
{
char *event = va_arg(ap,char *);
const struct mob_data *md = NULL;
@@ -12657,7 +14424,8 @@ int buildin_mobcount_sub(struct block_list *bl, va_list ap)
}
// Added by RoVeRT
-BUILDIN(mobcount) {
+static BUILDIN(mobcount)
+{
const char *mapname,*event;
int16 m;
mapname=script_getstr(st,2);
@@ -12690,7 +14458,8 @@ BUILDIN(mobcount) {
return true;
}
-BUILDIN(marriage) {
+static BUILDIN(marriage)
+{
const char *partner=script_getstr(st,2);
struct map_session_data *sd = script->rid2sd(st);
struct map_session_data *p_sd = script->nick2sd(st, partner);
@@ -12702,7 +14471,7 @@ BUILDIN(marriage) {
script_pushint(st,1);
return true;
}
-BUILDIN(wedding_effect)
+static BUILDIN(wedding_effect)
{
struct map_session_data *sd = script->rid2sd(st);
struct block_list *bl;
@@ -12714,7 +14483,7 @@ BUILDIN(wedding_effect)
clif->wedding_effect(bl);
return true;
}
-BUILDIN(divorce)
+static BUILDIN(divorce)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL || pc->divorce(sd) < 0) {
@@ -12725,7 +14494,8 @@ BUILDIN(divorce)
return true;
}
-BUILDIN(ispartneron) {
+static BUILDIN(ispartneron)
+{
struct map_session_data *sd = script->rid2sd(st);
if (sd==NULL || !pc->ismarried(sd)
@@ -12738,7 +14508,7 @@ BUILDIN(ispartneron) {
return true;
}
-BUILDIN(getpartnerid)
+static BUILDIN(getpartnerid)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -12748,7 +14518,7 @@ BUILDIN(getpartnerid)
return true;
}
-BUILDIN(getchildid)
+static BUILDIN(getchildid)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -12758,7 +14528,7 @@ BUILDIN(getchildid)
return true;
}
-BUILDIN(getmotherid)
+static BUILDIN(getmotherid)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -12768,7 +14538,8 @@ BUILDIN(getmotherid)
return true;
}
-BUILDIN(getfatherid) {
+static BUILDIN(getfatherid)
+{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
@@ -12777,7 +14548,7 @@ BUILDIN(getfatherid) {
return true;
}
-BUILDIN(warppartner)
+static BUILDIN(warppartner)
{
int x,y;
unsigned short map_index;
@@ -12807,7 +14578,7 @@ BUILDIN(warppartner)
/*================================================
* Script for Displaying MOB Information [Valaris]
*------------------------------------------------*/
-BUILDIN(strmobinfo)
+static BUILDIN(strmobinfo)
{
int num=script_getnum(st,2);
@@ -12837,52 +14608,60 @@ BUILDIN(strmobinfo)
return true;
}
-/*==========================================
- * Summon guardians [Valaris]
- * guardian("<map name>",<x>,<y>,"<name to show>",<mob id>{,"<event label>"}{,<guardian index>}) -> <id>
- *------------------------------------------*/
-BUILDIN(guardian) {
- int class_ = 0, x = 0, y = 0, guardian = 0;
- const char *str, *mapname, *evt="";
+/**
+ * Summons a castle guardian mob.
+ *
+ * @code{.herc}
+ * guardian("<map name>", <x>, <y>, "<name to show>", <mob id>{, <guardian index>});
+ * guardian("<map name>", <x>, <y>, "<name to show>", <mob id>{, "<event label>"{, <guardian index>}});
+ * @endcode
+ *
+ * @author Valaris
+ *
+ **/
+static BUILDIN(guardian)
+{
bool has_index = false;
+ int guardian = 0;
+ const char *event = "";
- mapname = script_getstr(st,2);
- x = script_getnum(st,3);
- y = script_getnum(st,4);
- str = script_getstr(st,5);
- class_ = script_getnum(st,6);
-
- if( script_hasdata(st,8) )
- {// "<event label>",<guardian index>
- evt=script_getstr(st,7);
- guardian=script_getnum(st,8);
+ if (script_hasdata(st, 8)) { /// "<event label>", <guardian index>
+ event = script_getstr(st, 7);
+ script->check_event(st, event);
+ guardian = script_getnum(st, 8);
has_index = true;
- } else if( script_hasdata(st,7) ) {
- struct script_data *data = script_getdata(st,7);
- script->get_val(st,data); // Dereference if it's a variable
- if( data_isstring(data) ) {
- // "<event label>"
- evt=script_getstr(st,7);
- } else if( data_isint(data) ) {
- // <guardian index>
- guardian=script_getnum(st,7);
+ } else if (script_hasdata(st, 7)) {
+ struct script_data *data = script_getdata(st, 7);
+
+ script->get_val(st, data); /// Dereference if it's a variable.
+
+ if (data_isstring(data)) { /// "<event label>"
+ event = script_getstr(st, 7);
+ script->check_event(st, event);
+ } else if (data_isint(data)) { /// <guardian index>
+ guardian = script_getnum(st, 7);
has_index = true;
} else {
- ShowError("script:guardian: invalid data type for argument #6 (from 1)\n");
+ ShowError("script:guardian: Invalid data type for argument #6!\n");
script->reportdata(data);
return false;
}
}
- script->check_event(st, evt);
- script_pushint(st, mob->spawn_guardian(mapname,x,y,str,class_,evt,guardian,has_index));
+ const char *mapname = script_getstr(st, 2);
+ const char *name = script_getstr(st, 5);
+ const int x = script_getnum(st, 3);
+ const int y = script_getnum(st, 4);
+ const int mob_id = script_getnum(st, 6);
+ script_pushint(st, mob->spawn_guardian(mapname, x, y, name, mob_id, event, guardian, has_index, st->oid));
return true;
}
/*==========================================
* Invisible Walls [Zephyrus]
*------------------------------------------*/
-BUILDIN(setwall) {
+static BUILDIN(setwall)
+{
const char *mapname, *name;
int x, y, m, size, dir;
bool shootable;
@@ -12901,9 +14680,15 @@ BUILDIN(setwall) {
map->iwall_set(m, x, y, size, dir, shootable, name);
return true;
}
-BUILDIN(delwall) {
+
+static BUILDIN(delwall)
+{
const char *name = script_getstr(st,2);
- map->iwall_remove(name);
+
+ if (!map->iwall_remove(name)) {
+ ShowWarning("buildin_delwall: Non-existent '%s' provided.\n", name);
+ return false;
+ }
return true;
}
@@ -12915,7 +14700,8 @@ BUILDIN(delwall) {
/// 1 - maximum hp
/// 2 - current hp
///
-BUILDIN(guardianinfo) {
+static BUILDIN(guardianinfo)
+{
const char* mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int id = script_getnum(st,3);
int type = script_getnum(st,4);
@@ -12947,7 +14733,8 @@ BUILDIN(guardianinfo) {
/*==========================================
* Get the item name by item_id or null
*------------------------------------------*/
-BUILDIN(getitemname) {
+static BUILDIN(getitemname)
+{
int item_id=0;
struct item_data *i_data;
char *item_name;
@@ -12975,7 +14762,7 @@ BUILDIN(getitemname) {
/*==========================================
* Returns number of slots an item has. [Skotlex]
*------------------------------------------*/
-BUILDIN(getitemslots)
+static BUILDIN(getitemslots)
{
int item_id;
struct item_data *i_data;
@@ -12991,88 +14778,529 @@ BUILDIN(getitemslots)
return true;
}
-// TODO: add matk here if needed/once we get rid of RENEWAL
+/**
+ * Returns various information about an item.
+ *
+ * @code{.herc}
+ * getiteminfo(<item ID>, <type>);
+ * getiteminfo("<item name>", <type>);
+ * @endcode
+ *
+ **/
+static BUILDIN(getiteminfo)
+{
+ struct item_data *it;
-/*==========================================
- * Returns some values of an item [Lupus]
- * Price, Weight, etc...
- * getiteminfo(itemID,n), where n
- * 0 value_buy;
- * 1 value_sell;
- * 2 type;
- * 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
- * if = 0, then monsters don't drop it at all (rare or a quest item)
- * if = -1, then this item is sold in NPC shops only
- * 4 sex;
- * 5 equip;
- * 6 weight;
- * 7 atk;
- * 8 def;
- * 9 range;
- * 10 slot;
- * 11 look;
- * 12 elv;
- * 13 wlv;
- * 14 view id
- *------------------------------------------*/
-BUILDIN(getiteminfo)
+ if (script_isstringtype(st, 2)) { /// Item name.
+ const char *name = script_getstr(st, 2);
+ it = itemdb->search_name(name);
+ } else { /// Item ID.
+ it = itemdb->exists(script_getnum(st, 2));
+ }
+
+ if (it == NULL) {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ int type = script_getnum(st, 3);
+
+ switch (type) {
+ case ITEMINFO_BUYPRICE:
+ script_pushint(st, it->value_buy);
+ break;
+ case ITEMINFO_SELLPRICE:
+ script_pushint(st, it->value_sell);
+ break;
+ case ITEMINFO_TYPE:
+ script_pushint(st, it->type);
+ break;
+ case ITEMINFO_MAXCHANCE:
+ script_pushint(st, it->maxchance);
+ break;
+ case ITEMINFO_SEX:
+ script_pushint(st, it->sex);
+ break;
+ case ITEMINFO_LOC:
+ script_pushint(st, it->equip);
+ break;
+ case ITEMINFO_WEIGHT:
+ script_pushint(st, it->weight);
+ break;
+ case ITEMINFO_ATK:
+ script_pushint(st, it->atk);
+ break;
+ case ITEMINFO_DEF:
+ script_pushint(st, it->def);
+ break;
+ case ITEMINFO_RANGE:
+ script_pushint(st, it->range);
+ break;
+ case ITEMINFO_SLOTS:
+ script_pushint(st, it->slot);
+ break;
+ case ITEMINFO_SUBTYPE:
+ script_pushint(st, it->subtype);
+ break;
+ case ITEMINFO_ELV:
+ script_pushint(st, it->elv);
+ break;
+ case ITEMINFO_WLV:
+ script_pushint(st, it->wlv);
+ break;
+ case ITEMINFO_VIEWID:
+ script_pushint(st, it->view_id);
+ break;
+ case ITEMINFO_MATK:
+ script_pushint(st, it->matk);
+ break;
+ case ITEMINFO_VIEWSPRITE:
+ script_pushint(st, it->view_sprite);
+ break;
+ case ITEMINFO_TRADE:
+ script_pushint(st, it->flag.trade_restriction);
+ break;
+ case ITEMINFO_ELV_MAX:
+ script_pushint(st, it->elvmax);
+ break;
+ case ITEMINFO_DROPEFFECT_MODE:
+ script_pushint(st, it->dropeffectmode);
+ break;
+ case ITEMINFO_DELAY:
+ script_pushint(st, it->delay);
+ break;
+ case ITEMINFO_CLASS_BASE_1:
+ script_pushint(st, it->class_base[0]);
+ break;
+ case ITEMINFO_CLASS_BASE_2:
+ script_pushint(st, it->class_base[1]);
+ break;
+ case ITEMINFO_CLASS_BASE_3:
+ script_pushint(st, it->class_base[2]);
+ break;
+ case ITEMINFO_CLASS_UPPER:
+ script_pushint(st, it->class_upper);
+ break;
+ case ITEMINFO_FLAG_NO_REFINE:
+ script_pushint(st, it->flag.no_refine);
+ break;
+ case ITEMINFO_FLAG_DELAY_CONSUME:
+ script_pushint(st, it->flag.delay_consume);
+ break;
+ case ITEMINFO_FLAG_AUTOEQUIP:
+ script_pushint(st, it->flag.autoequip);
+ break;
+ case ITEMINFO_FLAG_AUTO_FAVORITE:
+ script_pushint(st, it->flag.auto_favorite);
+ break;
+ case ITEMINFO_FLAG_BUYINGSTORE:
+ script_pushint(st, it->flag.buyingstore);
+ break;
+ case ITEMINFO_FLAG_BINDONEQUIP:
+ script_pushint(st, it->flag.bindonequip);
+ break;
+ case ITEMINFO_FLAG_KEEPAFTERUSE:
+ script_pushint(st, it->flag.keepafteruse);
+ break;
+ case ITEMINFO_FLAG_FORCE_SERIAL:
+ script_pushint(st, it->flag.force_serial);
+ break;
+ case ITEMINFO_FLAG_NO_OPTIONS:
+ script_pushint(st, it->flag.no_options);
+ break;
+ case ITEMINFO_FLAG_DROP_ANNOUNCE:
+ script_pushint(st, it->flag.drop_announce);
+ break;
+ case ITEMINFO_FLAG_SHOWDROPEFFECT:
+ script_pushint(st, it->flag.showdropeffect);
+ break;
+ case ITEMINFO_STACK_AMOUNT:
+ script_pushint(st, it->stack.amount);
+ break;
+ case ITEMINFO_STACK_FLAG: {
+ int stack_flag = 0;
+
+ if (it->stack.inventory != 0)
+ stack_flag |= 1;
+
+ if (it->stack.cart != 0)
+ stack_flag |= 2;
+
+ if (it->stack.storage != 0)
+ stack_flag |= 4;
+
+ if (it->stack.guildstorage != 0)
+ stack_flag |= 8;
+
+ script_pushint(st, stack_flag);
+ break;
+ }
+ case ITEMINFO_ITEM_USAGE_FLAG:
+ script_pushint(st, it->item_usage.flag);
+ break;
+ case ITEMINFO_ITEM_USAGE_OVERRIDE:
+ script_pushint(st, it->item_usage.override);
+ break;
+ case ITEMINFO_GM_LV_TRADE_OVERRIDE:
+ script_pushint(st, it->gm_lv_trade_override);
+ break;
+ case ITEMINFO_ID:
+ script_pushint(st, it->nameid);
+ break;
+ case ITEMINFO_AEGISNAME:
+ script_pushstrcopy(st, it->name);
+ break;
+ case ITEMINFO_NAME:
+ script_pushstrcopy(st, it->jname);
+ break;
+ default:
+ ShowError("buildin_getiteminfo: Invalid item info type %d.\n", type);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Returns the value of the current equipment being parsed using static variables -
+ * current_equip_item_index and current_equip_option_index.
+ * !!Designed to be used with item_options.conf only!!
+ * *getequippedoptioninfo(<info_type>);
+ *
+ * @param (int) Types -
+ * IT_OPT_INDEX ID of the item option.
+ * IT_OPT_VALUE Amount of the bonus to be added.
+ * @return value of the type or -1.
+ */
+static BUILDIN(getequippedoptioninfo)
{
- int item_id,n;
- struct item_data *i_data;
+ int val = 0, type = script_getnum(st, 2);
+ struct map_session_data *sd = NULL;
+
+ if ((sd = script->rid2sd(st)) == NULL || status->current_equip_item_index == -1 || status->current_equip_option_index == -1
+ || !sd->status.inventory[status->current_equip_item_index].option[status->current_equip_option_index].index) {
+ script_pushint(st, -1);
+ return false;
+ }
+
+ switch (type) {
+ case IT_OPT_INDEX:
+ val = sd->status.inventory[status->current_equip_item_index].option[status->current_equip_option_index].index;
+ break;
+ case IT_OPT_VALUE:
+ val = sd->status.inventory[status->current_equip_item_index].option[status->current_equip_option_index].value;
+ break;
+ default:
+ ShowError("buildin_getequippedoptioninfo: Invalid option data type %d (Max %d).\n", type, IT_OPT_MAX-1);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ script_pushint(st, val);
+
+ return true;
+}
- item_id = script_getnum(st,2);
- n = script_getnum(st,3);
- i_data = itemdb->exists(item_id);
+/**
+ * Gets the option information of an equipment.
+ * *getequipoption(<equip_index>,<slot>,<type>);
+ *
+ * @param equip_index as the Index of the Equipment.
+ * @param slot as the slot# of the Item Option (1 to MAX_ITEM_OPTIONS)
+ * @param type IT_OPT_INDEX or IT_OPT_VALUE.
+ * @return (int) value or -1 on failure.
+ */
+static BUILDIN(getequipoption)
+{
+ int val = 0, equip_index = script_getnum(st, 2);
+ int slot = script_getnum(st, 3);
+ int opt_type = script_getnum(st, 4);
+ int i = -1;
+ struct map_session_data *sd = script->rid2sd(st);
- if (i_data && n>=0 && n<=14) {
- int *item_arr = (int*)&i_data->value_buy;
- script_pushint(st,item_arr[n]);
+ if (sd == NULL) {
+ script_pushint(st, -1);
+ ShowError("buildin_getequipoption: Player not attached!\n");
+ return false;
+ }
+
+ if (slot <= 0 || slot > MAX_ITEM_OPTIONS) {
+ script_pushint(st, -1);
+ ShowError("buildin_getequipoption: Invalid option slot %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
+ return false;
+ }
+
+ if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) {
+ if ((i = pc->checkequip(sd, script->equip[equip_index - 1])) == -1) {
+ ShowError("buildin_getequipoption: No equipment is equipped in the given index %d.\n", equip_index);
+ script_pushint(st, -1);
+ return false;
+ }
} else {
- script_pushint(st,-1);
+ ShowError("buildin_getequipoption: Invalid equipment index %d provided.\n", equip_index);
+ script_pushint(st, 0);
+ return false;
}
+
+ if (sd->status.inventory[i].nameid != 0) {
+ switch (opt_type) {
+ case IT_OPT_INDEX:
+ val = sd->status.inventory[i].option[slot-1].index;
+ break;
+ case IT_OPT_VALUE:
+ val = sd->status.inventory[i].option[slot-1].value;
+ break;
+ default:
+ ShowError("buildin_getequipoption: Invalid option data type %d provided.\n", opt_type);
+ script_pushint(st, -1);
+ break;
+ }
+ }
+
+ script_pushint(st, val);
+
return true;
}
+/**
+ * Set an equipment's option value.
+ * *setequipoption(<equip_index>,<slot>,<opt_index>,<value>);
+ *
+ * @param equip_index as the inventory index of the equipment.
+ * @param slot as the slot of the item option (1 to MAX_ITEM_OPTIONS)
+ * @param opt_index as the index of the option available as "Id" in db/item_options.conf.
+ * @param value as the value of the option type.
+ * For IT_OPT_INDEX see "Name" in item_options.conf
+ * For IT_OPT_VALUE, the value of the script bonus.
+ * @return 0 on failure, 1 on success.
+ */
+static BUILDIN(setequipoption)
+{
+ int equip_index = script_getnum(st, 2);
+ int slot = script_getnum(st, 3);
+ int opt_index = script_getnum(st, 4);
+ int value = script_getnum(st, 5);
+ int i = -1;
+
+ struct map_session_data *sd = script->rid2sd(st);
+ struct itemdb_option *ito = NULL;
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipoption: Player not attached!\n");
+ return false;
+ }
+
+ if (slot <= 0 || slot > MAX_ITEM_OPTIONS) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipoption: Invalid option index %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
+ return false;
+ }
+
+ if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) {
+ if ((i = pc->checkequip(sd, script->equip[equip_index - 1])) == -1) {
+ ShowError("buildin_setequipoption: No equipment is equipped in the given index %d.\n", equip_index);
+ script_pushint(st, 0);
+ return false;
+ }
+ } else {
+ ShowError("buildin_setequipoption: Invalid equipment index %d provided.\n", equip_index);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (sd->status.inventory[i].nameid != 0) {
+ if (opt_index == 0) {
+ // Remove the option
+ sd->status.inventory[i].option[slot-1].index = 0;
+ sd->status.inventory[i].option[slot-1].value = 0;
+ } else {
+ if ((ito = itemdb->option_exists(opt_index)) == NULL) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipotion: Option index %d does not exist!\n", opt_index);
+ return false;
+ } else if (value < -INT16_MAX || value > INT16_MAX) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipotion: Option value %d exceeds maximum limit (%d to %d) for type!\n", value, -INT16_MAX, INT16_MAX);
+ return false;
+ }
+ /* Add Option Index */
+ sd->status.inventory[i].option[slot-1].index = ito->index;
+ /* Add Option Value */
+ sd->status.inventory[i].option[slot-1].value = value;
+ }
+
+ /* Unequip and simulate deletion of the item. */
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // status calc will happen in pc->equipitem() below
+ clif->refine(sd->fd, 0, i, sd->status.inventory[i].refine); // notify client of a refine.
+ clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); // notify client to simulate item deletion.
+ /* Log deletion of the item. */
+ logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]);
+ /* Equip and simulate addition of the item. */
+ clif->additem(sd, i, 1, 0); // notify client to simulate item addition.
+ /* Log addition of the item. */
+ logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i], sd->inventory_data[i]);
+ pc->equipitem(sd, i, sd->status.inventory[i].equip); // force equip the item at the original position.
+ clif->misceffect(&sd->bl, 2); // show effect
+ }
+
+ script_pushint(st, 1);
+
+ return true;
+
+}
+
/*==========================================
* Set some values of an item [Lupus]
* Price, Weight, etc...
- * setiteminfo(itemID,n,Value), where n
- * 0 value_buy;
- * 1 value_sell;
- * 2 type;
- * 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
- * if = 0, then monsters don't drop it at all (rare or a quest item)
- * if = -1, then this item is sold in NPC shops only
- * 4 sex;
- * 5 equip;
- * 6 weight;
- * 7 atk;
- * 8 def;
- * 9 range;
- * 10 slot;
- * 11 look;
- * 12 elv;
- * 13 wlv;
- * 14 view id
- * Returns Value or -1 if the wrong field's been set
*------------------------------------------*/
-BUILDIN(setiteminfo)
+static BUILDIN(setiteminfo)
{
- int item_id,n,value;
- struct item_data *i_data;
+ // TODO: Validate data in a similar way as during database load
+ int item_id = script_getnum(st, 2);
+ int n = script_getnum(st, 3);
+ int value = script_getnum(st,4);
+ struct item_data *it = itemdb->exists(item_id);
- item_id = script_getnum(st,2);
- n = script_getnum(st,3);
- value = script_getnum(st,4);
- i_data = itemdb->exists(item_id);
+ if (it == NULL) {
+ script_pushint(st, -1);
+ return true;
+ }
- if (i_data && n>=0 && n<=14) {
- int *item_arr = (int*)&i_data->value_buy;
- item_arr[n] = value;
- script_pushint(st,value);
- } else {
+ switch (n) {
+ case ITEMINFO_BUYPRICE:
+ it->value_buy = value;
+ break;
+ case ITEMINFO_SELLPRICE:
+ it->value_sell = value;
+ break;
+ case ITEMINFO_TYPE:
+ it->type = value;
+ break;
+ case ITEMINFO_MAXCHANCE:
+ it->maxchance = value;
+ break;
+ case ITEMINFO_SEX:
+ it->sex = value;
+ break;
+ case ITEMINFO_LOC:
+ it->equip = value;
+ break;
+ case ITEMINFO_WEIGHT:
+ it->weight = value;
+ break;
+ case ITEMINFO_ATK:
+ it->atk = value;
+ break;
+ case ITEMINFO_DEF:
+ it->def = value;
+ break;
+ case ITEMINFO_RANGE:
+ it->range = value;
+ break;
+ case ITEMINFO_SLOTS:
+ it->slot = value;
+ break;
+ case ITEMINFO_SUBTYPE:
+ it->subtype = value;
+ break;
+ case ITEMINFO_ELV:
+ it->elv = value;
+ break;
+ case ITEMINFO_WLV:
+ it->wlv = value;
+ break;
+ case ITEMINFO_VIEWID:
+ it->view_id = value;
+ break;
+ case ITEMINFO_MATK:
+ it->matk = value;
+ break;
+ case ITEMINFO_VIEWSPRITE:
+ it->view_sprite = value;
+ break;
+ case ITEMINFO_TRADE:
+ it->flag.trade_restriction = value;
+ break;
+ case ITEMINFO_ELV_MAX:
+ it->elvmax = cap_value(value, 0, MAX_LEVEL);
+ break;
+ case ITEMINFO_DROPEFFECT_MODE:
+ it->dropeffectmode = value;
+ break;
+ case ITEMINFO_DELAY:
+ it->delay = value;
+ break;
+ case ITEMINFO_CLASS_BASE_1:
+ it->class_base[0] = value;
+ break;
+ case ITEMINFO_CLASS_BASE_2:
+ it->class_base[1] = value;
+ break;
+ case ITEMINFO_CLASS_BASE_3:
+ it->class_base[2] = value;
+ break;
+ case ITEMINFO_CLASS_UPPER:
+ it->class_upper = value;
+ break;
+ case ITEMINFO_FLAG_NO_REFINE:
+ it->flag.no_refine = cap_value(value, 0, MAX_REFINE);
+ break;
+ case ITEMINFO_FLAG_DELAY_CONSUME:
+ it->flag.delay_consume = value;
+ break;
+ case ITEMINFO_FLAG_AUTOEQUIP:
+ it->flag.autoequip = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_AUTO_FAVORITE:
+ it->flag.auto_favorite = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_BUYINGSTORE:
+ it->flag.buyingstore = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_BINDONEQUIP:
+ it->flag.bindonequip = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_KEEPAFTERUSE:
+ it->flag.keepafteruse = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_FORCE_SERIAL:
+ it->flag.force_serial = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_NO_OPTIONS:
+ it->flag.no_options = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_DROP_ANNOUNCE:
+ it->flag.drop_announce = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_FLAG_SHOWDROPEFFECT:
+ it->flag.showdropeffect = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_STACK_AMOUNT:
+ it->stack.amount = cap_value(value, 0, USHRT_MAX);
+ break;
+ case ITEMINFO_STACK_FLAG:
+ it->stack.inventory = ((value & 1) != 0);
+ it->stack.cart = ((value & 2) != 0);
+ it->stack.storage = ((value & 4) != 0);
+ it->stack.guildstorage = ((value & 8) != 0);
+ break;
+ case ITEMINFO_ITEM_USAGE_FLAG:
+ it->item_usage.flag = cap_value(value, 0, 1);
+ break;
+ case ITEMINFO_ITEM_USAGE_OVERRIDE:
+ it->item_usage.override = value;
+ break;
+ case ITEMINFO_GM_LV_TRADE_OVERRIDE:
+ it->gm_lv_trade_override = value;
+ break;
+ default:
+ ShowError("buildin_setiteminfo: invalid type %d.\n", n);
script_pushint(st,-1);
+ return false;
}
+ script_pushint(st,value);
return true;
}
@@ -13088,7 +15316,7 @@ BUILDIN(setiteminfo)
* Useful for such quests as "Sign this refined item with players name" etc
* Hat[0] +4 -> Player's Hat[0] +4
*------------------------------------------*/
-BUILDIN(getequipcardid)
+static BUILDIN(getequipcardid)
{
int i=-1,num,slot;
struct map_session_data *sd;
@@ -13113,7 +15341,7 @@ BUILDIN(getequipcardid)
/*==========================================
* petskillbonus [Valaris] //Rewritten by [Skotlex]
*------------------------------------------*/
-BUILDIN(petskillbonus)
+static BUILDIN(petskillbonus)
{
struct pet_data *pd;
@@ -13150,7 +15378,7 @@ BUILDIN(petskillbonus)
/*==========================================
* pet looting [Valaris] //Rewritten by [Skotlex]
*------------------------------------------*/
-BUILDIN(petloot)
+static BUILDIN(petloot)
{
int max;
struct pet_data *pd;
@@ -13187,96 +15415,119 @@ BUILDIN(petloot)
* Set arrays with info of all sd inventory :
* @inventorylist_id, @inventorylist_amount, @inventorylist_equip,
* @inventorylist_refine, @inventorylist_identify, @inventorylist_attribute,
- * @inventorylist_card(0..3), @inventorylist_expire
+ * @inventorylist_card(0..3),
+ * @inventorylist_opt_id(0..MAX_ITEM_OPTIONS),
+ * @inventorylist_opt_val(0..MAX_ITEM_OPTIONS),
+ * @inventorylist_opt_param(0..MAX_ITEM_OPTIONS),
+ * @inventorylist_expire, @inventorylist_bound, @inventorylist_favorite,
+ * @inventorylist_idx
* @inventorylist_count = scalar
*------------------------------------------*/
-BUILDIN(getinventorylist)
+static BUILDIN(getinventorylist)
{
struct map_session_data *sd = script->rid2sd(st);
- char card_var[NAME_LENGTH];
+ char script_var[SCRIPT_VARNAME_LENGTH];
+ int j = 0, k = 0;
- int i,j=0,k;
- if(!sd) return true;
+ if (sd == NULL)
+ return true;
- for(i=0;i<MAX_INVENTORY;i++) {
- if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) {
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid);
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount);
- if(sd->status.inventory[i].equip) {
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),pc->equippoint(sd,i));
+ for (int i = 0; i < sd->status.inventorySize; i++) {
+ if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) {
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_id"), j), sd->status.inventory[i].nameid);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_amount"), j), sd->status.inventory[i].amount);
+ if (sd->status.inventory[i].equip != 0) {
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_equip"), j), pc->equippoint(sd, i));
} else {
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),0);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_equip"), j), 0);
}
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine);
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify);
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_refine"), j), sd->status.inventory[i].refine);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_identify"), j), sd->status.inventory[i].identify);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_attribute"), j), sd->status.inventory[i].attribute);
for (k = 0; k < MAX_SLOTS; k++) {
- sprintf(card_var, "@inventorylist_card%d",k+1);
- pc->setreg(sd,reference_uid(script->add_str(card_var), j),sd->status.inventory[i].card[k]);
+ sprintf(script_var, "@inventorylist_card%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].card[k]);
}
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time);
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_bound"), j),sd->status.inventory[i].bound);
+ for (k = 0; k < MAX_ITEM_OPTIONS; k++) {
+ sprintf(script_var, "@inventorylist_opt_id%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].index);
+ sprintf(script_var, "@inventorylist_opt_val%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].value);
+ sprintf(script_var, "@inventorylist_opt_param%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(script_var), j), sd->status.inventory[i].option[k].param);
+ }
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_expire"), j), sd->status.inventory[i].expire_time);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_bound"), j), sd->status.inventory[i].bound);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_favorite"), j), sd->status.inventory[i].favorite);
+ pc->setreg(sd, reference_uid(script->add_variable("@inventorylist_idx"), j), i);
j++;
}
}
- pc->setreg(sd,script->add_str("@inventorylist_count"),j);
+ pc->setreg(sd, script->add_variable("@inventorylist_count"), j);
return true;
}
-BUILDIN(getcartinventorylist)
+static BUILDIN(getcartinventorylist)
{
struct map_session_data *sd = script->rid2sd(st);
- char card_var[26];
+ char card_var[SCRIPT_VARNAME_LENGTH];
int i,j=0,k;
if(!sd) return true;
for(i=0;i<MAX_CART;i++) {
if(sd->status.cart[i].nameid > 0 && sd->status.cart[i].amount > 0) {
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_id"), j),sd->status.cart[i].nameid);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_amount"), j),sd->status.cart[i].amount);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_equip"), j),sd->status.cart[i].equip);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_refine"), j),sd->status.cart[i].refine);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_identify"), j),sd->status.cart[i].identify);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_attribute"), j),sd->status.cart[i].attribute);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_id"), j),sd->status.cart[i].nameid);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_amount"), j),sd->status.cart[i].amount);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_equip"), j),sd->status.cart[i].equip);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_refine"), j),sd->status.cart[i].refine);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_identify"), j),sd->status.cart[i].identify);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_attribute"), j),sd->status.cart[i].attribute);
for (k = 0; k < MAX_SLOTS; k++) {
sprintf(card_var, "@cartinventorylist_card%d",k+1);
- pc->setreg(sd,reference_uid(script->add_str(card_var), j),sd->status.cart[i].card[k]);
+ pc->setreg(sd,reference_uid(script->add_variable(card_var), j),sd->status.cart[i].card[k]);
+ }
+ for (k = 0; k < MAX_ITEM_OPTIONS; k++) {
+ sprintf(card_var, "@cartinventorylist_opt_id%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.cart[i].option[k].index);
+ sprintf(card_var, "@cartinventorylist_opt_val%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.cart[i].option[k].value);
+ sprintf(card_var, "@cartinventorylist_opt_param%d", k + 1);
+ pc->setreg(sd, reference_uid(script->add_variable(card_var), j), sd->status.cart[i].option[k].param);
}
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_expire"), j),sd->status.cart[i].expire_time);
- pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_bound"), j),sd->status.cart[i].bound);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_expire"), j),sd->status.cart[i].expire_time);
+ pc->setreg(sd,reference_uid(script->add_variable("@cartinventorylist_bound"), j),sd->status.cart[i].bound);
j++;
}
}
- pc->setreg(sd,script->add_str("@cartinventorylist_count"),j);
+ pc->setreg(sd,script->add_variable("@cartinventorylist_count"),j);
return true;
}
-BUILDIN(getskilllist)
+static BUILDIN(getskilllist)
{
struct map_session_data *sd = script->rid2sd(st);
int i,j=0;
if (sd == NULL)
return true;
- for(i=0;i<MAX_SKILL;i++) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0) {
- pc->setreg(sd,reference_uid(script->add_str("@skilllist_id"), j),sd->status.skill[i].id);
- pc->setreg(sd,reference_uid(script->add_str("@skilllist_lv"), j),sd->status.skill[i].lv);
- pc->setreg(sd,reference_uid(script->add_str("@skilllist_flag"), j),sd->status.skill[i].flag);
+ pc->setreg(sd,reference_uid(script->add_variable("@skilllist_id"), j),sd->status.skill[i].id);
+ pc->setreg(sd,reference_uid(script->add_variable("@skilllist_lv"), j),sd->status.skill[i].lv);
+ pc->setreg(sd,reference_uid(script->add_variable("@skilllist_flag"), j),sd->status.skill[i].flag);
j++;
}
}
- pc->setreg(sd,script->add_str("@skilllist_count"),j);
+ pc->setreg(sd,script->add_variable("@skilllist_count"),j);
return true;
}
-BUILDIN(clearitem)
+static BUILDIN(clearitem)
{
struct map_session_data *sd = script->rid2sd(st);
- int i;
if (sd == NULL)
return true;
- for (i=0; i<MAX_INVENTORY; i++) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
if (sd->status.inventory[i].amount) {
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT);
}
@@ -13287,7 +15538,7 @@ BUILDIN(clearitem)
/*==========================================
* Disguise Player (returns Mob/NPC ID if success, 0 on fail)
*------------------------------------------*/
-BUILDIN(disguise)
+static BUILDIN(disguise)
{
int id;
struct map_session_data *sd = script->rid2sd(st);
@@ -13308,7 +15559,7 @@ BUILDIN(disguise)
/*==========================================
* Undisguise Player (returns 1 if success, 0 on fail)
*------------------------------------------*/
-BUILDIN(undisguise)
+static BUILDIN(undisguise)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -13327,22 +15578,33 @@ BUILDIN(undisguise)
* Transform a bl to another class,
* @type unused
*------------------------------------------*/
-BUILDIN(classchange) {
- int class_,type;
- struct block_list *bl=map->id2bl(st->oid);
+static BUILDIN(classchange)
+{
+ int class, type, target;
+ struct block_list *bl = map->id2bl(st->oid);
+
+ if (bl == NULL)
+ return true;
- if(bl==NULL) return true;
+ class = script_getnum(st, 2);
+ type = script_getnum(st, 3);
+ target = script_hasdata(st, 4) ? script_getnum(st, 4) : 0;
- class_=script_getnum(st,2);
- type=script_getnum(st,3);
- clif->class_change(bl,class_,type);
+ if (target > 0) {
+ struct map_session_data *sd = script->charid2sd(st, target);
+ if (sd != NULL) {
+ clif->class_change(bl, class, type, sd);
+ }
+ } else {
+ clif->class_change(bl, class, type, NULL);
+ }
return true;
}
/*==========================================
* Display an effect
*------------------------------------------*/
-BUILDIN(misceffect)
+static BUILDIN(misceffect)
{
int type;
@@ -13361,7 +15623,7 @@ BUILDIN(misceffect)
/*==========================================
* Play a BGM on a single client [Rikter/Yommy]
*------------------------------------------*/
-BUILDIN(playbgm)
+static BUILDIN(playbgm)
{
struct map_session_data* sd = script->rid2sd(st);
@@ -13374,7 +15636,7 @@ BUILDIN(playbgm)
return true;
}
-int playbgm_sub(struct block_list* bl,va_list ap)
+static int playbgm_sub(struct block_list *bl, va_list ap)
{
const char* name = va_arg(ap,const char*);
@@ -13383,10 +15645,11 @@ int playbgm_sub(struct block_list* bl,va_list ap)
return 0;
}
-int playbgm_foreachpc_sub(struct map_session_data* sd, va_list args)
+static int playbgm_foreachpc_sub(struct map_session_data *sd, va_list args)
{
const char* name = va_arg(args, const char*);
+ nullpo_ret(name);
clif->playBGM(sd, name);
return 0;
}
@@ -13394,7 +15657,8 @@ int playbgm_foreachpc_sub(struct map_session_data* sd, va_list args)
/*==========================================
* Play a BGM on multiple client [Rikter/Yommy]
*------------------------------------------*/
-BUILDIN(playbgmall) {
+static BUILDIN(playbgmall)
+{
const char* name;
name = script_getstr(st,2);
@@ -13436,7 +15700,7 @@ BUILDIN(playbgmall) {
/*==========================================
* Play a .wav sound for sd
*------------------------------------------*/
-BUILDIN(soundeffect)
+static BUILDIN(soundeffect)
{
struct map_session_data *sd = script->rid2sd(st);
const char* name = script_getstr(st,2);
@@ -13448,7 +15712,7 @@ BUILDIN(soundeffect)
return true;
}
-int soundeffect_sub(struct block_list *bl, va_list ap)
+static int soundeffect_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
char *name = va_arg(ap, char *);
@@ -13467,7 +15731,8 @@ int soundeffect_sub(struct block_list *bl, va_list ap)
* Play a sound effect (.wav) on multiple clients
* soundeffectall "<filepath>",<type>{,"<map name>"}{,<x0>,<y0>,<x1>,<y1>};
*------------------------------------------*/
-BUILDIN(soundeffectall) {
+static BUILDIN(soundeffectall)
+{
struct block_list* bl;
const char* name;
int type;
@@ -13518,7 +15783,7 @@ BUILDIN(soundeffectall) {
/*==========================================
* pet status recovery [Valaris] / Rewritten by [Skotlex]
*------------------------------------------*/
-BUILDIN(petrecovery)
+static BUILDIN(petrecovery)
{
struct pet_data *pd;
struct map_session_data *sd = script->rid2sd(st);
@@ -13547,7 +15812,7 @@ BUILDIN(petrecovery)
*------------------------------------------*/
/// petskillattack <skill id>,<level>,<div>,<rate>,<bonusrate>
/// petskillattack "<skill name>",<level>,<div>,<rate>,<bonusrate>
-BUILDIN(petskillattack)
+static BUILDIN(petskillattack)
{
struct pet_data *pd;
struct map_session_data *sd = script->rid2sd(st);
@@ -13573,7 +15838,7 @@ BUILDIN(petskillattack)
*------------------------------------------*/
/// petskillsupport <skill id>,<level>,<delay>,<hp>,<sp>
/// petskillsupport "<skill name>",<level>,<delay>,<hp>,<sp>
-BUILDIN(petskillsupport)
+static BUILDIN(petskillsupport)
{
struct pet_data *pd;
struct map_session_data *sd = script->rid2sd(st);
@@ -13612,7 +15877,7 @@ BUILDIN(petskillsupport)
*------------------------------------------*/
/// skilleffect <skill id>,<level>
/// skilleffect "<skill name>",<level>
-BUILDIN(skilleffect)
+static BUILDIN(skilleffect)
{
struct map_session_data *sd;
@@ -13640,7 +15905,8 @@ BUILDIN(skilleffect)
*------------------------------------------*/
/// npcskilleffect <skill id>,<level>,<x>,<y>
/// npcskilleffect "<skill name>",<level>,<x>,<y>
-BUILDIN(npcskilleffect) {
+static BUILDIN(npcskilleffect)
+{
struct block_list *bl= map->id2bl(st->oid);
uint16 skill_id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
@@ -13657,26 +15923,43 @@ BUILDIN(npcskilleffect) {
/*==========================================
* Special effects [Valaris]
*------------------------------------------*/
-BUILDIN(specialeffect) {
+static BUILDIN(specialeffect)
+{
struct block_list *bl = NULL;
- int type = script_getnum(st,2);
- enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA;
+ int type = script_getnum(st, 2);
+ enum send_target target = AREA;
- if (script_hasdata(st,4)) {
- struct npc_data *nd = npc->name2id(script_getstr(st,4));
- if (nd != NULL)
- bl = &nd->bl;
+ if (script_hasdata(st, 3)) {
+ target = script_getnum(st, 3);
+ }
+
+ if (script_hasdata(st, 4)) {
+ if (script_isstringtype(st, 4)) {
+ struct npc_data *nd = npc->name2id(script_getstr(st, 4));
+ if (nd != NULL) {
+ bl = &nd->bl;
+ }
+ } else {
+ bl = map->id2bl(script_getnum(st, 4));
+ }
} else {
bl = map->id2bl(st->oid);
}
- if (bl == NULL)
+ if (bl == NULL) {
return true;
+ }
if (target == SELF) {
- struct map_session_data *sd = script->rid2sd(st);
- if (sd != NULL)
+ struct map_session_data *sd;
+ if (script_hasdata(st, 5)) {
+ sd = map->id2sd(script_getnum(st, 5));
+ } else {
+ sd = script->rid2sd(st);
+ }
+ if (sd != NULL) {
clif->specialeffect_single(bl, type, sd->fd);
+ }
} else {
clif->specialeffect(bl, type, target);
}
@@ -13684,7 +15967,58 @@ BUILDIN(specialeffect) {
return true;
}
-BUILDIN(specialeffect2) {
+/*==========================================
+ * Special effects with num [4144]
+ *------------------------------------------*/
+static BUILDIN(specialeffectnum)
+{
+ struct block_list *bl = NULL;
+ int type = script_getnum(st, 2);
+ int num = script_getnum(st, 3);
+ int num2 = script_getnum(st, 4);
+ enum send_target target = AREA;
+
+ if (script_hasdata(st, 5)) {
+ target = script_getnum(st, 5);
+ }
+
+ if (script_hasdata(st, 6)) {
+ if (script_isstringtype(st, 6)) {
+ struct npc_data *nd = npc->name2id(script_getstr(st, 6));
+ if (nd != NULL) {
+ bl = &nd->bl;
+ }
+ } else {
+ bl = map->id2bl(script_getnum(st, 6));
+ }
+ } else {
+ bl = map->id2bl(st->oid);
+ }
+
+ if (bl == NULL) {
+ return true;
+ }
+
+ uint64 bigNum = ((uint64)num2) * 0xffffffff + num;
+ if (target == SELF) {
+ struct map_session_data *sd;
+ if (script_hasdata(st, 7)) {
+ sd = map->id2sd(script_getnum(st, 7));
+ } else {
+ sd = script->rid2sd(st);
+ }
+ if (sd != NULL) {
+ clif->specialeffect_value_single(bl, type, bigNum, sd->fd);
+ }
+ } else {
+ clif->specialeffect_value(bl, type, bigNum, target);
+ }
+
+ return true;
+}
+
+static BUILDIN(specialeffect2)
+{
struct map_session_data *sd;
int type = script_getnum(st,2);
enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA;
@@ -13700,10 +16034,54 @@ BUILDIN(specialeffect2) {
return true;
}
+static BUILDIN(removespecialeffect)
+{
+ struct block_list *bl = NULL;
+ int type = script_getnum(st, 2);
+ enum send_target target = AREA;
+
+ if (script_hasdata(st, 3)) {
+ target = script_getnum(st, 3);
+ }
+
+ if (script_hasdata(st, 4)) {
+ if (script_isstringtype(st, 4)) {
+ struct npc_data *nd = npc->name2id(script_getstr(st, 4));
+ if (nd != NULL) {
+ bl = &nd->bl;
+ }
+ } else {
+ bl = map->id2bl(script_getnum(st, 4));
+ }
+ } else {
+ bl = map->id2bl(st->oid);
+ }
+
+ if (bl == NULL) {
+ return true;
+ }
+
+ if (target == SELF) {
+ struct map_session_data *sd;
+ if (script_hasdata(st, 5)) {
+ sd = map->id2sd(script_getnum(st, 5));
+ } else {
+ sd = script->rid2sd(st);
+ }
+ if (sd != NULL) {
+ clif->removeSpecialEffect_single(bl, type, &sd->bl);
+ }
+ } else {
+ clif->removeSpecialEffect(bl, type, target);
+ }
+
+ return true;
+}
+
/*==========================================
* Nude [Valaris]
*------------------------------------------*/
-BUILDIN(nude)
+static BUILDIN(nude)
{
struct map_session_data *sd = script->rid2sd(st);
int i, calcflag = 0;
@@ -13728,12 +16106,11 @@ BUILDIN(nude)
/*==========================================
* gmcommand [MouseJstr]
*------------------------------------------*/
-BUILDIN(atcommand)
+static BUILDIN(atcommand)
{
struct map_session_data *sd, *dummy_sd = NULL;
int fd;
const char* cmd;
- bool ret = true;
cmd = script_getstr(st,2);
@@ -13756,11 +16133,12 @@ BUILDIN(atcommand)
if (!atcommand->exec(fd, sd, cmd, false)) {
ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
- script->reportsrc(st);
- ret = false;
+ if (dummy_sd != NULL)
+ aFree(dummy_sd);
+ return false;
}
if (dummy_sd) aFree(dummy_sd);
- return ret;
+ return true;
}
/**
@@ -13770,7 +16148,7 @@ BUILDIN(atcommand)
* dispbottom "<message>"{,<color>};
* @endcode
*/
-BUILDIN(dispbottom)
+static BUILDIN(dispbottom)
{
struct map_session_data *sd = script->rid2sd(st);
const char *message = script_getstr(st,2);
@@ -13782,7 +16160,7 @@ BUILDIN(dispbottom)
int color = script_getnum(st,3);
clif->messagecolor_self(sd->fd, color, message);
} else {
- clif_disp_onlyself(sd, message, (int)strlen(message));
+ clif_disp_onlyself(sd, message);
}
return true;
@@ -13792,52 +16170,130 @@ BUILDIN(dispbottom)
* All The Players Full Recovery
* (HP/SP full restore and resurrect if need)
*------------------------------------------*/
-BUILDIN(recovery)
+static int buildin_recovery_sub(struct map_session_data *sd)
{
- struct map_session_data *sd;
- struct s_mapiterator* iter;
+ nullpo_retr(0, sd);
- iter = mapit_getallusers();
- for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if(pc_isdead(sd))
- status->revive(&sd->bl, 100, 100);
- else
- status_percent_heal(&sd->bl, 100, 100);
- clif->message(sd->fd,msg_sd(sd,880)); // "You have been recovered!"
+ if (pc_isdead(sd)) {
+ status->revive(&sd->bl, 100, 100);
+ } else {
+ status_percent_heal(&sd->bl, 100, 100);
+ }
+
+ return 0;
+}
+
+static int buildin_recovery_pc_sub(struct map_session_data *sd, va_list ap)
+{
+ return script->buildin_recovery_sub(sd);
+}
+
+static int buildin_recovery_bl_sub(struct block_list *bl, va_list ap)
+{
+ return script->buildin_recovery_sub(BL_CAST(BL_PC, bl));
+}
+
+static BUILDIN(recovery)
+{
+ if (script_hasdata(st, 2)) {
+ if (script_isstringtype(st, 2)) {
+ int16 m = map->mapname2mapid(script_getstr(st, 2));
+
+ if (m == -1) {
+ ShowWarning("script:recovery: invalid map!\n");
+ return false;
+ }
+
+ if (script_hasdata(st, 6)) {
+ int16 x1 = script_getnum(st, 3);
+ int16 y1 = script_getnum(st, 4);
+ int16 x2 = script_getnum(st, 5);
+ int16 y2 = script_getnum(st, 6);
+ map->foreachinarea(script->buildin_recovery_bl_sub, m, x1, y1, x2, y2, BL_PC);
+ } else {
+ map->foreachinmap(script->buildin_recovery_bl_sub, m, BL_PC);
+ }
+ } else {
+ struct map_session_data *sd = script->id2sd(st, script_getnum(st, 2));
+
+ if (sd != NULL) {
+ script->buildin_recovery_sub(sd);
+ }
+ }
+ } else {
+ map->foreachpc(script->buildin_recovery_pc_sub);
}
- mapit->free(iter);
return true;
}
-/*==========================================
- * Get your pet info: getpetinfo(n)
- * n -> 0:pet_id 1:pet_class 2:pet_name
- * 3:friendly 4:hungry, 5: rename flag.
- *------------------------------------------*/
-BUILDIN(getpetinfo)
+
+/*
+ * Get your current pet information
+ */
+static BUILDIN(getpetinfo)
{
struct map_session_data *sd = script->rid2sd(st);
- struct pet_data *pd;
- int type=script_getnum(st,2);
+ if (sd == NULL)
+ return true;
- if (sd == NULL || sd->pd == NULL) {
- if (type == 2)
- script_pushconststr(st,"null");
+ struct pet_data *pd = sd->pd;
+ int type = script_getnum(st, 2);
+ if (pd == NULL) {
+ if (type == PETINFO_NAME)
+ script_pushconststr(st, "null");
else
- script_pushint(st,0);
+ script_pushint(st, 0);
return true;
}
- pd = sd->pd;
+
switch(type) {
- case 0: script_pushint(st,pd->pet.pet_id); break;
- case 1: script_pushint(st,pd->pet.class_); break;
- case 2: script_pushstrcopy(st,pd->pet.name); break;
- case 3: script_pushint(st,pd->pet.intimate); break;
- case 4: script_pushint(st,pd->pet.hungry); break;
- case 5: script_pushint(st,pd->pet.rename_flag); break;
- default:
- script_pushint(st,0);
- break;
+ case PETINFO_ID:
+ script_pushint(st, pd->pet.pet_id);
+ break;
+ case PETINFO_CLASS:
+ script_pushint(st, pd->pet.class_);
+ break;
+ case PETINFO_NAME:
+ script_pushstrcopy(st, pd->pet.name);
+ break;
+ case PETINFO_INTIMACY:
+ script_pushint(st, pd->pet.intimate);
+ break;
+ case PETINFO_HUNGRY:
+ script_pushint(st, pd->pet.hungry);
+ break;
+ case PETINFO_RENAME:
+ script_pushint(st, pd->pet.rename_flag);
+ break;
+ case PETINFO_GID:
+ script_pushint(st, pd->bl.id);
+ break;
+ case PETINFO_EGGITEM:
+ script_pushint(st, pd->pet.egg_id);
+ break;
+ case PETINFO_FOODITEM:
+ script_pushint(st, pd->petDB->FoodID);
+ break;
+ case PETINFO_ACCESSORYITEM:
+ script_pushint(st, pd->petDB->AcceID);
+ break;
+ case PETINFO_ACCESSORYFLAG:
+ script_pushint(st, (pd->pet.equip != 0)? 1:0);
+ break;
+ case PETINFO_EVO_EGGID:
+ if (VECTOR_DATA(pd->petDB->evolve_data) != NULL)
+ script_pushint(st, VECTOR_DATA(pd->petDB->evolve_data)->petEggId);
+ else
+ script_pushint(st, 0);
+ break;
+ case PETINFO_AUTOFEED:
+ script_pushint(st, pd->pet.autofeed);
+ break;
+ default:
+ ShowWarning("buildin_getpetinfo: Invalid type %d.\n", type);
+ script_pushint(st, 0);
+ return false;
}
+
return true;
}
@@ -13847,7 +16303,7 @@ BUILDIN(getpetinfo)
* 3:friendly 4:hungry, 5: rename flag.
* 6: level
*------------------------------------------*/
-BUILDIN(gethominfo)
+static BUILDIN(gethominfo)
{
struct map_session_data *sd = script->rid2sd(st);
int type = script_getnum(st,2);
@@ -13875,20 +16331,15 @@ BUILDIN(gethominfo)
return true;
}
-/// Retrieves information about character's mercenary
-/// getmercinfo <type>[,<char id>];
-BUILDIN(getmercinfo)
+/*
+ * Retrieves information about character's mercenary
+ * getmercinfo <type>{, <char id> };
+ */
+static BUILDIN(getmercinfo)
{
- int type;
- struct map_session_data* sd;
- struct mercenary_data* md;
-
- type = script_getnum(st,2);
-
- if (script_hasdata(st,3)) {
- int char_id = script_getnum(st,3);
-
- if ((sd = script->charid2sd(st, char_id)) == NULL) {
+ struct map_session_data *sd;
+ if (script_hasdata(st, 3)) {
+ if ((sd = script->charid2sd(st, script_getnum(st, 3))) == NULL) {
script_pushnil(st);
return true;
}
@@ -13897,27 +16348,48 @@ BUILDIN(getmercinfo)
return true;
}
- md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL;
+ struct mercenary_data *md = (sd->status.mer_id && sd->md)? sd->md : NULL;
+ int type = script_getnum(st, 2);
+ if (md == NULL) {
+ if (type == MERCINFO_NAME)
+ script_pushconststr(st, "");
+ else
+ script_pushint(st, 0);
+ return true;
+ }
- switch( type )
- {
- case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break;
- case 1: script_pushint(st,md ? md->mercenary.class_ : 0); break;
- case 2:
- if( md )
- script_pushstrcopy(st,md->db->name);
- else
- script_pushconststr(st,"");
- break;
- case 3: script_pushint(st,md ? mercenary->get_faith(md) : 0); break;
- case 4: script_pushint(st,md ? mercenary->get_calls(md) : 0); break;
- case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break;
- case 6: script_pushint(st,md ? mercenary->get_lifetime(md) : 0); break;
- case 7: script_pushint(st,md ? md->db->lv : 0); break;
- default:
- ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id);
- script_pushnil(st);
- return false;
+ switch (type) {
+ case MERCINFO_ID:
+ script_pushint(st, md->mercenary.mercenary_id);
+ break;
+ case MERCINFO_CLASS:
+ script_pushint(st, md->mercenary.class_);
+ break;
+ case MERCINFO_NAME:
+ script_pushstrcopy(st, md->db->name);
+ break;
+ case MERCINFO_FAITH:
+ script_pushint(st, mercenary->get_faith(md));
+ break;
+ case MERCINFO_CALLS:
+ script_pushint(st, mercenary->get_calls(md));
+ break;
+ case MERCINFO_KILLCOUNT:
+ script_pushint(st, md->mercenary.kill_count);
+ break;
+ case MERCINFO_LIFETIME:
+ script_pushint(st, mercenary->get_lifetime(md));
+ break;
+ case MERCINFO_LEVEL:
+ script_pushint(st, md->db->lv);
+ break;
+ case MERCINFO_GID:
+ script_pushint(st, md->bl.id);
+ break;
+ default:
+ ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id);
+ script_pushnil(st);
+ return false;
}
return true;
@@ -13928,21 +16400,20 @@ BUILDIN(getmercinfo)
* selected card or not.
* checkequipedcard(4001);
*------------------------------------------*/
-BUILDIN(checkequipedcard)
+static BUILDIN(checkequipedcard)
{
- int n,i,c=0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- c = script_getnum(st,2);
+ int c = script_getnum(st,2);
- for( i=0; i<MAX_INVENTORY; i++) {
+ for (int i = 0; i < sd->status.inventorySize; 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++) {
+ for (int n = 0; n < sd->inventory_data[i]->slot; n++) {
if(sd->status.inventory[i].card[n]==c) {
script_pushint(st,1);
return true;
@@ -13955,7 +16426,7 @@ BUILDIN(checkequipedcard)
return true;
}
-BUILDIN(__jump_zero)
+static BUILDIN(__jump_zero)
{
int sel;
sel=script_getnum(st,2);
@@ -13977,7 +16448,7 @@ BUILDIN(__jump_zero)
/*==========================================
* movenpc [MouseJstr]
*------------------------------------------*/
-BUILDIN(movenpc)
+static BUILDIN(movenpc)
{
struct npc_data *nd = NULL;
const char *npc_name;
@@ -13999,7 +16470,7 @@ BUILDIN(movenpc)
/*==========================================
* message [MouseJstr]
*------------------------------------------*/
-BUILDIN(message)
+static BUILDIN(message)
{
const char *message;
struct map_session_data *sd = NULL;
@@ -14018,14 +16489,38 @@ BUILDIN(message)
return true;
}
+static BUILDIN(servicemessage)
+{
+ struct map_session_data *sd = NULL;
+
+ if (script_hasdata(st, 4)) {
+ if (script_isstringtype(st, 4))
+ sd = script->nick2sd(st, script_getstr(st, 4));
+ else
+ sd = script->id2sd(st, script_getnum(st, 4));
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ if (sd == NULL)
+ return true;
+
+ const char *message = script_getstr(st, 2);
+ const int color = script_getnum(st, 3);
+ clif->serviceMessageColor(sd, color, message);
+
+ return true;
+}
+
/*==========================================
* npctalk (sends message to surrounding area)
- * usage: npctalk "<message>"{,"<npc name>"};
+ * usage: npctalk("<message>"{, "<npc name>"{, <show_name>}});
*------------------------------------------*/
-BUILDIN(npctalk)
+static BUILDIN(npctalk)
{
struct npc_data* nd;
const char *str = script_getstr(st,2);
+ bool show_name = true;
if (script_hasdata(st, 3)) {
nd = npc->name2id(script_getstr(st, 3));
@@ -14033,61 +16528,78 @@ BUILDIN(npctalk)
nd = map->id2nd(st->oid);
}
+ if (script_hasdata(st, 4)) {
+ show_name = (script_getnum(st, 4) != 0) ? true : false;
+ }
+
if (nd != NULL) {
char name[NAME_LENGTH], message[256];
safestrncpy(name, nd->name, sizeof(name));
strtok(name, "#"); // discard extra name identifier if present
- safesnprintf(message, sizeof(message), "%s : %s", name, str);
- clif->disp_overhead(&nd->bl, message);
+ if (show_name) {
+ safesnprintf(message, sizeof(message), "%s : %s", name, str);
+ } else {
+ safesnprintf(message, sizeof(message), "%s", str);
+ }
+ clif->disp_overhead(&nd->bl, message, AREA_CHAT_WOC, NULL);
}
return true;
}
// change npc walkspeed [Valaris]
-BUILDIN(npcspeed) {
- struct npc_data* nd;
- int speed;
-
- speed = script_getnum(st,2);
- nd = map->id2nd(st->oid);
+static BUILDIN(npcspeed)
+{
+ struct npc_data *nd = map->id2nd(st->oid);
+ int speed = script_getnum(st, 2);
if (nd != NULL) {
unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
+ if (nd->ud == NULL) {
+ ShowWarning("buildin_npcspeed: floating NPC don't have unit data.\n");
+ return false;
+ }
nd->speed = speed;
nd->ud->state.speed_changed = 1;
}
return true;
}
+
// make an npc walk to a position [Valaris]
-BUILDIN(npcwalkto)
+static BUILDIN(npcwalkto)
{
struct npc_data *nd = map->id2nd(st->oid);
- int x=0,y=0;
-
- x=script_getnum(st,2);
- y=script_getnum(st,3);
+ int x = script_getnum(st, 2);
+ int y = script_getnum(st, 3);
if (nd != NULL) {
unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
+ if (nd->ud == NULL) {
+ ShowWarning("buildin_npcwalkto: floating NPC don't have unit data.\n");
+ return false;
+ }
if (!nd->status.hp) {
status_calc_npc(nd, SCO_FIRST);
} else {
status_calc_npc(nd, SCO_NONE);
}
- unit->walktoxy(&nd->bl,x,y,0);
+ unit->walk_toxy(&nd->bl, x, y, 0);
}
return true;
}
// stop an npc's movement [Valaris]
-BUILDIN(npcstop)
+static BUILDIN(npcstop)
{
struct npc_data *nd = map->id2nd(st->oid);
if (nd != NULL) {
unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
+ if (nd->ud == NULL) {
+ ShowWarning("buildin_npcstop: floating NPC don't have unit data.\n");
+ return false;
+ }
unit->stop_walking(&nd->bl, STOPWALKING_FLAG_FIXPOS|STOPWALKING_FLAG_NEXTCELL);
}
@@ -14095,7 +16607,7 @@ BUILDIN(npcstop)
}
// set click npc distance [4144]
-BUILDIN(setnpcdistance)
+static BUILDIN(setnpcdistance)
{
struct npc_data *nd = map->id2nd(st->oid);
if (nd == NULL)
@@ -14107,7 +16619,7 @@ BUILDIN(setnpcdistance)
}
// return current npc direction [4144]
-BUILDIN(getnpcdir)
+static BUILDIN(getnpcdir)
{
const struct npc_data *nd = NULL;
@@ -14133,7 +16645,7 @@ BUILDIN(getnpcdir)
}
// set npc direction [4144]
-BUILDIN(setnpcdir)
+static BUILDIN(setnpcdir)
{
int newdir;
struct npc_data *nd = NULL;
@@ -14167,7 +16679,7 @@ BUILDIN(setnpcdir)
}
// return npc class [4144]
-BUILDIN(getnpcclass)
+static BUILDIN(getnpcclass)
{
const struct npc_data *nd = NULL;
@@ -14195,7 +16707,7 @@ BUILDIN(getnpcclass)
/*==========================================
* getlook char info. getlook(arg)
*------------------------------------------*/
-BUILDIN(getlook)
+static BUILDIN(getlook)
{
int type,val = -1;
struct map_session_data *sd = script->rid2sd(st);
@@ -14205,15 +16717,15 @@ BUILDIN(getlook)
type=script_getnum(st,2);
switch(type) {
case LOOK_HAIR: val = sd->status.hair; break; //1
- case LOOK_WEAPON: val = sd->status.weapon; break; //2
- case LOOK_HEAD_BOTTOM: val = sd->status.head_bottom; break; //3
- case LOOK_HEAD_TOP: val = sd->status.head_top; break; //4
- case LOOK_HEAD_MID: val = sd->status.head_mid; break; //5
+ case LOOK_WEAPON: val = sd->status.look.weapon; break; //2
+ case LOOK_HEAD_BOTTOM: val = sd->status.look.head_bottom; break; //3
+ case LOOK_HEAD_TOP: val = sd->status.look.head_top; break; //4
+ case LOOK_HEAD_MID: val = sd->status.look.head_mid; break; //5
case LOOK_HAIR_COLOR: val = sd->status.hair_color; break; //6
case LOOK_CLOTHES_COLOR: val = sd->status.clothes_color; break; //7
- case LOOK_SHIELD: val = sd->status.shield; break; //8
+ case LOOK_SHIELD: val = sd->status.look.shield; break; //8
case LOOK_SHOES: break; //9
- case LOOK_ROBE: val = sd->status.robe; break; //12
+ case LOOK_ROBE: val = sd->status.look.robe; break; //12
case LOOK_BODY2: val=sd->status.body; break; //13
}
@@ -14224,7 +16736,7 @@ BUILDIN(getlook)
/*==========================================
* get char save point. argument: 0- map name, 1- x, 2- y
*------------------------------------------*/
-BUILDIN(getsavepoint)
+static BUILDIN(getsavepoint)
{
int type;
struct map_session_data *sd = script->rid2sd(st);
@@ -14267,7 +16779,7 @@ BUILDIN(getsavepoint)
* 0 - success
* -1 - some error, MapName$,MapX,MapY contains unknown value.
*------------------------------------------*/
-BUILDIN(getmapxy)
+static BUILDIN(getmapxy)
{
struct block_list *bl = NULL;
struct map_session_data *sd = NULL;
@@ -14320,7 +16832,7 @@ BUILDIN(getmapxy)
case 0: //Get Character Position
if (script_hasdata(st,6)) {
if (script_isstringtype(st,6))
- sd = map->nick2sd(script_getstr(st,6));
+ sd = map->nick2sd(script_getstr(st,6), false);
else
sd = map->id2sd(script_getnum(st,6));
} else {
@@ -14347,7 +16859,7 @@ BUILDIN(getmapxy)
case 2: //Get Pet Position
if (script_hasdata(st,6)) {
if (script_isstringtype(st,6))
- sd = map->nick2sd(script_getstr(st,6));
+ sd = map->nick2sd(script_getstr(st,6), false);
else {
bl = map->id2bl(script_getnum(st,6));
break;
@@ -14369,7 +16881,7 @@ BUILDIN(getmapxy)
case 4: //Get Homun Position
if (script_hasdata(st,6)) {
if (script_isstringtype(st,6)) {
- sd = map->nick2sd(script_getstr(st,6));
+ sd = map->nick2sd(script_getstr(st,6), false);
} else {
bl = map->id2bl(script_getnum(st,6));
break;
@@ -14384,7 +16896,7 @@ BUILDIN(getmapxy)
case 5: //Get Mercenary Position
if (script_hasdata(st,6)) {
if (script_isstringtype(st,6)) {
- sd = map->nick2sd(script_getstr(st,6));
+ sd = map->nick2sd(script_getstr(st,6), false);
} else {
bl = map->id2bl(script_getnum(st,6));
break;
@@ -14399,7 +16911,7 @@ BUILDIN(getmapxy)
case 6: //Get Elemental Position
if (script_hasdata(st,6)) {
if (script_isstringtype(st,6)) {
- sd = map->nick2sd(script_getstr(st,6));
+ sd = map->nick2sd(script_getstr(st,6), false);
} else {
bl = map->id2bl(script_getnum(st,6));
break;
@@ -14463,61 +16975,97 @@ BUILDIN(getmapxy)
return true;
}
+enum logmes_type {
+ LOGMES_NPC,
+ LOGMES_ATCOMMAND
+};
+
/*==========================================
- * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus]
+ * Allows player to write logs (i.e. Bank NPC, etc) [Lupus]
*------------------------------------------*/
-BUILDIN(logmes)
+static BUILDIN(logmes)
{
- const char *str;
+ const char *str = script_getstr(st, 2);
struct map_session_data *sd = script->rid2sd(st);
+ enum logmes_type type = LOGMES_NPC;
+ nullpo_retr(false, sd);
- if (sd == NULL)
- return true;
+ if (script_hasdata(st, 3)) {
+ type = script_getnum(st, 3);
+ }
+
+ switch (type) {
+ case LOGMES_ATCOMMAND:
+ logs->atcommand(sd, str);
+ break;
+ case LOGMES_NPC:
+ logs->npc(sd, str);
+ break;
+ default:
+ ShowError("script:logmes: Unknown log type!\n");
+ st->state = END;
+ return false;
+ }
- str = script_getstr(st,2);
- logs->npc(sd,str);
return true;
}
-BUILDIN(summon)
+/**
+ * Summons a mob which will act as a slave for the invoking character.
+ *
+ * @code{.herc}
+ * summon("mob name", <mob id>{, <timeout>{, "event label"}});
+ * @endcode
+ *
+ * @author Celest
+ *
+ **/
+static BUILDIN(summon)
{
- int class_, timeout=0;
- const char *str,*event="";
- struct mob_data *md;
- int64 tick = timer->gettick();
struct map_session_data *sd = script->rid2sd(st);
+
if (sd == NULL)
return true;
- str = script_getstr(st,2);
- class_ = script_getnum(st,3);
- if( script_hasdata(st,4) )
- timeout=script_getnum(st,4);
- if( script_hasdata(st,5) ) {
- event=script_getstr(st,5);
+ const int64 tick = timer->gettick();
+
+ clif->skill_poseffect(&sd->bl, AM_CALLHOMUN, 1, sd->bl.x, sd->bl.y, tick);
+
+ const char *event = "";
+
+ if (script_hasdata(st, 5)) {
+ event = script_getstr(st, 5);
script->check_event(st, event);
}
- clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick);
+ const char *name = script_getstr(st, 2);
+ const int mob_id = script_getnum(st, 3);
+ struct mob_data *md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, name, mob_id, event,
+ SZ_SMALL, AI_NONE, 0);
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_SMALL, AI_NONE);
- if (md) {
- md->master_id=sd->bl.id;
+ if (md != NULL) {
+ md->master_id = sd->bl.id;
md->special_state.ai = AI_ATTACK;
- if( md->deletetimer != INVALID_TIMER )
+
+ if (md->deletetimer != INVALID_TIMER)
timer->delete(md->deletetimer, mob->timer_delete);
- md->deletetimer = timer->add(tick+(timeout>0?timeout*1000:60000),mob->timer_delete,md->bl.id,0);
- mob->spawn (md); //Now it is ready for spawning.
- clif->specialeffect(&md->bl,344,AREA);
+
+ const int timeout = script_hasdata(st, 4) ? script_getnum(st, 4) * 1000 : 60000;
+
+ md->deletetimer = timer->add(tick + ((timeout == 0) ? 60000 : timeout), mob->timer_delete, md->bl.id, 0);
+ mob->spawn(md);
+ clif->specialeffect(&md->bl, 344, AREA);
sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
}
+
return true;
}
/*==========================================
* Checks whether it is daytime/nighttime
*------------------------------------------*/
-BUILDIN(isnight) {
+static BUILDIN(isnight)
+{
script_pushint(st,(map->night_flag == 1));
return true;
}
@@ -14526,7 +17074,7 @@ BUILDIN(isnight) {
* Check how many items/cards in the list are
* equipped - used for 2/15's cards patch [celest]
*------------------------------------------------*/
-BUILDIN(isequippedcnt)
+static BUILDIN(isequippedcnt)
{
int i, j, k, id = 1;
int ret = 0;
@@ -14547,6 +17095,8 @@ BUILDIN(isequippedcnt)
if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue;
if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue;
+ if(j == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == index) continue;
+ if(j == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == index || sd->equip_index[EQI_COSTUME_LOW] == index)) continue;
if(!sd->inventory_data[index])
continue;
@@ -14575,7 +17125,7 @@ BUILDIN(isequippedcnt)
* -- Items checked cannot be reused in another
* card set to prevent exploits
*------------------------------------------------*/
-BUILDIN(isequipped)
+static BUILDIN(isequipped)
{
int i, j, k, id = 1;
int index, flag;
@@ -14600,6 +17150,8 @@ BUILDIN(isequipped)
if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue;
if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue;
+ if(j == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == index) continue;
+ if(j == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == index || sd->equip_index[EQI_COSTUME_LOW] == index)) continue;
if(!sd->inventory_data[index])
continue;
@@ -14655,7 +17207,7 @@ BUILDIN(isequipped)
* Check how many given inserted cards in the CURRENT
* weapon - used for 2/15's cards patch [Lupus]
*------------------------------------------------*/
-BUILDIN(cardscnt)
+static BUILDIN(cardscnt)
{
int i, k, id = 1;
int ret = 0;
@@ -14697,25 +17249,30 @@ BUILDIN(cardscnt)
* Returns the refined number of the current item, or an
* item with inventory index specified
*-------------------------------------------------------*/
-BUILDIN(getrefine)
+static BUILDIN(getrefine)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
- script_pushint(st,sd->status.inventory[status->current_equip_item_index].refine);
+ if (status->current_equip_item_index < 0)
+ script_pushint(st, 0);
+ else
+ script_pushint(st, sd->status.inventory[status->current_equip_item_index].refine);
return true;
}
/*=======================================================
* Day/Night controls
*-------------------------------------------------------*/
-BUILDIN(night) {
+static BUILDIN(night)
+{
if (map->night_flag != 1) pc->map_night_timer(pc->night_timer_tid, 0, 0, 1);
return true;
}
-BUILDIN(day) {
+static BUILDIN(day)
+{
if (map->night_flag != 0) pc->map_day_timer(pc->day_timer_tid, 0, 0, 1);
return true;
}
@@ -14723,7 +17280,7 @@ BUILDIN(day) {
//=======================================================
// Unequip [Spectre]
//-------------------------------------------------------
-BUILDIN(unequip)
+static BUILDIN(unequip)
{
size_t num;
struct map_session_data *sd;
@@ -14738,7 +17295,7 @@ BUILDIN(unequip)
return true;
}
-BUILDIN(equip)
+static BUILDIN(equip)
{
int nameid=0,i;
struct item_data *item_data;
@@ -14749,17 +17306,17 @@ BUILDIN(equip)
nameid=script_getnum(st,2);
if((item_data = itemdb->exists(nameid)) == NULL)
{
- ShowError("wrong item ID : equipitem(%i)\n",nameid);
+ ShowError("wrong item ID : equipitem(%d)\n",nameid);
return false;
}
- ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid && sd->status.inventory[i].equip == 0 );
- if( i < MAX_INVENTORY )
- pc->equipitem(sd,i,item_data->equip);
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].nameid == nameid && sd->status.inventory[i].equip == 0);
+ if (i < sd->status.inventorySize)
+ pc->equipitem(sd, i, item_data->equip);
return true;
}
-BUILDIN(autoequip)
+static BUILDIN(autoequip)
{
int nameid, flag;
struct item_data *item_data;
@@ -14786,7 +17343,7 @@ BUILDIN(autoequip)
* Equip2
* equip2 <item id>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
*-------------------------------------------------------*/
-BUILDIN(equip2)
+static BUILDIN(equip2)
{
int i,nameid,ref,attr,c0,c1,c2,c3;
struct item_data *item_data;
@@ -14805,33 +17362,33 @@ BUILDIN(equip2)
return false;
}
- ref = script_getnum(st,3);
- attr = script_getnum(st,4);
- c0 = (short)script_getnum(st,5);
- c1 = (short)script_getnum(st,6);
- c2 = (short)script_getnum(st,7);
- c3 = (short)script_getnum(st,8);
+ ref = script_getnum(st, 3);
+ attr = script_getnum(st, 4);
+ c0 = script_getnum(st, 5);
+ c1 = script_getnum(st, 6);
+ c2 = script_getnum(st, 7);
+ c3 = script_getnum(st, 8);
- ARR_FIND( 0, MAX_INVENTORY, i,( sd->status.inventory[i].equip == 0 &&
+ ARR_FIND(0, sd->status.inventorySize, i, (sd->status.inventory[i].equip == 0 &&
sd->status.inventory[i].nameid == nameid &&
sd->status.inventory[i].refine == ref &&
sd->status.inventory[i].attribute == attr &&
sd->status.inventory[i].card[0] == c0 &&
sd->status.inventory[i].card[1] == c1 &&
sd->status.inventory[i].card[2] == c2 &&
- sd->status.inventory[i].card[3] == c3 ) );
+ sd->status.inventory[i].card[3] == c3));
- if( i < MAX_INVENTORY ) {
+ if (i < sd->status.inventorySize) {
script_pushint(st,1);
pc->equipitem(sd,i,item_data->equip);
- }
- else
+ } else {
script_pushint(st,0);
+ }
return true;
}
-BUILDIN(setbattleflag)
+static BUILDIN(setbattleflag)
{
const char *flag, *value;
@@ -14846,7 +17403,7 @@ BUILDIN(setbattleflag)
return true;
}
-BUILDIN(getbattleflag)
+static BUILDIN(getbattleflag)
{
const char *flag;
int value;
@@ -14868,7 +17425,7 @@ BUILDIN(getbattleflag)
//=======================================================
// strlen [Valaris]
//-------------------------------------------------------
-BUILDIN(getstrlen)
+static BUILDIN(getstrlen)
{
const char *str = script_getstr(st,2);
@@ -14881,7 +17438,7 @@ BUILDIN(getstrlen)
//=======================================================
// isalpha [Valaris]
//-------------------------------------------------------
-BUILDIN(charisalpha)
+static BUILDIN(charisalpha)
{
const char *str=script_getstr(st,2);
int pos=script_getnum(st,3);
@@ -14895,7 +17452,7 @@ BUILDIN(charisalpha)
//=======================================================
// charisupper <str>, <index>
//-------------------------------------------------------
-BUILDIN(charisupper)
+static BUILDIN(charisupper)
{
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
@@ -14909,7 +17466,7 @@ BUILDIN(charisupper)
//=======================================================
// charislower <str>, <index>
//-------------------------------------------------------
-BUILDIN(charislower)
+static BUILDIN(charislower)
{
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
@@ -14923,7 +17480,8 @@ BUILDIN(charislower)
//=======================================================
// charat <str>, <index>
//-------------------------------------------------------
-BUILDIN(charat) {
+static BUILDIN(charat)
+{
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
@@ -14938,9 +17496,164 @@ BUILDIN(charat) {
}
//=======================================================
+// isstr <argument>
+//
+// returns type:
+// 0 - int
+// 1 - string
+// 2 - other
+//-------------------------------------------------------
+static BUILDIN(isstr)
+{
+ if (script_isinttype(st, 2)) {
+ script_pushint(st, 0);
+ } else if (script_isstringtype(st, 2)) {
+ script_pushint(st, 1);
+ } else {
+ script_pushint(st, 2);
+ }
+ return true;
+}
+
+enum datatype {
+ DATATYPE_NIL = 1 << 7, // we don't start at 1, to leave room for primitives
+ DATATYPE_STR = 1 << 8,
+ DATATYPE_INT = 1 << 9,
+ DATATYPE_CONST = 1 << 10,
+ DATATYPE_PARAM = 1 << 11,
+ DATATYPE_VAR = 1 << 12,
+ DATATYPE_LABEL = 1 << 13,
+};
+
+static BUILDIN(getdatatype)
+{
+ int type;
+
+ if (script_hasdata(st, 2)) {
+ struct script_data *data = script_getdata(st, 2);
+
+ if (data_isstring(data)) {
+ type = DATATYPE_STR;
+ if (data->type == C_CONSTSTR) {
+ type |= DATATYPE_CONST;
+ }
+ } else if (data_isint(data)) {
+ type = DATATYPE_INT;
+ } else if (data_islabel(data)) {
+ type = DATATYPE_LABEL;
+ } else if (data_isreference(data)) {
+ if (reference_toconstant(data)) {
+ type = DATATYPE_CONST | DATATYPE_INT;
+ } else if (reference_toparam(data)) {
+ type = DATATYPE_PARAM | DATATYPE_INT;
+ } else if (reference_tovariable(data)) {
+ type = DATATYPE_VAR;
+ if (is_string_variable(reference_getname(data))) {
+ type |= DATATYPE_STR;
+ } else {
+ type |= DATATYPE_INT;
+ }
+ } else {
+ ShowError("script:getdatatype: Unknown reference type!\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+ } else {
+ type = data->type; // fallback to primitive type if unknown
+ }
+ } else {
+ type = DATATYPE_NIL; // nothing was passed
+ }
+
+ script_pushint(st, type);
+ return true;
+}
+
+static BUILDIN(data_to_string)
+{
+ if (script_hasdata(st, 2)) {
+ struct script_data *data = script_getdata(st, 2);
+
+ if (data_isstring(data)) {
+ script_pushcopy(st, 2);
+ } else if (data_isint(data)) {
+ char *str = NULL;
+
+ CREATE(str, char, 20);
+ safesnprintf(str, 20, "%"PRId64"", data->u.num);
+ script_pushstr(st, str);
+ } else if (data_islabel(data)) {
+ const char *str = "";
+
+ // XXX: because all we have is the label pos we can't be sure which
+ // one is the correct label if more than one has the same pos.
+ // We might want to store both the pos and str_data index in
+ // data->u.num, similar to how C_NAME stores both the array
+ // index and str_data index in u.num with bitmasking. This
+ // would also avoid the awkward for() loops as we could
+ // directly access the string with script->get_str().
+
+ if (st->oid) {
+ struct npc_data *nd = map->id2nd(st->oid);
+
+ for (int i = 0; i < nd->u.scr.label_list_num; ++i) {
+ if (nd->u.scr.label_list[i].pos == data->u.num) {
+ str = nd->u.scr.label_list[i].name;
+ break;
+ }
+ }
+ } else {
+ for (int i = LABEL_START; script->str_data[i].next != 0; i = script->str_data[i].next) {
+ if (script->str_data[i].label == data->u.num) {
+ str = script->get_str(i);
+ break;
+ }
+ }
+ }
+
+ script_pushconststr(st, str);
+ } else if (data_isreference(data)) {
+ script_pushstrcopy(st, reference_getname(data));
+ } else {
+ ShowWarning("script:data_to_string: unknown data type!\n");
+ script->reportdata(data);
+ script_pushconststr(st, "");
+ }
+ } else {
+ script_pushconststr(st, ""); // NIL
+ }
+
+ return true;
+}
+
+//=======================================================
+// chr <int>
+//-------------------------------------------------------
+static BUILDIN(chr)
+{
+ char output[2];
+ output[0] = script_getnum(st, 2);
+ output[1] = '\0';
+
+ script_pushstrcopy(st, output);
+ return true;
+}
+
+//=======================================================
+// ord <chr>
+//-------------------------------------------------------
+static BUILDIN(ord)
+{
+ const char *chr = script_getstr(st, 2);
+ script_pushint(st, *chr);
+ return true;
+}
+
+//=======================================================
// setchar <string>, <char>, <index>
//-------------------------------------------------------
-BUILDIN(setchar)
+static BUILDIN(setchar)
{
const char *str = script_getstr(st,2);
const char *c = script_getstr(st,3);
@@ -14957,7 +17670,7 @@ BUILDIN(setchar)
//=======================================================
// insertchar <string>, <char>, <index>
//-------------------------------------------------------
-BUILDIN(insertchar)
+static BUILDIN(insertchar)
{
const char *str = script_getstr(st,2);
const char *c = script_getstr(st,3);
@@ -14984,7 +17697,7 @@ BUILDIN(insertchar)
//=======================================================
// delchar <string>, <index>
//-------------------------------------------------------
-BUILDIN(delchar)
+static BUILDIN(delchar)
{
const char *str = script_getstr(st,2);
int index = script_getnum(st,3);
@@ -15010,7 +17723,7 @@ BUILDIN(delchar)
//=======================================================
// strtoupper <str>
//-------------------------------------------------------
-BUILDIN(strtoupper)
+static BUILDIN(strtoupper)
{
const char *str = script_getstr(st,2);
char *output = aStrdup(str);
@@ -15028,7 +17741,7 @@ BUILDIN(strtoupper)
//=======================================================
// strtolower <str>
//-------------------------------------------------------
-BUILDIN(strtolower)
+static BUILDIN(strtolower)
{
const char *str = script_getstr(st,2);
char *output = aStrdup(str);
@@ -15046,7 +17759,7 @@ BUILDIN(strtolower)
//=======================================================
// substr <str>, <start>, <end>
//-------------------------------------------------------
-BUILDIN(substr)
+static BUILDIN(substr)
{
const char *str = script_getstr(st,2);
char *output;
@@ -15072,7 +17785,7 @@ BUILDIN(substr)
// explode <dest_string_array>, <str>, <delimiter>
// Note: delimiter is limited to 1 char
//-------------------------------------------------------
-BUILDIN(explode)
+static BUILDIN(explode)
{
struct script_data* data = script_getdata(st, 2);
const char *str = script_getstr(st,3);
@@ -15137,7 +17850,7 @@ BUILDIN(explode)
// implode <string_array>
// implode <string_array>, <glue>
//-------------------------------------------------------
-BUILDIN(implode)
+static BUILDIN(implode)
{
struct script_data* data = script_getdata(st, 2);
const char *name;
@@ -15229,130 +17942,19 @@ BUILDIN(implode)
// Implements C sprintf, except format %n. The resulting string is
// returned, instead of being saved in variable by reference.
//-------------------------------------------------------
-BUILDIN(sprintf) {
- unsigned int argc = 0, arg = 0;
- const char* format;
- char* p;
- char* q;
- char* buf = NULL;
- char* buf2 = NULL;
- struct script_data* data;
- size_t len, buf2_len = 0;
- StringBuf final_buf;
-
- // Fetch init data
- format = script_getstr(st, 2);
- argc = script_lastdata(st)-2;
- len = strlen(format);
-
- // Skip parsing, where no parsing is required.
- if(len==0) {
- script_pushconststr(st,"");
- return true;
- }
-
- // Pessimistic alloc
- CREATE(buf, char, len+1);
-
- // Need not be parsed, just solve stuff like %%.
- if(argc==0) {
- memcpy(buf,format,len+1);
- script_pushstrcopy(st, buf);
- aFree(buf);
- return true;
- }
-
- safestrncpy(buf, format, len+1);
-
- // Issue sprintf for each parameter
- StrBuf->Init(&final_buf);
- q = buf;
- while((p = strchr(q, '%'))!=NULL) {
- if(p!=q) {
- len = p-q+1;
- if(buf2_len<len) {
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- StrBuf->AppendStr(&final_buf, buf2);
- q = p;
- }
- p = q+1;
- if(*p=='%') { // %%
- StrBuf->AppendStr(&final_buf, "%");
- q+=2;
- continue;
- }
- if(*p=='n') { // %n
- ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
- script->reportsrc(st);
- q+=2;
- continue;
- }
- if(arg>=argc) {
- ShowError("buildin_sprintf: Not enough arguments passed!\n");
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- if((p = strchr(q+1, '%'))==NULL) {
- p = strchr(q, 0); // EOS
- }
- len = p-q+1;
- if(buf2_len<len) {
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- q = p;
-
- // Note: This assumes the passed value being the correct
- // type to the current format specifier. If not, the server
- // probably crashes or returns anything else, than expected,
- // but it would behave in normal code the same way so it's
- // the scripter's responsibility.
- data = script_getdata(st, arg+3);
- if(data_isstring(data)) { // String
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- } else if(data_isint(data)) { // Number
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- } else if(data_isreference(data)) { // Variable
- char* name = reference_getname(data);
- if(name[strlen(name)-1]=='$') { // var Str
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- } else { // var Int
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- }
- } else { // Unsupported type
- ShowError("buildin_sprintf: Unknown argument type!\n");
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- arg++;
- }
-
- // Append anything left
- if(*q) {
- StrBuf->AppendStr(&final_buf, q);
- }
+static BUILDIN(sprintf)
+{
+ struct StringBuf buf;
+ StrBuf->Init(&buf);
- // Passed more, than needed
- if(arg<argc) {
- ShowWarning("buildin_sprintf: Unused arguments passed.\n");
- script->reportsrc(st);
+ if (!script->sprintf_helper(st, 2, &buf)) {
+ StrBuf->Destroy(&buf);
+ script_pushconststr(st, "");
+ return false;
}
- script_pushstrcopy(st, StrBuf->Value(&final_buf));
-
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
+ script_pushstrcopy(st, StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
return true;
}
@@ -15361,7 +17963,8 @@ BUILDIN(sprintf) {
// sscanf(<str>, <format>, ...);
// Implements C sscanf.
//-------------------------------------------------------
-BUILDIN(sscanf) {
+static BUILDIN(sscanf)
+{
unsigned int argc, arg = 0;
struct script_data* data;
struct map_session_data* sd = NULL;
@@ -15474,7 +18077,8 @@ BUILDIN(sscanf) {
// Implements PHP style strpos. Adapted from code from
// http://www.daniweb.com/code/snippet313.html, Dave Sinkula
//-------------------------------------------------------
-BUILDIN(strpos) {
+static BUILDIN(strpos)
+{
const char *haystack = script_getstr(st,2);
const char *needle = script_getstr(st,3);
int i;
@@ -15518,7 +18122,7 @@ BUILDIN(strpos) {
// instances as specified in <count>. By default will be case
// sensitive.
//---------------------------------------------------------------
-BUILDIN(replacestr)
+static BUILDIN(replacestr)
{
const char *input = script_getstr(st, 2);
const char *find = script_getstr(st, 3);
@@ -15601,7 +18205,7 @@ BUILDIN(replacestr)
// Note: Counts the number of times <search> occurs in
// <input>. By default will be case sensitive.
//--------------------------------------------------------
-BUILDIN(countstr)
+static BUILDIN(countstr)
{
const char *input = script_getstr(st, 2);
const char *find = script_getstr(st, 3);
@@ -15658,7 +18262,8 @@ BUILDIN(countstr)
/// setnpcdisplay("<npc name>", "<new display name>", <new class id>) -> <int>
/// setnpcdisplay("<npc name>", "<new display name>") -> <int>
/// setnpcdisplay("<npc name>", <new class id>) -> <int>
-BUILDIN(setnpcdisplay) {
+static BUILDIN(setnpcdisplay)
+{
const char* name;
const char* newname = NULL;
int class_ = -1, size = -1;
@@ -15704,14 +18309,16 @@ BUILDIN(setnpcdisplay) {
return true;
}
-BUILDIN(atoi) {
+static BUILDIN(atoi)
+{
const char *value;
value = script_getstr(st,2);
script_pushint(st,atoi(value));
return true;
}
-BUILDIN(axtoi) {
+static BUILDIN(axtoi)
+{
const char *hex = script_getstr(st,2);
long value = strtol(hex, NULL, 16);
#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
@@ -15721,7 +18328,8 @@ BUILDIN(axtoi) {
return true;
}
-BUILDIN(strtol) {
+static BUILDIN(strtol)
+{
const char *string = script_getstr(st, 2);
int base = script_getnum(st, 3);
long value = strtol(string, NULL, base);
@@ -15733,7 +18341,7 @@ BUILDIN(strtol) {
}
// case-insensitive substring search [lordalfa]
-BUILDIN(compare)
+static BUILDIN(compare)
{
const char *message;
const char *cmpstring;
@@ -15743,7 +18351,7 @@ BUILDIN(compare)
return true;
}
-BUILDIN(strcmp)
+static BUILDIN(strcmp)
{
const char *str1 = script_getstr(st,2);
const char *str2 = script_getstr(st,3);
@@ -15753,7 +18361,7 @@ BUILDIN(strcmp)
// List of mathematics commands --->
-BUILDIN(log10)
+static BUILDIN(log10)
{
double i, a;
i = script_getnum(st,2);
@@ -15762,16 +18370,20 @@ BUILDIN(log10)
return true;
}
-BUILDIN(sqrt) //[zBuffer]
+static BUILDIN(sqrt) //[zBuffer]
{
double i, a;
i = script_getnum(st,2);
+ if (i < 0) {
+ ShowError("sqrt from negative value\n");
+ return false;
+ }
a = sqrt(i);
script_pushint(st,(int)a);
return true;
}
-BUILDIN(pow) //[zBuffer]
+static BUILDIN(pow) //[zBuffer]
{
double i, a, b;
a = script_getnum(st,2);
@@ -15781,7 +18393,7 @@ BUILDIN(pow) //[zBuffer]
return true;
}
-BUILDIN(distance) //[zBuffer]
+static BUILDIN(distance) //[zBuffer]
{
int x0, y0, x1, y1;
@@ -15796,7 +18408,7 @@ BUILDIN(distance) //[zBuffer]
// <--- List of mathematics commands
-BUILDIN(min)
+static BUILDIN(min)
{
int i, min;
@@ -15811,7 +18423,7 @@ BUILDIN(min)
return true;
}
-BUILDIN(max)
+static BUILDIN(max)
{
int i, max;
@@ -15826,22 +18438,34 @@ BUILDIN(max)
return true;
}
-BUILDIN(md5)
+static BUILDIN(cap_value)
+{
+ int value = script_getnum(st, 2);
+ int min = script_getnum(st, 3);
+ int max = script_getnum(st, 4);
+
+ script_pushint(st, (int)cap_value(value, min, max));
+
+ return true;
+}
+
+static BUILDIN(md5)
{
const char *tmpstr;
char *md5str;
tmpstr = script_getstr(st,2);
md5str = (char *)aMalloc((32+1)*sizeof(char));
- MD5_String(tmpstr, md5str);
+ md5->string(tmpstr, md5str);
script_pushstr(st, md5str);
return true;
}
-BUILDIN(swap)
+static BUILDIN(swap)
{
struct map_session_data *sd = NULL;
struct script_data *data1, *data2;
+ struct reg_db *ref1, *ref2;
const char *varname1, *varname2;
int64 uid1, uid2;
@@ -15882,6 +18506,8 @@ BUILDIN(swap)
uid1 = reference_getuid(data1);
uid2 = reference_getuid(data2);
+ ref1 = reference_getref(data1);
+ ref2 = reference_getref(data2);
if (is_string_variable(varname1)) {
const char *value1, *value2;
@@ -15890,8 +18516,8 @@ BUILDIN(swap)
value2 = script_getstr(st,3);
if (strcmpi(value1, value2)) {
- script->set_reg(st, sd, uid1, varname1, value2, script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, value1, script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, value2, ref1);
+ script->set_reg(st, sd, uid2, varname2, value1, ref2);
}
}
else {
@@ -15901,8 +18527,8 @@ BUILDIN(swap)
value2 = script_getnum(st,3);
if (value1 != value2) {
- script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), ref1);
+ script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), ref2);
}
}
return true;
@@ -15910,7 +18536,7 @@ BUILDIN(swap)
// [zBuffer] List of dynamic var commands --->
-BUILDIN(setd)
+static BUILDIN(setd)
{
struct map_session_data *sd = NULL;
char varname[100];
@@ -15940,7 +18566,7 @@ BUILDIN(setd)
return true;
}
-int buildin_query_sql_sub(struct script_state *st, struct Sql *handle)
+static int buildin_query_sql_sub(struct script_state *st, struct Sql *handle)
{
int i, j;
struct map_session_data *sd = NULL;
@@ -16022,11 +18648,13 @@ int buildin_query_sql_sub(struct script_state *st, struct Sql *handle)
return true;
}
-BUILDIN(query_sql) {
+static BUILDIN(query_sql)
+{
return script->buildin_query_sql_sub(st, map->mysql_handle);
}
-BUILDIN(query_logsql) {
+static BUILDIN(query_logsql)
+{
if( !logs->config.sql_logs ) {// logs->mysql_handle == NULL
ShowWarning("buildin_query_logsql: SQL logs are disabled, query '%s' will not be executed.\n", script_getstr(st,2));
script_pushint(st,-1);
@@ -16036,7 +18664,7 @@ BUILDIN(query_logsql) {
}
//Allows escaping of a given string.
-BUILDIN(escape_sql)
+static BUILDIN(escape_sql)
{
const char *str;
char *esc_str;
@@ -16050,25 +18678,37 @@ BUILDIN(escape_sql)
return true;
}
-BUILDIN(getd) {
+static BUILDIN(getd)
+{
char varname[100];
const char *buffer;
int elem;
+ int id;
buffer = script_getstr(st, 2);
if (sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2)
elem = 0;
+ id = script->add_variable(varname);
+
+ if (script->str_data[id].type != C_NAME && // variable
+ script->str_data[id].type != C_PARAM && // param
+ script->str_data[id].type != C_INT) { // constant
+ ShowError("script:getd: `%s` is already used by something that is not a variable.\n", varname);
+ st->state = END;
+ return false;
+ }
+
// Push the 'pointer' so it's more flexible [Lance]
- script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem),NULL);
+ script->push_val(st->stack, C_NAME, reference_uid(id, elem),NULL);
return true;
}
// <--- [zBuffer] List of dynamic var commands
// Pet stat [Lance]
-BUILDIN(petstat)
+static BUILDIN(petstat)
{
struct pet_data *pd;
int flag = script_getnum(st,2);
@@ -16094,7 +18734,7 @@ BUILDIN(petstat)
return true;
}
-BUILDIN(callshop)
+static BUILDIN(callshop)
{
struct npc_data *nd;
const char *shopname;
@@ -16134,7 +18774,7 @@ BUILDIN(callshop)
return true;
}
-BUILDIN(npcshopitem)
+static BUILDIN(npcshopitem)
{
const char* npcname = script_getstr(st, 2);
struct npc_data* nd = npc->name2id(npcname);
@@ -16163,7 +18803,7 @@ BUILDIN(npcshopitem)
return true;
}
-BUILDIN(npcshopadditem)
+static BUILDIN(npcshopadditem)
{
const char* npcname = script_getstr(st,2);
struct npc_data* nd = npc->name2id(npcname);
@@ -16192,7 +18832,7 @@ BUILDIN(npcshopadditem)
return true;
}
-BUILDIN(npcshopdelitem)
+static BUILDIN(npcshopdelitem)
{
const char* npcname = script_getstr(st,2);
struct npc_data* nd = npc->name2id(npcname);
@@ -16214,10 +18854,12 @@ BUILDIN(npcshopdelitem)
unsigned int nameid = script_getnum(st,i);
ARR_FIND(0, size, n, nd->u.shop.shop_item[n].nameid == nameid);
- if (n < size) {
- memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0])*(size-n));
- size--;
+ if (n == size) {
+ continue;
+ } else if (n < size - 1) {
+ memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0]) * (size - n - 1));
}
+ size--;
}
RECREATE(nd->u.shop.shop_item, struct npc_item_list, size);
@@ -16228,7 +18870,8 @@ BUILDIN(npcshopdelitem)
}
//Sets a script to attach to a shop npc.
-BUILDIN(npcshopattach) {
+static BUILDIN(npcshopattach)
+{
const char* npcname = script_getstr(st,2);
struct npc_data* nd = npc->name2id(npcname);
int flag = 1;
@@ -16260,7 +18903,7 @@ BUILDIN(npcshopattach) {
* 1 - Equip script
* 2 - Unequip script
*------------------------------------------*/
-BUILDIN(setitemscript)
+static BUILDIN(setitemscript)
{
int item_id,n=0;
const char *new_bonus_script;
@@ -16306,7 +18949,8 @@ BUILDIN(setitemscript)
* is updated to the new rate. Rate must be in the range [1:10000]
* Returns 1 if succeeded (added/updated a mob drop)
*-------------------------------------------------------*/
-BUILDIN(addmonsterdrop) {
+static BUILDIN(addmonsterdrop)
+{
struct mob_db *monster;
int item_id, rate, i, c = MAX_MOB_DROP;
@@ -16366,7 +19010,8 @@ BUILDIN(addmonsterdrop) {
*
* Returns 1 if succeeded (deleted a mob drop)
*-------------------------------------------------------*/
-BUILDIN(delmonsterdrop) {
+static BUILDIN(delmonsterdrop)
+{
struct mob_db *monster;
int item_id, i;
@@ -16408,7 +19053,7 @@ BUILDIN(delmonsterdrop) {
* Name, Level, race, size, etc...
* getmonsterinfo(monsterID,queryIndex);
*------------------------------------------*/
-BUILDIN(getmonsterinfo)
+static BUILDIN(getmonsterinfo)
{
struct mob_db *monster;
int mob_id;
@@ -16447,12 +19092,13 @@ BUILDIN(getmonsterinfo)
case 20: script_pushint(st,monster->status.def_ele); break;
case 21: script_pushint(st,monster->status.mode); break;
case 22: script_pushint(st,monster->mexp); break;
+ case 23: script_pushint(st, monster->dmg_taken_rate); break;
default: script_pushint(st,-1); //wrong Index
}
return true;
}
-BUILDIN(checkvending) // check vending [Nab4]
+static BUILDIN(checkvending) // check vending [Nab4]
{
struct map_session_data *sd = NULL;
@@ -16470,7 +19116,8 @@ BUILDIN(checkvending) // check vending [Nab4]
}
// check chatting [Marka]
-BUILDIN(checkchatting) {
+static BUILDIN(checkchatting)
+{
struct map_session_data *sd = NULL;
if (script_hasdata(st,2))
@@ -16479,14 +19126,15 @@ BUILDIN(checkchatting) {
sd = script->rid2sd(st);
if (sd != NULL)
- script_pushint(st,(sd->chatID != 0));
+ script_pushint(st, (sd->chat_id != 0));
else
script_pushint(st,0);
return true;
}
-BUILDIN(checkidle) {
+static BUILDIN(checkidle)
+{
struct map_session_data *sd = NULL;
if (script_hasdata(st, 2))
@@ -16502,7 +19150,7 @@ BUILDIN(checkidle) {
return true;
}
-BUILDIN(searchitem)
+static BUILDIN(searchitem)
{
struct script_data* data = script_getdata(st, 2);
const char *itemname = script_getstr(st,3);
@@ -16518,7 +19166,7 @@ BUILDIN(searchitem)
if ((items[0] = itemdb->exists(atoi(itemname)))) {
count = 1;
} else {
- count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, 0);
+ count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, IT_SEARCH_NAME_PARTIAL);
if (count > MAX_SEARCH) count = MAX_SEARCH;
}
@@ -16565,7 +19213,7 @@ BUILDIN(searchitem)
}
// [zBuffer] List of player cont commands --->
-BUILDIN(rid2name)
+static BUILDIN(rid2name)
{
struct block_list *bl = NULL;
int rid = script_getnum(st,2);
@@ -16589,7 +19237,8 @@ BUILDIN(rid2name)
return true;
}
-BUILDIN(pcblockmove) {
+static BUILDIN(pcblockmove)
+{
int id, flag;
struct map_session_data *sd = NULL;
@@ -16601,13 +19250,101 @@ BUILDIN(pcblockmove) {
else
sd = script->rid2sd(st);
- if (sd != NULL)
- sd->state.blockedmove = flag > 0;
+ if (!sd)
+ return true;
+
+ if (flag)
+ sd->block_action.move = 1;
+ else
+ sd->block_action.move = 0;
+
+ return true;
+}
+
+static BUILDIN(setpcblock)
+{
+ struct map_session_data *sd = script_hasdata(st, 4) ? script->id2sd(st, script_getnum(st, 4)) : script->rid2sd(st);
+ enum pcblock_action_flag type = script_getnum(st, 2);
+ int state = (script_getnum(st, 3) > 0) ? 1 : 0;
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ if ((type & PCBLOCK_MOVE) != 0)
+ sd->block_action.move = state;
+
+ if ((type & PCBLOCK_ATTACK) != 0)
+ sd->block_action.attack = state;
+
+ if ((type & PCBLOCK_SKILL) != 0)
+ sd->block_action.skill = state;
+ if ((type & PCBLOCK_USEITEM) != 0)
+ sd->block_action.useitem = state;
+
+ if ((type & PCBLOCK_CHAT) != 0)
+ sd->block_action.chat = state;
+
+ if ((type & PCBLOCK_IMMUNE) != 0)
+ sd->block_action.immune = state;
+
+ if ((type & PCBLOCK_SITSTAND) != 0)
+ sd->block_action.sitstand = state;
+
+ if ((type & PCBLOCK_COMMANDS) != 0)
+ sd->block_action.commands = state;
+
+ if ((type & PCBLOCK_NPC) != 0)
+ sd->block_action.npc = state;
+
+ script_pushint(st, 1);
return true;
}
-BUILDIN(pcfollow)
+static BUILDIN(checkpcblock)
+{
+ struct map_session_data *sd = script_hasdata(st, 2) ? script->id2sd(st, script_getnum(st, 2)) : script->rid2sd(st);
+ int retval = PCBLOCK_NONE;
+
+ if (sd == NULL) {
+ script_pushint(st, PCBLOCK_NONE);
+ return true;
+ }
+
+ if (sd->block_action.move != 0)
+ retval |= PCBLOCK_MOVE;
+
+ if (sd->block_action.attack != 0)
+ retval |= PCBLOCK_ATTACK;
+
+ if (sd->block_action.skill != 0)
+ retval |= PCBLOCK_SKILL;
+
+ if (sd->block_action.useitem != 0)
+ retval |= PCBLOCK_USEITEM;
+
+ if (sd->block_action.chat != 0)
+ retval |= PCBLOCK_CHAT;
+
+ if (sd->block_action.immune != 0)
+ retval |= PCBLOCK_IMMUNE;
+
+ if (sd->block_action.sitstand != 0)
+ retval |= PCBLOCK_SITSTAND;
+
+ if (sd->block_action.commands != 0)
+ retval |= PCBLOCK_COMMANDS;
+
+ if (sd->block_action.npc != 0)
+ retval |= PCBLOCK_NPC;
+
+ script_pushint(st, retval);
+ return true;
+}
+
+static BUILDIN(pcfollow)
{
int id, targetid;
struct map_session_data *sd = NULL;
@@ -16626,7 +19363,7 @@ BUILDIN(pcfollow)
return true;
}
-BUILDIN(pcstopfollow)
+static BUILDIN(pcstopfollow)
{
int id;
struct map_session_data *sd = NULL;
@@ -16647,7 +19384,8 @@ BUILDIN(pcstopfollow)
// [zBuffer] List of mob control commands --->
//## TODO always return if the request/whatever was successfull [FlavioJS]
-BUILDIN(getunittype) {
+static BUILDIN(getunittype)
+{
struct block_list* bl;
int value;
@@ -16674,39 +19412,1852 @@ BUILDIN(getunittype) {
return true;
}
+/**
+ * Sets real-time unit data for a game object.
+ *
+ * @code{.herc}
+ * setunitdata <GUID>, <DataType>, <Val1>{, <Val2>, <Val3>}
+ * @endcode
+ *
+ * @param1 GUID GID of the unit.
+ * @param2 DataType Type of Data to be set for the unit.
+ * @param3 Value#1 Value to be passed as change in data.
+ * @param4 Value#2 Optional int value to be passed for certain data types.
+ * @param5 Value#3 Optional int value to be passed for certain data types.
+ * @return 1 on success, 0 on failure.
+ *
+ * Note: Please make this script command only modify ONE INTEGER value.
+ * If need to modify string type data, or having multiple arguments, please introduce a new script command.
+ *
+ **/
+static BUILDIN(setunitdata)
+{
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
+
+ if (bl == NULL) {
+ ShowWarning("buildin_setunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ int type = script_getnum(st, 3);
+
+ // Type bounds.
+ if (type < UDT_SIZE || type >= UDT_MAX) { // Note: UDT_TYPE is not valid here
+ ShowError("buildin_setunitdata: Invalid unit data type %d provided.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ const char *mapname = NULL;
+ int val = 0;
+
+ // Mandatory argument #3. Subject to deprecate.
+ if (type == UDT_MAPIDXY) {
+ if (!script_isstringtype(st, 4)) {
+ ShowError("buildin_setunitdata: Invalid data type for argument #3.\n");
+ script_pushint(st, 0);
+ return false;
+ }
+
+ mapname = script_getstr(st, 4);
+ } else {
+ if (script_isstringtype(st, 4)) {
+ ShowError("buildin_setunitdata: Invalid data type for argument #3.\n");
+ script_pushint(st, 0);
+ return false;
+ }
+
+ val = script_getnum(st, 4);
+ }
+
+/****************************************************************************************************
+ * Define temporary macros. [BEGIN]
+ ****************************************************************************************************/
+
+// Checks if value is out of bounds.
+#define setunitdata_check_bounds(arg, min, max) \
+ do { \
+ if (script_getnum(st, (arg)) < (min) || script_getnum(st, (arg)) > (max)) { \
+ ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", \
+ script_getnum(st, (arg)), (arg) - 1, (min), (max)); \
+ script_pushint(st, 0); \
+ return false; \
+ } \
+ } while(0);
+
+// Checks if value is too low.
+#define setunitdata_check_min(arg, min) \
+ do { \
+ if (script_getnum(st, (arg)) < (min)) { \
+ ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", \
+ script_getnum(st, (arg)), (arg) - 1, (min)); \
+ script_pushint(st, 0); \
+ return false; \
+ } \
+ } while(0);
+
+// Checks if the argument doesn't exist, if required. Also checks if the argument exists, if not required.
+#define setunitdata_assert_arg(arg, required) \
+ do { \
+ if (required && !script_hasdata(st, (arg))) { \
+ ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg) - 1); \
+ script_pushint(st, 0); \
+ return false; \
+ } else if (!required && script_hasdata(st, arg)) { \
+ ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg) - 1, type); \
+ script_pushint(st, 0); \
+ return false; \
+ } \
+ } while (0);
+
+// Checks if the data is an integer.
+#define setunitdata_check_int(arg) \
+ do { \
+ setunitdata_assert_arg((arg), true); \
+ if (script_isstringtype(st, (arg))) { \
+ ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg) - 1); \
+ script_pushint(st, 0); \
+ return false; \
+ } \
+ } while(0);
+
+// Checks if the data is a string.
+#define setunitdata_check_string(arg) \
+ do { \
+ setunitdata_assert_arg((arg), true); \
+ if (script_isinttype(st, (arg))) { \
+ ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg) - 1); \
+ script_pushint(st, 0); \
+ return false; \
+ } \
+ } while(0);
+
+/****************************************************************************************************
+ * Define temporary macros. [END]
+ ****************************************************************************************************/
+
+ if (type != UDT_MAPIDXY && type != UDT_WALKTOXY) {
+ setunitdata_assert_arg(5, false);
+ setunitdata_assert_arg(6, false);
+ }
+
+ int val2 = 0;
+ int val3 = 0;
+
+ struct map_session_data *tsd = NULL;
+
+ switch (type) {
+ case UDT_SIZE:
+ setunitdata_check_bounds(4, SZ_SMALL, SZ_BIG);
+ break;
+ case UDT_LEVEL:
+ case UDT_HP:
+ case UDT_MAXHP:
+ case UDT_SP:
+ case UDT_MAXSP:
+ case UDT_CLASS:
+ case UDT_HEADBOTTOM:
+ case UDT_HEADMIDDLE:
+ case UDT_HEADTOP:
+ case UDT_CLOTHCOLOR:
+ case UDT_SHIELD:
+ case UDT_WEAPON:
+ case UDT_INTIMACY:
+ case UDT_LIFETIME:
+ case UDT_MERC_KILLCOUNT:
+ case UDT_ROBE:
+ case UDT_BODY2:
+ setunitdata_check_min(4, 0);
+ break;
+ case UDT_MASTERAID:
+ setunitdata_check_min(4, 0);
+ tsd = map->id2sd(val);
+
+ if (tsd == NULL) {
+ ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n", val);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ break;
+ case UDT_MASTERCID:
+ setunitdata_check_min(4, 0);
+ tsd = map->charid2sd(val);
+
+ if (tsd == NULL) {
+ ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n", val);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ break;
+ case UDT_MAPIDXY:
+ if ((val = map->mapname2mapid(mapname)) == INDEX_NOT_FOUND) {
+ ShowError("buildin_setunitdata: Non-existent map %s provided.\n", mapname);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ setunitdata_check_int(5);
+ setunitdata_check_int(6);
+ setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2);
+ setunitdata_check_bounds(6, 0, MAX_MAP_SIZE / 2);
+ val2 = script_getnum(st, 5);
+ val3 = script_getnum(st, 6);
+ break;
+ case UDT_WALKTOXY:
+ setunitdata_assert_arg(6, false);
+ setunitdata_check_int(5);
+ val2 = script_getnum(st, 5);
+ setunitdata_check_bounds(4, 0, MAX_MAP_SIZE / 2);
+ setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2);
+ break;
+ case UDT_SPEED:
+ setunitdata_check_bounds(4, 0, MAX_WALK_SPEED);
+ break;
+ case UDT_MODE:
+ setunitdata_check_bounds(4, MD_NONE, MD_MASK);
+ break;
+ case UDT_AI:
+ setunitdata_check_bounds(4, AI_NONE, AI_MAX-1);
+ break;
+ case UDT_SCOPTION:
+ setunitdata_check_bounds(4, OPTION_NOTHING, OPTION_COSTUME);
+ break;
+ case UDT_SEX:
+ setunitdata_check_bounds(4, SEX_FEMALE, SEX_MALE);
+ break;
+ case UDT_HAIRSTYLE:
+ setunitdata_check_bounds(4, 0, battle->bc->max_hair_style);
+ break;
+ case UDT_HAIRCOLOR:
+ setunitdata_check_bounds(4, 0, battle->bc->max_hair_color);
+ break;
+ case UDT_LOOKDIR:
+ setunitdata_check_bounds(4, 0, 7);
+ break;
+ case UDT_CANMOVETICK:
+ setunitdata_check_min(4, 0);
+ break;
+ case UDT_STR:
+ case UDT_AGI:
+ case UDT_VIT:
+ case UDT_INT:
+ case UDT_DEX:
+ case UDT_LUK:
+ case UDT_STATPOINT:
+ case UDT_ATKRANGE:
+ case UDT_ATKMIN:
+ case UDT_ATKMAX:
+ case UDT_MATKMIN:
+ case UDT_MATKMAX:
+ case UDT_AMOTION:
+ case UDT_ADELAY:
+ case UDT_DMOTION:
+ setunitdata_check_bounds(4, 0, USHRT_MAX);
+ break;
+ case UDT_DEF:
+ case UDT_MDEF:
+ case UDT_HIT:
+ case UDT_FLEE:
+ case UDT_PDODGE:
+ case UDT_CRIT:
+ setunitdata_check_bounds(4, 0, SHRT_MAX);
+ break;
+ case UDT_HUNGER:
+ setunitdata_check_bounds(4, PET_HUNGER_STARVING, PET_HUNGER_STUFFED); // Pets and Homunculi have the same hunger value bounds.
+ break;
+ case UDT_RACE:
+ case UDT_ELETYPE:
+ case UDT_ELELEVEL:
+ setunitdata_check_bounds(4, 0, CHAR_MAX);
+ break;
+ case UDT_GROUP:
+ setunitdata_check_bounds(4, 0, INT_MAX);
+
+ struct unit_data *ud = unit->bl2ud2(bl);
+
+ if (ud == NULL) {
+ ShowError("buildin_setunitdata: ud is NULL!\n");
+ script_pushint(st, 0);
+ return false;
+ }
+
+ ud->groupId = script_getnum(st, 4);
+ clif->blname_ack(0, bl); // Send update to client.
+ script_pushint(st, 1);
+ return true;
+ case UDT_DAMAGE_TAKEN_RATE:
+ setunitdata_check_bounds(4, 1, INT_MAX);
+ break;
+ default:
+ break;
+ }
+
+/****************************************************************************************************
+ * Undefine temporary macros. [BEGIN]
+ ****************************************************************************************************/
+
+#undef setunitdata_check_bounds
+#undef setunitdata_check_min
+#undef setunitdata_assert_arg
+#undef setunitdata_check_int
+#undef setunitdata_check_string
+
+/****************************************************************************************************
+ * Undefine temporary macros. [END]
+ ****************************************************************************************************/
+
+ // Set the values.
+ switch (bl->type) {
+ case BL_MOB: {
+ struct mob_data *md = BL_UCAST(BL_MOB, bl);
+
+ if (md == NULL) {
+ ShowError("buildin_setunitdata: Can't find monster for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ md->status.size = (unsigned char)val;
+ break;
+ case UDT_LEVEL:
+ md->level = val;
+
+ if ((battle_config.show_mob_info & 4) != 0)
+ clif->blname_ack(0, &md->bl);
+
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ clif->blname_ack(0, &md->bl);
+ break;
+ case UDT_MAXHP:
+ md->status.max_hp = (unsigned int)val;
+ clif->blname_ack(0, &md->bl);
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ md->status.max_sp = (unsigned int)val;
+ break;
+ case UDT_MASTERAID:
+ md->master_id = val;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_SPEED:
+ md->status.speed = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_MODE:
+ md->status.mode = (enum e_mode)val;
+ break;
+ case UDT_AI:
+ md->special_state.ai = (enum ai)val;
+ break;
+ case UDT_SCOPTION:
+ md->sc.option = (unsigned int)val;
+ break;
+ case UDT_SEX:
+ md->vd->sex = (char)val;
+ break;
+ case UDT_CLASS:
+ mob->class_change(md, val);
+ break;
+ case UDT_HAIRSTYLE:
+ clif->changelook(bl, LOOK_HAIR, val);
+ break;
+ case UDT_HAIRCOLOR:
+ clif->changelook(bl, LOOK_HAIR_COLOR, val);
+ break;
+ case UDT_HEADBOTTOM:
+ clif->changelook(bl, LOOK_HEAD_BOTTOM, val);
+ break;
+ case UDT_HEADMIDDLE:
+ clif->changelook(bl, LOOK_HEAD_MID, val);
+ break;
+ case UDT_HEADTOP:
+ clif->changelook(bl, LOOK_HEAD_TOP, val);
+ break;
+ case UDT_CLOTHCOLOR:
+ clif->changelook(bl, LOOK_CLOTHES_COLOR, val);
+ break;
+ case UDT_SHIELD:
+ clif->changelook(bl, LOOK_SHIELD, val);
+ break;
+ case UDT_WEAPON:
+ clif->changelook(bl, LOOK_WEAPON, val);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_CANMOVETICK:
+ md->ud.canmove_tick = val;
+ break;
+ case UDT_STR:
+ md->status.str = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_AGI:
+ md->status.agi = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_VIT:
+ md->status.vit = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_INT:
+ md->status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_DEX:
+ md->status.dex = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_LUK:
+ md->status.luk = (unsigned short)val;
+ status->calc_misc(bl, &md->status, md->level);
+ break;
+ case UDT_ATKRANGE:
+ md->status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ md->status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ md->status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ md->status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ md->status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ md->status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ md->status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ md->status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ md->status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ md->status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ md->status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ md->status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ md->status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ md->status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ md->status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ md->status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ md->status.dmotion = (unsigned short)val;
+ break;
+ case UDT_DAMAGE_TAKEN_RATE:
+ md->dmg_taken_rate = (int)val;
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for mob unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ break;
+ }
+ case BL_HOM: {
+ struct homun_data *hd = BL_UCAST(BL_HOM, bl);
+
+ if (hd == NULL) {
+ ShowError("buildin_setunitdata: Can't find Homunculus for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ hd->base_status.size = (unsigned char)val;
+ break;
+ case UDT_LEVEL:
+ hd->homunculus.level = (short)val;
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXHP:
+ hd->homunculus.max_hp = val;
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ hd->homunculus.max_sp = val;
+ break;
+ case UDT_MASTERCID:
+ hd->homunculus.char_id = val;
+ hd->master = tsd;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_SPEED:
+ hd->base_status.speed = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_CANMOVETICK:
+ hd->ud.canmove_tick = val;
+ break;
+ case UDT_STR:
+ hd->base_status.str = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_AGI:
+ hd->base_status.agi = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_VIT:
+ hd->base_status.vit = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_INT:
+ hd->base_status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_DEX:
+ hd->base_status.dex = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_LUK:
+ hd->base_status.luk = (unsigned short)val;
+ status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
+ break;
+ case UDT_ATKRANGE:
+ hd->base_status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ hd->base_status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ hd->base_status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ hd->base_status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ hd->base_status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ hd->base_status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ hd->base_status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ hd->base_status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ hd->base_status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ hd->base_status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ hd->base_status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ hd->base_status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ hd->base_status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ hd->base_status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ hd->base_status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ hd->base_status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ hd->base_status.dmotion = (unsigned short)val;
+ break;
+ case UDT_HUNGER:
+ hd->homunculus.hunger = (short)val;
+ clif->send_homdata(hd->master, SP_HUNGRY, hd->homunculus.hunger);
+ break;
+ case UDT_INTIMACY:
+ homun->add_intimacy(hd, (unsigned int)val);
+ clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100);
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for homunculus unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ clif->send_homdata(hd->master, SP_ACK, 0); // Send Homunculus data.
+ break;
+ }
+ case BL_PET: {
+ struct pet_data *pd = BL_UCAST(BL_PET, bl);
+
+ if (pd == NULL) {
+ ShowError("buildin_setunitdata: Can't find pet for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ pd->status.size = (unsigned char)val;
+ break;
+ case UDT_LEVEL:
+ pd->pet.level = (short)val;
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXHP:
+ pd->status.max_hp = (unsigned int)val;
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ pd->status.max_sp = (unsigned int)val;
+ break;
+ case UDT_MASTERAID:
+ pd->pet.account_id = val;
+ pd->msd = tsd;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_SPEED:
+ pd->status.speed = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_CANMOVETICK:
+ pd->ud.canmove_tick = val;
+ break;
+ case UDT_STR:
+ pd->status.str = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_AGI:
+ pd->status.agi = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_VIT:
+ pd->status.vit = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_INT:
+ pd->status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_DEX:
+ pd->status.dex = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_LUK:
+ pd->status.luk = (unsigned short)val;
+ status->calc_misc(bl, &pd->status, pd->pet.level);
+ break;
+ case UDT_ATKRANGE:
+ pd->status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ pd->status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ pd->status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ pd->status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ pd->status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ pd->status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ pd->status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ pd->status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ pd->status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ pd->status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ pd->status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ pd->status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ pd->status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ pd->status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ pd->status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ pd->status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ pd->status.dmotion = (unsigned short)val;
+ break;
+ case UDT_INTIMACY:
+ pet->set_intimate(pd, val);
+ clif->send_petdata(pd->msd, pd, 1, pd->pet.intimate);
+ break;
+ case UDT_HUNGER:
+ pet->set_hunger(pd, val);
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for pet unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ clif->send_petstatus(pd->msd); // Send pet data.
+ break;
+ }
+ case BL_MER: {
+ struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
+
+ if (mc == NULL) {
+ ShowError("buildin_setunitdata: Can't find mercenary for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ mc->base_status.size = (unsigned char)val;
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXHP:
+ mc->base_status.max_hp = (unsigned int)val;
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ mc->base_status.max_sp = (unsigned int)val;
+ break;
+ case UDT_MASTERCID:
+ mc->mercenary.char_id = val;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_SPEED:
+ mc->base_status.size = (unsigned char)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_CANMOVETICK:
+ mc->ud.canmove_tick = val;
+ break;
+ case UDT_STR:
+ mc->base_status.str = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_AGI:
+ mc->base_status.agi = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_VIT:
+ mc->base_status.vit = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_INT:
+ mc->base_status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_DEX:
+ mc->base_status.dex = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_LUK:
+ mc->base_status.luk = (unsigned short)val;
+ status->calc_misc(bl, &mc->base_status, mc->db->lv);
+ break;
+ case UDT_ATKRANGE:
+ mc->base_status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ mc->base_status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ mc->base_status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ mc->base_status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ mc->base_status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ mc->base_status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ mc->base_status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ mc->base_status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ mc->base_status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ mc->base_status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ mc->base_status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ mc->base_status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ mc->base_status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ mc->base_status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ mc->base_status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ mc->base_status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ mc->base_status.dmotion = (unsigned short)val;
+ break;
+ case UDT_MERC_KILLCOUNT:
+ mc->mercenary.kill_count = (unsigned int)val;
+ break;
+ case UDT_LIFETIME:
+ mc->mercenary.life_time = (unsigned int)val;
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for mercenary unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ // Send mercenary data.
+ clif->mercenary_info(map->charid2sd(mc->mercenary.char_id));
+ clif->mercenary_skillblock(map->charid2sd(mc->mercenary.char_id));
+ break;
+ }
+ case BL_ELEM: {
+ struct elemental_data *ed = BL_UCAST(BL_ELEM, bl);
+
+ if (ed == NULL) {
+ ShowError("buildin_setunitdata: Can't find Elemental for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ ed->base_status.size = (unsigned char)val;
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXHP:
+ ed->base_status.max_hp = (unsigned int)val;
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ ed->base_status.max_sp = (unsigned int)val;
+ break;
+ case UDT_MASTERCID:
+ ed->elemental.char_id = val;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_SPEED:
+ ed->base_status.speed = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_CANMOVETICK:
+ ed->ud.canmove_tick = val;
+ break;
+ case UDT_STR:
+ ed->base_status.str = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_AGI:
+ ed->base_status.agi = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_VIT:
+ ed->base_status.vit = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_INT:
+ ed->base_status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_DEX:
+ ed->base_status.dex = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_LUK:
+ ed->base_status.luk = (unsigned short)val;
+ status->calc_misc(bl, &ed->base_status, ed->db->lv);
+ break;
+ case UDT_ATKRANGE:
+ ed->base_status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ ed->base_status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ ed->base_status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ ed->base_status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ ed->base_status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ ed->base_status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ ed->base_status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ ed->base_status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ ed->base_status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ ed->base_status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ ed->base_status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ ed->base_status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ ed->base_status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ ed->base_status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ ed->base_status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ ed->base_status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ ed->base_status.dmotion = (unsigned short)val;
+ break;
+ case UDT_LIFETIME:
+ ed->elemental.life_time = val;
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for elemental unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ clif->elemental_info(ed->master); // Send Elemental data.
+ break;
+ }
+ case BL_NPC: {
+ struct npc_data *nd = BL_UCAST(BL_NPC, bl);
+
+ if (nd == NULL) {
+ ShowError("buildin_setunitdata: Can't find NPC for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ case UDT_SIZE:
+ nd->status.size = (unsigned char)val;
+ break;
+ case UDT_LEVEL:
+ nd->level = (unsigned short)val;
+ break;
+ case UDT_HP:
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXHP:
+ nd->status.max_hp = (unsigned int)val;
+ break;
+ case UDT_SP:
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
+ break;
+ case UDT_MAXSP:
+ nd->status.max_sp = (unsigned int)val;
+ break;
+ case UDT_MAPIDXY:
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
+ break;
+ case UDT_WALKTOXY:
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
+ break;
+ case UDT_CLASS:
+ npc->setclass(nd, (short)val);
+ break;
+ case UDT_SPEED:
+ nd->speed = (short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_LOOKDIR:
+ unit->set_dir(bl, (enum unit_dir)val);
+ break;
+ case UDT_STR:
+ nd->status.str = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_AGI:
+ nd->status.agi = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_VIT:
+ nd->status.vit = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_INT:
+ nd->status.int_ = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_DEX:
+ nd->status.dex = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_LUK:
+ nd->status.luk = (unsigned short)val;
+ status->calc_misc(bl, &nd->status, nd->level);
+ break;
+ case UDT_STATPOINT:
+ nd->stat_point = (unsigned short)val;
+ break;
+ case UDT_ATKRANGE:
+ nd->status.rhw.range = (unsigned short)val;
+ break;
+ case UDT_ATKMIN:
+ nd->status.rhw.atk = (unsigned short)val;
+ break;
+ case UDT_ATKMAX:
+ nd->status.rhw.atk2 = (unsigned short)val;
+ break;
+ case UDT_MATKMIN:
+ nd->status.matk_min = (unsigned short)val;
+ break;
+ case UDT_MATKMAX:
+ nd->status.matk_max = (unsigned short)val;
+ break;
+ case UDT_DEF:
+ nd->status.def = (defType)val;
+ break;
+ case UDT_MDEF:
+ nd->status.mdef = (defType)val;
+ break;
+ case UDT_HIT:
+ nd->status.hit = (short)val;
+ break;
+ case UDT_FLEE:
+ nd->status.flee = (short)val;
+ break;
+ case UDT_PDODGE:
+ nd->status.flee2 = (short)val;
+ break;
+ case UDT_CRIT:
+ nd->status.cri = (short)val;
+ break;
+ case UDT_RACE:
+ nd->status.race = (unsigned char)val;
+ break;
+ case UDT_ELETYPE:
+ nd->status.def_ele = (unsigned char)val;
+ break;
+ case UDT_ELELEVEL:
+ nd->status.ele_lv = (unsigned char)val;
+ break;
+ case UDT_AMOTION:
+ nd->status.amotion = (unsigned short)val;
+ break;
+ case UDT_ADELAY:
+ nd->status.adelay = (unsigned short)val;
+ break;
+ case UDT_DMOTION:
+ nd->status.dmotion = (unsigned short)val;
+ break;
+ case UDT_SEX:
+ nd->vd.sex = (char)val;
+ npc->refresh(nd);
+ break;
+ case UDT_HAIRSTYLE:
+ clif->changelook(bl, LOOK_HAIR, val);
+ break;
+ case UDT_HAIRCOLOR:
+ clif->changelook(bl, LOOK_HAIR_COLOR, val);
+ break;
+ case UDT_HEADBOTTOM:
+ clif->changelook(bl, LOOK_HEAD_BOTTOM, val);
+ break;
+ case UDT_HEADMIDDLE:
+ clif->changelook(bl, LOOK_HEAD_MID, val);
+ break;
+ case UDT_HEADTOP:
+ clif->changelook(bl, LOOK_HEAD_TOP, val);
+ break;
+ case UDT_CLOTHCOLOR:
+ clif->changelook(bl, LOOK_CLOTHES_COLOR, val);
+ break;
+ case UDT_SHIELD:
+ clif->changelook(bl, LOOK_SHIELD, val);
+ break;
+ case UDT_WEAPON:
+ clif->changelook(bl, LOOK_WEAPON, val);
+ break;
+ case UDT_ROBE:
+ clif->changelook(bl, LOOK_ROBE, val);
+ break;
+ case UDT_BODY2:
+ clif->changelook(bl, LOOK_BODY2, val);
+ break;
+ default:
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for NPC unit.\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ break;
+ }
+ default:
+ ShowError("buildin_setunitdata: Unknown object!\n");
+ script_pushint(st, 0);
+ return false;
+ } // End of bl->type switch.
+
+ script_pushint(st, 1);
+
+ return true;
+}
+
+/**
+ * Retrieves real-time data for a game object.
+ * Getunitdata <GUID>,<DataType>{,<Variable>}
+ * @param1 GUID Game object unique Id.
+ * @param2 DataType Type of Data to be set for the unit.
+ * @param3 Variable array reference to store data into. (used for UDT_MAPIDXY)
+ * @return 0 on failure, <value> on success
+
+ Note: Please make this script command only return ONE INTEGER value.
+ If the unit data having multiple arguments, or need to return in array,
+ please introduce a new script command.
+ */
+static BUILDIN(getunitdata)
+{
+ struct block_list *bl;
+ const char *udtype = NULL;
+ const struct map_session_data *sd = NULL;
+ int type = 0;
+ char* name = NULL;
+ struct script_data *data = script_hasdata(st,4)?script_getdata(st, 4):NULL;
+
+ bl = map->id2bl(script_getnum(st, 2));
+
+ if (bl == NULL) {
+ ShowWarning("buildin_getunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, -1);
+ return false;
+ }
+
+ type = script_getnum(st, 3);
+
+ /* Type check */
+ if (type < UDT_TYPE || type >= UDT_MAX) {
+ ShowError("buildin_getunitdata: Invalid unit data type %d provided.\n", type);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ /* Argument checks. Subject to deprecate */
+ if (type == UDT_MAPIDXY) {
+ if (data == NULL || !data_isreference(data)) {
+ ShowWarning("buildin_getunitdata: Error in argument 3. Please provide a reference variable to store values in.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+
+ name = reference_getname(data);
+
+ if (not_server_variable(*name)) {
+ sd = script->rid2sd(st);
+ if (sd == NULL) {
+ ShowWarning("buildin_getunitdata: Player not attached! Cannot use player variable %s.\n",name);
+ script_pushint(st, -1);
+ return true;// no player attached
+ }
+ }
+ } else if (type == UDT_GROUP) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL) {
+ ShowError("buildin_setunitdata: ud is NULL!\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ script_pushint(st, ud->groupId);
+ return true;
+ }
+
+#define getunitdata_sub(idx__,var__) script->setd_sub(st,NULL,name,(idx__),(void *)h64BPTRSIZE((int)(var__)),data->ref);
+
+ switch (bl->type) {
+ case BL_MOB:
+ {
+ const struct mob_data *md = BL_UCAST(BL_MOB, bl);
+
+ nullpo_retr(false, md);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_MOB); break;
+ case UDT_SIZE: script_pushint(st, md->status.size); break;
+ case UDT_LEVEL: script_pushint(st, md->level); break;
+ case UDT_HP: script_pushint(st, md->status.hp); break;
+ case UDT_MAXHP: script_pushint(st, md->status.max_hp); break;
+ case UDT_SP: script_pushint(st, md->status.sp); break;
+ case UDT_MAXSP: script_pushint(st, md->status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, md->bl.m);
+ getunitdata_sub(1, md->bl.x);
+ getunitdata_sub(2, md->bl.y);
+ break;
+ case UDT_SPEED: script_pushint(st, md->status.speed); break;
+ case UDT_MODE: script_pushint(st, md->status.mode); break;
+ case UDT_AI: script_pushint(st, md->special_state.ai); break;
+ case UDT_SCOPTION: script_pushint(st, md->sc.option); break;
+ case UDT_SEX: script_pushint(st, md->vd->sex); break;
+ case UDT_CLASS: script_pushint(st, md->vd->class); break;
+ case UDT_HAIRSTYLE: script_pushint(st, md->vd->hair_style); break;
+ case UDT_HAIRCOLOR: script_pushint(st, md->vd->hair_color); break;
+ case UDT_HEADBOTTOM: script_pushint(st, md->vd->head_bottom); break;
+ case UDT_HEADMIDDLE: script_pushint(st, md->vd->head_mid); break;
+ case UDT_HEADTOP: script_pushint(st, md->vd->head_top); break;
+ case UDT_CLOTHCOLOR: script_pushint(st, md->vd->cloth_color); break;
+ case UDT_SHIELD: script_pushint(st, md->vd->shield); break;
+ case UDT_WEAPON: script_pushint(st, md->vd->weapon); break;
+ case UDT_LOOKDIR: script_pushint(st, md->ud.dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, md->ud.canmove_tick); break;
+ case UDT_STR: script_pushint(st, md->status.str); break;
+ case UDT_AGI: script_pushint(st, md->status.agi); break;
+ case UDT_VIT: script_pushint(st, md->status.vit); break;
+ case UDT_INT: script_pushint(st, md->status.int_); break;
+ case UDT_DEX: script_pushint(st, md->status.dex); break;
+ case UDT_LUK: script_pushint(st, md->status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, md->status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, md->status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, md->status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, md->status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, md->status.matk_max); break;
+ case UDT_DEF: script_pushint(st, md->status.def); break;
+ case UDT_MDEF: script_pushint(st, md->status.mdef); break;
+ case UDT_HIT: script_pushint(st, md->status.hit); break;
+ case UDT_FLEE: script_pushint(st, md->status.flee); break;
+ case UDT_PDODGE: script_pushint(st, md->status.flee2); break;
+ case UDT_CRIT: script_pushint(st, md->status.cri); break;
+ case UDT_RACE: script_pushint(st, md->status.race); break;
+ case UDT_ELETYPE: script_pushint(st, md->status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, md->status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, md->status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, md->status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, md->status.dmotion); break;
+ case UDT_DAMAGE_TAKEN_RATE: script_pushint(st, md->dmg_taken_rate); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mob unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ case BL_HOM:
+ {
+ const struct homun_data *hd = BL_UCAST(BL_HOM, bl);
+
+ nullpo_retr(false, hd);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_HOM); break;
+ case UDT_SIZE: script_pushint(st, hd->base_status.size); break;
+ case UDT_LEVEL: script_pushint(st, hd->homunculus.level); break;
+ case UDT_HP: script_pushint(st, hd->base_status.hp); break;
+ case UDT_MAXHP: script_pushint(st, hd->base_status.max_hp); break;
+ case UDT_SP: script_pushint(st, hd->base_status.sp); break;
+ case UDT_MAXSP: script_pushint(st, hd->base_status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, hd->bl.m);
+ getunitdata_sub(1, hd->bl.x);
+ getunitdata_sub(2, hd->bl.y);
+ break;
+ case UDT_SPEED: script_pushint(st, hd->base_status.speed); break;
+ case UDT_LOOKDIR: script_pushint(st, hd->ud.dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, hd->ud.canmove_tick); break;
+ case UDT_MODE: script_pushint(st, hd->base_status.mode); break;
+ case UDT_STR: script_pushint(st, hd->base_status.str); break;
+ case UDT_AGI: script_pushint(st, hd->base_status.agi); break;
+ case UDT_VIT: script_pushint(st, hd->base_status.vit); break;
+ case UDT_INT: script_pushint(st, hd->base_status.int_); break;
+ case UDT_DEX: script_pushint(st, hd->base_status.dex); break;
+ case UDT_LUK: script_pushint(st, hd->base_status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, hd->base_status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, hd->base_status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, hd->base_status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, hd->base_status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, hd->base_status.matk_max); break;
+ case UDT_DEF: script_pushint(st, hd->base_status.def); break;
+ case UDT_MDEF: script_pushint(st, hd->base_status.mdef); break;
+ case UDT_HIT: script_pushint(st, hd->base_status.hit); break;
+ case UDT_FLEE: script_pushint(st, hd->base_status.flee); break;
+ case UDT_PDODGE: script_pushint(st, hd->base_status.flee2); break;
+ case UDT_CRIT: script_pushint(st, hd->base_status.cri); break;
+ case UDT_RACE: script_pushint(st, hd->base_status.race); break;
+ case UDT_ELETYPE: script_pushint(st, hd->base_status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, hd->base_status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, hd->base_status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, hd->base_status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, hd->base_status.dmotion); break;
+ case UDT_MASTERCID: script_pushint(st, hd->homunculus.char_id); break;
+ case UDT_HUNGER: script_pushint(st, hd->homunculus.hunger); break;
+ case UDT_INTIMACY: script_pushint(st, hd->homunculus.intimacy); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for Homunculus unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ case BL_PET:
+ {
+ const struct pet_data *pd = BL_UCAST(BL_PET, bl);
+
+ nullpo_retr(false, pd);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_PET); break;
+ case UDT_SIZE: script_pushint(st, pd->status.size); break;
+ case UDT_LEVEL: script_pushint(st, pd->pet.level); break;
+ case UDT_HP: script_pushint(st, pd->status.hp); break;
+ case UDT_MAXHP: script_pushint(st, pd->status.max_hp); break;
+ case UDT_SP: script_pushint(st, pd->status.sp); break;
+ case UDT_MAXSP: script_pushint(st, pd->status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, pd->bl.m);
+ getunitdata_sub(1, pd->bl.x);
+ getunitdata_sub(2, pd->bl.y);
+ break;
+ case UDT_SPEED: script_pushint(st, pd->status.speed); break;
+ case UDT_LOOKDIR: script_pushint(st, pd->ud.dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, pd->ud.canmove_tick); break;
+ case UDT_MODE: script_pushint(st, pd->status.mode); break;
+ case UDT_STR: script_pushint(st, pd->status.str); break;
+ case UDT_AGI: script_pushint(st, pd->status.agi); break;
+ case UDT_VIT: script_pushint(st, pd->status.vit); break;
+ case UDT_INT: script_pushint(st, pd->status.int_); break;
+ case UDT_DEX: script_pushint(st, pd->status.dex); break;
+ case UDT_LUK: script_pushint(st, pd->status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, pd->status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, pd->status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, pd->status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, pd->status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, pd->status.matk_max); break;
+ case UDT_DEF: script_pushint(st, pd->status.def); break;
+ case UDT_MDEF: script_pushint(st, pd->status.mdef); break;
+ case UDT_HIT: script_pushint(st, pd->status.hit); break;
+ case UDT_FLEE: script_pushint(st, pd->status.flee); break;
+ case UDT_PDODGE: script_pushint(st, pd->status.flee2); break;
+ case UDT_CRIT: script_pushint(st, pd->status.cri); break;
+ case UDT_RACE: script_pushint(st, pd->status.race); break;
+ case UDT_ELETYPE: script_pushint(st, pd->status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, pd->status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, pd->status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, pd->status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, pd->status.dmotion); break;
+ case UDT_MASTERAID: script_pushint(st, pd->pet.account_id); break;
+ case UDT_HUNGER: script_pushint(st, pd->pet.hungry); break;
+ case UDT_INTIMACY: script_pushint(st, pd->pet.intimate); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for Pet unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ case BL_MER:
+ {
+ const struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
+
+ nullpo_retr(false, mc);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_MER); break;
+ case UDT_SIZE: script_pushint(st, mc->base_status.size); break;
+ case UDT_HP: script_pushint(st, mc->base_status.hp); break;
+ case UDT_MAXHP: script_pushint(st, mc->base_status.max_hp); break;
+ case UDT_SP: script_pushint(st, mc->base_status.sp); break;
+ case UDT_MAXSP: script_pushint(st, mc->base_status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, mc->bl.m);
+ getunitdata_sub(1, mc->bl.x);
+ getunitdata_sub(2, mc->bl.y);
+ break;
+ case UDT_SPEED: script_pushint(st, mc->base_status.speed); break;
+ case UDT_LOOKDIR: script_pushint(st, mc->ud.dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, mc->ud.canmove_tick); break;
+ case UDT_MODE: script_pushint(st, mc->base_status.mode); break;
+ case UDT_STR: script_pushint(st, mc->base_status.str); break;
+ case UDT_AGI: script_pushint(st, mc->base_status.agi); break;
+ case UDT_VIT: script_pushint(st, mc->base_status.vit); break;
+ case UDT_INT: script_pushint(st, mc->base_status.int_); break;
+ case UDT_DEX: script_pushint(st, mc->base_status.dex); break;
+ case UDT_LUK: script_pushint(st, mc->base_status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, mc->base_status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, mc->base_status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, mc->base_status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, mc->base_status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, mc->base_status.matk_max); break;
+ case UDT_DEF: script_pushint(st, mc->base_status.def); break;
+ case UDT_MDEF: script_pushint(st, mc->base_status.mdef); break;
+ case UDT_HIT: script_pushint(st, mc->base_status.hit); break;
+ case UDT_FLEE: script_pushint(st, mc->base_status.flee); break;
+ case UDT_PDODGE: script_pushint(st, mc->base_status.flee2); break;
+ case UDT_CRIT: script_pushint(st, mc->base_status.cri); break;
+ case UDT_RACE: script_pushint(st, mc->base_status.race); break;
+ case UDT_ELETYPE: script_pushint(st, mc->base_status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, mc->base_status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, mc->base_status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, mc->base_status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, mc->base_status.dmotion); break;
+ case UDT_MASTERCID: script_pushint(st, mc->mercenary.char_id); break;
+ case UDT_MERC_KILLCOUNT: script_pushint(st, mc->mercenary.kill_count); break;
+ case UDT_LIFETIME: script_pushint(st, mc->mercenary.life_time); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for Mercenary unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ case BL_ELEM:
+ {
+ const struct elemental_data *ed = BL_UCAST(BL_ELEM, bl);
+
+ nullpo_retr(false, ed);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_ELEM); break;
+ case UDT_SIZE: script_pushint(st, ed->base_status.size); break;
+ case UDT_HP: script_pushint(st, ed->base_status.hp); break;
+ case UDT_MAXHP: script_pushint(st, ed->base_status.max_hp); break;
+ case UDT_SP: script_pushint(st, ed->base_status.sp); break;
+ case UDT_MAXSP: script_pushint(st, ed->base_status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, ed->bl.m);
+ getunitdata_sub(1, ed->bl.x);
+ getunitdata_sub(2, ed->bl.y);
+ break;
+ case UDT_SPEED: script_pushint(st, ed->base_status.speed); break;
+ case UDT_LOOKDIR: script_pushint(st, ed->ud.dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, ed->ud.canmove_tick); break;
+ case UDT_MODE: script_pushint(st, ed->base_status.mode); break;
+ case UDT_STR: script_pushint(st, ed->base_status.str); break;
+ case UDT_AGI: script_pushint(st, ed->base_status.agi); break;
+ case UDT_VIT: script_pushint(st, ed->base_status.vit); break;
+ case UDT_INT: script_pushint(st, ed->base_status.int_); break;
+ case UDT_DEX: script_pushint(st, ed->base_status.dex); break;
+ case UDT_LUK: script_pushint(st, ed->base_status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, ed->base_status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, ed->base_status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, ed->base_status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, ed->base_status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, ed->base_status.matk_max); break;
+ case UDT_DEF: script_pushint(st, ed->base_status.def); break;
+ case UDT_MDEF: script_pushint(st, ed->base_status.mdef); break;
+ case UDT_HIT: script_pushint(st, ed->base_status.hit); break;
+ case UDT_FLEE: script_pushint(st, ed->base_status.flee); break;
+ case UDT_PDODGE: script_pushint(st, ed->base_status.flee2); break;
+ case UDT_CRIT: script_pushint(st, ed->base_status.cri); break;
+ case UDT_RACE: script_pushint(st, ed->base_status.race); break;
+ case UDT_ELETYPE: script_pushint(st, ed->base_status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, ed->base_status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, ed->base_status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, ed->base_status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, ed->base_status.dmotion); break;
+ case UDT_MASTERCID: script_pushint(st, ed->elemental.char_id); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for Elemental unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ case BL_NPC:
+ {
+ const struct npc_data *nd = BL_UCAST(BL_NPC, bl);
+
+ nullpo_retr(false, nd);
+
+ switch (type)
+ {
+ case UDT_TYPE: script_pushint(st, BL_NPC); break;
+ case UDT_SIZE: script_pushint(st, nd->status.size); break;
+ case UDT_HP: script_pushint(st, nd->status.hp); break;
+ case UDT_MAXHP: script_pushint(st, nd->status.max_hp); break;
+ case UDT_SP: script_pushint(st, nd->status.sp); break;
+ case UDT_MAXSP: script_pushint(st, nd->status.max_sp); break;
+ case UDT_MAPIDXY:
+ getunitdata_sub(0, bl->m);
+ getunitdata_sub(1, bl->x);
+ getunitdata_sub(2, bl->y);
+ break;
+ case UDT_SPEED: script_pushint(st, nd->status.speed); break;
+ case UDT_LOOKDIR: script_pushint(st, nd->ud->dir); break;
+ case UDT_CANMOVETICK: script_pushint(st, nd->ud->canmove_tick); break;
+ case UDT_MODE: script_pushint(st, nd->status.mode); break;
+ case UDT_STR: script_pushint(st, nd->status.str); break;
+ case UDT_AGI: script_pushint(st, nd->status.agi); break;
+ case UDT_VIT: script_pushint(st, nd->status.vit); break;
+ case UDT_INT: script_pushint(st, nd->status.int_); break;
+ case UDT_DEX: script_pushint(st, nd->status.dex); break;
+ case UDT_LUK: script_pushint(st, nd->status.luk); break;
+ case UDT_ATKRANGE: script_pushint(st, nd->status.rhw.range); break;
+ case UDT_ATKMIN: script_pushint(st, nd->status.rhw.atk); break;
+ case UDT_ATKMAX: script_pushint(st, nd->status.rhw.atk2); break;
+ case UDT_MATKMIN: script_pushint(st, nd->status.matk_min); break;
+ case UDT_MATKMAX: script_pushint(st, nd->status.matk_max); break;
+ case UDT_DEF: script_pushint(st, nd->status.def); break;
+ case UDT_MDEF: script_pushint(st, nd->status.mdef); break;
+ case UDT_HIT: script_pushint(st, nd->status.hit); break;
+ case UDT_FLEE: script_pushint(st, nd->status.flee); break;
+ case UDT_PDODGE: script_pushint(st, nd->status.flee2); break;
+ case UDT_CRIT: script_pushint(st, nd->status.cri); break;
+ case UDT_RACE: script_pushint(st, nd->status.race); break;
+ case UDT_ELETYPE: script_pushint(st, nd->status.def_ele); break;
+ case UDT_ELELEVEL: script_pushint(st, nd->status.ele_lv); break;
+ case UDT_AMOTION: script_pushint(st, nd->status.amotion); break;
+ case UDT_ADELAY: script_pushint(st, nd->status.adelay); break;
+ case UDT_DMOTION: script_pushint(st, nd->status.dmotion); break;
+ case UDT_SEX: script_pushint(st, nd->vd.sex); break;
+ case UDT_CLASS: script_pushint(st, nd->vd.class); break;
+ case UDT_HAIRSTYLE: script_pushint(st, nd->vd.hair_style); break;
+ case UDT_HAIRCOLOR: script_pushint(st, nd->vd.hair_color); break;
+ case UDT_HEADBOTTOM: script_pushint(st, nd->vd.head_bottom); break;
+ case UDT_HEADMIDDLE: script_pushint(st, nd->vd.head_mid); break;
+ case UDT_HEADTOP: script_pushint(st, nd->vd.head_top); break;
+ case UDT_CLOTHCOLOR: script_pushint(st, nd->vd.cloth_color); break;
+ case UDT_SHIELD: script_pushint(st, nd->vd.shield); break;
+ case UDT_WEAPON: script_pushint(st, nd->vd.weapon); break;
+ case UDT_ROBE: script_pushint(st, nd->vd.robe); break;
+ case UDT_BODY2: script_pushint(st, nd->vd.body_style); break;
+ default:
+ ShowWarning("buildin_getunitdata: Invalid data type '%s' for NPC unit.\n", udtype);
+ script_pushint(st, -1);
+ return false;
+ }
+ }
+ break;
+ default:
+ ShowError("buildin_getunitdata: Unknown object!\n");
+ script_pushint(st, -1);
+ return false;
+ } // end of bl->type switch
+
+#undef getunitdata_sub
+
+ return true;
+}
+
+/**
+ * Gets the name of a Unit.
+ * Supported types are [MOB|HOM|PET|NPC].
+ * MER and ELEM don't support custom names.
+ *
+ * @command getunitname <GUID>;
+ * @param GUID Game Object Unique ID.
+ * @return boolean or Name of the game object.
+ */
+static BUILDIN(getunitname)
+{
+ const struct block_list* bl = NULL;
+
+ bl = map->id2bl(script_getnum(st, 2));
+
+ if (bl == NULL) {
+ ShowWarning("buildin_getunitname: Error in finding object with given game ID %d!\n", script_getnum(st, 2));
+ script_pushconststr(st, "Unknown");
+ return false;
+ }
+
+ script_pushstrcopy(st, status->get_name(bl));
+
+ return true;
+}
+
+/**
+ * Changes the name of a bl.
+ * Supported types are [MOB|HOM|PET].
+ * For NPC see 'setnpcdisplay', MER and ELEM don't support custom names.
+ *
+ * @command setunitname <GUID>,<name>;
+ * @param GUID Game object unique ID.
+ * @param Name as string.
+ * @return boolean.
+ */
+static BUILDIN(setunitname)
+{
+ struct block_list* bl = map->id2bl(script_getnum(st, 2));
+
+ if (bl == NULL) {
+ ShowWarning("buildin_setunitname: Game object with ID %d was not found!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (bl->type) {
+ case BL_MOB:
+ {
+ struct mob_data *md = BL_UCAST(BL_MOB, bl);
+ if (md == NULL) {
+ ShowWarning("buildin_setunitname: Error in finding object BL_MOB!\n");
+ script_pushint(st, 0);
+ return false;
+ }
+ safestrncpy(md->name, script_getstr(st, 3), NAME_LENGTH);
+ }
+ break;
+ case BL_HOM:
+ {
+ struct homun_data *hd = BL_UCAST(BL_HOM, bl);
+ if (hd == NULL) {
+ ShowWarning("buildin_setunitname: Error in finding object BL_HOM!\n");
+ script_pushint(st, 0);
+ return false;
+ }
+ safestrncpy(hd->homunculus.name, script_getstr(st, 3), NAME_LENGTH);
+ }
+ break;
+ case BL_PET:
+ {
+ struct pet_data *pd = BL_UCAST(BL_PET, bl);
+ if (pd == NULL) {
+ ShowWarning("buildin_setunitname: Error in finding object BL_PET!\n");
+ script_pushint(st, 0);
+ return false;
+ }
+ safestrncpy(pd->pet.name, script_getstr(st, 3), NAME_LENGTH);
+ }
+ break;
+ default:
+ script_pushint(st, 0);
+ ShowWarning("buildin_setunitname: Unknown object type!\n");
+ return false;
+ }
+
+ script_pushint(st, 1);
+ clif->blname_ack(0, bl); // Send update to client.
+
+ return true;
+}
+
+static BUILDIN(setunittitle)
+{
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
+ if (bl == NULL) {
+ ShowWarning("buildin_setunittitle: Error in finding object with given game ID %d!\n", script_getnum(st, 2));
+ return false;
+ }
+
+ struct unit_data *ud = unit->bl2ud2(bl);
+ if (ud == NULL) {
+ ShowWarning("buildin_setunittitle: Error in finding unit_data for given game ID %d!\n", script_getnum(st, 2));
+ return false;
+ }
+
+ safestrncpy(ud->title, script_getstr(st, 3), NAME_LENGTH);
+ clif->blname_ack(0, bl); // Send update to client.
+
+ return true;
+}
+
+static BUILDIN(getunittitle)
+{
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
+ if (bl == NULL) {
+ ShowWarning("buildin_getunitname: Error in finding object with given game ID %d!\n", script_getnum(st, 2));
+ script_pushconststr(st, "Unknown");
+ return false;
+ }
+
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL) {
+ ShowWarning("buildin_setunittitle: Error in finding unit_data for given game ID %d!\n", script_getnum(st, 2));
+ return false;
+ }
+
+ script_pushstrcopy(st, ud->title);
+
+ return true;
+}
+
/// Makes the unit walk to target position or target id
/// Returns if it was successfull
///
/// unitwalk(<unit_id>,<x>,<y>) -> <bool>
/// unitwalk(<unit_id>,<target_id>) -> <bool>
-BUILDIN(unitwalk) {
- struct block_list* bl;
+static BUILDIN(unitwalk)
+{
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
- bl = map->id2bl(script_getnum(st,2));
- if( bl == NULL ) {
+ if (bl == NULL) {
script_pushint(st, 0);
return true;
}
- if( bl->type == BL_NPC ) {
- unit->bl2ud2(bl); // ensure the ((struct npc_data*)bl)->ud is safe to edit
+ if (bl->type == BL_NPC) {
+ struct unit_data *ud = unit->bl2ud2(bl); // ensure the ((struct npc_data*)bl)->ud is safe to edit
+ if (ud == NULL) {
+ ShowWarning("buildin_unitwalk: floating NPC don't have unit data.\n");
+ return false;
+ }
}
- if( script_hasdata(st,4) ) {
- int x = script_getnum(st,3);
- int y = script_getnum(st,4);
- script_pushint(st, unit->walktoxy(bl,x,y,0));// We'll use harder calculations.
- } else {
- int target_id = script_getnum(st,3);
- script_pushint(st, unit->walktobl(bl,map->id2bl(target_id),1,1));
+ if (script_hasdata(st, 4)) {
+ int x = script_getnum(st, 3);
+ int y = script_getnum(st, 4);
+ if (unit->walk_toxy(bl, x, y, 0) == 0) // We'll use harder calculations.
+ script_pushint(st, 1);
+ else
+ script_pushint(st, 0);
+ }
+ else {
+ int target_id = script_getnum(st, 3);
+ script_pushint(st, unit->walktobl(bl, map->id2bl(target_id), 1, 1));
+ }
+
+ return true;
+}
+
+/**
+ * Checks if a unit is walking.
+ *
+ * Returns 1 if unit is walking, 0 if unit is not walking and -1 on error.
+ *
+ * @code{.herc}
+ * unitiswalking({<GID>});
+ * @endcode
+ *
+ **/
+static BUILDIN(unitiswalking)
+{
+ int gid = script_hasdata(st, 2) ? script_getnum(st, 2) : st->rid;
+ struct block_list *bl = map->id2bl(gid);
+
+ if (bl == NULL) {
+ ShowWarning("buildin_unitiswalking: Error in finding object for GID %d!\n", gid);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (unit->bl2ud(bl) == NULL) {
+ ShowWarning("buildin_unitiswalking: Error in finding unit_data for GID %d!\n", gid);
+ script_pushint(st, -1);
+ return false;
}
+ script_pushint(st, unit->is_walking(bl));
+
return true;
}
/// Kills the unit
///
/// unitkill <unit_id>;
-BUILDIN(unitkill)
+static BUILDIN(unitkill)
{
struct block_list* bl = map->id2bl(script_getnum(st,2));
if( bl != NULL )
@@ -16719,33 +21270,36 @@ BUILDIN(unitkill)
/// Returns if it was successfull
///
/// unitwarp(<unit_id>,"<map name>",<x>,<y>) -> <bool>
-BUILDIN(unitwarp) {
- int unit_id;
+static BUILDIN(unitwarp)
+{
+ int unit_id = script_getnum(st, 2);
+ const char *mapname = script_getstr(st, 3);
+ short x = (short)script_getnum(st, 4);
+ short y = (short)script_getnum(st, 5);
int mapid;
- short x;
- short y;
- struct block_list* bl;
- const char *mapname;
-
- unit_id = script_getnum(st,2);
- mapname = script_getstr(st, 3);
- x = (short)script_getnum(st,4);
- y = (short)script_getnum(st,5);
+ struct block_list *bl;
if (!unit_id) //Warp the script's runner
bl = map->id2bl(st->rid);
else
bl = map->id2bl(unit_id);
- if( strcmp(mapname,"this") == 0 )
- mapid = bl?bl->m:-1;
+ if (strcmp(mapname, "this") == 0)
+ mapid = bl ? bl->m : -1;
else
mapid = map->mapname2mapid(mapname);
- if( mapid >= 0 && bl != NULL ) {
- unit->bl2ud2(bl); // ensure ((struct npc_data *)bl)->ud is safe to edit
- script_pushint(st, unit->warp(bl,mapid,x,y,CLR_OUTSIGHT));
- } else {
+ if (mapid >= 0 && bl != NULL) {
+ struct unit_data *ud = unit->bl2ud2(bl); // ensure ((struct npc_data *)bl)->ud is safe to edit
+ if (bl->type == BL_NPC) {
+ if (ud == NULL) {
+ ShowWarning("buildin_unitwarp: floating NPC don't have unit data.\n");
+ return false;
+ }
+ }
+ script_pushint(st, unit->warp(bl, mapid, x, y, CLR_OUTSIGHT));
+ }
+ else {
script_pushint(st, 0);
}
@@ -16759,7 +21313,8 @@ BUILDIN(unitwarp) {
///
/// unitattack(<unit_id>,"<target name>"{,<action type>}) -> <bool>
/// unitattack(<unit_id>,<target_id>{,<action type>}) -> <bool>
-BUILDIN(unitattack) {
+static BUILDIN(unitattack)
+{
struct block_list* unit_bl;
struct block_list* target_bl = NULL;
int actiontype = 0;
@@ -16813,18 +21368,21 @@ BUILDIN(unitattack) {
/// Makes the unit stop attacking and moving
///
/// unitstop <unit_id>;
-BUILDIN(unitstop) {
- int unit_id;
- struct block_list* bl;
-
- unit_id = script_getnum(st,2);
+static BUILDIN(unitstop)
+{
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
- bl = map->id2bl(unit_id);
- if( bl != NULL ) {
- unit->bl2ud2(bl); // ensure ((struct npc_data *)bl)->ud is safe to edit
+ if (bl != NULL) {
+ struct unit_data *ud = unit->bl2ud2(bl); // ensure ((struct npc_data *)bl)->ud is safe to edit
+ if (bl->type == BL_NPC) {
+ if (ud == NULL) {
+ ShowWarning("buildin_unitstop: floating NPC don't have unit data.\n");
+ return false;
+ }
+ }
unit->stop_attack(bl);
unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL);
- if( bl->type == BL_MOB )
+ if (bl->type == BL_MOB)
BL_UCAST(BL_MOB, bl)->target_id = 0;
}
@@ -16833,15 +21391,30 @@ BUILDIN(unitstop) {
/// Makes the unit say the message
///
-/// unittalk <unit_id>,"<message>";
-BUILDIN(unittalk) {
+/// unittalk(<unit_id>,"<message>"{, show_name{, <send_target>{, <target_id>}}});
+static BUILDIN(unittalk)
+{
int unit_id;
const char* message;
- struct block_list* bl;
+ struct block_list *bl, *target_bl = NULL;
+ bool show_name = true;
+ enum send_target target = AREA_CHAT_WOC;
unit_id = script_getnum(st,2);
message = script_getstr(st, 3);
+ if (script_hasdata(st, 4)) {
+ show_name = (script_getnum(st, 4) != 0) ? true : false;
+ }
+
+ if (script_hasdata(st, 5)) {
+ target = script_getnum(st, 5);
+ }
+
+ if (script_hasdata(st, 6)) {
+ target_bl = map->id2bl(script_getnum(st, 6));
+ }
+
bl = map->id2bl(unit_id);
if( bl != NULL ) {
struct StringBuf sbuf;
@@ -16850,8 +21423,17 @@ BUILDIN(unittalk) {
safestrncpy(blname, clif->get_bl_name(bl), sizeof(blname));
if(bl->type == BL_NPC)
strtok(blname, "#");
- StrBuf->Printf(&sbuf, "%s : %s", blname, message);
- clif->disp_overhead(bl, StrBuf->Value(&sbuf));
+ if (show_name) {
+ StrBuf->Printf(&sbuf, "%s : %s", blname, message);
+ } else {
+ StrBuf->Printf(&sbuf, "%s", message);
+ }
+
+ if (bl->type == BL_PC && target == SELF && (target_bl == NULL || bl == target_bl)) {
+ clif->notify_playerchat(bl, StrBuf->Value(&sbuf));
+ } else {
+ clif->disp_overhead(bl, StrBuf->Value(&sbuf), target, target_bl);
+ }
StrBuf->Destroy(&sbuf);
}
@@ -16863,7 +21445,8 @@ BUILDIN(unittalk) {
/// unitemote <unit_id>,<emotion>;
///
/// @see e_* in const.txt
-BUILDIN(unitemote) {
+static BUILDIN(unitemote)
+{
int unit_id;
int emotion;
struct block_list* bl;
@@ -16881,7 +21464,8 @@ BUILDIN(unitemote) {
///
/// unitskilluseid <unit_id>,<skill_id>,<skill_lv>{,<target_id>};
/// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>};
-BUILDIN(unitskilluseid) {
+static BUILDIN(unitskilluseid)
+{
int unit_id;
uint16 skill_id;
uint16 skill_lv;
@@ -16903,7 +21487,10 @@ BUILDIN(unitskilluseid) {
} else {
status_calc_npc(nd, SCO_NONE);
}
+ } else if (bl->type == BL_PC) {
+ pc->autocast_clear(BL_UCAST(BL_PC, bl));
}
+
unit->skilluse_id(bl, target_id, skill_id, skill_lv);
}
@@ -16914,7 +21501,8 @@ BUILDIN(unitskilluseid) {
///
/// unitskillusepos <unit_id>,<skill_id>,<skill_lv>,<target_x>,<target_y>;
/// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>;
-BUILDIN(unitskillusepos) {
+static BUILDIN(unitskillusepos)
+{
int unit_id;
uint16 skill_id;
uint16 skill_lv;
@@ -16938,7 +21526,10 @@ BUILDIN(unitskillusepos) {
} else {
status_calc_npc(nd, SCO_NONE);
}
+ } else if (bl->type == BL_PC) {
+ pc->autocast_clear(BL_UCAST(BL_PC, bl));
}
+
unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
}
@@ -16950,7 +21541,7 @@ BUILDIN(unitskillusepos) {
/// Pauses the execution of the script, detaching the player
///
/// sleep <mili seconds>;
-BUILDIN(sleep)
+static BUILDIN(sleep)
{
int ticks;
@@ -16979,7 +21570,8 @@ BUILDIN(sleep)
/// Returns if a player is still attached
///
/// sleep2(<mili secconds>) -> <bool>
-BUILDIN(sleep2) {
+static BUILDIN(sleep2)
+{
int ticks;
ticks = script_getnum(st,2);
@@ -17003,7 +21595,7 @@ BUILDIN(sleep2) {
/// Awakes all the sleep timers of the target npc
///
/// awake "<npc name>";
-BUILDIN(awake)
+static BUILDIN(awake)
{
struct DBIterator *iter;
struct script_state *tst;
@@ -17046,7 +21638,7 @@ BUILDIN(awake)
/// Returns 0 if an error occurs.
///
/// getvariableofnpc(<variable>, "<npc name>") -> <reference>
-BUILDIN(getvariableofnpc)
+static BUILDIN(getvariableofnpc)
{
struct script_data* data;
const char* name;
@@ -17088,13 +21680,62 @@ BUILDIN(getvariableofnpc)
return true;
}
+static BUILDIN(getvariableofpc)
+{
+ const char* name;
+ struct script_data* data = script_getdata(st, 2);
+ struct map_session_data *sd = map->id2sd(script_getnum(st, 3));
+
+ if (!data_isreference(data)) {
+ ShowError("script:getvariableofpc: not a variable\n");
+ script->reportdata(data);
+ script_pushnil(st);
+ st->state = END;
+ return false;
+ }
+
+ name = reference_getname(data);
+
+ switch (*name)
+ {
+ case '$':
+ case '.':
+ case '\'':
+ ShowError("script:getvariableofpc: illegal scope (not pc variable)\n");
+ script->reportdata(data);
+ script_pushnil(st);
+ st->state = END;
+ return false;
+ }
+
+ if (sd == NULL)
+ {
+ // player not found, return default value
+ if (script_hasdata(st, 4)) {
+ script_pushcopy(st, 4);
+ } else if (is_string_variable(name)) {
+ script_pushconststr(st, "");
+ } else {
+ script_pushint(st, 0);
+ }
+ return true;
+ }
+
+ if (!sd->regs.vars)
+ sd->regs.vars = i64db_alloc(DB_OPT_BASE);
+
+ script->push_val(st->stack, C_NAME, reference_getuid(data), &sd->regs);
+ return true;
+}
+
/// Opens a warp portal.
/// Has no "portal opening" effect/sound, it opens the portal immediately.
///
/// warpportal <source x>,<source y>,"<target map>",<target x>,<target y>;
///
/// @author blackhole89
-BUILDIN(warpportal) {
+static BUILDIN(warpportal)
+{
int spx;
int spy;
unsigned short map_index;
@@ -17131,7 +21772,7 @@ BUILDIN(warpportal) {
return true;
}
-BUILDIN(openmail)
+static BUILDIN(openmail)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -17142,7 +21783,7 @@ BUILDIN(openmail)
return true;
}
-BUILDIN(openauction)
+static BUILDIN(openauction)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -17158,7 +21799,8 @@ BUILDIN(openauction)
/// checkcell("<map name>",<x>,<y>,<type>) -> <bool>
///
/// @see cell_chk* constants in const.txt for the types
-BUILDIN(checkcell) {
+static BUILDIN(checkcell)
+{
int16 m = map->mapname2mapid(script_getstr(st,2));
int16 x = script_getnum(st,3);
int16 y = script_getnum(st,4);
@@ -17179,7 +21821,8 @@ BUILDIN(checkcell) {
/// setcell "<map name>",<x1>,<y1>,<x2>,<y2>,<type>,<flag>;
///
/// @see cell_* constants in const.txt for the types
-BUILDIN(setcell) {
+static BUILDIN(setcell)
+{
int16 m = map->mapname2mapid(script_getstr(st,2));
int16 x1 = script_getnum(st,3);
int16 y1 = script_getnum(st,4);
@@ -17208,7 +21851,7 @@ BUILDIN(setcell) {
/*==========================================
* Mercenary Commands
*------------------------------------------*/
-BUILDIN(mercenary_create)
+static BUILDIN(mercenary_create)
{
struct map_session_data *sd;
int class_, contract_time;
@@ -17226,7 +21869,8 @@ BUILDIN(mercenary_create)
return true;
}
-BUILDIN(mercenary_heal) {
+static BUILDIN(mercenary_heal)
+{
struct map_session_data *sd = script->rid2sd(st);
int hp, sp;
@@ -17235,11 +21879,12 @@ BUILDIN(mercenary_heal) {
hp = script_getnum(st,2);
sp = script_getnum(st,3);
- status->heal(&sd->md->bl, hp, sp, 0);
+ status->heal(&sd->md->bl, hp, sp, STATUS_HEAL_DEFAULT);
return true;
}
-BUILDIN(mercenary_sc_start) {
+static BUILDIN(mercenary_sc_start)
+{
struct map_session_data *sd = script->rid2sd(st);
enum sc_type type;
int tick, val1;
@@ -17255,7 +21900,8 @@ BUILDIN(mercenary_sc_start) {
return true;
}
-BUILDIN(mercenary_get_calls) {
+static BUILDIN(mercenary_get_calls)
+{
struct map_session_data *sd = script->rid2sd(st);
int guild_id;
@@ -17281,7 +21927,8 @@ BUILDIN(mercenary_get_calls) {
return true;
}
-BUILDIN(mercenary_set_calls) {
+static BUILDIN(mercenary_set_calls)
+{
struct map_session_data *sd = script->rid2sd(st);
int guild_id, value, *calls;
@@ -17311,7 +21958,8 @@ BUILDIN(mercenary_set_calls) {
return true;
}
-BUILDIN(mercenary_get_faith) {
+static BUILDIN(mercenary_get_faith)
+{
struct map_session_data *sd = script->rid2sd(st);
int guild_id;
@@ -17337,7 +21985,8 @@ BUILDIN(mercenary_get_faith) {
return true;
}
-BUILDIN(mercenary_set_faith) {
+static BUILDIN(mercenary_set_faith)
+{
struct map_session_data *sd = script->rid2sd(st);
int guild_id, value, *calls;
@@ -17372,7 +22021,7 @@ BUILDIN(mercenary_set_faith) {
/*------------------------------------------
* Book Reading
*------------------------------------------*/
-BUILDIN(readbook)
+static BUILDIN(readbook)
{
struct map_session_data *sd;
int book_id, page;
@@ -17391,89 +22040,214 @@ BUILDIN(readbook)
* Questlog script commands *
****************************/
-BUILDIN(questinfo)
+static BUILDIN(questinfo)
{
struct npc_data *nd = map->id2nd(st->oid);
- int quest_id, icon;
- struct questinfo qi;
+ struct questinfo qi = { 0 };
+ int icon = script_getnum(st, 2);
- if( nd == NULL || nd->bl.m == -1 )
+ if (nd == NULL)
return true;
- quest_id = script_getnum(st, 2);
- icon = script_getnum(st, 3);
-
- #if PACKETVER >= 20120410
- if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
- icon = 9999; // Default to nothing if icon id is invalid.
- #else
- if(icon < 0 || icon > 7)
- icon = 0;
- else
- icon = icon + 1;
- #endif
-
- qi.quest_id = quest_id;
- qi.icon = (unsigned char)icon;
- qi.nd = nd;
+ if (nd->bl.m == -1) {
+ ShowWarning("buildin_questinfo: questinfo cannot be set for an npc with no valid map.\n");
+ return false;
+ }
- if (script_hasdata(st, 4)) {
- int color = script_getnum(st, 4);
+ qi.icon = quest->questinfo_validate_icon(icon);
+ if (script_hasdata(st, 3)) {
+ int color = script_getnum(st, 3);
if (color < 0 || color > 3) {
- ShowWarning("buildin_questinfo: invalid color '%d', changing to 0\n",color);
+ ShowWarning("buildin_questinfo: invalid color '%d', defaulting to 0.\n", color);
script->reportfunc(st);
color = 0;
}
qi.color = (unsigned char)color;
}
- qi.hasJob = false;
+ VECTOR_ENSURE(nd->qi_data, 1, 1);
+ VECTOR_PUSH(nd->qi_data, qi);
+ map->add_questinfo(nd->bl.m, nd);
+ return true;
+}
- if (script_hasdata(st, 5)) {
- int job = script_getnum(st, 5);
+static BUILDIN(setquestinfo)
+{
+ struct npc_data *nd = map->id2nd(st->oid);
+ struct questinfo *qi = NULL;
+ uint32 type = script_getnum(st, 2);
- if (!pc->db_checkid(job)) {
- ShowError("buildin_questinfo: Nonexistant Job Class.\n");
- } else {
- qi.hasJob = true;
- qi.job = (unsigned short)job;
+ if (nd == NULL)
+ return true;
+
+ if (nd->bl.m == -1) {
+ ShowWarning("buildin_setquestinfo: questinfo cannot be set for an npc with no valid map.\n");
+ return false;
+ }
+
+ if (VECTOR_LENGTH(nd->qi_data) == 0) {
+ ShowWarning("buildin_setquestinfo: no valide questinfo data has been found for this npc.\n");
+ return false;
+ }
+
+ qi = &VECTOR_LAST(nd->qi_data);
+
+ switch (type) {
+ case QINFO_JOB:
+ {
+ int jobid = script_getnum(st, 3);
+ if (!pc->db_checkid(jobid)) {
+ ShowWarning("buildin_setquestinfo: invalid job id given (%d).\n", jobid);
+ return false;
+ }
+ qi->hasJob = true;
+ qi->job = jobid;
+ break;
+ }
+ case QINFO_SEX:
+ {
+ int sex = script_getnum(st, 3);
+ if (sex != SEX_MALE && sex != SEX_FEMALE) {
+ ShowWarning("buildin_setquestinfo: unsupported sex has been given (%d).\n", sex);
+ return false;
}
+ qi->sex_enabled = true;
+ qi->sex = sex;
+ break;
+ }
+ case QINFO_BASE_LEVEL:
+ {
+ int min = script_getnum(st, 3);
+ int max = script_getnum(st, 4);
+ if (min > max) {
+ ShowWarning("buildin_setquestinfo: minimal level (%d) is bigger than the maximal level (%d).\n", min, max);
+ return false;
+ }
+ qi->base_level.min = min;
+ qi->base_level.max = max;
+ break;
}
+ case QINFO_JOB_LEVEL:
+ {
+ int min = script_getnum(st, 3);
+ int max = script_getnum(st, 4);
+ if (min > max) {
+ ShowWarning("buildin_setquestinfo: minimal level (%d) is bigger than the maximal level (%d).\n", min, max);
+ return false;
+ }
+ qi->job_level.min = min;
+ qi->job_level.max = max;
+ break;
+ }
+ case QINFO_ITEM:
+ {
+ struct questinfo_itemreq item = { 0 };
- map->add_questinfo(nd->bl.m,&qi);
+ item.nameid = script_getnum(st, 3);
+ item.min = script_hasdata(st, 4) ? script_getnum(st, 4) : 0;
+ item.max = script_hasdata(st, 5) ? script_getnum(st, 5) : 0;
+ if (itemdb->exists(item.nameid) == NULL) {
+ ShowWarning("buildin_setquestinfo: non existing item (%d) have been given.\n", item.nameid);
+ return false;
+ }
+ if (item.min > item.max) {
+ ShowWarning("buildin_setquestinfo: minimal amount (%d) is bigger than the maximal amount (%d).\n", item.min, item.max);
+ return false;
+ }
+ if (item.min < 0 || item.min > MAX_AMOUNT) {
+ ShowWarning("buildin_setquestinfo: given amount (%d) must be bigger than or equal to 0 and smaller than %d.\n", item.min, MAX_AMOUNT + 1);
+ return false;
+ }
+ if (item.max < 0 || item.max > MAX_AMOUNT) {
+ ShowWarning("buildin_setquestinfo: given amount (%d) must be bigger than or equal to 0 and smaller than %d.\n", item.max, MAX_AMOUNT + 1);
+ return false;
+ }
+ if (VECTOR_LENGTH(qi->items) == 0)
+ VECTOR_INIT(qi->items);
+ VECTOR_ENSURE(qi->items, 1, 1);
+ VECTOR_PUSH(qi->items, item);
+ break;
+ }
+ case QINFO_HOMUN_LEVEL:
+ {
+ int min = script_getnum(st, 3);
+ if (min > battle_config.hom_max_level && min > battle_config.hom_S_max_level) {
+ ShowWarning("buildin_setquestinfo: minimum homunculus level given (%d) is bigger than the max possible level.\n", min);
+ return false;
+ }
+ qi->homunculus.level = min;
+ break;
+ }
+ case QINFO_HOMUN_TYPE:
+ {
+ int hom_type = script_getnum(st, 3);
+ if (hom_type < HT_REG || hom_type > HT_S) {
+ ShowWarning("buildin_setquestinfo: invalid homunculus type (%d).\n", hom_type);
+ return false;
+ }
+ qi->homunculus_type = hom_type;
+ break;
+ }
+ case QINFO_QUEST:
+ {
+ struct questinfo_qreq quest_req = { 0 };
+ struct quest_db *quest_data = NULL;
+
+ quest_req.id = script_getnum(st, 3);
+ quest_req.state = script_getnum(st, 4);
+
+ quest_data = quest->db(quest_req.id);
+ if (quest_data == &quest->dummy) {
+ ShowWarning("buildin_setquestinfo: invalid quest given (%d).\n", quest_req.id);
+ return false;
+ }
+ if (quest_req.state < Q_INACTIVE || quest_req.state > Q_COMPLETE) {
+ ShowWarning("buildin_setquestinfo: invalid quest state given (%d).\n", quest_req.state);
+ return false;
+ }
+
+ if (VECTOR_LENGTH(qi->quest_requirement) == 0)
+ VECTOR_INIT(qi->quest_requirement);
+ VECTOR_ENSURE(qi->quest_requirement, 1, 1);
+ VECTOR_PUSH(qi->quest_requirement, quest_req);
+ break;
+ }
+ case QINFO_MERCENARY_CLASS:
+ {
+ int mer_class = script_getnum(st, 3);
+
+ if (!mercenary->class(mer_class)) {
+ ShowWarning("buildin_setquestinfo: invalid mercenary class given (%d).\n", mer_class);
+ return false;
+ }
+ qi->mercenary_class = mer_class;
+ break;
+ }
+ default:
+ ShowWarning("buildin_setquestinfo: invalid type given (%u).\n", type);
+ return false;
+ }
return true;
}
-BUILDIN(setquest)
+static BUILDIN(setquest)
{
- unsigned short i;
int quest_id;
+ unsigned int time_limit;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
quest_id = script_getnum(st, 2);
+ time_limit = script_hasdata(st, 3) ? script_getnum(st, 3) : 0;
- quest->add(sd, quest_id);
-
- // If questinfo is set, remove quest bubble once quest is set.
- for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
- struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
- if( qi->quest_id == quest_id ) {
-#if PACKETVER >= 20120410
- clif->quest_show_event(sd, &qi->nd->bl, 9999, 0);
-#else
- clif->quest_show_event(sd, &qi->nd->bl, 0, 0);
-#endif
- }
- }
-
+ quest->add(sd, quest_id, time_limit);
return true;
}
-BUILDIN(erasequest)
+static BUILDIN(erasequest)
{
struct map_session_data *sd = script->rid2sd(st);
@@ -17496,7 +22270,7 @@ BUILDIN(erasequest)
return true;
}
-BUILDIN(completequest)
+static BUILDIN(completequest)
{
struct map_session_data *sd = script->rid2sd(st);
@@ -17519,7 +22293,7 @@ BUILDIN(completequest)
return true;
}
-BUILDIN(changequest)
+static BUILDIN(changequest)
{
struct map_session_data *sd = script->rid2sd(st);
@@ -17530,7 +22304,7 @@ BUILDIN(changequest)
return true;
}
-BUILDIN(questactive)
+static BUILDIN(questactive)
{
struct map_session_data *sd = script->rid2sd(st);
int qid, i;
@@ -17556,7 +22330,7 @@ BUILDIN(questactive)
return true;
}
-BUILDIN(questprogress)
+static BUILDIN(questprogress)
{
struct map_session_data *sd = script->rid2sd(st);
enum quest_check_type type = HAVEQUEST;
@@ -17584,7 +22358,7 @@ BUILDIN(questprogress)
return true;
}
-BUILDIN(showevent)
+static BUILDIN(showevent)
{
struct map_session_data *sd = script->rid2sd(st);
struct npc_data *nd = map->id2nd(st->oid);
@@ -17603,24 +22377,106 @@ BUILDIN(showevent)
}
}
- #if PACKETVER >= 20120410
- if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
- icon = 9999; // Default to nothing if icon id is invalid.
- #else
- if(icon < 0 || icon > 7)
- icon = 0;
- else
- icon = icon + 1;
- #endif
+ icon = quest->questinfo_validate_icon(icon);
clif->quest_show_event(sd, &nd->bl, icon, color);
return true;
}
/*==========================================
+ * Achievement System [Smokexyz/Hercules]
+ *-----------------------------------------*/
+/**
+ * Validates an objective index for the given achievement.
+ * Can be used for any achievement type.
+ * @command achievement_progress(<ach_id>,<obj_idx>,<progress>,<incremental?>{,<char_id>});
+ * @param aid - achievement ID
+ * @param obj_idx - achievement objective index.
+ * @param progress - objective progress towards goal.
+ * @Param incremental - (boolean) true to add the progress towards the goal,
+ * false to use the progress only as a comparand.
+ * @param account_id - (optional) character ID to perform on.
+ * @return true on success, false on failure.
+ * @push 1 on success, 0 on failure.
+ */
+static BUILDIN(achievement_progress)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ int aid = script_getnum(st, 2);
+ int obj_idx = script_getnum(st, 3);
+ int progress = script_getnum(st, 4);
+ int incremental = script_getnum(st, 5);
+ int account_id = script_hasdata(st, 6) ? script_getnum(st, 6) : 0;
+ const struct achievement_data *ad = NULL;
+
+ if ((ad = achievement->get(aid)) == NULL) {
+ ShowError("buildin_achievement_progress: Invalid achievement ID %d received.\n", aid);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (obj_idx <= 0 || obj_idx > VECTOR_LENGTH(ad->objective)) {
+ ShowError("buildin_achievement_progress: Invalid objective index %d received. (min: %d, max: %d)\n", obj_idx, 0, VECTOR_LENGTH(ad->objective));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ obj_idx--; // convert to array index.
+
+ if (progress <= 0 || progress > VECTOR_INDEX(ad->objective, obj_idx).goal) {
+ ShowError("buildin_achievement_progress: Progress exceeds goal limit for achievement id %d.\n", aid);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (incremental < 0 || incremental > 1) {
+ ShowError("buildin_achievement_progress: Argument 4 expects boolean (0/1). provided value: %d\n", incremental);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (script_hasdata(st, 6)) {
+ if (account_id <= 0) {
+ ShowError("buildin_achievement_progress: Invalid Account id %d provided.\n", account_id);
+ script_pushint(st, 0);
+ return false;
+ } else if ((sd = map->id2sd(account_id)) == NULL) {
+ ShowError("buildin_achievement_progress: Account with id %d was not found.\n", account_id);
+ script_pushint(st, 0);
+ return false;
+ }
+ }
+
+ if (achievement->validate(sd, aid, obj_idx, progress, incremental ? true : false))
+ script_pushint(st, progress);
+ else
+ script_pushint(st, 0);
+
+ return true;
+}
+
+static BUILDIN(achievement_iscompleted)
+{
+ struct map_session_data *sd = script_hasdata(st, 3) ? map->id2sd(script_getnum(st, 3)) : script->rid2sd(st);
+ if (sd == NULL)
+ return false;
+
+ int aid = script_getnum(st, 2);
+ const struct achievement_data *ad = achievement->get(aid);
+ if (ad == NULL) {
+ ShowError("buildin_achievement_iscompleted: Invalid Achievement %d provided.\n", aid);
+ return false;
+ }
+
+ script_pushint(st, achievement->check_complete(sd, ad));
+ return true;
+}
+
+/*==========================================
* BattleGround System
*------------------------------------------*/
-BUILDIN(waitingroom2bg) {
+static BUILDIN(waitingroom2bg)
+{
struct npc_data *nd;
struct chat_data *cd;
const char *map_name, *ev = "", *dev = "";
@@ -17664,17 +22520,18 @@ BUILDIN(waitingroom2bg) {
for (i = 0; i < n && i < MAX_BG_MEMBERS; i++) {
struct map_session_data *sd = cd->usersd[i];
if (sd != NULL && bg->team_join(bg_id, sd))
- mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), sd->bl.id);
+ mapreg->setreg(reference_uid(script->add_variable("$@arenamembers"), i), sd->bl.id);
else
- mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), 0);
+ mapreg->setreg(reference_uid(script->add_variable("$@arenamembers"), i), 0);
}
- mapreg->setreg(script->add_str("$@arenamembersnum"), i);
+ mapreg->setreg(script->add_variable("$@arenamembersnum"), i);
script_pushint(st,bg_id);
return true;
}
-BUILDIN(waitingroom2bg_single) {
+static BUILDIN(waitingroom2bg_single)
+{
const char* map_name;
struct npc_data *nd;
struct chat_data *cd;
@@ -17707,7 +22564,7 @@ BUILDIN(waitingroom2bg_single) {
return true;
}
-BUILDIN(bg_team_setxy)
+static BUILDIN(bg_team_setxy)
{
struct battleground_data *bgd;
int bg_id;
@@ -17721,7 +22578,7 @@ BUILDIN(bg_team_setxy)
return true;
}
-BUILDIN(bg_warp)
+static BUILDIN(bg_warp)
{
int x, y, map_index, bg_id;
const char* map_name;
@@ -17736,24 +22593,35 @@ BUILDIN(bg_warp)
return true;
}
-BUILDIN(bg_monster)
+/**
+ * Spawns a mob with allegiance to the given battle group.
+ *
+ * @code{.herc}
+ * bg_monster(<battle group>, "<map name>", <x>, <y>, "<name to show>", <mob id>{, "<event label>"});
+ * @endcode
+ *
+ **/
+static BUILDIN(bg_monster)
{
- int class_ = 0, x = 0, y = 0, bg_id = 0;
- const char *str, *mapname, *evt="";
+ const char *event = "";
+
+ if (script_hasdata(st, 8)) {
+ event = script_getstr(st, 8);
+ script->check_event(st, event);
+ }
- bg_id = script_getnum(st,2);
- mapname = script_getstr(st,3);
- x = script_getnum(st,4);
- y = script_getnum(st,5);
- str = script_getstr(st,6);
- class_ = script_getnum(st,7);
- if( script_hasdata(st,8) ) evt = script_getstr(st,8);
- script->check_event(st, evt);
- script_pushint(st, mob->spawn_bg(mapname,x,y,str,class_,evt,bg_id));
+ const char *mapname = script_getstr(st, 3);
+ const char *name = script_getstr(st, 6);
+ const int bg_id = script_getnum(st, 2);
+ const int x = script_getnum(st, 4);
+ const int y = script_getnum(st, 5);
+ const int mob_id = script_getnum(st, 7);
+
+ script_pushint(st, mob->spawn_bg(mapname, x, y, name, mob_id, event, bg_id, st->oid));
return true;
}
-BUILDIN(bg_monster_set_team)
+static BUILDIN(bg_monster_set_team)
{
int id = script_getnum(st,2),
bg_id = script_getnum(st,3);
@@ -17767,12 +22635,12 @@ BUILDIN(bg_monster_set_team)
mob_stop_attack(md);
mob_stop_walking(md, STOPWALKING_FLAG_NONE);
md->target_id = md->attacked_id = 0;
- clif->charnameack(0, &md->bl);
+ clif->blname_ack(0, &md->bl);
return true;
}
-BUILDIN(bg_leave)
+static BUILDIN(bg_leave)
{
struct map_session_data *sd = script->rid2sd(st);
if( sd == NULL || !sd->bg_id )
@@ -17782,14 +22650,14 @@ BUILDIN(bg_leave)
return true;
}
-BUILDIN(bg_destroy)
+static BUILDIN(bg_destroy)
{
int bg_id = script_getnum(st,2);
bg->team_delete(bg_id);
return true;
}
-BUILDIN(bg_getareausers)
+static BUILDIN(bg_getareausers)
{
const char *str;
int16 m, x0, y0, x1, y1;
@@ -17823,7 +22691,8 @@ BUILDIN(bg_getareausers)
return true;
}
-BUILDIN(bg_updatescore) {
+static BUILDIN(bg_updatescore)
+{
const char *str;
int16 m;
@@ -17838,7 +22707,7 @@ BUILDIN(bg_updatescore) {
return true;
}
-BUILDIN(bg_get_data)
+static BUILDIN(bg_get_data)
{
struct battleground_data *bgd;
int bg_id = script_getnum(st,2),
@@ -17865,10 +22734,12 @@ BUILDIN(bg_get_data)
* Instancing Script Commands
*------------------------------------------*/
-BUILDIN(instance_create) {
+static BUILDIN(instance_create)
+{
const char *name;
int owner_id, res;
int type = IOT_PARTY;
+ struct map_session_data *sd = map->id2sd(st->rid);
name = script_getstr(st, 2);
owner_id = script_getnum(st, 3);
@@ -17881,27 +22752,49 @@ BUILDIN(instance_create) {
}
res = instance->create(owner_id, name, (enum instance_owner_type) type);
- if( res == -4 ) { // Already exists
- script_pushint(st, -1);
- return true;
- } else if( res < 0 ) {
+ if (sd != NULL) {
+ switch (res) {
+ case -4: // Already exists
+ clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE, name);
+ break;
+ case -3: // No free instances
+ clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST, name);
+ break;
+ case -2: // Invalid type
+ clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT, name);
+ break;
+ case -1: // Unknown
+ clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN, name);
+ break;
+ default:
+ if (res < 0)
+ ShowError("buildin_instance_create: failed to unknown reason [%d].\n", res);
+ }
+ } else {
const char *err;
- switch(res) {
- case -3: err = "No free instances"; break;
- case -2: err = "Invalid party ID"; break;
- case -1: err = "Invalid type"; break;
- default: err = "Unknown"; break;
+ switch (res) {
+ case -3:
+ err = "No free instances";
+ break;
+ case -2:
+ err = "Invalid party ID";
+ break;
+ case -1:
+ err = "Invalid type";
+ break;
+ default:
+ err = "Unknown";
+ break;
}
- ShowError("buildin_instance_create: %s [%d].\n", err, res);
- script_pushint(st, -2);
- return true;
+ if (res < 0)
+ ShowError("buildin_instance_create: %s [%d].\n", err, res);
}
-
script_pushint(st, res);
return true;
}
-BUILDIN(instance_destroy) {
+static BUILDIN(instance_destroy)
+{
int instance_id = -1;
if( script_hasdata(st, 2) )
@@ -17919,7 +22812,7 @@ BUILDIN(instance_destroy) {
return true;
}
-BUILDIN(instance_attachmap)
+static BUILDIN(instance_attachmap)
{
const char *map_name = NULL;
int16 m;
@@ -17943,7 +22836,8 @@ BUILDIN(instance_attachmap)
return true;
}
-BUILDIN(instance_detachmap) {
+static BUILDIN(instance_detachmap)
+{
const char *str;
int16 m;
int instance_id = -1;
@@ -17964,7 +22858,7 @@ BUILDIN(instance_detachmap) {
return true;
}
-BUILDIN(instance_attach)
+static BUILDIN(instance_attach)
{
int instance_id = script_getnum(st, 2);
@@ -17975,12 +22869,13 @@ BUILDIN(instance_attach)
return true;
}
-BUILDIN(instance_id) {
+static BUILDIN(instance_id)
+{
script_pushint(st, st->instance_id);
return true;
}
-BUILDIN(instance_set_timeout)
+static BUILDIN(instance_set_timeout)
{
int progress_timeout, idle_timeout;
int instance_id = -1;
@@ -18000,7 +22895,8 @@ BUILDIN(instance_set_timeout)
return true;
}
-BUILDIN(instance_init) {
+static BUILDIN(instance_init)
+{
int instance_id = script_getnum(st, 2);
if( !instance->valid(instance_id) ) {
@@ -18017,7 +22913,8 @@ BUILDIN(instance_init) {
return true;
}
-BUILDIN(instance_announce) {
+static BUILDIN(instance_announce)
+{
int instance_id = script_getnum(st,2);
const char *mes = script_getstr(st,3);
int flag = script_getnum(st,4);
@@ -18026,8 +22923,9 @@ BUILDIN(instance_announce) {
int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
-
int i;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if( instance_id == -1 ) {
if( st->instance_id >= 0 )
@@ -18041,12 +22939,13 @@ BUILDIN(instance_announce) {
for( i = 0; i < instance->list[instance_id].num_map; i++ )
map->foreachinmap(script->buildin_announce_sub, instance->list[instance_id].map[i], BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
-BUILDIN(instance_npcname) {
+static BUILDIN(instance_npcname)
+{
const char *str;
int instance_id = -1;
struct npc_data *nd;
@@ -18070,81 +22969,100 @@ BUILDIN(instance_npcname) {
return true;
}
-BUILDIN(has_instance) {
+static BUILDIN(has_instance)
+{
struct map_session_data *sd;
const char *str;
int16 m;
int instance_id = -1;
+ int i = 0, j = 0;
bool type = strcmp(script->getfuncname(st),"has_instance2") == 0 ? true : false;
str = script_getstr(st, 2);
- if( (m = map->mapname2mapid(str)) < 0 ) {
- if( type )
+ if ((m = map->mapname2mapid(str)) < 0) {
+ if (type) {
script_pushint(st, -1);
- else
+ } else {
script_pushconststr(st, "");
+ }
return true;
}
- if( script_hasdata(st, 3) )
+ if (script_hasdata(st, 3))
instance_id = script_getnum(st, 3);
- else if( st->instance_id >= 0 )
+ else if (st->instance_id >= 0)
instance_id = st->instance_id;
- else if( (sd = script->rid2sd(st)) != NULL ) {
+ else if ((sd = script->rid2sd(st)) != NULL) {
struct party_data *p;
- int i = 0, j = 0;
- if( sd->instances ) {
- for( i = 0; i < sd->instances; i++ ) {
- if( sd->instance[i] >= 0 ) {
+ if (sd->instances) {
+ for (i = 0; i < sd->instances; i++) {
+ if (sd->instance[i] >= 0) {
ARR_FIND(0, instance->list[sd->instance[i]].num_map, j, map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[sd->instance[i]].num_map )
+ if (j != instance->list[sd->instance[i]].num_map)
break;
}
}
- if( i != sd->instances )
+ if (i != sd->instances) {
instance_id = sd->instance[i];
+ }
}
if (instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances) {
- for( i = 0; i < p->instances; i++ ) {
- if( p->instance[i] >= 0 ) {
+ for (i = 0; i < p->instances; i++) {
+ if (p->instance[i] >= 0) {
ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[p->instance[i]].num_map )
+ if (j != instance->list[p->instance[i]].num_map)
break;
}
}
- if( i != p->instances )
+ if (i != p->instances) {
instance_id = p->instance[i];
+ }
}
- if( instance_id == -1 && sd->guild && sd->guild->instances ) {
- for( i = 0; i < sd->guild->instances; i++ ) {
- if( sd->guild->instance[i] >= 0 ) {
+ if (instance_id == -1 && sd->guild && sd->guild->instances) {
+ for (i = 0; i < sd->guild->instances; i++) {
+ if (sd->guild->instance[i] >= 0) {
ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j, map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[sd->guild->instance[i]].num_map )
+ if (j != instance->list[sd->guild->instance[i]].num_map)
break;
}
}
- if( i != sd->guild->instances )
+ if (i != sd->guild->instances)
instance_id = sd->guild->instance[i];
}
}
- if( !instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0 ) {
- if( type )
+ if (instance_id == -1) {
+ for (i = 0; i < instance->instances; i++) {
+ if (instance->list[i].state != INSTANCE_FREE && instance->list[i].owner_type == IOT_NONE && instance->list[i].num_map > 0) {
+ ARR_FIND(0, instance->list[i].num_map, j, map->list[instance->list[i].map[j]].instance_src_map == m);
+ if (j != instance->list[i].num_map)
+ break;
+ }
+ }
+ if (i != instance->instances) {
+ instance_id = instance->list[i].id;
+ }
+ }
+
+ if (!instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0) {
+ if (type) {
script_pushint(st, -1);
- else
+ } else {
script_pushconststr(st, "");
+ }
return true;
}
- if( type )
+ if (type) {
script_pushint(st, instance_id);
- else
+ } else {
script_pushconststr(st, map->list[m].name);
+ }
return true;
}
-int buildin_instance_warpall_sub(struct block_list *bl, va_list ap)
+static int buildin_instance_warpall_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = NULL;
int map_index = va_arg(ap,int);
@@ -18159,7 +23077,9 @@ int buildin_instance_warpall_sub(struct block_list *bl, va_list ap)
return 0;
}
-BUILDIN(instance_warpall) {
+
+static BUILDIN(instance_warpall)
+{
int16 m;
int instance_id = -1;
const char *mapn;
@@ -18197,7 +23117,7 @@ BUILDIN(instance_warpall) {
* Example: instance_check_party (getcharid(1){,amount}{,min}{,max});
* Example 2: instance_check_party (getcharid(1),1,1,99);
*------------------------------------------*/
-BUILDIN(instance_check_party)
+static BUILDIN(instance_check_party)
{
int amount, min, max, i, party_id, c = 0;
struct party_data *p = NULL;
@@ -18256,7 +23176,7 @@ BUILDIN(instance_check_party)
* Example: instance_check_guild (getcharid(2){,amount}{,min}{,max});
* Example 2: instance_check_guild (getcharid(2),1,1,99);
*------------------------------------------*/
-BUILDIN(instance_check_guild)
+static BUILDIN(instance_check_guild)
{
int amount, min, max, i, guild_id, c = 0;
struct guild *g = NULL;
@@ -18308,7 +23228,7 @@ BUILDIN(instance_check_guild)
/*==========================================
* Custom Fonts
*------------------------------------------*/
-BUILDIN(setfont)
+static BUILDIN(setfont)
{
struct map_session_data *sd = script->rid2sd(st);
int font = script_getnum(st,2);
@@ -18324,7 +23244,20 @@ BUILDIN(setfont)
return true;
}
-int buildin_mobuseskill_sub(struct block_list *bl, va_list ap)
+static BUILDIN(getfont)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ script_pushint(st, sd->status.font);
+ return true;
+}
+
+static int buildin_mobuseskill_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md = NULL;
struct block_list *tbl;
@@ -18367,10 +23300,12 @@ int buildin_mobuseskill_sub(struct block_list *bl, va_list ap)
return 0;
}
+
/*==========================================
* areamobuseskill "Map Name",<x>,<y>,<range>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>;
*------------------------------------------*/
-BUILDIN(areamobuseskill) {
+static BUILDIN(areamobuseskill)
+{
struct block_list center;
int16 m;
int range,mobid,skill_id,skill_lv,casttime,emotion,target,cancel;
@@ -18399,7 +23334,7 @@ BUILDIN(areamobuseskill) {
return true;
}
-BUILDIN(progressbar)
+static BUILDIN(progressbar)
{
struct map_session_data * sd = script->rid2sd(st);
const char * color;
@@ -18420,10 +23355,31 @@ BUILDIN(progressbar)
clif->progressbar(sd, (unsigned int)strtoul(color, (char **)NULL, 0), second);
return true;
}
+static BUILDIN(progressbar_unit)
+{
+ const char *color = script_getstr(st, 2);
+ uint32 second = script_getnum(st, 3);
+
+ if (script_hasdata(st, 4)) {
+ struct block_list *bl = map->id2bl(script_getnum(st, 4));
-BUILDIN(pushpc)
+ if (bl == NULL) {
+ ShowWarning("buildin_progressbar_unit: Error in finding object with given GID %d!\n", script_getnum(st, 4));
+ return true;
+ }
+ clif->progressbar_unit(bl, (unsigned int)strtoul(color, (char **)NULL, 0), second);
+ } else {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return false;
+
+ clif->progressbar_unit(&sd->bl, (unsigned int)strtoul(color, (char **)NULL, 0), second);
+ }
+ return true;
+}
+static BUILDIN(pushpc)
{
- uint8 dir;
int cells, dx, dy;
struct map_session_data* sd;
@@ -18432,15 +23388,14 @@ BUILDIN(pushpc)
return true;
}
- dir = script_getnum(st,2);
- cells = script_getnum(st,3);
+ enum unit_dir dir = script_getnum(st, 2);
+ cells = script_getnum(st,3);
- if(dir>7)
- {
+ if (dir >= UNIT_DIR_MAX) {
ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", dir);
script->reportsrc(st);
- dir%= 8; // trim spin-over
+ dir %= UNIT_DIR_MAX; // trim spin-over
}
if(!cells)
@@ -18449,10 +23404,11 @@ BUILDIN(pushpc)
}
else if(cells<0)
{// pushing backwards
- dir = (dir+4)%8; // turn around
- cells = -cells;
+ dir = unit_get_opposite_dir(dir);
+ cells = -cells;
}
+ Assert_retr(false, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
dx = dirx[dir];
dy = diry[dir];
@@ -18462,7 +23418,7 @@ BUILDIN(pushpc)
/// Invokes buying store preparation window
/// buyingstore <slots>;
-BUILDIN(buyingstore)
+static BUILDIN(buyingstore)
{
struct map_session_data* sd;
@@ -18476,7 +23432,7 @@ BUILDIN(buyingstore)
/// Invokes search store info window
/// searchstores <uses>,<effect>;
-BUILDIN(searchstores)
+static BUILDIN(searchstores)
{
unsigned short effect;
unsigned int uses;
@@ -18507,7 +23463,7 @@ BUILDIN(searchstores)
}
/// Displays a number as large digital clock.
/// showdigit <value>[,<type>];
-BUILDIN(showdigit)
+static BUILDIN(showdigit)
{
unsigned int type = 0;
int value;
@@ -18537,7 +23493,7 @@ BUILDIN(showdigit)
/**
* Rune Knight
**/
-BUILDIN(makerune)
+static BUILDIN(makerune)
{
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -18550,15 +23506,19 @@ BUILDIN(makerune)
/**
* hascashmount() returns 1 if mounting a cash mount or 0 otherwise
**/
-BUILDIN(hascashmount)
+static BUILDIN(hascashmount)
{
struct map_session_data *sd = script->rid2sd(st);
+
if (sd == NULL)
return true;
- if( sd->sc.data[SC_ALL_RIDING] )
- script_pushint(st,1);
- else
- script_pushint(st,0);
+
+ if (sd->sc.data[SC_ALL_RIDING]) {
+ script_pushint(st, 1);
+ } else {
+ script_pushint(st, 0);
+ }
+
return true;
}
@@ -18569,21 +23529,27 @@ BUILDIN(hascashmount)
* - Will fail if the player is already riding a standard mount e.g. dragon, peco, wug, mado, etc.
* - Will unmount the player is he is already mounting a cash mount
**/
-BUILDIN(setcashmount)
+static BUILDIN(setcashmount)
{
struct map_session_data *sd = script->rid2sd(st);
+
if (sd == NULL)
return true;
+
if (pc_hasmount(sd)) {
- clif->msgtable(sd, MSG_REINS_CANT_USE_MOUNTED);
- script_pushint(st,0);//can't mount with one of these
+#if PACKETVER >= 20110531
+ clif->msgtable(sd, MSG_FAIELD_RIDING_OVERLAPPED);
+#endif
+ script_pushint(st, 0); // Can't mount with one of these
} else {
- if (sd->sc.data[SC_ALL_RIDING])
+ if (sd->sc.data[SC_ALL_RIDING]) {
status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
- else
- sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, 25, INFINITE_DURATION);
- script_pushint(st,1);//in both cases, return 1.
+ } else {
+ sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, battle_config.boarding_halter_speed, INFINITE_DURATION);
+ }
+ script_pushint(st, 1); // In both cases, return 1.
}
+
return true;
}
@@ -18591,7 +23557,8 @@ BUILDIN(setcashmount)
* Retrieves quantity of arguments provided to callfunc/callsub.
* getargcount() -> amount of arguments received in a function
**/
-BUILDIN(getargcount) {
+static BUILDIN(getargcount)
+{
struct script_retinfo* ri;
if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) {
@@ -18605,16 +23572,18 @@ BUILDIN(getargcount) {
return true;
}
+
/**
* getcharip(<account ID>/<character ID>/<character name>)
**/
-BUILDIN(getcharip) {
+static BUILDIN(getcharip)
+{
struct map_session_data* sd = NULL;
/* check if a character name is specified */
if (script_hasdata(st, 2)) {
if (script_isstringtype(st, 2)) {
- sd = map->nick2sd(script_getstr(st, 2));
+ sd = map->nick2sd(script_getstr(st, 2), false);
} else {
int id = script_getnum(st, 2);
sd = (map->id2sd(id) ? map->id2sd(id) : map->charid2sd(id));
@@ -18631,45 +23600,71 @@ BUILDIN(getcharip) {
return false;
}
- /* check for IP */
- if (!sockt->session[sd->fd]->client_addr) {
+ if (sd->fd <= 0 || sockt->session[sd->fd] == NULL || sockt->session[sd->fd]->client_addr == 0) {
script_pushconststr(st, "");
- return true;
- }
-
- /* return the client ip_addr converted for output */
- if (sd && sd->fd && sockt->session[sd->fd])
- {
- /* initiliaze */
- const char *ip_addr = NULL;
- uint32 ip;
-
- /* set ip, ip_addr and convert to ip and push str */
- ip = sockt->session[sd->fd]->client_addr;
- ip_addr = sockt->ip2str(ip, NULL);
+ } else {
+ uint32 ip = sockt->session[sd->fd]->client_addr;
+ const char *ip_addr = sockt->ip2str(ip, NULL);
script_pushstrcopy(st, ip_addr);
}
return true;
}
+
+enum function_type {
+ FUNCTION_IS_NONE = 0,
+ FUNCTION_IS_COMMAND,
+ FUNCTION_IS_GLOBAL,
+ FUNCTION_IS_LOCAL,
+ FUNCTION_IS_LABEL,
+};
+
/**
- * is_function(<function name>) -> 1 if function exists, 0 otherwise
+ * is_function(<function name>)
**/
-BUILDIN(is_function) {
- const char* str = script_getstr(st,2);
+static BUILDIN(is_function)
+{
+ const char *str = script_getstr(st, 2);
+ enum function_type type = FUNCTION_IS_NONE;
- if( strdb_exists(script->userfunc_db, str) )
- script_pushint(st,1);
- else
- script_pushint(st,0);
+ // TODO: add support for exported functions (#2142)
+
+ if (strdb_exists(script->userfunc_db, str)) {
+ type = FUNCTION_IS_GLOBAL;
+ } else {
+ int n = script->search_str(str);
+ if (n >= 0) {
+ switch (script->str_data[n].type) {
+ case C_FUNC:
+ type = FUNCTION_IS_COMMAND;
+ break;
+ case C_USERFUNC:
+ case C_USERFUNC_POS:
+ type = FUNCTION_IS_LOCAL;
+ break;
+ case C_POS:
+ type = FUNCTION_IS_LABEL;
+ break;
+ case C_NAME:
+ if (script->str_data[n].label >= 0) {
+ // WTF... ?
+ // for some reason local functions can have type C_NAME
+ type = FUNCTION_IS_LOCAL;
+ }
+ }
+ }
+ }
+
+ script_pushint(st, type);
return true;
}
+
/**
* freeloop(<toggle>) -> toggles this script instance's looping-check ability
**/
-BUILDIN(freeloop) {
-
+static BUILDIN(freeloop)
+{
if( script_getnum(st,2) )
st->freeloop = 1;
else
@@ -18680,7 +23675,8 @@ BUILDIN(freeloop) {
return true;
}
-BUILDIN(sit) {
+static BUILDIN(sit)
+{
struct map_session_data *sd = NULL;
if (script_hasdata(st, 2))
@@ -18700,7 +23696,8 @@ BUILDIN(sit) {
return true;
}
-BUILDIN(stand) {
+static BUILDIN(stand)
+{
struct map_session_data *sd = NULL;
if (script_hasdata(st, 2))
@@ -18720,7 +23717,8 @@ BUILDIN(stand) {
return true;
}
-BUILDIN(issit) {
+static BUILDIN(issit)
+{
struct map_session_data *sd = NULL;
if (script_hasdata(st, 2))
@@ -18738,10 +23736,48 @@ BUILDIN(issit) {
return true;
}
+static BUILDIN(add_group_command)
+{
+ AtCommandInfo *acmd_d;
+ struct atcmd_binding_data *bcmd_d;
+ GroupSettings *group;
+ int group_index;
+ const char *atcmd = script_getstr(st, 2);
+ int group_id = script_getnum(st, 3);
+ bool self_perm = (script_getnum(st, 4) == 1);
+ bool char_perm = (script_getnum(st, 5) == 1);
+
+ if (!pcg->exists(group_id)) {
+ ShowWarning("script:add_group_command: group does not exist: %i\n", group_id);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ group = pcg->id2group(group_id);
+ group_index = pcg->get_idx(group);
+
+ if ((bcmd_d = atcommand->get_bind_byname(atcmd)) != NULL) {
+ bcmd_d->at_groups[group_index] = self_perm;
+ bcmd_d->char_groups[group_index] = char_perm;
+ script_pushint(st, 1);
+ return true;
+ } else if ((acmd_d = atcommand->get_info_byname(atcmd)) != NULL) {
+ acmd_d->at_groups[group_index] = self_perm;
+ acmd_d->char_groups[group_index] = char_perm;
+ script_pushint(st, 1);
+ return true;
+ }
+
+ ShowWarning("script:add_group_command: command does not exist: %s\n", atcmd);
+ script_pushint(st, 0);
+ return false;
+}
+
/**
* @commands (script based)
**/
-BUILDIN(bindatcmd) {
+static BUILDIN(bindatcmd)
+{
const char* atcmd;
const char* eventName;
int i, group_lv = 0, group_lv_char = 99;
@@ -18786,12 +23822,15 @@ BUILDIN(bindatcmd) {
atcommand->binding[i]->group_lv = group_lv;
atcommand->binding[i]->group_lv_char = group_lv_char;
atcommand->binding[i]->log = log;
+ CREATE(atcommand->binding[i]->at_groups, char, db_size(pcg->db));
+ CREATE(atcommand->binding[i]->char_groups, char, db_size(pcg->db));
}
return true;
}
-BUILDIN(unbindatcmd) {
+static BUILDIN(unbindatcmd)
+{
const char* atcmd;
int i = 0;
@@ -18808,6 +23847,8 @@ BUILDIN(unbindatcmd) {
ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, atcmd) == 0);
if( i < atcommand->binding_count ) {
int cursor = 0;
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
atcommand->binding[i] = NULL;
/* compact the list now that we freed a slot somewhere */
@@ -18832,7 +23873,8 @@ BUILDIN(unbindatcmd) {
return true;
}
-BUILDIN(useatcmd) {
+static BUILDIN(useatcmd)
+{
struct map_session_data *sd, *dummy_sd = NULL;
int fd;
const char* cmd;
@@ -18869,70 +23911,70 @@ BUILDIN(useatcmd) {
return true;
}
-BUILDIN(checkre)
+static BUILDIN(has_permission)
{
- int num;
+ struct map_session_data *sd;
+ enum e_pc_permission perm;
- num=script_getnum(st,2);
- switch(num) {
- case 0:
-#ifdef RENEWAL
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 1:
-#ifdef RENEWAL_CAST
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 2:
-#ifdef RENEWAL_DROP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 3:
-#ifdef RENEWAL_EXP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 4:
-#ifdef RENEWAL_LVDMG
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 5:
-#ifdef RENEWAL_EDP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 6:
-#ifdef RENEWAL_ASPD
- script_pushint(st, 1);
-#else
+ if (script_hasdata(st, 3)) {
+ sd = map->id2sd(script_getnum(st, 3));
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (script_isstringtype(st, 2)) {
+ // to check for plugin permissions
+ int i = 0, j = -1;
+ const char *name = script_getstr(st, 2);
+ for (; i < pcg->permission_count; ++i) {
+ if (strcmp(pcg->permissions[i].name, name) == 0) {
+ j = i;
+ break;
+ }
+ }
+ if (j < 0) {
+ ShowError("script:has_permission: unknown permission: %s\n", name);
script_pushint(st, 0);
-#endif
- break;
- default:
- ShowWarning("buildin_checkre: unknown parameter.\n");
- break;
+ return false;
+ }
+ script_pushint(st, pc_has_permission(sd, pcg->permissions[j].permission));
+ return true;
}
+
+ // to ckeck for built-in permission
+ perm = script_getnum(st, 2);
+ script_pushint(st, pc_has_permission(sd, perm));
+ return true;
+}
+
+static BUILDIN(can_use_command)
+{
+ struct map_session_data *sd;
+ const char *cmd = script_getstr(st, 2);
+
+ if (script_hasdata(st, 3)) {
+ sd = map->id2sd(script_getnum(st, 3));
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return false;
+ }
+
+ script_pushint(st, pc->can_use_command(sd, cmd));
return true;
}
/* getrandgroupitem <container_item_id>,<quantity> */
-BUILDIN(getrandgroupitem) {
+static BUILDIN(getrandgroupitem)
+{
struct item_data *data = NULL;
struct map_session_data *sd = NULL;
int nameid = script_getnum(st, 2);
@@ -18972,7 +24014,7 @@ BUILDIN(getrandgroupitem) {
if ((flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) {
clif->additem(sd, 0, 0, flag);
if( pc->candrop(sd,&it) )
- map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &it, get_count, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
@@ -18985,14 +24027,14 @@ BUILDIN(getrandgroupitem) {
/* cleanmap <map_name>;
* cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */
-int script_cleanfloor_sub(struct block_list *bl, va_list ap) {
- nullpo_ret(bl);
+static int script_cleanfloor_sub(struct block_list *bl, va_list ap)
+{
map->clearflooritem(bl);
return 0;
}
-BUILDIN(cleanmap)
+static BUILDIN(cleanmap)
{
const char *mapname = script_getstr(st, 2);
int16 m = map->mapname2mapid(mapname);
@@ -19017,10 +24059,11 @@ BUILDIN(cleanmap)
return true;
}
+
/* Cast a skill on the attached player.
* npcskill <skill id>, <skill lvl>, <stat point>, <NPC level>;
* npcskill "<skill name>", <skill lvl>, <stat point>, <NPC level>; */
-BUILDIN(npcskill)
+static BUILDIN(npcskill)
{
struct npc_data *nd;
uint16 skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
@@ -19066,7 +24109,8 @@ BUILDIN(npcskill)
/* Turns a player into a monster and grants SC attribute effect. [malufett/Hercules]
* montransform <monster name/id>, <duration>, <sc type>, <val1>, <val2>, <val3>, <val4>; */
-BUILDIN(montransform) {
+static BUILDIN(montransform)
+{
int tick;
enum sc_type type;
struct block_list* bl;
@@ -19149,7 +24193,7 @@ BUILDIN(montransform) {
*
* @return The queue, or NULL if it doesn't exist.
*/
-struct script_queue *script_hqueue_get(int idx)
+static struct script_queue *script_hqueue_get(int idx)
{
if (idx < 0 || idx >= VECTOR_LENGTH(script->hq) || !VECTOR_INDEX(script->hq, idx).valid)
return NULL;
@@ -19161,7 +24205,7 @@ struct script_queue *script_hqueue_get(int idx)
*
* @return The index of the created queue.
*/
-int script_hqueue_create(void)
+static int script_hqueue_create(void)
{
struct script_queue *queue = NULL;
int i;
@@ -19188,7 +24232,7 @@ int script_hqueue_create(void)
* .@queue_id = queue();
* @endcode
*/
-BUILDIN(queue)
+static BUILDIN(queue)
{
script_pushint(st,script->queue_create());
return true;
@@ -19203,7 +24247,7 @@ BUILDIN(queue)
* .@size = queuesize(<queue id>);
* \endcode
*/
-BUILDIN(queuesize)
+static BUILDIN(queuesize)
{
int idx = script_getnum(st, 2);
@@ -19225,7 +24269,7 @@ BUILDIN(queuesize)
* @retval false if the queue is invalid or the entry is already in the queue.
* @retval true in case of success.
*/
-bool script_hqueue_add(int idx, int var)
+static bool script_hqueue_add(int idx, int var)
{
int i;
struct map_session_data *sd = NULL;
@@ -19263,7 +24307,7 @@ bool script_hqueue_add(int idx, int var)
* .@size = queuesize(.@queue_id);
* @endcode
*/
-BUILDIN(queueadd)
+static BUILDIN(queueadd)
{
int idx = script_getnum(st, 2);
int var = script_getnum(st, 3);
@@ -19284,7 +24328,7 @@ BUILDIN(queueadd)
* @retval true if the entry was removed.
* @retval false if the entry wasn't in queue.
*/
-bool script_hqueue_remove(int idx, int var)
+static bool script_hqueue_remove(int idx, int var)
{
int i;
struct map_session_data *sd = NULL;
@@ -19321,7 +24365,7 @@ bool script_hqueue_remove(int idx, int var)
* queueremove(.@queue_id, .@value);
* @endcode
*/
-BUILDIN(queueremove)
+static BUILDIN(queueremove)
{
int idx = script_getnum(st, 2);
int var = script_getnum(st, 3);
@@ -19337,7 +24381,7 @@ BUILDIN(queueremove)
/**
* Script command queueopt: Modifies the options of a queue.
*
- * When the option value isn't provided, the option is removed.
+ * When the <event label> isn't provided, the option is removed.
*
* Returns 1 (true) on success, 0 (false) on failure.
*
@@ -19347,13 +24391,13 @@ BUILDIN(queueremove)
* - QUEUEOPT_MAPCHANGE
*
* When the QUEUEOPT_MAPCHANGE event is triggered, it sets a temporary
- * character variable \c @Queue_Destination_Map$ with the destination map name.
+ * character variable @Queue_Destination_Map$ with the destination map name.
*
* @code{.herc}
- * queueopt(.@queue_id, optionType, <optional val>);
+ * queueopt(.@queue_id, optionType{, <event label>});
* @endcode
*/
-BUILDIN(queueopt)
+static BUILDIN(queueopt)
{
int idx = script_getnum(st, 2);
int var = script_getnum(st, 3);
@@ -19403,7 +24447,7 @@ BUILDIN(queueopt)
* @retval true if the queue was correctly deleted.
* @retval false if the queue didn't exist.
*/
-bool script_hqueue_del(int idx)
+static bool script_hqueue_del(int idx)
{
if (!script->queue_clear(idx))
return false;
@@ -19422,7 +24466,7 @@ bool script_hqueue_del(int idx)
* queuedel(.@queue_id);
* @endcode
*/
-BUILDIN(queuedel)
+static BUILDIN(queuedel)
{
int idx = script_getnum(st, 2);
@@ -19442,7 +24486,7 @@ BUILDIN(queuedel)
* @retval true if the queue was correctly cleared.
* @retval false if the queue didn't exist.
*/
-bool script_hqueue_clear(int idx)
+static bool script_hqueue_clear(int idx)
{
struct script_queue *queue = NULL;
@@ -19479,7 +24523,7 @@ bool script_hqueue_clear(int idx)
* .@id = queueiterator(.@queue_id);
* @endcode
*/
-BUILDIN(queueiterator)
+static BUILDIN(queueiterator)
{
int qid = script_getnum(st, 2);
struct script_queue *queue = NULL;
@@ -19522,7 +24566,7 @@ BUILDIN(queueiterator)
* }
* @endcode
*/
-BUILDIN(qiget)
+static BUILDIN(qiget)
{
int idx = script_getnum(st, 2);
struct script_queue_iterator *it = NULL;
@@ -19556,7 +24600,7 @@ BUILDIN(qiget)
* }
* @endcode
*/
-BUILDIN(qicheck)
+static BUILDIN(qicheck)
{
int idx = script_getnum(st, 2);
struct script_queue_iterator *it = NULL;
@@ -19587,7 +24631,7 @@ BUILDIN(qicheck)
* qiclear(.@iter);
* @endcode
*/
-BUILDIN(qiclear)
+static BUILDIN(qiclear)
{
int idx = script_getnum(st, 2);
struct script_queue_iterator *it = NULL;
@@ -19612,7 +24656,8 @@ BUILDIN(qiclear)
* packageitem({<optional container_item_id>})
* when no item id is provided it tries to assume it comes from the current item id being processed (if any)
**/
-BUILDIN(packageitem) {
+static BUILDIN(packageitem)
+{
struct item_data *data = NULL;
struct map_session_data *sd = NULL;
int nameid;
@@ -19646,7 +24691,8 @@ BUILDIN(packageitem) {
/* New Battlegrounds Stuff */
/* bg_team_create(map_name,respawn_x,respawn_y) */
/* returns created team id or -1 when fails */
-BUILDIN(bg_create_team) {
+static BUILDIN(bg_create_team)
+{
const char *map_name, *ev = "", *dev = "";//ev and dev will be dropped.
int x, y, map_index = 0, bg_id;
@@ -19654,7 +24700,7 @@ BUILDIN(bg_create_team) {
if( strcmp(map_name,"-") != 0 ) {
map_index = script->mapindexname2id(st,map_name);
if( map_index == 0 ) { // Invalid Map
- script_pushint(st,0);
+ script_pushint(st, -1);
return true;
}
}
@@ -19673,7 +24719,8 @@ BUILDIN(bg_create_team) {
/* bg_join_team(team_id{,optional account id}) */
/* when account id is not present it tries to autodetect from the attached player (if any) */
/* returns 0 when successful, 1 otherwise */
-BUILDIN(bg_join_team) {
+static BUILDIN(bg_join_team)
+{
struct map_session_data *sd;
int team_id = script_getnum(st, 2);
@@ -19699,9 +24746,9 @@ BUILDIN(bg_join_team) {
* 3 - Party Bound
* 4 - Character Bound
*------------------------------------------*/
-BUILDIN(countbound)
+static BUILDIN(countbound)
{
- int i, type, j=0, k=0;
+ int type, j=0, k=0;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
@@ -19709,12 +24756,12 @@ BUILDIN(countbound)
type = script_hasdata(st,2)?script_getnum(st,2):0;
- for(i=0;i<MAX_INVENTORY;i++) {
+ for (int i = 0; i < sd->status.inventorySize; i++) {
if(sd->status.inventory[i].nameid > 0 && (
(!type && sd->status.inventory[i].bound > 0) ||
(type && sd->status.inventory[i].bound == type)
)) {
- pc->setreg(sd,reference_uid(script->add_str("@bound_items"), k),sd->status.inventory[i].nameid);
+ pc->setreg(sd,reference_uid(script->add_variable("@bound_items"), k),sd->status.inventory[i].nameid);
k++;
j += sd->status.inventory[i].amount;
}
@@ -19734,7 +24781,7 @@ BUILDIN(countbound)
* 3 - Party Bound
* 4 - Character Bound
*------------------------------------------*/
-BUILDIN(checkbound)
+static BUILDIN(checkbound)
{
int i, nameid = script_getnum(st,2);
int bound_type = 0;
@@ -19755,27 +24802,28 @@ BUILDIN(checkbound)
ShowError("script_checkbound: Not a valid bind type! Type=%d\n", bound_type);
}
- ARR_FIND( 0, MAX_INVENTORY, i, (sd->status.inventory[i].nameid == nameid &&
+ ARR_FIND(0, sd->status.inventorySize, i, (sd->status.inventory[i].nameid == nameid &&
( sd->status.inventory[i].refine == (script_hasdata(st,4)? script_getnum(st,4) : sd->status.inventory[i].refine) ) &&
( sd->status.inventory[i].attribute == (script_hasdata(st,5)? script_getnum(st,5) : sd->status.inventory[i].attribute) ) &&
( sd->status.inventory[i].card[0] == (script_hasdata(st,6)? script_getnum(st,6) : sd->status.inventory[i].card[0]) ) &&
( sd->status.inventory[i].card[1] == (script_hasdata(st,7)? script_getnum(st,7) : sd->status.inventory[i].card[1]) ) &&
( sd->status.inventory[i].card[2] == (script_hasdata(st,8)? script_getnum(st,8) : sd->status.inventory[i].card[2]) ) &&
( sd->status.inventory[i].card[3] == (script_hasdata(st,9)? script_getnum(st,9) : sd->status.inventory[i].card[3]) ) &&
- ((sd->status.inventory[i].bound > 0 && !bound_type) || sd->status.inventory[i].bound == bound_type )) );
+ ((sd->status.inventory[i].bound > 0 && !bound_type) || sd->status.inventory[i].bound == bound_type)));
- if( i < MAX_INVENTORY ){
+ if (i < sd->status.inventorySize) {
script_pushint(st, sd->status.inventory[i].bound);
return true;
- } else
+ } else {
script_pushint(st,0);
+ }
return true;
}
/* bg_match_over( arena_name {, optional canceled } ) */
/* returns 0 when successful, 1 otherwise */
-BUILDIN(bg_match_over)
+static BUILDIN(bg_match_over)
{
bool canceled = script_hasdata(st,3) ? true : false;
struct bg_arena *arena = bg->name2arena(script_getstr(st, 2));
@@ -19789,7 +24837,8 @@ BUILDIN(bg_match_over)
return true;
}
-BUILDIN(instance_mapname) {
+static BUILDIN(instance_mapname)
+{
const char *map_name;
int m;
short instance_id = -1;
@@ -19809,10 +24858,12 @@ BUILDIN(instance_mapname) {
return true;
}
+
/* modify an instances' reload-spawn point */
/* instance_set_respawn <map_name>,<x>,<y>{,<instance_id>} */
/* returns 1 when successful, 0 otherwise. */
-BUILDIN(instance_set_respawn) {
+static BUILDIN(instance_set_respawn)
+{
const char *map_name;
short instance_id = -1;
short mid;
@@ -19853,12 +24904,13 @@ BUILDIN(instance_set_respawn) {
}
return true;
}
+
/**
* @call openshop({NPC Name});
*
* @return 1 on success, 0 otherwise.
**/
-BUILDIN(openshop)
+static BUILDIN(openshop)
{
struct npc_data *nd;
struct map_session_data *sd;
@@ -19888,17 +24940,147 @@ BUILDIN(openshop)
return true;
}
+
+static bool script_sellitemcurrency_add(struct npc_data *nd, struct script_state* st, int argIndex)
+{
+ nullpo_retr(false, nd);
+ nullpo_retr(false, st);
+
+ if (!script_hasdata(st, argIndex + 1))
+ return false;
+
+ int id = script_getnum(st, argIndex);
+ struct item_data *it;
+ if (!(it = itemdb->exists(id))) {
+ ShowWarning("buildin_sellitemcurrency: unknown item id '%d'!\n", id);
+ return false;
+ }
+ int qty = 0;
+ if ((qty = script_getnum(st, argIndex + 1)) <= 0) {
+ ShowError("buildin_sellitemcurrency: invalid 'qty'!\n");
+ return false;
+ }
+ int refine_level = -1;
+ if (script_hasdata(st, argIndex + 2)) {
+ refine_level = script_getnum(st, argIndex + 2);
+ }
+ int items = nd->u.scr.shop->items;
+ if (nd->u.scr.shop == NULL || items == 0) {
+ ShowWarning("buildin_sellitemcurrency: shop not have items!\n");
+ return false;
+ }
+ if (nd->u.scr.shop->shop_last_index >= items || nd->u.scr.shop->shop_last_index < 0) {
+ ShowWarning("buildin_sellitemcurrency: wrong selected shop index!\n");
+ return false;
+ }
+
+ struct npc_item_list *item_list = &nd->u.scr.shop->item[nd->u.scr.shop->shop_last_index];
+ int index = item_list->value2;
+ if (item_list->currency == NULL) {
+ CREATE(item_list->currency, struct npc_barter_currency, 1);
+ item_list->value2 ++;
+ } else {
+ RECREATE(item_list->currency, struct npc_barter_currency, ++item_list->value2);
+ }
+ struct npc_barter_currency *currency = &item_list->currency[index];
+ currency->nameid = id;
+ currency->refine = refine_level;
+ currency->amount = qty;
+ return true;
+}
+
+/**
+ * @call sellitemcurrency <Item_ID>,qty{,refine}};
+ *
+ * adds <Item_ID> to last item in expanded barter shop
+ **/
+static BUILDIN(sellitemcurrency)
+{
+ struct npc_data *nd;
+ if ((nd = map->id2nd(st->oid)) == NULL) {
+ ShowWarning("buildin_sellitemcurrency: trying to run without a proper NPC!\n");
+ return false;
+ }
+ if (nd->u.scr.shop == NULL || nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ ShowWarning("buildin_sellitemcurrency: this command can be used only with expanded barter shops!\n");
+ return false;
+ }
+
+ script->sellitemcurrency_add(nd, st, 2);
+ return true;
+}
+
+/**
+ * @call endsellitem;
+ *
+ * complete sell item in expanded barter shop (NST_EXPANDED_BARTER)
+ **/
+static BUILDIN(endsellitem)
+{
+ struct npc_data *nd;
+ if ((nd = map->id2nd(st->oid)) == NULL) {
+ ShowWarning("buildin_endsellitem: trying to run without a proper NPC!\n");
+ return false;
+ }
+ if (nd->u.scr.shop == NULL || nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ ShowWarning("buildin_endsellitem: this command can be used only with expanded barter shops!\n");
+ return false;
+ }
+
+ int newIndex = nd->u.scr.shop->shop_last_index;
+ const struct npc_item_list *const newItem = &nd->u.scr.shop->item[newIndex];
+ int i = 0;
+ for (i = 0; i < nd->u.scr.shop->items - 1; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid != newItem->nameid || item->value != newItem->value)
+ continue;
+ if (item->value2 != newItem->value2)
+ continue;
+ bool found = true;
+ for (int k = 0; k < item->value2; k ++) {
+ struct npc_barter_currency *currency = &item->currency[k];
+ struct npc_barter_currency *newCurrency = &newItem->currency[k];
+ if (currency->nameid != newCurrency->nameid ||
+ currency->amount != newCurrency->amount ||
+ currency->refine != newCurrency->refine) {
+ found = false;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ break;
+ }
+
+ if (i != nd->u.scr.shop->items - 1) {
+ if (nd->u.scr.shop->item[i].qty != -1) {
+ nd->u.scr.shop->item[i].qty += nd->u.scr.shop->item[newIndex].qty;
+ npc->expanded_barter_tosql(nd, i);
+ }
+ nd->u.scr.shop->shop_last_index --;
+ nd->u.scr.shop->items--;
+ if (nd->u.scr.shop->item[newIndex].currency != NULL) {
+ aFree(nd->u.scr.shop->item[newIndex].currency);
+ nd->u.scr.shop->item[newIndex].currency = NULL;
+ }
+ }
+
+ return true;
+}
+
/**
* @call sellitem <Item_ID>,{,price{,qty}};
*
* adds <Item_ID> (or modifies if present) to shop
* if price not provided (or -1) uses the item's value_sell
**/
-BUILDIN(sellitem) {
+static BUILDIN(sellitem)
+{
struct npc_data *nd;
struct item_data *it;
int i = 0, id = script_getnum(st,2);
int value = 0;
+ int value2 = 0;
int qty = 0;
if( !(nd = map->id2nd(st->oid)) ) {
@@ -19909,16 +25091,71 @@ BUILDIN(sellitem) {
return false;
}
- value = script_hasdata(st,3) ? script_getnum(st, 3) : it->value_buy;
- if( value == -1 )
- value = it->value_buy;
+ const bool have_shop = (nd->u.scr.shop != NULL);
+ if (!have_shop) {
+ npc->trader_update(nd->src_id ? nd->src_id : nd->bl.id);
+ }
- if( !nd->u.scr.shop )
- npc->trader_update(nd->src_id?nd->src_id:nd->bl.id);
- else {/* no need to run this if its empty */
- for( i = 0; i < nd->u.scr.shop->items; i++ ) {
- if( nd->u.scr.shop->item[i].nameid == id )
+ if (nd->u.scr.shop->type != NST_BARTER) {
+ value = script_hasdata(st, 3) ? script_getnum(st, 3) : it->value_buy;
+ if (value == -1)
+ value = it->value_buy;
+ }
+
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ if (!script_hasdata(st, 5)) {
+ ShowError("buildin_sellitem: invalid number of parameters for barter-type shop!\n");
+ return false;
+ }
+ value = script_getnum(st, 4);
+ value2 = script_getnum(st, 5);
+ } else if (nd->u.scr.shop->type == NST_EXPANDED_BARTER) {
+ if (!script_hasdata(st, 4)) {
+ ShowError("buildin_sellitem: invalid number of parameters for expanded barter type shop!\n");
+ return false;
+ }
+ if ((qty = script_getnum(st, 4)) <= 0 && qty != -1) {
+ ShowError("buildin_sellitem: invalid 'qty' for expanded barter type shop!\n");
+ return false;
+ }
+ }
+
+ if (have_shop) {
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == id && item->value == value && item->value2 == value2) {
+ break;
+ }
+ }
+ } else if (nd->u.scr.shop->type == NST_EXPANDED_BARTER) {
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid != id || item->value != value)
+ continue;
+ if (item->value2 != (script_lastdata(st) - 4) / 3)
+ continue;
+ bool found = true;
+ for (int k = 0; k < item->value2; k ++) {
+ const int scriptOffset = k * 3 + 5;
+ struct npc_barter_currency *currency = &item->currency[k];
+ if (currency->nameid != script_getnum(st, scriptOffset) ||
+ currency->amount != script_getnum(st, scriptOffset + 1) ||
+ currency->refine != script_getnum(st, scriptOffset + 2)) {
+ found = false;
+ break;
+ }
+ }
+ if (!found)
+ continue;
break;
+ }
+ } else {
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ if (nd->u.scr.shop->item[i].nameid == id) {
+ break;
+ }
+ }
}
}
@@ -19934,19 +25171,30 @@ BUILDIN(sellitem) {
it->name, id, value, (int)(value*0.75), it->value_sell, (int)(it->value_sell*1.24), nd->exname, nd->path);
}
- if( i != nd->u.scr.shop->items ) {
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ qty = script_getnum(st, 3);
+ if (qty < -1 || value <= 0 || value2 <= 0) {
+ ShowError("buildin_sellitem: invalid parameters for barter-type shop!\n");
+ return false;
+ }
+ }
+
+ bool foundInShop = (i != nd->u.scr.shop->items);
+ if (foundInShop) {
nd->u.scr.shop->item[i].value = value;
nd->u.scr.shop->item[i].qty = qty;
- if( nd->u.scr.shop->type == NST_MARKET ) /* has been manually updated, make it reflect on sql */
- npc->market_tosql(nd,i);
+ if (nd->u.scr.shop->type == NST_MARKET) /* has been manually updated, make it reflect on sql */
+ npc->market_tosql(nd, i);
+ else if (nd->u.scr.shop->type == NST_BARTER) /* has been manually updated, make it reflect on sql */
+ npc->barter_tosql(nd, i);
} else {
- for( i = 0; i < nd->u.scr.shop->items; i++ ) {
- if( nd->u.scr.shop->item[i].nameid == 0 )
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ if (nd->u.scr.shop->item[i].nameid == 0)
break;
}
- if( i == nd->u.scr.shop->items ) {
- if( nd->u.scr.shop->items == USHRT_MAX ) {
+ if (i == nd->u.scr.shop->items) {
+ if (nd->u.scr.shop->items == USHRT_MAX) {
ShowWarning("buildin_sellitem: Can't add %s (%s/%s), shop list is full!\n", it->name, nd->exname, nd->path);
return false;
}
@@ -19956,11 +25204,89 @@ BUILDIN(sellitem) {
nd->u.scr.shop->item[i].nameid = it->nameid;
nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].value2 = value2;
nd->u.scr.shop->item[i].qty = qty;
+ nd->u.scr.shop->item[i].currency = NULL;
+ }
+ nd->u.scr.shop->shop_last_index = i;
+
+ if (!foundInShop) {
+ for (int k = 5; k <= script_lastdata(st); k += 3) {
+ script->sellitemcurrency_add(nd, st, k);
+ }
}
+ if (foundInShop) {
+ if (nd->u.scr.shop->type == NST_EXPANDED_BARTER) { /* has been manually updated, make it reflect on sql */
+ npc->expanded_barter_tosql(nd, i);
+ }
+ }
return true;
}
+
+/**
+ * @call startsellitem <Item_ID>,{,price{,qty}};
+ *
+ * Starts adding item into expanded barter shop (NST_EXPANDED_BARTER)
+ **/
+static BUILDIN(startsellitem)
+{
+ struct npc_data *nd;
+ struct item_data *it;
+ int i = 0, id = script_getnum(st,2);
+ int value2 = 0;
+ int qty = 0;
+
+ if (!(nd = map->id2nd(st->oid))) {
+ ShowWarning("buildin_startsellitem: trying to run without a proper NPC!\n");
+ return false;
+ } else if (!(it = itemdb->exists(id))) {
+ ShowWarning("buildin_startsellitem: unknown item id '%d'!\n", id);
+ return false;
+ }
+
+ const bool have_shop = (nd->u.scr.shop != NULL);
+ if (!have_shop) {
+ npc->trader_update(nd->src_id ? nd->src_id : nd->bl.id);
+ }
+
+ if (nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ ShowWarning("script_startsellitem: can works only for NST_EXPANDED_BARTER shops");
+ return false;
+ }
+
+ int value = script_hasdata(st, 3) ? script_getnum(st, 3) : it->value_buy;
+ if (value == -1)
+ value = it->value_buy;
+
+ if ((qty = script_getnum(st, 4)) <= 0 && qty != -1) {
+ ShowError("buildin_startsellitem: invalid 'qty' for expanded barter type shop!\n");
+ return false;
+ }
+
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ if (nd->u.scr.shop->item[i].nameid == 0)
+ break;
+ }
+
+ if (i == nd->u.scr.shop->items) {
+ if (nd->u.scr.shop->items == USHRT_MAX) {
+ ShowWarning("buildin_startsellitem: Can't add %s (%s/%s), shop list is full!\n", it->name, nd->exname, nd->path);
+ return false;
+ }
+ i = nd->u.scr.shop->items;
+ RECREATE(nd->u.scr.shop->item, struct npc_item_list, ++nd->u.scr.shop->items);
+ }
+
+ nd->u.scr.shop->item[i].nameid = it->nameid;
+ nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].value2 = value2;
+ nd->u.scr.shop->item[i].qty = qty;
+ nd->u.scr.shop->item[i].currency = NULL;
+ nd->u.scr.shop->shop_last_index = i;
+ return true;
+}
+
/**
* @call stopselling <Item_ID>;
*
@@ -19968,56 +25294,100 @@ BUILDIN(sellitem) {
*
* @return 1 on success, 0 otherwise
**/
-BUILDIN(stopselling) {
+static BUILDIN(stopselling)
+{
struct npc_data *nd;
- int i, id = script_getnum(st,2);
+ int i, id = script_getnum(st, 2);
- if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ if (!(nd = map->id2nd(st->oid)) || !nd->u.scr.shop) {
ShowWarning("buildin_stopselling: trying to run without a proper NPC!\n");
return false;
}
- for( i = 0; i < nd->u.scr.shop->items; i++ ) {
- if( nd->u.scr.shop->item[i].nameid == id )
- break;
+ if (nd->u.scr.shop->type == NST_BARTER) {
+ if (!script_hasdata(st, 4)) {
+ ShowError("buildin_stopselling: called with wrong number of arguments\n");
+ return false;
+ }
+ const int id2 = script_getnum(st, 3);
+ const int amount2 = script_getnum(st, 4);
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == id && item->value == id2 && item->value2 == amount2) {
+ break;
+ }
+ }
+ } else if (nd->u.scr.shop->type == NST_EXPANDED_BARTER) {
+ if (!script_hasdata(st, 3)) {
+ ShowError("buildin_stopselling: called with wrong number of arguments\n");
+ return false;
+ }
+ const int price = script_getnum(st, 3);
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ const struct npc_item_list *const item = &nd->u.scr.shop->item[i];
+ if (item->nameid == id && item->value == price) {
+ break;
+ }
+ }
+ } else {
+ for (i = 0; i < nd->u.scr.shop->items; i++) {
+ if (nd->u.scr.shop->item[i].nameid == id) {
+ break;
+ }
+ }
}
- if( i != nd->u.scr.shop->items ) {
+ if (i != nd->u.scr.shop->items) {
int cursor;
- if( nd->u.scr.shop->type == NST_MARKET )
- npc->market_delfromsql(nd,i);
+ if (nd->u.scr.shop->type == NST_MARKET)
+ npc->market_delfromsql(nd, i);
+ else if (nd->u.scr.shop->type == NST_BARTER)
+ npc->barter_delfromsql(nd, i);
+ else if (nd->u.scr.shop->type == NST_EXPANDED_BARTER)
+ npc->expanded_barter_delfromsql(nd, i);
nd->u.scr.shop->item[i].nameid = 0;
nd->u.scr.shop->item[i].value = 0;
+ nd->u.scr.shop->item[i].value2 = 0;
nd->u.scr.shop->item[i].qty = 0;
+ if (nd->u.scr.shop->item[i].currency != NULL) {
+ aFree(nd->u.scr.shop->item[i].currency);
+ nd->u.scr.shop->item[i].currency = NULL;
+ }
- for( i = 0, cursor = 0; i < nd->u.scr.shop->items; i++ ) {
- if( nd->u.scr.shop->item[i].nameid == 0 )
+ for (i = 0, cursor = 0; i < nd->u.scr.shop->items; i++) {
+ if (nd->u.scr.shop->item[i].nameid == 0)
continue;
- if( cursor != i ) {
+ if (cursor != i) {
nd->u.scr.shop->item[cursor].nameid = nd->u.scr.shop->item[i].nameid;
nd->u.scr.shop->item[cursor].value = nd->u.scr.shop->item[i].value;
+ nd->u.scr.shop->item[cursor].value2 = nd->u.scr.shop->item[i].value2;
nd->u.scr.shop->item[cursor].qty = nd->u.scr.shop->item[i].qty;
+ nd->u.scr.shop->item[cursor].currency = nd->u.scr.shop->item[i].currency;
}
cursor++;
}
+ nd->u.scr.shop->items--;
+ nd->u.scr.shop->item[nd->u.scr.shop->items].currency = NULL;
script_pushint(st, 1);
- } else
+ } else {
script_pushint(st, 0);
+ }
return true;
}
+
/**
* @call setcurrency <Val1>{,<Val2>};
*
* updates currently-attached player shop currency
**/
/* setcurrency(<Val1>,{<Val2>}) */
-BUILDIN(setcurrency)
+static BUILDIN(setcurrency)
{
int val1 = script_getnum(st,2),
val2 = script_hasdata(st, 3) ? script_getnum(st,3) : 0;
@@ -20033,6 +25403,7 @@ BUILDIN(setcurrency)
return true;
}
+
/**
* @call tradertype(<type>);
*
@@ -20040,7 +25411,8 @@ BUILDIN(setcurrency)
* check enum npc_shop_types for list
* cleans shop list on use
**/
-BUILDIN(tradertype) {
+static BUILDIN(tradertype)
+{
int type = script_getnum(st, 2);
struct npc_data *nd;
@@ -20061,7 +25433,9 @@ BUILDIN(tradertype) {
nd->u.scr.shop->item[i].value = 0;
nd->u.scr.shop->item[i].qty = 0;
}
- npc->market_delfromsql(nd,USHRT_MAX);
+ npc->market_delfromsql(nd, INT_MAX);
+ npc->barter_delfromsql(nd, INT_MAX);
+ npc->expanded_barter_delfromsql(nd, INT_MAX);
}
#if PACKETVER < 20131223
@@ -20070,18 +25444,32 @@ BUILDIN(tradertype) {
script->reportsrc(st);
}
#endif
+#if PACKETVER_MAIN_NUM < 20190116 && PACKETVER_RE_NUM < 20190116 && PACKETVER_ZERO_NUM < 20181226
+ if (type == NST_BARTER) {
+ ShowWarning("buildin_tradertype: NST_BARTER is only available with PACKETVER_ZERO_NUM 20181226 or PACKETVER_MAIN_NUM 20190116 or PACKETVER_RE_NUM 20190116 or newer!\n");
+ script->reportsrc(st);
+ }
+#endif
+#if PACKETVER_MAIN_NUM < 20191120 && PACKETVER_RE_NUM < 20191106 && PACKETVER_ZERO_NUM < 20191127
+ if (type == NST_EXPANDED_BARTER) {
+ ShowWarning("buildin_tradertype: NST_EXPANDED_BARTER is only available with PACKETVER_ZERO_NUM 20191127 or PACKETVER_MAIN_NUM 20191120 or PACKETVER_RE_NUM 20191106 or newer!\n");
+ script->reportsrc(st);
+ }
+#endif
if( nd->u.scr.shop )
nd->u.scr.shop->type = type;
return true;
}
+
/**
* @call purchaseok();
*
* signs the transaction can proceed
**/
-BUILDIN(purchaseok) {
+static BUILDIN(purchaseok)
+{
struct npc_data *nd;
if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
@@ -20093,12 +25481,14 @@ BUILDIN(purchaseok) {
return true;
}
+
/**
* @call shopcount(<Item_ID>);
*
* @return number of available items in the script's attached shop
**/
-BUILDIN(shopcount) {
+static BUILDIN(shopcount)
+{
struct npc_data *nd;
int id = script_getnum(st, 2);
unsigned short i;
@@ -20109,8 +25499,8 @@ BUILDIN(shopcount) {
} else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) {
ShowWarning("buildin_shopcount(%d): trying to use without any items!\n",id);
return false;
- } else if ( nd->u.scr.shop->type != NST_MARKET ) {
- ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET shop!\n",id);
+ } else if (nd->u.scr.shop->type != NST_MARKET && nd->u.scr.shop->type != NST_BARTER && nd->u.scr.shop->type != NST_EXPANDED_BARTER) {
+ ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET and non-NST_BARTER and non-NST_EXPANDED_BARTER shop!\n",id);
return false;
}
@@ -20135,9 +25525,9 @@ BUILDIN(shopcount) {
* Sends a message through the specified chat channel.
*
*/
-BUILDIN(channelmes)
+static BUILDIN(channelmes)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = map->id2sd(st->rid);
const char *channelname = script_getstr(st, 2);
struct channel_data *chan = channel->search(channelname, sd);
@@ -20152,14 +25542,66 @@ BUILDIN(channelmes)
return true;
}
+static BUILDIN(addchannelhandler)
+{
+ int i;
+ struct map_session_data *sd = map->id2sd(st->rid);
+ const char *channelname = script_getstr(st, 2);
+ const char *eventname = script_getstr(st, 3);
+ struct channel_data *chan = channel->search(channelname, sd);
+
+ if (!chan) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ ARR_FIND(0, MAX_EVENTQUEUE, i, chan->handlers[i][0] == '\0');
+
+ if (i < MAX_EVENTQUEUE) {
+ safestrncpy(chan->handlers[i], eventname, EVENT_NAME_LENGTH); //Event enqueued.
+ script_pushint(st, 1);
+ return true;
+ }
+
+ ShowWarning("script:addchannelhandler: too many handlers for channel %s.\n", channelname);
+ script_pushint(st, 0);
+ return true;
+}
+
+static BUILDIN(removechannelhandler)
+{
+ int i;
+ struct map_session_data *sd = map->id2sd(st->rid);
+ const char *channelname = script_getstr(st, 2);
+ const char *eventname = script_getstr(st, 3);
+ struct channel_data *chan = channel->search(channelname, sd);
+
+ if (!chan) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ for (i = 0; i < MAX_EVENTQUEUE; i++) {
+ if (strcmp(chan->handlers[i], eventname) == 0) {
+ chan->handlers[i][0] = '\0';
+ script_pushint(st, 1);
+ return true;
+ }
+ }
+
+ script_pushint(st, 0);
+ return true;
+}
+
/** By Cydh
-Display script message
-showscript "<message>"{,<GID>};
-*/
-BUILDIN(showscript) {
+ * Display script message
+ * showscript "<message>"{, <GID>};
+ */
+static BUILDIN(showscript)
+{
struct block_list *bl = NULL;
const char *msg = script_getstr(st, 2);
- int id = 0;
+ int id = 0, flag = AREA;
if (script_hasdata(st, 3)) {
id = script_getnum(st, 3);
@@ -20171,18 +25613,18 @@ BUILDIN(showscript) {
if (!bl) {
ShowError("buildin_showscript: Script not attached. (id=%d, rid=%d, oid=%d)\n", id, st->rid, st->oid);
- script_pushint(st, 0);
return false;
}
- clif->ShowScript(bl, msg);
-
- script_pushint(st, 1);
+ if (script_hasdata(st, 4))
+ if (script_getnum(st, 4) == SELF)
+ flag = SELF;
+ clif->ShowScript(bl, msg, flag);
return true;
}
-BUILDIN(mergeitem)
+static BUILDIN(mergeitem)
{
struct map_session_data *sd = script->rid2sd(st);
@@ -20193,8 +25635,198 @@ BUILDIN(mergeitem)
return true;
}
+
+// getcalendartime(<day of month>, <day of week>{, <hour>{, <minute>}});
+// Returns the UNIX Timestamp of next ocurrency of given time
+static BUILDIN(getcalendartime)
+{
+ struct tm info = { 0 };
+ int day_of_month = script_hasdata(st, 4) ? script_getnum(st, 4) : -1;
+ int day_of_week = script_hasdata(st, 5) ? script_getnum(st, 5) : -1;
+ int year = date_get_year();
+ int month = date_get_month();
+ int day = date_get_day();
+ int cur_hour = date_get_hour();
+ int cur_min = date_get_min();
+ int hour = script_getnum(st, 2);
+ int minute = script_getnum(st, 3);
+
+ info.tm_sec = 0;
+ info.tm_min = minute;
+ info.tm_hour = hour;
+ info.tm_mday = day;
+ info.tm_mon = month - 1;
+ info.tm_year = year - 1900;
+
+ if (day_of_month > -1 && day_of_week > -1) {
+ ShowError("script:getcalendartime: You must only specify a day_of_week or a day_of_month, not both\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_month > -1 && (day_of_month < 1 || day_of_month > 31)) {
+ ShowError("script:getcalendartime: Day of Month in invalid range. Must be between 1 and 31.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_week > -1 && (day_of_week < 0 || day_of_week > 6)) {
+ ShowError("script:getcalendartime: Day of Week in invalid range. Must be between 0 and 6.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour > -1 && (hour > 23)) {
+ ShowError("script:getcalendartime: Hour in invalid range. Must be between 0 and 23.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (minute > -1 && (minute > 59)) {
+ ShowError("script:getcalendartime: Minute in invalid range. Must be between 0 and 59.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour == -1 || minute == -1) {
+ ShowError("script:getcalendartime: Minutes and Hours are required\n");
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (day_of_month > -1) {
+ if (day_of_month < day) { // Next Month
+ info.tm_mon++;
+ } else if (day_of_month == day) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { // But past time, next month
+ info.tm_mon++;
+ }
+ }
+
+ // Loops until month has finding a month that has day_of_month
+ do {
+ time_t t;
+ struct tm *lt;
+ info.tm_mday = day_of_month;
+ t = mktime(&info);
+ lt = localtime(&t);
+ info = *lt;
+ } while (info.tm_mday != day_of_month);
+ } else if (day_of_week > -1) {
+ int cur_wday = date_get_dayofweek();
+
+ if (day_of_week > cur_wday) { // This week
+ info.tm_mday += (day_of_week - cur_wday);
+ } else if (day_of_week == cur_wday) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute <= cur_min)) {
+ info.tm_mday += 7; // Next week
+ }
+ } else if (day_of_week < cur_wday) { // Next week
+ info.tm_mday += (7 - cur_wday + day_of_week);
+ }
+ } else if (day_of_week == -1 && day_of_month == -1) { // Next occurence of hour/min
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) {
+ info.tm_mday++;
+ }
+ }
+
+ script_pushint(st, mktime(&info));
+
+ return true;
+}
+
+enum consolemes_type {
+ CONSOLEMES_DEBUG = 0,
+ CONSOLEMES_ERROR = 1,
+ CONSOLEMES_WARNING = 2,
+ CONSOLEMES_INFO = 3,
+ CONSOLEMES_STATUS = 4,
+ CONSOLEMES_NOTICE = 5,
+};
+
+/*==========================================
+* consolemes(<type>, "text")
+*------------------------------------------*/
+static BUILDIN(consolemes)
+{
+ struct StringBuf buf;
+ StrBuf->Init(&buf);
+ int type = script_hasdata(st, 2) ? script_getnum(st, 2) : 0;
+
+ if (!script->sprintf_helper(st, 3, &buf)) {
+ StrBuf->Destroy(&buf);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
+ default:
+ case CONSOLEMES_DEBUG:
+ ShowDebug("consolemes: %s\n", StrBuf->Value(&buf));
+ break;
+ case CONSOLEMES_ERROR:
+ ShowError("consolemes: (st->rid: %d) (st->oid: %d) %s\n", st->rid, st->oid, StrBuf->Value(&buf));
+ break;
+ case CONSOLEMES_WARNING:
+ ShowWarning("consolemes: (st->rid: %d) (st->oid: %d) %s\n", st->rid, st->oid, StrBuf->Value(&buf));
+ break;
+ case CONSOLEMES_INFO:
+ ShowInfo("consolemes: %s\n", StrBuf->Value(&buf));
+ break;
+ case CONSOLEMES_STATUS:
+ ShowStatus("consolemes: %s\n", StrBuf->Value(&buf));
+ break;
+ case CONSOLEMES_NOTICE:
+ ShowNotice("consolemes: %s\n", StrBuf->Value(&buf));
+ break;
+ }
+
+ StrBuf->Destroy(&buf);
+ script_pushint(st, 1);
+ return true;
+}
+
+static BUILDIN(setfavoriteitemidx)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ int idx = script_getnum(st, 2);
+ int value = script_getnum(st, 3);
+
+ if (sd == NULL) {
+ ShowError("buildin_setfavoriteitemidx: No player attached.\n");
+ return false;
+ }
+
+ if (idx < 0 || idx >= sd->status.inventorySize) {
+ ShowError("buildin_setfavoriteitemidx: Invalid inventory index %d (min: %d, max: %d).\n", idx, 0, (sd->status.inventorySize - 1));
+ return false;
+ } else if (sd->inventory_data[idx] == NULL || sd->inventory_data[idx]->nameid <= 0) {
+ ShowWarning("buildin_setfavoriteitemidx: Current inventory index %d has no data.\n", idx);
+ return false;
+ } else if (sd->status.inventory[idx].equip > 0) {
+ ShowWarning("buildin_setfavoriteitemidx: Cant change favorite flag of an equipped item.\n");
+ return false;
+ } else {
+ sd->status.inventory[idx].favorite = cap_value(value, 0, 1);
+ clif->favorite_item(sd, idx);
+ }
+
+ return true;
+}
+
+static BUILDIN(autofavoriteitem)
+{
+ int nameid = script_getnum(st, 2);
+ int flag = script_getnum(st, 3);
+ struct item_data *item_data;
+
+ if ((item_data = itemdb->exists(nameid)) == NULL) {
+ ShowError("buildin_autofavoriteitem: Invalid item '%d'.\n", nameid);
+ return false;
+ }
+
+ item_data->flag.auto_favorite = cap_value(flag, 0, 1);
+ return true;
+}
+
/** place holder for the translation macro **/
-BUILDIN(_) {
+static BUILDIN(_)
+{
return true;
}
@@ -20204,7 +25836,52 @@ BUILDIN(activatepset);
BUILDIN(deactivatepset);
BUILDIN(deletepset);
-BUILDIN(pcre_match) {
+enum dressroom_mode {
+ DRESSROOM_CLOSE = 0,
+ DRESSROOM_OPEN = 1
+};
+
+/**
+ * dressroom({<enum dressroom_mode>});
+ */
+static BUILDIN(dressroom)
+{
+#if PACKETVER >= 20150513
+ struct map_session_data *sd = script->rid2sd(st);
+ enum dressroom_mode mode = DRESSROOM_OPEN;
+
+ if (sd == NULL) {
+ return false;
+ }
+
+ if (script_hasdata(st, 2)) {
+ mode = script_getnum(st, 2);
+ }
+
+ switch (mode) {
+ case DRESSROOM_OPEN:
+ clif->dressroom_open(sd, 1);
+ break;
+ case DRESSROOM_CLOSE:
+ clif->dressroom_open(sd, 0);
+ break;
+ default:
+ ShowWarning("script:dressroom: unknown mode (%u).\n", mode);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ script_pushint(st, 1);
+ return true;
+#else
+ ShowError("The dressing room works only with packet version >= 20150513");
+ script_pushint(st, 0);
+ return false;
+#endif
+}
+
+static BUILDIN(pcre_match)
+{
const char *input = script_getstr(st, 2);
const char *regex = script_getstr(st, 3);
@@ -20213,6 +25890,685 @@ BUILDIN(pcre_match) {
}
/**
+ * navigateto("<map>"{,<x>,<y>,<flag>,<hide_window>,<monster_id>,<char_id>});
+ */
+static BUILDIN(navigateto)
+{
+#if PACKETVER >= 20111010
+ struct map_session_data* sd;
+ const char *mapname;
+ uint16 x = 0;
+ uint16 y = 0;
+ uint16 monster_id = 0;
+ uint8 flag = NAV_KAFRA_AND_AIRSHIP;
+ bool hideWindow = true;
+
+ mapname = script_getstr(st, 2);
+
+ if (script_hasdata(st, 3))
+ x = script_getnum(st, 3);
+ if (script_hasdata(st, 4))
+ y = script_getnum(st, 4);
+ if (script_hasdata(st, 5))
+ flag = (uint8)script_getnum(st, 5);
+ if (script_hasdata(st, 6))
+ hideWindow = script_getnum(st, 6) ? true : false;
+ if (script_hasdata(st, 7))
+ monster_id = script_getnum(st, 7);
+
+ if (script_hasdata(st, 8)) {
+ sd = map->charid2sd(script_getnum(st, 8));
+ } else {
+ sd = script->rid2sd(st);
+ }
+
+ clif->navigate_to(sd, mapname, x, y, flag, hideWindow, monster_id);
+
+ return true;
+#else
+ ShowError("Navigation system works only with packet version >= 20111010");
+ return false;
+#endif
+}
+
+static bool rodex_sendmail_sub(struct script_state *st, struct rodex_message *msg)
+{
+ const char *sender_name, *title, *body;
+
+ if (strcmp(script->getfuncname(st), "rodex_sendmail_acc") == 0 || strcmp(script->getfuncname(st), "rodex_sendmail_acc2") == 0)
+ msg->receiver_accountid = script_getnum(st, 2);
+ else
+ msg->receiver_id = script_getnum(st, 2);
+
+ sender_name = script_getstr(st, 3);
+ if (strlen(sender_name) >= NAME_LENGTH) {
+ ShowError("script:rodex_sendmail: Sender name must not be bigger than %d!\n", NAME_LENGTH - 1);
+ return false;
+ }
+ safestrncpy(msg->sender_name, sender_name, NAME_LENGTH);
+
+ title = script_getstr(st, 4);
+ if (strlen(title) >= RODEX_TITLE_LENGTH) {
+ ShowError("script:rodex_sendmail: Mail Title must not be bigger than %d!\n", RODEX_TITLE_LENGTH - 1);
+ return false;
+ }
+ safestrncpy(msg->title, title, RODEX_TITLE_LENGTH);
+
+ body = script_getstr(st, 5);
+ if (strlen(body) >= MAIL_BODY_LENGTH) {
+ ShowError("script:rodex_sendmail: Mail Message must not be bigger than %d!\n", RODEX_BODY_LENGTH - 1);
+ return false;
+ }
+ safestrncpy(msg->body, body, MAIL_BODY_LENGTH);
+
+ if (script_hasdata(st, 6)) {
+ msg->zeny = script_getnum(st, 6);
+ if (msg->zeny < 0 || msg->zeny > MAX_ZENY) {
+ ShowError("script:rodex_sendmail: Invalid Zeny value %"PRId64"!\n", msg->zeny);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static BUILDIN(rodex_sendmail)
+{
+ struct rodex_message msg = { 0 };
+ int item_count = 0, i = 0, param = 7;
+
+ // Common parameters - sender/message/zeny
+ if (rodex_sendmail_sub(st, &msg) == false)
+ return false;
+
+ // Item list
+ while (i < RODEX_MAX_ITEM && script_hasdata(st, param)) {
+ struct item_data *idata;
+
+ if (!script_hasdata(st, param + 1)) {
+ ShowError("script:rodex_sendmail: Missing Item %d amount!\n", (i + 1));
+ return false;
+ }
+
+ ++item_count;
+ if (data_isstring(script_getdata(st, param)) == false) {
+ int itemid = script_getnum(st, param);
+
+ if (itemdb->exists(itemid) == false) {
+ ShowError("script:rodex_sendmail: Unknown item ID %d.\n", itemid);
+ return false;
+ }
+
+ idata = itemdb->search(itemid);
+ }
+ else {
+ ShowError("script:rodex_sendmail: Item %d must be passed as Number.\n", (i + 1));
+ return false;
+ }
+
+ msg.items[i].item.nameid = idata->nameid;
+ msg.items[i].item.amount = script_getnum(st, (param + 1));
+ msg.items[i].item.identify = 1;
+
+ ++i;
+ param += 2;
+ }
+ msg.items_count = item_count;
+
+ msg.type = MAIL_TYPE_NPC;
+ if (msg.zeny > 0)
+ msg.type |= MAIL_TYPE_ZENY;
+ if (msg.items_count > 0)
+ msg.type |= MAIL_TYPE_ITEM;
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+
+ return true;
+}
+
+static BUILDIN(rodex_sendmail2)
+{
+ struct rodex_message msg = { 0 };
+ int item_count = 0, i = 0, param = 7;
+
+ // Common parameters - sender/message/zeny
+ if (rodex_sendmail_sub(st, &msg) == false)
+ return false;
+
+ // Item list
+ while (i < RODEX_MAX_ITEM && script_hasdata(st, param)) {
+ struct item_data *idata;
+ int j;
+
+ // Tests
+ if (!script_hasdata(st, param + 1)) {
+ ShowError("script:rodex_sendmail: Missing Item %d amount!\n", (i + 1));
+ return false;
+ }
+ if (!script_hasdata(st, param + 2)) {
+ ShowError("script:rodex_sendmail: Missing Item %d refine!\n", (i + 1));
+ return false;
+ }
+ if (!script_hasdata(st, param + 3)) {
+ ShowError("script:rodex_sendmail: Missing Item %d attribute!\n", (i + 1));
+ return false;
+ }
+ for (j = 0; j < MAX_SLOTS; ++j) {
+ if (!script_hasdata(st, param + 4 + j)) {
+ ShowError("script:rodex_sendmail: Missing Item %d card %d!\n", (i + 1), j);
+ return false;
+ }
+ }
+
+ // Set data to message
+ ++item_count;
+ if (data_isstring(script_getdata(st, param)) == false) {
+ int itemid = script_getnum(st, param);
+
+ if (itemdb->exists(itemid) == false) {
+ ShowError("script:rodex_sendmail: Unknown item ID %d.\n", itemid);
+ return false;
+ }
+
+ idata = itemdb->search(itemid);
+ } else {
+ ShowError("script:rodex_sendmail: Item %d must be passed as Number.\n", (i + 1));
+ return false;
+ }
+
+ msg.items[i].item.nameid = idata->nameid;
+ msg.items[i].item.amount = script_getnum(st, (param + 1));
+ msg.items[i].item.refine = script_getnum(st, (param + 2));
+ msg.items[i].item.attribute = script_getnum(st, (param + 3));
+ msg.items[i].item.identify = 1;
+
+ for (j = 0; j < MAX_SLOTS; ++j) {
+ msg.items[i].item.card[j] = script_getnum(st, param + 4 + j);
+ }
+
+ ++i;
+ param += 4 + MAX_SLOTS;
+ }
+ msg.items_count = item_count;
+
+ msg.type = MAIL_TYPE_NPC;
+ if (msg.zeny > 0)
+ msg.type |= MAIL_TYPE_ZENY;
+ if (msg.items_count > 0)
+ msg.type |= MAIL_TYPE_ITEM;
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+
+ return true;
+}
+
+/**
+ * Clan System: Add a player to a clan
+ */
+static BUILDIN(clan_join)
+{
+ struct map_session_data *sd = NULL;
+ int clan_id = script_getnum(st, 2);
+
+ if (script_hasdata(st, 3))
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = map->id2sd(st->rid);
+
+ if (sd == NULL) {
+ script_pushint(st, false);
+ return false;
+ }
+
+ if (clan->join(sd, clan_id))
+ script_pushint(st, true);
+ else
+ script_pushint(st, false);
+
+ return true;
+}
+
+/**
+ * Clan System: Remove a player from clan
+ */
+static BUILDIN(clan_leave)
+{
+ struct map_session_data *sd = NULL;
+
+ if (script_hasdata(st, 2))
+ sd = map->id2sd(script_getnum(st, 2));
+ else
+ sd = map->id2sd(st->rid);
+
+ if (sd == NULL) {
+ script_pushint(st, false);
+ return false;
+ }
+
+ if (clan->leave(sd, false))
+ script_pushint(st, true);
+ else
+ script_pushint(st, false);
+
+ return true;
+}
+
+/**
+ * Clan System: Show clan emblem next to npc name
+ */
+static BUILDIN(clan_master)
+{
+ struct npc_data *nd = map->id2nd(st->oid);
+ int clan_id = script_getnum(st, 2);
+
+ if (nd == NULL) {
+ script_pushint(st, false);
+ return false;
+ } else if (clan_id <= 0) {
+ script_pushint(st, false);
+ ShowError("buildin_clan_master: Received Invalid Clan ID %d\n", clan_id);
+ return false;
+ } else if (clan->search(clan_id) == NULL) {
+ script_pushint(st, false);
+ ShowError("buildin_clan_master: Received Id of a nonexistent Clan. Id: %d\n", clan_id);
+ return false;
+ }
+
+ nd->clan_id = clan_id;
+ clif->sc_load(&nd->bl, nd->bl.id, AREA, status->get_sc_icon(SC_CLAN_INFO), 0, clan_id, 0);
+
+ script_pushint(st, true);
+ return true;
+}
+
+static BUILDIN(airship_respond)
+{
+ struct map_session_data *sd = map->id2sd(st->rid);
+ int32 flag = script_getnum(st, 2);
+
+ if (sd == NULL)
+ return false;
+
+ if (flag < P_AIRSHIP_NONE || flag > P_AIRSHIP_ITEM_INVALID) {
+ ShowWarning("buildin_airship_respond: invalid flag %d has been given.", flag);
+ return false;
+ }
+
+ clif->PrivateAirshipResponse(sd, flag);
+ return true;
+}
+
+/**
+ * hateffect(EffectID, Enable_State)
+ */
+static BUILDIN(hateffect)
+{
+#if PACKETVER >= 20150422
+ struct map_session_data *sd = script_rid2sd(st);
+ int effectId, enabled = 0;
+ int i;
+
+ if (sd == NULL)
+ return false;
+
+ effectId = script_getnum(st, 2);
+ enabled = script_getnum(st, 3);
+
+ for (i = 0; i < VECTOR_LENGTH(sd->hatEffectId); ++i) {
+ if (VECTOR_INDEX(sd->hatEffectId, i) == effectId) {
+ if (enabled == 1) { // Already Enabled
+ return true;
+ } else { // Remove
+ VECTOR_ERASE(sd->hatEffectId, i);
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+ return true;
+ }
+ }
+ }
+
+ VECTOR_ENSURE(sd->hatEffectId, 1, 1);
+ VECTOR_PUSH(sd->hatEffectId, effectId);
+
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+#endif
+ return true;
+}
+
+static BUILDIN(openstylist)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+
+ if (sd == NULL)
+ return false;
+
+#if PACKETVER >= 20150128
+ clif->open_ui(sd, CZ_STYLIST_UI);
+#endif
+ return true;
+}
+
+static BUILDIN(msgtable)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+
+ const enum clif_messages msgId = script_getnum(st, 2);
+ if (script_hasdata(st, 3)) {
+ clif->msgtable_color(sd, msgId, script_getnum(st, 3));
+ } else {
+ clif->msgtable(sd, msgId);
+ }
+
+ return true;
+}
+
+static BUILDIN(msgtable2)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+
+ const enum clif_messages msgId = script_getnum(st, 2);
+ if (script_isstringtype(st, 3)) {
+ const char *value = script_getstr(st, 3);
+ if (script_hasdata(st, 4)) {
+ clif->msgtable_str_color(sd, msgId, value, script_getnum(st, 4));
+ } else {
+ clif->msgtable_str(sd, msgId, value);
+ }
+ } else {
+ const int value = script_getnum(st, 3);
+ clif->msgtable_num(sd, msgId, value);
+ }
+
+ return true;
+}
+
+// show/hide camera info
+static BUILDIN(camerainfo)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+
+ clif->camera_showWindow(sd);
+ return true;
+}
+
+// allow change some camera parameters
+static BUILDIN(changecamera)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+
+ enum send_target target = SELF;
+ if (script_hasdata(st, 5)) {
+ target = script_getnum(st, 5);
+ }
+ clif->camera_change(sd, (float)script_getnum(st, 2), (float)script_getnum(st, 3), (float)script_getnum(st, 4), target);
+ return true;
+}
+
+// update preview window to given item
+static BUILDIN(itempreview)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ clif->item_preview(sd, script_getnum(st, 2));
+ return true;
+}
+
+// insert or remove card into equipped item
+static BUILDIN(enchantitem)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ const int pos = script_getnum(st, 2);
+ if ((pos < EQI_ACC_L || pos > EQI_HAND_R) && pos != EQI_AMMO) {
+ ShowError("Wrong equip position: %d\n", pos);
+ script->reportfunc(st);
+ script->reportsrc(st);
+ script_pushint(st, false);
+ return true;
+ }
+ const int cardId = script_getnum(st, 4);
+ struct item_data *it = itemdb->exists(cardId);
+ if (it == NULL || it->type != IT_CARD) {
+ ShowError("Item id is not card or not exists: %d\n", cardId);
+ script->reportfunc(st);
+ script->reportsrc(st);
+ script_pushint(st, false);
+ return true;
+ }
+ const int n = sd->equip_index[pos];
+ if (n < 0) {
+ ShowError("Item in equipment slot %d is not equipped\n", pos);
+ script->reportfunc(st);
+ script->reportsrc(st);
+ script_pushint(st, false);
+ return true;
+ }
+ const int cardSlot = script_getnum(st, 3);
+ if (cardSlot < 0 || cardSlot >= MAX_SLOTS) {
+ ShowError("Wrong card slot %d. Must be in range 0-3.\n", cardSlot);
+ script->reportfunc(st);
+ script->reportsrc(st);
+ script_pushint(st, false);
+ return true;
+ }
+ const bool res = clif->enchant_equipment(sd, pc->equip_pos[pos], cardSlot, cardId);
+ if (res) {
+ logs->pick_pc(sd, LOG_TYPE_CARD, -1, &sd->status.inventory[n],sd->inventory_data[n]);
+ sd->status.inventory[n].card[cardSlot] = cardId;
+ logs->pick_pc(sd, LOG_TYPE_CARD, 1, &sd->status.inventory[n],sd->inventory_data[n]);
+ status_calc_pc(sd, SCO_NONE);
+ }
+ script_pushint(st, res);
+ return true;
+}
+
+// send ack to inventory expand request
+static BUILDIN(expandinventoryack)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ int itemId = 0;
+ if (script_hasdata(st, 3)) {
+ itemId = script_getnum(st, 3);
+ }
+ clif->inventoryExpandAck(sd, script_getnum(st, 2), itemId);
+ return true;
+}
+
+// send final ack to inventory expand request
+static BUILDIN(expandinventoryresult)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ clif->inventoryExpandResult(sd, script_getnum(st, 2));
+ return true;
+}
+
+// adjust player inventory size to given value positive or negative
+static BUILDIN(expandinventory)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ script_pushint(st, pc->expandInventory(sd, script_getnum(st, 2)));
+ return true;
+}
+
+// return current player inventory size
+static BUILDIN(getinventorysize)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ script_pushint(st, sd->status.inventorySize);
+ return true;
+}
+
+// force close roulette window if it opened
+static BUILDIN(closeroulette)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ clif->roulette_close(sd);
+ return true;
+}
+
+static BUILDIN(openrefineryui)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ if (battle_config.enable_refinery_ui == 0) {
+ script_pushint(st, 0);
+ return true;
+ }
+
+ clif->OpenRefineryUI(sd);
+ script_pushint(st, 1);
+ return true;
+}
+
+/**
+ * identify(<item id>)
+ * Identifies the first unidentified <item id> item on player's inventory.
+ * Returns -2 on error, -1 if no item to identify was found, identified idx otherwise.
+ */
+static BUILDIN(identify)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, -2);
+ return true;
+ }
+
+ int itemid = script_getnum(st, 2);
+ if (itemdb->exists(itemid) == NULL) {
+ ShowError("buildin_identify: Invalid item ID (%d)\n", itemid);
+ script_pushint(st, -2);
+ return true;
+ }
+
+ int idx = -1;
+ ARR_FIND(0, sd->status.inventorySize, idx, (sd->status.inventory[idx].nameid == itemid && sd->status.inventory[idx].identify == 0));
+
+ if (idx < 0 || idx >= sd->status.inventorySize) {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ sd->status.inventory[idx].identify = 1;
+ clif->item_identified(sd, idx, 0);
+ script_pushint(st, idx);
+
+ return true;
+}
+
+/**
+ * identifyidx(idx)
+ * Identifies item at idx.
+ * Returns true if item is identified, false otherwise.
+ */
+static BUILDIN(identifyidx)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+
+ if (sd == NULL) {
+ script_pushint(st, false);
+ return true;
+ }
+
+ int idx = script_getnum(st, 2);
+ if (idx < 0 || idx >= sd->status.inventorySize) {
+ ShowError("buildin_identifyidx: Invalid inventory index (%d), expected a value between 0 and %d\n", idx, sd->status.inventorySize);
+ script_pushint(st, false);
+ return true;
+ }
+
+ if (sd->status.inventory[idx].nameid <= 0 || sd->status.inventory[idx].identify != 0) {
+ script_pushint(st, false);
+ return true;
+ }
+
+ sd->status.inventory[idx].identify = 1;
+ clif->item_identified(sd, idx, 0);
+ script_pushint(st, true);
+
+ return true;
+}
+
+static BUILDIN(openlapineddukddakboxui)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ if (sd == NULL)
+ return false;
+ const int item_id = script_getnum(st, 2);
+ struct item_data *it = itemdb->exists(item_id);
+ if (it == NULL) {
+ ShowError("buildin_openlapineddukddakboxui: Item %d is not valid\n", item_id);
+ script->reportfunc(st);
+ script->reportsrc(st);
+ script_pushint(st, false);
+ return true;
+ }
+ clif->lapineDdukDdak_open(sd, item_id);
+ script_pushint(st, true);
+ return true;
+}
+
+// Reset 'Feeling' maps.
+BUILDIN(resetfeel)
+{
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 2))
+ sd = script->id2sd(st, script_getnum(st, 2));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd != NULL)
+ pc->resetfeel(sd);
+
+ return true;
+}
+
+// Reset hatred target marks.
+BUILDIN(resethate)
+{
+ struct map_session_data *sd;
+
+ if (script_hasdata(st, 2))
+ sd = script->id2sd(st, script_getnum(st, 2));
+ else
+ sd = script->rid2sd(st);
+
+ if (sd != NULL)
+ pc->resethate(sd);
+
+ return true;
+}
+
+/**
* Adds a built-in script function.
*
* @param buildin Script function data
@@ -20220,7 +26576,8 @@ BUILDIN(pcre_match) {
* (i.e. a plugin overriding a built-in function)
* @return Whether the function was successfully added.
*/
-bool script_add_builtin(const struct script_function *buildin, bool override) {
+static bool script_add_builtin(const struct script_function *buildin, bool override)
+{
int n = 0, offset = 0;
size_t slen;
if( !buildin ) {
@@ -20272,8 +26629,10 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n;
else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n;
else if( strcmp(buildin->name, "mes") == 0 ) script->buildin_mes_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "mesf") == 0 ) script->buildin_mesf_offset = script->buildin_count;
else if( strcmp(buildin->name, "select") == 0 ) script->buildin_select_offset = script->buildin_count;
else if( strcmp(buildin->name, "_") == 0 ) script->buildin_lang_macro_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "_$") == 0 ) script->buildin_lang_macro_fmtstring_offset = script->buildin_count;
offset = script->buildin_count;
@@ -20299,7 +26658,8 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
return true;
}
-bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated) {
+static bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated)
+{
struct script_function buildin;
buildin.name = name;
buildin.arg = args;
@@ -20308,7 +26668,7 @@ bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)
return script->add_builtin(&buildin, true);
}
-void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1)));
+static void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1)));
/**
* Run use script for item.
@@ -20317,14 +26677,15 @@ void script_run_use_script(struct map_session_data *sd, struct item_data *data,
* @param n item index in inventory. Must be correct and checked before.
* @param oid npc id. Can be also 0 or fake npc id.
*/
-void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid)
+static void script_run_use_script(struct map_session_data *sd, struct item_data *data, int oid)
{
+ nullpo_retv(data);
script->current_item_id = data->nameid;
script->run(data->script, 0, sd->bl.id, oid);
script->current_item_id = 0;
}
-void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2)));
+static void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2)));
/**
* Run item equip script for item.
@@ -20333,14 +26694,14 @@ void script_run_item_equip_script(struct map_session_data *sd, struct item_data
* @param data equipped item data. Must be correct and checked before.
* @param oid npc id. Can be also 0 or fake npc id.
*/
-void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid)
+static void script_run_item_equip_script(struct map_session_data *sd, struct item_data *data, int oid)
{
script->current_item_id = data->nameid;
script->run(data->equip_script, 0, sd->bl.id, oid);
script->current_item_id = 0;
}
-void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2)));
+static void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2)));
/**
* Run item unequip script for item.
@@ -20349,31 +26710,80 @@ void script_run_item_unequip_script(struct map_session_data *sd, struct item_dat
* @param data unequipped item data. Must be correct and checked before.
* @param oid npc id. Can be also 0 or fake npc id.
*/
-void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid)
+static void script_run_item_unequip_script(struct map_session_data *sd, struct item_data *data, int oid)
{
script->current_item_id = data->nameid;
script->run(data->unequip_script, 0, sd->bl.id, oid);
script->current_item_id = 0;
}
+static void script_run_item_rental_start_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull(1, 2)));
+
+/**
+ * Run item rental start script
+ * @param sd player session data. Must be correct and checked before.
+ * @param data rental item data. Must be correct and checked before.
+ * @param oid npc id. Can be also 0 or fake npc id.
+ **/
+static void script_run_item_rental_start_script(struct map_session_data *sd, struct item_data *data, int oid)
+{
+ script->current_item_id = data->nameid;
+ script->run(data->rental_start_script, 0, sd->bl.id, oid);
+ script->current_item_id = 0;
+}
+
+static void script_run_item_rental_end_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull(1, 2)));
+
+/**
+* Run item rental end script
+* @param sd player session data. Must be correct and checked before.
+* @param data rental item data. Must be correct and checked before.
+* @param oid npc id. Can be also 0 or fake npc id.
+**/
+static void script_run_item_rental_end_script(struct map_session_data *sd, struct item_data *data, int oid)
+{
+ script->current_item_id = data->nameid;
+ script->run(data->rental_end_script, 0, sd->bl.id, oid);
+ script->current_item_id = 0;
+}
+
+static void script_run_item_lapineddukddak_script(struct map_session_data *sd, struct item_data *data, int oid) __attribute__((nonnull (1, 2)));
+
+/**
+ * Run item lapineddukddak script for item.
+ *
+ * @param sd player session data. Must be correct and checked before.
+ * @param data unequipped item data. Must be correct and checked before.
+ * @param oid npc id. Can be also 0 or fake npc id.
+ */
+static void script_run_item_lapineddukddak_script(struct map_session_data *sd, struct item_data *data, int oid)
+{
+ script->current_item_id = data->nameid;
+ script->run(data->lapineddukddak->script, 0, sd->bl.id, oid);
+ script->current_item_id = 0;
+}
+
#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args, false }
#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args, false }
#define BUILDIN_DEF_DEPRECATED(x,args) { buildin_ ## x , #x , args, true }
#define BUILDIN_DEF2_DEPRECATED(x,x2,args) { buildin_ ## x , x2 , args, true }
-void script_parse_builtin(void) {
+static void script_parse_builtin(void)
+{
struct script_function BUILDIN[] = {
/* Commands for internal use by the script engine */
BUILDIN_DEF(__jump_zero,"il"),
BUILDIN_DEF(__setr,"rv?"),
// NPC interaction
- BUILDIN_DEF(mes,"s*"),
+ BUILDIN_DEF(mes, "?"),
+ BUILDIN_DEF(mesf, "s*"),
BUILDIN_DEF(next,""),
+ BUILDIN_DEF(mesclear,""),
BUILDIN_DEF(close,""),
BUILDIN_DEF(close2,""),
BUILDIN_DEF(menu,"sl*"),
BUILDIN_DEF(select,"s*"), //for future jA script compatibility
- BUILDIN_DEF(prompt,"s*"),
+ BUILDIN_DEF2(select, "prompt", "s*"),
//
BUILDIN_DEF(goto,"l"),
BUILDIN_DEF(callsub,"l*"),
@@ -20386,8 +26796,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(warp,"sii?"),
BUILDIN_DEF(areawarp,"siiiisii??"),
BUILDIN_DEF(warpchar,"siii"), // [LuzZza]
- BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X]
- BUILDIN_DEF(warpguild,"siii"), // [Fredzilla]
+ BUILDIN_DEF(warpparty,"siii???"), // [Fredzilla] [Paradox924X] [Jedzkie] [Dastgir]
+ BUILDIN_DEF(warpguild,"siii??"), // [Fredzilla]
BUILDIN_DEF(setlook,"ii"),
BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it
BUILDIN_DEF2(__setr,"set","rv"),
@@ -20395,6 +26805,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(cleararray,"rvi"),
BUILDIN_DEF(copyarray,"rri"),
BUILDIN_DEF(getarraysize,"r"),
+ BUILDIN_DEF(getarrayindex,"r"),
BUILDIN_DEF(deletearray,"r?"),
BUILDIN_DEF(getelementofarray,"ri"),
BUILDIN_DEF(getitem,"vi?"),
@@ -20403,8 +26814,10 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getnameditem,"vv"),
BUILDIN_DEF2(grouprandomitem,"groupranditem","i"),
BUILDIN_DEF(makeitem,"visii"),
+ BUILDIN_DEF(makeitem2,"viiiiiiii????"),
BUILDIN_DEF(delitem,"vi?"),
BUILDIN_DEF(delitem2,"viiiiiiii?"),
+ BUILDIN_DEF(delitemidx, "i??"),
BUILDIN_DEF2(enableitemuse,"enable_items",""),
BUILDIN_DEF2(disableitemuse,"disable_items",""),
BUILDIN_DEF(cutin,"si"),
@@ -20415,20 +26828,24 @@ void script_parse_builtin(void) {
BUILDIN_DEF(rand,"i?"),
BUILDIN_DEF(countitem,"v"),
BUILDIN_DEF(countitem2,"viiiiiii"),
+ BUILDIN_DEF(countnameditem,"v?"),
BUILDIN_DEF(checkweight,"vi*"),
BUILDIN_DEF(checkweight2,"rr"),
BUILDIN_DEF(readparam,"i?"),
+ BUILDIN_DEF(setparam,"ii?"),
BUILDIN_DEF(getcharid,"i?"),
- BUILDIN_DEF(getnpcid,"i?"),
+ BUILDIN_DEF(getnpcid, "?"),
BUILDIN_DEF(getpartyname,"i"),
BUILDIN_DEF(getpartymember,"i?"),
BUILDIN_DEF(getpartyleader,"i?"),
- BUILDIN_DEF(getguildname,"i"),
- BUILDIN_DEF(getguildmaster,"i"),
- BUILDIN_DEF(getguildmasterid,"i"),
+ BUILDIN_DEF_DEPRECATED(getguildname,"i"),
+ BUILDIN_DEF_DEPRECATED(getguildmaster,"i"),
+ BUILDIN_DEF_DEPRECATED(getguildmasterid,"i"),
BUILDIN_DEF(getguildmember,"i?"),
- BUILDIN_DEF(strcharinfo,"i"),
- BUILDIN_DEF(strnpcinfo,"i"),
+ BUILDIN_DEF(getguildinfo,"i?"),
+ BUILDIN_DEF(getguildonline, "i?"),
+ BUILDIN_DEF(strcharinfo,"i??"),
+ BUILDIN_DEF(strnpcinfo,"i??"),
BUILDIN_DEF(charid2rid,"i"),
BUILDIN_DEF(getequipid,"i"),
BUILDIN_DEF(getequipname,"i"),
@@ -20439,14 +26856,15 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getequipisequiped,"i"),
BUILDIN_DEF(getequipisenableref,"i"),
BUILDIN_DEF(getequipisidentify,"i"),
- BUILDIN_DEF(getequiprefinerycnt,"i"),
+ BUILDIN_DEF(getequiprefinerycnt,"i*"),
BUILDIN_DEF(getequipweaponlv,"i"),
- BUILDIN_DEF(getequippercentrefinery,"i"),
+ BUILDIN_DEF(getequippercentrefinery,"i?"),
BUILDIN_DEF(successrefitem,"i?"),
BUILDIN_DEF(failedrefitem,"i"),
BUILDIN_DEF(downrefitem,"i?"),
BUILDIN_DEF(statusup,"i"),
BUILDIN_DEF(statusup2,"ii"),
+ BUILDIN_DEF(needed_status_point, "ii"),
BUILDIN_DEF(bonus,"iv"),
BUILDIN_DEF2(bonus,"bonus2","ivi"),
BUILDIN_DEF2(bonus,"bonus3","ivii"),
@@ -20463,21 +26881,21 @@ void script_parse_builtin(void) {
BUILDIN_DEF(basicskillcheck,""),
BUILDIN_DEF(getgmlevel,""),
BUILDIN_DEF(setgroupid, "i?"),
- BUILDIN_DEF(getgroupid,""),
+ BUILDIN_DEF(getgroupid,"?"),
BUILDIN_DEF(end,""),
- BUILDIN_DEF(checkoption,"i"),
- BUILDIN_DEF(setoption,"i?"),
+ BUILDIN_DEF(checkoption,"i?"),
+ BUILDIN_DEF(setoption,"i??"),
BUILDIN_DEF(setcart,"?"),
BUILDIN_DEF(checkcart,""),
BUILDIN_DEF(setfalcon,"?"),
BUILDIN_DEF(checkfalcon,""),
- BUILDIN_DEF(setmount,"?"),
+ BUILDIN_DEF(setmount,"??"),
BUILDIN_DEF(checkmount,""),
BUILDIN_DEF(checkwug,""),
BUILDIN_DEF(savepoint,"sii"),
BUILDIN_DEF(gettimetick,"i"),
BUILDIN_DEF(gettime,"i"),
- BUILDIN_DEF(gettimestr,"si"),
+ BUILDIN_DEF(gettimestr, "si?"),
BUILDIN_DEF(openstorage,""),
BUILDIN_DEF(guildopenstorage,""),
BUILDIN_DEF(itemskill,"vi?"),
@@ -20488,12 +26906,15 @@ void script_parse_builtin(void) {
BUILDIN_DEF(areamonster,"siiiisii???"),
BUILDIN_DEF(killmonster,"ss?"),
BUILDIN_DEF(killmonsterall,"s?"),
+ BUILDIN_DEF(killmonstergid, "i"),
BUILDIN_DEF(clone,"siisi????"),
BUILDIN_DEF(doevent,"s"),
BUILDIN_DEF(donpcevent,"s"),
- BUILDIN_DEF(addtimer,"is"),
- BUILDIN_DEF(deltimer,"s"),
- BUILDIN_DEF(addtimercount,"si"),
+ BUILDIN_DEF(addtimer,"is?"),
+ BUILDIN_DEF(deltimer,"s?"),
+ BUILDIN_DEF(addtimercount,"si?"),
+ BUILDIN_DEF(gettimer,"i??"),
+ BUILDIN_DEF(getunits,"iri?????"),
BUILDIN_DEF(initnpctimer,"??"),
BUILDIN_DEF(stopnpctimer,"??"),
BUILDIN_DEF(startnpctimer,"??"),
@@ -20502,6 +26923,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest]
BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest]
BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex]
+ BUILDIN_DEF(mobattached, ""),
BUILDIN_DEF(announce,"si?????"),
BUILDIN_DEF(mapannounce,"ssi?????"),
BUILDIN_DEF(areaannounce,"siiiisi?????"),
@@ -20514,18 +26936,23 @@ void script_parse_builtin(void) {
BUILDIN_DEF(disablenpc,"s"),
BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"),
+ BUILDIN_DEF(cloakonnpc,"s?"),
+ BUILDIN_DEF(cloakoffnpc,"s?"),
BUILDIN_DEF(sc_start,"iii???"),
BUILDIN_DEF2(sc_start,"sc_start2","iiii???"),
BUILDIN_DEF2(sc_start,"sc_start4","iiiiii???"),
BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getstatus, "i?"),
BUILDIN_DEF(getscrate,"ii?"),
- BUILDIN_DEF(debugmes,"v"),
+ BUILDIN_DEF_DEPRECATED(debugmes,"v*"),
+ BUILDIN_DEF(consolemes,"iv*"),
BUILDIN_DEF2(catchpet,"pet","i"),
BUILDIN_DEF2(birthpet,"bpet",""),
BUILDIN_DEF(resetlvl,"i"),
BUILDIN_DEF(resetstatus,""),
BUILDIN_DEF(resetskill,""),
+ BUILDIN_DEF(resetfeel, "?"),
+ BUILDIN_DEF(resethate, "?"),
BUILDIN_DEF(skillpointcount,""),
BUILDIN_DEF(changebase,"i?"),
BUILDIN_DEF(changesex,""),
@@ -20542,6 +26969,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(isloggedin,"i?"),
BUILDIN_DEF(setmapflagnosave,"ssii"),
BUILDIN_DEF(getmapflag,"si"),
+ BUILDIN_DEF(getmapinfo,"i?"),
BUILDIN_DEF(setmapflag,"si?"),
BUILDIN_DEF(removemapflag,"si"),
BUILDIN_DEF(pvpon,"s"),
@@ -20578,8 +27006,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getcartinventorylist,""),
BUILDIN_DEF(getskilllist,""),
BUILDIN_DEF(clearitem,""),
- BUILDIN_DEF(classchange,"ii"),
- BUILDIN_DEF(misceffect,"i"),
+ BUILDIN_DEF(classchange,"ii?"),
+ BUILDIN_DEF_DEPRECATED(misceffect,"i"),
BUILDIN_DEF(playbgm,"s"),
BUILDIN_DEF(playbgmall,"s?????"),
BUILDIN_DEF(soundeffect,"si"),
@@ -20594,15 +27022,18 @@ void script_parse_builtin(void) {
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest]
BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris]
+ BUILDIN_DEF(specialeffect,"i???"), // npc skill effect [Valaris]
+ BUILDIN_DEF(specialeffectnum,"iii???"), // npc skill effect with num [4144]
+ BUILDIN_DEF(removespecialeffect,"i???"),
+ BUILDIN_DEF_DEPRECATED(specialeffect2,"i??"), // skill effect on players[Valaris]
BUILDIN_DEF(nude,""), // nude command [Valaris]
BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
BUILDIN_DEF(atcommand,"s"), // [MouseJstr]
BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr]
BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr]
BUILDIN_DEF(message,"vs"), // [MouseJstr]
- BUILDIN_DEF(npctalk,"s?"), // [Valaris]
+ BUILDIN_DEF(servicemessage, "si?"),
+ BUILDIN_DEF(npctalk,"s??"), // [Valaris][Murilo BiO]
BUILDIN_DEF(mobcount,"ss"),
BUILDIN_DEF(getlook,"i"),
BUILDIN_DEF(getsavepoint,"i"),
@@ -20614,11 +27045,11 @@ void script_parse_builtin(void) {
BUILDIN_DEF(setnpcdir,"*"), // [4144]
BUILDIN_DEF(getnpcclass,"?"), // [4144]
BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus]
- BUILDIN_DEF(checkoption1,"i"),
- BUILDIN_DEF(checkoption2,"i"),
+ BUILDIN_DEF(checkoption1,"i?"),
+ BUILDIN_DEF(checkoption2,"i?"),
BUILDIN_DEF(guildgetexp,"i"),
BUILDIN_DEF(guildchangegm,"is"),
- BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus]
+ BUILDIN_DEF(logmes,"s?"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus]
BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest]
BUILDIN_DEF(isnight,""), // check whether it is night time [Celest]
BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest]
@@ -20631,10 +27062,11 @@ void script_parse_builtin(void) {
BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr]
BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr]
BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr]
+ BUILDIN_DEF(dressroom,"?"),
BUILDIN_DEF(pcre_match,"ss"),
BUILDIN_DEF(dispbottom,"s?"), //added from jA [Lupus]
BUILDIN_DEF(getusersname,""),
- BUILDIN_DEF(recovery,""),
+ BUILDIN_DEF(recovery,"?????"),
BUILDIN_DEF(getpetinfo,"i"),
BUILDIN_DEF(gethominfo,"i"),
BUILDIN_DEF(getmercinfo,"i?"),
@@ -20644,6 +27076,12 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
BUILDIN_DEF(charat,"si"),
+ BUILDIN_DEF(isstr,"v"),
+ BUILDIN_DEF(getdatatype, "?"),
+ BUILDIN_DEF(data_to_string, "?"),
+ BUILDIN_DEF2(getd, "string_to_data", "?"),
+ BUILDIN_DEF(chr,"i"),
+ BUILDIN_DEF(ord,"s"),
BUILDIN_DEF(setchar,"ssi"),
BUILDIN_DEF(insertchar,"ssi"),
BUILDIN_DEF(delchar,"si"),
@@ -20662,24 +27100,29 @@ void script_parse_builtin(void) {
BUILDIN_DEF(setnpcdisplay,"sv??"),
BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine.
BUILDIN_DEF(strcmp,"ss"),
- BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info
+ BUILDIN_DEF(getiteminfo,"vi"), //[Lupus] returns Items Buy / sell Price, etc info
BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info
BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item
+ BUILDIN_DEF(getequippedoptioninfo, "i"),
+ BUILDIN_DEF(getequipoption, "iii"),
+ BUILDIN_DEF(setequipoption, "iiii"),
+ BUILDIN_DEF(getequipisenableopt, "i"),
// List of mathematics commands --->
BUILDIN_DEF(log10,"i"),
BUILDIN_DEF(sqrt,"i"), //[zBuffer]
- BUILDIN_DEF(pow,"ii"), //[zBuffer]
+ BUILDIN_DEF_DEPRECATED(pow,"ii"), //[zBuffer]
BUILDIN_DEF(distance,"iiii"), //[zBuffer]
// <--- List of mathematics commands
BUILDIN_DEF(min, "i*"),
BUILDIN_DEF(max, "i*"),
+ BUILDIN_DEF(cap_value, "iii"),
BUILDIN_DEF(md5,"s"),
BUILDIN_DEF(swap,"rr"),
// [zBuffer] List of dynamic var commands --->
BUILDIN_DEF(getd,"s"),
BUILDIN_DEF(setd,"sv"),
// <--- [zBuffer] List of dynamic var commands
- BUILDIN_DEF(petstat,"i"),
+ BUILDIN_DEF_DEPRECATED(petstat, "i"), // Deprecated 2019-03-11
BUILDIN_DEF(callshop,"s?"), // [Skotlex]
BUILDIN_DEF(npcshopitem,"sii*"), // [Lance]
BUILDIN_DEF(npcshopadditem,"sii*"),
@@ -20706,16 +27149,26 @@ void script_parse_builtin(void) {
BUILDIN_DEF(rid2name,"i"),
BUILDIN_DEF(pcfollow,"ii"),
BUILDIN_DEF(pcstopfollow,"i"),
- BUILDIN_DEF(pcblockmove,"ii"),
+ BUILDIN_DEF_DEPRECATED(pcblockmove,"ii"), // Deprecated 2018-05-04
+ BUILDIN_DEF(setpcblock, "ii?"),
+ BUILDIN_DEF(checkpcblock, "?"),
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
BUILDIN_DEF(getunittype,"i"),
+ /* Unit Data */
+ BUILDIN_DEF(setunitdata,"iiv??"),
+ BUILDIN_DEF(getunitdata,"ii?"),
+ BUILDIN_DEF(getunitname,"i"),
+ BUILDIN_DEF(setunitname,"is"),
+ BUILDIN_DEF(getunittitle,"i"),
+ BUILDIN_DEF(setunittitle,"is"),
BUILDIN_DEF(unitwalk,"ii?"),
+ BUILDIN_DEF(unitiswalking, "?"),
BUILDIN_DEF(unitkill,"i"),
BUILDIN_DEF(unitwarp,"isii"),
BUILDIN_DEF(unitattack,"iv?"),
BUILDIN_DEF(unitstop,"i"),
- BUILDIN_DEF(unittalk,"is"),
+ BUILDIN_DEF(unittalk,"is???"),
BUILDIN_DEF(unitemote,"ii"),
BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest]
BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest]
@@ -20724,6 +27177,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(sleep2,"i"),
BUILDIN_DEF(awake,"s"),
BUILDIN_DEF(getvariableofnpc,"rs"),
+ BUILDIN_DEF(getvariableofpc,"ri?"),
BUILDIN_DEF(warpportal,"iisii"),
BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
BUILDIN_DEF2(homunculus_mutate,"hommutate","?"),
@@ -20751,16 +27205,23 @@ void script_parse_builtin(void) {
BUILDIN_DEF(mercenary_set_faith,"ii"),
BUILDIN_DEF(readbook,"ii"),
BUILDIN_DEF(setfont,"i"),
+ BUILDIN_DEF(getfont, ""),
BUILDIN_DEF(areamobuseskill,"siiiiviiiii"),
BUILDIN_DEF(progressbar,"si"),
+ BUILDIN_DEF(progressbar_unit,"si?"),
BUILDIN_DEF(pushpc,"ii"),
BUILDIN_DEF(buyingstore,"i"),
BUILDIN_DEF(searchstores,"ii"),
BUILDIN_DEF(showdigit,"i?"),
+ BUILDIN_DEF(msgtable, "i?"),
+ BUILDIN_DEF(msgtable2, "iv?"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
BUILDIN_DEF(agitcheck2,""),
+ // Achievements [Smokexyz/Hercules]
+ BUILDIN_DEF(achievement_progress, "iiii?"),
+ BUILDIN_DEF(achievement_iscompleted, "i?"),
// BattleGround
BUILDIN_DEF(waitingroom2bg,"siiss?"),
BUILDIN_DEF(waitingroom2bg_single,"isiis"),
@@ -20819,7 +27280,10 @@ void script_parse_builtin(void) {
**/
BUILDIN_DEF(bindatcmd, "ss???"),
BUILDIN_DEF(unbindatcmd, "s"),
- BUILDIN_DEF(useatcmd, "s"),
+ BUILDIN_DEF_DEPRECATED(useatcmd, "s"),
+ BUILDIN_DEF(has_permission, "v?"),
+ BUILDIN_DEF(can_use_command, "s?"),
+ BUILDIN_DEF(add_group_command, "siii"),
/**
* Item bound [Xantara] [Akinari] [Mhalicot/Hercules]
@@ -20830,8 +27294,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(checkbound, "i???????"),
//Quest Log System [Inkfish]
- BUILDIN_DEF(questinfo, "ii??"),
- BUILDIN_DEF(setquest, "i"),
+ BUILDIN_DEF(questinfo, "i?"),
+ BUILDIN_DEF(setquestinfo, "i???"),
+ BUILDIN_DEF(setquest, "i?"),
BUILDIN_DEF(erasequest, "i?"),
BUILDIN_DEF(completequest, "i?"),
BUILDIN_DEF(questprogress, "i?"),
@@ -20868,17 +27333,63 @@ void script_parse_builtin(void) {
/* New Shop Support */
BUILDIN_DEF(openshop,"?"),
- BUILDIN_DEF(sellitem,"i??"),
- BUILDIN_DEF(stopselling,"i"),
+ BUILDIN_DEF(sellitem, "i???*"),
+ BUILDIN_DEF(sellitemcurrency, "ii?"),
+ BUILDIN_DEF(startsellitem, "iii"),
+ BUILDIN_DEF(endsellitem, ""),
+ BUILDIN_DEF(stopselling,"i??"),
BUILDIN_DEF(setcurrency,"i?"),
BUILDIN_DEF(tradertype,"i"),
BUILDIN_DEF(purchaseok,""),
BUILDIN_DEF(shopcount, "i"),
+ /* Navigation */
+ BUILDIN_DEF(navigateto, "s??????"),
+
+ /* Clan System */
+ BUILDIN_DEF(clan_join,"i?"),
+ BUILDIN_DEF(clan_leave,"?"),
+ BUILDIN_DEF(clan_master,"i"),
+
BUILDIN_DEF(channelmes, "ss"),
- BUILDIN_DEF(showscript, "s?"),
+ BUILDIN_DEF(addchannelhandler, "ss"),
+ BUILDIN_DEF(removechannelhandler, "ss"),
+ BUILDIN_DEF(showscript, "s??"),
BUILDIN_DEF(mergeitem,""),
+ BUILDIN_DEF(getcalendartime, "ii??"),
+
+ // -- RoDEX
+ BUILDIN_DEF(rodex_sendmail, "isss???????????"),
+ BUILDIN_DEF2(rodex_sendmail, "rodex_sendmail_acc", "isss???????????"),
+ BUILDIN_DEF(rodex_sendmail2, "isss?????????????????????????????????????????"),
+ BUILDIN_DEF2(rodex_sendmail2, "rodex_sendmail_acc2", "isss?????????????????????????????????????????"),
+ BUILDIN_DEF(airship_respond, "i"),
+ BUILDIN_DEF(openstylist,""),
BUILDIN_DEF(_,"s"),
+ BUILDIN_DEF2(_, "_$", "s"),
+
+ // -- HatEffect
+ BUILDIN_DEF(hateffect, "ii"),
+
+ // camera
+ BUILDIN_DEF(camerainfo, ""),
+ BUILDIN_DEF(changecamera, "iii?"),
+
+ BUILDIN_DEF(itempreview, "i"),
+ BUILDIN_DEF(enchantitem, "iii"),
+ BUILDIN_DEF(expandinventoryack, "i?"),
+ BUILDIN_DEF(expandinventoryresult, "i"),
+ BUILDIN_DEF(expandinventory, "i"),
+ BUILDIN_DEF(getinventorysize, ""),
+
+ BUILDIN_DEF(closeroulette, ""),
+ BUILDIN_DEF(openrefineryui, ""),
+ BUILDIN_DEF(setfavoriteitemidx, "ii"),
+ BUILDIN_DEF(autofavoriteitem, "ii"),
+
+ BUILDIN_DEF(identify, "i"),
+ BUILDIN_DEF(identifyidx, "i"),
+ BUILDIN_DEF(openlapineddukddakboxui, "i"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
@@ -20890,7 +27401,8 @@ void script_parse_builtin(void) {
#undef BUILDIN_DEF
#undef BUILDIN_DEF2
-void script_label_add(int key, int pos) {
+static void script_label_add(int key, int pos)
+{
int idx = script->label_count;
if( script->labels_size == script->label_count ) {
@@ -20906,7 +27418,7 @@ void script_label_add(int key, int pos) {
/**
* Sets source-end constants for scripts to play with
**/
-void script_hardcoded_constants(void)
+static void script_hardcoded_constants(void)
{
script->constdb_comment("Boolean");
script->set_constant("true", 1, false, false);
@@ -20917,12 +27429,20 @@ void script_hardcoded_constants(void)
script->set_constant("MAX_LEVEL",MAX_LEVEL,false, false);
script->set_constant("MAX_STORAGE",MAX_STORAGE,false, false);
script->set_constant("MAX_GUILD_STORAGE",MAX_GUILD_STORAGE,false, false);
- script->set_constant("MAX_CART",MAX_INVENTORY,false, false);
+ script->set_constant("MAX_CART", MAX_CART, false, false);
script->set_constant("MAX_INVENTORY",MAX_INVENTORY,false, false);
+ script->set_constant("FIXED_INVENTORY_SIZE", FIXED_INVENTORY_SIZE, false, false);
script->set_constant("MAX_ZENY",MAX_ZENY,false, false);
+ script->set_constant("MAX_BANK_ZENY", MAX_BANK_ZENY, false, false);
script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false, false);
script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false, false);
script->set_constant("MAX_REFINE",MAX_REFINE,false, false);
+ script->set_constant("MAX_ITEM_ID",MAX_ITEM_ID,false, false);
+ script->set_constant("MAX_MENU_OPTIONS", MAX_MENU_OPTIONS, false, false);
+ script->set_constant("MAX_MENU_LENGTH", MAX_MENU_LENGTH, false, false);
+ script->set_constant("MOB_CLONE_START", MOB_CLONE_START, false, false);
+ script->set_constant("MOB_CLONE_END", MOB_CLONE_END, false, false);
+ script->set_constant("MAX_NPC_PER_MAP", MAX_NPC_PER_MAP, false, false);
script->constdb_comment("status options");
script->set_constant("Option_Nothing",OPTION_NOTHING,false, false);
@@ -20949,6 +27469,7 @@ void script_hardcoded_constants(void)
script->set_constant("Option_Dragon5",OPTION_DRAGON5,false, false);
script->set_constant("Option_Hanbok",OPTION_HANBOK,false, false);
script->set_constant("Option_Oktoberfest",OPTION_OKTOBERFEST,false, false);
+ script->set_constant("Option_Summer2", OPTION_SUMMER2, false, false);
script->constdb_comment("status option compounds");
script->set_constant("Option_Dragon",OPTION_DRAGON,false, false);
@@ -21026,6 +27547,483 @@ void script_hardcoded_constants(void)
script->set_constant("EQP_SHADOW_SHOES", EQP_SHADOW_SHOES, false, false);
script->set_constant("EQP_SHADOW_ACC_R", EQP_SHADOW_ACC_R, false, false);
script->set_constant("EQP_SHADOW_ACC_L", EQP_SHADOW_ACC_L, false, false);
+ // Synonyms and combined values
+ script->set_constant("EQP_WEAPON", EQP_WEAPON, false, false);
+ script->set_constant("EQP_SHIELD", EQP_SHIELD, false, false);
+ script->set_constant("EQP_ARMS", EQP_ARMS, false, false);
+ script->set_constant("EQP_HELM", EQP_HELM, false, false);
+ script->set_constant("EQP_ACC", EQP_ACC, false, false);
+ script->set_constant("EQP_COSTUME", EQP_COSTUME, false, false);
+ script->set_constant("EQP_SHADOW_ACC", EQP_SHADOW_ACC, false, false);
+ script->set_constant("EQP_SHADOW_ARMS", EQP_SHADOW_ARMS, false, false);
+
+ script->constdb_comment("Item Option Types");
+ script->set_constant("IT_OPT_INDEX", IT_OPT_INDEX, false, false);
+ script->set_constant("IT_OPT_VALUE", IT_OPT_VALUE, false, false);
+ script->set_constant("IT_OPT_PARAM", IT_OPT_PARAM, false, false);
+
+ script->constdb_comment("Maximum Item Options");
+ script->set_constant("MAX_ITEM_OPTIONS", MAX_ITEM_OPTIONS, false, false);
+
+ script->constdb_comment("Navigation constants, use with *navigateto*");
+ script->set_constant("NAV_NONE", NAV_NONE, false, false);
+ script->set_constant("NAV_AIRSHIP_ONLY", NAV_AIRSHIP_ONLY, false, false);
+ script->set_constant("NAV_SCROLL_ONLY", NAV_SCROLL_ONLY, false, false);
+ script->set_constant("NAV_AIRSHIP_AND_SCROLL", NAV_AIRSHIP_AND_SCROLL, false, false);
+ script->set_constant("NAV_KAFRA_ONLY", NAV_KAFRA_ONLY, false, false);
+ script->set_constant("NAV_KAFRA_AND_AIRSHIP", NAV_KAFRA_AND_AIRSHIP, false, false);
+ script->set_constant("NAV_KAFRA_AND_SCROLL", NAV_KAFRA_AND_SCROLL, false, false);
+ script->set_constant("NAV_ALL", NAV_ALL, false, false);
+
+ script->constdb_comment("BL types");
+ script->set_constant("BL_PC",BL_PC,false, false);
+ script->set_constant("BL_MOB",BL_MOB,false, false);
+ script->set_constant("BL_PET",BL_PET,false, false);
+ script->set_constant("BL_HOM",BL_HOM,false, false);
+ script->set_constant("BL_MER",BL_MER,false, false);
+ script->set_constant("BL_ITEM",BL_ITEM,false, false);
+ script->set_constant("BL_SKILL",BL_SKILL,false, false);
+ script->set_constant("BL_NPC",BL_NPC,false, false);
+ script->set_constant("BL_CHAT",BL_CHAT,false, false);
+ script->set_constant("BL_ELEM",BL_ELEM,false, false);
+ script->set_constant("BL_CHAR",BL_CHAR,false, false);
+ script->set_constant("BL_ALL",BL_ALL,false, false);
+
+ script->constdb_comment("Refine Chance Types");
+ script->set_constant("REFINE_CHANCE_TYPE_NORMAL", REFINE_CHANCE_TYPE_NORMAL, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_ENRICHED", REFINE_CHANCE_TYPE_ENRICHED, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_E_NORMAL", REFINE_CHANCE_TYPE_E_NORMAL, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_E_ENRICHED", REFINE_CHANCE_TYPE_E_ENRICHED, false, false);
+
+ script->constdb_comment("Player permissions");
+ script->set_constant("PERM_TRADE", PC_PERM_TRADE, false, false);
+ script->set_constant("PERM_PARTY", PC_PERM_PARTY, false, false);
+ script->set_constant("PERM_ALL_SKILL", PC_PERM_ALL_SKILL, false, false);
+ script->set_constant("PERM_USE_ALL_EQUIPMENT", PC_PERM_USE_ALL_EQUIPMENT, false, false);
+ script->set_constant("PERM_SKILL_UNCONDITIONAL", PC_PERM_SKILL_UNCONDITIONAL, false, false);
+ script->set_constant("PERM_JOIN_ALL_CHAT", PC_PERM_JOIN_ALL_CHAT, false, false);
+ script->set_constant("PERM_NO_CHAT_KICK", PC_PERM_NO_CHAT_KICK, false, false);
+ script->set_constant("PERM_HIDE_SESSION", PC_PERM_HIDE_SESSION, false, false);
+ script->set_constant("PERM_RECEIVE_HACK_INFO", PC_PERM_RECEIVE_HACK_INFO, false, false);
+ script->set_constant("PERM_WARP_ANYWHERE", PC_PERM_WARP_ANYWHERE, false, false);
+ script->set_constant("PERM_VIEW_HPMETER", PC_PERM_VIEW_HPMETER, false, false);
+ script->set_constant("PERM_VIEW_EQUIPMENT", PC_PERM_VIEW_EQUIPMENT, false, false);
+ script->set_constant("PERM_USE_CHECK", PC_PERM_USE_CHECK, false, false);
+ script->set_constant("PERM_USE_CHANGEMAPTYPE", PC_PERM_USE_CHANGEMAPTYPE, false, false);
+ script->set_constant("PERM_USE_ALL_COMMANDS", PC_PERM_USE_ALL_COMMANDS, false, false);
+ script->set_constant("PERM_RECEIVE_REQUESTS", PC_PERM_RECEIVE_REQUESTS, false, false);
+ script->set_constant("PERM_SHOW_BOSS", PC_PERM_SHOW_BOSS, false, false);
+ script->set_constant("PERM_DISABLE_PVM", PC_PERM_DISABLE_PVM, false, false);
+ script->set_constant("PERM_DISABLE_PVP", PC_PERM_DISABLE_PVP, false, false);
+ script->set_constant("PERM_DISABLE_CMD_DEAD", PC_PERM_DISABLE_CMD_DEAD, false, false);
+ script->set_constant("PERM_HCHSYS_ADMIN", PC_PERM_HCHSYS_ADMIN, false, false);
+ script->set_constant("PERM_TRADE_BOUND", PC_PERM_TRADE_BOUND, false, false);
+ script->set_constant("PERM_DISABLE_PICK_UP", PC_PERM_DISABLE_PICK_UP, false, false);
+ script->set_constant("PERM_DISABLE_STORE", PC_PERM_DISABLE_STORE, false, false);
+ script->set_constant("PERM_DISABLE_EXP", PC_PERM_DISABLE_EXP, false, false);
+ script->set_constant("PERM_DISABLE_SKILL_USAGE", PC_PERM_DISABLE_SKILL_USAGE, false, false);
+ script->set_constant("PERM_BYPASS_NOSTORAGE", PC_PERM_BYPASS_NOSTORAGE, false, false);
+
+ script->constdb_comment("Data types");
+ script->set_constant("DATATYPE_NIL", DATATYPE_NIL, false, false);
+ script->set_constant("DATATYPE_STR", DATATYPE_STR, false, false);
+ script->set_constant("DATATYPE_INT", DATATYPE_INT, false, false);
+ script->set_constant("DATATYPE_CONST", DATATYPE_CONST, false, false);
+ script->set_constant("DATATYPE_PARAM", DATATYPE_PARAM, false, false);
+ script->set_constant("DATATYPE_VAR", DATATYPE_VAR, false, false);
+ script->set_constant("DATATYPE_LABEL", DATATYPE_LABEL, false, false);
+
+ script->constdb_comment("Logmes types");
+ script->set_constant("LOGMES_NPC", LOGMES_NPC, false, false);
+ script->set_constant("LOGMES_ATCOMMAND", LOGMES_ATCOMMAND, false, false);
+
+ script->constdb_comment("Item Subtypes (Weapon types)");
+ script->set_constant("W_FIST", W_FIST, false, false);
+ script->set_constant("W_DAGGER", W_DAGGER, false, false);
+ script->set_constant("W_1HSWORD", W_1HSWORD, false, false);
+ script->set_constant("W_2HSWORD", W_2HSWORD, false, false);
+ script->set_constant("W_1HSPEAR", W_1HSPEAR, false, false);
+ script->set_constant("W_2HSPEAR", W_2HSPEAR, false, false);
+ script->set_constant("W_1HAXE", W_1HAXE, false, false);
+ script->set_constant("W_2HAXE", W_2HAXE, false, false);
+ script->set_constant("W_MACE", W_MACE, false, false);
+ script->set_constant("W_2HMACE", W_2HMACE, false, false);
+ script->set_constant("W_STAFF", W_STAFF, false, false);
+ script->set_constant("W_BOW", W_BOW, false, false);
+ script->set_constant("W_KNUCKLE", W_KNUCKLE, false, false);
+ script->set_constant("W_MUSICAL", W_MUSICAL, false, false);
+ script->set_constant("W_WHIP", W_WHIP, false, false);
+ script->set_constant("W_BOOK", W_BOOK, false, false);
+ script->set_constant("W_KATAR", W_KATAR, false, false);
+ script->set_constant("W_REVOLVER", W_REVOLVER, false, false);
+ script->set_constant("W_RIFLE", W_RIFLE, false, false);
+ script->set_constant("W_GATLING", W_GATLING, false, false);
+ script->set_constant("W_SHOTGUN", W_SHOTGUN, false, false);
+ script->set_constant("W_GRENADE", W_GRENADE, false, false);
+ script->set_constant("W_HUUMA", W_HUUMA, false, false);
+ script->set_constant("W_2HSTAFF", W_2HSTAFF, false, false);
+
+ script->constdb_comment("Item Subtypes (Ammunition types)");
+ script->set_constant("A_ARROW", A_ARROW, false, false);
+ script->set_constant("A_DAGGER", A_DAGGER, false, false);
+ script->set_constant("A_BULLET", A_BULLET, false, false);
+ script->set_constant("A_SHELL", A_SHELL, false, false);
+ script->set_constant("A_GRENADE", A_GRENADE, false, false);
+ script->set_constant("A_SHURIKEN", A_SHURIKEN, false, false);
+ script->set_constant("A_KUNAI", A_KUNAI, false, false);
+ script->set_constant("A_CANNONBALL", A_CANNONBALL, false, false);
+ script->set_constant("A_THROWWEAPON", A_THROWWEAPON, false, false);
+
+ script->constdb_comment("Item Upper Masks");
+ script->set_constant("ITEMUPPER_NONE", ITEMUPPER_NONE, false, false);
+ script->set_constant("ITEMUPPER_NORMAL", ITEMUPPER_NORMAL, false, false);
+ script->set_constant("ITEMUPPER_UPPER", ITEMUPPER_UPPER, false, false);
+ script->set_constant("ITEMUPPER_BABY", ITEMUPPER_BABY, false, false);
+ script->set_constant("ITEMUPPER_THIRD", ITEMUPPER_THIRD, false, false);
+ script->set_constant("ITEMUPPER_THIRDUPPER", ITEMUPPER_THIRDUPPER, false, false);
+ script->set_constant("ITEMUPPER_THIRDBABY", ITEMUPPER_THIRDBABY, false, false);
+ script->set_constant("ITEMUPPER_ALL", ITEMUPPER_ALL, false, false);
+
+ script->constdb_comment("dressroom modes");
+ script->set_constant("DRESSROOM_OPEN", DRESSROOM_OPEN, false, false);
+ script->set_constant("DRESSROOM_CLOSE", DRESSROOM_CLOSE, false, false);
+
+ script->constdb_comment("getmapinfo options");
+ script->set_constant("MAPINFO_NAME", MAPINFO_NAME, false, false);
+ script->set_constant("MAPINFO_ID", MAPINFO_ID, false, false);
+ script->set_constant("MAPINFO_SIZE_X", MAPINFO_SIZE_X, false, false);
+ script->set_constant("MAPINFO_SIZE_Y", MAPINFO_SIZE_Y, false, false);
+ script->set_constant("MAPINFO_ZONE", MAPINFO_ZONE, false, false);
+ script->set_constant("MAPINFO_NPC_COUNT", MAPINFO_NPC_COUNT, false, false);
+
+ script->constdb_comment("consolemes options");
+ script->set_constant("CONSOLEMES_DEBUG", CONSOLEMES_DEBUG, false, false);
+ script->set_constant("CONSOLEMES_ERROR", CONSOLEMES_ERROR, false, false);
+ script->set_constant("CONSOLEMES_WARNING", CONSOLEMES_WARNING, false, false);
+ script->set_constant("CONSOLEMES_INFO", CONSOLEMES_INFO, false, false);
+ script->set_constant("CONSOLEMES_STATUS", CONSOLEMES_STATUS, false, false);
+ script->set_constant("CONSOLEMES_NOTICE", CONSOLEMES_NOTICE, false, false);
+
+ script->constdb_comment("set/getiteminfo options");
+ script->set_constant("ITEMINFO_BUYPRICE", ITEMINFO_BUYPRICE, false, false);
+ script->set_constant("ITEMINFO_SELLPRICE", ITEMINFO_SELLPRICE, false, false);
+ script->set_constant("ITEMINFO_TYPE", ITEMINFO_TYPE, false, false);
+ script->set_constant("ITEMINFO_MAXCHANCE", ITEMINFO_MAXCHANCE, false, false);
+ script->set_constant("ITEMINFO_SEX", ITEMINFO_SEX, false, false);
+ script->set_constant("ITEMINFO_LOC", ITEMINFO_LOC, false, false);
+ script->set_constant("ITEMINFO_WEIGHT", ITEMINFO_WEIGHT, false, false);
+ script->set_constant("ITEMINFO_ATK", ITEMINFO_ATK, false, false);
+ script->set_constant("ITEMINFO_DEF", ITEMINFO_DEF, false, false);
+ script->set_constant("ITEMINFO_RANGE", ITEMINFO_RANGE, false, false);
+ script->set_constant("ITEMINFO_SLOTS", ITEMINFO_SLOTS, false, false);
+ script->set_constant("ITEMINFO_SUBTYPE", ITEMINFO_SUBTYPE, false, false);
+ script->set_constant("ITEMINFO_ELV", ITEMINFO_ELV, false, false);
+ script->set_constant("ITEMINFO_WLV", ITEMINFO_WLV, false, false);
+ script->set_constant("ITEMINFO_VIEWID", ITEMINFO_VIEWID, false, false);
+ script->set_constant("ITEMINFO_MATK", ITEMINFO_MATK, false, false);
+ script->set_constant("ITEMINFO_VIEWSPRITE", ITEMINFO_VIEWSPRITE, false, false);
+ script->set_constant("ITEMINFO_TRADE", ITEMINFO_TRADE, false, false);
+ script->set_constant("ITEMINFO_ELV_MAX", ITEMINFO_ELV_MAX, false, false);
+ script->set_constant("ITEMINFO_DROPEFFECT_MODE", ITEMINFO_DROPEFFECT_MODE, false, false);
+ script->set_constant("ITEMINFO_DELAY", ITEMINFO_DELAY, false, false);
+ script->set_constant("ITEMINFO_CLASS_BASE_1", ITEMINFO_CLASS_BASE_1, false, false);
+ script->set_constant("ITEMINFO_CLASS_BASE_2", ITEMINFO_CLASS_BASE_2, false, false);
+ script->set_constant("ITEMINFO_CLASS_BASE_3", ITEMINFO_CLASS_BASE_3, false, false);
+ script->set_constant("ITEMINFO_CLASS_UPPER", ITEMINFO_CLASS_UPPER, false, false);
+ script->set_constant("ITEMINFO_FLAG_NO_REFINE", ITEMINFO_FLAG_NO_REFINE, false, false);
+ script->set_constant("ITEMINFO_FLAG_DELAY_CONSUME", ITEMINFO_FLAG_DELAY_CONSUME, false, false);
+ script->set_constant("ITEMINFO_FLAG_AUTOEQUIP", ITEMINFO_FLAG_AUTOEQUIP, false, false);
+ script->set_constant("ITEMINFO_FLAG_AUTO_FAVORITE", ITEMINFO_FLAG_AUTO_FAVORITE, false, false);
+ script->set_constant("ITEMINFO_FLAG_BUYINGSTORE", ITEMINFO_FLAG_BUYINGSTORE, false, false);
+ script->set_constant("ITEMINFO_FLAG_BINDONEQUIP", ITEMINFO_FLAG_BINDONEQUIP, false, false);
+ script->set_constant("ITEMINFO_FLAG_KEEPAFTERUSE", ITEMINFO_FLAG_KEEPAFTERUSE, false, false);
+ script->set_constant("ITEMINFO_FLAG_FORCE_SERIAL", ITEMINFO_FLAG_FORCE_SERIAL, false, false);
+ script->set_constant("ITEMINFO_FLAG_NO_OPTIONS", ITEMINFO_FLAG_NO_OPTIONS, false, false);
+ script->set_constant("ITEMINFO_FLAG_DROP_ANNOUNCE", ITEMINFO_FLAG_DROP_ANNOUNCE, false, false);
+ script->set_constant("ITEMINFO_FLAG_SHOWDROPEFFECT", ITEMINFO_FLAG_SHOWDROPEFFECT, false, false);
+ script->set_constant("ITEMINFO_STACK_AMOUNT", ITEMINFO_STACK_AMOUNT, false, false);
+ script->set_constant("ITEMINFO_STACK_FLAG", ITEMINFO_STACK_FLAG, false, false);
+ script->set_constant("ITEMINFO_ITEM_USAGE_FLAG", ITEMINFO_ITEM_USAGE_FLAG, false, false);
+ script->set_constant("ITEMINFO_ITEM_USAGE_OVERRIDE", ITEMINFO_ITEM_USAGE_OVERRIDE, false, false);
+ script->set_constant("ITEMINFO_GM_LV_TRADE_OVERRIDE", ITEMINFO_GM_LV_TRADE_OVERRIDE, false, false);
+ script->set_constant("ITEMINFO_ID", ITEMINFO_ID, false, false);
+ script->set_constant("ITEMINFO_AEGISNAME", ITEMINFO_AEGISNAME, false, false);
+ script->set_constant("ITEMINFO_NAME", ITEMINFO_NAME, false, false);
+
+ script->constdb_comment("getmercinfo options");
+ script->set_constant("MERCINFO_ID,", MERCINFO_ID, false, false);
+ script->set_constant("MERCINFO_CLASS", MERCINFO_CLASS, false, false);
+ script->set_constant("MERCINFO_NAME", MERCINFO_NAME, false, false);
+ script->set_constant("MERCINFO_FAITH", MERCINFO_FAITH, false, false);
+ script->set_constant("MERCINFO_CALLS", MERCINFO_CALLS, false, false);
+ script->set_constant("MERCINFO_KILLCOUNT", MERCINFO_KILLCOUNT, false, false);
+ script->set_constant("MERCINFO_LIFETIME", MERCINFO_LIFETIME, false, false);
+ script->set_constant("MERCINFO_LEVEL", MERCINFO_LEVEL, false, false);
+ script->set_constant("MERCINFO_GID", MERCINFO_GID, false, false);
+
+ script->constdb_comment("getpetinfo options");
+ script->set_constant("PETINFO_ID", PETINFO_ID, false, false);
+ script->set_constant("PETINFO_CLASS", PETINFO_CLASS, false, false);
+ script->set_constant("PETINFO_NAME", PETINFO_NAME, false, false);
+ script->set_constant("PETINFO_INTIMACY", PETINFO_INTIMACY, false, false);
+ script->set_constant("PETINFO_HUNGRY", PETINFO_HUNGRY, false, false);
+ script->set_constant("PETINFO_RENAME", PETINFO_RENAME, false, false);
+ script->set_constant("PETINFO_GID", PETINFO_GID, false, false);
+ script->set_constant("PETINFO_EGGITEM", PETINFO_EGGITEM, false, false);
+ script->set_constant("PETINFO_FOODITEM", PETINFO_FOODITEM, false, false);
+ script->set_constant("PETINFO_ACCESSORYITEM", PETINFO_ACCESSORYITEM, false, false);
+ script->set_constant("PETINFO_ACCESSORYFLAG", PETINFO_ACCESSORYFLAG, false, false);
+ script->set_constant("PETINFO_EVO_EGGID", PETINFO_EVO_EGGID, false, false);
+ script->set_constant("PETINFO_AUTOFEED", PETINFO_AUTOFEED, false, false);
+
+ script->constdb_comment("Pet hunger levels");
+ script->set_constant("PET_HUNGER_STARVING", PET_HUNGER_STARVING, false, false);
+ script->set_constant("PET_HUNGER_VERY_HUNGRY", PET_HUNGER_VERY_HUNGRY, false, false);
+ script->set_constant("PET_HUNGER_HUNGRY", PET_HUNGER_HUNGRY, false, false);
+ script->set_constant("PET_HUNGER_NEUTRAL", PET_HUNGER_NEUTRAL, false, false);
+ script->set_constant("PET_HUNGER_SATISFIED", PET_HUNGER_SATISFIED, false, false);
+ script->set_constant("PET_HUNGER_STUFFED", PET_HUNGER_STUFFED, false, false);
+
+ script->constdb_comment("Pet intimacy levels");
+ script->set_constant("PET_INTIMACY_NONE", PET_INTIMACY_NONE, false, false);
+ script->set_constant("PET_INTIMACY_AWKWARD", PET_INTIMACY_AWKWARD, false, false);
+ script->set_constant("PET_INTIMACY_SHY", PET_INTIMACY_SHY, false, false);
+ script->set_constant("PET_INTIMACY_NEUTRAL", PET_INTIMACY_NEUTRAL, false, false);
+ script->set_constant("PET_INTIMACY_CORDIAL", PET_INTIMACY_CORDIAL, false, false);
+ script->set_constant("PET_INTIMACY_LOYAL", PET_INTIMACY_LOYAL, false, false);
+ script->set_constant("PET_INTIMACY_MAX", PET_INTIMACY_MAX, false, false);
+
+ script->constdb_comment("monster skill states");
+ script->set_constant("MSS_ANY", MSS_ANY, false, false);
+ script->set_constant("MSS_IDLE", MSS_IDLE, false, false);
+ script->set_constant("MSS_WALK", MSS_WALK, false, false);
+ script->set_constant("MSS_LOOT", MSS_LOOT, false, false);
+ script->set_constant("MSS_DEAD", MSS_DEAD, false, false);
+ script->set_constant("MSS_BERSERK", MSS_BERSERK, false, false);
+ script->set_constant("MSS_ANGRY", MSS_ANGRY, false, false);
+ script->set_constant("MSS_RUSH", MSS_RUSH, false, false);
+ script->set_constant("MSS_FOLLOW", MSS_FOLLOW, false, false);
+ script->set_constant("MSS_ANYTARGET", MSS_ANYTARGET, false, false);
+
+ script->constdb_comment("monster skill conditions");
+ script->set_constant("MSC_ANY", -1, false, false);
+ script->set_constant("MSC_ALWAYS", MSC_ALWAYS, false, false);
+ script->set_constant("MSC_MYHPLTMAXRATE", MSC_MYHPLTMAXRATE, false, false);
+ script->set_constant("MSC_MYHPINRATE", MSC_MYHPINRATE, false, false);
+ script->set_constant("MSC_FRIENDHPLTMAXRATE", MSC_FRIENDHPLTMAXRATE, false, false);
+ script->set_constant("MSC_FRIENDHPINRATE", MSC_FRIENDHPINRATE, false, false);
+ script->set_constant("MSC_MYSTATUSON", MSC_MYSTATUSON, false, false);
+ script->set_constant("MSC_MYSTATUSOFF", MSC_MYSTATUSOFF, false, false);
+ script->set_constant("MSC_FRIENDSTATUSON", MSC_FRIENDSTATUSON, false, false);
+ script->set_constant("MSC_FRIENDSTATUSOFF", MSC_FRIENDSTATUSOFF, false, false);
+ script->set_constant("MSC_ATTACKPCGT", MSC_ATTACKPCGT, false, false);
+ script->set_constant("MSC_ATTACKPCGE", MSC_ATTACKPCGE, false, false);
+ script->set_constant("MSC_SLAVELT", MSC_SLAVELT, false, false);
+ script->set_constant("MSC_SLAVELE", MSC_SLAVELE, false, false);
+ script->set_constant("MSC_CLOSEDATTACKED", MSC_CLOSEDATTACKED, false, false);
+ script->set_constant("MSC_LONGRANGEATTACKED", MSC_LONGRANGEATTACKED, false, false);
+ script->set_constant("MSC_SKILLUSED", MSC_SKILLUSED, false, false);
+ script->set_constant("MSC_AFTERSKILL", MSC_AFTERSKILL, false, false);
+ script->set_constant("MSC_CASTTARGETED", MSC_CASTTARGETED, false, false);
+ script->set_constant("MSC_RUDEATTACKED", MSC_RUDEATTACKED, false, false);
+ script->set_constant("MSC_MASTERHPLTMAXRATE", MSC_MASTERHPLTMAXRATE, false, false);
+ script->set_constant("MSC_MASTERATTACKED", MSC_MASTERATTACKED, false, false);
+ script->set_constant("MSC_ALCHEMIST", MSC_ALCHEMIST, false, false);
+ script->set_constant("MSC_SPAWN", MSC_SPAWN, false, false);
+
+ script->constdb_comment("monster skill targets");
+ script->set_constant("MST_TARGET", MST_TARGET, false, false);
+ script->set_constant("MST_RANDOM", MST_RANDOM , false, false);
+ script->set_constant("MST_SELF", MST_SELF, false, false);
+ script->set_constant("MST_FRIEND", MST_FRIEND , false, false);
+ script->set_constant("MST_MASTER", MST_MASTER , false, false);
+ script->set_constant("MST_AROUND5", MST_AROUND5, false, false);
+ script->set_constant("MST_AROUND6", MST_AROUND6, false, false);
+ script->set_constant("MST_AROUND7", MST_AROUND7, false, false);
+ script->set_constant("MST_AROUND8", MST_AROUND8, false, false);
+ script->set_constant("MST_AROUND1", MST_AROUND1, false, false);
+ script->set_constant("MST_AROUND2", MST_AROUND2, false, false);
+ script->set_constant("MST_AROUND3", MST_AROUND3, false, false);
+ script->set_constant("MST_AROUND4", MST_AROUND4, false, false);
+ script->set_constant("MST_AROUND", MST_AROUND , false, false);
+
+ script->constdb_comment("Monster group constants");
+ script->set_constant("ALL_MOBS_NONBOSS", ALL_MOBS_NONBOSS, false, false);
+ script->set_constant("ALL_MOBS_BOSS", ALL_MOBS_BOSS, false, false);
+ script->set_constant("ALL_MOBS", ALL_MOBS, false, false);
+
+ script->constdb_comment("pc block constants, use with *setpcblock* and *checkpcblock*");
+ script->set_constant("PCBLOCK_NONE", PCBLOCK_NONE, false, false);
+ script->set_constant("PCBLOCK_MOVE", PCBLOCK_MOVE, false, false);
+ script->set_constant("PCBLOCK_ATTACK", PCBLOCK_ATTACK, false, false);
+ script->set_constant("PCBLOCK_SKILL", PCBLOCK_SKILL, false, false);
+ script->set_constant("PCBLOCK_USEITEM", PCBLOCK_USEITEM, false, false);
+ script->set_constant("PCBLOCK_CHAT", PCBLOCK_CHAT, false, false);
+ script->set_constant("PCBLOCK_IMMUNE", PCBLOCK_IMMUNE, false, false);
+ script->set_constant("PCBLOCK_SITSTAND", PCBLOCK_SITSTAND, false, false);
+ script->set_constant("PCBLOCK_COMMANDS", PCBLOCK_COMMANDS, false, false);
+ script->set_constant("PCBLOCK_NPC", PCBLOCK_NPC, false, false);
+
+ script->constdb_comment("private airship responds");
+ script->set_constant("P_AIRSHIP_NONE", P_AIRSHIP_NONE, false, false);
+ script->set_constant("P_AIRSHIP_RETRY", P_AIRSHIP_RETRY, false, false);
+ script->set_constant("P_AIRSHIP_INVALID_START_MAP", P_AIRSHIP_INVALID_START_MAP, false, false);
+ script->set_constant("P_AIRSHIP_INVALID_END_MAP", P_AIRSHIP_INVALID_END_MAP, false, false);
+ script->set_constant("P_AIRSHIP_ITEM_NOT_ENOUGH", P_AIRSHIP_ITEM_NOT_ENOUGH, false, false);
+ script->set_constant("P_AIRSHIP_ITEM_INVALID", P_AIRSHIP_ITEM_INVALID, false, false);
+
+ script->constdb_comment("questinfo types");
+ script->set_constant("QINFO_JOB", QINFO_JOB, false, false);
+ script->set_constant("QINFO_SEX", QINFO_SEX, false, false);
+ script->set_constant("QINFO_BASE_LEVEL", QINFO_BASE_LEVEL, false, false);
+ script->set_constant("QINFO_JOB_LEVEL", QINFO_JOB_LEVEL, false, false);
+ script->set_constant("QINFO_ITEM", QINFO_ITEM, false, false);
+ script->set_constant("QINFO_HOMUN_LEVEL", QINFO_HOMUN_LEVEL, false, false);
+ script->set_constant("QINFO_HOMUN_TYPE", QINFO_HOMUN_TYPE, false, false);
+ script->set_constant("QINFO_QUEST", QINFO_QUEST, false, false);
+ script->set_constant("QINFO_MERCENARY_CLASS", QINFO_MERCENARY_CLASS, false, false);
+
+ script->constdb_comment("function types");
+ script->set_constant("FUNCTION_IS_COMMAND", FUNCTION_IS_COMMAND, false, false);
+ script->set_constant("FUNCTION_IS_GLOBAL", FUNCTION_IS_GLOBAL, false, false);
+ script->set_constant("FUNCTION_IS_LOCAL", FUNCTION_IS_LOCAL, false, false);
+ script->set_constant("FUNCTION_IS_LABEL", FUNCTION_IS_LABEL, false, false);
+
+ script->constdb_comment("item trade restrictions");
+ script->set_constant("ITR_NONE", ITR_NONE, false, false);
+ script->set_constant("ITR_NODROP", ITR_NODROP, false, false);
+ script->set_constant("ITR_NOTRADE", ITR_NOTRADE, false, false);
+ script->set_constant("ITR_PARTNEROVERRIDE", ITR_PARTNEROVERRIDE, false, false);
+ script->set_constant("ITR_NOSELLTONPC", ITR_NOSELLTONPC, false, false);
+ script->set_constant("ITR_NOCART", ITR_NOCART, false, false);
+ script->set_constant("ITR_NOSTORAGE", ITR_NOSTORAGE, false, false);
+ script->set_constant("ITR_NOGSTORAGE", ITR_NOGSTORAGE, false, false);
+ script->set_constant("ITR_NOMAIL", ITR_NOMAIL, false, false);
+ script->set_constant("ITR_NOAUCTION", ITR_NOAUCTION, false, false);
+ script->set_constant("ITR_ALL", ITR_ALL, false, false);
+
+ script->constdb_comment("inventory expand ack responds");
+ script->set_constant("EXPAND_INV_ASK_CONFIRMATION", EXPAND_INVENTORY_ASK_CONFIRMATION, false, false);
+ script->set_constant("EXPAND_INV_FAILED", EXPAND_INVENTORY_FAILED, false, false);
+ script->set_constant("EXPAND_INV_OTHER_WORK", EXPAND_INVENTORY_OTHER_WORK, false, false);
+ script->set_constant("EXPAND_INV_MISSING_ITEM", EXPAND_INVENTORY_MISSING_ITEM, false, false);
+ script->set_constant("EXPAND_INV_MAX_SIZE", EXPAND_INVENTORY_MAX_SIZE, false, false);
+
+ script->constdb_comment("inventory expand final responds");
+ script->set_constant("EXPAND_INV_RESULT_SUCCESS", EXPAND_INVENTORY_RESULT_SUCCESS, false, false);
+ script->set_constant("EXPAND_INV_RESULT_FAILED", EXPAND_INVENTORY_RESULT_FAILED, false, false);
+ script->set_constant("EXPAND_INV_RESULT_OTHER_WORK", EXPAND_INVENTORY_RESULT_OTHER_WORK, false, false);
+ script->set_constant("EXPAND_INV_RESULT_MISSING_ITEM", EXPAND_INVENTORY_RESULT_MISSING_ITEM, false, false);
+ script->set_constant("EXPAND_INV_RESULT_MAX_SIZE", EXPAND_INVENTORY_RESULT_MAX_SIZE, false, false);
+
+ script->constdb_comment("trader type");
+ script->set_constant("NST_ZENY", NST_ZENY, false, false);
+ script->set_constant("NST_CASH", NST_CASH, false, false);
+ script->set_constant("NST_MARKET", NST_MARKET, false, false);
+ script->set_constant("NST_CUSTOM", NST_CUSTOM, false, false);
+ script->set_constant("NST_BARTER", NST_BARTER, false, false);
+ script->set_constant("NST_EXPANDED_BARTER", NST_EXPANDED_BARTER, false, false);
+
+ script->constdb_comment("script unit data types");
+ script->set_constant("UDT_TYPE", UDT_TYPE, false, false);
+ script->set_constant("UDT_SIZE", UDT_SIZE, false, false);
+ script->set_constant("UDT_LEVEL", UDT_LEVEL, false, false);
+ script->set_constant("UDT_HP", UDT_HP, false, false);
+ script->set_constant("UDT_MAXHP", UDT_MAXHP, false, false);
+ script->set_constant("UDT_SP", UDT_SP, false, false);
+ script->set_constant("UDT_MAXSP", UDT_MAXSP, false, false);
+ script->set_constant("UDT_MASTERAID", UDT_MASTERAID, false, false);
+ script->set_constant("UDT_MASTERCID", UDT_MASTERCID, false, false);
+ script->set_constant("UDT_MAPIDXY", UDT_MAPIDXY, false, true); // for setunitdata use *unitwarp, for getunitdata use *getmapxy
+ script->set_constant("UDT_WALKTOXY", UDT_WALKTOXY, false, true); // use *unitwalk
+ script->set_constant("UDT_SPEED", UDT_SPEED, false, false);
+ script->set_constant("UDT_MODE", UDT_MODE, false, false);
+ script->set_constant("UDT_AI", UDT_AI, false, false);
+ script->set_constant("UDT_SCOPTION", UDT_SCOPTION, false, false);
+ script->set_constant("UDT_SEX", UDT_SEX, false, false);
+ script->set_constant("UDT_CLASS", UDT_CLASS, false, false);
+ script->set_constant("UDT_HAIRSTYLE", UDT_HAIRSTYLE, false, false);
+ script->set_constant("UDT_HAIRCOLOR", UDT_HAIRCOLOR, false, false);
+ script->set_constant("UDT_HEADBOTTOM", UDT_HEADBOTTOM, false, false);
+ script->set_constant("UDT_HEADMIDDLE", UDT_HEADMIDDLE, false, false);
+ script->set_constant("UDT_HEADTOP", UDT_HEADTOP, false, false);
+ script->set_constant("UDT_CLOTHCOLOR", UDT_CLOTHCOLOR, false, false);
+ script->set_constant("UDT_SHIELD", UDT_SHIELD, false, false);
+ script->set_constant("UDT_WEAPON", UDT_WEAPON, false, false);
+ script->set_constant("UDT_LOOKDIR", UDT_LOOKDIR, false, false);
+ script->set_constant("UDT_CANMOVETICK", UDT_CANMOVETICK, false, false);
+ script->set_constant("UDT_STR", UDT_STR, false, false);
+ script->set_constant("UDT_AGI", UDT_AGI, false, false);
+ script->set_constant("UDT_VIT", UDT_VIT, false, false);
+ script->set_constant("UDT_INT", UDT_INT, false, false);
+ script->set_constant("UDT_DEX", UDT_DEX, false, false);
+ script->set_constant("UDT_LUK", UDT_LUK, false, false);
+ script->set_constant("UDT_ATKRANGE", UDT_ATKRANGE, false, false);
+ script->set_constant("UDT_ATKMIN", UDT_ATKMIN, false, false);
+ script->set_constant("UDT_ATKMAX", UDT_ATKMAX, false, false);
+ script->set_constant("UDT_MATKMIN", UDT_MATKMIN, false, false);
+ script->set_constant("UDT_MATKMAX", UDT_MATKMAX, false, false);
+ script->set_constant("UDT_DEF", UDT_DEF, false, false);
+ script->set_constant("UDT_MDEF", UDT_MDEF, false, false);
+ script->set_constant("UDT_HIT", UDT_HIT, false, false);
+ script->set_constant("UDT_FLEE", UDT_FLEE, false, false);
+ script->set_constant("UDT_PDODGE", UDT_PDODGE, false, false);
+ script->set_constant("UDT_CRIT", UDT_CRIT, false, false);
+ script->set_constant("UDT_RACE", UDT_RACE, false, false);
+ script->set_constant("UDT_ELETYPE", UDT_ELETYPE, false, false);
+ script->set_constant("UDT_ELELEVEL", UDT_ELELEVEL, false, false);
+ script->set_constant("UDT_AMOTION", UDT_AMOTION, false, false);
+ script->set_constant("UDT_ADELAY", UDT_ADELAY, false, false);
+ script->set_constant("UDT_DMOTION", UDT_DMOTION, false, false);
+ script->set_constant("UDT_HUNGER", UDT_HUNGER, false, false);
+ script->set_constant("UDT_INTIMACY", UDT_INTIMACY, false, false);
+ script->set_constant("UDT_LIFETIME", UDT_LIFETIME, false, false);
+ script->set_constant("UDT_MERC_KILLCOUNT", UDT_MERC_KILLCOUNT, false, false);
+ script->set_constant("UDT_STATPOINT", UDT_STATPOINT, false, false);
+ script->set_constant("UDT_ROBE", UDT_ROBE, false, false);
+ script->set_constant("UDT_BODY2", UDT_BODY2, false, false);
+ script->set_constant("UDT_GROUP", UDT_GROUP, false, false);
+ script->set_constant("UDT_DAMAGE_TAKEN_RATE", UDT_DAMAGE_TAKEN_RATE, false, false);
+
+ script->constdb_comment("getguildonline types");
+ script->set_constant("GUILD_ONLINE_ALL", GUILD_ONLINE_ALL, false, false);
+ script->set_constant("GUILD_ONLINE_VENDOR", GUILD_ONLINE_VENDOR, false, false);
+ script->set_constant("GUILD_ONLINE_NO_VENDOR", GUILD_ONLINE_NO_VENDOR, false, false);
+
+ script->constdb_comment("Siege Types");
+ script->set_constant("SIEGE_TYPE_FE", SIEGE_TYPE_FE, false, false);
+ script->set_constant("SIEGE_TYPE_SE", SIEGE_TYPE_SE, false, false);
+ script->set_constant("SIEGE_TYPE_TE", SIEGE_TYPE_TE, false, false);
+
+ script->constdb_comment("guildinfo types");
+ script->set_constant("GUILDINFO_NAME", GUILDINFO_NAME, false, false);
+ script->set_constant("GUILDINFO_ID", GUILDINFO_ID, false, false);
+ script->set_constant("GUILDINFO_LEVEL", GUILDINFO_LEVEL, false, false);
+ script->set_constant("GUILDINFO_ONLINE", GUILDINFO_ONLINE, false, false);
+ script->set_constant("GUILDINFO_AV_LEVEL", GUILDINFO_AV_LEVEL, false, false);
+ script->set_constant("GUILDINFO_MAX_MEMBERS", GUILDINFO_MAX_MEMBERS, false, false);
+ script->set_constant("GUILDINFO_EXP", GUILDINFO_EXP, false, false);
+ script->set_constant("GUILDINFO_NEXT_EXP", GUILDINFO_NEXT_EXP, false, false);
+ script->set_constant("GUILDINFO_SKILL_POINTS", GUILDINFO_SKILL_POINTS, false, false);
+ script->set_constant("GUILDINFO_MASTER_NAME", GUILDINFO_MASTER_NAME, false, false);
+ script->set_constant("GUILDINFO_MASTER_CID", GUILDINFO_MASTER_CID, false, false);
+
+ script->constdb_comment("madogear types");
+ script->set_constant("MADO_ROBOT", MADO_ROBOT, false, false);
+ script->set_constant("MADO_SUITE", MADO_SUITE, false, false);
+
+ script->constdb_comment("itemskill option flags");
+ script->set_constant("ISF_NONE", ISF_NONE, false, false);
+ script->set_constant("ISF_CHECKCONDITIONS", ISF_CHECKCONDITIONS, false, false);
+ script->set_constant("ISF_INSTANTCAST", ISF_INSTANTCAST, false, false);
+ script->set_constant("ISF_CASTONSELF", ISF_CASTONSELF, false, false);
+
+ script->constdb_comment("Item Bound Types");
+ script->set_constant("IBT_ANY", IBT_NONE, false, false); // for *checkbound()
+ script->set_constant("IBT_ACCOUNT", IBT_ACCOUNT, false, false);
+ script->set_constant("IBT_GUILD", IBT_GUILD, false, false);
+ script->set_constant("IBT_PARTY", IBT_PARTY, false, false);
+ script->set_constant("IBT_CHARACTER", IBT_CHARACTER, false, false);
script->constdb_comment("Renewal");
#ifdef RENEWAL
@@ -21069,7 +28067,8 @@ void script_hardcoded_constants(void)
/**
* a mapindex_name2id wrapper meant to help with invalid name handling
**/
-unsigned short script_mapindexname2id (struct script_state *st, const char* name) {
+static unsigned short script_mapindexname2id(struct script_state *st, const char *name)
+{
unsigned short index;
if( !(index=mapindex->name2id(name)) ) {
@@ -21079,7 +28078,8 @@ unsigned short script_mapindexname2id (struct script_state *st, const char* name
return index;
}
-void script_defaults(void) {
+void script_defaults(void)
+{
// aegis->athena slot position conversion table
unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L};
@@ -21112,8 +28112,8 @@ void script_defaults(void) {
script->label_count = 0;
script->labels_size = 0;
- script->buf = NULL;
- script->pos = 0, script->size = 0;
+ VECTOR_INIT(script->buf);
+ VECTOR_INIT(script->translation_buf);
script->parse_options = 0;
script->buildin_set_ref = 0;
@@ -21171,10 +28171,12 @@ void script_defaults(void) {
script->get_val = get_val;
script->get_val2 = get_val2;
script->get_val_ref_str = get_val_npcscope_str;
+ script->get_val_pc_ref_str = get_val_pc_ref_str;
script->get_val_scope_str = get_val_npcscope_str;
script->get_val_npc_str = get_val_npcscope_str;
script->get_val_instance_str = get_val_instance_str;
script->get_val_ref_num = get_val_npcscope_num;
+ script->get_val_pc_ref_num = get_val_pc_ref_num;
script->get_val_scope_num = get_val_npcscope_num;
script->get_val_npc_num = get_val_npcscope_num;
script->get_val_instance_num = get_val_instance_num;
@@ -21203,10 +28205,12 @@ void script_defaults(void) {
script->setarray_pc = script_setarray_pc;
script->config_read = script_config_read;
script->add_str = script_add_str;
+ script->add_variable = script_add_variable;
script->get_str = script_get_str;
script->search_str = script_search_str;
script->setd_sub = setd_sub;
script->attach_state = script_attach_state;
+ script->sprintf_helper = script_sprintf_helper;
script->queue = script_hqueue_get;
script->queue_add = script_hqueue_add;
@@ -21239,6 +28243,11 @@ void script_defaults(void) {
script->parse_nextline = parse_nextline;
script->parse_variable = parse_variable;
script->parse_simpleexpr = parse_simpleexpr;
+ script->parse_simpleexpr_paren = parse_simpleexpr_paren;
+ script->parse_simpleexpr_number = parse_simpleexpr_number;
+ script->parse_simpleexpr_string = parse_simpleexpr_string;
+ script->parse_simpleexpr_name = parse_simpleexpr_name;
+ script->add_translatable_string = script_add_translatable_string;
script->parse_expr = parse_expr;
script->parse_line = parse_line;
script->read_constdb = read_constdb;
@@ -21248,10 +28257,12 @@ void script_defaults(void) {
script->errorwarning_sub = script_errorwarning_sub;
script->set_reg = set_reg;
script->set_reg_ref_str = set_reg_npcscope_str;
+ script->set_reg_pc_ref_str = set_reg_pc_ref_str;
script->set_reg_scope_str = set_reg_npcscope_str;
script->set_reg_npc_str = set_reg_npcscope_str;
script->set_reg_instance_str = set_reg_instance_str;
script->set_reg_ref_num = set_reg_npcscope_num;
+ script->set_reg_pc_ref_num = set_reg_pc_ref_num;
script->set_reg_scope_num = set_reg_npcscope_num;
script->set_reg_npc_num = set_reg_npcscope_num;
script->set_reg_instance_num = set_reg_instance_num;
@@ -21268,6 +28279,9 @@ void script_defaults(void) {
script->db_free_code_sub = db_script_free_code_sub;
script->add_autobonus = script_add_autobonus;
script->menu_countoptions = menu_countoptions;
+ script->buildin_recovery_sub = buildin_recovery_sub;
+ script->buildin_recovery_pc_sub = buildin_recovery_pc_sub;
+ script->buildin_recovery_bl_sub = buildin_recovery_bl_sub;
script->buildin_areawarp_sub = buildin_areawarp_sub;
script->buildin_areapercentheal_sub = buildin_areapercentheal_sub;
script->buildin_delitem_delete = buildin_delitem_delete;
@@ -21295,8 +28309,8 @@ void script_defaults(void) {
script->getfuncname = script_getfuncname;
/* script_config base */
- script->config.warn_func_mismatch_argtypes = 1;
- script->config.warn_func_mismatch_paramnum = 1;
+ script->config.warn_func_mismatch_argtypes = true;
+ script->config.warn_func_mismatch_paramnum = true;
script->config.check_cmdcount = 65535;
script->config.check_gotocount = 2048;
script->config.input_min_value = 0;
@@ -21358,15 +28372,22 @@ void script_defaults(void) {
script->mapindexname2id = script_mapindexname2id;
script->string_dup = script_string_dup;
script->load_translations = script_load_translations;
+ script->load_translation_addstring = script_load_translation_addstring;
+ script->load_translation_file = script_load_translation_file;
script->load_translation = script_load_translation;
script->translation_db_destroyer = script_translation_db_destroyer;
script->clear_translations = script_clear_translations;
script->parse_cleanup_timer = script_parse_cleanup_timer;
script->add_language = script_add_language;
- script->get_translation_file_name = script_get_translation_file_name;
+ script->get_translation_dir_name = script_get_translation_dir_name;
script->parser_clean_leftovers = script_parser_clean_leftovers;
script->run_use_script = script_run_use_script;
script->run_item_equip_script = script_run_item_equip_script;
script->run_item_unequip_script = script_run_item_unequip_script;
+ script->run_item_rental_start_script = script_run_item_rental_start_script;
+ script->run_item_rental_end_script = script_run_item_rental_end_script;
+ script->run_item_lapineddukddak_script = script_run_item_lapineddukddak_script;
+
+ script->sellitemcurrency_add = script_sellitemcurrency_add;
}
diff --git a/src/map/script.h b/src/map/script.h
index a1fbe31f0..511497a66 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ struct item_data;
#define NUM_WHISPER_VAR 10
/// Maximum amount of elements in script arrays
-#define SCRIPT_MAX_ARRAYSIZE (UINT_MAX - 1)
+#define SCRIPT_MAX_ARRAYSIZE (INT_MAX - 1)
#define SCRIPT_BLOCK_SIZE 512
@@ -64,6 +64,9 @@ struct item_data;
#define SCRIPT_EQUIP_TABLE_SIZE 20
+#define MAX_MENU_OPTIONS 0xFF
+#define MAX_MENU_LENGTH 0x800
+
//#define SCRIPT_DEBUG_DISP
//#define SCRIPT_DEBUG_DISASM
//#define SCRIPT_DEBUG_HASH
@@ -143,7 +146,6 @@ struct item_data;
/// Returns if this a reference to a param
#define reference_toparam(data) ( script->str_data[reference_getid(data)].type == C_PARAM )
/// Returns if this a reference to a variable
-//##TODO confirm it's C_NAME [FlavioJS]
#define reference_tovariable(data) ( script->str_data[reference_getid(data)].type == C_NAME )
/// Returns the unique id of the reference (id and index)
#define reference_getuid(data) ( (data)->u.num )
@@ -178,6 +180,8 @@ struct item_data;
#define BUILDIN(x) bool buildin_ ## x (struct script_state* st)
+#define get_buildin_name(st) ( script->get_str((int)(script_getdata((st), 0)->u.num)) )
+
#define script_fetch(st, n, t) do { \
if( script_hasdata((st),(n)) ) \
(t)=script_getnum((st),(n)); \
@@ -235,6 +239,7 @@ typedef enum c_op {
C_SUB_PRE, // --a
C_RE_EQ, // ~=
C_RE_NE, // ~!
+ C_POW, // **
} c_op;
/// Script queue options
@@ -335,7 +340,241 @@ enum {
MF_RESET,
MF_NOTOMB,
MF_NOCASHSHOP,
- MF_NOVIEWID
+ MF_NOAUTOLOOT,
+ MF_NOVIEWID,
+ MF_PAIRSHIP_STARTABLE,
+ MF_PAIRSHIP_ENDABLE,
+ MF_NOSTORAGE,
+ MF_NOGSTORAGE
+};
+
+enum navigation_service {
+ NAV_NONE = 0,
+ NAV_AIRSHIP_ONLY = 1,
+ NAV_SCROLL_ONLY = 10,
+ NAV_AIRSHIP_AND_SCROLL = NAV_AIRSHIP_ONLY + NAV_SCROLL_ONLY, //11
+ NAV_KAFRA_ONLY = 100,
+ NAV_KAFRA_AND_AIRSHIP = NAV_KAFRA_ONLY + NAV_AIRSHIP_ONLY, // 101
+ NAV_KAFRA_AND_SCROLL = NAV_KAFRA_ONLY + NAV_SCROLL_ONLY, // 110
+ NAV_ALL = NAV_AIRSHIP_ONLY + NAV_SCROLL_ONLY + NAV_KAFRA_ONLY // 111-255
+};
+
+/**
+ * Unit Types for script handling.
+ */
+enum script_unit_types {
+ UNIT_PC = 0,
+ UNIT_NPC,
+ UNIT_PET,
+ UNIT_MOB,
+ UNIT_HOM,
+ UNIT_MER,
+ UNIT_ELEM,
+};
+
+/**
+ * Unit Data Types for script handling.
+ */
+enum script_unit_data_types {
+ UDT_TYPE = 0,
+ UDT_SIZE,
+ UDT_LEVEL,
+ UDT_HP,
+ UDT_MAXHP,
+ UDT_SP,
+ UDT_MAXSP,
+ UDT_MASTERAID,
+ UDT_MASTERCID,
+ UDT_MAPIDXY,
+ UDT_WALKTOXY,
+ UDT_SPEED,
+ UDT_MODE,
+ UDT_AI,
+ UDT_SCOPTION,
+ UDT_SEX,
+ UDT_CLASS,
+ UDT_HAIRSTYLE,
+ UDT_HAIRCOLOR,
+ UDT_HEADBOTTOM,
+ UDT_HEADMIDDLE,
+ UDT_HEADTOP,
+ UDT_CLOTHCOLOR,
+ UDT_SHIELD,
+ UDT_WEAPON,
+ UDT_LOOKDIR,
+ UDT_CANMOVETICK,
+ UDT_STR,
+ UDT_AGI,
+ UDT_VIT,
+ UDT_INT,
+ UDT_DEX,
+ UDT_LUK,
+ UDT_ATKRANGE,
+ UDT_ATKMIN,
+ UDT_ATKMAX,
+ UDT_MATKMIN,
+ UDT_MATKMAX,
+ UDT_DEF,
+ UDT_MDEF,
+ UDT_HIT,
+ UDT_FLEE,
+ UDT_PDODGE,
+ UDT_CRIT,
+ UDT_RACE,
+ UDT_ELETYPE,
+ UDT_ELELEVEL,
+ UDT_AMOTION,
+ UDT_ADELAY,
+ UDT_DMOTION,
+ UDT_HUNGER,
+ UDT_INTIMACY,
+ UDT_LIFETIME,
+ UDT_MERC_KILLCOUNT,
+ UDT_STATPOINT,
+ UDT_ROBE,
+ UDT_BODY2,
+ UDT_GROUP,
+ UDT_DAMAGE_TAKEN_RATE,
+ UDT_MAX
+};
+
+/**
+ * Item Info types.
+ */
+enum script_iteminfo_types {
+ ITEMINFO_BUYPRICE = 0,
+ ITEMINFO_SELLPRICE,
+ ITEMINFO_TYPE,
+ ITEMINFO_MAXCHANCE,
+ ITEMINFO_SEX,
+ ITEMINFO_LOC,
+ ITEMINFO_WEIGHT,
+ ITEMINFO_ATK,
+ ITEMINFO_DEF,
+ ITEMINFO_RANGE,
+ ITEMINFO_SLOTS,
+ ITEMINFO_SUBTYPE,
+ ITEMINFO_ELV,
+ ITEMINFO_WLV,
+ ITEMINFO_VIEWID,
+ ITEMINFO_MATK,
+ ITEMINFO_VIEWSPRITE,
+ ITEMINFO_TRADE,
+ ITEMINFO_ELV_MAX,
+ ITEMINFO_DROPEFFECT_MODE,
+ ITEMINFO_DELAY,
+ ITEMINFO_CLASS_BASE_1,
+ ITEMINFO_CLASS_BASE_2,
+ ITEMINFO_CLASS_BASE_3,
+ ITEMINFO_CLASS_UPPER,
+ // ITEMINFO_FLAG_AVAILABLE,
+ ITEMINFO_FLAG_NO_REFINE,
+ ITEMINFO_FLAG_DELAY_CONSUME,
+ ITEMINFO_FLAG_AUTOEQUIP,
+ ITEMINFO_FLAG_AUTO_FAVORITE,
+ ITEMINFO_FLAG_BUYINGSTORE,
+ ITEMINFO_FLAG_BINDONEQUIP,
+ ITEMINFO_FLAG_KEEPAFTERUSE,
+ ITEMINFO_FLAG_FORCE_SERIAL,
+ ITEMINFO_FLAG_NO_OPTIONS,
+ ITEMINFO_FLAG_DROP_ANNOUNCE,
+ ITEMINFO_FLAG_SHOWDROPEFFECT,
+ ITEMINFO_STACK_AMOUNT,
+ ITEMINFO_STACK_FLAG,
+ ITEMINFO_ITEM_USAGE_FLAG,
+ ITEMINFO_ITEM_USAGE_OVERRIDE,
+ ITEMINFO_GM_LV_TRADE_OVERRIDE,
+ ITEMINFO_ID,
+ ITEMINFO_AEGISNAME,
+ ITEMINFO_NAME,
+ ITEMINFO_MAX
+};
+
+/**
+ * Mercenary Info types.
+ */
+enum script_mercinfo_types {
+ MERCINFO_ID = 0,
+ MERCINFO_CLASS,
+ MERCINFO_NAME,
+ MERCINFO_FAITH,
+ MERCINFO_CALLS,
+ MERCINFO_KILLCOUNT,
+ MERCINFO_LIFETIME,
+ MERCINFO_LEVEL,
+ MERCINFO_GID,
+
+ MERCINFO_MAX
+};
+
+/**
+ * Pet Info types.
+ */
+enum script_petinfo_types {
+ PETINFO_ID = 0,
+ PETINFO_CLASS,
+ PETINFO_NAME,
+ PETINFO_INTIMACY,
+ PETINFO_HUNGRY,
+ PETINFO_RENAME,
+ PETINFO_GID,
+ PETINFO_EGGITEM,
+ PETINFO_FOODITEM,
+ PETINFO_ACCESSORYITEM,
+ PETINFO_ACCESSORYFLAG,
+ PETINFO_EVO_EGGID,
+ PETINFO_AUTOFEED,
+
+ PETINFO_MAX
+};
+
+/**
+ * Player blocking actions related flags.
+ */
+enum pcblock_action_flag {
+ PCBLOCK_NONE = 0x000,
+ PCBLOCK_MOVE = 0x001,
+ PCBLOCK_ATTACK = 0x002,
+ PCBLOCK_SKILL = 0x004,
+ PCBLOCK_USEITEM = 0x008,
+ PCBLOCK_CHAT = 0x010,
+ PCBLOCK_IMMUNE = 0x020,
+ PCBLOCK_SITSTAND = 0x040,
+ PCBLOCK_COMMANDS = 0x080,
+ PCBLOCK_NPC = 0x100,
+ PCBLOCK_ALL = 0x1FF,
+};
+
+/**
+ * Types of Siege (WoE)
+ */
+enum siege_type {
+ SIEGE_TYPE_FE,
+ SIEGE_TYPE_SE,
+ SIEGE_TYPE_TE,
+ SIEGE_TYPE_MAX
+};
+
+/**
+ * Types of MadoGear
+ */
+enum mado_type {
+ MADO_ROBOT = 0x00,
+ // unused = 0x01,
+ MADO_SUITE = 0x02,
+#ifndef MADO_MAX
+ MADO_MAX
+#endif
+};
+
+/**
+ * Option flags for itemskill() script command.
+ **/
+enum itemskill_flag {
+ ISF_NONE = 0x00,
+ ISF_CHECKCONDITIONS = 0x01, // Check skill conditions and consume them.
+ ISF_INSTANTCAST = 0x02, // Cast skill instantaneously.
+ ISF_CASTONSELF = 0x04, // Forcefully cast skill on invoking character without showing the target selection cursor.
};
/**
@@ -343,8 +582,8 @@ enum {
**/
struct Script_Config {
- unsigned warn_func_mismatch_argtypes : 1;
- unsigned warn_func_mismatch_paramnum : 1;
+ bool warn_func_mismatch_argtypes;
+ bool warn_func_mismatch_paramnum;
int check_cmdcount;
int check_gotocount;
int input_min_value;
@@ -394,11 +633,20 @@ struct script_data {
struct reg_db *ref; ///< Reference to the scope's variables
};
+/**
+ * A script string buffer, used to hold strings used by the script engine.
+ */
+VECTOR_STRUCT_DECL(script_string_buf, char);
+
+/**
+ * Script buffer, used to hold parsed script data.
+ */
+VECTOR_STRUCT_DECL(script_buf, unsigned char);
+
// Moved defsp from script_state to script_stack since
// it must be saved when script state is RERUNLINE. [Eoe / jA 1094]
struct script_code {
- int script_size;
- unsigned char *script_buf;
+ struct script_buf script_buf;
struct reg_db local; ///< Local (npc) vars
unsigned short instances;
};
@@ -493,8 +741,8 @@ struct script_syntax_data {
int index; // Number of the syntax used in the script
int last_func; // buildin index of the last parsed function
unsigned int nested_call; //Dont really know what to call this
- bool lang_macro_active;
- struct DBMap *strings; // string map parsed (used when exporting strings only)
+ bool lang_macro_active; // Used to generate translation strings
+ bool lang_macro_fmtstring_active; // Used to generate translation strings
struct DBMap *translation_db; //non-null if this npc has any translated strings to be linked
};
@@ -517,16 +765,16 @@ struct script_array {
unsigned int *members;/* member list */
};
-struct script_string_buf {
- char *ptr;
- size_t pos,size;
+struct string_translation_entry {
+ uint8 lang_id;
+ char string[];
};
struct string_translation {
int string_id;
uint8 translations;
- unsigned int len;
- char *buf;
+ int len;
+ uint8 *buf; // Array of struct string_translation_entry
};
/**
@@ -566,7 +814,7 @@ struct script_interface {
int string_list_size;
int string_list_pos;
/* */
- unsigned short current_item_id;
+ int current_item_id;
/* */
struct script_label_entry *labels;
int label_count;
@@ -576,8 +824,7 @@ struct script_interface {
/* */
/// temporary buffer for passing around compiled bytecode
/// @see add_scriptb, set_label, parse_script
- unsigned char* buf;
- int pos, size;
+ struct script_buf buf;
/* */
struct script_syntax_data syntax;
/* */
@@ -611,26 +858,22 @@ struct script_interface {
/* */
unsigned int *generic_ui_array;
unsigned int generic_ui_array_size;
- /* Set during startup when attempting to export the lang, unset after server initialization is over */
- FILE *lang_export_fp;
- char *lang_export_file;/* for lang_export_fp */
/* set and unset on npc_parse_script */
const char *parser_current_npc_name;
/* */
int buildin_mes_offset;
+ int buildin_mesf_offset;
int buildin_select_offset;
int buildin_lang_macro_offset;
+ int buildin_lang_macro_fmtstring_offset;
/* */
struct DBMap *translation_db;/* npc_name => DBMap (strings) */
- char **translation_buf;/* */
- uint32 translation_buf_size;
+ VECTOR_DECL(uint8 *) translation_buf;
/* */
char **languages;
uint8 max_lang_id;
/* */
- struct script_string_buf parse_simpleexpr_str;
- struct script_string_buf lang_export_line_buf;
- struct script_string_buf lang_export_unescaped_buf;
+ struct script_string_buf parse_simpleexpr_strbuf;
/* */
int parse_cleanup_timer_id;
/* */
@@ -657,10 +900,12 @@ struct script_interface {
struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref);
struct script_data *(*get_val) (struct script_state* st, struct script_data* data);
char* (*get_val_ref_str) (struct script_state* st, struct reg_db *n, struct script_data* data);
+ char* (*get_val_pc_ref_str) (struct script_state* st, struct reg_db *n, struct script_data* data);
char* (*get_val_scope_str) (struct script_state* st, struct reg_db *n, struct script_data* data);
char* (*get_val_npc_str) (struct script_state* st, struct reg_db *n, struct script_data* data);
char* (*get_val_instance_str) (struct script_state* st, const char* name, struct script_data* data);
int (*get_val_ref_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
+ int (*get_val_pc_ref_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
int (*get_val_scope_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
int (*get_val_npc_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
int (*get_val_instance_num) (struct script_state* st, const char* name, struct script_data* data);
@@ -688,8 +933,9 @@ struct script_interface {
void (*run_autobonus) (const char *autobonus,int id, int pos);
void (*cleararray_pc) (struct map_session_data* sd, const char* varname, void* value);
void (*setarray_pc) (struct map_session_data* sd, const char* varname, uint32 idx, void* value, int* refcache);
- int (*config_read) (char *cfgName);
+ bool (*config_read) (const char *filename, bool imported);
int (*add_str) (const char* p);
+ int (*add_variable) (const char *varname);
const char* (*get_str) (int id);
int (*search_str) (const char* p);
void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, const void *value, struct reg_db *ref);
@@ -706,8 +952,8 @@ struct script_interface {
const char * (*parse_syntax_close) (const char *p);
const char * (*parse_syntax_close_sub) (const char *p, int *flag);
const char * (*parse_syntax) (const char *p);
- c_op (*get_com) (unsigned char *scriptbuf, int *pos);
- int (*get_num) (unsigned char *scriptbuf, int *pos);
+ c_op (*get_com) (const struct script_buf *scriptbuf, int *pos);
+ int (*get_num) (const struct script_buf *scriptbuf, int *pos);
const char* (*op2name) (int op);
void (*reportsrc) (struct script_state *st);
void (*reportdata) (struct script_data *data);
@@ -724,21 +970,28 @@ struct script_interface {
int (*add_word) (const char *p);
const char* (*parse_callfunc) (const char *p, int require_paren, int is_custom);
void (*parse_nextline) (bool first, const char *p);
- const char* (*parse_variable) (const char *p);
- const char* (*parse_simpleexpr) (const char *p);
- const char* (*parse_expr) (const char *p);
- const char* (*parse_line) (const char *p);
- void (*read_constdb) (void);
+ const char *(*parse_variable) (const char *p);
+ const char *(*parse_simpleexpr) (const char *p);
+ const char *(*parse_simpleexpr_paren) (const char *p);
+ const char *(*parse_simpleexpr_number) (const char *p);
+ const char *(*parse_simpleexpr_string) (const char *p);
+ const char *(*parse_simpleexpr_name) (const char *p);
+ void (*add_translatable_string) (const struct script_string_buf *string, const char *start_point);
+ const char *(*parse_expr) (const char *p);
+ const char *(*parse_line) (const char *p);
+ void (*read_constdb) (bool reload);
void (*constdb_comment) (const char *comment);
void (*load_parameters) (void);
const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line);
void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos);
int (*set_reg) (struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref);
void (*set_reg_ref_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
+ void (*set_reg_pc_ref_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
void (*set_reg_scope_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
void (*set_reg_npc_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
void (*set_reg_instance_str) (struct script_state* st, int64 num, const char* name, const char *str);
void (*set_reg_ref_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val);
+ void (*set_reg_pc_ref_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val);
void (*set_reg_scope_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val);
void (*set_reg_npc_num) (struct script_state* st, struct reg_db *n, int64 num, const char* name, int val);
void (*set_reg_instance_num) (struct script_state* st, int64 num, const char* name, int val);
@@ -749,11 +1002,14 @@ struct script_interface {
void (*op_2num) (struct script_state *st, int op, int i1, int i2);
void (*op_2) (struct script_state *st, int op);
void (*op_1) (struct script_state *st, int op);
- void (*check_buildin_argtype) (struct script_state *st, int func);
+ bool (*check_buildin_argtype) (struct script_state *st, int func);
void (*detach_state) (struct script_state *st, bool dequeue_event);
int (*db_free_code_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*add_autobonus) (const char *autobonus);
int (*menu_countoptions) (const char *str, int max_count, int *total);
+ int (*buildin_recovery_sub) (struct map_session_data *sd);
+ int (*buildin_recovery_pc_sub) (struct map_session_data *sd, va_list ap);
+ int (*buildin_recovery_bl_sub) (struct block_list *bl, va_list ap);
int (*buildin_areawarp_sub) (struct block_list *bl, va_list ap);
int (*buildin_areapercentheal_sub) (struct block_list *bl, va_list ap);
void (*buildin_delitem_delete) (struct map_session_data *sd, int idx, int *amount, bool delete_items);
@@ -778,6 +1034,7 @@ struct script_interface {
int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap);
int (*cleanfloor_sub) (struct block_list *bl, va_list ap);
int (*run_func) (struct script_state *st);
+ bool (*sprintf_helper) (struct script_state *st, int start, struct StringBuf *out);
const char *(*getfuncname) (struct script_state *st);
// for ENABLE_CASE_CHECK
unsigned int (*calc_hash_ci) (const char *p);
@@ -807,16 +1064,22 @@ struct script_interface {
unsigned short (*mapindexname2id) (struct script_state *st, const char* name);
int (*string_dup) (char *str);
void (*load_translations) (void);
- void (*load_translation) (const char *file, uint8 lang_id, uint32 *total);
+ bool (*load_translation_addstring) (const char *file, uint8 lang_id, const char *msgctxt, const struct script_string_buf *msgid, const struct script_string_buf *msgstr);
+ int (*load_translation_file) (const char *file, uint8 lang_id);
+ int (*load_translation) (const char *directory, uint8 lang_id);
int (*translation_db_destroyer) (union DBKey key, struct DBData *data, va_list ap);
void (*clear_translations) (bool reload);
int (*parse_cleanup_timer) (int tid, int64 tick, int id, intptr_t data);
uint8 (*add_language) (const char *name);
- const char *(*get_translation_file_name) (const char *file);
+ const char *(*get_translation_dir_name) (const char *directory);
void (*parser_clean_leftovers) (void);
void (*run_use_script) (struct map_session_data *sd, struct item_data *data, int oid);
void (*run_item_equip_script) (struct map_session_data *sd, struct item_data *data, int oid);
void (*run_item_unequip_script) (struct map_session_data *sd, struct item_data *data, int oid);
+ void (*run_item_rental_end_script) (struct map_session_data *sd, struct item_data *data, int oid);
+ void (*run_item_rental_start_script) (struct map_session_data *sd, struct item_data *data, int oid);
+ void (*run_item_lapineddukddak_script) (struct map_session_data *sd, struct item_data *data, int oid);
+ bool (*sellitemcurrency_add) (struct npc_data *nd, struct script_state* st, int argIndex);
};
#ifdef HERCULES_CORE
diff --git a/src/map/searchstore.c b/src/map/searchstore.c
index 560063e8b..a2f00bb0a 100644
--- a/src/map/searchstore.c
+++ b/src/map/searchstore.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,14 +27,16 @@
#include "map/pc.h" // struct map_session_data
#include "common/cbasetypes.h"
#include "common/memmgr.h" // aMalloc, aRealloc, aFree
+#include "common/nullpo.h" // nullpo_*
#include "common/showmsg.h" // ShowError, ShowWarning
#include "common/strlib.h" // safestrncpy
-struct searchstore_interface searchstore_s;
+static struct searchstore_interface searchstore_s;
struct searchstore_interface *searchstore;
/// retrieves search function by type
-static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type) {
+static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type)
+{
switch( type ) {
case SEARCHTYPE_VENDING: return vending->search;
case SEARCHTYPE_BUYING_STORE: return buyingstore->search;
@@ -42,9 +44,9 @@ static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type)
return NULL;
}
-
/// retrieves search-all function by type
-static inline searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type) {
+static inline searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type)
+{
switch( type ) {
case SEARCHTYPE_VENDING: return vending->searchall;
case SEARCHTYPE_BUYING_STORE: return buyingstore->searchall;
@@ -52,9 +54,10 @@ static inline searchstore_searchall_t searchstore_getsearchallfunc(unsigned char
return NULL;
}
-
/// checks if the player has a store by type
-static inline bool searchstore_hasstore(struct map_session_data* sd, unsigned char type) {
+static inline bool searchstore_hasstore(struct map_session_data *sd, unsigned char type)
+{
+ nullpo_retr(false, sd);
switch( type ) {
case SEARCHTYPE_VENDING: return sd->state.vending;
case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore;
@@ -62,9 +65,10 @@ static inline bool searchstore_hasstore(struct map_session_data* sd, unsigned ch
return false;
}
-
/// returns player's store id by type
-static inline unsigned int searchstore_getstoreid(struct map_session_data* sd, unsigned char type) {
+static inline unsigned int searchstore_getstoreid(struct map_session_data *sd, unsigned char type)
+{
+ nullpo_retr(false, sd);
switch( type ) {
case SEARCHTYPE_VENDING: return sd->vender_id;
case SEARCHTYPE_BUYING_STORE: return sd->buyer_id;
@@ -72,8 +76,9 @@ static inline unsigned int searchstore_getstoreid(struct map_session_data* sd, u
return 0;
}
-
-bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect) {
+static bool searchstore_open(struct map_session_data *sd, unsigned int uses, unsigned short effect)
+{
+ nullpo_retr(false, sd);
if( !battle_config.feature_search_stores || sd->searchstore.open ) {
return false;
}
@@ -91,8 +96,11 @@ bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned s
return true;
}
-
-void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count)
+static void searchstore_query(struct map_session_data *sd,
+ unsigned char type,
+ unsigned int min_price, unsigned int max_price,
+ const uint32 *itemlist, unsigned int item_count,
+ const uint32 *cardlist, unsigned int card_count)
{
unsigned int i;
struct map_session_data* pl_sd;
@@ -105,6 +113,7 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
return;
}
+ nullpo_retv(sd);
if( !sd->searchstore.open ) {
return;
}
@@ -126,17 +135,20 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
return;
}
+ nullpo_retv(itemlist);
+ nullpo_retv(cardlist);
+
// validate lists
for( i = 0; i < item_count; i++ ) {
if( !itemdb->exists(itemlist[i]) ) {
- ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]);
+ ShowWarning("searchstore_query: Client resolved item %u is not known.\n", itemlist[i]);
clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
return;
}
}
for( i = 0; i < card_count; i++ ) {
if( !itemdb->exists(cardlist[i]) ) {
- ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]);
+ ShowWarning("searchstore_query: Client resolved card %u is not known.\n", cardlist[i]);
clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
return;
}
@@ -200,9 +212,10 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
}
}
-
/// checks whether or not more results are available for the client
-bool searchstore_querynext(struct map_session_data* sd) {
+static bool searchstore_querynext(struct map_session_data *sd)
+{
+ nullpo_retr(false, sd);
if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages ) {
return true;
}
@@ -210,8 +223,9 @@ bool searchstore_querynext(struct map_session_data* sd) {
return false;
}
-
-void searchstore_next(struct map_session_data* sd) {
+static void searchstore_next(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
if( !battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE )
{// nothing (more) to display
return;
@@ -224,8 +238,9 @@ void searchstore_next(struct map_session_data* sd) {
sd->searchstore.pages++;
}
-
-void searchstore_clear(struct map_session_data* sd) {
+static void searchstore_clear(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
searchstore->clearremote(sd);
if( sd->searchstore.items ) {// release results
@@ -237,8 +252,9 @@ void searchstore_clear(struct map_session_data* sd) {
sd->searchstore.pages = 0;
}
-
-void searchstore_close(struct map_session_data* sd) {
+static void searchstore_close(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
if( sd->searchstore.open ) {
searchstore->clear(sd);
@@ -247,12 +263,13 @@ void searchstore_close(struct map_session_data* sd) {
}
}
-
-void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) {
+static void searchstore_click(struct map_session_data *sd, int account_id, int store_id, int nameid)
+{
unsigned int i;
struct map_session_data* pl_sd;
searchstore_search_t store_search;
+ nullpo_retv(sd);
if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) {
return;
}
@@ -261,7 +278,7 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id
ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid );
if( i == sd->searchstore.count ) {// no such result, crafted
- ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id);
+ ShowWarning("searchstore_click: Received request with item %d of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id);
clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
return;
}
@@ -313,27 +330,31 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id
}
}
-
/// checks whether or not sd has opened account_id's shop remotely
-bool searchstore_queryremote(struct map_session_data* sd, int account_id) {
+static bool searchstore_queryremote(struct map_session_data *sd, int account_id)
+{
+ nullpo_retr(false, sd);
return (bool)( sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id );
}
-
/// removes range-check bypassing for remotely opened stores
-void searchstore_clearremote(struct map_session_data* sd) {
+static void searchstore_clearremote(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
sd->searchstore.remote_id = 0;
}
-
/// receives results from a store-specific callback
-bool searchstore_result(struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine)
+static bool searchstore_result(struct map_session_data *sd, unsigned int store_id, int account_id, const char *store_name, int nameid, unsigned short amount, unsigned int price, const int *card, unsigned char refine_level, const struct item_option *option)
{
struct s_search_store_info_item* ssitem;
+ nullpo_retr(false, sd);
if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) {// no more
return false;
}
+ nullpo_retr(false, store_name);
+ nullpo_retr(false, card);
ssitem = &sd->searchstore.items[sd->searchstore.count++];
ssitem->store_id = store_id;
@@ -343,12 +364,14 @@ bool searchstore_result(struct map_session_data* sd, unsigned int store_id, int
ssitem->amount = amount;
ssitem->price = price;
memcpy(ssitem->card, card, sizeof(ssitem->card));
- ssitem->refine = refine;
+ ssitem->refine = refine_level;
+ memcpy(ssitem->option, option, sizeof(ssitem->option));
return true;
}
-void searchstore_defaults (void) {
+void searchstore_defaults(void)
+{
searchstore = &searchstore_s;
searchstore->open = searchstore_open;
diff --git a/src/map/searchstore.h b/src/map/searchstore.h
index 8edfcd2a8..83705d4ca 100644
--- a/src/map/searchstore.h
+++ b/src/map/searchstore.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -60,8 +60,8 @@ enum e_searchstore_failure {
/// information about the search being performed
struct s_search_store_search {
struct map_session_data* search_sd; // sd of the searching player
- const unsigned short* itemlist;
- const unsigned short* cardlist;
+ const uint32* itemlist;
+ const uint32* cardlist;
unsigned int item_count;
unsigned int card_count;
unsigned int min_price;
@@ -72,11 +72,12 @@ struct s_search_store_info_item {
unsigned int store_id;
int account_id;
char store_name[MESSAGE_SIZE];
- unsigned short nameid;
+ int nameid;
unsigned short amount;
unsigned int price;
- short card[MAX_SLOTS];
+ int card[MAX_SLOTS];
unsigned char refine;
+ struct item_option option[MAX_ITEM_OPTIONS];
};
struct s_search_store_info {
@@ -92,7 +93,7 @@ struct s_search_store_info {
};
/// type for shop search function
-typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid);
+typedef bool (*searchstore_search_t)(struct map_session_data* sd, int nameid);
typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s);
/**
@@ -100,15 +101,15 @@ typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struc
**/
struct searchstore_interface {
bool (*open) (struct map_session_data* sd, unsigned int uses, unsigned short effect);
- void (*query) (struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count);
+ void (*query) (struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const uint32* itemlist, unsigned int item_count, const uint32* cardlist, unsigned int card_count);
bool (*querynext) (struct map_session_data* sd);
void (*next) (struct map_session_data* sd);
void (*clear) (struct map_session_data* sd);
void (*close) (struct map_session_data* sd);
- void (*click) (struct map_session_data* sd, int account_id, int store_id, unsigned short nameid);
+ void (*click) (struct map_session_data* sd, int account_id, int store_id, int nameid);
bool (*queryremote) (struct map_session_data* sd, int account_id);
void (*clearremote) (struct map_session_data* sd);
- bool (*result) (struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine);
+ bool (*result) (struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, int nameid, unsigned short amount, unsigned int price, const int* card, unsigned char refine_level, const struct item_option *option);
};
#ifdef HERCULES_CORE
diff --git a/src/map/skill.c b/src/map/skill.c
index 79f965f67..0ead96472 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
#include "map/battle.h"
#include "map/battleground.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/date.h"
#include "map/elemental.h"
@@ -36,12 +37,14 @@
#include "map/log.h"
#include "map/map.h"
#include "map/mercenary.h"
+#include "map/messages.h"
#include "map/mob.h"
#include "map/npc.h"
#include "map/party.h"
#include "map/path.h"
#include "map/pc.h"
#include "map/pet.h"
+#include "map/refine.h"
#include "map/script.h"
#include "map/status.h"
#include "map/unit.h"
@@ -54,6 +57,7 @@
#include "common/strlib.h"
#include "common/timer.h"
#include "common/utils.h"
+#include "common/conf.h"
#include <math.h>
#include <stdio.h>
@@ -63,27 +67,43 @@
#define SKILLUNITTIMER_INTERVAL 100
-// ranges reserved for mapping skill ids to skilldb offsets
-#define HM_SKILLRANGEMIN 750
-#define HM_SKILLRANGEMAX (HM_SKILLRANGEMIN + MAX_HOMUNSKILL)
-#define MC_SKILLRANGEMIN (HM_SKILLRANGEMAX + 1)
-#define MC_SKILLRANGEMAX (MC_SKILLRANGEMIN + MAX_MERCSKILL)
-#define EL_SKILLRANGEMIN (MC_SKILLRANGEMAX + 1)
-#define EL_SKILLRANGEMAX (EL_SKILLRANGEMIN + MAX_ELEMENTALSKILL)
-#define GD_SKILLRANGEMIN (EL_SKILLRANGEMAX + 1)
-#define GD_SKILLRANGEMAX (GD_SKILLRANGEMIN + MAX_GUILDSKILL)
-
-#if GD_SKILLRANGEMAX > 999
- #error GD_SKILLRANGEMAX is greater than 999
-#endif
-
-struct skill_interface skill_s;
-struct s_skill_dbs skilldbs;
+static struct skill_interface skill_s;
+static struct s_skill_dbs skilldbs;
struct skill_interface *skill;
+static const struct {
+ int start;
+ int end;
+} skill_idx_ranges[] = {
+ { NV_BASIC, NPC_LEX_AETERNA },
+ { KN_CHARGEATK, SA_ELEMENTWIND },
+ { RK_ENCHANTBLADE, AB_SILENTIUM },
+ { WL_WHITEIMPRISON, SC_FEINTBOMB },
+ { LG_CANNONSPEAR, SR_GENTLETOUCH_REVITALIZE },
+ { WA_SWING_DANCE, WA_MOONLIT_SERENADE },
+ { MI_RUSH_WINDMILL, MI_HARMONIZE },
+ { WM_LESSON, WM_UNLIMITED_HUMMING_VOICE },
+ { SO_FIREWALK, SO_EARTH_INSIGNIA },
+ { GN_TRAINING_SWORD, GN_SLINGITEM_RANGEMELEEATK },
+ { AB_SECRAMENT, LG_OVERBRAND_PLUSATK },
+ { ALL_ODINS_RECALL, ALL_LIGHTGUARD },
+ { RL_GLITTERING_GREED, RL_GLITTERING_GREED_ATK },
+ { KO_YAMIKUMO, OB_AKAITSUKI },
+ { ECL_SNOWFLIP, ALL_THANATOS_RECALL },
+ { GC_DARKCROW, NC_MAGMA_ERUPTION_DOTDAMAGE },
+ { SU_BASIC_SKILL, SU_SPIRITOFSEA },
+ { HLIF_HEAL, MH_VOLCANIC_ASH },
+ { MS_BASH, MER_INVINCIBLEOFF2 },
+ { EL_CIRCLE_OF_FIRE, EL_STONE_RAIN },
+ { GD_APPROVAL, GD_DEVELOPMENT },
+ CUSTOM_SKILL_RANGES
+};
+
//Since only mob-casted splash skills can hit ice-walls
-static inline int splash_target(struct block_list* bl) {
+static int skill_splash_target(struct block_list *bl)
+{
+ nullpo_retr(BL_CHAR, bl);
#ifndef RENEWAL
return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR;
#else // Some skills can now hit ground skills(traps, ice wall & etc.)
@@ -92,7 +112,8 @@ static inline int splash_target(struct block_list* bl) {
}
/// Returns the id of the skill, or 0 if not found.
-int skill_name2id(const char* name) {
+static int skill_name2id(const char *name)
+{
if( name == NULL )
return 0;
@@ -101,131 +122,635 @@ int skill_name2id(const char* name) {
/// Maps skill ids to skill db offsets.
/// Returns the skill's array index, or 0 (Unknown Skill).
-int skill_get_index( uint16 skill_id ) {
- // avoid ranges reserved for mapping guild/homun/mercenary skills
- if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX)
- || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX)
- || (skill_id >= MC_SKILLRANGEMIN && skill_id <= MC_SKILLRANGEMAX)
- || (skill_id >= EL_SKILLRANGEMIN && skill_id <= EL_SKILLRANGEMAX) )
+static int skill_get_index(int skill_id)
+{
+ int length = ARRAYLENGTH(skill_idx_ranges);
+
+
+ if (skill_id < skill_idx_ranges[0].start || skill_id > skill_idx_ranges[length - 1].end) {
+ ShowWarning("skill_get_index: skill id '%d' is not being handled!\n", skill_id);
+ Assert_report(0);
return 0;
+ }
- // map skill id to skill db index
- if( skill_id >= GD_SKILLBASE )
- skill_id = GD_SKILLRANGEMIN + skill_id - GD_SKILLBASE;
- else if( skill_id >= EL_SKILLBASE )
- skill_id = EL_SKILLRANGEMIN + skill_id - EL_SKILLBASE;
- else if( skill_id >= MC_SKILLBASE )
- skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE;
- else if( skill_id >= HM_SKILLBASE )
- skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE;
- //[Ind/Hercules] GO GO GO LESS! - http://herc.ws/board/topic/512-skill-id-processing-overhaul/
- else if( skill_id > 1019 && skill_id < 8001 ) {
- if( skill_id < 2058 ) // 1020 - 2000 are empty
- skill_id = 1020 + skill_id - 2001;
- else if( skill_id < 2549 ) // 2058 - 2200 are empty - 1020+57
- skill_id = (1077) + skill_id - 2201;
- else if ( skill_id < 3036 ) // 2549 - 3000 are empty - 1020+57+348
- skill_id = (1425) + skill_id - 3001;
- else if ( skill_id < 5019 ) // 3036 - 5000 are empty - 1020+57+348+35
- skill_id = (1460) + skill_id - 5001;
- else
- ShowWarning("skill_get_index: skill id '%d' is not being handled!\n",skill_id);
+ int skill_idx = 0;
+ bool found = false;
+ // Map Skill ID to Skill Indexes (in reverse order)
+ for (int i = 0; i < length; i++) {
+ // Check if SkillID belongs to this range.
+ if (skill_id <= skill_idx_ranges[i].end && skill_id >= skill_idx_ranges[i].start) {
+ skill_idx += (skill_idx_ranges[i].end - skill_id);
+ found = true;
+ break;
+ }
+ // Add the difference of current range
+ skill_idx += (skill_idx_ranges[i].end - skill_idx_ranges[i].start + 1);
}
- // validate result
- if( !skill_id || skill_id >= MAX_SKILL_DB )
+ if (!found) {
+ ShowWarning("skill_get_index: skill id '%d' (idx: %d) is not handled as it lies outside the defined ranges!\n", skill_id, skill_idx);
+ Assert_report(0);
return 0;
+ }
+ if (skill_idx >= MAX_SKILL_DB) {
+ ShowWarning("skill_get_index: skill id '%d'(idx: %d) is not being handled as it exceeds MAX_SKILL_DB!\n", skill_id, skill_idx);
+ Assert_report(0);
+ return 0;
+ }
- return skill_id;
+ return skill_idx;
}
-const char* skill_get_name( uint16 skill_id ) {
+static const char *skill_get_name(int skill_id)
+{
return skill->dbs->db[skill->get_index(skill_id)].name;
}
-const char* skill_get_desc( uint16 skill_id ) {
+static const char *skill_get_desc(int skill_id)
+{
return skill->dbs->db[skill->get_index(skill_id)].desc;
}
-// out of bounds error checking [celest]
-void skill_chk(uint16* skill_id) {
- *skill_id = skill->get_index(*skill_id); // checks/adjusts id
-}
+#define skill_get_lvl_idx(lv) (min((lv), MAX_SKILL_LEVEL) - 1)
+#define skill_adjust_over_level(val, lv, max_lv) ((val) > 1 ? ((val) + ((lv) - (max_lv)) / 2) : (val))
-#define skill_get(var,id) do { skill->chk(&(id)); if(!(id)) return 0; return (var); } while(0)
-#define skill_get2(var,id,lv) do { \
- skill->chk(&(id)); \
- if(!(id)) return 0; \
- if( (lv) > MAX_SKILL_LEVEL && (var) > 1 ) { \
- int lv2__ = (lv); (lv) = skill->dbs->db[(id)].max; \
- return (var) + ((lv2__-(lv))/2);\
- } \
- return (var);\
-} while(0)
-#define skill_glv(lv) min((lv),MAX_SKILL_LEVEL-1)
// Skill DB
-int skill_get_hit( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].hit, skill_id); }
-int skill_get_inf( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf, skill_id); }
-int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get (skill->dbs->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); }
-int skill_get_nk( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].nk, skill_id); }
-int skill_get_max( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].max, skill_id); }
-int skill_get_range( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 ( (skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); }
-int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_state(uint16 skill_id) { skill_get (skill->dbs->db[skill_id].state, skill_id); }
-int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].itemid[idx], skill_id); }
-int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].amount[idx], skill_id); }
-int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castdef( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].cast_def_rate, skill_id); }
-int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].weapon, skill_id); }
-int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].ammo, skill_id); }
-int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_inf2( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf2, skill_id); }
-int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].castcancel, skill_id); }
-int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_type( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].skill_type, skill_id); }
-int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->dbs->db[skill_id].unit_id[flag], skill_id); }
-int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_interval, skill_id); }
-int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BCT_ALL, skill_id); }
-int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BL_ALL, skill_id); }
-int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_flag, skill_id); }
-int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) {
+
+static int skill_get_hit(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].hit;
+}
+
+static int skill_get_inf(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return INF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(INF_NONE, idx != 0);
+ return skill->dbs->db[idx].inf;
+}
+
+static int skill_get_ele(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return ELE_NEUTRAL;
+ idx = skill->get_index(skill_id);
+ Assert_retr(ELE_NEUTRAL, idx != 0);
+ Assert_retr(ELE_NEUTRAL, skill_lv > 0);
+ return skill->dbs->db[idx].element[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_nk(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return NK_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(NK_NONE, idx != 0);
+ return skill->dbs->db[idx].nk;
+}
+
+static int skill_get_max(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].max;
+}
+
+static int skill_get_range(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].range[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].range[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_splash(int skill_id, int skill_lv)
+{
+ int idx, val;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ val = skill->dbs->db[idx].splash[skill_get_lvl_idx(skill_lv)];
+ if (val < 0) {
+ val = AREA_SIZE;
+ }
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return val;
+}
+
+static int skill_get_hp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].hp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].hp[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_sp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].sp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].sp[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_hp_rate(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].hp_rate[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].hp_rate[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_sp_rate(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].sp_rate[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].sp_rate[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_state(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return ST_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(ST_NONE, idx != 0);
+ return skill->dbs->db[idx].state;
+}
+
+static int skill_get_spiritball(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].spiritball[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].spiritball[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_itemid(int skill_id, int item_idx)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(item_idx >= 0 && item_idx < MAX_SKILL_ITEM_REQUIRE);
+ return skill->dbs->db[idx].itemid[item_idx];
+}
+
+static int skill_get_itemqty(int skill_id, int item_idx)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(item_idx >= 0 && item_idx < MAX_SKILL_ITEM_REQUIRE);
+ return skill->dbs->db[idx].amount[item_idx];
+}
+
+static int skill_get_zeny(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].zeny[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].zeny[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_num(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].num[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].num[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_cast(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].cast[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].cast[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_delay(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].delay[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].delay[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_walkdelay(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].walkdelay[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].walkdelay[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_time(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].upkeep_time[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].upkeep_time[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_time2(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].upkeep_time2[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].upkeep_time2[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_castdef(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].cast_def_rate;
+}
+
+static int skill_get_weapontype(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].weapon;
+}
+
+static int skill_get_ammotype(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].ammo;
+}
+
+static int skill_get_ammo_qty(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].ammo_qty[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].ammo_qty[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_inf2(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return INF2_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(INF2_NONE, idx != 0);
+ return skill->dbs->db[idx].inf2;
+}
+
+static int skill_get_castcancel(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].castcancel;
+}
+
+static int skill_get_maxcount(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].maxcount[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].maxcount[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_blewcount(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].blewcount[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].blewcount[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_mhp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].mhp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].mhp[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_castnodex(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].castnodex[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].castnodex[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_delaynodex(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].delaynodex[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].delaynodex[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_type(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BF_NONE, idx != 0);
+ return skill->dbs->db[idx].skill_type;
+}
+
+static int skill_get_unit_id(int skill_id, int flag)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(flag >= 0 && flag < ARRAYLENGTH(skill->dbs->db[0].unit_id));
+ return skill->dbs->db[idx].unit_id[flag];
+}
+
+static int skill_get_unit_interval(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].unit_interval;
+}
+
+static int skill_get_unit_range(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].unit_range[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].unit_range[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_unit_target(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BCT_NOONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BCT_NOONE, idx != 0);
+ return skill->dbs->db[idx].unit_target & BCT_ALL;
+}
+
+static int skill_get_unit_bl_target(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BL_NUL;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BL_NUL, idx != 0);
+ return skill->dbs->db[idx].unit_target & BL_ALL;
+}
+
+static int skill_get_unit_flag(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return UF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(UF_NONE, idx != 0);
+ return skill->dbs->db[idx].unit_flag;
+}
+
+static int skill_get_unit_layout_type(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].unit_layout_type[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].unit_layout_type[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_cooldown(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].cooldown[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].cooldown[skill_get_lvl_idx(skill_lv)];
+}
+
+static int skill_get_fixed_cast(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
#ifdef RENEWAL_CAST
- Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].fixed_cast[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].fixed_cast[skill_get_lvl_idx(skill_lv)];
#else
return 0;
#endif
}
-int skill_tree_get_max(uint16 skill_id, int b_class)
+
+static int skill_tree_get_max(int skill_id, int class)
{
int i;
- b_class = pc->class2idx(b_class);
+ int class_idx = pc->class2idx(class);
- ARR_FIND( 0, MAX_SKILL_TREE, i, pc->skill_tree[b_class][i].id == 0 || pc->skill_tree[b_class][i].id == skill_id );
- if( i < MAX_SKILL_TREE && pc->skill_tree[b_class][i].id == skill_id )
- return pc->skill_tree[b_class][i].max;
+ ARR_FIND( 0, MAX_SKILL_TREE, i, pc->skill_tree[class_idx][i].id == 0 || pc->skill_tree[class_idx][i].id == skill_id );
+ if( i < MAX_SKILL_TREE && pc->skill_tree[class_idx][i].id == skill_id )
+ return pc->skill_tree[class_idx][i].max;
else
return skill->get_max(skill_id);
}
-int skill_get_casttype (uint16 skill_id) {
+static int skill_get_casttype(int skill_id)
+{
int inf = skill->get_inf(skill_id);
if (inf&(INF_GROUND_SKILL))
return CAST_GROUND;
@@ -241,8 +766,11 @@ int skill_get_casttype (uint16 skill_id) {
return CAST_DAMAGE;
}
-int skill_get_casttype2 (uint16 index) {
- int inf = skill->dbs->db[index].inf;
+static int skill_get_casttype2(int index)
+{
+ int inf;
+ Assert_retr(CAST_NODAMAGE, index < MAX_SKILL_DB);
+ inf = skill->dbs->db[index].inf;
if (inf&(INF_GROUND_SKILL))
return CAST_GROUND;
if (inf&INF_SUPPORT_SKILL)
@@ -258,7 +786,8 @@ int skill_get_casttype2 (uint16 index) {
}
//Returns actual skill range taking into account attack range and AC_OWL [Skotlex]
-int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
+static int skill_get_range2(struct block_list *bl, int skill_id, int skill_lv)
+{
int range;
struct map_session_data *sd = BL_CAST(BL_PC, bl);
if( bl->type == BL_MOB && battle_config.mob_ai&0x400 )
@@ -292,7 +821,7 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
if (sd != NULL)
range += pc->checkskill(sd, AC_VULTURE);
else
- range += 10; //Assume level 10?
+ range += battle->bc->mob_eye_range_bonus;
break;
// added to allow GS skills to be effected by the range of Snake Eyes [Reddozen]
case GS_RAPIDSHOWER:
@@ -303,7 +832,7 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
if (sd != NULL)
range += pc->checkskill(sd, GS_SNAKEEYE);
else
- range += 10; //Assume level 10?
+ range += battle->bc->mob_eye_range_bonus;
break;
case NJ_KIRIKAGE:
if (sd != NULL)
@@ -346,7 +875,8 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
return range;
}
-int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal) {
+static int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal)
+{
int skill2_lv, hp;
struct map_session_data *sd = BL_CAST(BL_PC, src);
struct map_session_data *tsd = BL_CAST(BL_PC, target);
@@ -354,7 +884,10 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
nullpo_ret(src);
- switch( skill_id ) {
+ switch (skill_id) {
+ case SU_TUNABELLY:
+ hp = status_get_max_hp(target) * ((20 * skill_lv) - 10) / 100;
+ break;
case BA_APPLEIDUN:
#ifdef RENEWAL
hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery
@@ -386,6 +919,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
hp += hp * skill2_lv * 2 / 100;
else if (src->type == BL_HOM && (skill2_lv = homun->checkskill(BL_UCAST(BL_HOM, src), HLIF_BRAIN)) > 0)
hp += hp * skill2_lv * 2 / 100;
+ if (sd != NULL && ((skill2_lv = pc->checkskill(sd, SU_POWEROFSEA)) > 0)) {
+ hp += hp * 10 / 100;
+ if (pc->checkskill(sd, SU_TUNABELLY) == 5 && pc->checkskill(sd, SU_TUNAPARTY) == 5 && pc->checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc->checkskill(sd, SU_FRESHSHRIMP) == 5)
+ hp += hp * 20 / 100;
+ }
break;
}
@@ -411,6 +949,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
hp -= hp * 20/100;
if(sc->data[SC_HEALPLUS] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN)
hp += hp * sc->data[SC_HEALPLUS]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
+ if (sc->data[SC_VITALIZE_POTION] != NULL && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN)
+ hp += hp * sc->data[SC_VITALIZE_POTION]->val3 / 100;
if(sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
hp += hp / 10;
if (sc->data[SC_VITALITYACTIVATION])
@@ -433,19 +973,21 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
}
// Making plagiarize check its own function [Aru]
-int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* bl)
+static int can_copy(struct map_session_data *sd, uint16 skill_id, struct block_list *bl)
{
+ nullpo_ret(sd);
// Never copy NPC/Wedding Skills
if (skill->get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL))
return 0;
- // High-class skills
- if((skill_id >= LK_AURABLADE && skill_id <= ASC_CDP) || (skill_id >= ST_PRESERVE && skill_id <= CR_CULTIVATION))
- {
- if(battle_config.copyskill_restrict == 2)
+ // Transcendent-class skills
+ if((skill_id >= LK_AURABLADE && skill_id <= ASC_CDP) || (skill_id >= ST_PRESERVE && skill_id <= CR_CULTIVATION)) {
+ if (battle_config.copyskill_restrict == 2) {
return 0;
- else if(battle_config.copyskill_restrict)
- return (sd->status.class_ == JOB_STALKER);
+ } else if (battle_config.copyskill_restrict == 1) {
+ if ((sd->job & (MAPID_UPPERMASK | JOBL_UPPER)) != MAPID_STALKER)
+ return 0;
+ }
}
//Added so plagarize can't copy agi/bless if you're undead since it damages you
@@ -454,18 +996,21 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
skill_id == MER_INCAGI || skill_id == MER_BLESSING))
return 0;
- // Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie]
- if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE)))
+ // Couldn't preserve 3rd Class/Summoner skills except only when using Reproduce skill. [Jobbie]
+ if (!(sd->sc.data[SC__REPRODUCE]) &&
+ ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) ||
+ (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) ||
+ (skill_id >= GC_DARKCROW && skill_id <= SU_FRESHSHRIMP)))
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
- else if( sd->sc.data[SC__REPRODUCE] && !skill->dbs->reproduce_db[skill->get_index(skill_id)] )
+ else if (sd->sc.data[SC__REPRODUCE] && (skill->get_inf2(skill_id) & INF2_ALLOW_REPRODUCE) == 0)
return 0;
return 1;
}
// [MouseJstr] - skill ok to cast? and when?
-int skillnotok (uint16 skill_id, struct map_session_data *sd)
+static int skillnotok(uint16 skill_id, struct map_session_data *sd)
{
int16 idx,m;
nullpo_retr (1, sd);
@@ -481,21 +1026,21 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL))
return 0; // can do any damn thing they want
- if( skill_id == AL_TELEPORT && sd->skillitem == skill_id && sd->skillitemlv > 2 )
- return 0; // Teleport lv 3 bypasses this check.[Inkfish]
+ if (skill_id == AL_TELEPORT && sd->autocast.type == AUTOCAST_ITEM && sd->autocast.skill_lv > 2)
+ return 0; // Teleport level 3 and higher bypasses this check if cast by itemskill() script commands.
// Epoque:
// This code will compare the player's attack motion value which is influenced by ASPD before
// allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as
// AC_DOUBLE which do not have a skill delay and are not regarded in terms of attack motion.
- if( !sd->state.autocast && sd->skillitem != skill_id && sd->canskill_tick &&
+ if (sd->autocast.type == AUTOCAST_NONE && sd->canskill_tick != 0 &&
DIFF_TICK(timer->gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (battle_config.skill_amotion_leniency) / 100) )
{// attempted to cast a skill before the attack motion has finished
return 1;
}
if (sd->blockskill[idx]) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return 1;
}
@@ -503,7 +1048,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
* It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions below
* Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map
**/
- if( sd->skillitem == skill_id )
+ if (sd->autocast.type == AUTOCAST_ITEM)
return 0;
if( sd->sc.data[SC_ALL_RIDING] )
@@ -542,21 +1087,22 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
//char output[150];
//sprintf(output, msg_txt(862), battle_config.min_npc_vendchat_distance); // "You're too close to a NPC, you must be at least %d cells away from any NPC."
//clif->message(sd->fd, output);
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_THERE_ARE_NPC_AROUND, 0, 0);
return 1;
}
+ FALLTHROUGH
case MC_IDENTIFY:
return 0; // always allowed
case WZ_ICEWALL:
// noicewall flag [Valaris]
if (map->list[m].flag.noicewall) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
break;
case GC_DARKILLUSION:
if( map_flag_gvg2(m) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
break;
@@ -565,7 +1111,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
|| !(battle_config.emergency_call&(map->list[m].flag.gvg || map->list[m].flag.gvg_castle?8:4))
|| (battle_config.emergency_call&16 && map->list[m].flag.nowarpto && !map->list[m].flag.gvg_castle)
) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
break;
@@ -579,12 +1125,21 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
return 1;
}
break;
-
+ default:
+ return skill->not_ok_unknown(skill_id, sd);
}
return (map->list[m].flag.noskill);
}
-int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
+static int skill_notok_unknown(uint16 skill_id, struct map_session_data *sd)
+{
+ int16 m;
+ nullpo_retr (1, sd);
+ m = sd->bl.m;
+ return (map->list[m].flag.noskill);
+}
+
+static int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
{
uint16 idx = skill->get_index(skill_id);
nullpo_retr(1,hd);
@@ -598,7 +1153,7 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
case MH_LIGHT_OF_REGENE:
if( homun->get_intimacy_grade(hd) != 4 ){
if( hd->master )
- clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_RELATIONGRADE, 0);
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_RELATIONGRADE, 0, 0);
return 1;
}
break;
@@ -610,13 +1165,22 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
if(hd->sc.data[SC_GOLDENE_FERSE])
return 1;
break;
+ default:
+ return skill->not_ok_hom_unknown(skill_id, hd);
}
//Use master's criteria.
return skill->not_ok(skill_id, hd->master);
}
-int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md)
+static int skillnotok_hom_unknown(uint16 skill_id, struct homun_data *hd)
+{
+ nullpo_retr(1, hd);
+ //Use master's criteria.
+ return skill->not_ok(skill_id, hd->master);
+}
+
+static int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md)
{
uint16 idx = skill->get_index(skill_id);
nullpo_retr(1,md);
@@ -629,10 +1193,36 @@ int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md)
return skill->not_ok(skill_id, md->master);
}
-struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y) {
+/**
+ * Validates the plausibility of auto-cast related data and calls pc_autocast_clear() if necessary.
+ *
+ * @param sd The character who cast the skill.
+ * @param skill_id The cast skill's ID.
+ * @param skill_lv The cast skill's level. (clif_parse_UseSkillMap() passes 0.)
+ *
+ **/
+static void skill_validate_autocast_data(struct map_session_data *sd, int skill_id, int skill_lv)
+{
+ nullpo_retv(sd);
+
+ // Determine if called by clif_parse_UseSkillMap().
+ bool use_skill_map = (skill_lv == 0 && (skill_id == AL_WARP || skill_id == AL_TELEPORT));
+
+ if (sd->autocast.type == AUTOCAST_NONE)
+ pc->autocast_clear(sd); // No auto-cast type set. Preventively unset all auto-cast related data.
+ else if (sd->autocast.type == AUTOCAST_TEMP)
+ pc->autocast_clear(sd); // AUTOCAST_TEMP should have been unset straight after usage.
+ else if (sd->autocast.skill_id == 0 || skill_id == 0 || sd->autocast.skill_id != skill_id)
+ pc->autocast_clear(sd); // Implausible skill ID.
+ else if (sd->autocast.skill_lv == 0 || (!use_skill_map && (skill_lv == 0 || sd->autocast.skill_lv != skill_lv)))
+ pc->autocast_clear(sd); // Implausible skill level.
+}
+
+static struct s_skill_unit_layout *skill_get_unit_layout(uint16 skill_id, uint16 skill_lv, struct block_list *src, int x, int y)
+{
int pos = skill->get_unit_layout_type(skill_id,skill_lv);
- uint8 dir;
+ nullpo_retr(&skill->dbs->unit_layout[0], src);
if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) {
ShowError("skill_get_unit_layout: unsupported layout type %d for skill %d (level %d)\n", pos, skill_id, skill_lv);
pos = cap_value(pos, 0, MAX_SQUARE_LAYOUT); // cap to nearest square layout
@@ -641,7 +1231,9 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill
if (pos != -1) // simple single-definition layout
return &skill->dbs->unit_layout[pos];
- dir = (src->x == x && src->y == y) ? 6 : map->calc_dir(src,x,y); // 6 - default aegis direction
+ enum unit_dir dir = UNIT_DIR_EAST; // default aegis direction
+ if (src->x != x || src->y != y)
+ dir = map->calc_dir(src, x, y);
if (skill_id == MG_FIREWALL)
return &skill->dbs->unit_layout [skill->firewall_unit_pos + dir];
@@ -657,7 +1249,8 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill
/*==========================================
*
*------------------------------------------*/
-int skill_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick) {
+static int skill_additional_effect(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick)
+{
struct map_session_data *sd, *dstsd;
struct mob_data *md, *dstmd;
struct status_data *sstatus, *tstatus;
@@ -761,7 +1354,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break; // If a normal attack is a skill, it's splash damage. [Inkfish]
if(sd) {
// Automatic trigger of Blitz Beat
- if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (temp=pc->checkskill(sd,HT_BLITZBEAT))>0 &&
+ if (pc_isfalcon(sd) && sd->weapontype == W_BOW && (temp=pc->checkskill(sd,HT_BLITZBEAT))>0 &&
rnd()%1000 <= sstatus->luk*3 ) {
rate = sd->status.job_level / 10 + 1;
skill->castend_damage_id(src,bl,HT_BLITZBEAT,(temp<rate)?temp:rate,tick,SD_LEVEL);
@@ -770,13 +1363,13 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if( pc_iswug(sd) && (temp=pc->checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*3 )
skill->castend_damage_id(src,bl,RA_WUGSTRIKE,temp,tick,0);
// Gank
- if(dstmd && sd->status.weapon != W_BOW &&
+ if(dstmd && sd->weapontype != W_BOW &&
(temp=pc->checkskill(sd,RG_SNATCHER)) > 0 &&
(temp*15 + 55) + pc->checkskill(sd,TF_STEAL)*10 > rnd()%1000) {
if(pc->steal_item(sd,bl,pc->checkskill(sd,TF_STEAL)))
clif->skill_nodamage(src,bl,TF_STEAL,temp,1);
else
- clif->skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, RG_SNATCHER, USESKILL_FAIL_LEVEL, 0, 0);
}
// Chance to trigger Taekwon kicks [Dralnu]
if(sc && !sc->data[SC_COMBOATTACK]) {
@@ -842,7 +1435,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (!sc_start2(src,bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv))
&& sd && skill_id==TF_POISON
)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case AS_SONICBLOW:
@@ -860,7 +1453,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (!sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv))
&& sd && skill_id == MG_FROSTDIVER
)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
#ifdef RENEWAL
@@ -869,6 +1462,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
#endif
+ case WZ_HEAVENDRIVE:
+ status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
+ break;
+
case WZ_STORMGUST:
/**
* Storm Gust counter was dropped in renewal
@@ -1102,8 +1699,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case TK_JUMPKICK:
- if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] )
- {// debuff the following statuses
+ if (dstsd != NULL && (dstsd->job & MAPID_UPPERMASK) != MAPID_SOUL_LINKER && tsc->data[SC_PRESERVE] == NULL) {
+ // debuff the following statuses
status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
status_change_end(bl, SC_KAITE, INVALID_TIMER);
@@ -1382,6 +1979,25 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
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;
+ /**
+ * Summoner
+ */
+ case SU_SCRATCH:
+ sc_start2(src, bl, SC_BLOODING, (skill_lv * 3), skill_lv, src->id, skill->get_time(skill_id, skill_lv)); // TODO: What's the chance/time?
+ break;
+ case SU_SV_STEMSPEAR:
+ sc_start2(src, bl, SC_BLOODING, 10, skill_lv, src->id, skill->get_time(skill_id, skill_lv));
+ break;
+ case SU_CN_METEOR:
+ sc_start(src, bl, SC_CURSE, 10, skill_lv, skill->get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
+ break;
+ case SU_SCAROFTAROU:
+ sc_start(src, bl, SC_STUN, 10, skill_lv, skill->get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
+ break;
+ case SU_LUNATICCARROTBEAT:
+ if (skill->area_temp[3] == 1)
+ sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time(skill_id, skill_lv)); // TODO: What's the chance/time?
+ break;
default:
skill->additional_effect_unknown(src, bl, &skill_id, &skill_lv, &attack_type, &dmg_lv, &tick);
break;
@@ -1469,7 +2085,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
ud->canact_tick = tick+rate;
if ( battle_config.display_status_timers )
- clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0);
}
}
}
@@ -1490,9 +2106,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
temp = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -1543,21 +2159,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
else if (temp == PF_SPIDERWEB) //Special case, due to its nature of coding.
type = CAST_GROUND;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,auto_skill_lv,1);
skill->toggle_magicpower(src, temp);
- switch (type) {
- case CAST_GROUND:
- skill->castend_pos2(src, tbl->x, tbl->y, temp, auto_skill_lv, tick, 0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, tbl, temp, auto_skill_lv, tick, 0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(src, tbl, temp, auto_skill_lv, tick, 0);
- break;
- }
- sd->state.autocast = 0;
+ skill->castend_type(type, src, tbl, temp, auto_skill_lv, tick, 0);
+ sd->autocast.type = AUTOCAST_NONE;
+
//Set canact delay. [Skotlex]
ud = unit->bl2ud(src);
if (ud) {
@@ -1565,7 +2172,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
ud->canact_tick = tick+rate;
if (battle_config.display_status_timers)
- clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0);
}
}
}
@@ -1614,16 +2221,21 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
return 0;
}
-void skill_additional_effect_unknown(struct block_list* src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int *attack_type, int *dmg_lv, int64 *tick) {
+static void skill_additional_effect_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int *attack_type, int *dmg_lv, int64 *tick)
+{
}
-int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick) {
+static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick)
+{
int temp, skill_lv, i, type, notok;
struct block_list *tbl;
if( sd == NULL || !skill_id )
return 0;
+ // Preserve auto-cast type if bAutoSpellOnSkill was triggered by a skill which was cast by Abracadabra, Improvised Song or an item.
+ enum autocast_type ac_type = sd->autocast.type;
+
for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ ) {
if( sd->autospell3[i].flag != skill_id )
continue;
@@ -1633,9 +2245,9 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
temp = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -1681,18 +2293,16 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
!battle->check_range(&sd->bl, tbl, skill->get_range2(&sd->bl, temp,skill_lv) + (temp == RG_CLOSECONFINE?0:1)) )
continue;
- sd->state.autocast = 1;
sd->autospell3[i].lock = true;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,skill_lv,1);
- switch( type ) {
- case CAST_GROUND: skill->castend_pos2(&sd->bl, tbl->x, tbl->y, temp, skill_lv, tick, 0); break;
- case CAST_NODAMAGE: skill->castend_nodamage_id(&sd->bl, tbl, temp, skill_lv, tick, 0); break;
- case CAST_DAMAGE: skill->castend_damage_id(&sd->bl, tbl, temp, skill_lv, tick, 0); break;
- }
+ skill->castend_type(type, &sd->bl, tbl, temp, skill_lv, tick, 0);
+ sd->autocast.type = AUTOCAST_NONE;
sd->autospell3[i].lock = false;
- sd->state.autocast = 0;
}
+ sd->autocast.type = ac_type;
+
if (sd->autobonus3[0].rate) {
for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) {
if( rnd()%1000 >= sd->autobonus3[i].rate )
@@ -1715,7 +2325,8 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
* type of skills, so not every instance of skill->additional_effect needs a call
* to this one.
*/
-int skill_counter_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick) {
+static int skill_counter_additional_effect(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick)
+{
int rate;
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
@@ -1789,7 +2400,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
break;
}
- if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
+ if (sd != NULL && (sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
&& 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);
@@ -1799,11 +2410,11 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
) {
// 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 )
+ if (skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id) {
;
- else {
+ } else {
clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
- status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, 2);
+ status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, STATUS_HEAL_SHOWEFFECT);
}
}
@@ -1826,9 +2437,9 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
}
}
- if( hp || sp ) {
+ if (hp != 0 || sp != 0) {
// updated to force healing to allow healing through berserk
- status->heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1);
+ status->heal(src, hp, sp, STATUS_HEAL_FORCED | (battle_config.show_hp_sp_gain ? STATUS_HEAL_SHOWEFFECT : STATUS_HEAL_DEFAULT));
}
}
@@ -1838,6 +2449,9 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
struct unit_data *ud;
int i, auto_skill_id, auto_skill_lv, type, notok;
+ // Preserve auto-cast type if bAutoSpellWhenHit was triggered during cast of a skill which was cast by Abracadabra, Improvised Song or an item.
+ enum autocast_type ac_type = dstsd->autocast.type;
+
for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) {
if(!(dstsd->autospell2[i].flag&attack_type&BF_WEAPONMASK &&
@@ -1853,9 +2467,9 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
if (attack_type&BF_LONG)
rate>>=1;
- dstsd->state.autocast = 1;
+ dstsd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(auto_skill_id, dstsd);
- dstsd->state.autocast = 0;
+ dstsd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -1896,20 +2510,11 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
if( !battle->check_range(src, tbl, skill->get_range2(src, auto_skill_id,auto_skill_lv) + (auto_skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
continue;
- dstsd->state.autocast = 1;
+ dstsd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(dstsd,auto_skill_id,auto_skill_lv,1);
- switch (type) {
- case CAST_GROUND:
- skill->castend_pos2(bl, tbl->x, tbl->y, auto_skill_id, auto_skill_lv, tick, 0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
- break;
- }
- dstsd->state.autocast = 0;
+ skill->castend_type(type, bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
+ dstsd->autocast.type = AUTOCAST_NONE;
+
// Set canact delay. [Skotlex]
ud = unit->bl2ud(bl);
if (ud) {
@@ -1917,10 +2522,12 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
ud->canact_tick = tick+rate;
if (battle_config.display_status_timers)
- clif->status_change(bl, SI_POSTDELAY, 1, rate, 0, 0, 0);
+ clif->status_change(bl, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0);
}
}
}
+
+ dstsd->autocast.type = ac_type;
}
//Autobonus when attacked
@@ -1942,7 +2549,8 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
return 0;
}
-void skill_counter_additional_effect_unknown(struct block_list* src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int *attack_type, int64 *tick) {
+static void skill_counter_additional_effect_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int *attack_type, int64 *tick)
+{
}
/*=========================================================================
@@ -1951,7 +2559,7 @@ void skill_counter_additional_effect_unknown(struct block_list* src, struct bloc
* - flag is a BCT_ flag to indicate which type of adjustment should be used
* (BCT_ENEMY/BCT_PARTY/BCT_SELF) are the valid values.
*------------------------------------------------------------------------*/
-int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag)
+static int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag)
{
const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM};
const enum sc_type scatk[4] = {SC_NOEQUIPWEAPON, SC_NOEQUIPARMOR, SC_NOEQUIPSHIELD, SC_NOEQUIPHELM};
@@ -1968,7 +2576,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
if (sd->bonus.unbreakable)
rate -= rate*sd->bonus.unbreakable/100;
if (where&EQP_WEAPON) {
- switch (sd->status.weapon) {
+ switch (sd->weapontype) {
case W_FIST: //Bare fists should not break :P
case W_1HAXE:
case W_2HAXE:
@@ -2005,7 +2613,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
if (sd) {
for (i = 0; i < EQI_MAX; i++) {
int j = sd->equip_index[i];
- if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j])
+ if (j < 0 || (sd->status.inventory[j].attribute & ATTR_BROKEN) != 0 || !sd->inventory_data[j])
continue;
switch(i) {
@@ -2031,17 +2639,18 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
continue;
}
if (flag) {
- sd->status.inventory[j].attribute = 1;
+ sd->status.inventory[j].attribute |= ATTR_BROKEN;
pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
}
- clif->equiplist(sd);
+ clif->equipList(sd);
}
return where; //Return list of pieces broken.
}
-int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) {
+static int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time)
+{
struct status_change *sc;
const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC};
const enum sc_type sc_atk[5] = {SC_NOEQUIPWEAPON, SC_NOEQUIPSHIELD, SC_NOEQUIPARMOR, SC_NOEQUIPHELM, SC__STRIPACCESSARY};
@@ -2067,21 +2676,25 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int
}
return where?1:0;
}
+
/*=========================================================================
- Used to knock back players, monsters, traps, etc
- - 'count' is the number of squares to knock back
- - 'direction' indicates the way OPPOSITE to the knockback direction (or -1 for default behavior)
- - if 'flag&0x1', position update packets must not be sent.
- - if 'flag&0x2', skill blown ignores players' special_state.no_knockback
- -------------------------------------------------------------------------*/
-int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag)
+ * Used to knock back players, monsters, traps, etc
+ * 'count' is the number of squares to knock back
+ * 'direction' indicates the way OPPOSITE to the knockback direction (or UNIT_DIR_UNDEFINED for default behavior)
+ * if 'flag&0x1', position update packets must not be sent.
+ * if 'flag&0x2', skill blown ignores players' special_state.no_knockback
+ */
+static int skill_blown(struct block_list *src, struct block_list *target, int count, enum unit_dir dir, int flag)
{
int dx = 0, dy = 0;
+ struct status_change *tsc = status->get_sc(target);
nullpo_ret(src);
if (src != target && map->list[src->m].flag.noknockback)
return 0; // No knocking
+
+ nullpo_ret(target);
if (count == 0)
return 0; // Actual knockback distance is 0.
@@ -2113,15 +2726,18 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
break;
}
- if (dir == -1) // <optimized>: do the computation here instead of outside
+ if (dir == UNIT_DIR_UNDEFINED) // <optimized>: do the computation here instead of outside
dir = map->calc_dir(target, src->x, src->y); // direction from src to target, reversed
- if (dir >= 0 && dir < 8) {
+ if (dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX) {
// take the reversed 'direction' and reverse it
dx = -dirx[dir];
dy = -diry[dir];
}
+ if (tsc != NULL && tsc->data[SC_SU_STOOP]) // Any knockback will cancel it.
+ status_change_end(target, SC_SU_STOOP, INVALID_TIMER);
+
return unit->blown(target, dx, dy, count, flag); // send over the proper flag
}
@@ -2132,10 +2748,12 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
1 - Regular reflection (Maya)
2 - SL_KAITE reflection
*/
-int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) {
+static int skill_magic_reflect(struct block_list *src, struct block_list *bl, int type)
+{
struct status_change *sc = status->get_sc(bl);
struct map_session_data* sd = BL_CAST(BL_PC, bl);
+ nullpo_ret(src);
if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability
return 0;
@@ -2179,9 +2797,14 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type)
* client (causes player characters to not scream skill name)
* flag&0x4000 - Return 0 if damage was reflected
*-------------------------------------------------------------------------*/
-int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static int skill_attack(int attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
struct Damage dmg;
+#if MAGIC_REFLECTION_TYPE
struct status_data *sstatus, *tstatus;
+#else
+ struct status_data *tstatus;
+#endif
struct status_change *sc;
struct map_session_data *sd, *tsd;
int type;
@@ -2216,7 +2839,9 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
)
return 0;
+#if MAGIC_REFLECTION_TYPE
sstatus = status->get_status_data(src);
+#endif
tstatus = status->get_status_data(bl);
sc = status->get_sc(bl);
if (sc && !sc->count) sc = NULL; //Don't need it.
@@ -2322,14 +2947,28 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
}
#endif /* MAGIC_REFLECTION_TYPE */
}
- if(sc && sc->data[SC_MAGICROD] && src == dsrc) {
- int sp = skill->get_sp(skill_id,skill_lv);
+ if (sc && sc->data[SC_MAGICROD] && src == dsrc) {
+ int sp = skill->get_sp(skill_id, skill_lv);
dmg.damage = dmg.damage2 = 0;
dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex]
sp = sp * sc->data[SC_MAGICROD]->val2 / 100;
- if(skill_id == WZ_WATERBALL && skill_lv > 1)
- sp = sp/((skill_lv|1)*(skill_lv|1)); //Estimate SP cost of a single water-ball
- status->heal(bl, 0, sp, 2);
+ if (skill_id == WZ_WATERBALL && skill_lv > 1)
+ sp = sp / ((skill_lv | 1) * (skill_lv | 1)); //Estimate SP cost of a single water-ball
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
+ if (battle->bc->magicrod_type == 1)
+ clif->skill_nodamage(bl, bl, SA_MAGICROD, sc->data[SC_MAGICROD]->val1, 1); // Animation used here in eAthena [Wolfie]
+ }
+ }
+
+ if (bl->type == BL_MOB) {
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if (md != NULL) {
+ if (md->db->dmg_taken_rate != 100) {
+ if (dmg.damage > 0)
+ dmg.damage = apply_percentrate64(dmg.damage, md->db->dmg_taken_rate, 100);
+ if (dmg.damage2 > 0)
+ dmg.damage2 = apply_percentrate64(dmg.damage2, md->db->dmg_taken_rate, 100);
+ }
}
}
@@ -2375,7 +3014,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case TK_STORMKICK:
case TK_DOWNKICK:
case TK_COUNTER:
- if (pc->famerank(sd->status.char_id,MAPID_TAEKWON)) {//Extend combo time.
+ if (pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0) { //Extend combo time.
sce->val1 = skill_id; //Update combo-skill
sce->val3 = skill_id;
if( sce->timer != INVALID_TIMER )
@@ -2493,18 +3132,20 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case KO_MUCHANAGE:
if( dmg.dmg_lv == ATK_FLEE )
break;
+ FALLTHROUGH
case WL_SOULEXPANSION:
case WL_COMET:
case NJ_HUUMA:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,BDT_MULTIHIT);
break;
case WL_CHAINLIGHTNING_ATK:
- dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,BDT_SKILL);
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING_ATK,-2,BDT_SKILL);
break;
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND:
/* Fall through */
dmg.amotion = status_get_amotion(src) * 2;
+ FALLTHROUGH
case LG_OVERBRAND_PLUSATK:
dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH);
break;
@@ -2563,6 +3204,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH);
if( dsrc != src ) // avoid damage display redundancy
break;
+ FALLTHROUGH
case HT_LANDMINE:
dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type);
break;
@@ -2575,6 +3217,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case AB_DUPLELIGHT_MELEE:
case AB_DUPLELIGHT_MAGIC:
dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */
+ FALLTHROUGH
default:
skill->attack_display_unknown(&attack_type, src, dsrc, bl, &skill_id, &skill_lv, &tick, &flag, &type, &dmg, &damage);
break;
@@ -2644,8 +3287,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
}
tsd->reproduceskill_id = copy_skill;
- pc_setglobalreg(tsd, script->add_str("REPRODUCE_SKILL"), copy_skill);
- pc_setglobalreg(tsd, script->add_str("REPRODUCE_SKILL_LV"), lv);
+ pc_setglobalreg(tsd, script->add_variable("REPRODUCE_SKILL"), copy_skill);
+ pc_setglobalreg(tsd, script->add_variable("REPRODUCE_SKILL_LV"), lv);
tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
@@ -2668,8 +3311,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
lv = plagiarismlvl;
tsd->cloneskill_id = copy_skill;
- pc_setglobalreg(tsd, script->add_str("CLONE_SKILL"), copy_skill);
- pc_setglobalreg(tsd, script->add_str("CLONE_SKILL_LV"), lv);
+ pc_setglobalreg(tsd, script->add_variable("CLONE_SKILL"), copy_skill);
+ pc_setglobalreg(tsd, script->add_variable("CLONE_SKILL_LV"), lv);
tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
@@ -2708,7 +3351,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
//Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex]
//Reflected spells do not bounce back (bl == dsrc since it only happens for direct skills)
if (dmg.blewcount > 0 && bl!=dsrc && !status->isdead(bl)) {
- int8 dir = -1; // default
+ enum unit_dir dir = UNIT_DIR_UNDEFINED; // default
switch(skill_id) {//direction
case MG_FIREWALL:
case PR_SANCTUARY:
@@ -2721,13 +3364,13 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
if(!battle_config.stormgust_knockback)
- dir = rnd()%8;
+ dir = rnd() % UNIT_DIR_MAX;
break;
case WL_CRIMSONROCK:
dir = map->calc_dir(bl,skill->area_temp[4],skill->area_temp[5]);
break;
case MC_CARTREVOLUTION:
- dir = 6; // Official servers push target to the West
+ dir = UNIT_DIR_EAST; // Official servers push target to the West
break;
default:
dir = skill->attack_dir_unknown(&attack_type, src, dsrc, bl, &skill_id, &skill_lv, &tick, &flag);
@@ -2748,8 +3391,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case SR_KNUCKLEARROW:
if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) && !(flag&4) ) {
short dir_x, dir_y;
- dir_x = dirx[(dir+4)%8];
- dir_y = diry[(dir+4)%8];
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ dir_x = dirx[unit_get_opposite_dir(dir)];
+ dir_y = diry[unit_get_opposite_dir(dir)];
if (map->getcell(bl->m, bl, bl->x + dir_x, bl->y + dir_y, CELL_CHKNOPASS) != 0)
skill->addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
}
@@ -2870,15 +3517,27 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
return (int)cap_value(damage,INT_MIN,INT_MAX);
}
-void skill_attack_combo1_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_change_entry *sce, int *combo) {
+static void skill_attack_combo1_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_change_entry *sce, int *combo)
+{
if (src == dsrc) // Ground skills are exceptions. [Inkfish]
status_change_end(src, SC_COMBOATTACK, INVALID_TIMER);
}
-void skill_attack_combo2_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *combo) {
+static void skill_attack_combo2_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *combo)
+{
}
-void skill_attack_display_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage) {
+static void skill_attack_display_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage)
+{
+ nullpo_retv(bl);
+ nullpo_retv(dmg);
+ nullpo_retv(tick);
+ nullpo_retv(flag);
+ nullpo_retv(damage);
+ nullpo_retv(skill_id);
+ nullpo_retv(skill_lv);
+ nullpo_retv(type);
+
if (*flag & SD_ANIMATION && dmg->div_ < 2) //Disabling skill animation doesn't works on multi-hit.
*type = BDT_SPLASH;
if (bl->type == BL_SKILL) {
@@ -2889,24 +3548,36 @@ void skill_attack_display_unknown(int *attack_type, struct block_list* src, stru
dmg->dmotion = clif->skill_damage(dsrc, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, *type);
}
-int skill_attack_copy_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
- return *skill_id;
+static int skill_attack_copy_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+{
+ nullpo_ret(skill_id);
+ return *skill_id;
}
-int skill_attack_dir_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
- return -1;
+static int skill_attack_dir_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+{
+ return UNIT_DIR_UNDEFINED;
}
-void skill_attack_blow_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, int8 *dir) {
+static void skill_attack_blow_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl,
+ uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type,
+ struct Damage *dmg, int64 *damage, enum unit_dir *dir)
+{
+ nullpo_retv(bl);
+ nullpo_retv(dmg);
+ nullpo_retv(dir);
+ nullpo_retv(damage);
+
skill->blown(dsrc, bl, dmg->blewcount, *dir, 0x0);
if (!dmg->blewcount && bl->type == BL_SKILL && *damage > 0){
struct skill_unit *su = BL_UCAST(BL_SKILL, bl);
if (su->group && su->group->skill_id == HT_BLASTMINE)
- skill->blown(src, bl, 3, -1, 0);
+ skill->blown(src, bl, 3, UNIT_DIR_UNDEFINED, 0);
}
}
-void skill_attack_post_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
+static void skill_attack_post_unknown(int *attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+{
}
/*==========================================
@@ -2914,7 +3585,8 @@ void skill_attack_post_unknown(int *attack_type, struct block_list* src, struct
* 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) {
+static int skill_area_sub(struct block_list *bl, va_list ap)
+{
struct block_list *src;
uint16 skill_id,skill_lv;
int flag;
@@ -2943,7 +3615,7 @@ int skill_area_sub(struct block_list *bl, va_list ap) {
return 0;
}
-int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
+static int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
{
const struct skill_unit *su = NULL;
uint16 skill_id,g_skill_id;
@@ -2965,6 +3637,7 @@ int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
case AL_PNEUMA:
if(g_skill_id == SA_LANDPROTECTOR)
break;
+ FALLTHROUGH
case MG_SAFETYWALL:
case MH_STEINWAND:
case SC_MAELSTROM:
@@ -3013,7 +3686,8 @@ int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
return 1;
}
-int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) {
+static int skill_check_unit_range(struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv)
+{
//Non players do not check for the skill's splash-trigger area.
int range = bl->type == BL_PC ? skill->get_unit_range(skill_id, skill_lv):0;
int layout_type = skill->get_unit_layout_type(skill_id,skill_lv);
@@ -3026,7 +3700,8 @@ int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id
return map->foreachinarea(skill->check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skill_id);
}
-int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) {
+static int skill_check_unit_range2_sub(struct block_list *bl, va_list ap)
+{
uint16 skill_id;
if(bl->prev == NULL)
@@ -3045,7 +3720,8 @@ int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) {
return 1;
}
-int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) {
+static int skill_check_unit_range2(struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv)
+{
int range, type;
switch (skill_id) {
@@ -3088,12 +3764,13 @@ int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_i
* &1: finished casting the skill (invoke hp/sp/item consumption)
* &2: picked menu entry (Warp Portal, Teleport and other menu based skills)
*------------------------------------------*/
-int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, int type) {
+static int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, int type)
+{
struct status_data *st;
struct map_session_data *sd = NULL;
int i, hp, sp, hp_rate, sp_rate, state, mhp;
- uint16 idx;
- int itemid[MAX_SKILL_ITEM_REQUIRE],amount[ARRAYLENGTH(itemid)],index[ARRAYLENGTH(itemid)];
+ int idx;
+ int itemid[MAX_SKILL_ITEM_REQUIRE], amount[MAX_SKILL_ITEM_REQUIRE], index[MAX_SKILL_ITEM_REQUIRE];
if( lv < 1 || lv > MAX_SKILL_LEVEL )
return 0;
@@ -3109,8 +3786,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
return 0;
// Requirements
- for( i = 0; i < ARRAYLENGTH(itemid); i++ )
- {
+ for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
itemid[i] = skill->dbs->db[idx].itemid[i];
amount[i] = skill->dbs->db[idx].amount[i];
}
@@ -3146,11 +3822,11 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
if( !(type&2) ) {
if( hp > 0 && st->hp <= (unsigned int)hp ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0, 0);
return 0;
}
if( sp > 0 && st->sp <= (unsigned int)sp ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0);
return 0;
}
}
@@ -3159,7 +3835,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
switch( state ) {
case ST_MOVE_ENABLE:
if( !unit->can_move(bl) ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -3173,7 +3849,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
if (itemid[i] < 1) continue; // No item
index[i] = pc->search_inventory(sd, itemid[i]);
if (index[i] == INDEX_NOT_FOUND || sd->status.inventory[index[i]].amount < amount[i]) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i]|(itemid[i] << 16));
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i], itemid[i]);
return 0;
}
}
@@ -3196,14 +3872,16 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
/*==========================================
* what the hell it doesn't need to receive this many params, it doesn't do anything ~_~
*------------------------------------------*/
-int skill_area_sub_count(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static int skill_area_sub_count(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
return 1;
}
/*==========================================
*
*------------------------------------------*/
-int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
+static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *src = map->id2bl(id),*target = NULL;
struct unit_data *ud = unit->bl2ud(src);
struct skill_timerskill *skl;
@@ -3387,6 +4065,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
skill->blown(src,target,skill->get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 );
break;
}
+ FALLTHROUGH
}
default:
skill->timerskill_target_unknown(tid, tick, src, target, ud, skl);
@@ -3397,7 +4076,8 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
break;
switch( skl->skill_id ) {
case WZ_METEOR:
- if( skl->type >= 0 ) {
+ case SU_CN_METEOR:
+ if (skl->type >= 0) {
int x = skl->type>>16, y = skl->type&0xFFFF;
if( path->search_long(NULL, src, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag);
@@ -3413,6 +4093,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
map->foreachinarea(skill->cell_overlap,src->m,skl->x-i,skl->y-i,skl->x+i,skl->y+i,BL_SKILL,skl->skill_id,&dummy,src);
}
+ FALLTHROUGH
// fall through ...
case WL_EARTHSTRAIN:
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag);
@@ -3433,24 +4114,26 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-bool skill_timerskill_dead_unknown(struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl)
+static bool skill_timerskill_dead_unknown(struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl)
{
return false;
}
-void skill_timerskill_target_unknown(int tid, int64 tick, struct block_list *src, struct block_list *target, struct unit_data *ud, struct skill_timerskill *skl)
+static void skill_timerskill_target_unknown(int tid, int64 tick, struct block_list *src, struct block_list *target, struct unit_data *ud, struct skill_timerskill *skl)
{
+ nullpo_retv(skl);
skill->attack(skl->type, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
}
-void skill_timerskill_notarget_unknown(int tid, int64 tick, struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl)
+static void skill_timerskill_notarget_unknown(int tid, int64 tick, struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl)
{
}
/*==========================================
*
*------------------------------------------*/
-int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) {
+static int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x, int y, uint16 skill_id, uint16 skill_lv, int type, int flag)
+{
int i;
struct unit_data *ud;
nullpo_retr(1, src);
@@ -3479,7 +4162,7 @@ int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,in
/*==========================================
*
*------------------------------------------*/
-int skill_cleartimerskill (struct block_list *src)
+static int skill_cleartimerskill(struct block_list *src)
{
int i;
struct unit_data *ud;
@@ -3512,12 +4195,12 @@ int skill_cleartimerskill (struct block_list *src)
return 1;
}
-bool skill_cleartimerskill_exception(int skill_id)
+static bool skill_cleartimerskill_exception(int skill_id)
{
return false;
}
-int skill_activate_reverberation(struct block_list *bl, va_list ap)
+static int skill_activate_reverberation(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
struct skill_unit_group *sg = NULL;
@@ -3530,14 +4213,14 @@ int skill_activate_reverberation(struct block_list *bl, va_list ap)
if( su->alive && (sg = su->group) != NULL && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) {
int64 tick = timer->gettick();
clif->changetraplook(bl,UNT_USED_TRAPS);
- map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, tick);
+ skill->trap_do_splash(bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
su->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
}
return 0;
}
-int skill_reveal_trap(struct block_list *bl, va_list ap)
+static int skill_reveal_trap(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
@@ -3545,20 +4228,36 @@ int skill_reveal_trap(struct block_list *bl, va_list ap)
Assert_ret(bl->type == BL_SKILL);
su = BL_UCAST(BL_SKILL, bl);
- if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap.
- //Change look is not good enough, the client ignores it as an actual trap still. [Skotlex]
- //clif->changetraplook(bl, su->group->unit_id);
- clif->getareachar_skillunit(&su->bl,su,AREA);
+ if (su->alive && su->group && skill->get_inf2(su->group->skill_id) & INF2_HIDDEN_TRAP) { //Reveal trap.
+ su->visible = true;
+ clif->skillunit_update(bl);
return 1;
}
return 0;
}
+static void skill_castend_type(int type, struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
+ switch (type) {
+ case CAST_GROUND:
+ nullpo_retv(bl);
+ skill->castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, flag);
+ break;
+ case CAST_NODAMAGE:
+ skill->castend_nodamage_id(src, bl, skill_id, skill_lv, tick, flag);
+ break;
+ case CAST_DAMAGE:
+ skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
+ break;
+ }
+}
+
/*==========================================
*
*
*------------------------------------------*/
-int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static int skill_castend_damage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
struct map_session_data *sd = NULL;
struct status_data *tstatus;
struct status_change *sc;
@@ -3744,7 +4443,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if (!(flag&1) && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK) {
//Becomes a splash attack when Soul Linked.
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv),splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->splash_target(src),
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
} else
@@ -3755,14 +4454,14 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
skill->area_temp[1] = 0;
map->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
case KN_CHARGEATK: {
bool path_exists = path->search_long(NULL, src, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL);
unsigned int dist = distance_bl(src, bl);
- uint8 dir = map->calc_dir(bl, src->x, src->y);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
// teleport to target (if not on WoE grounds)
if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground && unit->movepos(src, bl->x, bl->y, 0, 1) )
@@ -3774,7 +4473,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->blown(src, bl, dist, dir, 0);
//HACK: since knockback officially defaults to the left, the client also turns to the left... therefore,
// make the caster look in the direction of the target
- unit->setdir(src, (dir+4)%8);
+ unit->set_dir(src, unit_get_opposite_dir(dir));
}
}
@@ -3791,7 +4490,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
//line of sight between caster and target.
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
@@ -3802,7 +4501,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NPC_THUNDERBREATH:
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
@@ -3813,15 +4512,16 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case RG_BACKSTAP:
{
- uint8 dir = map->calc_dir(src, bl->x, bl->y), t_dir = unit->getdir(bl);
- if ((!check_distance_bl(src, bl, 0) && !map->check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
+ enum unit_dir dir = map->calc_dir(src, bl->x, bl->y);
+ enum unit_dir t_dir = unit->getdir(bl);
+ if ((!check_distance_bl(src, bl, 0) && map->check_dir(dir, t_dir) == 0) || bl->type == BL_SKILL) {
status_change_end(src, SC_HIDING, INVALID_TIMER);
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
- dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
- unit->setdir(bl,dir);
+ dir = unit_get_opposite_dir(dir); // change direction [Celest]
+ unit->set_dir(bl, dir);
}
else if (sd)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -3845,14 +4545,13 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
{
short x, y, i = 2; // Move 2 cells for Issen(from target)
struct block_list *mbl = bl;
- short dir = 0;
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
if( skill_id == MO_EXTREMITYFIST ) {
mbl = src;
i = 3; // for Asura(from caster)
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
#ifdef RENEWAL
@@ -3862,18 +4561,18 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(src, SC_NJ_NEN, INVALID_TIMER);
status_change_end(src, SC_HIDING, INVALID_TIMER);
#ifdef RENEWAL
- status->set_hp(src, max(status_get_max_hp(src)/100, 1), 0);
+ status->set_hp(src, max(status_get_max_hp(src)/100, 1), STATUS_HEAL_DEFAULT);
#else // not RENEWAL
- status->set_hp(src, 1, 0);
+ status->set_hp(src, 1, STATUS_HEAL_DEFAULT);
#endif // RENEWAL
}
- dir = map->calc_dir(src,bl->x,bl->y);
- if( dir > 0 && dir < 4) x = -i;
- else if( dir > 4 ) x = i;
- else x = 0;
- if( dir > 2 && dir < 6 ) y = -i;
- else if( dir == 7 || dir < 2 ) y = i;
- else y = 0;
+ enum unit_dir dir = map->calc_dir(src, bl->x, bl->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ x = i * dirx[dir];
+ y = i * diry[dir];
if ((mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground))) { // only NJ_ISSEN don't have slide effect in GVG
if (!(unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1))) {
// The cell is not reachable (wall, object, ...), move next to the target
@@ -3896,11 +4595,22 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
- //Splash attack skills.
+ case SU_BITE:
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+ if (status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance.
+ skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
+ break;
+
+ case SU_PICKYPECK:
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ break;
+
+ // Splash attack skills.
case AS_GRIMTOOTH:
case MC_CARTREVOLUTION:
case NPC_SPLASHATTACK:
flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
+ FALLTHROUGH
case AS_SPLASHER:
case HT_BLITZBEAT:
case AC_SHOWER:
@@ -3948,7 +4658,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case KO_BAKURETSU:
case GN_ILLUSIONDOPING:
case MH_XENO_SLASHER:
- if( flag&1 ) {//Recursive invocation
+ case SU_SCRATCH:
+ case SU_LUNATICCARROTBEAT:
+ if (flag&1) { //Recursive invocation
// skill->area_temp[0] holds number of targets in area
// skill->area_temp[1] holds the id of the original target
// skill->area_temp[2] counts how many targets have already been processed
@@ -3963,15 +4675,19 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
break;
heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag);
- if( skill_id == NPC_VAMPIRE_GIFT && heal > 0 ) {
+ if (skill_id == NPC_VAMPIRE_GIFT && heal > 0) {
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status->heal(src,heal,0,0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
}
+ if (skill_id == SU_SCRATCH && status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance.
+ skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
} else {
switch ( skill_id ) {
case NJ_BAKUENRYU:
case LG_EARTHDRIVE:
case GN_CARTCANNON:
+ case SU_SCRATCH:
+ case SU_LUNATICCARROTBEAT:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case SR_TIGERCANNON:
@@ -3990,13 +4706,19 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->area_temp[0] = 0;
skill->area_temp[1] = bl->id;
skill->area_temp[2] = 0;
- if( skill_id == WL_CRIMSONROCK ) {
+ if (skill_id == WL_CRIMSONROCK) {
skill->area_temp[4] = bl->x;
skill->area_temp[5] = bl->y;
}
+ if (skill_id == SU_LUNATICCARROTBEAT) {
+ skill->area_temp[3] = 0;
+ }
- if( skill_id == NC_VULCANARM )
- if (sd) pc->overheat(sd,1);
+ if (skill_id == NC_VULCANARM) {
+ if (sd != NULL) {
+ pc->overheat(sd,1);
+ }
+ }
// if skill damage should be split among targets, count them
//SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets
@@ -4005,7 +4727,21 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
// recursive invocation of skill->castend_damage_id() with flag|1
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+
+ if (skill_id == AS_SPLASHER) {
+ // Prevent double item consumption when the target explodes (item requirements have already been processed in skill_castend_nodamage_id)
+ flag |= 1;
+ }
+
+ if (sd && skill_id == SU_LUNATICCARROTBEAT) {
+ short item_idx = pc->search_inventory(sd, ITEMID_CARROT);
+
+ if (item_idx >= 0) {
+ pc->delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME);
+ skill->area_temp[3] = 1;
+ }
+ }
}
break;
@@ -4063,12 +4799,12 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if(idb_exists(skill->bowling_db, bl->id))
break;
// Random direction
- dir = rnd()%8;
+ dir = rnd() % UNIT_DIR_MAX;
} else {
// Create an empty list of already hit targets
db_clear(skill->bowling_db);
// Direction is walkpath
- dir = (unit->getdir(src)+4)%8;
+ dir = unit_get_opposite_dir(unit->getdir(src));
}
// Add current target to the list of already hit targets
idb_put(skill->bowling_db, bl->id, bl);
@@ -4077,6 +4813,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
ty = bl->y;
for(i=0;i<c;i++) {
// Target coordinates (get changed even if knockback fails)
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
tx -= dirx[dir];
ty -= diry[dir];
// If target cell is a wall then break
@@ -4086,9 +4826,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// Splash around target cell, but only cells inside area; we first have to check the area is not negative
if((max(min_x,tx-1) <= min(max_x,tx+1)) &&
(max(min_y,ty-1) <= min(max_y,ty+1)) &&
- (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
+ (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
// Recursive call
- map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
+ map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), skill->splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
// Self-collision
if(bl->x >= min_x && bl->x <= max_x && bl->y >= min_y && bl->y <= max_y)
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
@@ -4105,18 +4845,24 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if (bl->id==skill->area_temp[1])
break;
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION))
- skill->blown(src,bl,skill->area_temp[2],-1,0);
+ skill->blown(src, bl, skill->area_temp[2], UNIT_DIR_UNDEFINED, 0);
} else {
- int x=bl->x,y=bl->y,i,dir;
- dir = map->calc_dir(bl,src->x,src->y);
+ int x = bl->x;
+ int y = bl->y;
+ int i;
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
skill->area_temp[1] = bl->id;
skill->area_temp[2] = skill->get_blewcount(skill_id,skill_lv);
// all the enemies between the caster and the target are hit, as well as the target
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0))
- skill->blown(src,bl,skill->area_temp[2],-1,0);
+ skill->blown(src, bl, skill->area_temp[2], UNIT_DIR_UNDEFINED, 0);
for (i=0;i<4;i++) {
map->foreachincell(skill->area_sub,bl->m,x,y,BL_CHAR,src,skill_id,skill_lv,
tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
x += dirx[dir];
y += diry[dir];
}
@@ -4240,7 +4986,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SL_STUN:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
@@ -4281,6 +5027,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if( (tsc = status->get_sc(bl)) && tsc->data[SC_HIDING] )
break;
}
+ FALLTHROUGH
case HVAN_EXPLOSION:
if (src != bl)
skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
@@ -4308,7 +5055,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
src, src, bl, skill_id, skill_lv, tick, flag);
if (heal > 0){
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status->heal(src, heal, 0, 0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -4337,7 +5084,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if(rnd()%100 < (10 + 3*skill_lv)) {
if( !sd || pc->checkskill(sd,KN_SPEARBOOMERANG) == 0 )
break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang.
- skill->blown(src,bl,6,-1,0);
+ skill->blown(src, bl, 6, UNIT_DIR_UNDEFINED, 0);
skill->addtimerskill(src,tick+800,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0);
}
@@ -4345,7 +5092,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case RK_PHANTOMTHRUST:
{
struct map_session_data *tsd = BL_CAST(BL_PC, bl);
- unit->setdir(src,map->calc_dir(src, bl->x, bl->y));
+ unit->set_dir(src, map->calc_dir(src, bl->x, bl->y));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
skill->blown(src,bl,distance_bl(src,bl)-1,unit->getdir(src),0);
@@ -4359,16 +5106,13 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case KO_JYUMONJIKIRI:
case GC_DARKILLUSION:
{
- short x, y;
- short dir = map->calc_dir(bl, src->x, src->y);
-
- if ( dir < 4 ) {
- x = bl->x + 2 * (dir > 0) - 3 * (dir > 0);
- y = bl->y + 1 - (dir / 2) - (dir > 2);
- } else {
- x = bl->x + 2 * (dir > 4) - 1 * (dir > 4);
- y = bl->y + (dir / 6) - 1 + (dir > 6);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
}
+ short x = bl->x + dirx[dir];
+ short y = bl->y + diry[dir];
if ( unit->movepos(src, x, y, 1, 1) ) {
clif->slide(src, x, y);
@@ -4383,12 +5127,12 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING )
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0, 0);
break;
case GC_CROSSRIPPERSLASHER:
if( sd && !(sc && sc->data[SC_ROLLINGCUTTER]) )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
else
{
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
@@ -4419,7 +5163,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
heal = 0; // Don't absorb heal from Ice Walls or other skill units.
if( heal && rnd()%100 < rate ) {
- status->heal(src, heal, 0, 0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
}
}
@@ -4489,20 +5233,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if( !skill->check_condition_castbegin(sd, spell_skill_id, spell_skill_lv) )
break;
- switch( skill->get_casttype(spell_skill_id) ) {
- case CAST_GROUND:
- skill->castend_pos2(src, bl->x, bl->y, spell_skill_id, spell_skill_lv, tick, 0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, bl, spell_skill_id, spell_skill_lv, tick, 0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(src, bl, spell_skill_id, spell_skill_lv, tick, 0);
- break;
- }
-
+ skill->castend_type(skill->get_casttype(spell_skill_id), src, bl, spell_skill_id, spell_skill_lv, tick, 0);
sd->ud.canact_tick = tick + skill->delay_fix(src, spell_skill_id, spell_skill_lv);
- clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0);
cooldown = skill->get_cooldown(spell_skill_id, spell_skill_lv);
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) {
@@ -4536,24 +5269,27 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|ELE_DARK);
break;
case RA_WUGSTRIKE:
- if( sd && pc_isridingwug(sd) ){
- short x[8]={0,-1,-1,-1,0,1,1,1};
- short y[8]={1,1,0,-1,-1,-1,0,1};
- uint8 dir = map->calc_dir(bl, src->x, src->y);
-
- if( unit->movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) )
- {
- clif->slide(src, bl->x+x[dir], bl->y+y[dir]);
+ if (sd != NULL && pc_isridingwug(sd)) {
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ short x = bl->x + dirx[dir];
+ short y = bl->y + diry[dir];
+ if (unit->movepos(src, x, y, 1, 1) != 0) {
+ clif->slide(src, x, y);
clif->fixpos(src);
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
}
break;
}
+ FALLTHROUGH
case RA_WUGBITE:
if( path->search(NULL,src,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) {
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
}else if( sd && skill_id == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message.
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
@@ -4572,10 +5308,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) {
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP;
+ item_tmp.nameid = sg->item_id ? sg->item_id : ITEMID_BOOBY_TRAP;
item_tmp.identify = 1;
if( item_tmp.nameid )
- map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0);
+ map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0, false);
}
skill->delunit(su);
}
@@ -4589,7 +5325,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it.
} else {
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
if( sd ) pc->overheat(sd,1);
}
@@ -4607,7 +5343,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// Destination area
skill->area_temp[4] = x;
skill->area_temp[5] = y;
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL);
}
@@ -4666,7 +5402,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
} else{
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
}
break;
@@ -4711,7 +5447,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
status_change_end(bl, SC_POISON, INVALID_TIMER);
} else if( sd )
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -4803,7 +5539,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if(flag & 1)
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
else {
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
}
break;
@@ -4824,6 +5560,15 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
break;
+ case SU_SV_STEMSPEAR:
+ skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ if (status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance.
+ skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, (skill_id == SU_SV_STEMSPEAR) ? BF_MAGIC : BF_WEAPON, flag);
+ break;
+ case SU_SCAROFTAROU:
+ sc_start(src, bl, status->skill2sc(skill_id), 10, skill_lv, skill->get_time(skill_id, skill_lv)); // TODO: What's the activation chance for the effect?
+ break;
+
case 0:/* no skill - basic/normal attack */
if(sd) {
if (flag & 3){
@@ -4867,8 +5612,12 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
return 0;
}
-bool skill_castend_damage_id_unknown(struct block_list* src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_data *tstatus, struct status_change *sc)
+static bool skill_castend_damage_id_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_data *tstatus, struct status_change *sc)
{
+ nullpo_retr(true, skill_id);
+ nullpo_retr(true, skill_lv);
+ nullpo_retr(true, tick);
+ nullpo_retr(true, tstatus);
ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n", *skill_id);
clif->skill_damage(src, bl, *tick, status_get_amotion(src), tstatus->dmotion,
0, abs(skill->get_num(*skill_id, *skill_lv)),
@@ -4880,7 +5629,8 @@ bool skill_castend_damage_id_unknown(struct block_list* src, struct block_list *
/*==========================================
*
*------------------------------------------*/
-int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
+static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *target, *src;
struct map_session_data *sd;
struct mob_data *md;
@@ -4917,12 +5667,11 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK) )
+ if (sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd, SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
}
-
ud->skilltimer = INVALID_TIMER;
}
@@ -4933,6 +5682,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
// Use a do so that you can break out of it when the skill fails.
do {
+ bool is_asura = (ud->skill_id == MO_EXTREMITYFIST);
+
if(!target || target->prev==NULL) break;
if(src->m != target->m || status->isdead(src)) break;
@@ -4957,6 +5708,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
ud->skilltimer=tid;
return skill->castend_pos(tid,tick,id,data);
case GN_WALLOFTHORN:
+ case SU_CN_POWDERING:
+ case SU_SV_ROOTTWIST:
ud->skillx = target->x;
ud->skilly = target->y;
ud->skilltimer = tid;
@@ -4968,8 +5721,9 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
}
if(ud->skill_id == RG_BACKSTAP) {
- uint8 dir = map->calc_dir(src,target->x,target->y),t_dir = unit->getdir(target);
- if(check_distance_bl(src, target, 0) || map->check_dir(dir,t_dir)) {
+ enum unit_dir dir = map->calc_dir(src, target->x, target->y);
+ enum unit_dir t_dir = unit->getdir(target);
+ if (check_distance_bl(src, target, 0) || map->check_dir(dir, t_dir) != 0) {
break;
}
}
@@ -5017,7 +5771,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
}
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);
+ clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0, 0);
break;
}
@@ -5025,7 +5779,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
if (BL_UCCAST(BL_MOB, target)->class_ == MOBID_EMPELIUM)
break;
} else if (inf && battle->check_target(src, target, inf) <= 0) {
- if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
} else if (ud->skill_id == RK_PHANTOMTHRUST && target->type != BL_MOB) {
if( !map_flag_vs(src->m) && battle->check_target(src,target,BCT_PARTY) <= 0 )
@@ -5037,7 +5791,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
&& rnd() % 100 < 75
) {
// Fogwall makes all offensive-type targeted skills fail at 75%
- if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0);
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -5056,7 +5810,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
!check_distance_bl(src, target, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range))
{
if (sd) {
- clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex]
skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,3);
}
@@ -5086,7 +5840,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH)
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
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);
@@ -5100,7 +5854,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
skill->blockpc_start(sd, ud->skill_id, cooldown);
}
if( battle_config.display_status_timers && sd )
- clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
if( sd )
{
switch( ud->skill_id )
@@ -5155,7 +5909,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
}
if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish]
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
if (ud->skilltimer == INVALID_TIMER) {
if(md) md->skill_idx = -1;
@@ -5163,8 +5917,9 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
ud->skill_lv = ud->skilltarget = 0;
}
- if (src->id != target->id)
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ // Asura Strike caster doesn't look to their target in the end
+ if (src->id != target->id && !is_asura)
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
map->freeblock_unlock();
return 1;
@@ -5175,7 +5930,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
//When Asura fails... (except when it fails from Fog of Wall)
//Consume SP/spheres
skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
sc = &sd->sc;
if (sc->count) {
//End states
@@ -5187,45 +5942,45 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
}
if (target && target->m == src->m) {
//Move character to target anyway.
- int dir, x, y;
- dir = map->calc_dir(src,target->x,target->y);
- if( dir > 0 && dir < 4) x = -2;
- else if( dir > 4 ) x = 2;
- else x = 0;
- if( dir > 2 && dir < 6 ) y = -2;
- else if( dir == 7 || dir < 2 ) y = 2;
- else y = 0;
- if (unit->movepos(src, src->x+x, src->y+y, 1, 1)) {
+ enum unit_dir dir = map->calc_dir(src, target->x, target->y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ int dist = 3; // number of cells that asura caster will walk
+ int x = dist * dirx[dir];
+ int y = dist * diry[dir];
+
+ if (unit->movepos(src, src->x + x, src->y + y, 1, 1) != 0) {
//Display movement + animation.
- clif->slide(src,src->x,src->y);
+ clif->slide(src, src->x, src->y);
clif->spiritball(src);
}
- clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ // "Skill Failed" message was already shown when checking that target is invalid
+ //clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
}
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick;
ud->skill_id = ud->skill_lv = ud->skilltarget = 0;
//You can't place a skill failed packet here because it would be
//sent in ALL cases, even cases where skill_check_condition fails
//which would lead to double 'skill failed' messages u.u [Skotlex]
if(sd)
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
else if(md)
md->skill_idx = -1;
return 0;
}
-bool skill_castend_id_unknown(struct unit_data *ud, struct block_list *src, struct block_list *target)
+static bool skill_castend_id_unknown(struct unit_data *ud, struct block_list *src, struct block_list *target)
{
- return false;
+ return false;
}
/*==========================================
*
*------------------------------------------*/
-int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
struct map_session_data *sd, *dstsd;
struct mob_data *md, *dstmd;
struct homun_data *hd;
@@ -5283,7 +6038,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case AL_DECAGI:
case AB_RENOVATIO:
case AB_HIGHNESSHEAL:
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0, 0);
return 0;
default:
if (skill->castend_nodamage_id_mado_unknown(src, bl, &skill_id, &skill_lv, &tick, &flag))
@@ -5299,9 +6054,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
switch (skill_id) {
case HLIF_HEAL: // [orn]
if (bl->type != BL_HOM) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ;
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0) ;
break ;
}
+ FALLTHROUGH
case AL_HEAL:
/**
@@ -5316,7 +6072,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sd && battle->check_undead(tstatus->race,tstatus->def_ele) && skill_id != AL_INCAGI) {
if (battle->check_target(src, bl, BCT_ENEMY) < 1) {
//Offensive heal does not works on non-enemies. [Skotlex]
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
@@ -5417,6 +6173,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
* Arch Bishop
**/
case AB_HIGHNESSHEAL:
+ /**
+ * Summoner
+ */
+ case SU_TUNABELLY:
{
int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true);
int heal_get_jobexp;
@@ -5427,7 +6187,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (status->isimmune(bl) || (dstmd != NULL && (dstmd->class_ == MOBID_EMPELIUM || mob_is_battleground(dstmd))))
heal = 0;
- if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0)
+ if (sd != NULL && dstsd != NULL && sd->status.partner_id == dstsd->status.char_id && (sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0)
heal = heal * 2;
if (tsc && tsc->count)
@@ -5446,16 +6206,19 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
else if (tsc->data[SC_BERSERK])
heal = 0; //Needed so that it actually displays 0 when healing.
}
+ if (skill_id == AL_HEAL) {
+ status_change_end(bl, SC_BITESCAR, INVALID_TIMER);
+ }
clif->skill_nodamage (src, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL )
heal = ~heal + 1;
- heal_get_jobexp = status->heal(bl,heal,0,0);
+ heal_get_jobexp = status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
if (heal_get_jobexp <= 0)
heal_get_jobexp = 1;
- pc->gainexp (sd, bl, 0, heal_get_jobexp, false);
+ pc->gainexp(sd, bl, 0, heal_get_jobexp, false);
}
}
break;
@@ -5463,7 +6226,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case PR_REDEMPTIO:
if (sd && !(flag&1)) {
if (sd->status.party_id == 0) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
skill->area_temp[0] = 0;
@@ -5472,7 +6235,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
src,skill_id,skill_lv,tick, flag|BCT_PARTY|1,
skill->castend_nodamage_id);
if (skill->area_temp[0] == 0) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
skill->area_temp[0] = 5 - skill->area_temp[0]; // The actual penalty...
@@ -5482,8 +6245,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_JOBEXP);
}
- status->set_hp(src, 1, 0);
- status->set_sp(src, 0, 0);
+ status->set_hp(src, 1, STATUS_HEAL_DEFAULT);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
break;
} else if (status->isdead(bl) && flag&1) { //Revive
skill->area_temp[0]++; //Count it in, then fall-through to the Resurrection code.
@@ -5494,7 +6257,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case ALL_RESURRECTION:
if(sd && (map_flag_gvg2(bl->m) || map->list[bl->m].flag.battleground)) {
//No reviving in WoE grounds!
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if (!status->isdead(bl))
@@ -5531,7 +6294,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (jexp < 1) jexp = 1;
}
if(exp > 0 || jexp > 0)
- pc->gainexp (sd, bl, exp, jexp, false);
+ pc->gainexp(sd, bl, exp, jexp, false);
}
}
}
@@ -5584,9 +6347,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sd) {
// player-casted
- sd->state.abra_flag = 1;
- sd->skillitem = abra_skill_id;
- sd->skillitemlv = abra_skill_lv;
+ sd->autocast.type = AUTOCAST_ABRA;
+ sd->autocast.skill_id = abra_skill_id;
+ sd->autocast.skill_lv = abra_skill_lv;
clif->item_skill(sd, abra_skill_id, abra_skill_lv);
} else {
// mob-casted
@@ -5647,7 +6410,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case SA_SUMMONMONSTER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE);
+ if (sd != NULL)
+ mob->once_spawn(sd, src->m, src->x, src->y, DEFAULT_MOB_JNAME, -1, 1, "", SZ_SMALL, AI_NONE);
break;
case SA_LEVELUP:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -5655,7 +6419,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case SA_INSTANTDEATH:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- status->set_hp(bl,1,0);
+ status->set_hp(bl, 1, STATUS_HEAL_DEFAULT);
break;
case SA_QUESTION:
case SA_GRAVITY:
@@ -5668,7 +6432,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int class_;
if ( sd && dstmd->status.mode&MD_BOSS )
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
class_ = skill_id == SA_MONOCELL ? MOBID_PORING : mob->get_random_id(4, 1, 0);
@@ -5688,7 +6452,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SA_DEATH:
if ( sd && dstmd && dstmd->status.mode&MD_BOSS )
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -5715,8 +6479,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case CR_PROVIDENCE:
if(sd && dstsd){ //Check they are not another crusader [Skotlex]
- if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if ((dstsd->job & MAPID_UPPERMASK) == MAPID_CRUSADER) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -5729,9 +6493,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
{
struct status_change* sc = status->get_sc(src);
- if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) {
+ if (sd != NULL && dstsd != NULL && (dstsd->job & MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex) {
// Cannot cast on another bard/dancer-type class of the same gender as caster
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -5748,7 +6512,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
status_change_end(bl, SC_MARIONETTE, INVALID_TIMER);
} else {
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -5765,7 +6529,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SA_LIGHTNINGLOADER:
case SA_SEISMICWEAPON:
if (dstsd) {
- if(dstsd->status.weapon == W_FIST ||
+ if (dstsd->weapontype == W_FIST ||
(dstsd->sc.count && !dstsd->sc.data[type] &&
( //Allow re-enchanting to lengthen time. [Skotlex]
dstsd->sc.data[SC_PROPERTYFIRE] ||
@@ -5777,7 +6541,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
dstsd->sc.data[SC_ENCHANTPOISON]
))
) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
break;
}
@@ -5785,7 +6549,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// 100% success rate at lv4 & 5, but lasts longer at lv5
if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) {
if (sd)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd)
clif->message(sd->fd, msg_sd(sd,869)); // "You broke the target's weapon."
}
@@ -5825,6 +6589,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case PR_KYRIE:
case MER_KYRIE:
+ case SU_TUNAPARTY:
clif->skill_nodamage(bl, bl, skill_id, -1,
sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
@@ -5837,24 +6602,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage (src,src,skill_id,skill_lv,1);
// Initiate 10% of your damage becomes fire element.
sc_start4(src,src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv));
- if( sd )
- skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv));
- else if( bl->type == BL_MER )
- skill->blockmerc_start(BL_UCAST(BL_MER, bl), skill_id, skill->get_time(skill_id, skill_lv));
break;
case TK_JUMPKICK:
/* Check if the target is an enemy; if not, skill should fail so the character doesn't unit->movepos (exploitable) */
- if( battle->check_target(src, bl, BCT_ENEMY) > 0 )
- {
- if( unit->movepos(src, bl->x, bl->y, 1, 1) )
- {
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- clif->slide(src,bl->x,bl->y);
+ if (battle->check_target(src, bl, BCT_ENEMY) > 0) {
+ if (unit->movepos(src, bl->x, bl->y, 1, 1)) {
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+ clif->slide(src, bl->x, bl->y);
}
+ } else if (sd != NULL) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
}
- else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
break;
case AL_INCAGI:
@@ -5941,9 +6700,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case RK_ABUNDANCE:
case RK_CRUSHSTRIKE:
case ALL_ODINS_POWER:
+ case SU_FRESHSHRIMP:
+ case SU_ARCLOUSEDASH:
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;
+ // Works just like the above list of skills, except animation caused by
+ // status must trigger AFTER the skill cast animation or it will cancel
+ // out the status's animation.
+ case SU_STOOP:
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ 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);
@@ -5966,7 +6734,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case HP_ASSUMPTIO:
if( sd && dstmd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
else
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -6019,7 +6787,7 @@ 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)));
else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
if (sd && dstsd && dstsd->sc.count) {
@@ -6032,7 +6800,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//dstsd->sc.data[SC_ENCHANTPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex]
) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -6062,17 +6830,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int id;
if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one
clif->mission_info(sd, sd->mission_mobid, sd->mission_count);
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
id = mob->get_random_id(0,0xF, sd->status.base_level);
if (!id) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
sd->mission_mobid = id;
sd->mission_count = 0;
- pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), id);
+ pc_setglobalreg(sd,script->add_variable("TK_MISSION_ID"), id);
clif->mission_info(sd, id, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
@@ -6102,7 +6870,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
(failure = sc_start(src,bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status->get_lv(src) - status->get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv))));
if( !failure ) {
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
@@ -6132,7 +6900,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( !dstsd || (!sd && !mer) )
{ // Only players can be devoted
if( sd )
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
@@ -6141,11 +6909,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( lv > battle_config.devotion_level_difference || // Level difference requeriments
(dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source
(skill_id == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner
- (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted
+ (dstsd->job & MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted
(dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted.
{
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -6160,7 +6928,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
ARR_FIND(0, count, i, sd->devotion[i] == 0 );
if( i == count ) {
// No free slots, skill Fail
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -6168,7 +6936,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sd->devotion[i] = bl->id;
}
- else
+ else if (mer != NULL)
mer->devotion_flag = 1; // Mercenary Devoting Owner
clif->skill_nodamage(src, bl, skill_id, skill_lv,
@@ -6194,7 +6962,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case MO_KITRANSLATION:
- if(dstsd && ((dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK)!=MAPID_REBELLION)) {
+ if (dstsd != NULL && (dstsd->job & MAPID_BASEMASK) != MAPID_GUNSLINGER) {
pc->addspiritball(dstsd,skill->get_time(skill_id,skill_lv),5);
}
break;
@@ -6210,10 +6978,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case MO_ABSORBSPIRITS:
{
int sp = 0;
- if ( dstsd && dstsd->spiritball
- && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group))
- && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)
- ) {
+ if (dstsd != NULL && dstsd->spiritball != 0
+ && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group))
+ && (dstsd->job & MAPID_BASEMASK) != MAPID_GUNSLINGER
+ ) {
// split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
sp = dstsd->spiritball * 7;
pc->delspiritball(dstsd, dstsd->spiritball, 0);
@@ -6225,7 +6993,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (dstsd && dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) {
pc->del_charm(dstsd, dstsd->charm_count, dstsd->charm_type);
}
- if (sp) status->heal(src, 0, sp, 3);
+ if (sp != 0)
+ status->heal(src, 0, sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0);
}
break;
@@ -6259,7 +7028,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
status_change_end(src, SC_HIDING, INVALID_TIMER);
@@ -6278,7 +7047,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int count = 0;
skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src),
+ count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
if( !count && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) )
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
@@ -6324,7 +7093,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);
skill->area_temp[1] = 0;
map->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
@@ -6338,7 +7107,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src, src, skill_id, -1, 1);
map->delblock(src); //Required to prevent chain-self-destructions hitting back.
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|targetmask,
skill->castend_damage_id);
map->addblock(src);
@@ -6414,14 +7183,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sd) {
if (!dstsd || !(
(sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SOULLINKER)
- || (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER
+ || (dstsd->job & MAPID_UPPERMASK) == MAPID_SOUL_LINKER
|| dstsd->status.char_id == sd->status.char_id
|| dstsd->status.char_id == sd->status.partner_id
|| dstsd->status.char_id == sd->status.child
)
) {
status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDRATE);
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -6448,7 +7217,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 0;
} else if( tsc && tsc->option&OPTION_MADOGEAR ) {
//Mado Gear cannot hide
- if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if( sd ) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
@@ -6474,7 +7243,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( failure )
clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
if ( skill_id == LG_FORCEOFVANGUARD || skill_id == RA_CAMOUFLAGE )
break;
map->freeblock_unlock();
@@ -6484,7 +7253,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( failure )
clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -6504,8 +7273,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// custom hack to make the mob display the skill, because these skills don't show the skill use text themselves
//NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches)
char temp[70];
- snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill->dbs->db[skill_id].desc);
- clif->disp_overhead(&md->bl,temp);
+ snprintf(temp, sizeof(temp), msg_txt(882), md->name, skill->get_desc(skill_id)); // %s : %s !!
+ clif->disp_overhead(&md->bl, temp, AREA_CHAT_WOC, NULL);
}
break;
@@ -6524,7 +7293,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(src,bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv)));
} else {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
- if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if(sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
}
break;
@@ -6534,20 +7303,20 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if(pc->steal_item(sd,bl,skill_lv))
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
}
break;
case RG_STEALCOIN:
if(sd) {
- int amount = pc->steal_coin(sd, bl);
- if( amount > 0 ) {
+ int amount = pc->steal_coin(sd, bl, skill_lv);
+ if (amount > 0 && dstmd != NULL) {
dstmd->state.provoke_flag = src->id;
mob->target(dstmd, src, skill->get_range2(src, skill_id, skill_lv));
clif->skill_nodamage(src, bl, skill_id, amount, 1);
} else
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -6555,7 +7324,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
{
int brate = 0;
if (tstatus->mode&MD_BOSS) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if(status->isimmune(bl) || !tsc)
@@ -6574,7 +7343,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
skill->get_time2(skill_id,skill_lv)))
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
else if(sd) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
// Level 6-10 doesn't consume a red gem if it fails [celest]
if (skill_lv > 5) {
// not to consume items
@@ -6587,7 +7356,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NV_FIRSTAID:
clif->skill_nodamage(src,bl,skill_id,5,1);
- status->heal(bl,5,0,0);
+ status->heal(bl, 5, 0, STATUS_HEAL_DEFAULT);
break;
case AL_CURE:
@@ -6598,7 +7367,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
status_change_end(bl, SC_BLIND, INVALID_TIMER);
status_change_end(bl, SC_CONFUSION, INVALID_TIMER);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ status_change_end(bl, SC_BITESCAR, INVALID_TIMER);
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
break;
case TF_DETOXIFY:
@@ -6608,27 +7378,34 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case PR_STRECOVERY:
- if(status->isimmune(bl)) {
- clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
+ if (status->isimmune(bl) != 0) {
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 0);
break;
}
- if (tsc && tsc->opt1) {
- status_change_end(bl, SC_FREEZE, INVALID_TIMER);
- status_change_end(bl, SC_STONE, INVALID_TIMER);
- status_change_end(bl, SC_SLEEP, INVALID_TIMER);
- status_change_end(bl, SC_STUN, INVALID_TIMER);
- status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER);
- }
- status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER);
- //Is this equation really right? It looks so... special.
- if( battle->check_undead(tstatus->race,tstatus->def_ele) ) {
- status->change_start(src, bl, SC_BLIND,
- 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), 1,0,0,0,
- skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,SCFLAG_NONE);
+
+ if (!battle->check_undead(tstatus->race, tstatus->def_ele)) {
+ if (tsc != NULL && tsc->opt1 != 0) {
+ status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+ status_change_end(bl, SC_STONE, INVALID_TIMER);
+ status_change_end(bl, SC_SLEEP, INVALID_TIMER);
+ status_change_end(bl, SC_STUN, INVALID_TIMER);
+ status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER);
+ }
+
+ status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER);
+ } else {
+ int rate = 100 * (100 - (tstatus->int_ / 2 + tstatus->vit / 3 + tstatus->luk / 10));
+ int duration = skill->get_time2(skill_id, skill_lv);
+
+ duration = duration * (100 - (tstatus->int_ + tstatus->vit) / 2) / 100;
+ status->change_start(src, bl, SC_BLIND, rate, 1, 0, 0, 0, duration, SCFLAG_NONE);
}
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if(dstmd)
- mob->unlocktarget(dstmd,tick);
+
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+
+ if (dstmd != NULL)
+ mob->unlocktarget(dstmd, tick);
+
break;
// Mercenary Supportive Skills
@@ -6663,7 +7440,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case MER_SCAPEGOAT:
if( mer && mer->master ) {
- status->heal(&mer->master->bl, mer->battle_status.hp, 0, 2);
+ status->heal(&mer->master->bl, mer->battle_status.hp, 0, STATUS_HEAL_SHOWEFFECT);
status->damage(src, src, mer->battle_status.max_hp, 0, 0, 1);
}
break;
@@ -6677,7 +7454,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
if( dstsd )
{ // Fail on Players
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if (dstmd && dstmd->class_ == MOBID_EMPELIUM)
@@ -6701,8 +7478,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
map->freeblock_unlock();
return 1;
}
- if( sd->skillitem != skill_id )
- status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded
+ if (sd->autocast.type == AUTOCAST_NONE)
+ status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded
}
break;
@@ -6718,7 +7495,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sd) {
//Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
if ( !pc_can_give_items(sd) )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
else {
sd->state.prevend = sd->state.workinprogress = 3;
clif->openvendingreq(sd,2+skill_lv);
@@ -6738,7 +7515,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
}
- if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 )
+ if (sd->autocast.type == AUTOCAST_TEMP || ((sd->autocast.skill_id == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1) || skill_lv == 3)
{
if( skill_lv == 1 )
pc->randomwarp(sd,CLR_TELEPORT);
@@ -6766,7 +7543,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (skill->produce_mix(sd, skill_id, ITEMID_HOLY_WATER, 0, 0, 0, 1))
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -6785,7 +7562,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
eflag = pc->additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE);
if(eflag) {
clif->additem(sd,0,0,eflag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
break;
@@ -6864,7 +7641,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//Nothing stripped.
if( sd && !rate )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
@@ -6878,22 +7655,23 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 1;
}
if( sd ) {
- int x,bonus=100, potion = min(500+skill_lv,505);
- x = skill_lv%11 - 1;
- i = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[x]);
- if (i == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[x] <= 0) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ int bonus = 100, potion = min(500+skill_lv,505);
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ int inventory_idx = pc->search_inventory(sd, item_id);
+ if (inventory_idx == INDEX_NOT_FOUND || item_id <= 0) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
- if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->dbs->db[skill_id].amount[x]) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd->inventory_data[inventory_idx] == NULL || sd->status.inventory[inventory_idx].amount < skill->get_itemqty(skill_id, item_idx)) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
if( skill_id == AM_BERSERKPITCHER ) {
- if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (dstsd != NULL && dstsd->status.base_level < sd->inventory_data[inventory_idx]->elv) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
@@ -6901,7 +7679,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
script->potion_flag = 1;
script->potion_hp = script->potion_sp = script->potion_per_hp = script->potion_per_sp = 0;
script->potion_target = bl->id;
- script->run_use_script(sd, sd->inventory_data[i], 0);
+ script->run_use_script(sd, sd->inventory_data[inventory_idx], 0);
script->potion_flag = script->potion_target = 0;
if( sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ALCHEMIST )
bonus += sd->status.base_level;
@@ -6979,7 +7757,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( tsc && tsc->data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
- status->heal(bl,(int)hp,sp,0);
+ status->heal(bl, (int)hp, sp, STATUS_HEAL_DEFAULT);
}
break;
case AM_CP_WEAPON:
@@ -6993,7 +7771,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
(dstsd && equip[skill_id - AM_CP_WEAPON] == EQP_SHIELD && pc->checkequip(dstsd, EQP_SHIELD) > 0
&& (index = dstsd->equip_index[EQI_HAND_L]) >= 0 && dstsd->inventory_data[index]
&& dstsd->inventory_data[index]->type != IT_ARMOR)) ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock(); // Don't consume item requirements
return 0;
}
@@ -7006,7 +7784,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);
//Prepare 200 White Potions.
if (!skill->produce_mix(sd, skill_id, ITEMID_WHITE_POTION, 0, 0, 0, 200))
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
case AM_TWILIGHT2:
@@ -7014,7 +7792,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);
//Prepare 200 Slim White Potions.
if (!skill->produce_mix(sd, skill_id, ITEMID_WHITE_SLIM_POTION, 0, 0, 0, 200))
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
case AM_TWILIGHT3:
@@ -7028,7 +7806,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
|| !skill->can_produce_mix(sd,ITEMID_FIRE_BOTTLE,-1, 50) //50 Flame Bottle
|| ebottle < 200 //200 empty bottle are required at total.
) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -7048,13 +7826,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
+ if ((dstsd != NULL && (dstsd->job & MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
|| (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 )
{
if (sd)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if(status->isimmune(bl) || !tsc || !tsc->count)
@@ -7110,7 +7888,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case TK_HIGHJUMP:
{
- int x,y, dir = unit->getdir(src);
+ int x;
+ int y;
+ enum unit_dir dir = unit->getdir(src);
//Fails on noteleport maps, except for GvG and BG maps [Skotlex]
if( map->list[src->m].flag.noteleport
@@ -7154,7 +7934,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sp = skill->get_sp(skill_id,skill_lv);
sp = sp * tsc->data[SC_MAGICROD]->val2 / 100;
if(sp < 1) sp = 1;
- status->heal(bl,0,sp,2);
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
} else {
struct unit_data *ud = unit->bl2ud(bl);
@@ -7167,7 +7947,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//Only 10% success chance against bosses. [Skotlex]
if (rnd()%100 < 90)
{
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
} else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players.
@@ -7186,14 +7966,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sp) //Recover some of the SP used
sp = sp*(25*(skill_lv-1))/100;
- if(hp || sp)
- status->heal(src, hp, sp, 2);
+ if (hp != 0 || sp != 0)
+ status->heal(src, hp, sp, STATUS_HEAL_SHOWEFFECT);
}
}
break;
case SA_MAGICROD:
- clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1);
- sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ if (battle->bc->magicrod_type == 0)
+ clif->skill_nodamage(src, src, SA_MAGICROD, skill_lv, 1); // Animation used here in official [Wolfie]
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SA_AUTOSPELL:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -7221,7 +8002,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
maxlv = skill_lv - 4;
}
else if(skill_lv >=2) {
- int i = rnd()%3;
+ int i = rnd() % ARRAYLENGTH(spellarray);
spellid = spellarray[i];
maxlv = skill_lv - 1;
}
@@ -7307,8 +8088,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NPC_LICK:
status_zap(bl, 0, 100);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(src,bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)));
+ clif->skill_nodamage(src, bl, skill_id, skill_lv,
+ sc_start(src, bl, type, (skill_lv * 20), skill_lv, skill->get_time2(skill_id, skill_lv)));
break;
case NPC_SUICIDE:
@@ -7358,11 +8139,19 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NPC_RUN:
{
- const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}};
- uint8 dir = (bl == src)?unit->getdir(src):map->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away.
+ enum unit_dir dir;
+ if (bl == src) //If cast on self, run forward, else run away.
+ dir = unit->getdir(src);
+ else
+ dir = map->calc_dir(src, bl->x, bl->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
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)
+ if (unit->walk_toxy(src, src->x + skill_lv * -dirx[dir], src->y + skill_lv * -diry[dir], 2) == 0
+ && md != NULL)
md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the AI.
}
break;
@@ -7428,16 +8217,16 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case WE_MALE:
{
- int hp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].hp_rate[skill_lv-1];
+ int hp_rate = skill_lv == 0 ? 0 : skill->get_hp_rate(skill_id, skill_lv);
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);
+ clif->skill_nodamage(src, bl, skill_id, status->heal(bl, gain_hp, 0, STATUS_HEAL_DEFAULT), 1);
}
break;
case WE_FEMALE:
{
- int sp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].sp_rate[skill_lv-1];
+ int sp_rate = skill_lv == 0 ? 0 : skill->get_sp_rate(skill_id, skill_lv);
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);
+ clif->skill_nodamage(src, bl, skill_id, status->heal(bl, 0, gain_sp, STATUS_HEAL_DEFAULT), 1);
}
break;
@@ -7458,7 +8247,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
we_baby_parents = true;
}
if (!we_baby_parents) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
@@ -7473,11 +8262,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
hp = sstatus->max_hp/10;
sp = hp * 10 * skill_lv / 100;
if (!status->charge(src,hp,0)) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- status->heal(bl,0,sp,2);
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
}
break;
@@ -7498,16 +8287,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( battle_config.skill_removetrap_type ) {
int i;
// get back all items used to deploy the trap
- for( i = 0; i < 10; i++ ) {
- if( skill->dbs->db[su->group->skill_id].itemid[i] > 0 ) {
+ for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
+ int nameid = skill->get_itemid(su->group->skill_id, i);
+ if (nameid > 0) {
int success;
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = skill->dbs->db[su->group->skill_id].itemid[i];
+ struct item item_tmp = { 0 };
+ int amount = skill->get_itemqty(su->group->skill_id, i);
+ item_tmp.nameid = nameid;
item_tmp.identify = 1;
- if (item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_SKILL)) != 0) {
+ if ((success = pc->additem(sd, &item_tmp, amount, LOG_TYPE_SKILL)) != 0) {
clif->additem(sd,0,0,success);
- map->addflooritem(&sd->bl, &item_tmp, skill->dbs->db[su->group->skill_id].amount[i], sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
@@ -7515,17 +8305,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// get back 1 trap
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP;
+ item_tmp.nameid = su->group->item_id ? su->group->item_id : ITEMID_BOOBY_TRAP;
item_tmp.identify = 1;
if (item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SKILL)) != 0) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
}
skill->delunit(su);
}else if(sd)
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -7541,6 +8331,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// remove trap should be used instead
break;
// otherwise fall through to below
+ FALLTHROUGH
case UNT_BLASTMINE:
case UNT_SKIDTRAP:
case UNT_LANDMINE:
@@ -7571,14 +8362,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
|| tstatus-> hp > tstatus->max_hp*3/4
#endif // RENEWAL
) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 1;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start4(src,bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000));
#ifndef RENEWAL
- if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000);
+ if (sd)
+ skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv) + 3000);
#endif
break;
@@ -7600,7 +8392,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (!clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)))
) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
@@ -7624,12 +8416,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
unsigned int sp1 = 0, sp2 = 0;
if (dstmd) {
if (dstmd->state.soul_change_flag) {
- if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if(sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
dstmd->state.soul_change_flag = 1;
sp2 = sstatus->max_sp * 3 /100;
- status->heal(src, 0, sp2, 2);
+ status->heal(src, 0, sp2, STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
}
@@ -7641,8 +8433,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( tsc && tsc->data[SC_EXTREMITYFIST2] )
sp1 = tstatus->sp;
#endif // RENEWAL
- status->set_sp(src, sp2, 3);
- status->set_sp(bl, sp1, 3);
+ status->set_sp(src, sp2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
+ status->set_sp(bl, sp1, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
@@ -7680,7 +8472,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1);
if(sp > 0)
clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1);
- status->heal(bl,hp,sp,0);
+ status->heal(bl, hp, sp, STATUS_HEAL_DEFAULT);
}
break;
// Full Chemical Protection
@@ -7700,7 +8492,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
s++;
}
if ( sd && !s ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock(); // Don't consume item requirements
return 0;
}
@@ -7732,12 +8524,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
if (rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPELIUM) || mob_is_battleground(dstmd)))) {
if (sd != NULL)
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
- status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish]
+ status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded [Inkfish]
do {
int eff = rnd() % 14;
if( eff == 5 )
@@ -7760,8 +8552,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
status_fix_damage(src, bl, 1000, 0);
clif->damage(src,bl,0,0,1000,0,BDT_NORMAL,0);
if( !status->isdead(bl) ) {
- int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT };
- skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY);
+ int where[] = {EQP_ARMOR, EQP_SHIELD, EQP_HELM};
+ skill->break_equip(bl, where[rnd() % ARRAYLENGTH(where)], 10000, BCT_ENEMY);
}
}
break;
@@ -7769,7 +8561,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
case 5: // 2000HP heal, random teleported
- status->heal(src, 2000, 0, 0);
+ status->heal(src, 2000, 0, STATUS_HEAL_DEFAULT);
if( !map_flag_vs(bl->m) )
unit->warp(bl, -1,-1,-1, CLR_TELEPORT);
break;
@@ -7782,7 +8574,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case 7: // stop freeze or stoned
{
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
- sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,sc[rnd() % ARRAYLENGTH(sc)],100,skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
case 8: // curse coma and poison
@@ -7839,14 +8631,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SL_SUPERNOVICE:
case SL_WIZARD:
//NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SOULLINK constant.
- if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd != NULL && !(dstsd != NULL && (dstsd->job & MAPID_UPPERMASK) == type)) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) {
//Erase death count 1% of the casts
dstsd->die_counter = 0;
- pc_setglobalreg(dstsd,script->add_str("PC_DIE_COUNTER"), 0);
+ pc_setglobalreg(dstsd,script->add_variable("PC_DIE_COUNTER"), 0);
clif->specialeffect(bl, 0x152, AREA);
//SC_SOULLINK invokes status_calc_pc for us.
}
@@ -7855,8 +8647,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
break;
case SL_HIGH:
- if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd != NULL && !(dstsd != NULL && (dstsd->job & JOBL_UPPER) != 0 && (dstsd->job & JOBL_2) == 0 && dstsd->status.base_level < 70)) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
@@ -7867,7 +8659,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SL_SWOO:
if (tsce) {
if(sd)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,SCFLAG_FIXEDRATE);
status_change_end(bl, SC_SWOO, INVALID_TIMER);
break;
@@ -7875,7 +8667,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SL_SKA: // [marquis007]
case SL_SKE:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
}
@@ -7967,7 +8759,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (sd) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if (!pc->set_hate_mob(sd, skill_lv-1, bl))
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -7997,16 +8789,16 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (homun->call(sd))
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
case AM_REST:
if (sd) {
- if (homun->vaporize(sd,HOM_ST_REST))
+ if (homun->vaporize(sd, HOM_ST_REST, false))
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -8016,8 +8808,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int x,y;
x = src->x;
y = src->y;
- if (hd)
- skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv));
+ if (hd) {
+#ifdef RENEWAL
+ skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
+#else
+ skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id, skill_lv));
+#endif
+ }
+
if (unit->movepos(src,bl->x,bl->y,0,0)) {
clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homun
@@ -8035,9 +8833,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
// Failed
else if (hd && hd->master)
- clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
else if (sd)
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case HVAN_CHAOTIC: // [orn]
{
@@ -8045,19 +8843,27 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int r = rnd()%100;
int target = (skill_lv-1)%5;
int hp;
- if(r<per[target][0]) //Self
+ if (r < per[target][0]) { //Self
bl = src;
- else if(r<per[target][1]) //Master
+ } else if (r < per[target][1]) { //Master
bl = battle->get_master(src);
- else //Enemy
- bl = map->id2bl(battle->get_target(src));
+ } else if ((per[target][1] - per[target][0]) < per[target][0]
+ && bl == battle->get_master(src)) {
+ /**
+ * Skill rolled for enemy, but there's nothing the Homunculus is attacking.
+ * So bl has been set to its master in unit->skilluse_id2.
+ * If it's more likely that it will heal itself,
+ * we let it heal itself.
+ */
+ bl = src;
+ }
if (!bl) bl = src;
hp = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true);
//Eh? why double skill packet?
clif->skill_nodamage(src,bl,AL_HEAL,hp,1);
clif->skill_nodamage(src,bl,skill_id,hp,1);
- status->heal(bl, hp, 0, 0);
+ status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT);
}
break;
// Homun single-target support skills [orn]
@@ -8140,7 +8946,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
{
if( !sd->status.party_id )
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
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);
@@ -8196,7 +9002,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( status->charge(bl,heal,0) )
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(src,bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv)));
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
case RK_REFRESH:
@@ -8204,7 +9010,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int heal = status_get_max_hp(bl) * 25 / 100;
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- status->heal(bl,heal,0,1);
+ status->heal(bl, heal, 0, STATUS_HEAL_FORCED);
status->change_clear_buffs(bl,4);
}
break;
@@ -8258,7 +9064,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
value = status_get_max_hp(bl) * 25 / 100;
status->change_clear_buffs(bl,4);
skill->area_temp[5] &= ~0x20;
- status->heal(bl,value,0,1);
+ status->heal(bl, value, 0, STATUS_HEAL_FORCED);
type = SC_REFRESH;
}else if( skill->area_temp[5]&0x40 ){
skill->area_temp[5] &= ~0x40;
@@ -8374,11 +9180,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
{
int heal = status_get_max_hp(bl) * ( 18 - 2 * skill_lv ) / 100;
if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails.
- if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0, 0);
break;
}
if( !status->charge(bl,heal,0) ) {
- if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -8390,7 +9196,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case AB_ANCILLA:
if( sd ) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill->produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1);
+ skill->produce_mix(sd, skill_id, ITEMID_ANSILA, 0, 0, 0, 1);
}
break;
@@ -8404,7 +9210,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, level + (sd?(sd->status.job_level / 10):0), skill->get_time(skill_id,skill_lv)));
else if( sd ) {
if( !level )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
else
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);
}
@@ -8443,7 +9249,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(bl, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
- status->heal(bl, heal, 0, 1);
+ status->heal(bl, heal, 0, STATUS_HEAL_FORCED);
}
} 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);
@@ -8508,9 +9314,9 @@ 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) || rnd()%100 >= 60 + 8 * skill_lv) {
+ if ((dstsd != NULL && (dstsd->job & MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 60 + 8 * skill_lv) {
if (sd)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if(status->isimmune(bl) || !tsc || !tsc->count)
@@ -8573,11 +9379,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int failure = sc_start2(src,bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,failure);
if( sd && !failure )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
}else
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0, 0);
break;
case WL_FROSTMISTY:
@@ -8613,7 +9419,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);
map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
}else if( sd ) // Failure on Rate
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
}
break;
@@ -8643,7 +9449,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( sc && !sc->data[i] )
break;
if( i == SC_SPELLBOOK7 ) {
- clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0);
+ clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0, 0);
break;
}
@@ -8706,7 +9512,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NC_F_SIDESLIDE:
case NC_B_SIDESLIDE:
{
- uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit->getdir(src)+4)%8 : unit->getdir(src);
+ enum unit_dir dir = unit->getdir(src);
+ if (skill_id == NC_F_SIDESLIDE)
+ dir = unit_get_opposite_dir(dir);
skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),dir,0);
clif->slide(src,src->x,src->y);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8716,10 +9524,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NC_SELFDESTRUCTION:
if (sd) {
if (pc_ismadogear(sd))
- pc->setmadogear(sd, false);
+ pc->setmadogear(sd, false, MADO_ROBOT);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag);
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
}
break;
@@ -8735,7 +9543,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int failure;
if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) )
{
- map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),skill->splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL);
if (sd) pc->overheat(sd,1);
}
@@ -8747,7 +9555,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( sd ) {
int heal, hp = 0; // % of max hp regen
if( !dstsd || !pc_ismadogear(dstsd) ) {
- clif->skill_fail(sd, skill_id,USESKILL_FAIL_TOTARGET,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0, 0);
break;
}
switch (cap_value(skill_lv, 1, 5)) {
@@ -8758,7 +9566,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case 5: hp = 23; break;
}
heal = tstatus->max_hp * hp / 100;
- status->heal(bl,heal,0,2);
+ status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src, bl, skill_id, skill_lv, heal);
}
break;
@@ -8781,7 +9589,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,bl,skill_id,1,1);
}
else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_IMITATION_SKILL_NONE,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_IMITATION_SKILL_NONE, 0, 0);
}
break;
@@ -8791,7 +9599,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
dstsd->shadowform_id = src->id;
}
else if( sd )
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case SC_BODYPAINT:
@@ -8825,9 +9633,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (is_boss(bl)) break;
joblvbonus = ( sd ? sd->status.job_level : 50 );
//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;
+ 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)));
@@ -8836,7 +9644,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int sp = 100 * skill_lv;
if( dstmd ) sp = dstmd->level * 2;
if( status_zap(bl,0,sp) )
- status->heal(src,0,sp/2,3);//What does flag 3 do? [Rytech]
+ status->heal(src, 0, sp / 2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
}
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.
@@ -8852,12 +9660,13 @@ 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);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case LG_TRAMPLE:
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
map->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick);
+ status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
break;
case LG_REFLECTDAMAGE:
@@ -8878,7 +9687,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
struct item_data *shield_data = NULL;
if( sd->equip_index[EQI_HAND_L] < 0 || !( shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]] ) || shield_data->type != IT_ARMOR ) {
//Skill will first check if a shield is equipped. If none is found on the caster the skill will fail.
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
//Generates a number between 1 - 3. The number generated will determine which effect will be triggered.
@@ -8959,7 +9768,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case 3:
sc_start(src, bl, SC_SHIELDSPELL_REF, 100, opt, INFINITE_DURATION); // HP Recovery
val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100;
- status->heal(bl, val, 0, 2);
+ status->heal(bl, val, 0, STATUS_HEAL_SHOWEFFECT);
status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER);
break;
}
@@ -9064,8 +9873,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SR_ASSIMILATEPOWER:
if( flag&1 ) {
int sp = 0;
- if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER )
- {
+ if (dstsd != NULL && dstsd->spiritball != 0 && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->job & MAPID_BASEMASK) != MAPID_GUNSLINGER) {
sp = dstsd->spiritball; //1%sp per spiritball.
pc->delspiritball(dstsd, dstsd->spiritball, 0);
status_percent_heal(src, 0, sp);
@@ -9076,14 +9884,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0);
} else {
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
case SR_POWERVELOCITY:
if( !dstsd )
break;
- if ( sd && (dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER ) {
+ if (sd != NULL && (dstsd->job & MAPID_BASEMASK) != MAPID_GUNSLINGER) {
int i, max = pc->getmaxspiritball(dstsd, 5);
for ( i = 0; i < max; i++ ) {
pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, 1), max);
@@ -9103,7 +9911,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100;
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status->get_lv(src)) / 4) - (1 + (rnd() % 10))) ) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
@@ -9174,7 +9982,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
heal = 1;
status->fixed_revive(bl, heal, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- status->set_sp(bl, 0, 0);
+ status->set_sp(bl, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -9213,7 +10021,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case WM_GLOOMYDAY:
if ( tsc && tsc->data[type] ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
// val4 indicates caster's voice lesson level
@@ -9280,10 +10088,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
improv_skill_lv = 4 + skill_lv;
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
- if (sd == NULL) {
- sd->state.abra_flag = 2;
- sd->skillitem = improv_skill_id;
- sd->skillitemlv = improv_skill_lv;
+ if (sd != NULL) {
+ sd->autocast.type = AUTOCAST_IMPROVISE;
+ sd->autocast.skill_id = improv_skill_id;
+ sd->autocast.skill_lv = improv_skill_lv;
clif->item_skill(sd, improv_skill_id, improv_skill_lv);
} else {
struct unit_data *ud = unit->bl2ud(src);
@@ -9345,7 +10153,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
}
if( !mapindex ) { //Given map not found?
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
map->freeblock_unlock();
return 0;
}
@@ -9387,6 +10195,25 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, BDT_SKILL);
break;
+ case SU_HIDE:
+ if (tsce != NULL) {
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ status_change_end(bl, type, INVALID_TIMER);
+ map->freeblock_unlock();
+ return 0;
+ }
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ break;
+
+ case SU_BUNCHOFSHRIMP:
+ if (sd == NULL || sd->status.party_id == 0 || flag&1) {
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ } else if (sd != NULL) {
+ 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 GM_SANDMAN:
if( tsc ) {
if( tsc->opt1 == OPT1_SLEEP )
@@ -9421,7 +10248,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// Summoning the new one.
if( !elemental->create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -9443,7 +10270,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case 3: mode = EL_MODE_AGGRESSIVE; break;
}
if (!elemental->change_mode(sd->ed, mode)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -9487,12 +10314,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( !ed ) break;
if( !status->charge(&sd->bl,s_hp,s_sp) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
e_hp = ed->battle_status.max_hp * 10 / 100;
e_sp = ed->battle_status.max_sp * 10 / 100;
- status->heal(&ed->bl,e_hp,e_sp,3);
+ status->heal(&ed->bl, e_hp, e_sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1);
}
break;
@@ -9518,7 +10345,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sc_start2(src,bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
(sc->bs_counter)++;
} else if( sd ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -9541,7 +10368,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case GN_SLINGITEM:
if( sd ) {
- short ammo_id;
+ int ammo_id;
int equip_idx = sd->equip_index[EQI_AMMO];
if( equip_idx <= 0 )
break; // No ammo.
@@ -9556,7 +10383,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
else
skill->attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag);
} else //Otherwise, it fails, shows animation and removes items.
- clif->skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0);
+ clif->skill_fail(sd, GN_SLINGITEM_RANGEMELEEATK, 0xa, 0, 0);
} else if( itemdb_is_GNthrowable(ammo_id) ) {
struct script_code *scriptroot = sd->inventory_data[equip_idx]->script;
if( !scriptroot )
@@ -9657,7 +10484,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
if(sd) {
- int ttype = skill->get_ele(skill_id, skill_lv);
+ enum spirit_charm_types ttype = skill->get_ele(skill_id, skill_lv);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype); // replace existing charms of other type
}
@@ -9667,7 +10494,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if(sd) {
struct mob_data *summon_md;
- summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE);
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE, 0);
if( summon_md ) {
summon_md->master_id = src->id;
summon_md->special_state.ai = AI_ZANZOU;
@@ -9684,7 +10511,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case KO_KYOUGAKU:
if (!map_flag_vs(src->m) || !dstsd) {
- if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0, 0);
break;
} else {
int time;
@@ -9706,14 +10533,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( status->get_lv(bl) <= status->get_lv(src) )
status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, SCFLAG_NONE);
} else if( sd )
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
case KO_GENWAKU:
if ( !map_flag_gvg2(src->m) && ( dstsd || dstmd ) && !(tstatus->mode&MD_PLANT) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
int x = src->x, y = src->y;
if( sd && rnd()%100 > max(5, (45 + 5 * skill_lv) - status_get_int(bl) / 10) ){//[(Base chance of success) - ( target's int / 10)]%.
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
@@ -9735,7 +10562,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case OB_OBOROGENSOU:
if( sd && ( (skill_id == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters.
|| is_boss(bl) ) ){ // Does not work on Boss monsters.
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET_PLAYER, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET_PLAYER, 0, 0);
break;
}
case KO_IZAYOI:
@@ -9768,7 +10595,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
} else {
skill->area_temp[2] = 0;
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
@@ -9793,6 +10620,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION
};
int heal;
+ if (hd == NULL)
+ break;
if(tsc){
int i;
for (i = 0; i < ARRAYLENGTH(scs); i++) {
@@ -9800,7 +10629,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
}
heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->bl, &hd->battle_status, status->get_lv(&hd->bl));
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
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), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
@@ -9848,7 +10677,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
for (i = 0; i < summons[skill_lv-1].quantity; i++) {
struct mob_data *summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src),
- summons[skill_lv-1].mob_id, "", SZ_SMALL, AI_ATTACK);
+ summons[skill_lv-1].mob_id, "", SZ_SMALL, AI_ATTACK, 0);
if (summon_md != NULL) {
summon_md->master_id = src->id;
if (summon_md->deletetimer != INVALID_TIMER)
@@ -9897,23 +10726,25 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 0;
}
-bool skill_castend_nodamage_id_dead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+static bool skill_castend_nodamage_id_dead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return true;
+ return true;
}
-bool skill_castend_nodamage_id_undead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+static bool skill_castend_nodamage_id_undead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return true;
+ return true;
}
-bool skill_castend_nodamage_id_mado_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+static bool skill_castend_nodamage_id_mado_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return false;
+ return false;
}
-bool skill_castend_nodamage_id_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+static bool skill_castend_nodamage_id_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
+ nullpo_retr(true, skill_id);
+ nullpo_retr(true, skill_lv);
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n", *skill_id);
clif->skill_nodamage(src, bl, *skill_id, *skill_lv, 1);
map->freeblock_unlock();
@@ -9923,13 +10754,14 @@ bool skill_castend_nodamage_id_unknown(struct block_list *src, struct block_list
/*==========================================
*
*------------------------------------------*/
-int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
+static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
{
struct block_list* src = map->id2bl(id);
struct map_session_data *sd;
struct unit_data *ud = unit->bl2ud(src);
struct mob_data *md;
+ nullpo_ret(src);
nullpo_ret(ud);
sd = BL_CAST(BL_PC , src);
@@ -9947,7 +10779,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && ( pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK ) )
+ if (sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd, SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
@@ -9964,7 +10796,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
skill->check_unit_range(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv)
)
{
- if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if( src->type&battle_config.skill_nofootset &&
@@ -9972,7 +10804,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
skill->check_unit_range2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv)
)
{
- if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
if( src->type&battle_config.land_skill_limit &&
@@ -9985,7 +10817,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
}
if( maxcount == 0 )
{
- if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -10028,7 +10860,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
if (ud->walktimer != INVALID_TIMER)
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv);
if (sd) { //Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
@@ -10042,7 +10874,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
skill->blockpc_start(sd, ud->skill_id, cooldown);
}
if( battle_config.display_status_timers && sd )
- clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
+ clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
#if 0
if (sd) {
switch (ud->skill_id) {
@@ -10057,10 +10889,10 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
map->freeblock_lock();
skill->castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0);
- if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
- sd->skillitem = sd->skillitemlv = 0;
+ if (sd != NULL && sd->autocast.skill_id != AL_WARP) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
+ pc->autocast_clear(sd);
- unit->setdir(src, map->calc_dir(src, ud->skillx, ud->skilly));
+ unit->set_dir(src, map->calc_dir(src, ud->skillx, ud->skilly));
if (ud->skilltimer == INVALID_TIMER) {
if (md) md->skill_idx = -1;
@@ -10072,18 +10904,18 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
return 1;
} while(0);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick;
ud->skill_id = ud->skill_lv = 0;
if(sd)
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
else if(md)
md->skill_idx = -1;
return 0;
}
-static int check_npc_chaospanic(struct block_list *bl, va_list args)
+static int skill_check_npc_chaospanic(struct block_list *bl, va_list args)
{
const struct npc_data *nd = NULL;
@@ -10096,20 +10928,57 @@ static int check_npc_chaospanic(struct block_list *bl, va_list args)
return 1;
}
+
/* skill count without self */
-static int skill_count_wos(struct block_list *bl,va_list ap) {
+static int skill_count_wos(struct block_list *bl, va_list ap)
+{
struct block_list* src = va_arg(ap, struct block_list*);
+ nullpo_retr(1, bl);
+ nullpo_retr(1, src);
if( src->id != bl->id ) {
return 1;
}
return 0;
}
+/**
+ * Returns the linked song/dance skill ID, if any (for the Bard/Dancer Soul Link).
+ *
+ * @param skill_id The skill ID to look up
+ *
+ * @return The linked song or dance's skill ID if any
+ * @retval 0 if the given skill_id doesn't have a linked skill ID
+ */
+static int skill_get_linked_song_dance_id(int skill_id)
+{
+ switch (skill_id) {
+ case BA_WHISTLE:
+ return DC_HUMMING;
+ case BA_ASSASSINCROSS:
+ return DC_DONTFORGETME;
+ case BA_POEMBRAGI:
+ return DC_FORTUNEKISS;
+ case BA_APPLEIDUN:
+ return DC_SERVICEFORYOU;
+ case DC_HUMMING:
+ return BA_WHISTLE;
+ case DC_DONTFORGETME:
+ return BA_ASSASSINCROSS;
+ case DC_FORTUNEKISS:
+ return BA_POEMBRAGI;
+ case DC_SERVICEFORYOU:
+ return BA_APPLEIDUN;
+ }
+ return 0;
+}
+
/*==========================================
*
*------------------------------------------*/
-int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *mapname) {
+static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const char *mapname)
+{
nullpo_ret(sd);
+ nullpo_ret(mapname);
//Simplify skill_failed code.
#define skill_failed(sd) ( (sd)->menuskill_id = (sd)->menuskill_val = 0 )
@@ -10179,7 +11048,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
map_index = mapindex->name2id(mapname);
if(!map_index) { //Given map not found?
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
skill_failed(sd);
return 0;
}
@@ -10194,13 +11063,13 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
maxcount--;
}
if(!maxcount) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
skill_failed(sd);
return 0;
}
}
- lv = sd->skillitem==skill_id?sd->skillitemlv:pc->checkskill(sd,skill_id);
+ lv = (sd->autocast.type > AUTOCAST_TEMP) ? sd->autocast.skill_lv : pc->checkskill(sd, skill_id);
wx = sd->menuskill_val>>16;
wy = sd->menuskill_val&0xffff;
@@ -10223,7 +11092,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
}
skill->consume_requirement(sd,sd->menuskill_id,lv,2);
- sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish]
+ pc->autocast_clear(sd); // Clear data which was skipped in skill_castend_pos().
if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) {
skill_failed(sd);
@@ -10246,7 +11115,8 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
/*==========================================
*
*------------------------------------------*/
-int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
struct map_session_data* sd;
struct status_change* sc;
struct status_change_entry *sce;
@@ -10275,6 +11145,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case HW_GANBANTEIN:
case LG_EARTHDRIVE:
case SC_ESCAPE:
+ case SU_CN_METEOR:
break; //Effect is displayed on respective switch case.
default:
skill->castend_pos2_effect_unknown(src, &x, &y, &skill_id, &skill_lv, &tick, &flag);
@@ -10311,9 +11182,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
map->foreachinarea(status->change_timer_sub,
src->m, x-r, y-r, x+r,y+r,BL_CHAR,
src,NULL,SC_SIGHT,tick);
- if(battle_config.traps_setting&1)
- map->foreachinarea(skill_reveal_trap,
- src->m, x-r, y-r, x+r, y+r, BL_SKILL);
+ if (battle_config.trap_visibility != 0) {
+ map->foreachinarea(skill_reveal_trap,
+ src->m, x - r, y - r, x + r, y + r, BL_SKILL);
+ }
break;
case SR_RIDEINLIGHTNING:
@@ -10339,10 +11211,11 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case SC_CHAOSPANIC:
case SC_MAELSTROM:
- if (sd && map->foreachinarea(&check_npc_chaospanic,src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd && map->foreachinarea(skill->check_npc_chaospanic, src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
+ FALLTHROUGH
case MG_SAFETYWALL:
{
@@ -10352,6 +11225,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
return 0; // Don't consume gems if cast on LP
}
}
+ FALLTHROUGH
case MG_FIREWALL:
case MG_THUNDERSTORM:
@@ -10461,10 +11335,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
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 SU_CN_POWDERING:
+ case SU_SV_ROOTTWIST:
+ flag |= 1; // Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
+ FALLTHROUGH
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
if ( skill_id == WM_SEVERE_RAINSTORM )
- sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv));
+ sc_start(src, src, type, 100, 0, skill->get_time(skill_id, skill_lv));
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
case WZ_ICEWALL:
@@ -10481,9 +11358,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if( sc && sc->data[SC_BASILICA] )
status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica
else { // Create Basilica. Start SC on caster. Unit timer start SC on others.
- if( map->foreachinrange(skill_count_wos, src, 2, BL_MOB|BL_PC, src) ) {
+ if( map->foreachinrange(skill->count_wos, src, 2, BL_MOB|BL_PC, src) ) {
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
return 1;
}
@@ -10513,11 +11390,24 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
break;
case WZ_METEOR:
+ case SU_CN_METEOR:
{
int area = skill->get_splash(skill_id, skill_lv);
short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
int i;
+#if 0
+ // The Meteor should inflict curse if Catnip fruit is consumed.
+ // Currently Catnip fruit is added as requirement.
+ if (sd && skill_id == SU_CN_METEOR) {
+ short item_idx = pc->search_inventory(sd, ITEMID_CATNIP_FRUIT);
+ if (item_idx >= 0) {
+ pc->delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_SKILL);
+ flag |= 1;
+ }
+ }
+#endif
+
for( i = 0; i < 2 + (skill_lv>>1); i++ ) {
// Creates a random Cell in the Splash Area
tmpx = x - area + rnd()%(area * 2 + 1);
@@ -10569,6 +11459,19 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
}
status_change_end(src, SC_HIDING, INVALID_TIMER);
break;
+ case SU_LOPE:
+ {
+ if (map->list[src->m].flag.noteleport && !(map->list[src->m].flag.battleground || map_flag_gvg2(src->m))) {
+ x = src->x;
+ y = src->y;
+ }
+ clif->skill_nodamage(src, src, SU_LOPE, skill_lv, 1);
+ if(!map->count_oncell(src->m, x, y, BL_PC | BL_NPC | BL_MOB, 0) && map->getcell(src->m, src, x, y, CELL_CHKREACH)) {
+ clif->slide(src, x, y);
+ unit->movepos(src, x, y, 1, 0);
+ }
+ }
+ break;
case AM_SPHEREMINE:
case AM_CANNIBALIZE:
{
@@ -10588,7 +11491,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
}
// Correct info, don't change any of this! [Celest]
- md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), class_, "", SZ_SMALL, AI_NONE);
+ md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), class_, "", SZ_SMALL, AI_NONE, 0);
if (md) {
md->master_id = src->id;
md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
@@ -10603,55 +11506,58 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
// Slim Pitcher [Celest]
case CR_SLIMPITCHER:
if (sd) {
- int i = skill_lv%11 - 1;
- int j = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[i]);
- if (j == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[i] <= 0
- || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->dbs->db[skill_id].amount[i]
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ int inventory_idx = pc->search_inventory(sd, item_id);
+ int bonus;
+ if (inventory_idx == INDEX_NOT_FOUND || item_id <= 0
+ || sd->inventory_data[inventory_idx] == NULL
+ || sd->status.inventory[inventory_idx].amount < skill->get_itemqty(skill_id, item_idx)
) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
script->potion_flag = 1;
script->potion_hp = 0;
script->potion_sp = 0;
- script->run_use_script(sd, sd->inventory_data[j], 0);
+ script->run_use_script(sd, sd->inventory_data[inventory_idx], 0);
script->potion_flag = 0;
//Apply skill bonuses
- i = pc->checkskill(sd,CR_SLIMPITCHER)*10
+ bonus = pc->checkskill(sd,CR_SLIMPITCHER)*10
+ pc->checkskill(sd,AM_POTIONPITCHER)*10
+ pc->checkskill(sd,AM_LEARNINGPOTION)*5
+ pc->skillheal_bonus(sd, skill_id);
- script->potion_hp = script->potion_hp * (100+i)/100;
- script->potion_sp = script->potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100 + bonus) / 100;
+ script->potion_sp = script->potion_sp * (100 + bonus) / 100;
- if(script->potion_hp > 0 || script->potion_sp > 0) {
- i = skill->get_splash(skill_id, skill_lv);
+ if (script->potion_hp > 0 || script->potion_sp > 0) {
+ r = skill->get_splash(skill_id, skill_lv);
map->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ src->m, x - r, y - r, x + r, y + r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_PARTY|BCT_GUILD|1,
skill->castend_nodamage_id);
}
} else {
- int i = skill_lv%11 - 1;
- struct item_data *item;
- i = skill->dbs->db[skill_id].itemid[i];
- item = itemdb->search(i);
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ struct item_data *item = itemdb->search(item_id);
+ int bonus;
script->potion_flag = 1;
script->potion_hp = 0;
script->potion_sp = 0;
script->run(item->script,0,src->id,0);
script->potion_flag = 0;
- i = skill->get_max(CR_SLIMPITCHER)*10;
+ bonus = skill->get_max(CR_SLIMPITCHER)*10;
- script->potion_hp = script->potion_hp * (100+i)/100;
- script->potion_sp = script->potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100 + bonus)/100;
+ script->potion_sp = script->potion_sp * (100 + bonus)/100;
- if(script->potion_hp > 0 || script->potion_sp > 0) {
- i = skill->get_splash(skill_id, skill_lv);
+ if (script->potion_hp > 0 || script->potion_sp > 0) {
+ r = skill->get_splash(skill_id, skill_lv);
map->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ src->m, x - r, y - r, x + r, y + r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_PARTY|BCT_GUILD|1,
skill->castend_nodamage_id);
}
}
@@ -10664,7 +11570,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
r = skill->get_splash(skill_id, skill_lv);
map->foreachinarea(skill->cell_overlap, src->m, x-r, y-r, x+r, y+r, BL_SKILL, HW_GANBANTEIN, &dummy, src);
} else {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
break;
@@ -10679,15 +11585,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case CR_CULTIVATION:
if (sd) {
if( map->count_oncell(src->m,x,y,BL_CHAR,0) > 0 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
clif->skill_poseffect(src,skill_id,skill_lv,x,y,tick);
if (rnd()%100 < 50) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
} else {
int mob_id = skill_lv < 2 ? MOBID_BLACK_MUSHROOM + rnd()%2 : MOBID_RED_PLANT + rnd()%6;
- struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, "--ja--", mob_id, "", SZ_SMALL, AI_NONE);
+ struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, DEFAULT_MOB_JNAME, mob_id, "", SZ_SMALL, AI_NONE, 0);
int i;
if (md == NULL)
break;
@@ -10733,7 +11639,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
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);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
break;
}
}
@@ -10746,7 +11652,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RK_DRAGONBREATH:
case RK_DRAGONBREATH_WATER:
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
break;
case WM_GREAT_ECHO:
@@ -10768,7 +11674,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
break;
case SO_ARRULLO:
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
break;
/**
@@ -10777,7 +11683,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case GC_POISONSMOKE:
if( !(sc && sc->data[SC_POISONINGWEAPON]) ) {
if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_POISONINGWEAPON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_POISONINGWEAPON, 0, 0);
return 0;
}
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL);
@@ -10796,17 +11702,16 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case WL_EARTHSTRAIN:
{
- int i, wave = skill_lv + 4, dir = map->calc_dir(src,x,y);
+ int i;
+ int wave = skill_lv + 4;
+ enum unit_dir dir = map->calc_dir(src, x, y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting
- for( i = 1; i <= wave; i++ )
- {
- switch( dir ){
- case 0: case 1: case 7: sy = y + i; break;
- case 3: case 4: case 5: sy = y - i; break;
- case 2: sx = x - i; break;
- case 6: sx = x + i; break;
- }
+ for (i = 1; i <= wave; i++) {
+ sy = y + i * diry[dir];
+ if (dir == UNIT_DIR_WEST || dir == UNIT_DIR_EAST)
+ sx = x + i * dirx[dir];
skill->addtimerskill(src,timer->gettick() + (140 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2);
}
}
@@ -10833,7 +11738,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case NC_SILVERSNIPER:
{
- struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE);
+ struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE, 0);
if (md) {
md->master_id = src->id;
md->special_state.ai = AI_FLORA;
@@ -10883,10 +11788,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case LG_RAYOFGENESIS:
if( status->charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) {
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
} else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
break;
case WM_DOMINION_IMPULSE:
@@ -10995,20 +11900,22 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
return 0;
}
-void skill_castend_pos2_effect_unknown(struct block_list* src, int *x, int *y, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
+static void skill_castend_pos2_effect_unknown(struct block_list *src, int *x, int *y, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+{
if (skill->get_inf(*skill_id) & INF_SELF_SKILL)
clif->skill_nodamage(src, src, *skill_id, *skill_lv, 1);
else
clif->skill_poseffect(src, *skill_id, *skill_lv, *x, *y, *tick);
}
-bool skill_castend_pos2_unknown(struct block_list* src, int *x, int *y, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
+static bool skill_castend_pos2_unknown(struct block_list *src, int *x, int *y, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
+{
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n", *skill_id);
return true;
}
/// transforms 'target' skill unit into dissonance (if conditions are met)
-int skill_dance_overlap_sub(struct block_list *bl, va_list ap)
+static int skill_dance_overlap_sub(struct block_list *bl, va_list ap)
{
struct skill_unit *target = NULL;
struct skill_unit *src = va_arg(ap, struct skill_unit*);
@@ -11038,7 +11945,8 @@ int skill_dance_overlap_sub(struct block_list *bl, va_list ap)
//Does the song/dance overlapping -> dissonance check. [Skotlex]
//When flag is 0, this unit is about to be removed, cancel the dissonance effect
//When 1, this unit has been positioned, so start the cancel effect.
-int skill_dance_overlap(struct skill_unit* su, int flag) {
+static int skill_dance_overlap(struct skill_unit *su, int flag)
+{
if (!su || !su->group || !(su->group->state.song_dance&0x1))
return 0;
@@ -11060,7 +11968,8 @@ int skill_dance_overlap(struct skill_unit* su, int flag) {
* @param flag 1 Revert
* @retval true success
**/
-bool skill_dance_switch(struct skill_unit* su, int flag) {
+static 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;
@@ -11116,7 +12025,8 @@ bool skill_dance_switch(struct skill_unit* su, int flag) {
* Initializes and sets a ground skill.
* flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
*------------------------------------------*/
-struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag) {
+static struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag)
+{
struct skill_unit_group *group;
int i,limit,val1=0,val2=0,val3=0;
int target,interval,range,unit_flag,req_item=0;
@@ -11146,9 +12056,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
sd = BL_CAST(BL_PC, src);
st = status->get_status_data(src);
+ nullpo_retr(NULL, st);
sc = status->get_sc(src); // for traps, firewall and fogwall - celest
- switch( skill_id ) {
+ switch (skill_id) {
case SO_ELEMENTAL_SHIELD:
val2 = 300 * skill_lv + 65 * (st->int_ + status->get_lv(src)) + st->max_sp;
break;
@@ -11217,8 +12128,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case HT_ANKLESNARE:
if( flag&2 )
val3 = SC_ESCAPE;
+ FALLTHROUGH
case HT_SHOCKWAVE:
val1=skill_lv*15+10;
+ FALLTHROUGH
case HT_SANDMAN:
case MA_SANDMAN:
case HT_CLAYMORETRAP:
@@ -11243,7 +12156,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case RA_ICEBOUNDTRAP:
{
struct skill_condition req = skill->get_requirement(sd,skill_id,skill_lv);
- ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY));
+ ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_BOOBY_TRAP || req.itemid[i] == ITEMID_SPECIAL_ALLOY_TRAP));
if( i != MAX_SKILL_ITEM_REQUIRE && req.itemid[i] )
req_item = req.itemid[i];
if( map_flag_gvg2(src->m) || map->list[src->m].flag.battleground )
@@ -11396,23 +12309,27 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE};
val1 = st->rhw.ele;
- if (!val1)
- val1=element[rnd()%5];
+ if (val1 == ELE_NEUTRAL)
+ val1 = element[rnd() % ARRAYLENGTH(element)];
- switch (val1)
- {
+ switch (val1) {
case ELE_FIRE:
- subunt++;
+ subunt = 4;
+ break;
case ELE_WATER:
- subunt++;
+ subunt = 3;
+ break;
case ELE_POISON:
- subunt++;
+ subunt = 2;
+ break;
case ELE_DARK:
- subunt++;
+ subunt = 1;
+ break;
case ELE_WIND:
+ subunt = 0;
break;
default:
- subunt=rnd()%5;
+ subunt = rnd() % 5;
break;
}
@@ -11445,6 +12362,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
target = BCT_ALL;
val1 = skill_lv + 1;
val2 = 1;
+ FALLTHROUGH
case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector.
case SO_WATER_INSIGNIA:
case SO_FIRE_INSIGNIA:
@@ -11487,6 +12405,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
break;
}
+ nullpo_retr(NULL, layout);
nullpo_retr(NULL, group=skill->init_unitgroup(src,layout->count,skill_id,skill_lv,skill->get_unit_id(skill_id,flag&1)+subunt, limit, interval));
group->val1=val1;
group->val2=val2;
@@ -11627,10 +12546,15 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
return group;
}
-void skill_unitsetting1_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *val1, int *val2, int *val3) {
+static void skill_unitsetting1_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *val1, int *val2, int *val3)
+{
}
-void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *unit_flag, int *val1, int *val2, int *val3, struct skill_unit_group *group) {
+static void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *unit_flag, int *val1, int *val2, int *val3, struct skill_unit_group *group)
+{
+ nullpo_retv(group);
+ nullpo_retv(val2);
+ nullpo_retv(unit_flag);
if (group->state.song_dance & 0x1)
*val2 = *unit_flag & (UF_DANCE | UF_SONG); //Store whether this is a song/dance
}
@@ -11638,7 +12562,8 @@ void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16
/*==========================================
*
*------------------------------------------*/
-int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick) {
+static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick)
+{
struct skill_unit_group *sg;
struct block_list *ss;
struct status_change *sc;
@@ -11716,7 +12641,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (bl->type == BL_PC && !working) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
- if ((!sd->chatID || battle_config.chat_warpportal) && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) {
+ if ((sd->chat_id == 0 || battle_config.chat_warpportal) && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) {
int x = sg->val2>>16;
int y = sg->val2&0xffff;
int count = sg->val1>>16;
@@ -11762,6 +12687,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
case UNT_HERMODE:
if (sg->src_id!=bl->id && battle->check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0)
status->change_clear_buffs(bl,1); //Should dispell only allies.
+ FALLTHROUGH
case UNT_RICHMANKIM:
case UNT_ETERNALCHAOS:
case UNT_DRUMBATTLEFIELD:
@@ -11780,6 +12706,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!battle_config.song_timer_reset && sc && sce)
return 0;
// Let it fall through
+ FALLTHROUGH
case UNT_WHISTLE:
case UNT_ASSASSINCROSS:
case UNT_POEMBRAGI:
@@ -11859,7 +12786,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (sg->src_id == bl->id)
break; //Does not affect the caster.
clif->changetraplook(&src->bl,UNT_USED_TRAPS);
- map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
sg->unit_id = UNT_USED_TRAPS;
sg->limit = DIFF_TICK32(tick,sg->tick) + 1500;
break;
@@ -11869,6 +12796,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
sc_start(ss, bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv));
break;
+ case UNT_CATNIPPOWDER:
+ if (sg->src_id == bl->id || (status_get_mode(bl)&MD_BOSS))
+ break; // Does not affect the caster or Boss.
+ if (sce == NULL && battle->check_target(&src->bl, bl, BCT_ENEMY) > 0)
+ sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time(sg->skill_id, sg->skill_lv));
+ break;
+
case UNT_GD_LEADERSHIP:
case UNT_GD_GLORYWOUNDS:
case UNT_GD_SOULCOLD:
@@ -11883,17 +12817,19 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
return skill_id;
}
-void skill_unit_onplace_unknown(struct skill_unit *src, struct block_list *bl, int64 *tick) {
+static void skill_unit_onplace_unknown(struct skill_unit *src, struct block_list *bl, int64 *tick)
+{
}
/*==========================================
*
*------------------------------------------*/
-int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick) {
+static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick)
+{
struct skill_unit_group *sg;
struct block_list *ss;
struct map_session_data *tsd;
- struct status_data *tstatus, *bst;
+ struct status_data *tstatus;
struct status_change *tsc, *ssc;
struct skill_unit_group_tickset *ts;
enum sc_type type;
@@ -11917,7 +12853,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
return 0;
tstatus = status->get_status_data(bl);
- bst = status->get_base_status(bl);
+ nullpo_ret(tstatus);
type = status->skill2sc(sg->skill_id);
skill_id = sg->skill_id;
@@ -11965,6 +12901,13 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
ts->tick += sg->interval*(map->count_oncell(bl->m,bl->x,bl->y,BL_CHAR,0)-1);
}
+ if (sg->skill_id == HT_ANKLESNARE
+ || (battle_config.trap_trigger == 1 && skill->get_inf2(sg->skill_id) & INF2_HIDDEN_TRAP)
+ ) {
+ src->visible = true;
+ clif->skillunit_update(&src->bl);
+ }
+
switch (sg->unit_id) {
case UNT_FIREWALL:
case UNT_KAEN: {
@@ -12006,7 +12949,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
if (tsc && tsc->data[SC_AKAITSUKI] && heal)
heal = ~heal + 1;
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if (diff >= 500)
sg->val1--;
}
@@ -12027,7 +12970,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if (status->isimmune(bl))
heal = 0;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
}
break;
@@ -12074,12 +13017,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
tsc->sg_counter++; //SG hit counter.
if (skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc)
tsc->sg_counter=0; //Attack absorbed.
- break;
+ break;
#endif
case GS_DESPERADO:
if (rnd()%100 < src->val1)
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
- break;
+ break;
default:
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
@@ -12117,10 +13060,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
clif->fixpos(bl);
}
sg->val2 = bl->id;
- } else
+ } else {
sec = 3000; //Couldn't trap it?
+ }
+
if( sg->unit_id == UNT_ANKLESNARE ) {
- clif->skillunit_update(&src->bl);
/**
* If you're snared from a trap that was invisible this makes the trap be
* visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE")
@@ -12144,7 +13088,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
}
- map->foreachinrange(skill->trap_splash, &src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick);
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
}
break;
@@ -12160,11 +13104,13 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_VERDURETRAP:
if( bl->type == BL_PC )// it won't work on players
break;
+ FALLTHROUGH
case UNT_FIRINGTRAP:
case UNT_ICEBOUNDTRAP:
case UNT_CLUSTERBOMB:
if( bl->id == ss->id )// it won't trigger on caster
break;
+ FALLTHROUGH
case UNT_LANDMINE:
case UNT_BLASTMINE:
case UNT_SHOCKWAVE:
@@ -12173,10 +13119,10 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_FREEZINGTRAP:
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);
+ if (sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP)
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag | BL_SKILL | ~BCT_SELF, tick);
else
- map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
if (sg->unit_id != UNT_FIREPILLAR_ACTIVE)
clif->changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
sg->limit=DIFF_TICK32(tick,sg->tick)+1500 +
@@ -12236,7 +13182,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -12290,7 +13236,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case 0: // Heal 1~9999 HP
heal = rnd() %9999+1;
clif->skill_nodamage(ss,bl,AL_HEAL,heal,1);
- status->heal(bl,heal,0,0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
break;
case 1: // End all negative status
status->change_clear_buffs(bl,2);
@@ -12407,9 +13353,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_GROUNDDRIFT_POISON:
case UNT_GROUNDDRIFT_WATER:
case UNT_GROUNDDRIFT_FIRE:
- map->foreachinrange(skill->trap_splash,&src->bl,
- skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag,
- &src->bl,tick);
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
sg->unit_id = UNT_USED_TRAPS;
//clif->changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE);
sg->limit=DIFF_TICK32(tick,sg->tick)+1500;
@@ -12437,7 +13381,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
}
hp = tstatus->max_hp * hp / 100;
sp = tstatus->max_sp * sp / 100;
- status->heal(bl, hp, sp, 2);
+ status->heal(bl, hp, sp, STATUS_HEAL_SHOWEFFECT);
sc_start(ss, bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100);
}
// Reveal hidden players every 5 seconds.
@@ -12456,6 +13400,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; // Don't work on Self (video shows that)
+ FALLTHROUGH
case UNT_NEUTRALBARRIER:
sc_start(ss,bl,type,100,sg->skill_lv,sg->interval + 100);
break;
@@ -12469,7 +13414,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_REVERBERATION:
clif->changetraplook(&src->bl,UNT_USED_TRAPS);
- map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
sg->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
break;
@@ -12558,7 +13503,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0);
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
hp = ~hp + 1;
- status->heal(bl, hp, 0, 0);
+ status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT);
sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval + 100);
}
break;
@@ -12572,13 +13517,13 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
int hp = tstatus->max_hp / 100; //+1% each 5s
if ((sg->val3) % 5) { //each 5s
if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)) {
- status->heal(bl, hp, 0, 2);
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
} else if( (sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH)
|| (sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE)
|| (sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER)
|| (sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND)
) {
- status->heal(bl, -hp, 0, 0);
+ status->heal(bl, -hp, 0, STATUS_HEAL_DEFAULT);
}
}
sg->val3++; //timer
@@ -12590,6 +13535,8 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) {
return 0;
} else {
+ struct status_data *bst = status->get_base_status(bl);
+ nullpo_ret(bst);
sg->limit -= 1000 * bst->str/20;
sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
@@ -12646,6 +13593,33 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0,
skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
+ case UNT_SV_ROOTTWIST:
+ if (status_get_mode(bl)&MD_BOSS) {
+ break;
+ }
+ if (tsc) {
+ if (!sg->val2) {
+ int sec = skill->get_time(sg->skill_id, sg->skill_lv);
+
+ if (sc_start2(ss, bl, type, 100, sg->skill_lv, sg->group_id, sec)) {
+ const struct TimerData* td = ((tsc->data[type])? timer->get(tsc->data[type]->timer) : NULL);
+
+ if (td != NULL)
+ sec = DIFF_TICK32(td->tick, tick);
+ clif->fixpos(bl);
+ sg->val2 = bl->id;
+ } else { // Couldn't trap it?
+ sec = 7000;
+ }
+ sg->limit = DIFF_TICK32(tick, sg->tick) + sec;
+ } else if (tsc->data[type] && bl->id == sg->val2) {
+ skill->attack(skill->get_type(SU_SV_ROOTTWIST_ATK), ss, &src->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
+ }
+ }
+ break;
+ default:
+ skill->unit_onplace_timer_unknown(src, bl, &tick);
+ break;
}
if (bl->type == BL_MOB && ss != bl)
@@ -12653,10 +13627,16 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
return skill_id;
}
+
+static void skill_unit_onplace_timer_unknown(struct skill_unit *src, struct block_list *bl, int64 *tick)
+{
+}
+
/*==========================================
* Triggered when a char steps out of a skill cell
*------------------------------------------*/
-int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) {
+static int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
+{
struct skill_unit_group *sg;
struct status_change *sc;
struct status_change_entry *sce;
@@ -12721,7 +13701,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
/*==========================================
* Triggered when a char steps out of a skill group (entirely) [Skotlex]
*------------------------------------------*/
-int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
+static int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick)
+{
struct status_change *sc;
struct status_change_entry *sce;
enum sc_type type;
@@ -12806,7 +13787,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case PF_FOGWALL:
if (sce) {
status_change_end(bl, type, INVALID_TIMER);
- if ((sce=sc->data[SC_BLIND])) {
+ nullpo_retb(sc);
+ if ((sce = sc->data[SC_BLIND])) {
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 {
@@ -12834,14 +13816,19 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
* flag&1: Invoke onplace function (otherwise invoke onout)
* flag&4: Invoke a onleft call (the unit might be scheduled for deletion)
*------------------------------------------*/
-int skill_unit_effect(struct block_list* bl, va_list ap) {
+static int skill_unit_effect(struct block_list *bl, va_list ap)
+{
struct skill_unit* su = va_arg(ap,struct skill_unit*);
- struct skill_unit_group* group = su->group;
+ struct skill_unit_group* group;
int64 tick = va_arg(ap,int64);
unsigned int flag = va_arg(ap,unsigned int);
uint16 skill_id;
bool dissonance;
+ nullpo_ret(bl);
+ nullpo_ret(su);
+ group = su->group;
+
if( (!su->alive && !(flag&4)) || bl->prev == NULL )
return 0;
@@ -12873,7 +13860,8 @@ int skill_unit_effect(struct block_list* bl, va_list ap) {
/*==========================================
*
*------------------------------------------*/
-int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick) {
+static int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick)
+{
struct skill_unit_group *sg;
nullpo_ret(src);
@@ -12907,7 +13895,7 @@ int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 da
/*==========================================
*
*------------------------------------------*/
-int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
+static int skill_check_condition_char_sub(struct block_list *bl, va_list ap)
{
struct map_session_data *tsd = NULL;
struct block_list *src = va_arg(ap, struct block_list *);
@@ -12936,33 +13924,34 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
return 0;
if( skill->get_inf2(skill_id)&INF2_CHORUS_SKILL ) {
- if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER )
+ if (tsd->status.party_id == sd->status.party_id && (tsd->job & MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER)
p_sd[(*c)++] = tsd->bl.id;
return 1;
} else {
switch(skill_id) {
- case PR_BENEDICTIO: {
- uint8 dir = map->calc_dir(&sd->bl,tsd->bl.x,tsd->bl.y);
- dir = (unit->getdir(&sd->bl) + dir)%8; //This adjusts dir to account for the direction the sd is facing.
- if ((tsd->class_&MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == 2 || dir == 6) //Must be standing to the left/right of Priest.
- && sd->status.sp >= 10)
+ case PR_BENEDICTIO:
+ {
+ enum unit_dir dir = map->calc_dir(&sd->bl, tsd->bl.x, tsd->bl.y);
+ dir = (unit->getdir(&sd->bl) + dir) % UNIT_DIR_MAX; //This adjusts dir to account for the direction the sd is facing.
+ if ((tsd->job & MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == UNIT_DIR_WEST || dir == UNIT_DIR_EAST) //Must be standing to the left/right of Priest.
+ && sd->status.sp >= 10) {
p_sd[(*c)++]=tsd->bl.id;
+ }
return 1;
}
case AB_ADORAMUS:
// Adoramus does not consume Blue Gemstone when there is at least 1 Priest class next to the caster
- if( (tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST )
+ if ((tsd->job & MAPID_UPPERMASK) == MAPID_PRIEST)
p_sd[(*c)++] = tsd->bl.id;
return 1;
case WL_COMET:
// Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster
- if( ( tsd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK )
+ if ((tsd->job & MAPID_THIRDMASK) == MAPID_WARLOCK)
p_sd[(*c)++] = tsd->bl.id;
return 1;
case LG_RAYOFGENESIS:
- if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD &&
- tsd->sc.data[SC_BANDING] )
+ if (tsd->status.party_id == sd->status.party_id && (tsd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD && tsd->sc.data[SC_BANDING])
p_sd[(*c)++] = tsd->bl.id;
return 1;
default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex]
@@ -12971,7 +13960,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
if(pc_issit(tsd) || !unit->can_move(&tsd->bl))
return 0;
if (sd->status.sex != tsd->status.sex &&
- (tsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER &&
+ (tsd->job & MAPID_UPPERMASK) == MAPID_BARDDANCER &&
(skill_lv = pc->checkskill(tsd, skill_id)) > 0 &&
(tsd->weapontype1==W_MUSICAL || tsd->weapontype1==W_WHIP) &&
sd->status.party_id && tsd->status.party_id &&
@@ -12994,12 +13983,16 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
/*==========================================
* Checks and stores partners for ensemble skills [Skotlex]
*------------------------------------------*/
-int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag) {
+static int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16 *skill_lv, int range, int cast_flag)
+{
static int c=0;
static int p_sd[2] = { 0, 0 };
int i;
bool is_chorus = ( skill->get_inf2(skill_id)&INF2_CHORUS_SKILL );
+ nullpo_ret(sd);
+ nullpo_ret(skill_lv);
+
if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL))
return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners.
@@ -13049,7 +14042,7 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16
/*==========================================
*
*------------------------------------------*/
-int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap)
+static int skill_check_condition_mob_master_sub(struct block_list *bl, va_list ap)
{
const struct mob_data *md = NULL;
int src_id = va_arg(ap, int);
@@ -13074,11 +14067,12 @@ int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap)
* Determines if a given skill should be made to consume ammo
* when used by the player. [Skotlex]
*------------------------------------------*/
-int skill_isammotype (struct map_session_data *sd, int skill_id)
+static int skill_isammotype(struct map_session_data *sd, int skill_id)
{
+ nullpo_ret(sd);
return (
battle_config.arrow_decrement==2 &&
- (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) &&
+ (sd->weapontype == W_BOW || (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE)) &&
skill_id != HT_PHANTASMIC &&
skill->get_type(skill_id) == BF_WEAPON &&
!(skill->get_nk(skill_id)&NK_NO_DAMAGE) &&
@@ -13089,43 +14083,35 @@ int skill_isammotype (struct map_session_data *sd, int skill_id)
/**
* Checks whether a skill can be used in combos or not
**/
-bool skill_is_combo( int skill_id )
+static bool skill_is_combo(int skill_id)
{
- switch( skill_id )
- {
- case MO_CHAINCOMBO:
- case MO_COMBOFINISH:
- case CH_TIGERFIST:
- case CH_CHAINCRUSH:
- case MO_EXTREMITYFIST:
- case TK_TURNKICK:
- case TK_STORMKICK:
- case TK_DOWNKICK:
- case TK_COUNTER:
- case TK_JUMPKICK:
- case HT_POWER:
- case GC_COUNTERSLASH:
- case GC_WEAPONCRUSH:
- case SR_FALLENEMPIRE:
- case SR_DRAGONCOMBO:
- case SR_TIGERCANNON:
- case SR_GATEOFHELL:
- return true;
- }
+ if (skill->get_inf2(skill_id) & INF2_IS_COMBO_SKILL)
+ return true;
+
return false;
}
-int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
+static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
+{
struct status_data *st;
struct status_change *sc;
struct skill_condition require;
nullpo_ret(sd);
- if (sd->chatID) return 0;
+ if (skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL)
+ return 0;
+
+ if (sd->chat_id != 0)
+ return 0;
- if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id) {
- //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
+ if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
+ && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ return 1;
+ }
+
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ // GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
return 1;
@@ -13156,34 +14142,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( !sc->count )
sc = NULL;
- if( sd->skillitem == skill_id ) {
- if( sd->state.abra_flag ) // Hocus-Pocus was used. [Inkfish]
- sd->state.abra_flag = 0;
- else {
- int i;
- // When a target was selected, consume items that were skipped in pc_use_item [Skotlex]
- if( (i = sd->itemindex) == -1 ||
- sd->status.inventory[i].nameid != sd->itemid ||
- sd->inventory_data[i] == NULL ||
- !sd->inventory_data[i]->flag.delay_consume ||
- sd->status.inventory[i].amount < 1
- ) {
- //Something went wrong, item exploit?
- sd->itemid = sd->itemindex = -1;
- return 0;
- }
- //Consume
- sd->itemid = sd->itemindex = -1;
- if( skill_id == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007]
- ; //Do not consume item.
- else if( sd->status.inventory[i].expire_time == 0 ) // Rental usable items are not consumed until expiration
- pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME);
- }
- return 1;
- }
-
- if( pc_is90overweight(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0);
+ if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -13211,8 +14171,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SG_FUSION:
case RA_WUGDASH:
case KO_YAMIKUMO:
- if( sc && sc->data[status->skill2sc(skill_id)] )
+ case SU_HIDE:
+ if (sc && sc->data[status->skill2sc(skill_id)])
return 1;
+ FALLTHROUGH
default:
{
int ret = skill->check_condition_castbegin_off_unknown(sc, &skill_id);
@@ -13304,9 +14266,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
}
- if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
- return 0;
-
require = skill->get_requirement(sd,skill_id,skill_lv);
//Can only update state when weapon/arrow info is checked.
@@ -13314,14 +14273,28 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
// perform skill-specific checks (and actions)
switch( skill_id ) {
+ case MC_VENDING:
+ case ALL_BUYING_STORE:
+ if (map->list[sd->bl.m].flag.novending) {
+ clif->message(sd->fd, msg_sd(sd, 276)); // "You can't open a shop on this map"
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ return 0;
+ }
+ if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) {
+ clif->message(sd->fd, msg_sd(sd, 204)); // "You can't open a shop on this cell."
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
+ return 0;
+ }
+ break;
case SO_SPELLFIST:
if(sd->skill_id_old != MG_FIREBOLT && sd->skill_id_old != MG_COLDBOLT && sd->skill_id_old != MG_LIGHTNINGBOLT){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case SA_CASTCANCEL:
if(sd->ud.skilltimer == INVALID_TIMER) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13336,7 +14309,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if(sc && sc->data[SC_RAISINGDRAGON])
skill_lv += sc->data[SC_RAISINGDRAGON]->val1;
if(sd->spiritball >= skill_lv) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13357,7 +14330,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (sc->data[SC_COMBOATTACK]) {
if( sc->data[SC_COMBOATTACK]->val1 == MO_TRIPLEATTACK )
break;
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_TRIPLEATTACK);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_TRIPLEATTACK, 0);
}
return 0;
case MO_COMBOFINISH:
@@ -13366,7 +14339,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[SC_COMBOATTACK] ) {
if ( sc->data[SC_COMBOATTACK]->val1 == MO_CHAINCOMBO )
break;
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_CHAINCOMBO);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_CHAINCOMBO, 0);
}
return 0;
case CH_TIGERFIST:
@@ -13375,7 +14348,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[SC_COMBOATTACK] ) {
if ( sc->data[SC_COMBOATTACK]->val1 == MO_COMBOFINISH )
break;
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_COMBOFINISH);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_COMBOFINISH, 0);
}
return 0;
case CH_CHAINCRUSH:
@@ -13384,7 +14357,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[SC_COMBOATTACK] ) {
if( sc->data[SC_COMBOATTACK]->val1 == CH_TIGERFIST )
break;
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, CH_TIGERFIST);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, CH_TIGERFIST, 0);
}
return 0;
case MO_EXTREMITYFIST:
@@ -13405,15 +14378,15 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
} else if (!unit->can_move(&sd->bl)) {
//Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex]
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case TK_MISSION:
- if( (sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON ) {
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_TAEKWON) {
// Cannot be used by Non-Taekwon classes
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13423,9 +14396,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case TK_READYSTORM:
case TK_READYTURN:
case TK_JUMPKICK:
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SOUL_LINKER) {
// Soul Linkers cannot use this skill
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13434,7 +14407,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case TK_STORMKICK:
case TK_DOWNKICK:
case TK_COUNTER:
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
return 0; //Anti-Soul Linker check in case you job-changed with Stances active.
if(!(sc && sc->data[SC_COMBOATTACK]) || sc->data[SC_COMBOATTACK]->val1 == TK_JUMPKICK)
return 0; //Combo needs to be ready
@@ -13446,7 +14419,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
status_change_end(&sd->bl, SC_COMBOATTACK, INVALID_TIMER);
return 0;
}
- if(sc->data[SC_COMBOATTACK]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) {
+ if (sc->data[SC_COMBOATTACK]->val1 != skill_id
+ && !(sd != NULL && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0)) {
//Cancel combo wait.
unit->cancel_combo(&sd->bl);
return 0;
@@ -13457,7 +14431,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
int time;
if(!(sc && sc->data[SC_DANCING]))
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
time = 1000*(sc->data[SC_DANCING]->val3>>16);
@@ -13466,7 +14440,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
(sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV
- time < skill->get_time2(skill_id,skill_lv))
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
}
@@ -13475,7 +14449,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case PR_BENEDICTIO:
if (skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 2)
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13493,7 +14467,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case CG_HERMODE:
if(!npc->check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill->get_splash(skill_id, skill_lv)))
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13505,7 +14479,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
int x = sd->bl.x+(i%size-range);
int y = sd->bl.y+(i/size-range);
if (map->getcell(sd->bl.m, &sd->bl, x, y, CELL_CHKWALL)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
}
@@ -13513,10 +14487,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
case PR_REDEMPTIO:
{
- int exp;
- if( ((exp = pc->nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) ||
- ((exp = pc->nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //Not enough exp.
+ int64 exp;
+ if (((exp = pc->nextbaseexp(sd)) > 0 && get_percentage64(sd->status.base_exp, exp) < 1) ||
+ ((exp = pc->nextjobexp(sd)) > 0 && get_percentage64(sd->status.job_exp, exp) < 1)) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0); //Not enough exp.
return 0;
}
break;
@@ -13525,7 +14499,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case AM_TWILIGHT3:
if (!party->skill_check(sd, sd->status.party_id, skill_id, skill_lv))
{
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13536,7 +14510,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
if (sd->bl.m == sd->feel_map[skill_id-SG_SUN_WARM].m)
break;
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
break;
case SG_SUN_COMFORT:
@@ -13547,7 +14521,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (sd->bl.m == sd->feel_map[skill_id-SG_SUN_COMFORT].m &&
(battle_config.allow_skill_without_day || pc->sg_info[skill_id-SG_SUN_COMFORT].day_func()))
break;
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
case SG_FUSION:
if (sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_STAR)
@@ -13556,7 +14530,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
//Only invoke on skill begin cast (instant cast skill). [Kevin]
if( require.sp > 0 ) {
if (st->sp < (unsigned int)require.sp)
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0);
else
status_zap(&sd->bl, 0, require.sp);
}
@@ -13565,9 +14539,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case GD_REGENERATION:
case GD_RESTORE:
if (!map_flag_gvg2(sd->bl.m)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case GD_EMERGENCYCALL:
// other checks were already done in skillnotok()
if (!sd->status.guild_id || !sd->state.gmaster_flag)
@@ -13576,7 +14551,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case GS_GLITTERING:
if(sd->spiritball >= 10) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13587,12 +14562,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
#else
if (st->hp < 2) {
#endif
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case NJ_BUNSINJYUTSU:
if (!(sc && sc->data[SC_NJ_NEN])) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13600,7 +14576,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case NJ_ZENYNAGE:
case KO_MUCHANAGE:
if(sd->status.zeny < require.zeny) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_MONEY, 0, 0);
return 0;
}
break;
@@ -13610,14 +14586,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
case AM_CALLHOMUN: //Can't summon if a hom is already out
if (sd->status.hom_id && sd->hd && !sd->hd->homunculus.vaporize) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
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);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13626,12 +14602,12 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
**/
case AB_ANCILLA:
{
- int count = 0, i;
- for( i = 0; i < MAX_INVENTORY; i ++ )
- if( sd->status.inventory[i].nameid == ITEMID_ANCILLA )
+ int count = 0;
+ for (int i = 0; i < sd->status.inventorySize; i ++)
+ if (sd->status.inventory[i].nameid == ITEMID_ANSILA)
count += sd->status.inventory[i].amount;
if( count >= 3 ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0, 0);
return 0;
}
}
@@ -13651,8 +14627,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
&& ((idx = pc->search_inventory(sd,require.itemid[0])) == INDEX_NOT_FOUND
|| 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);
+ //clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, require.amount[0], 0, require.itemid[0]);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13672,7 +14648,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
switch(skill_id){
case WL_TETRAVORTEX:
if( i < 4 ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
@@ -13681,13 +14657,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[j] )
i++;
if( i == 0 ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON_NONE, 0, 0);
return 0;
}
break;
default:
if( i == 5 ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0, 0);
return 0;
}
}
@@ -13698,14 +14674,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
**/
case GC_HALLUCINATIONWALK:
if( sc && (sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case GC_COUNTERSLASH:
case GC_WEAPONCRUSH:
if( !(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING) ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0, 0);
return 0;
}
break;
@@ -13714,25 +14690,25 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
**/
case RA_WUGMASTERY:
if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY] ) {
- clif->skill_fail(sd,skill_id,sd->sc.data[SC__GROOMY]?USESKILL_FAIL_MANUAL_NOTIFY:USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, sd->sc.data[SC__GROOMY] ? USESKILL_FAIL_MANUAL_NOTIFY : USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
case RA_WUGSTRIKE:
if( !pc_iswug(sd) && !pc_isridingwug(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
case RA_WUGRIDER:
if( pc_isfalcon(sd) || ( !pc_isridingwug(sd) && !pc_iswug(sd) ) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
case RA_WUGDASH:
if(!pc_isridingwug(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
@@ -13741,13 +14717,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
**/
case LG_BANDING:
if( sc && sc->data[SC_INSPIRATION] ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case LG_PRESTIGE:
if( sc && (sc->data[SC_BANDING] || sc->data[SC_INSPIRATION]) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13756,7 +14732,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[SC_INSPIRATION] )
return 1; // Don't check for partner.
if( !(sc && sc->data[SC_BANDING]) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0, 0);
return 0;
}
if( sc->data[SC_BANDING] &&
@@ -13767,12 +14743,12 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sc && sc->data[SC_COMBOATTACK] ) {
if( sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO )
break;
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, SR_DRAGONCOMBO);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, SR_DRAGONCOMBO, 0);
}
return 0;
case SR_CRESCENTELBOW:
if( sc && sc->data[SC_CRESCENTELBOW] ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_DUPLICATE, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_DUPLICATE, 0, 0);
return 0;
}
break;
@@ -13781,7 +14757,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (map->foreachinrange(mob->count_sub, &sd->bl, skill->get_splash(skill_id, skill_lv), BL_MOB,
MOBID_EMPELIUM, MOBID_S_EMPEL_1, MOBID_S_EMPEL_2)) {
char output[128];
- sprintf(output, "You're too close to a stone or emperium to do this skill"); /* TODO official response? or message.conf it */
+ sprintf(output, "%s", msg_txt(883)); /* TODO official response */ // You are too close to a stone or emperium to do this skill
clif->messagecolor_self(sd->fd, COLOR_RED, output);
return 0;
}
@@ -13789,7 +14765,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sd->spiritball > 0 )
sd->spiritball_old = require.spiritball = sd->spiritball;
else {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13800,7 +14776,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SC_MANHOLE:
case SC_DIMENSIONDOOR:
if( sc && sc->data[SC_MAGNETICFIELD] ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13808,7 +14784,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
int count;
count = skill->check_pc_partner(sd, skill_id, &skill_lv, skill->get_splash(skill_id,skill_lv), 0);
if( count < 1 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_HELPER, 0, 0);
return 0;
} else
require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party.
@@ -13818,7 +14794,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (sd->equip_index[EQI_HAND_R] < 0
|| !itemid_is_pilebunker(sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid)
) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_THIS_WEAPON, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_THIS_WEAPON, 0, 0);
return 0;
}
break;
@@ -13826,7 +14802,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (( sd->equip_index[EQI_ACC_L] >= 0 && sd->status.inventory[sd->equip_index[EQI_ACC_L]].nameid == ITEMID_HOVERING_BOOSTER ) ||
( sd->equip_index[EQI_ACC_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_ACC_R]].nameid == ITEMID_HOVERING_BOOSTER ));
else {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13834,25 +14810,25 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
if( sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case SO_EL_CONTROL:
if( !sd->status.ele_id || !sd->ed ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_EL_SUMMON, 0, 0);
return 0;
}
break;
case RETURN_TO_ELDICASTES:
if( pc_ismadogear(sd) ) { //Cannot be used if Mado is equipped.
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case CR_REFLECTSHIELD:
if( sc && sc->data[SC_KYOMU] && rnd()%100 < 5 * sc->data[SC_KYOMU]->val1 ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13861,14 +14837,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
if (sd->charm_type == skill->get_ele(skill_id, skill_lv) && sd->charm_count >= MAX_SPIRITCHARM) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0, 0);
return 0;
}
break;
case KO_KAIHOU:
case KO_ZENKAI:
if (sd->charm_type == CHARM_TYPE_NONE || sd->charm_count <= 0) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0, 0);
return 0;
}
break;
@@ -13883,66 +14859,67 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
switch(require.state) {
case ST_HIDING:
if(!(sc && sc->option&OPTION_HIDE)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_CLOAKING:
if(!pc_iscloaking(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_HIDDEN:
if(!pc_ishiding(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_RIDING:
if (!pc_isridingpeco(sd) && !pc_isridingdragon(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_FALCON:
if(!pc_isfalcon(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_CARTBOOST:
if(!(sc && sc->data[SC_CARTBOOST])) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case ST_CART:
if(!pc_iscarton(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CART,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CART, 0, 0);
return 0;
}
break;
case ST_SHIELD:
- if(sd->status.shield <= 0) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (!sd->has_shield) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_SIGHT:
if(!(sc && sc->data[SC_SIGHT])) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_EXPLOSIONSPIRITS:
if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_EXPLOSIONSPIRITS,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_EXPLOSIONSPIRITS, 0, 0);
return 0;
}
break;
case ST_RECOV_WEIGHT_RATE:
if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13951,7 +14928,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
sd->ud.canmove_tick = timer->gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex]
if (!unit->can_move(&sd->bl)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -13960,63 +14937,65 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKWATER))
break;
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
case ST_RIDINGDRAGON:
if( !pc_isridingdragon(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_DRAGON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_DRAGON, 0, 0);
return 0;
}
break;
case ST_WUG:
if( !pc_iswug(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_RIDINGWUG:
if( !pc_isridingwug(sd) ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
case ST_MADO:
if( !pc_ismadogear(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_MADOGEAR, 0, 0);
return 0;
}
break;
case ST_ELEMENTALSPIRIT:
if(!sd->ed) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_EL_SUMMON, 0, 0);
return 0;
}
break;
case ST_POISONINGWEAPON:
if (!(sc && sc->data[SC_POISONINGWEAPON])) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_POISONINGWEAPON, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_POISONINGWEAPON, 0, 0);
return 0;
}
break;
case ST_ROLLINGCUTTER:
if (!(sc && sc->data[SC_ROLLINGCUTTER])) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0, 0);
return 0;
}
break;
case ST_MH_FIGHTING:
if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_FIGHTING)){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case ST_MH_GRAPPLING:
if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_GRAPPLING)){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
+ FALLTHROUGH
case ST_PECO:
if (!pc_isridingpeco(sd)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
break;
@@ -14025,27 +15004,27 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if(require.mhp > 0 && get_percentage(st->hp, st->max_hp) > require.mhp) {
//mhp is the max-hp-requirement, that is,
//you must have this % or less of HP to cast it.
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0, 0);
return 0;
}
if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_THIS_WEAPON, 0, 0);
return 0;
}
- if( require.sp > 0 && st->sp < (unsigned int)require.sp) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0);
+ if (require.sp > 0 && st->sp < (unsigned int)require.sp && sd->autocast.type == AUTOCAST_NONE) { // Auto-cast skills don't consume SP.
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0);
return 0;
}
if( require.zeny > 0 && sd->status.zeny < require.zeny ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_MONEY, 0, 0);
return 0;
}
if( require.spiritball > 0 && sd->spiritball < require.spiritball) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SPIRITS,require.spiritball);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SPIRITS, require.spiritball, 0);
return 0;
}
@@ -14060,27 +15039,28 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 1;
}
-int skill_check_condition_castbegin_off_unknown(struct status_change *sc, uint16 *skill_id)
+static int skill_check_condition_castbegin_off_unknown(struct status_change *sc, uint16 *skill_id)
{
- return -1;
+ return -1;
}
-int skill_check_condition_castbegin_mount_unknown(struct status_change *sc, uint16 *skill_id)
+static int skill_check_condition_castbegin_mount_unknown(struct status_change *sc, uint16 *skill_id)
{
- return 0;
+ return 0;
}
-int skill_check_condition_castbegin_madogear_unknown(struct status_change *sc, uint16 *skill_id)
+static int skill_check_condition_castbegin_madogear_unknown(struct status_change *sc, uint16 *skill_id)
{
- return 0;
+ return 0;
}
-int skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 *skill_id)
+static int skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 *skill_id)
{
- return -1;
+ return -1;
}
-int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
+static int skill_check_condition_castend(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
+{
struct skill_condition require;
struct status_data *st;
int i;
@@ -14088,11 +15068,16 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
nullpo_ret(sd);
- if( sd->chatID )
+ if (sd->chat_id != 0)
return 0;
- if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) {
- //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
+ if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
+ && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ return 1;
+ }
+
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ // GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
return 1;
@@ -14118,15 +15103,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
return 0;
break;
}
- /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
-#if 0
- if( sd->state.abra_flag ) // Casting finished (Hocus-Pocus)
- return 1;
-#endif
- if( sd->skillitem == skill_id )
- return 1;
- if( pc_is90overweight(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0);
+
+ if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -14160,7 +15139,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
|| (skill_id==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2)
) {
//Fails when: exceed max limit. There are other plant types already out.
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
}
@@ -14180,7 +15159,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
map->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, MOBID_SILVERSNIPER, skill_id, &c);
}
if( c >= maxcount ) {
- clif->skill_fail(sd , skill_id, USESKILL_FAIL_SUMMON, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0, 0);
return 0;
}
}
@@ -14190,14 +15169,15 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
int c = 0;
i = map->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, MOBID_KO_KAGE, skill_id, &c);
if( c >= skill->get_maxcount(skill_id,skill_lv) || c != i) {
- clif->skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
}
break;
default:
- skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv);
- break;
+ if (!skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv))
+ break;
+ return 0;
}
st = &sd->battle_status;
@@ -14205,35 +15185,33 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
require = skill->get_requirement(sd,skill_id,skill_lv);
if( require.hp > 0 && st->hp <= (unsigned int)require.hp) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0, 0);
return 0;
}
if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_THIS_WEAPON, 0, 0);
return 0;
}
if( require.ammo ) { //Skill requires stuff equipped in the arrow slot.
if((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i] ) {
if( require.ammo&1<<8 )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_CANONBALL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_CANONBALL, 0, 0);
else
clif->arrow_fail(sd,0);
return 0;
} else if( sd->status.inventory[i].amount < require.ammo_qty ) {
char e_msg[100];
- sprintf(e_msg,"Skill Failed. [%s] requires %dx %s.",
+ sprintf(e_msg, msg_txt(884), // Skill Failed. [%s] requires %dx %s.
skill->get_desc(skill_id),
require.ammo_qty,
itemdb_jname(sd->status.inventory[i].nameid));
clif->messagecolor_self(sd->fd, COLOR_RED, e_msg);
return 0;
}
- if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message
- //which is the closest we have to wrong ammo type. [Skotlex]
- clif->arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex]
- //clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0);
+ if ((require.ammo & (1 << sd->inventory_data[i]->subtype)) == 0 || !battle->check_arrows(sd)) { // Ammo type check.
+ clif->arrow_fail(sd, 0); // "Please equip the proper ammunition first."
return 0;
}
}
@@ -14257,7 +15235,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
cause = USESKILL_FAIL_BLUEJAMSTONE; break;
case ITEMID_HOLY_WATER:
cause = USESKILL_FAIL_HOLYWATER; break;
- case ITEMID_ANCILLA:
+ case ITEMID_ANSILA:
cause = USESKILL_FAIL_ANCILLA; break;
case ITEMID_ACCELERATOR:
case ITEMID_HOVERING_BOOSTER:
@@ -14272,11 +15250,11 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
cause = USESKILL_FAIL_NEED_EQUIPMENT;
/* Fall through */
default:
- clif->skill_fail(sd, skill_id, cause, max(1,require.amount[i])|(require.itemid[i] << 16));
+ clif->skill_fail(sd, skill_id, cause, max(1, require.amount[i]), require.itemid[i]);
return 0;
}
}
- clif->skill_fail(sd, skill_id, cause, 0);
+ clif->skill_fail(sd, skill_id, cause, 0, 0);
return 0;
}
}
@@ -14284,16 +15262,24 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
return 1;
}
-void skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) {
+static bool skill_check_condition_castend_unknown(struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv)
+{
+ return false;
}
// type&2: consume items (after skill was used)
// type&1: consume the others (before skill was used)
-int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type) {
+static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type)
+{
struct skill_condition req;
nullpo_ret(sd);
+ if ((!sd->autocast.itemskill_check_conditions && sd->autocast.type == AUTOCAST_ITEM)
+ || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ return 1;
+ }
+
req = skill->get_requirement(sd,skill_id,skill_lv);
if (type&1) {
@@ -14302,9 +15288,15 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin
case MC_IDENTIFY:
req.sp = 0;
break;
+ case WZ_EARTHSPIKE:
+ if (sd->sc.count > 0 && sd->sc.data[SC_EARTHSCROLL] != NULL) // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, 10 SP are consumed. [Kenpachi]
+ req.sp = 10;
+
+ break;
default:
- if( sd->state.autocast )
+ if (sd->autocast.type != AUTOCAST_NONE) // Auto-cast skills don't consume SP.
req.sp = 0;
+
break;
}
@@ -14370,7 +15362,8 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin
return 1;
}
-struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
+static struct skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
+{
struct skill_condition req;
struct status_data *st;
struct status_change *sc;
@@ -14381,12 +15374,6 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if( !sd )
return req;
-#if 0 /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
- if( sd->state.abra_flag )
-#else // not 0
- if( sd->skillitem == skill_id )
-#endif // 0
- return req; // Hocus-Pocus don't have requirements.
sc = &sd->sc;
if( !sc->count )
@@ -14412,7 +15399,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
case TK_READYTURN:
case SG_FUSION:
case KO_YAMIKUMO:
- if( sc && sc->data[status->skill2sc(skill_id)] )
+ case SU_HIDE:
+ if (sc && sc->data[status->skill2sc(skill_id)])
return req;
/* Fall through */
default:
@@ -14495,7 +15483,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
}
for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
- if( (skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != skill_lv%11 - 1 )
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ if ((skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != item_idx)
continue;
switch( skill_id ) {
@@ -14568,7 +15557,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if ((item_index = pc->search_inventory(sd, req.itemid[i])) == INDEX_NOT_FOUND
|| sd->status.inventory[item_index].amount < req.amount[i]
) {
- req.itemid[i] = ITEMID_TRAP_ALLOY;
+ req.itemid[i] = ITEMID_SPECIAL_ALLOY_TRAP;
req.amount[i] = 1;
}
break;
@@ -14595,14 +15584,14 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
switch(skill_lv) {
case 1:
case 2:
- req.itemid[1] = ITEMID_REPAIR_A;
+ req.itemid[1] = ITEMID_REPAIRA;
break;
case 3:
case 4:
- req.itemid[1] = ITEMID_REPAIR_B;
+ req.itemid[1] = ITEMID_REPAIRB;
break;
case 5:
- req.itemid[1] = ITEMID_REPAIR_C;
+ req.itemid[1] = ITEMID_REPAIRC;
break;
}
req.amount[1] = 1;
@@ -14698,24 +15687,25 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
return req;
}
-bool skill_get_requirement_off_unknown(struct status_change *sc, uint16 *skill_id)
+static bool skill_get_requirement_off_unknown(struct status_change *sc, uint16 *skill_id)
{
- return false;
+ return false;
}
-bool skill_get_requirement_item_unknown(struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i)
+static bool skill_get_requirement_item_unknown(struct status_change *sc, struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i)
{
- return false;
+ return false;
}
-void skill_get_requirement_unknown(struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req)
+static void skill_get_requirement_unknown(struct status_change *sc, struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req)
{
}
/*==========================================
* Does cast-time reductions based on dex, item bonuses and config setting
*------------------------------------------*/
-int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
+static int skill_castfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
+{
int time = skill->get_cast(skill_id, skill_lv);
nullpo_ret(bl);
@@ -14765,11 +15755,13 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
/*==========================================
* Does cast-time reductions based on sc data.
*------------------------------------------*/
-int skill_castfix_sc (struct block_list *bl, int time) {
+static int skill_castfix_sc(struct block_list *bl, int time)
+{
struct status_change *sc = status->get_sc(bl);
if( time < 0 )
return 0;
+ nullpo_ret(bl);
if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter.
return time;
@@ -14790,6 +15782,8 @@ int skill_castfix_sc (struct block_list *bl, int time) {
}
if (sc->data[SC_POEMBRAGI])
time -= time * sc->data[SC_POEMBRAGI]->val2 / 100;
+ if (sc->data[SC_SKF_CAST] != NULL)
+ time -= time * sc->data[SC_SKF_CAST]->val1 / 100;
if (sc->data[SC_IZAYOI])
time -= time * 50 / 100;
}
@@ -14798,7 +15792,9 @@ int skill_castfix_sc (struct block_list *bl, int time) {
//ShowInfo("Castime castfix_sc = %d\n",time);
return time;
}
-int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv) {
+
+static int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv)
+{
#ifdef RENEWAL_CAST
struct status_change *sc = status->get_sc(bl);
struct map_session_data *sd = BL_CAST(BL_PC,bl);
@@ -14806,6 +15802,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
if( time < 0 )
return 0;
+ nullpo_ret(bl);
if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter.
return (int)time;
@@ -14877,6 +15874,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
case WZ_FIREPILLAR:
if(skill_lv < 5)
break;
+ FALLTHROUGH
case HW_GRAVITATION:
case MG_SAFETYWALL:
case MG_STONECURSE:
@@ -14887,6 +15885,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
}
if (sc->data[SC_MYSTICSCROLL])
VARCAST_REDUCTION(sc->data[SC_MYSTICSCROLL]->val1);
+ if (sc->data[SC_SKF_CAST] != NULL)
+ VARCAST_REDUCTION(sc->data[SC_SKF_CAST]->val1);
// Fixed cast reduction bonuses
if( sc->data[SC__LAZINESS] )
@@ -14938,7 +15938,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
/*==========================================
* Does delay reductions based on dex/agi, sc data, item bonuses, ...
*------------------------------------------*/
-int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
+static int skill_delay_fix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
+{
int delaynodex = skill->get_delaynodex(skill_id, skill_lv);
int time = skill->get_delay(skill_id, skill_lv);
struct map_session_data *sd;
@@ -15037,10 +16038,11 @@ struct square {
int val2[5];
};
-void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) {
+static void skill_brandishspear_first(struct square *tc, enum unit_dir dir, int16 x, int16 y)
+{
nullpo_retv(tc);
- if(dir == 0){
+ if (dir == UNIT_DIR_NORTH) {
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
@@ -15051,7 +16053,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y-1;
- } else if(dir==2){
+ } else if (dir == UNIT_DIR_WEST) {
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
@@ -15062,7 +16064,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
- } else if(dir==4){
+ } else if (dir == UNIT_DIR_SOUTH) {
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
@@ -15073,7 +16075,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y+1;
- } else if(dir==6){
+ } else if (dir == UNIT_DIR_EAST) {
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
@@ -15084,7 +16086,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
- } else if(dir==1){
+ } else if (dir == UNIT_DIR_NORTHWEST) {
tc->val1[0]=x-1;
tc->val1[1]=x;
tc->val1[2]=x+1;
@@ -15095,7 +16097,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=y-1;
tc->val2[3]=y;
tc->val2[4]=y+1;
- } else if(dir==3){
+ } else if (dir == UNIT_DIR_SOUTHWEST) {
tc->val1[0]=x+3;
tc->val1[1]=x+2;
tc->val1[2]=x+1;
@@ -15106,7 +16108,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=y+1;
tc->val2[3]=y+2;
tc->val2[4]=y+3;
- } else if(dir==5){
+ } else if (dir == UNIT_DIR_SOUTHEAST) {
tc->val1[0]=x+1;
tc->val1[1]=x;
tc->val1[2]=x-1;
@@ -15117,7 +16119,7 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
tc->val2[2]=y+1;
tc->val2[3]=y;
tc->val2[4]=y-1;
- } else if(dir==7){
+ } else if (dir == UNIT_DIR_NORTHEAST) {
tc->val1[0]=x-3;
tc->val1[1]=x-2;
tc->val1[2]=x-1;
@@ -15132,29 +16134,27 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y)
}
-void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) {
- int c;
+static void skill_brandishspear_dir(struct square *tc, enum unit_dir dir, int are)
+{
nullpo_retv(tc);
+ Assert_retv(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
- for( c = 0; c < 5; c++ ) {
- switch( dir ) {
- case 0: tc->val2[c]+=are; break;
- case 1: tc->val1[c]-=are; tc->val2[c]+=are; break;
- case 2: tc->val1[c]-=are; break;
- case 3: tc->val1[c]-=are; tc->val2[c]-=are; break;
- case 4: tc->val2[c]-=are; break;
- case 5: tc->val1[c]+=are; tc->val2[c]-=are; break;
- case 6: tc->val1[c]+=are; break;
- case 7: tc->val1[c]+=are; tc->val2[c]+=are; break;
- }
+ for (int c = 0; c < 5; c++) {
+ tc->val1[c] += dirx[dir] * are;
+ tc->val2[c] += diry[dir] * are;
}
}
-void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
+static void skill_brandishspear(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag)
+{
int c,n=4;
- uint8 dir = map->calc_dir(src,bl->x,bl->y);
struct square tc;
- int x=bl->x,y=bl->y;
+ int x, y;
+
+ nullpo_retv(bl);
+ x = bl->x;
+ y = bl->y;
+ enum unit_dir dir = map->calc_dir(src, x, y);
skill->brandishspear_first(&tc,dir,x,y);
skill->brandishspear_dir(&tc,dir,4);
skill->area_temp[1] = bl->id;
@@ -15199,7 +16199,8 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s
/*==========================================
* Weapon Repair [Celest/DracoRPG]
*------------------------------------------*/
-void skill_repairweapon (struct map_session_data *sd, int idx) {
+static void skill_repairweapon(struct map_session_data *sd, int idx)
+{
int material;
int materials[4] = {
ITEMID_IRON_ORE,
@@ -15215,15 +16216,18 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
if ( !( target_sd = map->id2sd(sd->menuskill_val) ) ) //Failed....
return;
- if( idx == 0xFFFF ) // No item selected ('Cancel' clicked)
+ if (idx == 0xFFFF || idx == -1) // No item selected ('Cancel' clicked)
return;
- if( idx < 0 || idx >= MAX_INVENTORY )
+ if (idx < 0 || idx >= sd->status.inventorySize)
return; //Invalid index??
item = &target_sd->status.inventory[idx];
- if( item->nameid <= 0 || item->attribute == 0 )
+ if( item->nameid <= 0 || (item->attribute & ATTR_BROKEN) == 0 )
return; //Again invalid item....
+ if (item->card[0] == CARD0_PET)
+ return;
+
if( sd != target_sd && !battle->check_range(&sd->bl,&target_sd->bl, skill->get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2) ) ){
clif->item_repaireffect(sd,idx,1);
return;
@@ -15234,15 +16238,16 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
else
material = materials[2]; // Armors consume 1 Steel
if (pc->search_inventory(sd,material) == INDEX_NOT_FOUND) {
- clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
clif->skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1);
- item->attribute = 0;/* clear broken state */
+ item->attribute |= ATTR_BROKEN;
+ item->attribute ^= ATTR_BROKEN; /* clear broken state */
- clif->equiplist(target_sd);
+ clif->equipList(target_sd);
pc->delitem(sd, pc->search_inventory(sd, material), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); // FIXME: is this the correct reason flag?
@@ -15255,13 +16260,13 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
/*==========================================
* Item Appraisal
*------------------------------------------*/
-void skill_identify (struct map_session_data *sd, int idx)
+static void skill_identify(struct map_session_data *sd, int idx)
{
int flag=1;
nullpo_retv(sd);
sd->state.workinprogress = 0;
- if(idx >= 0 && idx < MAX_INVENTORY) {
+ if (idx >= 0 && idx < sd->status.inventorySize) {
if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0 ){
flag=0;
sd->status.inventory[idx].identify=1;
@@ -15273,11 +16278,11 @@ void skill_identify (struct map_session_data *sd, int idx)
/*==========================================
* Weapon Refine [Celest]
*------------------------------------------*/
-void skill_weaponrefine (struct map_session_data *sd, int idx)
+static void skill_weaponrefine(struct map_session_data *sd, int idx)
{
nullpo_retv(sd);
- if (idx >= 0 && idx < MAX_INVENTORY) {
+ if (idx >= 0 && idx < sd->status.inventorySize) {
struct item *item;
struct item_data *ditem = sd->inventory_data[idx];
item = &sd->status.inventory[idx];
@@ -15293,7 +16298,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
int i = 0, per;
if( ditem->flag.no_refine ) {
// if the item isn't refinable
- clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, sd->menuskill_id, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
if( item->refine >= sd->menuskill_val || item->refine >= 10 ){
@@ -15305,13 +16310,13 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
return;
}
- per = status->get_refine_chance(ditem->wlv, (int)item->refine) * 10;
+ per = refine->get_refine_chance(ditem->wlv, (int)item->refine, REFINE_CHANCE_TYPE_NORMAL) * 10;
// Aegis leaked formula. [malufett]
- if( sd->status.class_ == JOB_MECHANIC_T )
+ if (sd->status.class == JOB_MECHANIC_T)
per += 100;
else
- per += 5 * ((signed int)sd->status.job_level - 50);
+ per += 5 * (sd->status.job_level - 50);
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_REFINE); // FIXME: is this the correct reason flag?
if (per > rnd() % 1000) {
@@ -15325,7 +16330,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
}
clif->delitem(sd, idx, 1, DELITEM_NORMAL);
clif->upgrademessage(sd->fd, 0,item->nameid);
- clif->inventorylist(sd);
+ clif->inventoryList(sd);
clif->refine(sd->fd,0,idx,item->refine);
if (ep)
pc->equipitem(sd,idx,ep);
@@ -15334,16 +16339,16 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
item->card[0] == CARD0_FORGE &&
(int)MakeDWord(item->card[2],item->card[3]) == sd->status.char_id)
{ // Fame point system [DracoRPG]
- switch(ditem->wlv){
- case 1:
- pc->addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
- break;
- case 2:
- pc->addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point
- break;
- case 3:
- pc->addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point
- break;
+ switch (ditem->wlv) {
+ case 1:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
+ break;
+ case 2:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point
+ break;
+ case 3:
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point
+ break;
}
}
} else {
@@ -15362,7 +16367,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
/*==========================================
*
*------------------------------------------*/
-int skill_autospell (struct map_session_data *sd, uint16 skill_id)
+static int skill_autospell(struct map_session_data *sd, uint16 skill_id)
{
uint16 skill_lv;
int maxlv=1,lv;
@@ -15405,7 +16410,7 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id)
/*==========================================
* Sitting skills functions.
*------------------------------------------*/
-int skill_sit_count(struct block_list *bl, va_list ap)
+static int skill_sit_count(struct block_list *bl, va_list ap)
{
int type = va_arg(ap, int);
struct map_session_data *sd = NULL;
@@ -15426,7 +16431,7 @@ int skill_sit_count(struct block_list *bl, va_list ap)
return 0;
}
-int skill_sit_in(struct block_list *bl, va_list ap)
+static int skill_sit_in(struct block_list *bl, va_list ap)
{
int type = va_arg(ap, int);
struct map_session_data *sd = NULL;
@@ -15450,7 +16455,7 @@ int skill_sit_in(struct block_list *bl, va_list ap)
return 0;
}
-int skill_sit_out(struct block_list *bl, va_list ap)
+static int skill_sit_out(struct block_list *bl, va_list ap)
{
int type = va_arg(ap, int);
struct map_session_data *sd = NULL;
@@ -15469,7 +16474,7 @@ int skill_sit_out(struct block_list *bl, va_list ap)
return 0;
}
-int skill_sit (struct map_session_data *sd, int type)
+static int skill_sit(struct map_session_data *sd, int type)
{
int flag = 0;
int range = 0, lv;
@@ -15489,9 +16494,9 @@ int skill_sit (struct map_session_data *sd, int type)
}
if( type ) {
- clif->sc_load(&sd->bl,sd->bl.id,SELF,SI_SIT,0,0,0);
+ clif->sc_load(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT), 0, 0, 0);
} else {
- clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT);
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT));
}
if (!flag) return 0;
@@ -15509,7 +16514,7 @@ int skill_sit (struct map_session_data *sd, int type)
/*==========================================
*
*------------------------------------------*/
-int skill_frostjoke_scream(struct block_list *bl, va_list ap)
+static int skill_frostjoke_scream(struct block_list *bl, va_list ap)
{
struct block_list *src;
uint16 skill_id,skill_lv;
@@ -15542,10 +16547,12 @@ int skill_frostjoke_scream(struct block_list *bl, va_list ap)
/*==========================================
*
*------------------------------------------*/
-void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag) {
+static void skill_unitsetmapcell(struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag)
+{
int range = skill->get_unit_range(skill_id,skill_lv);
int x,y;
+ nullpo_retv(src);
for( y = src->bl.y - range; y <= src->bl.y + range; ++y )
for( x = src->bl.x - range; x <= src->bl.x + range; ++x )
map->list[src->bl.m].setcell(src->bl.m, x, y, cell, flag);
@@ -15554,11 +16561,14 @@ void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill
/*==========================================
*
*------------------------------------------*/
-int skill_attack_area(struct block_list *bl, va_list ap) {
+static int skill_attack_area(struct block_list *bl, va_list ap)
+{
struct block_list *src,*dsrc;
int atk_type,skill_id,skill_lv,flag,type;
int64 tick;
+ nullpo_ret(bl);
+
if(status->isdead(bl))
return 0;
@@ -15594,7 +16604,7 @@ int skill_attack_area(struct block_list *bl, va_list ap) {
/*==========================================
*
*------------------------------------------*/
-int skill_clear_group (struct block_list *bl, int flag)
+static int skill_clear_group(struct block_list *bl, int flag)
{
struct unit_data *ud = unit->bl2ud(bl);
struct skill_unit_group *group[MAX_SKILLUNITGROUP];
@@ -15638,7 +16648,8 @@ int skill_clear_group (struct block_list *bl, int flag)
/*==========================================
* Returns the first element field found [Skotlex]
*------------------------------------------*/
-struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
+static struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
+{
struct unit_data *ud = unit->bl2ud(bl);
int i;
nullpo_ret(bl);
@@ -15660,7 +16671,7 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
}
// for graffiti cleaner [Valaris]
-int skill_graffitiremover(struct block_list *bl, va_list ap)
+static int skill_graffitiremover(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
@@ -15676,7 +16687,7 @@ int skill_graffitiremover(struct block_list *bl, va_list ap)
return 0;
}
-int skill_greed(struct block_list *bl, va_list ap)
+static int skill_greed(struct block_list *bl, va_list ap)
{
struct block_list *src = va_arg(ap, struct block_list *);
@@ -15693,7 +16704,7 @@ int skill_greed(struct block_list *bl, va_list ap)
}
//For Ranger's Detonator [Jobbie/3CeAM]
-int skill_detonator(struct block_list *bl, va_list ap)
+static int skill_detonator(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
struct block_list *src = va_arg(ap,struct block_list *);
@@ -15727,10 +16738,10 @@ int skill_detonator(struct block_list *bl, va_list ap)
case UNT_CLAYMORETRAP:
case UNT_FIRINGTRAP:
case UNT_ICEBOUNDTRAP:
- map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag|BL_SKILL|~BCT_SELF,bl,su->group->tick);
+ skill->trap_do_splash(bl, su->group->skill_id, su->group->skill_lv, su->group->bl_flag | BL_SKILL | ~BCT_SELF, su->group->tick);
break;
default:
- map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag,bl,su->group->tick);
+ skill->trap_do_splash(bl, su->group->skill_id, su->group->skill_lv, su->group->bl_flag, su->group->tick);
}
clif->changetraplook(bl, UNT_USED_TRAPS);
su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) +
@@ -15744,7 +16755,7 @@ int skill_detonator(struct block_list *bl, va_list ap)
/*==========================================
*
*------------------------------------------*/
-int skill_cell_overlap(struct block_list *bl, va_list ap)
+static int skill_cell_overlap(struct block_list *bl, va_list ap)
{
uint16 skill_id;
int *alive;
@@ -15842,7 +16853,7 @@ int skill_cell_overlap(struct block_list *bl, va_list ap)
/*==========================================
*
*------------------------------------------*/
-int skill_chastle_mob_changetarget(struct block_list *bl, va_list ap)
+static int skill_chastle_mob_changetarget(struct block_list *bl, va_list ap)
{
struct unit_data *ud = unit->bl2ud(bl);
struct block_list *from_bl = va_arg(ap, struct block_list *);
@@ -15863,16 +16874,38 @@ int skill_chastle_mob_changetarget(struct block_list *bl, va_list ap)
return 0;
}
+/**
+ * Does final adjustments (e.g. count enemies affected by splash) then runs trap splash function (skill_trap_splash).
+ *
+ * @param bl : trap skill unit's bl
+ * @param skill_id : Trap Skill ID
+ * @param skill_lv : Trap Skill Level
+ * @param bl_flag : Flag representing units affected by this trap
+ * @param tick : tick related to this trap
+ */
+static void skill_trap_do_splash(struct block_list *bl, uint16 skill_id, uint16 skill_lv, int bl_flag, int64 tick)
+{
+ int enemy_count = 0;
+
+ if (skill->get_nk(skill_id) & NK_SPLASHSPLIT) {
+ enemy_count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, bl, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
+ enemy_count = max(1, enemy_count); // Don't let enemy_count be 0 when spliting trap damage
+ }
+
+ map->foreachinrange(skill->trap_splash, bl, skill->get_splash(skill_id, skill_lv), bl_flag, bl, tick, enemy_count);
+}
+
/*==========================================
*
*------------------------------------------*/
-int skill_trap_splash(struct block_list *bl, va_list ap)
+static int skill_trap_splash(struct block_list *bl, va_list ap)
{
struct block_list *src = va_arg(ap, struct block_list *);
int64 tick = va_arg(ap, int64);
struct skill_unit *src_su = NULL;
struct skill_unit_group *sg;
struct block_list *ss;
+ int enemy_count = va_arg(ap, int);
nullpo_ret(bl);
nullpo_ret(src);
@@ -15967,7 +17000,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap)
}
/* Fall through */
default:
- skill->attack(skill->get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0);
+ skill->attack(skill->get_type(sg->skill_id), ss, src, bl, sg->skill_id, sg->skill_lv, tick, enemy_count);
break;
}
return 1;
@@ -15976,7 +17009,8 @@ int skill_trap_splash(struct block_list *bl, va_list ap)
/*==========================================
*
*------------------------------------------*/
-int skill_enchant_elemental_end (struct block_list *bl, int type) {
+static int skill_enchant_elemental_end(struct block_list *bl, int type)
+{
struct status_change *sc;
const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS };
int i;
@@ -15992,16 +17026,17 @@ int skill_enchant_elemental_end (struct block_list *bl, int type) {
return 0;
}
-bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce)
+static bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce)
{
- static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
- static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
bool wall = true;
+ nullpo_retr(false, bl);
if( (bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
|| (bl->type != BL_PC && battle_config.monster_cloak_check_type&1)
) {
//Check for walls.
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
int i;
ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
@@ -16030,7 +17065,8 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
/**
* Verifies if an user can use SC_CLOAKING
**/
-bool skill_can_cloak(struct map_session_data *sd) {
+static bool skill_can_cloak(struct map_session_data *sd)
+{
nullpo_retr(false, sd);
//Avoid cloaking with no wall and low skill level. [Skotlex]
@@ -16047,7 +17083,7 @@ bool skill_can_cloak(struct map_session_data *sd) {
* 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)
+static int skill_check_cloaking_end(struct block_list *bl, va_list ap)
{
struct map_session_data *sd = BL_CAST(BL_PC, bl);
@@ -16057,13 +17093,14 @@ int skill_check_cloaking_end(struct block_list *bl, va_list ap)
return 0;
}
-bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)
+static bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)
{
- static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
- static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
bool wall = true;
+ nullpo_retr(false, bl);
if( bl->type == BL_PC ) { //Check for walls.
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
int i;
ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
@@ -16084,7 +17121,7 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
return wall;
}
-bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit)
+static bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit)
{
struct status_change *sc;
@@ -16123,7 +17160,8 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit)
/*==========================================
*
*------------------------------------------*/
-struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) {
+static struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, int x, int y, int val1, int val2)
+{
struct skill_unit *su;
nullpo_retr(NULL, group);
@@ -16143,6 +17181,14 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
su->val1=val1;
su->val2 = val2;
su->prev = 0;
+ su->visible = true;
+
+ if (skill->get_inf2(group->skill_id) & INF2_HIDDEN_TRAP
+ && ((battle_config.trap_visibility == 1 && map_flag_vs(group->map)) // invisible in PvP/GvG
+ || battle_config.trap_visibility == 2 // always invisible
+ )) {
+ su->visible = false;
+ }
idb_put(skill->unit_db, su->bl.id, su);
map->addiddb(&su->bl);
@@ -16175,7 +17221,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
/*==========================================
*
*------------------------------------------*/
-int skill_delunit (struct skill_unit* su) {
+static int skill_delunit(struct skill_unit *su)
+{
struct skill_unit_group *group;
nullpo_ret(su);
@@ -16250,24 +17297,25 @@ int skill_delunit (struct skill_unit* su) {
*
*------------------------------------------*/
/// Returns the target skill_unit_group or NULL if not found.
-struct skill_unit_group* skill_id2group(int group_id)
+static struct skill_unit_group *skill_id2group(int group_id)
{
return (struct skill_unit_group*)idb_get(skill->group_db, group_id);
}
/// Returns a new group_id that isn't being used in skill->group_db.
/// Fatal error if nothing is available.
-int skill_get_new_group_id(void)
+static int skill_get_new_group_id(void)
{
- if( skill->unit_group_newid >= MAX_SKILL_DB && skill->id2group(skill->unit_group_newid) == NULL )
+ if (skill->unit_group_newid > MAX_SKILL_ID && skill->id2group(skill->unit_group_newid) == NULL)
return skill->unit_group_newid++;// available
- {// find next id
+
+ {
+ // find next id
int base_id = skill->unit_group_newid;
- while( base_id != ++skill->unit_group_newid )
- {
- if( skill->unit_group_newid < MAX_SKILL_DB )
- skill->unit_group_newid = MAX_SKILL_DB;
- if( skill->id2group(skill->unit_group_newid) == NULL )
+ while (base_id != ++skill->unit_group_newid) {
+ if (skill->unit_group_newid <= MAX_SKILL_ID)
+ skill->unit_group_newid = MAX_SKILL_ID + 1;
+ if (skill->id2group(skill->unit_group_newid) == NULL)
return skill->unit_group_newid++;// available
}
// full loop, nothing available
@@ -16276,7 +17324,7 @@ int skill_get_new_group_id(void)
}
}
-struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
+static struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
{
struct unit_data* ud = unit->bl2ud( src );
struct skill_unit_group* group;
@@ -16310,6 +17358,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
group->party_id = status->get_party_id(src);
group->guild_id = status->get_guild_id(src);
group->bg_id = bg->team_get_id(src);
+ group->clan_id = clan->get_id(src);
group->group_id = skill->get_new_group_id();
CREATE(group->unit.data, struct skill_unit, count);
group->unit.count = count;
@@ -16338,7 +17387,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
/*==========================================
*
*------------------------------------------*/
-int skill_delunitgroup(struct skill_unit_group *group, const char *file, int line, const char *func)
+static int skill_delunitgroup(struct skill_unit_group *group, const char *file, int line, const char *func)
{
struct block_list* src;
struct unit_data *ud;
@@ -16474,7 +17523,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char *file, int lin
/*==========================================
*
*------------------------------------------*/
-int skill_clear_unitgroup (struct block_list *src)
+static int skill_clear_unitgroup(struct block_list *src)
{
struct unit_data *ud = unit->bl2ud(src);
@@ -16489,13 +17538,14 @@ int skill_clear_unitgroup (struct block_list *src)
/*==========================================
*
*------------------------------------------*/
-struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int64 tick)
+static struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int64 tick)
{
int i,j=-1,s,id;
struct unit_data *ud;
struct skill_unit_group_tickset *set;
nullpo_ret(bl);
+ nullpo_ret(group);
if (group->interval==-1)
return NULL;
@@ -16530,10 +17580,16 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list
/*==========================================
*
*------------------------------------------*/
-int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
- struct skill_unit* su = va_arg(ap,struct skill_unit *);
- struct skill_unit_group* group = su->group;
- int64 tick = va_arg(ap,int64);
+static int skill_unit_timer_sub_onplace(struct block_list *bl, va_list ap)
+{
+ struct skill_unit* su;
+ struct skill_unit_group* group;
+ int64 tick;
+
+ su = va_arg(ap,struct skill_unit *);
+ nullpo_ret(su);
+ group = su->group;
+ tick = va_arg(ap,int64);
if( !su->alive || bl->prev == NULL )
return 0;
@@ -16554,13 +17610,18 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
/**
* @see DBApply
*/
-int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+static int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
{
- struct skill_unit* su = DB->data2ptr(data);
- struct skill_unit_group* group = su->group;
+ struct skill_unit* su;
+ struct skill_unit_group* group;
int64 tick = va_arg(ap,int64);
bool dissonance;
- struct block_list* bl = &su->bl;
+ struct block_list* bl;
+
+ su = DB->data2ptr(data);
+ nullpo_ret(su);
+ group = su->group;
+ bl = &su->bl;
if( !su->alive )
return 0;
@@ -16593,6 +17654,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
skill->delunit(su);
break;
}
+ FALLTHROUGH
case UNT_SKIDTRAP:
case UNT_LANDMINE:
case UNT_SHOCKWAVE:
@@ -16617,9 +17679,9 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
// revert unit back into a trap
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP;
+ item_tmp.nameid = group->item_id ? group->item_id : ITEMID_BOOBY_TRAP;
item_tmp.identify = 1;
- map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0);
+ map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0, false);
}
skill->delunit(su);
}
@@ -16661,7 +17723,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
break;
}
clif->changetraplook(bl,UNT_USED_TRAPS);
- map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
+ skill->trap_do_splash(bl, group->skill_id, group->skill_lv, group->bl_flag, tick);
group->limit = DIFF_TICK32(tick,group->tick)+1500;
su->limit = DIFF_TICK32(tick,group->tick)+1500;
group->unit_id = UNT_USED_TRAPS;
@@ -16670,7 +17732,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
case UNT_FEINTBOMB: {
struct block_list *src = map->id2bl(group->src_id);
if( src ) {
- map->foreachinrange(skill->area_sub, &su->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, &su->bl, su->range, skill->splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
status_change_end(src, SC__FEINTBOMB_MASTER, INVALID_TIMER);
}
skill->delunit(su);
@@ -16768,7 +17830,8 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
/*==========================================
* Executes on all skill units every SKILLUNITTIMER_INTERVAL milliseconds.
*------------------------------------------*/
-int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) {
+static int skill_unit_timer(int tid, int64 tick, int id, intptr_t data)
+{
map->freeblock_lock();
skill->unit_db->foreach(skill->unit_db, skill->unit_timer_sub, tick);
@@ -16781,7 +17844,7 @@ int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
*
*------------------------------------------*/
-int skill_unit_move_sub(struct block_list* bl, va_list ap)
+static int skill_unit_move_sub(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
struct skill_unit_group *group = NULL;
@@ -16794,6 +17857,7 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap)
uint16 skill_id;
int i;
+ nullpo_ret(target);
nullpo_ret(bl);
Assert_ret(bl->type == BL_SKILL);
su = BL_UCAST(BL_SKILL, bl);
@@ -16880,7 +17944,8 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap)
* units to figure out when they have left a group.
* flag&4: Force a onleft event (triggered when the bl is killed, for example)
*------------------------------------------*/
-int skill_unit_move(struct block_list *bl, int64 tick, int flag) {
+static int skill_unit_move(struct block_list *bl, int64 tick, int flag)
+{
nullpo_ret(bl);
if( bl->prev == NULL )
@@ -16905,7 +17970,8 @@ int skill_unit_move(struct block_list *bl, int64 tick, int flag) {
/*==========================================
*
*------------------------------------------*/
-int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) {
+static int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy)
+{
int i,j;
int64 tick = timer->gettick();
int *m_flag;
@@ -16994,7 +18060,7 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx
/*==========================================
*
*------------------------------------------*/
-int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, int qty)
+static int skill_can_produce_mix(struct map_session_data *sd, int nameid, int trigger, int qty)
{
int i,j;
@@ -17043,8 +18109,8 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger,
if (pc->search_inventory(sd,id) == INDEX_NOT_FOUND)
return 0;
} else {
- int x, y;
- for(y=0,x=0;y<MAX_INVENTORY;y++)
+ int x = 0;
+ for (int y = 0; y < sd->status.inventorySize; y++)
if( sd->status.inventory[y].nameid == id )
x+=sd->status.inventory[y].amount;
if(x<qty*skill->dbs->produce_db[i].mat_amount[j])
@@ -17057,7 +18123,8 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger,
/*==========================================
*
*------------------------------------------*/
-int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty) {
+static int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty)
+{
int slot[3];
int i,sc,ele,idx,equip,wlv,make_per = 0,flag = 0,skill_lv = 0;
int num = -1; // exclude the recipe
@@ -17114,10 +18181,12 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
else temp_qty = 1;
if (data->stack.inventory) {
- for( i = 0; i < MAX_INVENTORY; i++ ) {
+ for (i = 0; i < sd->status.inventorySize; i++ ) {
if( sd->status.inventory[i].nameid == nameid ) {
if( sd->status.inventory[i].amount >= data->stack.amount ) {
- clif->msgtable(sd, MSG_RUNE_STONE_MAX_AMOUNT);
+#if PACKETVER >= 20090729
+ clif->msgtable(sd, MSG_RUNESTONE_MAKEERROR_OVERCOUNT);
+#endif
return 0;
} else {
/**
@@ -17252,12 +18321,15 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
case ITEMID_HAGALAZ:
case ITEMID_OTHILA:
D -= 500; //Rank C
+ FALLTHROUGH
case ITEMID_ISA:
case ITEMID_WYRD:
D -= 500; //Rank B
+ FALLTHROUGH
case ITEMID_NAUTHIZ:
case ITEMID_URUZ:
D -= 500; //Rank A
+ FALLTHROUGH
case ITEMID_BERKANA:
case ITEMID_LUX_ANIMA:
D -= 500; //Rank S
@@ -17339,7 +18411,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
int difficulty = 30 + rnd()%120; // Random number between (30 ~ 150)
make_per = sd->status.job_level / 4 + st->luk / 2 + st->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3)
- qty = ~(5 + rnd()%5) + 1;
+ qty = ~(5 + rnd()%5) + 1; // FIXME[Haru]: This smells, if anyone knows the intent, please rewrite the expression in a more clear form.
switch(nameid){// difficulty factor
case ITEMID_APPLE_BOMB:
@@ -17375,7 +18447,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
qty = 5;
if( qty < 0 || (skill_lv == 1 && make_per < difficulty)){
- qty = ~qty + 1;
+ qty = ~qty + 1; // FIXME[Haru]: This smells. If anyone knows the intent, please rewrite the expression in a more clear form.
make_per = 0;
}else
make_per = 10000;
@@ -17418,7 +18490,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
make_per = make_per * battle_config.wp_rate / 100;
}
- if (sd->class_&JOBL_BABY) //if it's a Baby Class
+ if ((sd->job & JOBL_BABY) != 0) //if it's a Baby Class
make_per = (make_per * 50) / 100; //Baby penalty is 50% (bugreport:4847)
if(make_per < 1) make_per = 1;
@@ -17482,8 +18554,8 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
if(equip){
clif->produce_effect(sd,0,nameid);
clif->misceffect(&sd->bl,3);
- if(itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG]
- pc->addfame(sd,10); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point
+ if (itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG]
+ pc->addfame(sd, RANKTYPE_BLACKSMITH, 10); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point
} else {
int fame = 0;
tmp_item.amount = 0;
@@ -17523,8 +18595,9 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
sd->potion_success_counter = 0;
}
- if (fame)
- pc->addfame(sd,fame);
+ if (fame != 0 && (skill_id == AM_PHARMACY || skill_id == AM_TWILIGHT1 || skill_id == AM_TWILIGHT2 || skill_id == AM_TWILIGHT3)) {
+ pc->addfame(sd, RANKTYPE_ALCHEMIST, fame);
+ }
//Visual effects and the like.
switch (skill_id) {
case AM_PHARMACY:
@@ -17551,7 +18624,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
{ //Cooking items.
clif->specialeffect(&sd->bl, 608, AREA);
if( sd->cook_mastery < 1999 )
- pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->dbs->produce_db[idx].itemlv - 11) / 2 ) ) * 5);
+ pc_setglobalreg(sd, script->add_variable("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->dbs->produce_db[idx].itemlv - 11) / 2 ) ) * 5);
}
break;
}
@@ -17565,24 +18638,28 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
tmp_item.amount = qty * skill->dbs->changematerial_db[i].qty[j];
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
k++;
}
}
break;
}
- if( k ){
+ if (k) {
+#if PACKETVER >= 20091013
clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS);
+#endif
return 1;
}
} else if (tmp_item.amount) { //Success
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
- if( skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY )
+#if PACKETVER >= 20091013
+ if (skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY)
clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS);
+#endif
return 1;
}
}
@@ -17631,7 +18708,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
int rate = rnd()%500;
memset(&tmp_item,0,sizeof(tmp_item));
if( rate < 50) i = 4;
- else if( rate < 100) i = 2+rnd()%1;
+ else if( rate < 100) i = 2+rnd()%1; // FIXME[Haru]: This '%1' is certainly not intended. If anyone knows the purpose, please rewrite this code.
else if( rate < 250 ) i = 1;
else if( rate < 500 ) i = 0;
tmp_item.nameid = compensation[i];
@@ -17639,29 +18716,33 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
tmp_item.identify = 1;
if( pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE) ) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
- clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE);
+#if PACKETVER >= 20091013
+ clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAIL);
+#endif
}
break;
case GN_MAKEBOMB:
case GN_S_PHARMACY:
case GN_CHANGEMATERIAL:
- clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE);
+#if PACKETVER >= 20091013
+ clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAIL);
+#endif
break;
default:
if( skill->dbs->produce_db[idx].itemlv > 10 && skill->dbs->produce_db[idx].itemlv <= 20 )
{ //Cooking items.
clif->specialeffect(&sd->bl, 609, AREA);
if( sd->cook_mastery > 0 )
- pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 ));
+ pc_setglobalreg(sd, script->add_variable("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 ));
}
}
}
return 0;
}
-int skill_arrow_create (struct map_session_data *sd, int nameid)
+static int skill_arrow_create(struct map_session_data *sd, int nameid)
{
int i,j,flag,index=-1;
struct item tmp_item;
@@ -17696,18 +18777,20 @@ int skill_arrow_create (struct map_session_data *sd, int nameid)
continue;
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
return 0;
}
-int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
+
+static int skill_poisoningweapon(struct map_session_data *sd, int nameid)
+{
sc_type type;
int chance, i;
nullpo_ret(sd);
if (nameid <= 0 || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND || pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME)) {
- clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, GC_POISONINGWEAPON, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
switch( nameid )
@@ -17721,7 +18804,7 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
case ITEMID_POISON_LAUGHING: type = SC_MAGICMUSHROOM; break;
case ITEMID_POISON_OBLIVION: type = SC_OBLIVIONCURSE; break;
default:
- clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, GC_POISONINGWEAPON, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
@@ -17733,7 +18816,8 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
return 0;
}
-void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
+static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id)
+{
struct status_change *sc = status->get_sc(bl);
// non-offensive and non-magic skills do not affect the status
@@ -17757,7 +18841,8 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
}
}
-int skill_magicdecoy(struct map_session_data *sd, int nameid) {
+static int skill_magicdecoy(struct map_session_data *sd, int nameid)
+{
int x, y, i, class_ = 0, skill_id;
struct mob_data *md;
nullpo_ret(sd);
@@ -17767,7 +18852,7 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
|| (i = pc->search_inventory(sd, nameid)) == INDEX_NOT_FOUND
|| pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) != 0
) {
- clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, NC_MAGICDECOY, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
@@ -17779,21 +18864,21 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
sd->menuskill_val = 0;
switch (nameid) {
- case ITEMID_SCARLET_POINT:
+ case ITEMID_SCARLET_PTS:
class_ = MOBID_MAGICDECOY_FIRE;
break;
- case ITEMID_INDIGO_POINT:
+ case ITEMID_INDIGO_PTS:
class_ = MOBID_MAGICDECOY_WATER;
break;
- case ITEMID_LIME_GREEN_POINT:
+ case ITEMID_LIME_GREEN_PTS:
class_ = MOBID_MAGICDECOY_WIND;
break;
- case ITEMID_YELLOW_WISH_POINT:
+ case ITEMID_YELLOW_WISH_PTS:
class_ = MOBID_MAGICDECOY_EARTH;
break;
}
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE, 0);
if( md ) {
md->master_id = sd->bl.id;
md->special_state.ai = AI_FLORA;
@@ -17808,7 +18893,8 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
}
// Warlock Spellbooks. [LimitLine/3CeAM]
-int skill_spellbook (struct map_session_data *sd, int nameid) {
+static int skill_spellbook(struct map_session_data *sd, int nameid)
+{
int i, max_preserve, skill_id, point;
struct status_change *sc;
@@ -17820,7 +18906,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
for(i=SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) if( sc && !sc->data[i] ) break;
if( i > SC_SPELLBOOK7 )
{
- clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0);
+ clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0, 0);
return 0;
}
@@ -17830,7 +18916,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
if( !pc->checkskill(sd, (skill_id = skill->dbs->spellbook_db[i].skill_id)) )
{ // User don't know the skill
sc_start(&sd->bl, &sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB)));
- clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0);
+ clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0, 0);
return 0;
}
@@ -17839,7 +18925,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
if( sc && sc->data[SC_READING_SB] ) {
if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) {
- clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0);
+ clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0, 0);
return 0;
}
for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett]
@@ -17856,7 +18942,9 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
return 1;
}
-int skill_select_menu(struct map_session_data *sd,uint16 skill_id) {
+
+static int skill_select_menu(struct map_session_data *sd, uint16 skill_id)
+{
int id, lv, prob, aslvl = 0, idx = 0;
nullpo_ret(sd);
@@ -17869,7 +18957,7 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) {
if( skill_id >= GS_GLITTERING || skill->get_type(skill_id) != BF_MAGIC ||
(id = sd->status.skill[idx].id) == 0 || sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED ) {
- clif->skill_fail(sd,SC_AUTOSHADOWSPELL,0,0);
+ clif->skill_fail(sd, SC_AUTOSHADOWSPELL, 0, 0, 0);
return 0;
}
@@ -17880,7 +18968,7 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) {
return 0;
}
-int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list)
+static int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list)
{
int i;
@@ -17901,10 +18989,10 @@ int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const
del_amount -= (del_amount % 10);
add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ;
- if (idx < 0 || idx >= MAX_INVENTORY
+ if (idx < 0 || idx >= sd->status.inventorySize
|| (nameid = sd->status.inventory[idx].nameid) <= 0
|| del_amount < 0 || del_amount > sd->status.inventory[idx].amount) {
- clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, SO_EL_ANALYSIS, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
@@ -17920,18 +19008,18 @@ int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const
case ITEMID_WIND_OF_VERDURE: product = ITEMID_ROUGH_WIND; break;
case ITEMID_YELLOW_LIVE: product = ITEMID_GREAT_NATURE; break;
default:
- clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, SO_EL_ANALYSIS, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
if( pc->delitem(sd, idx, del_amount, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME) ) {
- clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, SO_EL_ANALYSIS, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
if( skill_lv == 2 && rnd()%100 < 25 ) {
// At level 2 have a fail chance. You loose your items if it fails.
- clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, SO_EL_ANALYSIS, USESKILL_FAIL_LEVEL, 0, 0);
return 1;
}
@@ -17944,7 +19032,7 @@ int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const
int flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME);
if (flag) {
clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &tmp_item, tmp_item.amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
}
@@ -17953,7 +19041,7 @@ int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const
return 0;
}
-int skill_changematerial(struct map_session_data *sd, const struct itemlist *item_list)
+static int skill_changematerial(struct map_session_data *sd, const struct itemlist *item_list)
{
int i, j, k, c, p = 0, nameid, amount;
@@ -17972,11 +19060,13 @@ int skill_changematerial(struct map_session_data *sd, const struct itemlist *ite
for (k = 0; k < VECTOR_LENGTH(*item_list); k++) {
const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, k);
int idx = entry->id;
- Assert_ret(idx >= 0 && idx < MAX_INVENTORY);
+ Assert_ret(idx >= 0 && idx < sd->status.inventorySize);
amount = entry->amount;
nameid = sd->status.inventory[idx].nameid;
if (nameid > 0 && sd->status.inventory[idx].identify == 0) {
- clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NEED_IDENTIFY);
+#if PACKETVER >= 20091013
+ clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_FAIL_MATERIAL_IDENTITY);
+#endif
return 0;
}
if( nameid == skill->dbs->produce_db[i].mat_id[j] && (amount-p*skill->dbs->produce_db[i].mat_amount[j]) >= skill->dbs->produce_db[i].mat_amount[j]
@@ -17996,16 +19086,17 @@ int skill_changematerial(struct map_session_data *sd, const struct itemlist *ite
}
}
}
-
- if( p == 0)
- clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NOT_FOUND);
-
+#if PACKETVER >= 20091013
+ if (p == 0)
+ clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_RECIPE_NOTEXIST);
+#endif
return 0;
}
+
/**
* for Royal Guard's LG_TRAMPLE
**/
-int skill_destroy_trap(struct block_list *bl, va_list ap)
+static int skill_destroy_trap(struct block_list *bl, va_list ap)
{
struct skill_unit *su = NULL;
struct skill_unit_group *sg;
@@ -18020,7 +19111,7 @@ int skill_destroy_trap(struct block_list *bl, va_list ap)
case UNT_CLAYMORETRAP:
case UNT_FIRINGTRAP:
case UNT_ICEBOUNDTRAP:
- map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick);
+ skill->trap_do_splash(&su->bl, sg->skill_id, sg->skill_lv, sg->bl_flag | BL_SKILL | ~BCT_SELF, tick);
break;
case UNT_LANDMINE:
case UNT_BLASTMINE:
@@ -18029,7 +19120,7 @@ int skill_destroy_trap(struct block_list *bl, va_list ap)
case UNT_FLASHER:
case UNT_FREEZINGTRAP:
case UNT_CLUSTERBOMB:
- map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick);
+ skill->trap_do_splash(&su->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick);
break;
}
// Traps aren't recovered.
@@ -18037,14 +19128,16 @@ int skill_destroy_trap(struct block_list *bl, va_list ap)
}
return 0;
}
+
/*==========================================
*
*------------------------------------------*/
-int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) {
+static int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data)
+{
struct map_session_data *sd = map->id2sd(id);
struct skill_cd * cd = NULL;
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (!sd || !sd->blockskill[data])
return 0;
@@ -18092,7 +19185,8 @@ int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) {
* @param tick the length of time the delay should last
* @return 0 if successful, -1 otherwise
*/
-int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) {
+static int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
+{
struct skill_cd* cd = NULL;
uint16 idx = skill->get_index(skill_id);
int64 now = timer->gettick();
@@ -18127,9 +19221,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
if (DIFF_TICK32(cd->entry[i]->started + cd->entry[i]->duration, now) > tick)
return 0;
cd->entry[i]->duration = tick;
-#if PACKETVER >= 20120604
cd->entry[i]->total = tick;
-#endif
cd->entry[i]->started = now;
if( timer->settick(cd->entry[i]->timer,now+tick) != -1 )
return 0;
@@ -18161,9 +19253,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry);
cd->entry[cd->cursor]->duration = tick;
-#if PACKETVER >= 20120604
cd->entry[cd->cursor]->total = tick;
-#endif
cd->entry[cd->cursor]->skidx = idx;
cd->entry[cd->cursor]->skill_id = skill_id;
cd->entry[cd->cursor]->started = now;
@@ -18176,10 +19266,10 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
}
// [orn]
-int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data)
+static int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data)
{
struct homun_data *hd = map->id2hd(id);
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (hd != NULL)
hd->blockskill[data] = 0;
@@ -18187,7 +19277,9 @@ int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data)
return 1;
}
-int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { // [orn]
+// [orn]
+static int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick)
+{
uint16 idx = skill->get_index(skill_id);
nullpo_retr (-1, hd);
@@ -18203,10 +19295,10 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { /
}
// [orn]
-int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data)
+static int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data)
{
struct mercenary_data *md = map->id2mc(id);
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (md != NULL)
md->blockskill[data] = 0;
@@ -18214,7 +19306,7 @@ int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data)
return 1;
}
-int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick)
+static int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick)
{
uint16 idx = skill->get_index(skill_id);
nullpo_retr (-1, md);
@@ -18229,12 +19321,15 @@ int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick)
md->blockskill[idx] = 1;
return timer->add(timer->gettick() + tick, skill->blockmerc_end, md->bl.id, idx);
}
+
/**
* Adds a new skill unit entry for this player to recast after map load
**/
-void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill_lv) {
+static void skill_usave_add(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
+{
struct skill_unit_save * sus = NULL;
+ nullpo_retv(sd);
if( idb_exists(skill->usave_db,sd->status.char_id) ) {
idb_remove(skill->usave_db,sd->status.char_id);
}
@@ -18247,9 +19342,12 @@ void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill
return;
}
-void skill_usave_trigger(struct map_session_data *sd) {
+
+static void skill_usave_trigger(struct map_session_data *sd)
+{
struct skill_unit_save * sus = NULL;
+ nullpo_retv(sd);
if( ! (sus = idb_get(skill->usave_db,sd->status.char_id)) ) {
return;
}
@@ -18263,10 +19361,12 @@ void skill_usave_trigger(struct map_session_data *sd) {
/*
*
*/
-int skill_split_atoi(char *str, int *val)
+static int skill_split_atoi(char *str, int *val)
{
int i, j, step = 1;
+ nullpo_ret(val);
+
for (i=0; i<MAX_SKILL_LEVEL; i++) {
if (!str) break;
val[i] = atoi(str);
@@ -18308,7 +19408,7 @@ int skill_split_atoi(char *str, int *val)
/*
*
*/
-void skill_init_unit_layout (void)
+static void skill_init_unit_layout(void)
{
int i,j,pos = 0;
@@ -18479,7 +19579,7 @@ void skill_init_unit_layout (void)
}
break;
default:
- ShowError("unknown unit layout at skill %d\n",i);
+ skill->init_unit_layout_unknown(i, pos);
break;
}
if (!skill->dbs->unit_layout[pos].count)
@@ -18580,7 +19680,14 @@ void skill_init_unit_layout (void)
}
-int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
+static void skill_init_unit_layout_unknown(int skill_idx, int pos)
+{
+ Assert_retv(skill_idx >= 0 && skill_idx < MAX_SKILL_DB);
+ ShowError("unknown unit layout at skill %d\n", skill->dbs->db[skill_idx].nameid);
+}
+
+static int skill_block_check(struct block_list *bl, sc_type type, uint16 skill_id)
+{
int inf = 0;
struct status_change *sc = status->get_sc(bl);
@@ -18727,7 +19834,8 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
return 0;
}
-int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
+static int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv)
+{
int type = 0;
switch (skill_id) {
@@ -18746,25 +19854,26 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
* update stored skill cooldowns for player logout
* @param sd the affected player structure
*/
-void skill_cooldown_save(struct map_session_data * sd) {
+static void skill_cooldown_save(struct map_session_data *sd)
+{
int i;
- struct skill_cd* cd = NULL;
+ struct skill_cd *cd = NULL;
int64 now = 0;
- // always check to make sure the session properly exists
nullpo_retv(sd);
- if( !(cd = idb_get(skill->cd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
+ if ((cd = idb_get(skill->cd_db, sd->status.char_id)) == NULL)
return;
- }
now = timer->gettick();
- // process each individual cooldown associated with the character
- for( i = 0; i < cd->cursor; i++ ) {
- cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started+cd->entry[i]->duration,now);
- if( cd->entry[i]->timer != INVALID_TIMER ) {
- timer->delete(cd->entry[i]->timer,skill->blockpc_end);
+ for (i = 0; i < cd->cursor; i++) {
+ if (battle_config.guild_skill_relog_delay == 1 && cd->entry[i]->skill_id > GD_SKILLBASE && cd->entry[i]->skill_id < GD_MAX)
+ continue;
+
+ cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started + cd->entry[i]->duration, now);
+ if (cd->entry[i]->timer != INVALID_TIMER) {
+ timer->delete(cd->entry[i]->timer, skill->blockpc_end);
cd->entry[i]->timer = INVALID_TIMER;
}
}
@@ -18774,7 +19883,8 @@ void skill_cooldown_save(struct map_session_data * sd) {
* reload stored skill cooldowns when a player logs in.
* @param sd the affected player structure
*/
-void skill_cooldown_load(struct map_session_data * sd) {
+static void skill_cooldown_load(struct map_session_data *sd)
+{
int i;
struct skill_cd* cd = NULL;
int64 now = 0;
@@ -18792,231 +19902,28 @@ void skill_cooldown_load(struct map_session_data * sd) {
// process each individual cooldown associated with the character
for( i = 0; i < cd->cursor; i++ ) {
- cd->entry[i]->started = now;
- cd->entry[i]->timer = timer->add(timer->gettick()+cd->entry[i]->duration,skill->blockpc_end,sd->bl.id,cd->entry[i]->skidx);
- sd->blockskill[cd->entry[i]->skidx] = true;
- }
-}
-
-/*==========================================
- * sub-function of DB reading.
- * skill_db.txt
- *------------------------------------------*/
-bool skill_parse_row_skilldb(char* split[], int columns, int current) {
-// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description
- uint16 skill_id = atoi(split[0]);
- uint16 idx;
- if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX)
- || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX)
- || (skill_id >= MC_SKILLRANGEMIN && skill_id <= MC_SKILLRANGEMAX)
- || (skill_id >= EL_SKILLRANGEMIN && skill_id <= EL_SKILLRANGEMAX) ) {
- ShowWarning("skill_parse_row_skilldb: Skill id %d is forbidden (interferes with guild/homun/mercenary skill mapping)!\n", skill_id);
- return false;
- }
+ int64 remaining;
- idx = skill->get_index(skill_id);
- if( !idx ) // invalid skill id
- return false;
-
- skill->dbs->db[idx].nameid = skill_id;
- skill->split_atoi(split[1],skill->dbs->db[idx].range);
- skill->dbs->db[idx].hit = atoi(split[2]);
- skill->dbs->db[idx].inf = atoi(split[3]);
- skill->split_atoi(split[4],skill->dbs->db[idx].element);
- skill->dbs->db[idx].nk = (int)strtol(split[5], NULL, 0);
- skill->split_atoi(split[6],skill->dbs->db[idx].splash);
- skill->dbs->db[idx].max = atoi(split[7]);
- skill->split_atoi(split[8],skill->dbs->db[idx].num);
-
- if( strcmpi(split[9],"yes") == 0 )
- skill->dbs->db[idx].castcancel = 1;
- else
- skill->dbs->db[idx].castcancel = 0;
- skill->dbs->db[idx].cast_def_rate = atoi(split[10]);
- skill->dbs->db[idx].inf2 = (int)strtol(split[11], NULL, 0);
- skill->split_atoi(split[12],skill->dbs->db[idx].maxcount);
- if( strcmpi(split[13],"weapon") == 0 )
- skill->dbs->db[idx].skill_type = BF_WEAPON;
- else if( strcmpi(split[13],"magic") == 0 )
- skill->dbs->db[idx].skill_type = BF_MAGIC;
- else if( strcmpi(split[13],"misc") == 0 )
- skill->dbs->db[idx].skill_type = BF_MISC;
- else
- skill->dbs->db[idx].skill_type = 0;
- skill->split_atoi(split[14],skill->dbs->db[idx].blewcount);
- safestrncpy(skill->dbs->db[idx].name, trim(split[15]), sizeof(skill->dbs->db[idx].name));
- safestrncpy(skill->dbs->db[idx].desc, trim(split[16]), sizeof(skill->dbs->db[idx].desc));
- strdb_iput(skill->name2id_db, skill->dbs->db[idx].name, skill_id);
- script->set_constant2(skill->dbs->db[idx].name, (int)skill_id, false, false);
-
- return true;
-}
-
-bool skill_parse_row_requiredb(char* split[], int columns, int current) {
-// skill_id,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10
- char* p;
- int j;
-
- uint16 skill_id = atoi(split[0]);
- uint16 idx = skill->get_index(skill_id);
- if( !idx ) // invalid skill id
- return false;
-
- skill->split_atoi(split[1],skill->dbs->db[idx].hp);
- skill->split_atoi(split[2],skill->dbs->db[idx].mhp);
- skill->split_atoi(split[3],skill->dbs->db[idx].sp);
- skill->split_atoi(split[4],skill->dbs->db[idx].hp_rate);
- skill->split_atoi(split[5],skill->dbs->db[idx].sp_rate);
- skill->split_atoi(split[6],skill->dbs->db[idx].zeny);
-
- //Which weapon type are required, see doc/item_db for types
- p = split[7];
- for( j = 0; j < 32; j++ ) {
- int l = atoi(p);
- if( l == 99 ) { // Any weapon
- skill->dbs->db[idx].weapon = 0;
- break;
- } else
- skill->dbs->db[idx].weapon |= 1<<l;
- p = strchr(p,':');
- if(!p)
- break;
- p++;
- }
-
- //FIXME: document this
- p = split[8];
- for( j = 0; j < 32; j++ ) {
- int l = atoi(p);
- if( l == 99 ) { // Any ammo type
- skill->dbs->db[idx].ammo = 0xFFFFFFFF;
- break;
- } else if( l ) // 0 stands for no requirement
- skill->dbs->db[idx].ammo |= 1<<l;
- p = strchr(p,':');
- if( !p )
- break;
- p++;
- }
- skill->split_atoi(split[9],skill->dbs->db[idx].ammo_qty);
-
- if( strcmpi(split[10],"hiding") == 0 ) skill->dbs->db[idx].state = ST_HIDING;
- else if( strcmpi(split[10],"cloaking") == 0 ) skill->dbs->db[idx].state = ST_CLOAKING;
- else if( strcmpi(split[10],"hidden") == 0 ) skill->dbs->db[idx].state = ST_HIDDEN;
- else if( strcmpi(split[10],"riding") == 0 ) skill->dbs->db[idx].state = ST_RIDING;
- else if( strcmpi(split[10],"falcon") == 0 ) skill->dbs->db[idx].state = ST_FALCON;
- else if( strcmpi(split[10],"cart") == 0 ) skill->dbs->db[idx].state = ST_CART;
- else if( strcmpi(split[10],"shield") == 0 ) skill->dbs->db[idx].state = ST_SHIELD;
- else if( strcmpi(split[10],"sight") == 0 ) skill->dbs->db[idx].state = ST_SIGHT;
- else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->dbs->db[idx].state = ST_EXPLOSIONSPIRITS;
- else if( strcmpi(split[10],"cartboost") == 0 ) skill->dbs->db[idx].state = ST_CARTBOOST;
- else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->dbs->db[idx].state = ST_RECOV_WEIGHT_RATE;
- else if( strcmpi(split[10],"move_enable") == 0 ) skill->dbs->db[idx].state = ST_MOVE_ENABLE;
- else if( strcmpi(split[10],"water") == 0 ) skill->dbs->db[idx].state = ST_WATER;
- else if( strcmpi(split[10],"dragon") == 0 ) skill->dbs->db[idx].state = ST_RIDINGDRAGON;
- else if( strcmpi(split[10],"warg") == 0 ) skill->dbs->db[idx].state = ST_WUG;
- else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->dbs->db[idx].state = ST_RIDINGWUG;
- else if( strcmpi(split[10],"mado") == 0 ) skill->dbs->db[idx].state = ST_MADO;
- else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->dbs->db[idx].state = ST_ELEMENTALSPIRIT;
- else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->dbs->db[idx].state = ST_POISONINGWEAPON;
- else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->dbs->db[idx].state = ST_ROLLINGCUTTER;
- else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->dbs->db[idx].state = ST_MH_FIGHTING;
- else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->dbs->db[idx].state = ST_MH_GRAPPLING;
- else if( strcmpi(split[10],"peco") == 0 ) skill->dbs->db[idx].state = ST_PECO;
- /**
- * Unknown or no state
- **/
- else skill->dbs->db[idx].state = ST_NONE;
-
- skill->split_atoi(split[11],skill->dbs->db[idx].spiritball);
- for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) {
- skill->dbs->db[idx].itemid[j] = atoi(split[12+ 2*j]);
- skill->dbs->db[idx].amount[j] = atoi(split[13+ 2*j]);
+ if (battle_config.guild_skill_relog_delay == 2 && cd->entry[i]->skill_id >= GD_SKILLBASE && cd->entry[i]->skill_id < GD_MAX) {
+ remaining = cd->entry[i]->started + cd->entry[i]->total - now;
+ remaining = max(1, remaining); // expired cooldowns will be 1, so they'll expire in the normal way just after this.
+ } else {
+ cd->entry[i]->started = now;
+ remaining = cd->entry[i]->duration;
+ }
+ cd->entry[i]->timer = timer->add(timer->gettick() + remaining, skill->blockpc_end, sd->bl.id, cd->entry[i]->skidx);
+ sd->blockskill[cd->entry[i]->skidx] = true;
}
-
- return true;
-}
-
-bool skill_parse_row_castdb(char* split[], int columns, int current) {
-// skill_id,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2
- uint16 skill_id = atoi(split[0]);
- uint16 idx = skill->get_index(skill_id);
- if( !idx ) // invalid skill id
- return false;
-
- skill->split_atoi(split[1],skill->dbs->db[idx].cast);
- skill->split_atoi(split[2],skill->dbs->db[idx].delay);
- skill->split_atoi(split[3],skill->dbs->db[idx].walkdelay);
- skill->split_atoi(split[4],skill->dbs->db[idx].upkeep_time);
- skill->split_atoi(split[5],skill->dbs->db[idx].upkeep_time2);
- skill->split_atoi(split[6],skill->dbs->db[idx].cooldown);
-#ifdef RENEWAL_CAST
- skill->split_atoi(split[7],skill->dbs->db[idx].fixed_cast);
-#endif
- return true;
-}
-
-bool skill_parse_row_castnodexdb(char* split[], int columns, int current) {
-// Skill id,Cast,Delay (optional)
- uint16 skill_id = atoi(split[0]);
- uint16 idx = skill->get_index(skill_id);
- if( !idx ) // invalid skill id
- return false;
-
- skill->split_atoi(split[1],skill->dbs->db[idx].castnodex);
- if( split[2] ) // optional column
- skill->split_atoi(split[2],skill->dbs->db[idx].delaynodex);
-
- return true;
-}
-
-bool skill_parse_row_unitdb(char* split[], int columns, int current) {
-// ID,unit ID,unit ID 2,layout,range,interval,target,flag
- uint16 skill_id = atoi(split[0]);
- uint16 idx = skill->get_index(skill_id);
- if( !idx ) // invalid skill id
- return false;
-
- skill->dbs->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16);
- skill->dbs->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16);
- skill->split_atoi(split[3],skill->dbs->db[idx].unit_layout_type);
- skill->split_atoi(split[4],skill->dbs->db[idx].unit_range);
- skill->dbs->db[idx].unit_interval = atoi(split[5]);
-
- if( strcmpi(split[6],"noenemy")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY;
- else if( strcmpi(split[6],"friend")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY;
- else if( strcmpi(split[6],"party")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY;
- else if( strcmpi(split[6],"ally")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY|BCT_GUILD;
- else if( strcmpi(split[6],"guild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD;
- else if( strcmpi(split[6],"all")==0 ) skill->dbs->db[idx].unit_target = BCT_ALL;
- else if( strcmpi(split[6],"enemy")==0 ) skill->dbs->db[idx].unit_target = BCT_ENEMY;
- else if( strcmpi(split[6],"self")==0 ) skill->dbs->db[idx].unit_target = BCT_SELF;
- else if( strcmpi(split[6],"sameguild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD;
- else if( strcmpi(split[6],"noone")==0 ) skill->dbs->db[idx].unit_target = BCT_NOONE;
- else skill->dbs->db[idx].unit_target = (int)strtol(split[6],NULL,16);
-
- skill->dbs->db[idx].unit_flag = (int)strtol(split[7],NULL,16);
-
- if (skill->dbs->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
- skill->dbs->db[idx].unit_target = BCT_NOENEMY;
-
- //By default, target just characters.
- skill->dbs->db[idx].unit_target |= BL_CHAR;
- if (skill->dbs->db[idx].unit_flag&UF_NOPC)
- skill->dbs->db[idx].unit_target &= ~BL_PC;
- if (skill->dbs->db[idx].unit_flag&UF_NOMOB)
- skill->dbs->db[idx].unit_target &= ~BL_MOB;
- if (skill->dbs->db[idx].unit_flag&UF_SKILL)
- skill->dbs->db[idx].unit_target |= BL_SKILL;
-
- return true;
}
-bool skill_parse_row_producedb(char* split[], int columns, int current) {
+static bool skill_parse_row_producedb(char *split[], int columns, int current)
+{
// ProduceItemID,ItemLV,RequireSkill,Requireskill_lv,MaterialID1,MaterialAmount1,......
int x,y;
+ int i;
- int i = atoi(split[0]);
+ nullpo_retr(false, split);
+ i = atoi(split[0]);
if( !i )
return false;
@@ -19033,11 +19940,14 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) {
return true;
}
-bool skill_parse_row_createarrowdb(char* split[], int columns, int current) {
+static bool skill_parse_row_createarrowdb(char *split[], int columns, int current)
+{
// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5
int x,y;
- int i = atoi(split[0]);
+ int i;
+ nullpo_retr(false, split);
+ i = atoi(split[0]);
if( !i )
return false;
@@ -19050,12 +19960,19 @@ bool skill_parse_row_createarrowdb(char* split[], int columns, int current) {
return true;
}
-bool skill_parse_row_spellbookdb(char* split[], int columns, int current) {
+
+static bool skill_parse_row_spellbookdb(char *split[], int columns, int current)
+{
// skill_id,PreservePoints
- uint16 skill_id = atoi(split[0]);
- int points = atoi(split[1]);
- int nameid = atoi(split[2]);
+ uint16 skill_id;
+ int points;
+ int nameid;
+
+ nullpo_retr(false, split);
+ skill_id = atoi(split[0]);
+ points = atoi(split[1]);
+ nameid = atoi(split[2]);
if( !skill->get_index(skill_id) || !skill->get_max(skill_id) )
ShowError("spellbook_db: Invalid skill ID %d\n", skill_id);
@@ -19073,10 +19990,16 @@ bool skill_parse_row_spellbookdb(char* split[], int columns, int current) {
return false;
}
-bool skill_parse_row_improvisedb(char* split[], int columns, int current) {
+
+static bool skill_parse_row_improvisedb(char *split[], int columns, int current)
+{
// SkillID,Rate
- uint16 skill_id = atoi(split[0]);
- short j = atoi(split[1]);
+ uint16 skill_id;
+ short j;
+
+ nullpo_retr(false, split);
+ skill_id = atoi(split[0]);
+ j = atoi(split[1]);
if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) {
ShowError("skill_improvise_db: Invalid skill ID %d\n", skill_id);
@@ -19099,10 +20022,14 @@ bool skill_parse_row_improvisedb(char* split[], int columns, int current) {
return true;
}
-bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) {
+
+static bool skill_parse_row_magicmushroomdb(char *split[], int column, int current)
+{
// SkillID
- uint16 skill_id = atoi(split[0]);
+ uint16 skill_id;
+ nullpo_retr(false, split);
+ skill_id = atoi(split[0]);
if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) {
ShowError("magicmushroom_db: Invalid skill ID %d\n", skill_id);
return false;
@@ -19117,20 +20044,12 @@ bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) {
return true;
}
-bool skill_parse_row_reproducedb(char* split[], int column, int current) {
- uint16 skill_id = atoi(split[0]);
- uint16 idx = skill->get_index(skill_id);
- if( !idx )
- return false;
-
- skill->dbs->reproduce_db[idx] = true;
-
- return true;
-}
-
-bool skill_parse_row_abradb(char* split[], int columns, int current) {
+static bool skill_parse_row_abradb(char *split[], int columns, int current)
+{
// skill_id,DummyName,RequiredHocusPocusLevel,Rate
- uint16 skill_id = atoi(split[0]);
+ uint16 skill_id;
+ nullpo_retr(false, split);
+ skill_id = atoi(split[0]);
if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) {
ShowError("abra_db: Invalid skill ID %d\n", skill_id);
return false;
@@ -19147,12 +20066,16 @@ bool skill_parse_row_abradb(char* split[], int columns, int current) {
return true;
}
-bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
+static bool skill_parse_row_changematerialdb(char *split[], int columns, int current)
+{
// ProductID,BaseRate,MakeAmount1,MakeAmountRate1...,MakeAmount5,MakeAmountRate5
- uint16 skill_id = atoi(split[0]);
- short j = atoi(split[1]);
+ int skill_id;
+ short j;
int x,y;
+ nullpo_retr(false, split);
+ skill_id = atoi(split[0]);
+ j = atoi(split[1]);
for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){
if( skill->dbs->produce_db[x].nameid == skill_id )
if( skill->dbs->produce_db[x].req_skill == GN_CHANGEMATERIAL )
@@ -19180,19 +20103,1348 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
return true;
}
+#define skilldb_duplicate_warning(name, setting, skill) (ShowError("skill_read_skilldb: Duplicate entry '%s' in setting '%s' for Skill Id %d in '%s', skipping...\n", name, setting, skill, "db/"DBPATH"skill_db.conf"))
+#define skilldb_invalid_error(name, setting, skill) (ShowError("skill_read_skilldb: Invalid entry '%s' in setting '%s' for Skill Id %d in '%s', skipping...\n", name, setting, skill, "db/"DBPATH"skill_db.conf"))
+
+/**
+ * Sets Level based configuration for skill groups from skill_db.conf [ Smokexyz/Hercules ]
+ * @param *conf pointer to config setting.
+ * @param *arr pointer to array to be set.
+ */
+static void skill_config_set_level(struct config_setting_t *conf, int *arr)
+{
+ int i=0;
+
+ nullpo_retv(arr);
+ if (config_setting_is_group(conf)) {
+ for (i=0; i<MAX_SKILL_LEVEL; i++) {
+ char level[6]; // enough to contain "Lv100" in case of custom MAX_SKILL_LEVEL
+ sprintf(level, "Lv%d", i+1);
+ libconfig->setting_lookup_int(conf, level, &arr[i]);
+ }
+ } else if (config_setting_is_array(conf)) {
+ for (i=0; i<config_setting_length(conf) && i < MAX_SKILL_LEVEL; i++) {
+ arr[i] = libconfig->setting_get_int_elem(conf, i);
+ }
+ } else {
+ int val=libconfig->setting_get_int(conf);
+ for(i=0; i<MAX_SKILL_LEVEL; i++) {
+ arr[i] = val;
+ }
+ }
+}
+
+/**
+ * Sets all values in a skill level array to a specified value [ Smokexyz/Hercules ]
+ * @param *arr pointer to array being parsed.
+ * @param value value being set for the array.
+ * @return (void)
+ */
+static void skill_level_set_value(int *arr, int value)
+{
+ int i=0;
+
+ nullpo_retv(arr);
+ for(i=0; i<MAX_SKILL_LEVEL; i++) {
+ arr[i] = value;
+ }
+}
+
+static void skill_validate_hittype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ const char *type = NULL;
+
+ nullpo_retv(sk);
+ if (libconfig->setting_lookup_string(conf, "Hit", &type)) {
+ if (strcmpi(type, "BDT_SKILL") == 0) {
+ sk->hit = BDT_SKILL;
+ } else if (strcmpi(type, "BDT_MULTIHIT") == 0) {
+ sk->hit = BDT_MULTIHIT;
+ } else if (strcmpi(type, "BDT_NORMAL") == 0) {
+ sk->hit = BDT_NORMAL;
+ } else {
+ skilldb_invalid_error(type, "Hit", sk->nameid);
+ return;
+ }
+ }
+}
+
+/**
+ * Validates "SkillType" when reading skill_db.conf
+ * @param conf struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_skilltype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *t = NULL, *tt = NULL;
+
+ nullpo_retv(sk);
+ if((t=libconfig->setting_get_member(conf, "SkillType")) && config_setting_is_group(t)) {
+ int j=0;
+ while ((tt = libconfig->setting_get_elem(t, j++))) {
+ const char *type = config_setting_name(tt);
+ bool on = libconfig->setting_get_bool_real(tt);
+
+ if (strcmpi(type, "Enemy") == 0) {
+ if (on) {
+ sk->inf |= INF_ATTACK_SKILL;
+ } else {
+ sk->inf &= ~INF_ATTACK_SKILL;
+ }
+ } else if (strcmpi(type, "Place") == 0) {
+ if (on) {
+ sk->inf |= INF_GROUND_SKILL;
+ } else {
+ sk->inf &= ~INF_GROUND_SKILL;
+ }
+ } else if (strcmpi(type, "Self") == 0) {
+ if (on) {
+ sk->inf |= INF_SELF_SKILL;
+ } else {
+ sk->inf &= ~INF_SELF_SKILL;
+ }
+ } else if (strcmpi(type, "Friend") == 0) {
+ if (on) {
+ sk->inf |= INF_SUPPORT_SKILL;
+ } else {
+ sk->inf &= ~INF_SUPPORT_SKILL;
+ }
+ } else if (strcmpi(type, "Trap") == 0) {
+ if (on) {
+ sk->inf |= INF_TARGET_TRAP;
+ } else {
+ sk->inf &= ~INF_TARGET_TRAP;
+ }
+ } else if (strcmpi(type, "Passive") != 0) {
+ skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
+ }
+ }
+ }
+}
+
+/**
+ * Validates "SkillInfo" when reading skill_db.conf
+ * @param conf struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_skillinfo(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *t = NULL, *tt = NULL;
+
+ nullpo_retv(sk);
+ if ((t=libconfig->setting_get_member(conf, "SkillInfo")) && config_setting_is_group(t)) {
+ int j=0;
+ while ((tt = libconfig->setting_get_elem(t, j++))) {
+ const char *type = config_setting_name(tt);
+ bool on = libconfig->setting_get_bool_real(tt);
+
+ if (strcmpi(type, "Quest") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_QUEST_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_QUEST_SKILL;
+ }
+ } else if (strcmpi(type, "NPC") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_NPC_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_NPC_SKILL;
+ }
+ } else if (strcmpi(type, "Wedding") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_WEDDING_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_WEDDING_SKILL;
+ }
+ } else if (strcmpi(type, "Spirit") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_SPIRIT_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_SPIRIT_SKILL;
+ }
+ } else if (strcmpi(type, "Guild") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_GUILD_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_GUILD_SKILL;
+ }
+ } else if (strcmpi(type, "Song") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_SONG_DANCE;
+ } else {
+ sk->inf2 &= ~INF2_SONG_DANCE;
+ }
+ } else if (strcmpi(type, "Ensemble") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_ENSEMBLE_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_ENSEMBLE_SKILL;
+ }
+ } else if (strcmpi(type, "Trap") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_TRAP;
+ } else {
+ sk->inf2 &= ~INF2_TRAP;
+ }
+ } else if (strcmpi(type, "TargetSelf") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_TARGET_SELF;
+ } else {
+ sk->inf2 &= ~INF2_TARGET_SELF;
+ }
+ } else if (strcmpi(type, "NoCastSelf") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_NO_TARGET_SELF;
+ } else {
+ sk->inf2 &= ~INF2_NO_TARGET_SELF;
+ }
+ } else if (strcmpi(type, "PartyOnly") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_PARTY_ONLY;
+ } else {
+ sk->inf2 &= ~INF2_PARTY_ONLY;
+ }
+ } else if (strcmpi(type, "GuildOnly") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_GUILD_ONLY;
+ } else {
+ sk->inf2 &= ~INF2_GUILD_ONLY;
+ }
+ } else if (strcmpi(type, "NoEnemy") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_NO_ENEMY;
+ } else {
+ sk->inf2 &= ~INF2_NO_ENEMY;
+ }
+ } else if (strcmpi(type, "IgnoreLandProtector") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_NOLP;
+ } else {
+ sk->inf2 &= ~INF2_NOLP;
+ }
+ } else if (strcmpi(type, "Chorus") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_CHORUS_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_CHORUS_SKILL;
+ }
+ } else if (strcmpi(type, "FreeCastNormal") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_FREE_CAST_NORMAL;
+ } else {
+ sk->inf2 &= ~INF2_FREE_CAST_NORMAL;
+ }
+ } else if (strcmpi(type, "FreeCastReduced") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_FREE_CAST_REDUCED;
+ } else {
+ sk->inf2 &= ~INF2_FREE_CAST_REDUCED;
+ }
+ } else if (strcmpi(type, "ShowSkillScale") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_SHOW_SKILL_SCALE;
+ } else {
+ sk->inf2 &= ~INF2_SHOW_SKILL_SCALE;
+ }
+ } else if (strcmpi(type, "AllowReproduce") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_ALLOW_REPRODUCE;
+ } else {
+ sk->inf2 &= ~INF2_ALLOW_REPRODUCE;
+ }
+ } else if (strcmpi(type, "HiddenTrap") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_HIDDEN_TRAP;
+ } else {
+ sk->inf2 &= ~INF2_HIDDEN_TRAP;
+ }
+ } else if (strcmpi(type, "IsCombo") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_IS_COMBO_SKILL;
+ } else {
+ sk->inf2 &= ~INF2_IS_COMBO_SKILL;
+ }
+ } else if (strcmpi(type, "None") != 0) {
+ skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
+ }
+ }
+ }
+}
+
+/**
+ * Validates "AttackType" when reading skill_db.conf
+ * @param conf struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_attacktype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ const char *type = NULL;
+
+ nullpo_retv(sk);
+ if (libconfig->setting_lookup_string(conf, "AttackType", &type)) {
+ if (!strcmpi(type, "Weapon")) {
+ sk->skill_type = BF_WEAPON;
+ } else if (!strcmpi(type, "Magic")) {
+ sk->skill_type = BF_MAGIC;
+ } else if (!strcmpi(type, "Misc")) {
+ sk->skill_type = BF_MISC;
+ } else {
+ skilldb_invalid_error(type, "AttackType", sk->nameid);
+ return;
+ }
+ }
+}
+
+/**
+ * Validates "Element" when reading skill_db.conf
+ * @param ele_t struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_element(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ const char *type = NULL;
+ struct config_setting_t *t = NULL;
+
+ nullpo_retv(sk);
+ if ((t=libconfig->setting_get_member(conf, "Element")) && config_setting_is_group(t)) {
+ int j = 0;
+ char lv[6]; // enough to contain "Lv100" in case of custom MAX_SKILL_LEVEL
+
+ for (j=0; j < MAX_SKILL_LEVEL; j++) {
+ sprintf(lv, "Lv%d",j+1);
+ if (libconfig->setting_lookup_string(t, lv, &type)) {
+ if (strcmpi(type,"Ele_Weapon") == 0)
+ sk->element[j] = -1;
+ else if (strcmpi(type,"Ele_Endowed") == 0)
+ sk->element[j] = -2;
+ else if (strcmpi(type,"Ele_Random") == 0)
+ sk->element[j] = -3;
+ else if (!script->get_constant(type,&sk->element[j]))
+ skilldb_invalid_error(type, config_setting_name(conf), sk->nameid);
+ }
+ }
+
+ } else if (libconfig->setting_lookup_string(conf, "Element", &type)) {
+ int ele = 0;
+
+ if (strcmpi(type,"Ele_Weapon") == 0)
+ ele = -1;
+ else if (strcmpi(type,"Ele_Endowed") == 0)
+ ele = -2;
+ else if (strcmpi(type,"Ele_Random") == 0)
+ ele = -3;
+ else if (!script->get_constant(type, &ele)) {
+ skilldb_invalid_error(type, config_setting_name(conf), sk->nameid);
+ return;
+ }
+
+ skill->level_set_value(sk->element, ele);
+ }
+}
+
+/**
+ * Validates "DamageType" when reading skill_db.conf
+ * @param conf struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_damagetype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *t = NULL, *tt = NULL;
+
+ nullpo_retv(sk);
+ if ((t=libconfig->setting_get_member(conf, "DamageType")) && config_setting_is_group(t)) {
+ int j=0;
+ while ((tt = libconfig->setting_get_elem(t, j++))) {
+ const char *type = config_setting_name(tt);
+ bool on = libconfig->setting_get_bool_real(tt);
+
+ if (strcmpi(type, "NoDamage") == 0) {
+ if (on) {
+ sk->nk |= NK_NO_DAMAGE;
+ } else {
+ sk->nk &= ~NK_NO_DAMAGE;
+ }
+ } else if (strcmpi(type, "SplashArea") == 0) {
+ if (on) {
+ sk->nk |= NK_SPLASH_ONLY;
+ } else {
+ sk->nk &= ~NK_SPLASH_ONLY;
+ }
+ } else if (strcmpi(type, "SplitDamage") == 0) {
+ if (on) {
+ sk->nk |= NK_SPLASHSPLIT;
+ } else {
+ sk->nk &= ~NK_SPLASHSPLIT;
+ }
+ } else if (strcmpi(type, "IgnoreCards") == 0) {
+ if (on) {
+ sk->nk |= NK_NO_CARDFIX_ATK;
+ } else {
+ sk->nk &= ~NK_NO_CARDFIX_ATK;
+ }
+ } else if (strcmpi(type, "IgnoreElement") == 0) {
+ if (on) {
+ sk->nk |= NK_NO_ELEFIX;
+ } else {
+ sk->nk &= ~NK_NO_ELEFIX;
+ }
+ } else if (strcmpi(type, "IgnoreDefense") == 0) {
+ if (on) {
+ sk->nk |= NK_IGNORE_DEF;
+ } else {
+ sk->nk &= ~NK_IGNORE_DEF;
+ }
+ } else if (strcmpi(type, "IgnoreFlee") == 0) {
+ if (on) {
+ sk->nk |= NK_IGNORE_FLEE;
+ } else {
+ sk->nk &= ~NK_IGNORE_FLEE;
+ }
+ } else if (strcmpi(type, "IgnoreDefCards") == 0) {
+ if (on) {
+ sk->nk |= NK_NO_CARDFIX_DEF;
+ } else {
+ sk->nk &= ~NK_NO_CARDFIX_DEF;
+ }
+ } else {
+ skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
+ }
+ }
+ }
+}
+
+/**
+ * Validates "SkillCast/DelayOptions" when reading skill_db.conf
+ * @param conf struct, pointer to skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @param delay boolean, switch for cast/delay setting
+ * @return (void)
+ */
+static void skill_validate_castnodex(struct config_setting_t *conf, struct s_skill_db *sk, bool delay)
+{
+ struct config_setting_t *t = NULL, *tt = NULL;
+
+ nullpo_retv(sk);
+ if ((t=libconfig->setting_get_member(conf, delay?"SkillDelayOptions":"CastTimeOptions")) && config_setting_is_group(t)) {
+ int j = 0, tmpopt = 0;
+ while ((tt = libconfig->setting_get_elem(t, j++)) && j < 4) {
+ const char *type = config_setting_name(tt);
+ bool on = libconfig->setting_get_bool_real(tt);
+
+ if (strcmpi(type, "IgnoreDex") == 0) {
+ if (on) {
+ tmpopt |= 1<<0;
+ } else {
+ tmpopt &= ~(1<<0);
+ }
+ } else if (strcmpi(type, "IgnoreStatusEffect") == 0) {
+ if (on) {
+ tmpopt |= 1<<1;
+ } else {
+ tmpopt &= ~(1<<1);
+ }
+ } else if (strcmpi(type, "IgnoreItemBonus") == 0) {
+ if (on) {
+ tmpopt |= 1<<2;
+ } else {
+ tmpopt &= ~(1<<2);
+ }
+ } else {
+ skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
+ return;
+ }
+
+ }
+ skill->level_set_value(delay?sk->delaynodex:sk->castnodex, tmpopt);
+ }
+}
+
+/**
+ * Validates the "WeaponTypes" flag
+ * when parsing skill_db.conf
+ * @param *type const char, weapon type flag
+ * @param on boolean, switch for the flag
+ * @param *sk struct, pointer to s_skill_db
+ * @return void
+ */
+static int skill_validate_weapontype_sub(const char *type, bool on, struct s_skill_db *sk)
+{
+ nullpo_ret(sk);
+ if (strcmpi(type, "NoWeapon") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_FIST;
+ } else {
+ sk->weapon &= ~(1<<W_FIST);
+ }
+ } else if (strcmpi(type, "Daggers") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DAGGER;
+ } else {
+ sk->weapon &= ~(1<<W_DAGGER);
+ }
+ } else if (strcmpi(type, "1HSwords") == 0) {
+
+ if (on) {
+ sk->weapon |= 1<<W_1HSWORD;
+ } else {
+ sk->weapon &= ~(1<<W_1HSWORD);
+ }
+ } else if (strcmpi(type, "2HSwords") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_2HSWORD;
+ } else {
+ sk->weapon &= ~(1<<W_2HSWORD);
+ }
+ } else if (strcmpi(type, "1HSpears") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_1HSPEAR;
+ } else {
+ sk->weapon &= ~(1<<W_1HSPEAR);
+ }
+ } else if (strcmpi(type, "2HSpears") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_2HSPEAR;
+ } else {
+ sk->weapon &= ~(1<<W_2HSPEAR);
+ }
+ } else if (strcmpi(type, "1HAxes") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_1HAXE;
+ } else {
+ sk->weapon &= ~(1<<W_1HAXE);
+ }
+ } else if (strcmpi(type, "2HAxes") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_2HAXE;
+ } else {
+ sk->weapon &= ~(1<<W_2HAXE);
+ }
+ } else if (strcmpi(type, "Maces") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_MACE;
+ } else {
+ sk->weapon &= ~(1<<W_MACE);
+ }
+ } else if (strcmpi(type, "2HMaces") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_2HMACE;
+ } else {
+ sk->weapon &= ~(1<<W_2HMACE);
+ }
+ } else if (strcmpi(type, "Staves") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_STAFF;
+ } else {
+ sk->weapon &= ~(1<<W_STAFF);
+ }
+ } else if (strcmpi(type, "Bows") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_BOW;
+ } else {
+ sk->weapon &= ~(1<<W_BOW);
+ }
+ } else if (strcmpi(type, "Knuckles") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_KNUCKLE;
+ } else {
+ sk->weapon &= ~(1<<W_KNUCKLE);
+ }
+ } else if (strcmpi(type, "Instruments") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_MUSICAL;
+ } else {
+ sk->weapon &= ~(1<<W_MUSICAL);
+ }
+ } else if (strcmpi(type, "Whips") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_WHIP;
+ } else {
+ sk->weapon &= ~(1<<W_WHIP);
+ }
+ } else if (strcmpi(type, "Books") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_BOOK;
+ } else {
+ sk->weapon &= ~(1<<W_BOOK);
+ }
+ } else if (strcmpi(type, "Katars") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_KATAR;
+ } else {
+ sk->weapon &= ~(1<<W_KATAR);
+ }
+ } else if (strcmpi(type, "Revolvers") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_REVOLVER;
+ } else {
+ sk->weapon &= ~(1<<W_REVOLVER);
+ }
+ } else if (strcmpi(type, "Rifles") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_RIFLE;
+ } else {
+ sk->weapon &= ~(1<<W_RIFLE);
+ }
+ } else if (strcmpi(type, "GatlingGuns") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_GATLING;
+ } else {
+ sk->weapon &= ~(1<<W_GATLING);
+ }
+ } else if (strcmpi(type, "Shotguns") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_SHOTGUN;
+ } else {
+ sk->weapon &= ~(1<<W_SHOTGUN);
+ }
+ } else if (strcmpi(type, "GrenadeLaunchers") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_GRENADE;
+ } else {
+ sk->weapon &= ~(1<<W_GRENADE);
+ }
+ } else if (strcmpi(type, "FuumaShurikens") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_HUUMA;
+ } else {
+ sk->weapon &= ~(1<<W_HUUMA);
+ }
+ } else if (strcmpi(type, "2HStaves") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_2HSTAFF;
+ } else {
+ sk->weapon &= ~(1<<W_2HSTAFF);
+ }
+ }
+ /* MAX_SINGLE_WEAPON_TYPE excluded */
+ else if (strcmpi(type, "DWDaggers") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_DD;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_DD);
+ }
+ } else if (strcmpi(type, "DWSwords") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_SS;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_SS);
+ }
+ } else if (strcmpi(type, "DWAxes") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_AA;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_AA);
+ }
+ } else if (strcmpi(type, "DWDaggerSword") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_DS;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_DS);
+ }
+ } else if (strcmpi(type, "DWDaggerAxe") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_DA;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_DA);
+ }
+ } else if (strcmpi(type, "DWSwordAxe") == 0) {
+ if (on) {
+ sk->weapon |= 1<<W_DOUBLE_SA;
+ } else {
+ sk->weapon &= ~(1<<W_DOUBLE_SA);
+ }
+ } else if (strcmpi(type, "All") == 0) {
+ sk->weapon = 0;
+ } else {
+ ShowError("Item %d. Unknown weapon type %s\n", sk->nameid, type);
+ return 1; // invalid type
+ }
+
+ return 0;
+}
+
+/**
+ * Validates "WeaponTypes"
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_weapontype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *tt = NULL;
+ const char *type = NULL;
+
+ nullpo_retv(sk);
+ if ((tt = libconfig->setting_get_member(conf, "WeaponTypes")) && config_setting_is_group(tt)) {
+ int j = 0;
+ struct config_setting_t *wpt = NULL;
+ while ((wpt = libconfig->setting_get_elem(tt, j++)) != NULL) {
+ if (skill->validate_weapontype_sub(config_setting_name(wpt), libconfig->setting_get_bool_real(wpt), sk))
+ skilldb_invalid_error(config_setting_name(wpt), config_setting_name(tt), sk->nameid);
+ }
+ } else if (libconfig->setting_lookup_string(conf, "WeaponTypes", &type)) {
+ if (skill->validate_weapontype_sub(type, true, sk))
+ skilldb_invalid_error(type, "WeaponTypes", sk->nameid);
+ }
+}
+
+/**
+ * Validates the "AmmoTypes" flag
+ * when parsing skill_db.conf
+ * @param type string, ammo type flag
+ * @param on boolean, switch for the flag
+ * @param sk struct, pointer to s_skill_db
+ * @return void
+ */
+static int skill_validate_ammotype_sub(const char *type, bool on, struct s_skill_db *sk)
+{
+ nullpo_ret(sk);
+ if (strcmpi(type, "A_ARROW") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_ARROW;
+ } else {
+ sk->ammo &= ~(1<<A_ARROW);
+ }
+ } else if (strcmpi(type, "A_DAGGER") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_DAGGER;
+ } else {
+ sk->ammo &= ~(1<<A_DAGGER);
+ }
+ } else if (strcmpi(type, "A_BULLET") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_BULLET;
+ } else {
+ sk->ammo &= ~(1<<A_BULLET);
+ }
+ } else if (strcmpi(type, "A_SHELL") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_SHELL;
+ } else {
+ sk->ammo &= ~(1<<A_SHELL);
+ }
+ } else if (strcmpi(type, "A_GRENADE") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_GRENADE;
+ } else {
+ sk->ammo &= ~(1<<A_GRENADE);
+ }
+ } else if (strcmpi(type, "A_SHURIKEN") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_SHURIKEN;
+ } else {
+ sk->ammo &= ~(1<<A_SHURIKEN);
+ }
+ } else if (strcmpi(type, "A_KUNAI") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_KUNAI;
+ } else {
+ sk->ammo &= ~(1<<A_KUNAI);
+ }
+ } else if (strcmpi(type, "A_CANNONBALL") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_CANNONBALL;
+ } else {
+ sk->ammo &= ~(1<<A_CANNONBALL);
+ }
+ } else if (strcmpi(type, "A_THROWWEAPON") == 0) {
+ if (on) {
+ sk->ammo |= 1<<A_THROWWEAPON;
+ } else {
+ sk->ammo &= ~(1<<A_THROWWEAPON);
+ }
+ } else if (strcmpi(type, "All") == 0) {
+ if (on) {
+ sk->ammo = 0xFFFFFFFF;
+ } else {
+ sk->ammo = 0;
+ }
+ } else {
+ return 1; // Invalid Entry
+ }
+
+ return 0;
+}
+
+/**
+ * Validates the "AmmoTypes" flag
+ * when parsing skill_db.conf
+ * @param conf pointer to the skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return void
+ */
+static void skill_validate_ammotype(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *tt = NULL;
+ const char *tstr = NULL;
+
+ nullpo_retv(sk);
+ if ((tt = libconfig->setting_get_member(conf, "AmmoTypes")) && config_setting_is_group(tt)) {
+ int j = 0;
+ struct config_setting_t *amt = { 0 };
+ while ((amt = libconfig->setting_get_elem(tt, j++))) {
+ if (skill->validate_ammotype_sub(config_setting_name(amt), libconfig->setting_get_bool_real(amt), sk))
+ skilldb_invalid_error(config_setting_name(amt), config_setting_name(tt), sk->nameid);
+ }
+ } else if( libconfig->setting_lookup_string(conf, "AmmoTypes", &tstr)) {
+ if (skill->validate_ammotype_sub(tstr, true, sk))
+ skilldb_invalid_error(tstr, "AmmoTypes", sk->nameid);
+ }
+}
+
+/**
+ * Validates the "State" flag
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return void
+ */
+static void skill_validate_state(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ const char *type = NULL;
+
+ nullpo_retv(sk);
+ if (libconfig->setting_lookup_string(conf, "State", &type) && strcmpi(type,"None") != ST_NONE) {
+ if ( strcmpi(type,"Hiding") == 0 ) sk->state = ST_HIDING;
+ else if (strcmpi(type,"Cloaking") == 0 ) sk->state = ST_CLOAKING;
+ else if (strcmpi(type,"Hidden") == 0 ) sk->state = ST_HIDDEN;
+ else if (strcmpi(type,"Riding") == 0 ) sk->state = ST_RIDING;
+ else if (strcmpi(type,"Falcon") == 0 ) sk->state = ST_FALCON;
+ else if (strcmpi(type,"Cart") == 0 ) sk->state = ST_CART;
+ else if (strcmpi(type,"Shield") == 0 ) sk->state = ST_SHIELD;
+ else if (strcmpi(type,"Sight") == 0 ) sk->state = ST_SIGHT;
+ else if (strcmpi(type,"ExplosionSpirits") == 0 ) sk->state = ST_EXPLOSIONSPIRITS;
+ else if (strcmpi(type,"CartBoost") == 0 ) sk->state = ST_CARTBOOST;
+ else if (strcmpi(type,"NotOverWeight") == 0 ) sk->state = ST_RECOV_WEIGHT_RATE;
+ else if (strcmpi(type,"Moveable") == 0 ) sk->state = ST_MOVE_ENABLE;
+ else if (strcmpi(type,"InWater") == 0 ) sk->state = ST_WATER;
+ else if (strcmpi(type,"Dragon") == 0 ) sk->state = ST_RIDINGDRAGON;
+ else if (strcmpi(type,"Warg") == 0 ) sk->state = ST_WUG;
+ else if (strcmpi(type,"RidingWarg") == 0 ) sk->state = ST_RIDINGWUG;
+ else if (strcmpi(type,"MadoGear") == 0 ) sk->state = ST_MADO;
+ else if (strcmpi(type,"ElementalSpirit") == 0 ) sk->state = ST_ELEMENTALSPIRIT;
+ else if (strcmpi(type,"PoisonWeapon") == 0 ) sk->state = ST_POISONINGWEAPON;
+ else if (strcmpi(type,"RollingCutter") == 0 ) sk->state = ST_ROLLINGCUTTER;
+ else if (strcmpi(type,"MH_Fighting") == 0 ) sk->state = ST_MH_FIGHTING;
+ else if (strcmpi(type,"MH_Grappling") == 0 ) sk->state = ST_MH_GRAPPLING;
+ else if (strcmpi(type,"Peco") == 0 ) sk->state = ST_PECO;
+ else
+ skilldb_invalid_error(type, "State", sk->nameid);
+ }
+}
+
+/**
+ * Validates the "Items" flag
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return void
+ */
+static void skill_validate_item_requirements(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *tt = NULL;
+
+ nullpo_retv(sk);
+ if ((tt=libconfig->setting_get_member(conf, "Items")) && config_setting_is_group(conf)) {
+ int itx=-1;
+ struct config_setting_t *it;
+
+ while((it=libconfig->setting_get_elem(tt, ++itx)) && itx < MAX_SKILL_ITEM_REQUIRE) {
+ const char *type = config_setting_name(it);
+
+ if( type[0] == 'I' && type[1] == 'D' && itemdb->exists(atoi(type+2)) )
+ sk->itemid[itx] = atoi(type+2);
+ else if(!script->get_constant(type, &sk->itemid[itx])) {
+ ShowWarning("skill_read_skilldb: Invalid required Item '%s' given for skill Id %d in '%s', skipping...\n",type, sk->nameid, DBPATH"skill_db.conf");
+ continue;
+ }
+
+ if (config_setting_is_group(it)) {
+ // TODO: Per-level item requirements are not implemented yet!
+ // We just take the first level for the time being (old txt behavior)
+ sk->amount[itx] = libconfig->setting_get_int_elem(it, 0);
+ } else {
+ sk->amount[itx] = libconfig->setting_get_int(it);
+ }
+ }
+ }
+}
+
+/**
+ * Validates the "Unit > Target" flag
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, pointer to s_skill_db
+ * @return void
+ */
+static void skill_validate_unit_target(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ const char *type = NULL;
+
+ nullpo_retv(sk);
+ if(libconfig->setting_lookup_string(conf, "Target", &type)) {
+
+ if(!strcmpi(type,"NotEnemy")) sk->unit_target = BCT_NOENEMY;
+ else if(!strcmpi(type,"NotParty")) sk->unit_target = BCT_NOPARTY;
+ else if (!strcmpi(type,"NotGuild")) sk->unit_target = BCT_NOGUILD;
+ else if(!strcmpi(type,"Friend")) sk->unit_target = BCT_NOENEMY;
+ else if(!strcmpi(type,"Party")) sk->unit_target = BCT_PARTY;
+ else if(!strcmpi(type,"Ally")) sk->unit_target = BCT_PARTY|BCT_GUILD;
+ else if(!strcmpi(type,"Guild")) sk->unit_target = BCT_GUILD;
+ else if(!strcmpi(type,"All")) sk->unit_target = BCT_ALL;
+ else if(!strcmpi(type,"Enemy")) sk->unit_target = BCT_ENEMY;
+ else if(!strcmpi(type,"Self")) sk->unit_target = BCT_SELF;
+ else if(!strcmpi(type,"SameGuild")) sk->unit_target = BCT_GUILD|BCT_SAMEGUILD;
+ }
+
+ if (sk->unit_flag & UF_DEFNOTENEMY && battle_config.defnotenemy)
+ sk->unit_target = BCT_NOENEMY;
+
+ //By default, target just characters.
+ sk->unit_target |= BL_CHAR;
+
+ if (sk->unit_flag & UF_NOPC)
+ sk->unit_target &= ~BL_PC;
+ if (sk->unit_flag & UF_NOMOB)
+ sk->unit_target &= ~BL_MOB;
+ if (sk->unit_flag & UF_SKILL)
+ sk->unit_target |= BL_SKILL;
+}
+
+/**
+ * Validates the "Unit > Flag" setting
+ * when parsing skill_db.conf
+ * @param type const char, name of the flag being parsed.
+ * @param on boolean, switch for flag setting
+ * @param sk struct, pointer to s_skill_db.
+ * @return (void)
+ */
+static int skill_validate_unit_flag_sub(const char *type, bool on, struct s_skill_db *sk)
+{
+ nullpo_ret(type);
+ nullpo_ret(sk);
+ if (strcmpi(type, "UF_DEFNOTENEMY") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_DEFNOTENEMY;
+ } else {
+ sk->unit_flag &= ~UF_DEFNOTENEMY;
+ }
+ } else if (strcmpi(type, "UF_NOREITERATION") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_NOREITERATION;
+ } else {
+ sk->unit_flag &= ~UF_NOREITERATION;
+ }
+ } else if (strcmpi(type, "UF_NOFOOTSET") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_NOFOOTSET;
+ } else {
+ sk->unit_flag &= ~UF_NOFOOTSET;
+ }
+ } else if (strcmpi(type, "UF_NOOVERLAP") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_NOOVERLAP;
+ } else {
+ sk->unit_flag &= ~UF_NOOVERLAP;
+ }
+ } else if (strcmpi(type, "UF_PATHCHECK") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_PATHCHECK;
+ } else {
+ sk->unit_flag &= ~UF_PATHCHECK;
+ }
+ } else if (strcmpi(type, "UF_NOPC") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_NOPC;
+ } else {
+ sk->unit_flag &= ~UF_NOPC;
+ }
+ } else if (strcmpi(type, "UF_NOMOB") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_NOMOB;
+ } else {
+ sk->unit_flag &= ~UF_NOMOB;
+ }
+ } else if (strcmpi(type, "UF_SKILL") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_SKILL;
+ } else {
+ sk->unit_flag &= ~UF_SKILL;
+ }
+ } else if (strcmpi(type, "UF_DANCE") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_DANCE;
+ } else {
+ sk->unit_flag &= ~UF_DANCE;
+ }
+ } else if (strcmpi(type, "UF_ENSEMBLE") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_ENSEMBLE;
+ } else {
+ sk->unit_flag &= ~UF_ENSEMBLE;
+ }
+ } else if (strcmpi(type, "UF_SONG") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_SONG;
+ } else {
+ sk->unit_flag &= ~UF_SONG;
+ }
+ } else if (strcmpi(type, "UF_DUALMODE") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_DUALMODE;
+ } else {
+ sk->unit_flag &= ~UF_DUALMODE;
+ }
+ } else if (strcmpi(type, "UF_RANGEDSINGLEUNIT") == 0) {
+ if (on) {
+ sk->unit_flag |= UF_RANGEDSINGLEUNIT;
+ } else {
+ sk->unit_flag &= ~UF_RANGEDSINGLEUNIT;
+ }
+ } else {
+ return 1; // Invalid Type
+ }
+
+ return 0;
+}
+
+/**
+ * Validate "Unit > Flag" setting
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_unit_flag(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ struct config_setting_t *t = NULL;
+
+ nullpo_retv(sk);
+ if ((t=libconfig->setting_get_member(conf, "Flag")) && config_setting_is_group(t)) {
+ int j=0;
+ struct config_setting_t *tt = NULL;
+ while ((tt = libconfig->setting_get_elem(t, j++))) {
+ const char *name = config_setting_name(tt);
+
+ if (skill->validate_unit_flag_sub(name, libconfig->setting_get_bool_real(tt), sk))
+ skilldb_invalid_error(name, config_setting_name(t), sk->nameid);
+ }
+ }
+}
+/**
+ * Validate additional field settings via plugins
+ * when parsing skill_db.conf
+ * @param conf struct, pointer to the skill configuration
+ * @param sk struct, struct, pointer to s_skill_db
+ * @return (void)
+ */
+static void skill_validate_additional_fields(struct config_setting_t *conf, struct s_skill_db *sk)
+{
+ // Does nothing like a boss. *cough* plugins *cough*
+}
+
+/**
+ * Validates a skill entry and adds it to the database. [ Smokexyz/Hercules ]
+ * @param sk contains skill data to be checked.
+ * @param *source filepath constant.
+ * @return boolean true on success.
+ */
+static bool skill_validate_skilldb(struct s_skill_db *sk, const char *source)
+{
+ int idx;
+
+ nullpo_retr(false, sk);
+ idx = skill->get_index(sk->nameid);
+ if (idx == 0) {
+ ShowWarning("skill_validate_skilldb: Invalid skill Id %d provided in '%s'! ... skipping\n", sk->nameid, source);
+ ShowInfo("It is possible that the skill Id is 0 or unavailable (interferes with guild/homun/mercenary skill mapping).\n");
+ return false;
+ } else if (sk->max <= 0) {
+ ShowError("skill_validate_skilldb: Invalid Max Level %d specified for skill Id %d in '%s', skipping...\n", sk->max, sk->nameid, source);
+ return false;
+ }
+
+ /* Direct assignment of temporary skill storage to skill db */
+ skill->dbs->db[idx] = *sk;
+ /* Put skill name in name2id DB */
+ strdb_iput(skill->name2id_db, skill->dbs->db[idx].name, skill->dbs->db[idx].nameid);
+ /* Set Name to Id script constants */
+ script->set_constant2(skill->dbs->db[idx].name, (int)skill->dbs->db[idx].nameid, false, false);
+
+ return true;
+}
+
+/**
+ * Reads skill_db.conf from relative filepath and processes [ Smokexyz/Hercules ]
+ * entries into the skill database.
+ * @param filename contains the file path and name.
+ * @return boolean true on success
+ */
+static bool skill_read_skilldb(const char *filename)
+{
+ struct config_t skilldb;
+ struct config_setting_t *sk, *conf;
+ char filepath[256];
+ int count=0, index=0;
+ bool duplicate[MAX_SKILL_DB] = {0};
+
+ nullpo_retr(false, filename);
+
+ libconfig->format_db_path(filename, filepath, sizeof(filepath));
+
+ if (!libconfig->load_file(&skilldb, filepath)) {
+ return false; // Libconfig error report.
+ }
+
+ // Possible Syntax error.
+ if ((sk=libconfig->setting_get_member(skilldb.root, "skill_db")) == NULL) {
+ ShowError("skill_read_skilldb: Skill DB could not be loaded, please check '%s'.\n", filepath);
+ libconfig->destroy(&skilldb);
+ return false;
+ }
+
+ while ((conf = libconfig->setting_get_elem(sk,index++))) {
+ int idx=0, skill_id=0, temp=0;
+ struct config_setting_t *t = NULL, *tt = NULL;
+ struct s_skill_db tmp_db = { 0 };
+
+ /* Skill ID */
+ if (!libconfig->setting_lookup_int(conf, "Id", &skill_id)) {
+ ShowError("skill_read_skilldb: Skill Id not specified for entry %d in '%s', skipping...\n", index, filepath );
+ continue;
+ }
+
+ tmp_db.nameid = skill_id;
+
+ if((idx = skill->get_index(skill_id)) == 0) {
+ ShowError("skill_read_skilldb: Skill Id %d is out of range, or within a reserved range (for guild, homunculus, mercenary or elemental skills). skipping...\n", idx);
+ continue;
+ }
+
+ if (duplicate[idx]) {
+ ShowWarning("skill_read_skilldb: Duplicate Skill Id %d in entry %d in '%s', skipping...\n", skill_id, index, filepath);
+ continue;
+ }
+
+ /* Skill Name Constant */
+ if (!libconfig->setting_lookup_mutable_string(conf, "Name", tmp_db.name, sizeof(tmp_db.name))) {
+ ShowError("skill_read_skilldb: Name not specified for skill Id %d in '%s', skipping...\n", skill_id, filepath);
+ continue;
+ }
+
+ /* Skill Description */
+ libconfig->setting_lookup_mutable_string(conf, "Description", tmp_db.desc, sizeof(tmp_db.desc));
+
+ /* Max Level */
+ if (!libconfig->setting_lookup_int(conf, "MaxLevel", &temp)) {
+ ShowError("skill_read_skilldb: MaxLevel not specified for skill Id %d in '%s', skipping...\n", skill_id, filepath);
+ continue;
+ } else {
+ tmp_db.max = temp;
+ }
+
+ /* Range */
+ if ((t=libconfig->setting_get_member(conf, "Range")))
+ skill->config_set_level(t, tmp_db.range);
+
+ /* Hit Type */
+ skill->validate_hittype(conf, &tmp_db);
+
+ /* Skill Type */
+ skill->validate_skilltype(conf, &tmp_db);
+
+ /* Skill Info */
+ skill->validate_skillinfo(conf, &tmp_db);
+
+ /* Skill Attack Type */
+ skill->validate_attacktype(conf, &tmp_db);
+
+ /* Skill Element */
+ skill->validate_element(conf, &tmp_db);
+
+ /* Damage Type */
+ skill->validate_damagetype(conf, &tmp_db);
+
+ /* Splash Range */
+ if ((t = libconfig->setting_get_member(conf, "SplashRange")))
+ skill->config_set_level(t, tmp_db.splash);
+
+ /* Number of Hits */
+ if ((t = libconfig->setting_get_member(conf, "NumberOfHits")) && config_setting_is_group(t))
+ skill->config_set_level(t, tmp_db.num);
+ else if ((libconfig->setting_lookup_int(conf, "NumberOfHits", &temp)))
+ skill->level_set_value(tmp_db.num, temp);
+ else
+ skill->level_set_value(tmp_db.num, 1); // Default 1
+
+ /* Interrupt Cast */
+ if (libconfig->setting_lookup_bool(conf, "InterruptCast", &tmp_db.castcancel) == CONFIG_FALSE)
+ tmp_db.castcancel = 0;
+
+ /* Cast Defense Rate */
+ libconfig->setting_lookup_int(conf, "CastDefRate", &tmp_db.cast_def_rate);
+
+ /* Skill Instances */
+ if ((t = libconfig->setting_get_member(conf, "SkillInstances")))
+ skill->config_set_level(t, tmp_db.maxcount);
+
+ /* Knock-Back Tiles */
+ if ((t = libconfig->setting_get_member(conf, "KnockBackTiles")))
+ skill->config_set_level(t, tmp_db.blewcount);
+ /**
+ * Skill Cast / Delay data handling
+ */
+ /* Cast Time */
+ if ((t=libconfig->setting_get_member(conf, "CastTime")))
+ skill->config_set_level(t, tmp_db.cast);
+
+ /* After Cast Act Delay */
+ if ((t=libconfig->setting_get_member(conf, "AfterCastActDelay")))
+ skill->config_set_level(t, tmp_db.delay);
+
+ /* After Cast Walk Delay */
+ if ((t=libconfig->setting_get_member(conf, "AfterCastWalkDelay")))
+ skill->config_set_level(t, tmp_db.walkdelay);
+
+ /* Skill Data/Duration */
+ if ((t=libconfig->setting_get_member(conf, "SkillData1")))
+ skill->config_set_level(t, tmp_db.upkeep_time);
+
+ /* Skill Data/Duration 2 */
+ if ((t=libconfig->setting_get_member(conf, "SkillData2")))
+ skill->config_set_level(t, tmp_db.upkeep_time2);
+
+ /* Skill Cool Down */
+ if ((t=libconfig->setting_get_member(conf, "CoolDown")))
+ skill->config_set_level(t, tmp_db.cooldown);
+
+#ifdef RENEWAL_CAST
+ /* Fixed Casting Time */
+ if ((t=libconfig->setting_get_member(conf, "FixedCastTime")))
+ skill->config_set_level(t, tmp_db.fixed_cast);
+#endif
+ /* Cast Time Options */
+ skill->validate_castnodex(conf, &tmp_db, false);
+ skill->validate_castnodex(conf, &tmp_db, true);
+
+ /**
+ * Skill Requirements data handling
+ */
+ if ((t=libconfig->setting_get_member(conf, "Requirements")) && config_setting_is_group(t)) {
+
+ /* HP Costs */
+ if ((tt = libconfig->setting_get_member(t, "HPCost")))
+ skill->config_set_level(tt, tmp_db.hp);
+
+ /* Max HP Trigger */
+ if ((tt = libconfig->setting_get_member(t, "MaxHPTrigger")))
+ skill->config_set_level(tt, tmp_db.mhp);
+
+ /* SP Cost */
+ if ((tt = libconfig->setting_get_member(t, "SPCost")))
+ skill->config_set_level(tt, tmp_db.sp);
+
+ /* HP Rate */
+ if ((tt = libconfig->setting_get_member(t, "HPRateCost")))
+ skill->config_set_level(tt, tmp_db.hp_rate);
+
+ /* SP Rate */
+ if ((tt = libconfig->setting_get_member(t, "SPRateCost")))
+ skill->config_set_level(tt, tmp_db.sp_rate);
+
+ /* Zeny Cost */
+ if ((tt = libconfig->setting_get_member(t, "ZenyCost")))
+ skill->config_set_level(tt, tmp_db.zeny);
+
+ /* Spirit Sphere Cost */
+ if ((tt = libconfig->setting_get_member(t, "SpiritSphereCost")))
+ skill->config_set_level(tt, tmp_db.spiritball);
+
+ /* Weapon Types */
+ skill->validate_weapontype(t, &tmp_db);
+
+ /* Ammunition Types */
+ skill->validate_ammotype(t, &tmp_db);
+
+ /* Ammunition Amount */
+ if ((tt = libconfig->setting_get_member(t, "AmmoAmount")))
+ skill->config_set_level(tt, tmp_db.ammo_qty);
+
+ /* State */
+ skill->validate_state(t, &tmp_db);
+
+ /* Spirit Sphere Cost */
+ if ((tt = libconfig->setting_get_member(t, "SpiritSphereCost")))
+ skill->config_set_level(tt, tmp_db.spiritball);
+
+ /* Item Requirements and Amounts */
+ skill->validate_item_requirements(t, &tmp_db);
+ }
+
+ /**
+ * Skill Unit data handling
+ */
+ if ((t=libconfig->setting_get_member(conf, "Unit")) && config_setting_is_group(t)) {
+
+ /* Unit IDs [1,2] */
+ if ((tt=libconfig->setting_get_member(t, "Id")) && config_setting_is_array(tt)) {
+ tmp_db.unit_id[0] = libconfig->setting_get_int_elem(tt, 0);
+ tmp_db.unit_id[1] = libconfig->setting_get_int_elem(tt, 1);
+ } else {
+ libconfig->setting_lookup_int(t, "Id", &tmp_db.unit_id[0]);
+ }
+
+ /* Layout */
+ if((tt=libconfig->setting_get_member(t, "Layout")))
+ skill->config_set_level(tt, tmp_db.unit_layout_type);
+
+ /* Range */
+ if((tt=libconfig->setting_get_member(t, "Range")))
+ skill->config_set_level(tt, tmp_db.unit_range);
+
+ /* Interval */
+ if(libconfig->setting_lookup_int(t, "Interval", &temp))
+ tmp_db.unit_interval = temp;
+
+ /* Flag */
+ skill->validate_unit_flag(t, &tmp_db);
+
+ /* Target */
+ skill->validate_unit_target(t, &tmp_db);
+ }
+
+ /* Additional Fields for Plugins */
+ skill->validate_additional_fields(conf, &tmp_db);
+
+ // Validate the skill entry, add it to the duplicate array and increment count on success.
+ if ((duplicate[idx] = skill->validate_skilldb(&tmp_db, filepath)))
+ count++;
+ }
+
+ libconfig->destroy(&skilldb);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+
+ return true;
+}
+
+#undef skilldb_duplicate_warning
+#undef skilldb_invalid_error
+
/*===============================
* DB reading.
- * skill_db.txt
- * skill_require_db.txt
- * skill_cast_db.txt
- * skill_castnodex_db.txt
- * skill_nocast_db.txt
- * skill_unit_db.txt
* produce_db.txt
* create_arrow_db.txt
* abra_db.txt
*------------------------------*/
-void skill_readdb(bool minimal) {
+static void skill_readdb(bool minimal)
+{
// init skill db structures
db_clear(skill->name2id_db);
@@ -19205,10 +21457,12 @@ void skill_readdb(bool minimal) {
safestrncpy(skill->dbs->db[0].name, "UNKNOWN_SKILL", sizeof(skill->dbs->db[0].name));
safestrncpy(skill->dbs->db[0].desc, "Unknown Skill", sizeof(skill->dbs->db[0].desc));
+ itemdb->name_constants(); // refresh ItemDB constants before loading of skills
+
#ifdef ENABLE_CASE_CHECK
- script->parser_current_file = DBPATH"skill_db.txt";
+ script->parser_current_file = DBPATH"skill_db.conf";
#endif // ENABLE_CASE_CHECK
- sv->readdb(map->db_path, DBPATH"skill_db.txt", ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb);
+ skill->read_skilldb(DBPATH"skill_db.conf");
#ifdef ENABLE_CASE_CHECK
script->parser_current_file = NULL;
#endif // ENABLE_CASE_CHECK
@@ -19216,15 +21470,6 @@ void skill_readdb(bool minimal) {
if (minimal)
return;
- sv->readdb(map->db_path, DBPATH"skill_require_db.txt", ',', 32, 32, MAX_SKILL_DB, skill->parse_row_requiredb);
-#ifdef RENEWAL_CAST
- sv->readdb(map->db_path, "re/skill_cast_db.txt", ',', 8, 8, MAX_SKILL_DB, skill->parse_row_castdb);
-#else
- sv->readdb(map->db_path, "pre-re/skill_cast_db.txt", ',', 7, 7, MAX_SKILL_DB, skill->parse_row_castdb);
-#endif
- sv->readdb(map->db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill->parse_row_castnodexdb);
- sv->readdb(map->db_path, DBPATH"skill_unit_db.txt", ',', 8, 8, MAX_SKILL_DB, skill->parse_row_unitdb);
-
skill->init_unit_layout();
sv->readdb(map->db_path, "produce_db.txt", ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill->parse_row_producedb);
sv->readdb(map->db_path, "create_arrow_db.txt", ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill->parse_row_createarrowdb);
@@ -19233,12 +21478,11 @@ void skill_readdb(bool minimal) {
sv->readdb(map->db_path, "spellbook_db.txt", ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill->parse_row_spellbookdb);
//Guillotine Cross
sv->readdb(map->db_path, "magicmushroom_db.txt", ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill->parse_row_magicmushroomdb);
- sv->readdb(map->db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill->parse_row_reproducedb);
sv->readdb(map->db_path, "skill_improvise_db.txt", ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill->parse_row_improvisedb);
sv->readdb(map->db_path, "skill_changematerial_db.txt", ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill->parse_row_changematerialdb);
}
-void skill_reload(void)
+static void skill_reload(void)
{
struct s_mapiterator *iter;
struct map_session_data *sd;
@@ -19271,7 +21515,8 @@ void skill_reload(void)
/*==========================================
*
*------------------------------------------*/
-int do_init_skill(bool minimal) {
+static int do_init_skill(bool minimal)
+{
skill->name2id_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAX_SKILL_NAME_LENGTH);
skill->read_db(minimal);
@@ -19304,7 +21549,8 @@ int do_init_skill(bool minimal) {
return 0;
}
-int do_final_skill(void) {
+static int do_final_skill(void)
+{
db_destroy(skill->name2id_db);
db_destroy(skill->group_db);
db_destroy(skill->unit_db);
@@ -19317,8 +21563,10 @@ int do_final_skill(void) {
ers_destroy(skill->cd_entry_ers);
return 0;
}
+
/* initialize the interface */
-void skill_defaults(void) {
+void skill_defaults(void)
+{
const int skill_enchant_eff[5] = { 10, 14, 17, 19, 20 };
const int skill_deluge_eff[5] = { 5, 9, 12, 14, 15 };
@@ -19368,8 +21616,12 @@ void skill_defaults(void) {
skill->get_hp = skill_get_hp;
skill->get_mhp = skill_get_mhp;
skill->get_sp = skill_get_sp;
+ skill->get_hp_rate = skill_get_hp_rate;
+ skill->get_sp_rate = skill_get_sp_rate;
skill->get_state = skill_get_state;
skill->get_spiritball = skill_get_spiritball;
+ skill->get_itemid = skill_get_itemid;
+ skill->get_itemqty = skill_get_itemqty;
skill->get_zeny = skill_get_zeny;
skill->get_num = skill_get_num;
skill->get_cast = skill_get_cast;
@@ -19398,12 +21650,12 @@ void skill_defaults(void) {
skill->tree_get_max = skill_tree_get_max;
skill->get_name = skill_get_name;
skill->get_desc = skill_get_desc;
- skill->chk = skill_chk;
skill->get_casttype = skill_get_casttype;
skill->get_casttype2 = skill_get_casttype2;
skill->is_combo = skill_is_combo;
skill->name2id = skill_name2id;
skill->isammotype = skill_isammotype;
+ skill->castend_type = skill_castend_type;
skill->castend_id = skill_castend_id;
skill->castend_pos = skill_castend_pos;
skill->castend_map = skill_castend_map;
@@ -19449,8 +21701,11 @@ void skill_defaults(void) {
skill->can_cloak = skill_can_cloak;
skill->enchant_elemental_end = skill_enchant_elemental_end;
skill->not_ok = skillnotok;
+ skill->not_ok_unknown = skill_notok_unknown;
skill->not_ok_hom = skillnotok_hom;
+ skill->not_ok_hom_unknown = skillnotok_hom_unknown;
skill->not_ok_mercenary = skillnotok_mercenary;
+ skill->validate_autocast_data = skill_validate_autocast_data;
skill->chastle_mob_changetarget = skill_chastle_mob_changetarget;
skill->can_produce_mix = skill_can_produce_mix;
skill->produce_mix = skill_produce_mix;
@@ -19474,6 +21729,7 @@ void skill_defaults(void) {
skill->onskillusage = skill_onskillusage;
skill->cell_overlap = skill_cell_overlap;
skill->timerskill = skill_timerskill;
+ skill->trap_do_splash = skill_trap_do_splash;
skill->trap_splash = skill_trap_splash;
skill->check_condition_mercenary = skill_check_condition_mercenary;
skill->locate_element_field = skill_locate_element_field;
@@ -19497,6 +21753,7 @@ void skill_defaults(void) {
skill->sit_out = skill_sit_out;
skill->unitsetmapcell = skill_unitsetmapcell;
skill->unit_onplace_timer = skill_unit_onplace_timer;
+ skill->unit_onplace_timer_unknown = skill_unit_onplace_timer_unknown;
skill->unit_effect = skill_unit_effect;
skill->unit_timer_sub_onplace = skill_unit_timer_sub_onplace;
skill->unit_move_sub = skill_unit_move_sub;
@@ -19507,17 +21764,35 @@ void skill_defaults(void) {
skill->unit_timer = skill_unit_timer;
skill->unit_timer_sub = skill_unit_timer_sub;
skill->init_unit_layout = skill_init_unit_layout;
- skill->parse_row_skilldb = skill_parse_row_skilldb;
- skill->parse_row_requiredb = skill_parse_row_requiredb;
- skill->parse_row_castdb = skill_parse_row_castdb;
- skill->parse_row_castnodexdb = skill_parse_row_castnodexdb;
- skill->parse_row_unitdb = skill_parse_row_unitdb;
+ skill->init_unit_layout_unknown = skill_init_unit_layout_unknown;
+ /* Skill DB Libconfig */
+ skill->validate_hittype = skill_validate_hittype;
+ skill->validate_attacktype = skill_validate_attacktype;
+ skill->validate_element = skill_validate_element;
+ skill->validate_skilltype = skill_validate_skilltype;
+ skill->validate_skillinfo = skill_validate_skillinfo;
+ skill->validate_damagetype = skill_validate_damagetype;
+ skill->validate_castnodex = skill_validate_castnodex;
+ skill->validate_weapontype = skill_validate_weapontype;
+ skill->validate_ammotype = skill_validate_ammotype;
+ skill->validate_state = skill_validate_state;
+ skill->validate_item_requirements = skill_validate_item_requirements;
+ skill->validate_unit_target = skill_validate_unit_target;
+ skill->validate_unit_flag = skill_validate_unit_flag;
+ skill->validate_additional_fields = skill_validate_additional_fields;
+ skill->validate_skilldb = skill_validate_skilldb;
+ skill->validate_weapontype_sub = skill_validate_weapontype_sub;
+ skill->validate_ammotype_sub = skill_validate_ammotype_sub;
+ skill->validate_unit_flag_sub = skill_validate_unit_flag_sub;
+ skill->read_skilldb = skill_read_skilldb;
+ skill->config_set_level = skill_config_set_level;
+ skill->level_set_value = skill_level_set_value;
+ /* */
skill->parse_row_producedb = skill_parse_row_producedb;
skill->parse_row_createarrowdb = skill_parse_row_createarrowdb;
skill->parse_row_abradb = skill_parse_row_abradb;
skill->parse_row_spellbookdb = skill_parse_row_spellbookdb;
skill->parse_row_magicmushroomdb = skill_parse_row_magicmushroomdb;
- skill->parse_row_reproducedb = skill_parse_row_reproducedb;
skill->parse_row_improvisedb = skill_parse_row_improvisedb;
skill->parse_row_changematerialdb = skill_parse_row_changematerialdb;
skill->usave_add = skill_usave_add;
@@ -19568,4 +21843,8 @@ void skill_defaults(void) {
skill->get_requirement_off_unknown = skill_get_requirement_off_unknown;
skill->get_requirement_item_unknown = skill_get_requirement_item_unknown;
skill->get_requirement_unknown = skill_get_requirement_unknown;
+ skill->splash_target = skill_splash_target;
+ skill->check_npc_chaospanic = skill_check_npc_chaospanic;
+ skill->count_wos = skill_count_wos;
+ skill->get_linked_song_dance_id = skill_get_linked_song_dance_id;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 35fddafa4..4dbbaf147 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,9 +23,10 @@
#include "map/map.h" // struct block_list
#include "map/status.h" // enum sc_type
+#include "map/unitdefines.h" // enum unit_dir
#include "common/hercules.h"
#include "common/db.h"
-#include "common/mmo.h" // MAX_SKILL, struct square
+#include "common/mmo.h" // MAX_SKILL_DB, struct square
/**
* Declarations
@@ -43,7 +44,6 @@ struct status_change_entry;
/**
* Defines
**/
-#define MAX_SKILL_DB MAX_SKILL
#define MAX_SKILL_PRODUCE_DB 270
#define MAX_PRODUCE_RESOURCE 10
#define MAX_SKILL_ARROW_DB 140
@@ -58,7 +58,13 @@ struct status_change_entry;
#define MAX_SKILLUNITGROUP 25
#define MAX_SKILL_ITEM_REQUIRE 10
#define MAX_SKILLUNITGROUPTICKSET 25
-#define MAX_SKILL_NAME_LENGTH 30
+#define MAX_SKILL_NAME_LENGTH 32
+
+// Custom Skill Ranges is used in skill_get_index, to allocate indexes based on ID and gaps between 2 SkillID
+#ifndef CUSTOM_SKILL_RANGES
+ #define CUSTOM_SKILL_RANGES
+#endif // CUSTOM_SKILL_RANGES
+
// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names)
#define skill_ischangesex(id) ( \
@@ -77,6 +83,7 @@ struct status_change_entry;
//Constants to identify the skill's inf value:
enum e_skill_inf {
+ INF_NONE = 0x00,
INF_ATTACK_SKILL = 0x01,
INF_GROUND_SKILL = 0x02,
INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen
@@ -89,8 +96,10 @@ enum e_skill_inf {
//The NK value applies only to non INF_GROUND_SKILL skills
//when determining skill castend function to invoke.
enum e_skill_nk {
+ NK_NONE = 0x00,
NK_NO_DAMAGE = 0x01,
NK_SPLASH = 0x02|0x04, // 0x4 = splash & split
+ NK_SPLASH_ONLY = 0x02,
NK_SPLASHSPLIT = 0x04,
NK_NO_CARDFIX_ATK = 0x08,
NK_NO_ELEFIX = 0x10,
@@ -102,21 +111,28 @@ enum e_skill_nk {
//A skill with 3 would be no damage + splash: area of effect.
//Constants to identify a skill's inf2 value.
enum e_skill_inf2 {
- INF2_QUEST_SKILL = 0x0001,
- INF2_NPC_SKILL = 0x0002, // NPC skills are those that players can't have in their skill tree.
- INF2_WEDDING_SKILL = 0x0004,
- INF2_SPIRIT_SKILL = 0x0008,
- INF2_GUILD_SKILL = 0x0010,
- INF2_SONG_DANCE = 0x0020,
- INF2_ENSEMBLE_SKILL = 0x0040,
- INF2_TRAP = 0x0080,
- INF2_TARGET_SELF = 0x0100, // Refers to ground placed skills that will target the caster as well (like Grandcross)
- INF2_NO_TARGET_SELF = 0x0200,
- INF2_PARTY_ONLY = 0x0400,
- INF2_GUILD_ONLY = 0x0800,
- INF2_NO_ENEMY = 0x1000,
- INF2_NOLP = 0x2000, // Spells that can ignore Land Protector
- INF2_CHORUS_SKILL = 0x4000, // Chorus skill
+ INF2_NONE = 0x00000,
+ INF2_QUEST_SKILL = 0x00001,
+ INF2_NPC_SKILL = 0x00002, // NPC skills are those that players can't have in their skill tree.
+ INF2_WEDDING_SKILL = 0x00004,
+ INF2_SPIRIT_SKILL = 0x00008,
+ INF2_GUILD_SKILL = 0x00010,
+ INF2_SONG_DANCE = 0x00020,
+ INF2_ENSEMBLE_SKILL = 0x00040,
+ INF2_TRAP = 0x00080,
+ INF2_TARGET_SELF = 0x00100, // Refers to ground placed skills that will target the caster as well (like Grandcross)
+ INF2_NO_TARGET_SELF = 0x00200,
+ INF2_PARTY_ONLY = 0x00400,
+ INF2_GUILD_ONLY = 0x00800,
+ INF2_NO_ENEMY = 0x01000,
+ INF2_NOLP = 0x02000, // Spells that can ignore Land Protector
+ INF2_CHORUS_SKILL = 0x04000, // Chorus skill
+ INF2_FREE_CAST_NORMAL = 0x08000,
+ INF2_FREE_CAST_REDUCED = 0x10000,
+ INF2_SHOW_SKILL_SCALE = 0x20000,
+ INF2_ALLOW_REPRODUCE = 0x40000,
+ INF2_HIDDEN_TRAP = 0x80000, // Traps that are hidden (based on trap_visiblity battle conf)
+ INF2_IS_COMBO_SKILL = 0x100000, // Sets whether a skill can be used in combos or not
};
@@ -129,6 +145,7 @@ enum e_skill_display {
};
enum {
+ UF_NONE = 0x0000,
UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x0002, // Spell cannot be stacked
UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets
@@ -155,7 +172,7 @@ enum wl_spheres {
};
enum {
- ST_NONE,
+ ST_NONE = 0,
ST_HIDING,
ST_CLOAKING,
ST_HIDDEN,
@@ -1362,6 +1379,10 @@ enum e_skill {
ITEM_OPTION_SPLASH_ATTACK,
GM_FORCE_TRANSFER,
GM_WIDE_RESURRECTION,
+ ALL_NIFLHEIM_RECALL,
+ ALL_PRONTERA_RECALL,
+ ALL_GLASTHEIM_RECALL,
+ ALL_THANATOS_RECALL,
GC_DARKCROW = 5001,
RA_UNLIMIT,
@@ -1379,6 +1400,47 @@ enum e_skill {
ALL_FULL_THROTTLE,
NC_MAGMA_ERUPTION_DOTDAMAGE,
+ /** Summoner */
+ SU_BASIC_SKILL = 5018,
+ SU_BITE,
+ SU_HIDE,
+ SU_SCRATCH,
+ SU_STOOP,
+ SU_LOPE,
+ SU_SPRITEMABLE,
+ SU_POWEROFLAND,
+ SU_SV_STEMSPEAR,
+ SU_CN_POWDERING,
+ SU_CN_METEOR,
+ SU_SV_ROOTTWIST,
+ SU_SV_ROOTTWIST_ATK,
+ SU_POWEROFLIFE,
+ SU_SCAROFTAROU,
+ SU_PICKYPECK,
+ SU_PICKYPECK_DOUBLE_ATK,
+ SU_ARCLOUSEDASH,
+ SU_LUNATICCARROTBEAT,
+ SU_POWEROFSEA,
+ SU_TUNABELLY,
+ SU_TUNAPARTY,
+ SU_BUNCHOFSHRIMP,
+ SU_FRESHSHRIMP,
+ SU_CN_METEOR2,
+ SU_LUNATICCARROTBEAT2,
+ SU_SOULATTACK,
+ SU_POWEROFFLOCK,
+ SU_SVG_SPIRIT,
+ SU_HISS,
+ SU_NYANGGRASS,
+ SU_GROOMING,
+ SU_PURRING,
+ SU_SHRIMPARTY,
+ SU_SPIRITOFLIFE,
+ SU_MEOWMEOW,
+ SU_SPIRITOFLAND,
+ SU_CHATTERING,
+ SU_SPIRITOFSEA,
+
HLIF_HEAL = 8001,
HLIF_AVOID,
HLIF_BRAIN,
@@ -1648,6 +1710,9 @@ enum {
UNT_B_TRAP,
UNT_FIRE_RAIN,
+ UNT_CATNIPPOWDER,
+ UNT_SV_ROOTTWIST,
+
/**
* Guild Auras
**/
@@ -1659,6 +1724,15 @@ enum {
UNT_MAX = 0x190
};
+/** Constants to identify the auto-cast type. **/
+enum autocast_type {
+ AUTOCAST_NONE = 0,
+ AUTOCAST_TEMP, // Used when type is only required during the execution of the calling instance. (For example bAutoSpell* skills.)
+ AUTOCAST_ABRA, // Used for Abracadabra (Hocus pocus).
+ AUTOCAST_IMPROVISE, // Used for Improvised Song.
+ AUTOCAST_ITEM, // Used for itemskill() script command.
+};
+
/**
* Structures
**/
@@ -1670,7 +1744,7 @@ struct skill_condition {
// Database skills
struct s_skill_db {
- unsigned short nameid;
+ int nameid;
char name[MAX_SKILL_NAME_LENGTH];
char desc[40];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
@@ -1718,6 +1792,7 @@ struct skill_unit_group {
int party_id;
int guild_id;
int bg_id;
+ int clan_id;
int map;
int target_flag; //Holds BCT_* flag for battle_check_target
int bl_flag; //Holds BL_* flag for map_foreachin* functions
@@ -1749,6 +1824,7 @@ struct skill_unit {
int limit;
int val1,val2;
+ bool visible;
short alive,range;
int prev;
};
@@ -1785,9 +1861,7 @@ struct s_skill_magicmushroom_db {
struct skill_cd_entry {
int duration;//milliseconds
-#if PACKETVER >= 20120604
- int total;/* used for display on newer clients */
-#endif
+ int total;/* used when reducing offline cooldown and for display on newer clients */
short skidx;//the skill index entries belong to
int64 started;/* gettick() of when it started, used vs duration to measure how much left upon logout */
int timer;/* timer id */
@@ -1842,7 +1916,6 @@ BEGIN_ZEROED_BLOCK; // This block will be zeroed in skill_defaults() as well as
struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB];
struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB];
struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB];
- bool reproduce_db[MAX_SKILL_DB];
END_ZEROED_BLOCK;
struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT];
};
@@ -1879,54 +1952,56 @@ struct skill_interface {
int unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them
int unit_group_newid;
/* accesssors */
- int (*get_index) ( uint16 skill_id );
- int (*get_type) ( uint16 skill_id );
- int (*get_hit) ( uint16 skill_id );
- int (*get_inf) ( uint16 skill_id );
- int (*get_ele) ( uint16 skill_id, uint16 skill_lv );
- int (*get_nk) ( uint16 skill_id );
- int (*get_max) ( uint16 skill_id );
- int (*get_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_range2) (struct block_list *bl, uint16 skill_id, uint16 skill_lv);
- int (*get_splash) ( uint16 skill_id, uint16 skill_lv );
- int (*get_hp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_mhp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_sp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_state) (uint16 skill_id);
- int (*get_spiritball) (uint16 skill_id, uint16 skill_lv);
- int (*get_zeny) ( uint16 skill_id, uint16 skill_lv );
- int (*get_num) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cast) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_walkdelay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time2) ( uint16 skill_id, uint16 skill_lv );
- int (*get_castnodex) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delaynodex) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_castdef) ( uint16 skill_id );
- int (*get_weapontype) ( uint16 skill_id );
- int (*get_ammotype) ( uint16 skill_id );
- int (*get_ammo_qty) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_id) (uint16 skill_id,int flag);
- int (*get_inf2) ( uint16 skill_id );
- int (*get_castcancel) ( uint16 skill_id );
- int (*get_maxcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_blewcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_flag) ( uint16 skill_id );
- int (*get_unit_target) ( uint16 skill_id );
- int (*get_unit_interval) ( uint16 skill_id );
- int (*get_unit_bl_target) ( uint16 skill_id );
- int (*get_unit_layout_type) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_unit_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cooldown) ( uint16 skill_id, uint16 skill_lv );
- int (*tree_get_max) ( uint16 skill_id, int b_class );
- const char *(*get_name) ( uint16 skill_id );
- const char *(*get_desc) ( uint16 skill_id );
- /* check */
- void (*chk) (uint16* skill_id);
+ int (*get_index) (int skill_id);
+ int (*get_type) (int skill_id);
+ int (*get_hit) (int skill_id);
+ int (*get_inf) (int skill_id);
+ int (*get_ele) (int skill_id, int skill_lv);
+ int (*get_nk) (int skill_id);
+ int (*get_max) (int skill_id);
+ int (*get_range) (int skill_id, int skill_lv);
+ int (*get_range2) (struct block_list *bl, int skill_id, int skill_lv);
+ int (*get_splash) (int skill_id, int skill_lv);
+ int (*get_hp) (int skill_id, int skill_lv);
+ int (*get_mhp) (int skill_id, int skill_lv);
+ int (*get_sp) (int skill_id, int skill_lv);
+ int (*get_hp_rate) (int skill_id, int skill_lv);
+ int (*get_sp_rate) (int skill_id, int skill_lv);
+ int (*get_state) (int skill_id);
+ int (*get_spiritball) (int skill_id, int skill_lv);
+ int (*get_itemid) (int skill_id, int item_idx);
+ int (*get_itemqty) (int skill_id, int item_idx);
+ int (*get_zeny) (int skill_id, int skill_lv);
+ int (*get_num) (int skill_id, int skill_lv);
+ int (*get_cast) (int skill_id, int skill_lv);
+ int (*get_delay) (int skill_id, int skill_lv);
+ int (*get_walkdelay) (int skill_id, int skill_lv);
+ int (*get_time) (int skill_id, int skill_lv);
+ int (*get_time2) (int skill_id, int skill_lv);
+ int (*get_castnodex) (int skill_id, int skill_lv);
+ int (*get_delaynodex) (int skill_id, int skill_lv);
+ int (*get_castdef) (int skill_id);
+ int (*get_weapontype) (int skill_id);
+ int (*get_ammotype) (int skill_id);
+ int (*get_ammo_qty) (int skill_id, int skill_lv);
+ int (*get_unit_id) (int skill_id, int flag);
+ int (*get_inf2) (int skill_id);
+ int (*get_castcancel) (int skill_id);
+ int (*get_maxcount) (int skill_id, int skill_lv);
+ int (*get_blewcount) (int skill_id, int skill_lv);
+ int (*get_unit_flag) (int skill_id);
+ int (*get_unit_target) (int skill_id);
+ int (*get_unit_interval) (int skill_id);
+ int (*get_unit_bl_target) (int skill_id);
+ int (*get_unit_layout_type) (int skill_id, int skill_lv);
+ int (*get_unit_range) (int skill_id, int skill_lv);
+ int (*get_cooldown) (int skill_id, int skill_lv);
+ int (*tree_get_max) (int skill_id, int class);
+ const char *(*get_name) (int skill_id);
+ const char *(*get_desc) (int skill_id);
/* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */
- int (*get_casttype) (uint16 skill_id);
- int (*get_casttype2) (uint16 index);
+ int (*get_casttype) (int skill_id);
+ int (*get_casttype2) (int index);
bool (*is_combo) (int skill_id);
int (*name2id) (const char* name);
int (*isammotype) (struct map_session_data *sd, int skill_id);
@@ -1937,7 +2012,7 @@ struct skill_interface {
int (*addtimerskill) (struct block_list *src, int64 tick, int target, int x, int y, uint16 skill_id, uint16 skill_lv, int type, int flag);
int (*additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick);
int (*counter_additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick);
- int (*blown) (struct block_list* src, struct block_list* target, int count, int8 dir, int flag);
+ int (*blown) (struct block_list* src, struct block_list* target, int count, enum unit_dir dir, int flag);
int (*break_equip) (struct block_list *bl, unsigned short where, int rate, int flag);
int (*strip_equip) (struct block_list *bl, unsigned short where, int rate, int lv, int time);
struct skill_unit_group* (*id2group) (int group_id);
@@ -1975,12 +2050,16 @@ struct skill_interface {
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_unknown) (uint16 skill_id, struct map_session_data *sd);
int (*not_ok_hom) (uint16 skill_id, struct homun_data *hd);
+ int (*not_ok_hom_unknown) (uint16 skill_id, struct homun_data *hd);
int (*not_ok_mercenary) (uint16 skill_id, struct mercenary_data *md);
+ void (*validate_autocast_data) (struct map_session_data *sd, int skill_id, int skill_lv);
int (*chastle_mob_changetarget) (struct block_list *bl,va_list ap);
int (*can_produce_mix) ( struct map_session_data *sd, int nameid, int trigger, int qty);
int (*produce_mix) ( struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty );
int (*arrow_create) ( struct map_session_data *sd,int nameid);
+ void (*castend_type) (int type, struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
int (*castend_nodamage_id) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
int (*castend_damage_id) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick,int flag);
int (*castend_pos2) (struct block_list *src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
@@ -2000,6 +2079,7 @@ struct skill_interface {
int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick);
int (*cell_overlap) (struct block_list *bl, va_list ap);
int (*timerskill) (int tid, int64 tick, int id, intptr_t data);
+ void (*trap_do_splash) (struct block_list *bl, uint16 skill_id, uint16 skill_lv, int bl_flag, int64 tick);
int (*trap_splash) (struct block_list *bl, va_list ap);
int (*check_condition_mercenary) (struct block_list *bl, int skill_id, int lv, int type);
struct skill_unit_group *(*locate_element_field) (struct block_list *bl);
@@ -2015,14 +2095,15 @@ struct skill_interface {
bool (*dance_switch) (struct skill_unit* su, int flag);
int (*check_condition_char_sub) (struct block_list *bl, va_list ap);
int (*check_condition_mob_master_sub) (struct block_list *bl, va_list ap);
- void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y);
- void (*brandishspear_dir) (struct square* tc, uint8 dir, int are);
- int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv );
+ void (*brandishspear_first) (struct square *tc, enum unit_dir dir, int16 x, int16 y);
+ void (*brandishspear_dir) (struct square* tc, enum unit_dir dir, int are);
+ int (*get_fixed_cast) (int skill_id, int skill_lv);
int (*sit_count) (struct block_list *bl, va_list ap);
int (*sit_in) (struct block_list *bl, va_list ap);
int (*sit_out) (struct block_list *bl, va_list ap);
void (*unitsetmapcell) (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag);
int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, int64 tick);
+ void (*unit_onplace_timer_unknown) (struct skill_unit *src, struct block_list *bl, int64 *tick);
int (*unit_effect) (struct block_list* bl, va_list ap);
int (*unit_timer_sub_onplace) (struct block_list* bl, va_list ap);
int (*unit_move_sub) (struct block_list* bl, va_list ap);
@@ -2033,17 +2114,33 @@ struct skill_interface {
int (*unit_timer) (int tid, int64 tick, int id, intptr_t data);
int (*unit_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*init_unit_layout) (void);
- bool (*parse_row_skilldb) (char* split[], int columns, int current);
- bool (*parse_row_requiredb) (char* split[], int columns, int current);
- bool (*parse_row_castdb) (char* split[], int columns, int current);
- bool (*parse_row_castnodexdb) (char* split[], int columns, int current);
- bool (*parse_row_unitdb) (char* split[], int columns, int current);
+ void (*init_unit_layout_unknown) (int skill_idx, int pos);
+ void (*validate_hittype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_skilltype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_attacktype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_element) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_skillinfo) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_damagetype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_castnodex) (struct config_setting_t *conf, struct s_skill_db *sk, bool delay);
+ void (*validate_weapontype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_ammotype) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_state) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_item_requirements) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_unit_target) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_unit_flag) (struct config_setting_t *conf, struct s_skill_db *sk);
+ void (*validate_additional_fields) (struct config_setting_t *conf, struct s_skill_db *sk);
+ bool (*validate_skilldb) (struct s_skill_db *skt, const char *source);
+ int (*validate_weapontype_sub) (const char *type, bool on, struct s_skill_db *sk);
+ int (*validate_ammotype_sub) (const char *type, bool on, struct s_skill_db *sk);
+ int (*validate_unit_flag_sub) (const char *type, bool on, struct s_skill_db *sk);
+ bool (*read_skilldb) (const char *filename);
+ void (*config_set_level) (struct config_setting_t *conf, int *arr);
+ void (*level_set_value) (int *arr, int value);
bool (*parse_row_producedb) (char* split[], int columns, int current);
bool (*parse_row_createarrowdb) (char* split[], int columns, int current);
bool (*parse_row_abradb) (char* split[], int columns, int current);
bool (*parse_row_spellbookdb) (char* split[], int columns, int current);
bool (*parse_row_magicmushroomdb) (char* split[], int column, int current);
- bool (*parse_row_reproducedb) (char* split[], int column, int current);
bool (*parse_row_improvisedb) (char* split[], int columns, int current);
bool (*parse_row_changematerialdb) (char* split[], int columns, int current);
/* save new unit skill */
@@ -2076,7 +2173,7 @@ struct skill_interface {
void (*attack_display_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage);
int (*attack_copy_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag);
int (*attack_dir_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag);
- void (*attack_blow_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, int8 *dir);
+ void (*attack_blow_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, enum unit_dir *dir);
void (*attack_post_unknown) (int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag);
bool (*timerskill_dead_unknown) (struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl);
void (*timerskill_target_unknown) (int tid, int64 tick, struct block_list *src, struct block_list *target, struct unit_data *ud, struct skill_timerskill *skl);
@@ -2096,10 +2193,14 @@ struct skill_interface {
int (*check_condition_castbegin_mount_unknown) (struct status_change *sc, uint16 *skill_id);
int (*check_condition_castbegin_madogear_unknown) (struct status_change *sc, uint16 *skill_id);
int (*check_condition_castbegin_unknown) (struct status_change *sc, uint16 *skill_id);
- void (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv);
+ bool (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv);
bool (*get_requirement_off_unknown) (struct status_change *sc, uint16 *skill_id);
bool (*get_requirement_item_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i);
void (*get_requirement_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req);
+ int (*splash_target) (struct block_list* bl);
+ int (*check_npc_chaospanic) (struct block_list *bl, va_list args);
+ int (*count_wos) (struct block_list *bl, va_list ap);
+ int (*get_linked_song_dance_id) (int skill_id);
};
#ifdef HERCULES_CORE
diff --git a/src/map/status.c b/src/map/status.c
index a8771c0a5..9a274c080 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include "map/battle.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/elemental.h"
#include "map/guild.h"
@@ -37,6 +38,7 @@
#include "map/path.h"
#include "map/pc.h"
#include "map/pet.h"
+#include "map/refine.h"
#include "map/script.h"
#include "map/skill.h"
#include "map/skill.h"
@@ -60,17 +62,18 @@
#include <string.h>
#include <time.h>
-struct status_interface status_s;
-struct s_status_dbs statusdbs;
+static struct status_interface status_s;
+static struct s_status_dbs statusdbs;
struct status_interface *status;
/**
-* Returns the status change associated with a skill.
-* @param skill The skill to look up
-* @return The status registered for this skill
-**/
-sc_type status_skill2sc(int skill_id) {
+ * Returns the status change associated with a skill.
+ * @param skill The skill to look up
+ * @return The status registered for this skill
+ */
+static sc_type status_skill2sc(int skill_id)
+{
int idx;
if( (idx = skill->get_index(skill_id)) == 0 ) {
ShowError("status_skill2sc: Unsupported skill id %d\n", skill_id);
@@ -80,12 +83,12 @@ sc_type status_skill2sc(int skill_id) {
}
/**
-* Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change.
-* Utilized for various duration lookups. Use with caution!
-* @param sc The status to look up
-* @return A skill associated with the status
-**/
-int status_sc2skill(sc_type sc)
+ * Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change.
+ * Utilized for various duration lookups. Use with caution!
+ * @param sc The status to look up
+ * @return A skill associated with the status
+ */
+static int status_sc2skill(sc_type sc)
{
if( sc < 0 || sc >= SC_MAX ) {
ShowError("status_sc2skill: Unsupported status change id %d\n", sc);
@@ -96,11 +99,11 @@ int status_sc2skill(sc_type sc)
}
/**
-* Returns the status calculation flag associated with a given status change.
-* @param sc The status to look up
-* @return The scb_flag registered for this status (see enum scb_flag)
-**/
-unsigned int status_sc2scb_flag(sc_type sc)
+ * Returns the status calculation flag associated with a given status change.
+ * @param sc The status to look up
+ * @return The scb_flag registered for this status (see enum scb_flag)
+ */
+static unsigned int status_sc2scb_flag(sc_type sc)
{
if( sc < 0 || sc >= SC_MAX ) {
ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc);
@@ -111,21 +114,29 @@ unsigned int status_sc2scb_flag(sc_type sc)
}
/**
-* Returns the bl types which require a status change packet to be sent for a given client status identifier.
-* @param type The client-side status identifier to look up (see enum si_type)
-* @return The bl types relevant to the type (see enum bl_type)
-**/
-int status_type2relevant_bl_types(int type)
-{
- if( type < 0 || type >= SI_MAX ) {
- ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type);
+ * Returns the bl types which require a status change packet to be sent for a given client status identifier.
+ * @param type status identifier to look up (see enum sc_type)
+ * @return The bl types relevant to the type (see enum bl_type)
+ */
+static int status_get_sc_relevant_bl_types(enum sc_type type)
+{
+ if (type < 0 || type >= SC_MAX) {
+ ShowError("status_get_sc_relevant_bl_types: Unsupported type %d\n", type);
return BL_NUL;
}
- return status->dbs->RelevantBLTypes[type];
+ return status->dbs->IconChangeTable[type].relevant_bl_types;
}
-static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
+static int status_get_sc_icon(enum sc_type type)
+{
+ Assert_retr(SI_BLANK, type >= SC_NONE && type < SC_MAX);
+
+ return status->dbs->IconChangeTable[type].id;
+}
+
+static void status_set_sc(uint16 skill_id, sc_type sc, unsigned int flag)
+{
uint16 idx;
if( (idx = skill->get_index(skill_id)) == 0 ) {
ShowError("set_sc: Unsupported skill id %d\n", skill_id);
@@ -138,112 +149,110 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
if( status->dbs->SkillChangeTable[sc] == 0 )
status->dbs->SkillChangeTable[sc] = skill_id;
- if( status->dbs->IconChangeTable[sc] == SI_BLANK )
- status->dbs->IconChangeTable[sc] = icon;
status->dbs->ChangeFlagTable[sc] |= flag;
if( status->dbs->Skill2SCTable[idx] == SC_NONE )
status->dbs->Skill2SCTable[idx] = sc;
}
-void initChangeTables(void) {
-#define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE)
+static void initChangeTables(void)
+{
+#define add_sc(skill,sc) status->set_sc((skill),(sc),SCB_NONE)
// indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units
-#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0)
+#define set_sc_with_vfx(skill, sc, flag) do { status->set_sc((skill), (sc), (flag)); status->dbs->IconChangeTable[sc].relevant_bl_types |= BL_SCEFFECT; } while(0)
int i;
- for (i = 0; i < SC_MAX; i++)
- status->dbs->IconChangeTable[i] = SI_BLANK;
-
- for (i = 0; i < MAX_SKILL; i++)
+ for (i = 0; i < MAX_SKILL_DB; i++)
status->dbs->Skill2SCTable[i] = SC_NONE;
- for (i = 0; i < SI_MAX; i++)
- status->dbs->RelevantBLTypes[i] = BL_PC;
+ for (i = 0; i < SC_MAX; i++) {
+ status->dbs->IconChangeTable[i].id = SI_BLANK;
+ status->dbs->IconChangeTable[i].relevant_bl_types = BL_PC;
+ }
memset(status->dbs->SkillChangeTable, 0, sizeof(status->dbs->SkillChangeTable));
memset(status->dbs->ChangeFlagTable, 0, sizeof(status->dbs->ChangeFlagTable));
memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType));
//First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex]
- set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
- set_sc( NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
- set_sc( NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE );
- set_sc( NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE );
- set_sc( NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
- set_sc( NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED );
- set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE );
- set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE );
- set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE );
- set_sc( NPC_BLEEDING , SC_BLOODING , SI_BLOODING , SCB_REGEN );
- set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
+ status->set_sc( NPC_PETRIFYATTACK , SC_STONE , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_WIDEFREEZE , SC_FREEZE , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_STUNATTACK , SC_STUN , SCB_NONE );
+ status->set_sc( NPC_SLEEPATTACK , SC_SLEEP , SCB_NONE );
+ status->set_sc( NPC_POISON , SC_POISON , SCB_DEF2|SCB_REGEN );
+ status->set_sc( NPC_CURSEATTACK , SC_CURSE , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED );
+ status->set_sc( NPC_SILENCEATTACK , SC_SILENCE , SCB_NONE );
+ status->set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SCB_NONE );
+ status->set_sc( NPC_BLINDATTACK , SC_BLIND , SCB_HIT|SCB_FLEE );
+ status->set_sc( NPC_BLEEDING , SC_BLOODING , SCB_REGEN );
+ status->set_sc( NPC_POISON , SC_DPOISON , SCB_DEF2|SCB_REGEN );
//The main status definitions
add_sc( SM_BASH , SC_STUN );
- set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ status->set_sc( SM_PROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
add_sc( SM_MAGNUM , SC_SUB_WEAPONPROPERTY );
- set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD );
+ status->set_sc( SM_ENDURE , SC_ENDURE , SCB_MDEF|SCB_DSPD );
add_sc( MG_SIGHT , SC_SIGHT );
add_sc( MG_SAFETYWALL , SC_SAFETYWALL );
add_sc( MG_FROSTDIVER , SC_FREEZE );
add_sc( MG_STONECURSE , SC_STONE );
add_sc( AL_RUWACH , SC_RUWACH );
add_sc( AL_PNEUMA , SC_PNEUMA );
- set_sc( AL_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( AL_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( AL_CRUCIS , SC_CRUCIS , SI_CRUCIS , SCB_DEF );
- set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 );
- set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_AGI|SCB_DEX );
- set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED );
+ status->set_sc( AL_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( AL_DECAGI , SC_DEC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( AL_CRUCIS , SC_CRUCIS , SCB_DEF );
+ status->set_sc( AL_ANGELUS , SC_ANGELUS , SCB_DEF2 );
+ status->set_sc( AL_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SCB_AGI|SCB_DEX );
+ status->set_sc( TF_HIDING , SC_HIDING , SCB_SPEED );
add_sc( TF_POISON , SC_POISON );
- set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD );
+ status->set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SCB_ASPD );
add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER );
- set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
+ status->set_sc( PR_IMPOSITIO , SC_IMPOSITIO ,
#ifdef RENEWAL
SCB_NONE );
#else
SCB_WATK );
#endif
- set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE );
- set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE );
- set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
- set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN );
- set_sc( PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
- set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
- set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK );
+ status->set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SCB_NONE );
+ status->set_sc( PR_ASPERSIO , SC_ASPERSIO , SCB_ATK_ELE );
+ status->set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SCB_DEF_ELE );
+ status->set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SCB_REGEN );
+ status->set_sc( PR_KYRIE , SC_KYRIE , SCB_NONE );
+ status->set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SCB_REGEN );
+ status->set_sc( PR_GLORIA , SC_GLORIA , SCB_LUK );
add_sc( PR_LEXDIVINA , SC_SILENCE );
- set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SI_LEXAETERNA , SCB_NONE );
+ status->set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SCB_NONE );
add_sc( WZ_METEOR , SC_STUN );
add_sc( WZ_VERMILION , SC_BLIND );
add_sc( WZ_FROSTNOVA , SC_FREEZE );
add_sc( WZ_STORMGUST , SC_FREEZE );
- set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED );
- set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD );
- set_sc( BS_WEAPONPERFECT , SC_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 );
+ status->set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED );
+ status->set_sc( BS_ADRENALINE , SC_ADRENALINE , SCB_ASPD );
+ status->set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SCB_NONE );
+ status->set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SCB_NONE );
+ status->set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SCB_REGEN );
add_sc( HT_LANDMINE , SC_STUN );
- set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE );
+ status->set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SCB_NONE );
add_sc( HT_SANDMAN , SC_SLEEP );
add_sc( HT_FLASHER , SC_BLIND );
add_sc( HT_FREEZINGTRAP , SC_FREEZE );
- set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED );
+ status->set_sc( AS_CLOAKING , SC_CLOAKING , SCB_CRI|SCB_SPEED );
add_sc( AS_SONICBLOW , SC_STUN );
- set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SI_ENCHANTPOISON, SCB_ATK_ELE );
- set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE );
+ status->set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SCB_ATK_ELE );
+ status->set_sc( AS_POISONREACT , SC_POISONREACT , SCB_NONE );
add_sc( AS_VENOMDUST , SC_POISON );
add_sc( AS_SPLASHER , SC_SPLASHER );
- set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN );
- set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
+ status->set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SCB_REGEN );
+ status->set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SCB_NONE );
add_sc( TF_SPRINKLESAND , SC_BLIND );
add_sc( TF_THROWSTONE , SC_STUN );
- set_sc( MC_LOUD , SC_SHOUT , SI_SHOUT , SCB_STR );
- set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE );
- set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE );
+ status->set_sc( MC_LOUD , SC_SHOUT , SCB_STR );
+ status->set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SCB_NONE );
+ status->set_sc( NPC_EMOTION , SC_MODECHANGE , SCB_MODE );
add_sc( NPC_EMOTION_ON , SC_MODECHANGE );
- set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SI_ARMOR_PROPERTY , SCB_DEF_ELE );
+ status->set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SCB_DEF_ELE );
add_sc( NPC_CHANGEWATER , SC_ARMOR_PROPERTY );
add_sc( NPC_CHANGEGROUND , SC_ARMOR_PROPERTY );
add_sc( NPC_CHANGEFIRE , SC_ARMOR_PROPERTY );
@@ -260,184 +269,184 @@ void initChangeTables(void) {
add_sc( NPC_CURSEATTACK , SC_CURSE );
add_sc( NPC_SLEEPATTACK , SC_SLEEP );
add_sc( NPC_MAGICALATTACK , SC_MAGICALATTACK );
- set_sc( NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF );
+ status->set_sc( NPC_KEEPING , SC_KEEPING , SCB_DEF );
add_sc( NPC_DARKBLESSING , SC_COMA );
- set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF );
+ status->set_sc( NPC_BARRIER , SC_BARRIER , SCB_MDEF|SCB_DEF );
add_sc( NPC_DEFENDER , SC_ARMOR );
add_sc( NPC_LICK , SC_STUN );
- set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE );
+ status->set_sc( NPC_HALLUCINATION , SC_ILLUSION , SCB_NONE );
add_sc( NPC_REBIRTH , SC_REBIRTH );
add_sc( RG_RAID , SC_STUN );
#ifdef RENEWAL
add_sc( RG_RAID , SC_RAID );
add_sc( RG_BACKSTAP , SC_STUN );
#endif
- set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SI_NOEQUIPWEAPON , SCB_WATK );
- set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SI_NOEQUIPSHIELD , SCB_DEF );
- set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SI_NOEQUIPARMOR , SCB_VIT );
- set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SI_NOEQUIPHELM , SCB_INT );
+ status->set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SCB_WATK );
+ status->set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SCB_DEF );
+ status->set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SCB_VIT );
+ status->set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SCB_INT );
add_sc( AM_ACIDTERROR , SC_BLOODING );
- set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SI_PROTECTWEAPON , SCB_NONE );
- set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SI_PROTECTSHIELD , SCB_NONE );
- set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SI_PROTECTARMOR , SCB_NONE );
- set_sc( AM_CP_HELM , SC_PROTECTHELM , SI_PROTECTHELM , SCB_NONE );
- set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
+ status->set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SCB_NONE );
+ status->set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SCB_NONE );
+ status->set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SCB_NONE );
+ status->set_sc( AM_CP_HELM , SC_PROTECTHELM , SCB_NONE );
+ status->set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SCB_NONE );
add_sc( CR_SHIELDCHARGE , SC_STUN );
- set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
+ status->set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SCB_NONE );
add_sc( CR_HOLYCROSS , SC_BLIND );
add_sc( CR_GRANDCROSS , SC_BLIND );
add_sc( CR_DEVOTION , SC_DEVOTION );
- set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL );
- set_sc( CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
- set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE );
- set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED );
+ status->set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SCB_ALL );
+ status->set_sc( CR_DEFENDER , SC_DEFENDER , SCB_SPEED|SCB_ASPD );
+ status->set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE );
+ status->set_sc( MO_STEELBODY , SC_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED );
add_sc( MO_BLADESTOP , SC_BLADESTOP_WAIT );
add_sc( MO_BLADESTOP , SC_BLADESTOP );
- set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN );
- set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN );
+ status->set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN );
+ status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SCB_REGEN );
#ifdef RENEWAL
- set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE );
+ status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SCB_NONE );
#endif
add_sc( SA_MAGICROD , SC_MAGICROD );
- set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE );
- set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SI_PROPERTYFIRE , SCB_ATK_ELE );
- set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SI_PROPERTYWATER , SCB_ATK_ELE );
- set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SI_PROPERTYWIND , SCB_ATK_ELE );
- set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SI_PROPERTYGROUND , SCB_ATK_ELE );
- set_sc( SA_VOLCANO , SC_VOLCANO , SI_GROUNDMAGIC , SCB_WATK );
- set_sc( SA_DELUGE , SC_DELUGE , SI_GROUNDMAGIC , SCB_MAXHP );
- set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_GROUNDMAGIC , SCB_FLEE );
+ status->set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SCB_NONE );
+ status->set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SCB_ATK_ELE );
+ status->set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SCB_ATK_ELE );
+ status->set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SCB_ATK_ELE );
+ status->set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SCB_ATK_ELE );
+ status->set_sc( SA_VOLCANO , SC_VOLCANO , SCB_WATK );
+ status->set_sc( SA_DELUGE , SC_DELUGE , SCB_MAXHP );
+ status->set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SCB_FLEE );
add_sc( SA_REVERSEORCISH , SC_ORCISH );
add_sc( SA_COMA , SC_COMA );
- set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN );
+ status->set_sc( BD_ENCORE , SC_DANCING , SCB_SPEED|SCB_REGEN );
add_sc( BD_RICHMANKIM , SC_RICHMANKIM );
- set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2 );
- set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF );
- set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK );
+ status->set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SCB_DEF2 );
+ status->set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SCB_WATK|SCB_DEF );
+ status->set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SCB_WATK );
add_sc( BD_ROKISWEIL , SC_ROKISWEIL );
add_sc( BD_INTOABYSS , SC_INTOABYSS );
- set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL );
+ status->set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SCB_ALL );
add_sc( BA_FROSTJOKER , SC_FREEZE );
- set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 );
- set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD );
+ status->set_sc( BA_WHISTLE , SC_WHISTLE , SCB_FLEE|SCB_FLEE2 );
+ status->set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SCB_ASPD );
add_sc( BA_POEMBRAGI , SC_POEMBRAGI );
- set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP );
+ status->set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SCB_MAXHP );
add_sc( DC_SCREAM , SC_STUN );
- set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT );
- set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD );
- set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI );
- set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SI_BLANK , SCB_ALL );
+ status->set_sc( DC_HUMMING , SC_HUMMING , SCB_HIT );
+ status->set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SCB_SPEED|SCB_ASPD );
+ status->set_sc( DC_FORTUNEKISS , SC_FORTUNE , SCB_CRI );
+ status->set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SCB_ALL );
add_sc( NPC_DARKCROSS , SC_BLIND );
add_sc( NPC_GRANDDARKNESS , SC_BLIND );
- set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE );
- set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE );
- set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE );
- set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SI_PROPERTYUNDEAD , SCB_DEF_ELE );
- set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT );
- set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE );
+ status->set_sc( NPC_STOP , SC_STOP , SCB_NONE );
+ status->set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SCB_NONE );
+ status->set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SCB_NONE );
+ status->set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SCB_DEF_ELE );
+ status->set_sc( NPC_POWERUP , SC_INCHITRATE , SCB_HIT );
+ status->set_sc( NPC_AGIUP , SC_INCFLEERATE , SCB_FLEE );
add_sc( NPC_INVISIBLE , SC_CLOAKING );
- set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE );
- set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
+ status->set_sc( LK_AURABLADE , SC_AURABLADE , SCB_NONE );
+ status->set_sc( LK_PARRYING , SC_PARRYING , SCB_NONE );
#ifndef RENEWAL
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
+ status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
#else
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_HIT|SCB_DEF);
+ status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SCB_HIT|SCB_DEF);
#endif
- set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN );
- set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
- set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
+ status->set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SCB_REGEN );
+ status->set_sc( LK_BERSERK , SC_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
+ status->set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SCB_NONE );
add_sc( HP_BASILICA , SC_BASILICA );
- set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK );
+ status->set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SCB_MATK );
add_sc( PA_SACRIFICE , SC_SACRIFICE );
- set_sc( PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD );
+ status->set_sc( PA_GOSPEL , SC_GOSPEL , SCB_SPEED|SCB_ASPD );
add_sc( PA_GOSPEL , SC_SCRESIST );
add_sc( CH_TIGERFIST , SC_STOP );
- set_sc( ASC_EDP , SC_EDP , SI_EDP , SCB_NONE );
- set_sc( SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT );
- set_sc( SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED );
- set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE );
- set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED );
- set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED );
- set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SI_SWORDREJECT , SCB_NONE );
+ status->set_sc( ASC_EDP , SC_EDP , SCB_NONE );
+ status->set_sc( SN_SIGHT , SC_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT );
+ status->set_sc( SN_WINDWALK , SC_WINDWALK , SCB_FLEE|SCB_SPEED );
+ status->set_sc( WS_MELTDOWN , SC_MELTDOWN , SCB_NONE );
+ status->set_sc( WS_CARTBOOST , SC_CARTBOOST , SCB_SPEED );
+ status->set_sc( ST_CHASEWALK , SC_CHASEWALK , SCB_SPEED );
+ status->set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SCB_NONE );
add_sc( ST_REJECTSWORD , SC_AUTOCOUNTER );
- set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SI_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( CG_MARIONETTE , SC_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( LK_SPIRALPIERCE , SC_STOP );
add_sc( LK_HEADCRUSH , SC_BLOODING );
- set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD );
+ status->set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD );
add_sc( HW_NAPALMVULCAN , SC_CURSE );
- set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 );
+ status->set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SCB_MATK|SCB_MDEF2 );
add_sc( PF_MEMORIZE , SC_MEMORIZE );
add_sc( PF_FOGWALL , SC_FOGWALL );
- set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE );
- set_sc( WE_BABY , SC_BABY , SI_PROTECTEXP , SCB_NONE );
- set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD );
- set_sc( TK_RUN , SC_STRUP , SI_STRUP , SCB_STR );
- set_sc( TK_READYSTORM , SC_STORMKICK_READY , SI_STORMKICK_ON , SCB_NONE );
- set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SI_DOWNKICK_ON , SCB_NONE );
+ status->set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SCB_FLEE );
+ status->set_sc( WE_BABY , SC_BABY , SCB_NONE );
+ status->set_sc( TK_RUN , SC_RUN , SCB_SPEED|SCB_DSPD );
+ status->set_sc( TK_RUN , SC_STRUP , SCB_STR );
+ status->set_sc( TK_READYSTORM , SC_STORMKICK_READY , SCB_NONE );
+ status->set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SCB_NONE );
add_sc( TK_DOWNKICK , SC_STUN );
- set_sc( TK_READYTURN , SC_TURNKICK_READY , SI_TURNKICK_ON , SCB_NONE );
- set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SI_COUNTER_ON , SCB_NONE );
- set_sc( TK_DODGE , SC_DODGE_READY , SI_DODGE_ON , SCB_NONE );
- set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE );
+ status->set_sc( TK_READYTURN , SC_TURNKICK_READY , SCB_NONE );
+ status->set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SCB_NONE );
+ status->set_sc( TK_DODGE , SC_DODGE_READY , SCB_NONE );
+ status->set_sc( TK_SPTIME , SC_EARTHSCROLL , SCB_NONE );
add_sc( TK_SEVENWIND , SC_TK_SEVENWIND );
- set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SI_PROPERTYTELEKINESIS , SCB_ATK_ELE );
- set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SI_PROPERTYDARK , SCB_ATK_ELE );
- set_sc( SG_SUN_WARM , SC_WARM , SI_SG_SUN_WARM , SCB_NONE );
+ status->set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SCB_ATK_ELE );
+ status->set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SCB_ATK_ELE );
+ status->set_sc( SG_SUN_WARM , SC_WARM , SCB_NONE );
add_sc( SG_MOON_WARM , SC_WARM );
add_sc( SG_STAR_WARM , SC_WARM );
- set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 );
- set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE );
- set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD );
+ status->set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SCB_DEF2 );
+ status->set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SCB_FLEE );
+ status->set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SCB_ASPD );
add_sc( SG_FRIEND , SC_SKILLRATE_UP );
- set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL );
- set_sc( SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED );
- set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD );
- set_sc( SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE );
- set_sc( SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE );
- set_sc( SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE );
- set_sc( SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE );
+ status->set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SCB_ALL );
+ status->set_sc( SG_FUSION , SC_FUSION , SCB_SPEED );
+ status->set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SCB_ASPD );
+ status->set_sc( SL_KAIZEL , SC_KAIZEL , SCB_NONE );
+ status->set_sc( SL_KAAHI , SC_KAAHI , SCB_NONE );
+ status->set_sc( SL_KAUPE , SC_KAUPE , SCB_NONE );
+ status->set_sc( SL_KAITE , SC_KAITE , SCB_NONE );
add_sc( SL_STUN , SC_STUN );
- set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED );
- set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 );
- set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD );
- set_sc( SL_SMA , SC_SMA_READY , SI_SMA_READY , SCB_NONE );
- set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
- set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE );
- set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SI_DOUBLECASTING , SCB_NONE );
- set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD );
+ status->set_sc( SL_SWOO , SC_SWOO , SCB_SPEED );
+ status->set_sc( SL_SKE , SC_SKE , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 );
+ status->set_sc( SL_SKA , SC_SKA , SCB_DEF|SCB_MDEF|SCB_ASPD );
+ status->set_sc( SL_SMA , SC_SMA_READY , SCB_NONE );
+ status->set_sc( SM_SELFPROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ status->set_sc( ST_PRESERVE , SC_PRESERVE , SCB_NONE );
+ status->set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SCB_NONE );
+ status->set_sc( HW_GRAVITATION , SC_GRAVITATION , SCB_ASPD );
add_sc( WS_CARTTERMINATION , SC_STUN );
- set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SI_OVERTHRUSTMAX , SCB_NONE );
- set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD );
+ status->set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SCB_NONE );
+ status->set_sc( CG_LONGINGFREEDOM , SC_LONGING , SCB_SPEED|SCB_ASPD );
add_sc( CG_HERMODE , SC_HERMODE );
- set_sc( CG_TAROTCARD , SC_TAROTCARD , SI_TAROTCARD , SCB_NONE );
- set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE );
- set_sc( SL_HIGH , SC_SOULLINK , SI_SOULLINK , SCB_ALL );
- set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SI_ONEHANDQUICKEN , SCB_ASPD );
- set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 );
+ status->set_sc( CG_TAROTCARD , SC_TAROTCARD , SCB_NONE );
+ status->set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SCB_ATK_ELE );
+ status->set_sc( SL_HIGH , SC_SOULLINK , SCB_ALL );
+ status->set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SCB_ASPD );
+ status->set_sc( GS_FLING , SC_FLING , SCB_DEF|SCB_DEF2 );
add_sc( GS_CRACKER , SC_STUN );
add_sc( GS_DISARM , SC_NOEQUIPWEAPON );
add_sc( GS_PIERCINGSHOT , SC_BLOODING );
- set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_ASPD
+ status->set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SCB_ASPD
#ifndef RENEWAL
|SCB_BATK );
#else
);
#endif
- set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE );
- set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT );
- set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD
+ status->set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE );
+ status->set_sc( GS_INCREASING , SC_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT );
+ status->set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD
#ifndef RENEWAL
|SCB_BATK );
#else
);
#endif
- set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE );
- set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED );
+ status->set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SCB_NONE );
+ status->set_sc( NJ_SUITON , SC_NJ_SUITON , SCB_AGI|SCB_SPEED );
add_sc( NJ_HYOUSYOURAKU , SC_FREEZE );
- set_sc( NJ_NEN , SC_NJ_NEN , SI_NJ_NEN , SCB_STR|SCB_INT );
- set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SI_NJ_UTSUSEMI , SCB_NONE );
- set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SI_NJ_BUNSINJYUTSU , SCB_DYE );
+ status->set_sc( NJ_NEN , SC_NJ_NEN , SCB_STR|SCB_INT );
+ status->set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SCB_NONE );
+ status->set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SCB_DYE );
add_sc( NPC_ICEBREATH , SC_FREEZE );
add_sc( NPC_ACIDBREATH , SC_POISON );
@@ -451,202 +460,202 @@ void initChangeTables(void) {
add_sc( NPC_WIDESIGHT , SC_SIGHT );
add_sc( NPC_EVILLAND , SC_BLIND );
add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR );
- set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE );
- set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE );
- set_sc( NPC_STONESKIN , SC_STONESKIN , SI_BLANK , SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_SLOWCAST , SC_SLOWCAST , SCB_NONE );
+ status->set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SCB_NONE );
+ status->set_sc( NPC_STONESKIN , SC_STONESKIN , SCB_DEF|SCB_MDEF );
add_sc( NPC_ANTIMAGIC , SC_STONESKIN );
add_sc( NPC_WIDECURSE , SC_CURSE );
add_sc( NPC_WIDESTUN , SC_STUN );
- set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
- set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
- set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED );
- set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED );
+ status->set_sc( NPC_HELLPOWER , SC_HELLPOWER , SCB_NONE );
+ status->set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SCB_NONE );
+ status->set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SCB_SPEED );
+ status->set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SCB_SPEED );
- set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( CASH_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
+ status->set_sc( CASH_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( CASH_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SCB_NONE );
- set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE );
- set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF);
+ status->set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SCB_NONE );
+ status->set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF);
- set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE );
- set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
- set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
- set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SI_WZ_SIGHTBLASTER , SCB_NONE );
- set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SI_DC_WINKCHARM , SCB_NONE );
+ status->set_sc( CR_SHRINK , SC_CR_SHRINK , SCB_NONE );
+ status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SCB_NONE );
+ status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SCB_FLEE );
+ status->set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SCB_NONE );
+ status->set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SCB_NONE );
add_sc( MO_BALKYOUNG , SC_STUN );
add_sc( SA_ELEMENTWATER , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTFIRE , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTGROUND , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTWIND , SC_ARMOR_PROPERTY );
- set_sc( HLIF_AVOID , SC_HLIF_AVOID , SI_BLANK , SCB_SPEED );
- set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SI_BLANK , SCB_VIT|SCB_INT );
- set_sc( HFLI_FLEET , SC_HLIF_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK );
- set_sc( HFLI_SPEED , SC_HLIF_SPEED , SI_BLANK , SCB_FLEE );
- set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SI_BLANK , SCB_DEF );
- set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
+ status->set_sc( HLIF_AVOID , SC_HLIF_AVOID , SCB_SPEED );
+ status->set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SCB_VIT|SCB_INT );
+ status->set_sc( HFLI_FLEET , SC_HLIF_FLEET , SCB_ASPD|SCB_BATK|SCB_WATK );
+ status->set_sc( HFLI_SPEED , SC_HLIF_SPEED , SCB_FLEE );
+ status->set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SCB_DEF );
+ status->set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , 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 );
+ status->set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SCB_NONE );
+ status->set_sc( MH_OVERED_BOOST , SC_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);
+ status->set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
+ status->set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
add_sc( MH_STEINWAND, SC_SAFETYWALL );
- 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);
- set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
+ status->set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
+ status->set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SCB_NONE);
+ status->set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SCB_NONE);
+ status->set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
add_sc(MH_LAVA_SLIDE, SC_BURNING);
- set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SI_NEEDLE_OF_PARALYZE, SCB_DEF2);
+ status->set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SCB_DEF2);
add_sc(MH_POISON_MIST, SC_BLIND);
- set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
+ status->set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SCB_ASPD);
- set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE );
+ status->set_sc( MH_SILENT_BREEZE , SC_SILENCE , 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 );
+ status->set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SCB_NONE );
+ status->set_sc( MH_TINDER_BREAKER , SC_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 );
+ status->set_sc( MER_PROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY );
add_sc( MER_SIGHT , SC_SIGHT );
- set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
+ status->set_sc( MER_DECAGI , SC_DEC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SCB_REGEN );
add_sc( MER_LEXDIVINA , SC_SILENCE );
add_sc( MA_LANDMINE , SC_STUN );
add_sc( MA_SANDMAN , SC_SLEEP );
add_sc( MA_FREEZINGTRAP , SC_FREEZE );
- set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
- set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
- set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
- set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
- set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
- set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
+ status->set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SCB_NONE );
+ status->set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SCB_NONE );
+ status->set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SCB_NONE );
+ status->set_sc( ML_DEFENDER , SC_DEFENDER , SCB_SPEED|SCB_ASPD );
+ status->set_sc( MS_PARRYING , SC_PARRYING , SCB_NONE );
+ status->set_sc( MS_BERSERK , SC_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
add_sc( ML_SPIRALPIERCE , SC_STOP );
- set_sc( MER_QUICKEN , SC_MER_QUICKEN , SI_BLANK , SCB_ASPD );
+ status->set_sc( MER_QUICKEN , SC_MER_QUICKEN , SCB_ASPD );
add_sc( ML_DEVOTION , SC_DEVOTION );
- set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
- set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( MER_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( MER_KYRIE , SC_KYRIE , SCB_NONE );
+ status->set_sc( MER_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( MER_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR );
- set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT );
- set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI );
- set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX );
+ status->set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SCB_STR );
+ status->set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SCB_VIT );
+ status->set_sc( GD_SOULCOLD , SC_SOULCOLD , SCB_AGI );
+ status->set_sc( GD_HAWKEYES , SC_HAWKEYES , SCB_DEX );
- set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN );
+ status->set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SCB_REGEN );
/**
* Rune Knight
**/
- set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE );
- set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
- set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
- set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
+ status->set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SCB_NONE );
+ status->set_sc( RK_DRAGONHOWLING , SC_FEAR , SCB_FLEE|SCB_HIT );
+ status->set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SCB_NONE );
+ status->set_sc( RK_WINDCUTTER , SC_FEAR , SCB_FLEE|SCB_HIT );
add_sc( RK_DRAGONBREATH , SC_BURNING );
- set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
- set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
- set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
- set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE );
- set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN );
- set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD );
- set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE );
- set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
+ status->set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SCB_NONE );
+ status->set_sc( RK_REFRESH , SC_REFRESH , SCB_NONE );
+ status->set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SCB_STR );
+ status->set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SCB_NONE );
+ status->set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SCB_REGEN );
+ status->set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD );
+ status->set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SCB_NONE );
+ status->set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SCB_NONE );
add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY );
/**
* GC Guillotine Cross
**/
- set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE );
- set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE );
- set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE );
- set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED );
- set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE );
- set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE );
- set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SI_DARKCROW , SCB_NONE );
+ set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SCB_NONE );
+ status->set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SCB_NONE );
+ status->set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SCB_NONE );
+ status->set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SCB_SPEED );
+ status->set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SCB_FLEE );
+ status->set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SCB_NONE );
+ set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SCB_NONE );
/**
* Arch Bishop
**/
- set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED );
+ status->set_sc( AB_ADORAMUS , SC_ADORAMUS , SCB_AGI|SCB_SPEED );
add_sc( AB_CLEMENTIA , SC_BLESSING );
add_sc( AB_CANTO , SC_INC_AGI );
- set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP );
+ status->set_sc( AB_EPICLESIS , SC_EPICLESIS , SCB_MAXHP );
add_sc( AB_PRAEFATIO , SC_KYRIE );
- set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE );
- set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT );
- set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK );
- set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN );
- set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE );
- set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE );
- set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE );
- set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE );
+ set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SCB_NONE );
+ status->set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SCB_VIT );
+ status->set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SCB_LUK );
+ status->set_sc( AB_RENOVATIO , SC_RENOVATIO , SCB_REGEN );
+ status->set_sc( AB_EXPIATIO , SC_EXPIATIO , SCB_ATK_ELE );
+ status->set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SCB_NONE );
+ status->set_sc( AB_SECRAMENT , SC_SECRAMENT , SCB_NONE );
+ status->set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SCB_NONE );
/**
* Warlock
**/
add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON );
- set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF );
- set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX );
- set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK);
- set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE );
- set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK );
+ set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF );
+ status->set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX );
+ status->set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SCB_MATK);
+ status->set_sc( WL_STASIS , SC_STASIS , SCB_NONE );
+ status->set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SCB_MATK );
/**
* Ranger
**/
- set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE );
- set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE );
- set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED );
- set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED );
+ status->set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SCB_NONE );
+ status->set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SCB_NONE );
+ status->set_sc( RA_WUGDASH , SC_WUGDASH , SCB_SPEED );
+ status->set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SCB_SPEED );
add_sc( RA_MAGENTATRAP , SC_ARMOR_PROPERTY );
add_sc( RA_COBALTTRAP , SC_ARMOR_PROPERTY );
add_sc( RA_MAIZETRAP , SC_ARMOR_PROPERTY );
add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY );
add_sc( RA_FIRINGTRAP , SC_BURNING );
add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY );
- set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
+ status->set_sc( RA_UNLIMIT , SC_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
/**
* Mechanic
**/
- set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED );
- set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED );
- set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE );
- set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE );
- set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
- set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
- set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
- set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
+ status->set_sc( NC_ACCELERATION , SC_ACCELERATION , SCB_SPEED );
+ status->set_sc( NC_HOVERING , SC_HOVERING , SCB_SPEED );
+ status->set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SCB_DEF_ELE );
+ status->set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SCB_FLEE );
+ status->set_sc( NC_ANALYZE , SC_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
+ status->set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SCB_NONE );
+ status->set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
+ status->set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SCB_NONE );
/**
* Royal Guard
**/
- set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
- set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP );
- set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
- set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF );
- set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
- set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
- set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
- set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
- set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE );
+ status->set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SCB_NONE );
+ status->set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SCB_MAXHP );
+ status->set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SCB_NONE );
+ status->set_sc( LG_PRESTIGE , SC_PRESTIGE , SCB_DEF );
+ status->set_sc( LG_BANDING , SC_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
+ status->set_sc( LG_PIETY , SC_BENEDICTIO , SCB_DEF_ELE );
+ status->set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SCB_DEF|SCB_ASPD );
+ status->set_sc( LG_INSPIRATION , SC_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
+ status->set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SCB_NONE );
/**
* Shadow Chaser
**/
- set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE );
- set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE );
- set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE );
- set_sc( SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD );
- set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE );
- set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE );
- set_sc( SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK );
- set_sc( SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED );
- set_sc( SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE );
- set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE );
- set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 );
- set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP );
- set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
- set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE );
+ status->set_sc( SC_REPRODUCE , SC__REPRODUCE , SCB_NONE );
+ status->set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SCB_NONE );
+ status->set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SCB_NONE );
+ status->set_sc( SC_BODYPAINT , SC__BODYPAINT , SCB_ASPD );
+ status->set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE );
+ status->set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SCB_NONE );
+ status->set_sc( SC_ENERVATION , SC__ENERVATION , SCB_BATK );
+ status->set_sc( SC_GROOMY , SC__GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED );
+ status->set_sc( SC_IGNORANCE , SC__IGNORANCE , SCB_NONE );
+ status->set_sc( SC_LAZINESS , SC__LAZINESS , SCB_FLEE );
+ status->set_sc( SC_UNLUCKY , SC__UNLUCKY , SCB_CRI|SCB_FLEE2 );
+ status->set_sc( SC_WEAKNESS , SC__WEAKNESS , SCB_FLEE2|SCB_MAXHP );
+ status->set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
+ set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SCB_NONE );
add_sc( SC_CHAOSPANIC , SC__CHAOS );
add_sc( SC_MAELSTROM , SC__MAELSTROM );
add_sc( SC_BLOODYLUST , SC_BERSERK );
@@ -656,113 +665,132 @@ 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 );
- set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
- 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_DEF2|SCB_REGEN );
- set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
+ status->set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SCB_NONE );
+ status->set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SCB_NONE );
+ set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SCB_NONE );
+ status->set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SCB_NONE );
+ status->set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
+ status->set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SCB_NONE );
+ status->set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
+ status->set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SCB_MAXHP|SCB_DEF2|SCB_REGEN );
+ status->set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SCB_WATK );
/**
* Wanderer / Minstrel
**/
- set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD );
- set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF );
- set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK );
- set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK );
- set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 );
- set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE);
- set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE );
- set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
- set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE );
- set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD );
- set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SI_SONG_OF_MANA , SCB_NONE );
- set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD );
- set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
- set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP );
- set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT );
- set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP );
- set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
- set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP );
+ status->set_sc( WA_SWING_DANCE , SC_SWING , SCB_SPEED|SCB_ASPD );
+ status->set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SCB_MDEF );
+ status->set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SCB_MATK );
+ status->set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SCB_WATK );
+ status->set_sc( MI_ECHOSONG , SC_ECHOSONG , SCB_DEF2 );
+ status->set_sc( MI_HARMONIZE , SC_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SCB_NONE);
+ set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SCB_NONE );
+ set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SCB_NONE );
+ status->set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SCB_NONE );
+ status->set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SCB_FLEE|SCB_ASPD );
+ status->set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SCB_NONE );
+ status->set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SCB_ASPD );
+ status->set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
+ status->set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SCB_MAXHP );
+ status->set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SCB_INT );
+ status->set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SCB_STR|SCB_CRI|SCB_MAXHP );
+ status->set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SCB_NONE );
+ status->set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SCB_MAXHP );
+ status->set_sc( WM_SEVERE_RAINSTORM , SC_NO_SWITCH_EQUIP , SCB_NONE );
/**
* Sorcerer
**/
- set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
- set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
- set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
- set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
- set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
- set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
+ status->set_sc( SO_FIREWALK , SC_PROPERTYWALK , SCB_NONE );
+ status->set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SCB_NONE );
+ status->set_sc( SO_SPELLFIST , SC_SPELLFIST , SCB_NONE );
+ set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
+ status->set_sc( SO_CLOUD_KILL , SC_POISON , SCB_NONE );
+ status->set_sc( SO_STRIKING , SC_STRIKING , SCB_WATK|SCB_CRI );
add_sc( SO_WARMER , SC_WARMER ); // At the moment, no icon on officials
- set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
- set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
- set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SCB_NONE );
+ status->set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SCB_NONE );
+ status->set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
add_sc( SO_ELEMENTAL_SHIELD , SC_SAFETYWALL );
/**
* Genetic
**/
- set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
- set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE );
- set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SI_BLOODSUCKER , SCB_NONE );
- set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE );
- set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE );
- set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
- set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
+ status->set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SCB_SPEED );
+ status->set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SCB_NONE );
+ set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SCB_NONE );
+ status->set_sc( GN_WALLOFTHORN , SC_STOP , SCB_NONE );
+ status->set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SCB_NONE );
+ status->set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
+ status->set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SCB_INT );
+
+ /**
+ * Summoner
+ */
+ status->set_sc(SU_HIDE, SC_SUHIDE, SCB_SPEED);
+ add_sc(SU_SCRATCH, SC_BLOODING);
+ status->set_sc(SU_STOOP, SC_SU_STOOP, SCB_NONE);
+ status->set_sc(SU_FRESHSHRIMP, SC_FRESHSHRIMP, SCB_NONE);
+ add_sc(SU_SV_STEMSPEAR, SC_BLOODING);
+ status->set_sc(SU_CN_POWDERING, SC_CATNIPPOWDER, SCB_WATK | SCB_SPEED | SCB_REGEN);
+ add_sc(SU_CN_METEOR, SC_CURSE);
+ set_sc_with_vfx(SU_SV_ROOTTWIST, SC_SV_ROOTTWIST, SCB_NONE);
+ add_sc(SU_SCAROFTAROU, SC_STUN );
+ status->set_sc(SU_SCAROFTAROU, SC_BITESCAR, SCB_NONE);
+ status->set_sc(SU_ARCLOUSEDASH, SC_ARCLOUSEDASH, SCB_AGI | SCB_SPEED);
+ add_sc(SU_LUNATICCARROTBEAT, SC_STUN);
+ status->set_sc(SU_TUNAPARTY, SC_TUNAPARTY, SCB_NONE);
+ status->set_sc(SU_BUNCHOFSHRIMP, SC_SHRIMP, SCB_BATK | SCB_MATK);
// Elemental Spirit summoner's 'side' status changes.
- set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
- set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
- set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE );
- set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL );
- set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_WATK|SCB_FLEE );
- set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
- set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL );
- set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE );
- set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP );
- set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL );
- set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED );
- set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK );
- set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK );
- set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK );
- set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK );
- set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK );
- set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK );
- set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_ASPD );
- set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD );
- set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD );
- set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP );
- set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP );
- set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP );
- set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
- set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
- set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
+ status->set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
+ status->set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SCB_ALL );
+ status->set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SCB_NONE );
+ status->set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SCB_ALL );
+ status->set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SCB_WATK|SCB_FLEE );
+ status->set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
+ status->set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SCB_ALL );
+ status->set_sc( EL_ZEPHYR , SC_ZEPHYR , SCB_FLEE );
+ status->set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP );
+ status->set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SCB_ALL );
+ status->set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED );
+ status->set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SCB_WATK );
+ status->set_sc( EL_HEATER , SC_HEATER_OPTION , SCB_WATK );
+ status->set_sc( EL_TROPIC , SC_TROPIC_OPTION , SCB_WATK );
+ status->set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SCB_MATK );
+ status->set_sc( EL_COOLER , SC_COOLER_OPTION , SCB_MATK );
+ status->set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SCB_MATK );
+ status->set_sc( EL_GUST , SC_GUST_OPTION , SCB_ASPD );
+ status->set_sc( EL_BLAST , SC_BLAST_OPTION , SCB_ASPD );
+ status->set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SCB_ASPD );
+ status->set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SCB_MAXHP );
+ status->set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SCB_MAXHP );
+ status->set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SCB_MAXHP );
+ status->set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SCB_ALL );
+ status->set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SCB_DEF );
+ status->set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SCB_SPEED );
add_sc( KO_YAMIKUMO , SC_HIDING );
- set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE );
+ set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SCB_NONE );
add_sc( KO_MAKIBISHI , SC_STUN );
- set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
- set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SCB_NONE );
+ status->set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( KO_JYUSATSU , SC_CURSE );
- set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE );
- set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK );
- set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE );
- set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE );
- set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE );
- set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK );
- set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE );
- set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
+ status->set_sc( KO_ZENKAI , SC_ZENKAI , SCB_NONE );
+ status->set_sc( KO_IZAYOI , SC_IZAYOI , SCB_MATK );
+ status->set_sc( KG_KYOMU , SC_KYOMU , SCB_NONE );
+ status->set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SCB_NONE );
+ status->set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SCB_NONE );
+ status->set_sc( OB_ZANGETSU , SC_ZANGETSU , SCB_MATK|SCB_BATK );
+ set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SCB_NONE );
+ status->set_sc( OB_OBOROGENSOU , SC_GENSOU , SCB_NONE );
- set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( ALL_REVERSEORCISH , SC_ORCISH );
- set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
+ status->set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SCB_REGEN );
add_sc( NPC_WIDEHEALTHFEAR , SC_FEAR );
add_sc( NPC_WIDEBODYBURNNING , SC_BURNING );
@@ -771,228 +799,24 @@ void initChangeTables(void) {
add_sc( NPC_WIDE_DEEP_SLEEP , SC_DEEP_SLEEP );
add_sc( NPC_WIDESIREN , SC_SIREN );
- set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT );
+ set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SCB_HIT );
// Storing the target job rather than simply SC_SOULLINK simplifies code later on.
- status->dbs->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
- status->dbs->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK,
- status->dbs->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR,
- status->dbs->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE,
- status->dbs->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER,
- status->dbs->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE,
- status->dbs->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT,
- status->dbs->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD,
- status->dbs->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST,
- status->dbs->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER,
- status->dbs->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE,
- status->dbs->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN,
- status->dbs->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH,
- status->dbs->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER,
- status->dbs->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER,
-
- // Status that don't have a skill associated.
- status->dbs->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50;
- status->dbs->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90;
- status->dbs->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1;
- status->dbs->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2;
- status->dbs->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3;
- status->dbs->IconChangeTable[SC_MOVHASTE_POTION] = SI_MOVHASTE_POTION;
- status->dbs->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY;
- status->dbs->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE;
- status->dbs->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY;
- status->dbs->IconChangeTable[SC_MOVESLOW_POTION] = SI_MOVESLOW_POTION;
- status->dbs->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR;
- status->dbs->IconChangeTable[SC_MIRACLE] = SI_SOULLINK;
- status->dbs->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE;
- status->dbs->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR;
- status->dbs->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI;
- status->dbs->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT;
- status->dbs->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT;
- status->dbs->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX;
- status->dbs->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK;
- status->dbs->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE;
- status->dbs->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT;
- status->dbs->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK;
- status->dbs->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF;
- status->dbs->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK;
- status->dbs->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF;
- status->dbs->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK;
- status->dbs->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK;
- status->dbs->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER;
- status->dbs->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER;
- status->dbs->IconChangeTable[SC_FOOD_CRITICALSUCCESSVALUE] = SI_FOOD_CRITICALSUCCESSVALUE;
- status->dbs->IconChangeTable[SC_MORA_BUFF] = SI_MORA_BUFF;
- status->dbs->IconChangeTable[SC_BUCHEDENOEL] = SI_BUCHEDENOEL;
- status->dbs->IconChangeTable[SC_PHI_DEMON] = SI_PHI_DEMON;
-
- // Cash Items
- status->dbs->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH;
- status->dbs->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH;
- status->dbs->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH;
- status->dbs->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH;
- status->dbs->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH;
- status->dbs->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH;
- status->dbs->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP;
- status->dbs->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM;
- status->dbs->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP;
- status->dbs->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY;
- status->dbs->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM;
- status->dbs->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF;
- status->dbs->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF;
- status->dbs->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT;
- status->dbs->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE;
- status->dbs->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS;
- status->dbs->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION;
- status->dbs->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION;
- status->dbs->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD;
- status->dbs->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD;
- status->dbs->IconChangeTable[SC_ACARAJE] = SI_ACARAJE;
- status->dbs->IconChangeTable[SC_TARGET_ASPD] = SI_TARGET_ASPD;
- status->dbs->IconChangeTable[SC_ATKER_ASPD] = SI_ATKER_ASPD;
- status->dbs->IconChangeTable[SC_ATKER_MOVESPEED] = SI_ATKER_MOVESPEED;
- status->dbs->IconChangeTable[SC_CUP_OF_BOZA] = SI_CUP_OF_BOZA;
- status->dbs->IconChangeTable[SC_OVERLAPEXPUP] = SI_OVERLAPEXPUP;
- status->dbs->IconChangeTable[SC_GM_BATTLE] = SI_GM_BATTLE;
- status->dbs->IconChangeTable[SC_GM_BATTLE2] = SI_GM_BATTLE2;
- status->dbs->IconChangeTable[SC_2011RWC] = SI_2011RWC;
- status->dbs->IconChangeTable[SC_STR_SCROLL] = SI_STR_SCROLL;
- status->dbs->IconChangeTable[SC_INT_SCROLL] = SI_INT_SCROLL;
- status->dbs->IconChangeTable[SC_STEAMPACK] = SI_STEAMPACK;
- status->dbs->IconChangeTable[SC_MAGIC_CANDY] = SI_MAGIC_CANDY;
- status->dbs->IconChangeTable[SC_M_LIFEPOTION] = SI_M_LIFEPOTION;
- status->dbs->IconChangeTable[SC_G_LIFEPOTION] = SI_G_LIFEPOTION;
- status->dbs->IconChangeTable[SC_MYSTICPOWDER] = SI_MYSTICPOWDER;
-
- // Eden Crystal Synthesis
- status->dbs->IconChangeTable[SC_QUEST_BUFF1] = SI_QUEST_BUFF1;
- status->dbs->IconChangeTable[SC_QUEST_BUFF2] = SI_QUEST_BUFF2;
- status->dbs->IconChangeTable[SC_QUEST_BUFF3] = SI_QUEST_BUFF3;
-
- // Geffen Magic Tournament
- status->dbs->IconChangeTable[SC_GEFFEN_MAGIC1] = SI_GEFFEN_MAGIC1;
- status->dbs->IconChangeTable[SC_GEFFEN_MAGIC2] = SI_GEFFEN_MAGIC2;
- status->dbs->IconChangeTable[SC_GEFFEN_MAGIC3] = SI_GEFFEN_MAGIC3;
- status->dbs->IconChangeTable[SC_FENRIR_CARD] = SI_FENRIR_CARD;
-
- // MVP Scrolls
- status->dbs->IconChangeTable[SC_MVPCARD_TAOGUNKA] = SI_MVPCARD_TAOGUNKA;
- status->dbs->IconChangeTable[SC_MVPCARD_MISTRESS] = SI_MVPCARD_MISTRESS;
- status->dbs->IconChangeTable[SC_MVPCARD_ORCHERO] = SI_MVPCARD_ORCHERO;
- status->dbs->IconChangeTable[SC_MVPCARD_ORCLORD] = SI_MVPCARD_ORCLORD;
-
- // Mercenary Bonus Effects
- status->dbs->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE;
- status->dbs->IconChangeTable[SC_MER_ATK] = SI_MER_ATK;
- status->dbs->IconChangeTable[SC_MER_HP] = SI_MER_HP;
- status->dbs->IconChangeTable[SC_MER_SP] = SI_MER_SP;
- status->dbs->IconChangeTable[SC_MER_HIT] = SI_MER_HIT;
-
- // Warlock Spheres
- status->dbs->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1;
- status->dbs->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2;
- status->dbs->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3;
- status->dbs->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4;
- status->dbs->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5;
-
- // Warlock Preserved spells
- status->dbs->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1;
- status->dbs->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2;
- status->dbs->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3;
- status->dbs->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4;
- status->dbs->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5;
- status->dbs->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6;
- status->dbs->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7;
-
- // Mechanic status icon
- status->dbs->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER;
- status->dbs->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER;
- status->dbs->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT;
- status->dbs->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT;
-
- // Guillotine Cross status icons
- status->dbs->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY;
- status->dbs->IconChangeTable[SC_TOXIN] = SI_TOXIN;
- status->dbs->IconChangeTable[SC_PARALYSE] = SI_PARALYSE;
- status->dbs->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED;
- status->dbs->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM;
- status->dbs->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT;
- status->dbs->IconChangeTable[SC_PYREXIA] = SI_PYREXIA;
- status->dbs->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE;
- status->dbs->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND;
-
- // Royal Guard status icons
- status->dbs->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF;
- status->dbs->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF;
- status->dbs->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF;
- status->dbs->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE;
-
- // Sura status icon
- status->dbs->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER;
-
- // Genetics Food items / Throwable items status icons
- status->dbs->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK;
- status->dbs->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD;
- status->dbs->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ;
- status->dbs->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA;
- status->dbs->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED;
- status->dbs->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES;
- status->dbs->IconChangeTable[SC_BOOST500] |= SI_BOOST500;
- status->dbs->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K;
- status->dbs->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS;
- status->dbs->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M;
- status->dbs->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F;
- status->dbs->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z;
- status->dbs->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500;
- status->dbs->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE;
- status->dbs->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
- status->dbs->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER;
- status->dbs->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB;
- status->dbs->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB;
- status->dbs->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY;
- status->dbs->IconChangeTable[SC_PROMOTE_HEALTH_RESERCH] = SI_PROMOTE_HEALTH_RESERCH;
- status->dbs->IconChangeTable[SC_ENERGY_DRINK_RESERCH] = SI_ENERGY_DRINK_RESERCH;
-
- // Elemental Spirit's 'side' status change icons.
- status->dbs->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE;
- status->dbs->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK;
- status->dbs->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN;
- status->dbs->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP;
- status->dbs->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP;
- status->dbs->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN;
- status->dbs->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN;
- status->dbs->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD;
- status->dbs->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC;
- status->dbs->IconChangeTable[SC_HEATER] = SI_HEATER;
- status->dbs->IconChangeTable[SC_TROPIC] = SI_TROPIC;
- status->dbs->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY;
- status->dbs->IconChangeTable[SC_COOLER] = SI_COOLER;
- status->dbs->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR;
- status->dbs->IconChangeTable[SC_GUST] = SI_GUST;
- status->dbs->IconChangeTable[SC_BLAST] = SI_BLAST;
- status->dbs->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM;
- status->dbs->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY;
- status->dbs->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL;
- status->dbs->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL;
- status->dbs->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART;
- status->dbs->IconChangeTable[SC_REBOUND] = SI_REBOUND;
- status->dbs->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING;
- status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM;
-
- // Costumes
- status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR;
- status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR;
- status->dbs->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS;
- status->dbs->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC;
- status->dbs->IconChangeTable[SC_LJOSALFAR] = SI_LJOSALFAR;
- status->dbs->IconChangeTable[SC_MERMAID_LONGING] = SI_MERMAID_LONGING;
- status->dbs->IconChangeTable[SC_HAT_EFFECT] = SI_HAT_EFFECT;
- status->dbs->IconChangeTable[SC_FLOWERSMOKE] = SI_FLOWERSMOKE;
- status->dbs->IconChangeTable[SC_FSTONE] = SI_FSTONE;
- status->dbs->IconChangeTable[SC_HAPPINESS_STAR] = SI_HAPPINESS_STAR;
- status->dbs->IconChangeTable[SC_MAPLE_FALLS] = SI_MAPLE_FALLS;
- status->dbs->IconChangeTable[SC_TIME_ACCESSORY] = SI_TIME_ACCESSORY;
- status->dbs->IconChangeTable[SC_MAGICAL_FEATHER] = SI_MAGICAL_FEATHER;
- status->dbs->IconChangeTable[SC_BLOSSOM_FLUTTERING] = SI_BLOSSOM_FLUTTERING;
+ status->dbs->Skill2SCTable[skill->get_index(SL_ALCHEMIST)] = (sc_type)MAPID_ALCHEMIST,
+ status->dbs->Skill2SCTable[skill->get_index(SL_MONK)] = (sc_type)MAPID_MONK,
+ status->dbs->Skill2SCTable[skill->get_index(SL_STAR)] = (sc_type)MAPID_STAR_GLADIATOR,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SAGE)] = (sc_type)MAPID_SAGE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_CRUSADER)] = (sc_type)MAPID_CRUSADER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SUPERNOVICE)] = (sc_type)MAPID_SUPER_NOVICE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_KNIGHT)] = (sc_type)MAPID_KNIGHT,
+ status->dbs->Skill2SCTable[skill->get_index(SL_WIZARD)] = (sc_type)MAPID_WIZARD,
+ status->dbs->Skill2SCTable[skill->get_index(SL_PRIEST)] = (sc_type)MAPID_PRIEST,
+ status->dbs->Skill2SCTable[skill->get_index(SL_BARDDANCER)] = (sc_type)MAPID_BARDDANCER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_ROGUE)] = (sc_type)MAPID_ROGUE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_ASSASIN)] = (sc_type)MAPID_ASSASSIN,
+ status->dbs->Skill2SCTable[skill->get_index(SL_BLACKSMITH)] = (sc_type)MAPID_BLACKSMITH,
+ status->dbs->Skill2SCTable[skill->get_index(SL_HUNTER)] = (sc_type)MAPID_HUNTER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SOULLINKER)] = (sc_type)MAPID_SOUL_LINKER,
// Other SC which are not necessarily associated to skills.
status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD;
@@ -1061,6 +885,13 @@ void initChangeTables(void) {
status->dbs->ChangeFlagTable[SC_PHI_DEMON] |= SCB_ALL;
status->dbs->ChangeFlagTable[SC_MAGIC_CANDY] |= SCB_MATK | SCB_ALL;
status->dbs->ChangeFlagTable[SC_MYSTICPOWDER] |= SCB_FLEE | SCB_LUK;
+ status->dbs->ChangeFlagTable[SC_POPECOOKIE] |= SCB_BASE | SCB_BATK | SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_VITALIZE_POTION] |= SCB_BATK | SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_SKF_MATK] |= SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_SKF_ATK] |= SCB_BATK;
+ status->dbs->ChangeFlagTable[SC_SKF_ASPD] |= SCB_ASPD;
+ status->dbs->ChangeFlagTable[SC_SKF_CAST] |= SCB_NONE;
+ status->dbs->ChangeFlagTable[SC_ALMIGHTY] |= SCB_BATK | SCB_MATK;
// Cash Items
status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] |= SCB_STR;
@@ -1153,7 +984,11 @@ void initChangeTables(void) {
status->dbs->ChangeFlagTable[SC_MVPCARD_ORCHERO] |= SCB_ALL;
status->dbs->ChangeFlagTable[SC_MVPCARD_ORCLORD] |= SCB_ALL;
+ // Clan System
+ status->dbs->ChangeFlagTable[SC_CLAN_INFO] |= SCB_NONE;
+
// Costumes
+ status->dbs->ChangeFlagTable[SC_DRESS_UP] |= SCB_NONE;
status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE;
status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE;
status->dbs->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE;
@@ -1169,53 +1004,11 @@ void initChangeTables(void) {
status->dbs->ChangeFlagTable[SC_MAGICAL_FEATHER] |= SCB_NONE;
status->dbs->ChangeFlagTable[SC_BLOSSOM_FLUTTERING] |= SCB_NONE;
- /* status->dbs->DisplayType Table [Ind/Hercules] */
- status->dbs->DisplayType[SC_ALL_RIDING] = true;
- status->dbs->DisplayType[SC_PUSH_CART] = true;
- status->dbs->DisplayType[SC_SUMMON1] = true;
- status->dbs->DisplayType[SC_SUMMON2] = true;
- status->dbs->DisplayType[SC_SUMMON3] = true;
- status->dbs->DisplayType[SC_SUMMON4] = true;
- status->dbs->DisplayType[SC_SUMMON5] = true;
- status->dbs->DisplayType[SC_CAMOUFLAGE] = true;
- status->dbs->DisplayType[SC_DUPLELIGHT] = true;
- status->dbs->DisplayType[SC_ORATIO] = true;
- status->dbs->DisplayType[SC_FROSTMISTY] = true;
- status->dbs->DisplayType[SC_VENOMIMPRESS] = true;
- status->dbs->DisplayType[SC_HALLUCINATIONWALK] = true;
- status->dbs->DisplayType[SC_ROLLINGCUTTER] = true;
- status->dbs->DisplayType[SC_BANDING] = true;
- status->dbs->DisplayType[SC_COLD] = true;
- status->dbs->DisplayType[SC_DEEP_SLEEP] = true;
- status->dbs->DisplayType[SC_CURSEDCIRCLE_ATKER] = true;
- status->dbs->DisplayType[SC_CURSEDCIRCLE_TARGET] = true;
- status->dbs->DisplayType[SC_BLOOD_SUCKER] = true;
- status->dbs->DisplayType[SC__SHADOWFORM] = true;
- status->dbs->DisplayType[SC_MONSTER_TRANSFORM] = true;
-
- // Costumes
- status->dbs->DisplayType[SC_MOONSTAR] = true;
- status->dbs->DisplayType[SC_SUPER_STAR] = true;
- status->dbs->DisplayType[SC_STRANGELIGHTS] = true;
- status->dbs->DisplayType[SC_DECORATION_OF_MUSIC] = true;
- status->dbs->DisplayType[SC_LJOSALFAR] = true;
- status->dbs->DisplayType[SC_MERMAID_LONGING] = true;
- status->dbs->DisplayType[SC_HAT_EFFECT] = true;
- status->dbs->DisplayType[SC_FLOWERSMOKE] = true;
- status->dbs->DisplayType[SC_FSTONE] = true;
- status->dbs->DisplayType[SC_HAPPINESS_STAR] = true;
- status->dbs->DisplayType[SC_MAPLE_FALLS] = true;
- status->dbs->DisplayType[SC_TIME_ACCESSORY] = true;
- status->dbs->DisplayType[SC_MAGICAL_FEATHER] = true;
- status->dbs->DisplayType[SC_BLOSSOM_FLUTTERING] = true;
-
- if( !battle_config.display_hallucination ) //Disable Hallucination.
- status->dbs->IconChangeTable[SC_ILLUSION] = SI_BLANK;
#undef add_sc
#undef set_sc_with_vfx
}
-void initDummyData(void)
+static void initDummyData(void)
{
memset(&status->dummy, 0, sizeof(status->dummy));
status->dummy.hp =
@@ -1237,15 +1030,23 @@ void initDummyData(void)
}
//For copying a status_data structure from b to a, without overwriting current Hp and Sp
-static inline void status_cpy(struct status_data* a, const struct status_data* b)
+static void status_copy(struct status_data *a, const struct status_data *b)
{
+ nullpo_retv(a);
+ nullpo_retv(b);
memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp)));
}
-//Sets HP to given value. Flag is the flag passed to status->heal in case
-//final value is higher than current (use 2 to make a healing effect display
-//on players) It will always succeed (overrides Berserk block), but it can't kill.
-int status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
+/**
+ * Sets HP to the given value.
+ *
+ * @param bl The target unit.
+ * @param hp The desired HP value.
+ * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied.
+ * @return The amount of HP gained.
+ */
+static int status_set_hp(struct block_list *bl, unsigned int hp, enum status_heal_flag flag)
+{
struct status_data *st;
if (hp < 1) return 0;
st = status->get_status_data(bl);
@@ -1255,14 +1056,20 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
if (hp > st->max_hp) hp = st->max_hp;
if (hp == st->hp) return 0;
if (hp > st->hp)
- return status->heal(bl, hp - st->hp, 0, 1|flag);
+ return status->heal(bl, hp - st->hp, 0, STATUS_HEAL_FORCED | flag);
return status_zap(bl, st->hp - hp, 0);
}
-//Sets SP to given value. Flag is the flag passed to status->heal in case
-//final value is higher than current (use 2 to make a healing effect display
-//on players)
-int status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
+/**
+ * Sets SP to the given value.
+ *
+ * @param bl The target unit.
+ * @param hp The desired SP value.
+ * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied.
+ * @return The amount of SP gained.
+ */
+static int status_set_sp(struct block_list *bl, unsigned int sp, enum status_heal_flag flag)
+{
struct status_data *st;
st = status->get_status_data(bl);
@@ -1272,11 +1079,13 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
if (sp > st->max_sp) sp = st->max_sp;
if (sp == st->sp) return 0;
if (sp > st->sp)
- return status->heal(bl, 0, sp - st->sp, 1|flag);
+ return status->heal(bl, 0, sp - st->sp, STATUS_HEAL_FORCED | flag);
return status_zap(bl, 0, st->sp - sp);
}
-int status_charge(struct block_list* bl, int64 hp, int64 sp) {
+static int status_charge(struct block_list *bl, int64 hp, int64 sp)
+{
+ nullpo_retr((int)(hp + sp), bl);
if(!(bl->type&BL_CONSUME))
return (int)(hp+sp); //Assume all was charged so there are no 'not enough' fails.
return status->damage(NULL, bl, hp, sp, 0, 3);
@@ -1287,11 +1096,13 @@ int status_charge(struct block_list* bl, int64 hp, int64 sp) {
//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) {
+static int status_damage(struct block_list *src, struct block_list *target, int64 in_hp, int64 in_sp, int walkdelay, int flag)
+{
struct status_data *st;
struct status_change *sc;
int hp,sp;
+ nullpo_ret(target);
/* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */
hp = (int)cap_value(in_hp,INT_MIN,INT_MAX);
sp = (int)cap_value(in_sp,INT_MIN,INT_MAX);
@@ -1300,12 +1111,12 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
sp = 0; //Not a valid SP target.
if (hp < 0) { //Assume absorbed damage.
- status->heal(target, -hp, 0, 1);
+ status->heal(target, -hp, 0, STATUS_HEAL_FORCED);
hp = 0;
}
if (sp < 0) {
- status->heal(target, 0, -sp, 1);
+ status->heal(target, 0, -sp, STATUS_HEAL_FORCED);
sp = 0;
}
@@ -1376,6 +1187,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
status_change_end(target, SC_CLOAKING, INVALID_TIMER);
status_change_end(target, SC_CHASEWALK, INVALID_TIMER);
status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER);
+ status_change_end(target, SC_SUHIDE, INVALID_TIMER);
if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) {
//Endure count is only reduced by non-players on non-gvg maps.
//val4 signals infinite endure. [Skotlex]
@@ -1522,16 +1334,27 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
return (int)(hp+sp);
}
-//Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it)
-//If flag&2, when the player is healed, show the HP/SP heal effect.
-int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
+/**
+ * Heals a character.
+ *
+ * @param bl The target unit.
+ * @param in_hp Amount of HP to recover.
+ * @param in_sp Amount of SP to recover.
+ * @param flag Additional options, @see enum status_heal_flag.
+ * @return The amount of HP + SP healed.
+ */
+static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, enum status_heal_flag flag)
+{
struct status_data *st;
struct status_change *sc;
int hp,sp;
+ nullpo_ret(bl);
st = status->get_status_data(bl);
- if (st == &status->dummy || !st->hp)
+ if (st == &status->dummy)
+ return 0;
+ if (st->hp == 0 && (flag & STATUS_HEAL_ALLOWREVIVE) == 0)
return 0;
/* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */
@@ -1548,10 +1371,10 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
hp = 0;
}
- if(hp) {
- if( sc && sc->data[SC_BERSERK] ) {
- if( flag&1 )
- flag &= ~2;
+ if (hp != 0) {
+ if (sc && sc->data[SC_BERSERK] != NULL) {
+ if ((flag & STATUS_HEAL_FORCED) != 0)
+ flag &= ~STATUS_HEAL_SHOWEFFECT;
else
hp = 0;
}
@@ -1586,7 +1409,7 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
// send hp update to client
switch(bl->type) {
- case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag&2) ? 1 : 0); break;
+ case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag & STATUS_HEAL_SHOWEFFECT) != 0 ? 1 : 0); break;
case BL_MOB: mob->heal(BL_UCAST(BL_MOB, bl), hp); break;
case BL_HOM: homun->healed(BL_UCAST(BL_HOM, bl)); break;
case BL_MER: mercenary->heal(BL_UCAST(BL_MER, bl), hp, sp); break;
@@ -1602,7 +1425,8 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
//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 subtraction.
-int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) {
+static 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;
@@ -1640,23 +1464,26 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe
if (flag)
status->damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
else
- status->heal(target, INT_MAX, 0, 0);
+ status->heal(target, INT_MAX, 0, STATUS_HEAL_DEFAULT);
}
if (sp > INT_MAX) {
sp -= INT_MAX;
if (flag)
status->damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
else
- status->heal(target, 0, INT_MAX, 0);
+ status->heal(target, 0, INT_MAX, STATUS_HEAL_DEFAULT);
}
if (flag)
return status->damage(src, target, hp, sp, 0, (!src||src==target?5:1));
- return status->heal(target, hp, sp, 0);
+ return status->heal(target, hp, sp, STATUS_HEAL_DEFAULT);
}
-int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) {
+static int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)
+{
struct status_data *st;
unsigned int hp, sp;
+
+ nullpo_ret(bl);
if (!status->isdead(bl)) return 0;
st = status->get_status_data(bl);
@@ -1690,11 +1517,13 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
return 1;
}
-int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) {
+static int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp)
+{
struct status_data *st;
unsigned int hp, sp;
if (!status->isdead(bl)) return 0;
+ nullpo_ret(bl);
st = status->get_status_data(bl);
if (st == &status->dummy)
return 0; //Invalid target.
@@ -1726,17 +1555,18 @@ int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int
}
/*==========================================
-* Checks whether the src can use the skill on the target,
-* taking into account status/option of both source/target. [Skotlex]
-* flag:
-* 0 - Trying to use skill on target.
-* 1 - Cast bar is done.
-* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
-* src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack.
-* target MAY Be null, in which case the checks are only to see
-* whether the source can cast or not the skill on the ground.
-*------------------------------------------*/
-int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) {
+ * Checks whether the src can use the skill on the target,
+ * taking into account status/option of both source/target. [Skotlex]
+ * flag:
+ * 0 - Trying to use skill on target.
+ * 1 - Cast bar is done.
+ * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
+ * src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack.
+ * target MAY Be null, in which case the checks are only to see
+ * whether the source can cast or not the skill on the ground.
+ *------------------------------------------*/
+static int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag)
+{
struct status_data *st;
struct status_change *sc=NULL, *tsc;
int hide_flag;
@@ -1747,6 +1577,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (src != NULL && src->type != BL_PC && status->isdead(src))
return 0;
+ if (sd != NULL && sd->block_action.skill && skill_id) // *pcblock script command
+ return 0;
+
if (!skill_id) { //Normal attack checks.
if (!(st->mode&MD_CANATTACK))
return 0; //This mode is only needed for melee attacking.
@@ -1759,14 +1592,18 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
}
if( skill_id ) {
- if (src != NULL && (sd == NULL || sd->skillitem == 0)) {
+ if (src != NULL && (sd == NULL || sd->autocast.type != AUTOCAST_ITEM)) {
// Items that cast skills using 'itemskill' will not be handled by map_zone_db.
int i;
for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) {
if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) {
if (src->type == BL_PC) {
- clif->msgtable(sd, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 2);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50));
+#endif
} else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) {
if( st->mode&MD_BOSS ) { /* is boss */
if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) )
@@ -1799,7 +1636,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (src != NULL
&& map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR)
&& !(st->mode&MD_BOSS)
- && (src->type != BL_PC || sd->skillitem != skill_id))
+ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM))
return 0;
break;
default:
@@ -1822,6 +1659,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
(sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD)
|| (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_SUHIDE] && skill_id != SU_HIDE)
)
return 0;
@@ -1841,9 +1679,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
switch (sc->data[SC_BLADESTOP]->val1)
{
case 5: if (skill_id == MO_EXTREMITYFIST) break;
+ FALLTHROUGH
case 4: if (skill_id == MO_CHAINCOMBO) break;
+ FALLTHROUGH
case 3: if (skill_id == MO_INVESTIGATE) break;
+ FALLTHROUGH
case 2: if (skill_id == MO_FINGEROFFENSIVE) break;
+ FALLTHROUGH
default: return 0;
}
}
@@ -1873,7 +1715,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
}
- if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->skillitem != skill_id)) {
+ if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM)) {
//Skills blocked through status changes...
if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
sc->data[SC_SILENCE] ||
@@ -1985,7 +1827,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
|| (tsc->data[SC_CLOAKINGEXCEED] != NULL && is_detect)
))
return 0;
- if (tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && (!skill_id || (flag == 0 && src && src->type != BL_PC)))
+ if (tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && flag == 0)
return 0;
if (tsc->data[SC_STEALTHFIELD] && !is_boss)
return 0;
@@ -2007,6 +1849,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0; // Can't use Weapon endow skills on Mercenary (only Master)
if( skill_id == AM_POTIONPITCHER && ( target->type == BL_MER || target->type == BL_ELEM) )
return 0; // Can't use Potion Pitcher on Mercenaries
+ FALLTHROUGH
default:
//Check for chase-walk/hiding/cloaking opponents.
if( tsc ) {
@@ -2022,12 +1865,14 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
//Skotlex: Calculates the initial status for the given mob
//first will only be false when the mob leveled up or got a GuardUp level.
-int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
+static 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;
+ nullpo_retr(1, md);
if(opt&SCO_FIRST) { //Set basic level on respawn.
if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
;
@@ -2191,7 +2036,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
}
//Skotlex: Calculates the stats of the given pet.
-int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
+static int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
{
nullpo_ret(pd);
@@ -2208,9 +2053,7 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
if (battle_config.pet_lv_rate && pd->msd) {
struct map_session_data *sd = pd->msd;
- int lv;
-
- lv =sd->status.base_level*battle_config.pet_lv_rate/100;
+ int lv = sd->status.base_level * battle_config.pet_lv_rate / 100;
if (lv < 0)
lv = 1;
if (lv != pd->pet.level || opt&SCO_FIRST) {
@@ -2255,17 +2098,20 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
return 1;
}
-unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st)
+static unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st)
{
- uint64 val = pc->class2idx(sd->status.class_);
+ uint64 val;
+ nullpo_ret(sd);
+ nullpo_ret(st);
+ val = pc->class2idx(sd->status.class);
val = status->dbs->SP_table[val][sd->status.base_level];
- if ( sd->class_&JOBL_UPPER )
+ if ((sd->job & JOBL_UPPER) != 0)
val += val * 25 / 100;
- else if ( sd->class_&JOBL_BABY )
+ else if ((sd->job & JOBL_BABY) != 0)
val = val * 70 / 100;
- if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0)
val *= 3; //Triple max SP for top ranking Taekwons over level 90.
val += val * st->int_ / 100;
@@ -2273,23 +2119,26 @@ unsigned int status_get_base_maxsp(const struct map_session_data *sd, const stru
return (unsigned int)cap_value(val, 0, UINT_MAX);
}
-unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st)
+static unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st)
{
- uint64 val = pc->class2idx(sd->status.class_);
+ uint64 val;
+ nullpo_ret(sd);
+ nullpo_ret(st);
+ val = pc->class2idx(sd->status.class);
val = status->dbs->HP_table[val][sd->status.base_level];
- if ( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99 )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99)
val += 2000; //Supernovice lvl99 hp bonus.
- if ( (sd->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E && sd->status.base_level >= 150 )
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E && sd->status.base_level >= 150)
val += 2000; //Extented Supernovice lvl150 hp bonus.
- if ( sd->class_&JOBL_UPPER )
+ if ((sd->job & JOBL_UPPER) != 0)
val += val * 25 / 100; //Trans classes get a 25% hp bonus
- else if ( sd->class_&JOBL_BABY )
+ else if ((sd->job & JOBL_BABY) != 0)
val = val * 70 / 100; //Baby classes get a 30% hp penalty
- if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON))
val *= 3; //Triple max HP for top ranking Taekwons over level 90.
val += val * st->vit / 100; // +1% per each point of VIT
@@ -2297,22 +2146,83 @@ unsigned int status_get_base_maxhp(const struct map_session_data *sd, const stru
return (unsigned int)cap_value(val,0,UINT_MAX);
}
-void status_calc_pc_additional(struct map_session_data* sd, enum e_status_calc_opt opt) {
+/**
+ * Calculates the HP that a character will have after death, on respawn.
+ *
+ * @param sd The character to calculate.
+ * @param st The character's status data.
+ */
+static unsigned int status_get_restart_hp(const struct map_session_data *sd, const struct status_data *st)
+{
+ unsigned int hp = 0;
+
+ if (sd->special_state.restart_full_recover)
+ return st->max_hp;
+
+ if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 && battle_config.restart_hp_rate < 50)
+ hp = st->max_hp / 2;
+ else
+ hp = APPLY_RATE(st->max_hp, battle_config.restart_hp_rate);
+
+ if (hp > 0)
+ return hp;
+
+ return 1;
+}
+
+/**
+ * Calculates the SP that a character will have after death, on respawn.
+ *
+ * @param sd The character to calculate.
+ * @param st The character's status data.
+ */
+static unsigned int status_get_restart_sp(const struct map_session_data *sd, const struct status_data *st)
+{
+ unsigned int sp = 0;
+
+ if (sd->special_state.restart_full_recover)
+ return st->max_sp;
+
+ sp = APPLY_RATE(st->max_sp, battle_config.restart_sp_rate);
+
+ if (sp > 0)
+ return sp;
+
+ return 1; // the minimum for the respawn setting is SP:1
+}
+
+static void status_calc_pc_additional(struct map_session_data *sd, enum e_status_calc_opt opt)
+{
/* Just used for Plugin to give bonuses. */
return;
}
+static void status_calc_pc_recover_hp(struct map_session_data *sd, struct status_data *bstatus)
+{
+ nullpo_retv(sd);
+ nullpo_retv(bstatus);
+
+ if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0
+ && battle_config.restart_hp_rate < 50)
+ bstatus->hp = bstatus->max_hp>>1;
+ else
+ bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate);
+}
+
//Calculates player data from scratch without counting SC adjustments.
//Should be invoked whenever players raise stats, learn passive skills or change equipment.
-int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
+static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt opt)
+{
static int calculating = 0; //Check for recursive call preemption. [Skotlex]
struct status_data *bstatus; // pointer to the player's base status
- const struct status_change *sc = &sd->sc;
- struct s_skill b_skill[MAX_SKILL]; // previous skill tree
+ const struct status_change *sc;
+ struct s_skill b_skill[MAX_SKILL_DB]; // previous skill tree
int b_weight, b_max_weight, b_cart_weight_max, // previous weight
i, k, index, skill_lv,refinedef=0;
int64 i64;
+ nullpo_retr(-1, sd);
+ sc = &sd->sc;
if (++calculating > 10) //Too many recursive calls!
return -1;
@@ -2324,7 +2234,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
pc->calc_skilltree(sd); // SkillTree calculation
- sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
+ sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class)]+sd->status.str*300;
if(opt&SCO_FIRST) {
//Load Hp/SP from char-received data.
@@ -2333,7 +2243,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->regen.sregen = &sd->sregen;
sd->regen.ssregen = &sd->ssregen;
sd->weight=0;
- for(i=0;i<MAX_INVENTORY;i++){
+ for (i = 0; i < sd->status.inventorySize; i++) {
if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL)
continue;
sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount;
@@ -2369,7 +2279,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
memset(ZEROED_BLOCK_POS(&(sd->left_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->left_weapon)));
if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it
- clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE);
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_CLAIRVOYANCE));
memset(&sd->special_state,0,sizeof(sd->special_state));
@@ -2382,13 +2292,13 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->speed = pSpeed;
}
- //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
- //Give them all modes except these (useful for clones)
+ // FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
+ // Give them all modes except these (useful for clones)
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
- bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
+ bstatus->size = ((sd->job & JOBL_BABY) != 0 || (sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)?SZ_SMALL:SZ_MEDIUM;
if (battle_config.character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd))) { //[Lupus]
- if (sd->class_&JOBL_BABY) {
+ if ((sd->job & JOBL_BABY) != 0) {
if (battle_config.character_size&SZ_BIG)
bstatus->size++;
} else {
@@ -2398,7 +2308,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
}
bstatus->aspd_rate = 1000;
bstatus->ele_lv = 1;
- bstatus->race = RC_PLAYER;
+ bstatus->race = ((sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)?RC_BRUTE:RC_PLAYER;
// Autobonus
pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true);
@@ -2464,18 +2374,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
r = 0;
if (r)
- wa->atk2 = status->dbs->refine_info[wlv].bonus[r-1] / 100;
+ wa->atk2 = refine->get_bonus(wlv, r) / 100;
#ifdef RENEWAL
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = wlv;
if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus
- wa->matk += status->dbs->refine_info[wlv].bonus[r-1] / 100;
+ wa->matk += refine->get_bonus(wlv, r) / 100;
#endif
//Overrefined bonus.
if (r)
- wd->overrefine = status->dbs->refine_info[wlv].randombonus_max[r-1] / 100;
+ wd->overrefine = refine->get_randombonus_max(wlv, r) / 100;
wa->range += sd->inventory_data[index]->range;
if(sd->inventory_data[index]->script) {
@@ -2492,8 +2402,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
if (sd->status.inventory[index].card[0]==CARD0_FORGE) {
// Forged weapon
wd->star += (sd->status.inventory[index].card[1]>>8);
- if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
- if(pc->famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
+ if (wd->star >= 15)
+ wd->star = 40; // 3 Star Crumbs now give +40 dmg
+ if (pc->fame_rank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]), RANKTYPE_BLACKSMITH) > 0)
wd->star += 10;
if (!wa->ele) //Do not overwrite element from previous bonuses.
@@ -2509,7 +2420,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
r = 0;
if (r)
- refinedef += status->dbs->refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
+ refinedef += refine->get_bonus(REFINE_TYPE_ARMOR, r);
if(sd->inventory_data[index]->script) {
if( i == EQI_HAND_L ) //Shield
@@ -2628,14 +2539,57 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
}
}
+ /* parse item options [Smokexyz] */
+ for (i = 0; i < EQI_MAX; i++) {
+ status->current_equip_item_index = index = sd->equip_index[i];
+ status->current_equip_option_index = -1;
+
+ if (i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index)
+ continue;
+ else if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index)
+ continue;
+ else if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index))
+ continue;
+
+ if (index >= 0 && sd->inventory_data[index]) {
+ int j = 0;
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) {
+ int16 option_index = sd->status.inventory[index].option[j].index;
+ struct itemdb_option *ito = NULL;
+
+ if (option_index == 0 || (ito = itemdb->option_exists(option_index)) == NULL || ito->script == NULL)
+ continue;
+
+ status->current_equip_option_index = j;
+ script->run(ito->script, 0, sd->bl.id, 0);
+
+ if (calculating == 0) //Abort, script->run his function. [Skotlex]
+ return 1;
+ }
+ }
+ }
+
+ status->current_equip_option_index = -1;
+ status->current_equip_item_index = -1;
+
+ // Clan Buffs
+ if (sd->status.clan_id > 0) {
+ struct clan *c = clan->search(sd->status.clan_id);
+ clan->buff_start(sd, c);
+ }
+
status->calc_pc_additional(sd, opt);
- if( sd->pd ) { // Pet Bonus
+ if (sd->pd != NULL) { // Pet bonus.
struct pet_data *pd = sd->pd;
- if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly )
- script->run(pd->petDB->equip_script,0,sd->bl.id,0);
- if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus )
- pc->bonus(sd,pd->bonus->type, pd->bonus->val);
+
+ if (pd->petDB != NULL && pd->petDB->equip_script != NULL)
+ script->run(pd->petDB->equip_script, 0, sd->bl.id, 0);
+
+ if (pd->pet.intimate > PET_INTIMACY_NONE && pd->state.skillbonus == 1 && pd->bonus != NULL
+ && (battle_config.pet_equip_required == 0 || pd->pet.equip > 0)) {
+ pc->bonus(sd, pd->bonus->type, pd->bonus->val);
+ }
}
//param_bonus now holds card bonuses.
@@ -2656,9 +2610,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2];
sd->left_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype2];
- if ((pc_isridingpeco(sd) || pc_isridingdragon(sd))
- && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)
- ) {
+ if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) && (sd->weapontype == W_1HSPEAR || sd->weapontype == W_2HSPEAR)) {
//When Riding with spear, damage modifier to mid-class becomes
//same as versus large size.
sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2];
@@ -2668,8 +2620,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
// ----- STATS CALCULATION -----
// Job bonuses
- index = pc->class2idx(sd->status.class_);
- for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){
+ index = pc->class2idx(sd->status.class);
+ for (i = 0; i < sd->status.job_level && i < MAX_LEVEL; i++) {
if(!status->dbs->job_bonus[index][i])
continue;
switch(status->dbs->job_bonus[index][i]) {
@@ -2683,7 +2635,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
}
// If a Super Novice has never died and is at least joblv 70, he gets all stats +10
- if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) {
bstatus->str += 10;
bstatus->agi += 10;
bstatus->vit += 10;
@@ -2701,6 +2653,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->dex += skill_lv;
if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
bstatus->int_ += skill_lv;
+ if ((pc->checkskill(sd,SU_POWEROFLAND)) > 0)
+ bstatus->int_ += 20;
// Bonuses from cards and equipment as well as base stat, remember to avoid overflows.
i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
@@ -2720,8 +2674,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
// Base batk value is set on status->calc_misc
// weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?)
- if (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon])
- bstatus->batk += sd->weapon_atk[sd->status.weapon];
+ if (sd->weapontype < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->weapontype])
+ bstatus->batk += sd->weapon_atk[sd->weapontype];
// Absolute modifiers from passive skills
#ifndef RENEWAL
if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE.
@@ -2738,9 +2692,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
// Absolute modifiers from passive skills
- if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
+ if ((skill_lv=pc->checkskill(sd,CR_TRUST)) > 0)
bstatus->max_hp += skill_lv*200;
+ if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0)
+ bstatus->max_hp += 1000;
+
// Apply relative modifiers from equipment
if(sd->hprate < 0)
sd->hprate = 0;
@@ -2773,6 +2730,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->max_sp += 200 + 20 * skill_lv;
if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 )
bstatus->max_sp += 30 * skill_lv;
+ if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0)
+ bstatus->max_sp += 100;
// Apply relative modifiers from equipment
if(sd->sprate < 0)
@@ -2790,24 +2749,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
// ----- RESPAWN HP/SP -----
//
//Calc respawn hp and store it on base_status
- if (sd->special_state.restart_full_recover)
- {
- bstatus->hp = bstatus->max_hp;
- bstatus->sp = bstatus->max_sp;
- } else {
- if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
- && battle_config.restart_hp_rate < 50)
- bstatus->hp = bstatus->max_hp>>1;
- else
- bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate);
- if(!bstatus->hp)
- bstatus->hp = 1;
-
- bstatus->sp = APPLY_RATE(bstatus->max_sp, battle_config.restart_sp_rate);
-
- if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */
- bstatus->sp = 1;
- }
+ bstatus->hp = status->get_restart_hp(sd, bstatus);
+ bstatus->sp = status->get_restart_sp(sd, bstatus);
// ----- MISC CALCULATION -----
status->calc_misc(&sd->bl, bstatus, sd->status.base_level);
@@ -2845,6 +2788,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->critical_rate = 0;
if(sd->critical_rate != 100)
bstatus->cri = bstatus->cri * sd->critical_rate/100;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->cri += 20;
if(sd->flee2_rate < 0)
sd->flee2_rate = 0;
@@ -2862,10 +2807,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
#ifndef RENEWAL
bstatus->hit += skill_lv;
#endif
- if(sd->status.weapon == W_BOW)
+ if (sd->weapontype == W_BOW)
bstatus->rhw.range += skill_lv;
}
- if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) {
+ if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE) {
if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0)
bstatus->hit += 2*skill_lv;
if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) {
@@ -2873,18 +2818,22 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->rhw.range += skill_lv;
}
}
- if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 )
+ if ((sd->weapontype == W_1HAXE || sd->weapontype == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
bstatus->hit += 3*skill_lv;
- if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
+ if ((sd->weapontype == W_MACE || sd->weapontype == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
bstatus->hit += 2*skill_lv;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->hit += 20;
// ----- FLEE CALCULATION -----
// Absolute modifiers from passive skills
if((skill_lv=pc->checkskill(sd,TF_MISS))>0)
- bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
+ bstatus->flee += skill_lv*((sd->job & JOBL_2) != 0 && (sd->job & MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
if((skill_lv=pc->checkskill(sd,MO_DODGE))>0)
bstatus->flee += (skill_lv*3)>>1;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->flee += 20;
// ----- EQUIPMENT-DEF CALCULATION -----
// Apply relative modifiers from equipment
@@ -2927,16 +2876,15 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
// Basic ASPD value
i = status->base_amotion_pc(sd,bstatus);
- bstatus->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
+ bstatus->amotion = cap_value(i,((sd->job & JOBL_THIRD) != 0 ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
// Relative modifiers from passive skills
#ifndef RENEWAL_ASPD
- if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
+ if (sd->weapontype == W_BOOK && (skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0)
bstatus->aspd_rate -= 5*skill_lv;
if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
bstatus->aspd_rate -= 30*skill_lv;
- if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
- (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
+ if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE && (skill_lv=pc->checkskill(sd,GS_SINGLEACTION)) > 0)
bstatus->aspd_rate -= ((skill_lv+1)/2) * 10;
if (pc_isridingpeco(sd))
bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
@@ -3102,6 +3050,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->subele[ELE_EARTH] += i;
sd->subele[ELE_FIRE] -= i;
}
+ if (sc->data[SC_POPECOOKIE] != NULL) {
+ i = sc->data[SC_POPECOOKIE]->val3;
+ sd->subele[ELE_WATER] += i;
+ sd->subele[ELE_EARTH] += i;
+ sd->subele[ELE_FIRE] += i;
+ sd->subele[ELE_WIND] += i;
+ sd->subele[ELE_POISON] += i;
+ sd->subele[ELE_HOLY] += i;
+ sd->subele[ELE_DARK] += i;
+ sd->subele[ELE_GHOST] += i;
+ sd->subele[ELE_UNDEAD] += i;
+ }
if (sc->data[SC_MTF_MLEATKED])
sd->subele[ELE_NEUTRAL] += sc->data[SC_MTF_MLEATKED]->val1;
if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
@@ -3160,7 +3120,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->left_weapon.addrace[RC_DEMON] += sc->data[SC_PHI_DEMON]->val1;
}
}
- status_cpy(&sd->battle_status, bstatus);
+ status->copy(&sd->battle_status, bstatus);
// ----- CLIENT-SIDE REFRESH -----
if(!sd->bl.prev) {
@@ -3180,15 +3140,25 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
clif->updatestatus(sd,SP_CARTINFO);
}
+ // Spirit Marble status activates automatically for a infinite
+ // amount of time when the skill is learned. Felt this was the
+ // best place to put this. [Rytech]
+ if (pc->checkskill(sd, SU_SPRITEMABLE))
+ sc_start(&sd->bl, &sd->bl, SC_SPRITEMABLE, 100, 1, INFINITE_DURATION);
+
calculating = 0;
return 0;
}
-int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) {
- struct status_data *mstatus = &md->base_status;
- struct s_mercenary *merc = &md->mercenary;
+static int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt)
+{
+ struct status_data *mstatus;
+ struct s_mercenary *merc;
+ nullpo_ret(md);
+ mstatus = &md->base_status;
+ merc = &md->mercenary;
if( opt&SCO_FIRST ) {
memcpy(mstatus, &md->db->status, sizeof(struct status_data));
mstatus->mode = MD_CANMOVE|MD_CANATTACK;
@@ -3199,17 +3169,22 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt
}
status->calc_misc(&md->bl, mstatus, md->db->lv);
- status_cpy(&md->battle_status, mstatus);
+ status->copy(&md->battle_status, mstatus);
return 0;
}
-int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) {
- struct status_data *estatus = &ed->base_status;
- struct s_elemental *ele = &ed->elemental;
- struct map_session_data *sd = ed->master;
+static int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt)
+{
+ struct status_data *estatus;
+ struct s_elemental *ele;
+ struct map_session_data *sd;
- if ( !sd )
+ nullpo_ret(ed);
+ estatus = &ed->base_status;
+ ele = &ed->elemental;
+ sd = ed->master;
+ if (sd == NULL)
return 0;
if ( opt&SCO_FIRST ) {
@@ -3237,13 +3212,14 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt
memcpy(&ed->battle_status, estatus, sizeof(struct status_data));
} else {
status->calc_misc(&ed->bl, estatus, 0);
- status_cpy(&ed->battle_status, estatus);
+ status->copy(&ed->battle_status, estatus);
}
return 0;
}
-int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
+static int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt)
+{
struct status_data *nstatus;
if (!nd)
@@ -3274,17 +3250,21 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
nstatus->luk = nd->stat_point;
status->calc_misc(&nd->bl, nstatus, nd->level);
- status_cpy(&nd->status, nstatus);
+ status->copy(&nd->status, nstatus);
return 0;
}
-int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
- struct status_data *hstatus = &hd->base_status;
- struct s_homunculus *hom = &hd->homunculus;
+static int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
+{
+ struct status_data *hstatus;
+ struct s_homunculus *hom;
int skill_lv;
int amotion;
+ nullpo_retr(1, hd);
+ hstatus = &hd->base_status;
+ hom = &hd->homunculus;
hstatus->str = hom->str / 10;
hstatus->agi = hom->agi / 10;
hstatus->vit = hom->vit / 10;
@@ -3360,12 +3340,13 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
status->calc_misc(&hd->bl, hstatus, hom->level);
- status_cpy(&hd->battle_status, hstatus);
+ status->copy(&hd->battle_status, hstatus);
return 1;
}
//Calculates base regen values.
-void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) {
+static 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);
@@ -3465,8 +3446,9 @@ void status_calc_regen(struct block_list *bl, struct status_data *st, struct reg
}
//Calculates SC related regen rates.
-void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc)
+static void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc)
{
+ nullpo_retv(bl);
if (!(bl->type&BL_REGEN) || !regen)
return;
@@ -3509,7 +3491,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|| sc->data[SC_OBLIVIONCURSE] != NULL
|| sc->data[SC_MAXIMIZEPOWER] != NULL
|| sc->data[SC_REBOUND] != NULL
- || (bl->type == BL_PC && (BL_UCAST(BL_PC, bl)->class_&MAPID_UPPERMASK) == MAPID_MONK
+ || (bl->type == BL_PC && (BL_UCAST(BL_PC, bl)->job & MAPID_UPPERMASK) == MAPID_MONK
&& (sc->data[SC_EXTREMITYFIST] != NULL
|| (sc->data[SC_EXPLOSIONSPIRITS] != NULL
&& (sc->data[SC_SOULLINK] == NULL || sc->data[SC_SOULLINK]->val2 != SL_MONK)
@@ -3540,7 +3522,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
#endif
regen->rate.sp += 1;
}
-
+
if (sc->data[SC_GDSKILL_REGENERATION]) {
const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION];
if (!sce->val4) {
@@ -3573,6 +3555,10 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
regen->rate.hp += regen->rate.hp * sc->data[SC_BUCHEDENOEL]->val1 / 100;
regen->rate.sp += regen->rate.sp * sc->data[SC_BUCHEDENOEL]->val2 / 100;
}
+ if (sc->data[SC_CATNIPPOWDER]) {
+ regen->rate.hp *= 2;
+ regen->rate.sp *= 2;
+ }
}
#define status_get_homstr(st, hd) ((st)->str + (hd)->homunculus.str_value)
@@ -3584,13 +3570,16 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
/// Recalculates parts of an object's battle status according to the specified flags.
/// @param flag bitfield of values from enum scb_flag
-void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
+static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
+{
const struct status_data *bst = status->get_base_status(bl);
struct status_data *st = status->get_status_data(bl);
struct status_change *sc = status->get_sc(bl);
struct map_session_data *sd = BL_CAST(BL_PC,bl);
int temp;
+ nullpo_retv(bl);
+
if (!bst || !st)
return;
@@ -3610,7 +3599,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference.
- status_cpy(st, bst);
+ status->copy(st, bst);
return;
}
@@ -3677,7 +3666,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
temp = bst->batk - status->base_atk(bl,bst);
if (temp) {
temp += st->batk;
- st->batk = cap_value(temp, 0, USHRT_MAX);
+ st->batk = cap_value(temp, battle_config.batk_min, battle_config.batk_max);
}
st->batk = status->calc_batk(bl, sc, st->batk, true);
}
@@ -3792,13 +3781,15 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if(flag&SCB_CRI && bst->cri) {
- if (st->luk == bst->luk)
+ if (st->luk == bst->luk) {
st->cri = status->calc_critical(bl, sc, bst->cri, true);
- else
+ } else {
st->cri = status->calc_critical(bl, sc, bst->cri + 3*(st->luk - bst->luk), true);
+ }
+ if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->weapontype == W_KATAR) {
+ st->cri *= 2;
+ }
}
- if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->status.weapon == W_KATAR)
- st->cri <<= 1;
if(flag&SCB_FLEE2 && bst->flee2) {
if (st->luk == bst->luk)
@@ -3857,10 +3848,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if(flag&SCB_MAXSP) {
if( bl->type&BL_PC ) {
st->max_sp = status->get_base_maxsp(sd,st);
- if (sd)
+ if (sd != NULL) {
st->max_sp += bst->max_sp - sd->status.max_sp;
-
- st->max_sp = status->calc_maxsp(&sd->bl, &sd->sc, st->max_sp);
+ st->max_sp = status->calc_maxsp(&sd->bl, &sd->sc, st->max_sp);
+ }
if( st->max_sp > (unsigned int)battle_config.max_sp )
st->max_sp = (unsigned int)battle_config.max_sp;
@@ -3927,14 +3918,29 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
#endif
if ( st->aspd_rate != 1000 ) // absolute percentage modifier
amotion = amotion * st->aspd_rate / 1000;
- if ( sd && sd->ud.skilltimer != INVALID_TIMER && pc->checkskill(sd, SA_FREECAST) > 0 )
- amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100;
+ if (sd && sd->ud.skilltimer != INVALID_TIMER) {
+ if (pc->checkskill(sd, SA_FREECAST) > 0) {
+ amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100;
+ } else {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
+ amotion = amotion * 5 * (ud->skill_lv + 10) / 100;
+ }
+ }
+ }
#ifdef RENEWAL_ASPD
amotion += (max(0xc3 - amotion, 2) * (st->aspd_rate2 + status->calc_aspd(bl, sc, 2))) / 100;
- amotion = 10 * (200 - amotion) + sd->bonus.aspd_add;
+ amotion = 10 * (200 - amotion);
+ if (sd != NULL) {
+ amotion += sd->bonus.aspd_add;
+ }
#endif
amotion = status->calc_fix_aspd(bl, sc, amotion);
- st->amotion = cap_value(amotion, ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd), 2000);
+ if (sd != NULL) {
+ st->amotion = cap_value(amotion, ((sd->job & JOBL_THIRD) != 0 ? battle_config.max_third_aspd : battle_config.max_aspd), 2000);
+ } else {
+ st->amotion = cap_value(amotion, battle_config.max_aspd, 2000);
+ }
st->adelay = 2 * st->amotion;
} else { // mercenary and mobs
@@ -3958,15 +3964,17 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if(flag&SCB_REGEN && bl->type&BL_REGEN)
status->calc_regen_rate(bl, status->get_regen_data(bl), sc);
}
+
/// Recalculates parts of an object's base status and battle status according to the specified flags.
/// Also sends updates to the client wherever applicable.
/// @param flag bitfield of values from enum scb_flag
/// @param first if true, will cause status_calc_* functions to run their base status initialization code
-void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt)
+static void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt)
{
struct status_data bst; // previous battle status
struct status_data *st; // pointer to current battle status
+ nullpo_retv(bl);
if (bl->type == BL_PC) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
if (sd->delayed_damage != 0) {
@@ -4144,11 +4152,16 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca
clif->mercenary_updatestatus(ed->master, SP_SP);
}
}
+
//Checks whether the source can see and chase target.
-int status_check_visibility(struct block_list *src, struct block_list *target) {
+static int status_check_visibility(struct block_list *src, struct block_list *target)
+{
int view_range;
struct status_change *tsc = NULL;
+ nullpo_ret(src);
+ nullpo_ret(target);
+
switch ( src->type ) {
case BL_MOB:
view_range = BL_UCCAST(BL_MOB, src)->min_chase;
@@ -4193,17 +4206,22 @@ int status_check_visibility(struct block_list *src, struct block_list *target) {
}
// Basic ASPD value
-int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) {
+static int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st)
+{
int amotion;
#ifdef RENEWAL_ASPD /* [malufett/Hercules] */
float temp;
int skill_lv, val = 0;
- amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1];
- if ( sd->status.weapon > MAX_SINGLE_WEAPON_TYPE)
- amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4;
- if ( sd->status.shield )
- amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_SINGLE_WEAPON_TYPE];
- switch ( sd->status.weapon ) {
+
+ nullpo_ret(sd);
+ nullpo_ret(st);
+
+ amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1];
+ if (sd->weapontype > MAX_SINGLE_WEAPON_TYPE)
+ amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2] / 4;
+ if (sd->has_shield)
+ amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][MAX_SINGLE_WEAPON_TYPE];
+ switch (sd->weapontype) {
case W_BOW:
case W_MUSICAL:
case W_WHIP:
@@ -4218,16 +4236,16 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st)
temp = st->dex * st->dex / 5.0f + st->agi * st->agi * 0.5f;
}
temp = (float)(sqrt(temp) * 0.25f) + 0xc4;
- if ( (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0 && sd->status.weapon == W_BOOK )
+ if (sd->weapontype == W_BOOK && (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0)
val += (skill_lv - 1) / 2 + 1;
if ( (skill_lv = pc->checkskill(sd, GS_SINGLEACTION)) > 0 )
val += ((skill_lv + 1) / 2);
amotion = ((int)(temp + ((float)(status->calc_aspd(&sd->bl, &sd->sc, 1) + val) * st->agi / 200)) - min(amotion, 200));
#else
// base weapon delay
- amotion = (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE)
- ? (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
- : (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield
+ amotion = (sd->weapontype < MAX_SINGLE_WEAPON_TYPE)
+ ? (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype]) // single weapon
+ : (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2]) * 7 / 10; // dual-wield
// percentual delay reduction from stats
amotion -= amotion * (4 * st->agi + st->dex) / 1000;
@@ -4243,14 +4261,17 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st)
return amotion;
}
-unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) {
+static int status_base_atk(const struct block_list *bl, const struct status_data *st)
+{
int flag = 0, str, dex, dstr;
+ nullpo_ret(bl);
+ nullpo_ret(st);
if ( !(bl->type&battle_config.enable_baseatk) )
return 0;
if (bl->type == BL_PC) {
- switch (BL_UCCAST(BL_PC, bl)->status.weapon) {
+ switch (BL_UCCAST(BL_PC, bl)->weapontype) {
case W_BOW:
case W_MUSICAL:
case W_WHIP:
@@ -4297,34 +4318,61 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_
if (bl->type == BL_PC)
str += dex / 5 + st->luk / 5;
#endif // RENEWAL
- return cap_value(str, 0, USHRT_MAX);
+ return cap_value(str, battle_config.batk_min, battle_config.batk_max);
}
-#ifndef RENEWAL
-static inline unsigned short status_base_matk_min(const struct status_data *st) { return st->int_ + (st->int_ / 7)*(st->int_ / 7); }
-#endif // not RENEWAL
-static inline unsigned short status_base_matk_max(const struct status_data *st) { return st->int_ + (st->int_ / 5)*(st->int_ / 5); }
+static int status_base_matk_min(const struct status_data *st)
+{
+ nullpo_ret(st);
+#ifdef RENEWAL
+ Assert_ret(0);
+ return 0;
+#else // not RENEWAL
+ int matk = st->int_ + (st->int_ / 7) * (st->int_ / 7);
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
+#endif // RENEWAL
+}
+
+static int status_base_matk_max(const struct status_data *st)
+{
+ nullpo_ret(st);
+ int matk = st->int_ + (st->int_ / 5) * (st->int_ / 5);
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
+}
-unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) {
+static int status_base_matk(struct block_list *bl, const struct status_data *st, int level)
+{
#ifdef RENEWAL
- switch ( bl->type ) {
+ nullpo_ret(bl);
+ nullpo_ret(st);
+ int matk = 0;
+ switch (bl->type) {
case BL_MOB:
- return st->int_ + level;
+ matk = st->int_ + level;
+ break;
case BL_HOM:
- return status_get_homint(st, BL_UCCAST(BL_HOM, bl)) + level;
+ matk = status_get_homint(st, BL_UCCAST(BL_HOM, bl)) + level;
+ break;
case BL_MER:
- return st->int_ + st->int_ / 5 * st->int_ / 5;
+ matk = st->int_ + st->int_ / 5 * st->int_ / 5;
+ break;
case BL_PC:
default: // temporary until all are formulated
- return st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4);
+ matk = st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4);
+ break;
}
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
#else
+ Assert_ret(0);
return 0;
#endif
}
//Fills in the misc data that can be calculated from the other status info (except for level)
-void status_calc_misc(struct block_list *bl, struct status_data *st, int level) {
+static void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
+{
+ nullpo_retv(bl);
+ nullpo_retv(st);
//Non players get the value set, players need to stack with previous bonuses.
if ( bl->type != BL_PC )
st->batk =
@@ -4350,8 +4398,8 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
st->mdef2 += (int)(bl->type == BL_PC ? (st->int_ + ((float)level / 4) + ((float)(st->dex + st->vit) / 5)) : ((float)(st->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
}
#else // not RENEWAL
- st->matk_min = status_base_matk_min(st);
- st->matk_max = status_base_matk_max(st);
+ st->matk_min = status->base_matk_min(st);
+ st->matk_max = status->base_matk_max(st);
st->hit += level + st->dex;
st->flee += level + st->agi;
st->def2 += st->vit;
@@ -4370,7 +4418,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
if ( st->batk ) {
int temp = st->batk + status->base_atk(bl, st);
- st->batk = cap_value(temp, 0, USHRT_MAX);
+ st->batk = cap_value(temp, battle_config.batk_min, battle_config.batk_max);
} else
st->batk = status->base_atk(bl, st);
if ( st->cri ) {
@@ -4386,7 +4434,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
break;
case BL_MER:
#ifdef RENEWAL
- st->matk_min = st->matk_max = status_base_matk_max(st);
+ st->matk_min = st->matk_max = status->base_matk_max(st);
st->def2 = st->vit + level / 10 + st->vit / 5;
st->mdef2 = level / 10 + st->int_ / 5;
#endif
@@ -4403,9 +4451,9 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
}
/*==========================================
-* Apply shared stat mods from status changes [DracoRPG]
-*------------------------------------------*/
-unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str)
+ * Apply shared stat mods from status changes [DracoRPG]
+ *------------------------------------------*/
+static unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str)
{
if(!sc || !sc->count)
return cap_value(str,0,USHRT_MAX);
@@ -4468,7 +4516,7 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
-unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi)
+static unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi)
{
if(!sc || !sc->count)
return cap_value(agi,0,USHRT_MAX);
@@ -4522,13 +4570,16 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_2011RWC])
agi += sc->data[SC_2011RWC]->val1;
- if(sc->data[SC_MARSHOFABYSS])
+ if (sc->data[SC_MARSHOFABYSS])
agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100;
+ if (sc->data[SC_ARCLOUSEDASH])
+ agi += sc->data[SC_ARCLOUSEDASH]->val2;
+
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
-unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit)
+static unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit)
{
if(!sc || !sc->count)
return cap_value(vit,0,USHRT_MAX);
@@ -4579,8 +4630,9 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
-unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_)
+static unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_)
{
+ nullpo_ret(bl);
if(!sc || !sc->count)
return cap_value(int_,0,USHRT_MAX);
@@ -4645,8 +4697,9 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
-unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex)
+static unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex)
{
+ nullpo_ret(bl);
if(!sc || !sc->count)
return cap_value(dex,0,USHRT_MAX);
@@ -4707,7 +4760,9 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
-unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) {
+static unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk)
+{
+ nullpo_ret(bl);
if (!sc || !sc->count)
return cap_value(luk, 0, USHRT_MAX);
@@ -4759,16 +4814,22 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
return (unsigned short)cap_value(luk, 0, USHRT_MAX);
}
-unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable)
+
+static int status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable)
{
+ nullpo_ret(bl);
if(!sc || !sc->count)
- return cap_value(batk,0,USHRT_MAX);
+ return cap_value(batk, battle_config.batk_min, battle_config.batk_max);
if( !viewable ){
/* some statuses that are hidden in the status window */
if(sc->data[SC_PLUSATTACKPOWER])
batk += sc->data[SC_PLUSATTACKPOWER]->val1;
- return (unsigned short)cap_value(batk,0,USHRT_MAX);
+ if (sc->data[SC_POPECOOKIE] != NULL)
+ batk += batk * sc->data[SC_POPECOOKIE]->val1 / 100;
+ if (sc->data[SC_VITALIZE_POTION] != NULL)
+ batk += batk * sc->data[SC_VITALIZE_POTION]->val1 / 100;
+ return cap_value(batk, battle_config.batk_min, battle_config.batk_max);
}
#ifndef RENEWAL
if(sc->data[SC_PLUSATTACKPOWER])
@@ -4807,9 +4868,6 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
#ifndef RENEWAL
if(sc->data[SC_LKCONCENTRATION])
batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100;
-#else
- if ( sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC )
- batk -= batk * sc->data[SC_NOEQUIPWEAPON]->val2 / 100;
#endif
if(sc->data[SC_SKE])
batk += batk * 3;
@@ -4850,14 +4908,22 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
batk += batk * sc->data[SC_2011RWC]->val2 / 100;
if (sc->data[SC_STEAMPACK])
batk += sc->data[SC_STEAMPACK]->val1;
+ if (sc->data[SC_SKF_ATK] != NULL)
+ batk += sc->data[SC_SKF_ATK]->val1;
+ if (sc->data[SC_ALMIGHTY] != NULL)
+ batk += sc->data[SC_ALMIGHTY]->val1;
+
+ if (sc->data[SC_SHRIMP])
+ batk += batk * sc->data[SC_SHRIMP]->val2 / 100;
- return (unsigned short)cap_value(batk,0,USHRT_MAX);
+ return cap_value(batk, battle_config.batk_min, battle_config.batk_max);
}
-unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable)
+static int status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable)
{
+ nullpo_ret(bl);
if(!sc || !sc->count)
- return cap_value(watk,0,USHRT_MAX);
+ return cap_value(watk, battle_config.watk_min, battle_config.watk_max);
if( !viewable ){
/* some statuses that are hidden in the status window */
@@ -4865,7 +4931,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk -= sc->data[SC_WATER_BARRIER]->val3;
if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2)
watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2;
- return (unsigned short)cap_value(watk,0,USHRT_MAX);
+ return cap_value(watk, battle_config.watk_min, battle_config.watk_max);
}
#ifndef RENEWAL
if(sc->data[SC_IMPOSITIO])
@@ -4908,7 +4974,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_LKCONCENTRATION])
watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100;
#endif
- if(sc->data[SC_INCATKRATE] && bl->type != BL_MOB)
+ if(sc->data[SC_INCATKRATE])
watk += watk * sc->data[SC_INCATKRATE]->val1/100;
if(sc->data[SC_PROVOKE])
watk += watk * sc->data[SC_PROVOKE]->val3/100;
@@ -4918,10 +4984,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += watk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC_CURSE])
watk -= watk * 25/100;
-#ifndef RENEWAL
if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC)
watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100;
-#endif
if(sc->data[SC__ENERVATION])
watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
if(sc->data[SC_RUSH_WINDMILL])
@@ -4942,14 +5006,17 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
if( sc->data[SC_FLASHCOMBO] )
watk += sc->data[SC_FLASHCOMBO]->val2;
+ if (sc->data[SC_CATNIPPOWDER])
+ watk -= watk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
- return (unsigned short)cap_value(watk,0,USHRT_MAX);
+ return cap_value(watk, battle_config.watk_min, battle_config.watk_max);
}
-unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) {
-#ifdef RENEWAL
+static int status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk)
+{
+#ifdef RENEWAL
if (!sc || !sc->count)
- return cap_value(matk,0,USHRT_MAX);
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
if (sc->data[SC_PLUSMAGICPOWER])
matk += sc->data[SC_PLUSMAGICPOWER]->val1;
if (sc->data[SC_MATKFOOD])
@@ -4968,21 +5035,28 @@ unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc
matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
if(sc->data[SC_IZAYOI])
matk += 25 * sc->data[SC_IZAYOI]->val1;
- return (unsigned short)cap_value(matk,0,USHRT_MAX);
+ if (sc->data[SC_SHRIMP])
+ matk += matk * sc->data[SC_SHRIMP]->val2 / 100;
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
#else
return 0;
#endif
}
-unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) {
+static int status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable)
+{
if (!sc || !sc->count)
- return cap_value(matk,0,USHRT_MAX);
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
if (!viewable) {
/* some statuses that are hidden in the status window */
if (sc->data[SC_MINDBREAKER])
matk += matk * sc->data[SC_MINDBREAKER]->val2 / 100;
- return (unsigned short)cap_value(matk, 0, USHRT_MAX);
+ if (sc->data[SC_POPECOOKIE] != NULL)
+ matk += matk * sc->data[SC_POPECOOKIE]->val2 / 100;
+ if (sc->data[SC_VITALIZE_POTION] != NULL)
+ matk += matk * sc->data[SC_VITALIZE_POTION]->val2 / 100;
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
}
#ifndef RENEWAL
@@ -5039,18 +5113,22 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
matk += matk * sc->data[SC_2011RWC]->val2 / 100;
if (sc->data[SC_MAGIC_CANDY])
matk += sc->data[SC_MAGIC_CANDY]->val1;
+ if (sc->data[SC_SKF_MATK] != NULL)
+ matk += sc->data[SC_SKF_MATK]->val1;
+ if (sc->data[SC_ALMIGHTY] != NULL)
+ matk += sc->data[SC_ALMIGHTY]->val2;
- return (unsigned short)cap_value(matk, 0, USHRT_MAX);
+ return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
}
-signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) {
-
+static int status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable)
+{
if (!sc || !sc->count)
- return cap_value(critical, 10, SHRT_MAX);
+ return cap_value(critical, battle_config.critical_min, battle_config.critical_max);
if (!viewable) {
/* some statuses that are hidden in the status window */
- return (short)cap_value(critical, 10, SHRT_MAX);
+ return cap_value(critical, battle_config.critical_min, battle_config.critical_max);
}
if (sc->data[SC_CRITICALPERCENT])
@@ -5081,20 +5159,20 @@ signed short status_calc_critical(struct block_list *bl, struct status_change *s
if (sc->data[SC_BUCHEDENOEL])
critical += sc->data[SC_BUCHEDENOEL]->val4 * 10;
- return (short)cap_value(critical, 10, SHRT_MAX);
+ return cap_value(critical, battle_config.critical_min, battle_config.critical_max);
}
-signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable)
+static int status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable)
{
if (!sc || !sc->count)
- return cap_value(hit, 1, SHRT_MAX);
+ return cap_value(hit, battle_config.hit_min, battle_config.hit_max);
if (!viewable) {
/* some statuses that are hidden in the status window */
if (sc->data[SC_MTF_ASPD])
hit += sc->data[SC_MTF_ASPD]->val2;
- return (short)cap_value(hit, 1, SHRT_MAX);
+ return cap_value(hit, battle_config.hit_min, battle_config.hit_max);
}
if (sc->data[SC_INCHIT])
@@ -5136,24 +5214,26 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
if (sc->data[SC_BUCHEDENOEL])
hit += sc->data[SC_BUCHEDENOEL]->val3;
- return (short)cap_value(hit, 1, SHRT_MAX);
+ return cap_value(hit, battle_config.hit_min, battle_config.hit_max);
}
-signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) {
+static int status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable)
+{
+ nullpo_retr(1, bl);
if (bl->type == BL_PC) {
if (map_flag_gvg2(bl->m))
flee -= flee * battle_config.gvg_flee_penalty / 100;
- else if( map->list[bl->m].flag.battleground )
+ else if (map->list[bl->m].flag.battleground)
flee -= flee * battle_config.bg_flee_penalty / 100;
}
if (!sc || !sc->count)
- return cap_value(flee, 1, SHRT_MAX);
+ return cap_value(flee, battle_config.flee_min, battle_config.flee_max);
if (!viewable) {
/* some statuses that are hidden in the status window */
- return (short)cap_value(flee, 1, SHRT_MAX);
+ return cap_value(flee, battle_config.flee_min, battle_config.flee_max);
}
if (sc->data[SC_INCFLEE])
@@ -5231,17 +5311,17 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
if (sc->data[SC_MYSTICPOWDER])
flee += sc->data[SC_MYSTICPOWDER]->val2;
- return (short)cap_value(flee, 1, SHRT_MAX);
+ return cap_value(flee, battle_config.flee_min, battle_config.flee_max);
}
-signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable)
+static int status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable)
{
if(!sc || !sc->count)
- return cap_value(flee2,10,SHRT_MAX);
+ return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max);
if( !viewable ){
/* some statuses that are hidden in the status window */
- return (short)cap_value(flee2,10,SHRT_MAX);
+ return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max);
}
if(sc->data[SC_PLUSAVOIDVALUE])
@@ -5253,10 +5333,12 @@ signed short status_calc_flee2(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_FREYJASCROLL])
flee2 += sc->data[SC_FREYJASCROLL]->val2;
- return (short)cap_value(flee2,10,SHRT_MAX);
+ return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max);
}
-defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable)
+
+static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable)
{
+ nullpo_retr(DEFTYPE_MIN, bl);
if (!sc || !sc->count)
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);
@@ -5359,8 +5441,9 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);
}
-signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable)
+static signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable)
{
+ nullpo_retr(1, bl);
if(!sc || !sc->count)
#ifdef RENEWAL
return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
@@ -5435,7 +5518,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
#endif
}
-defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) {
+static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable)
+{
if(!sc || !sc->count)
return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX);
@@ -5491,7 +5575,7 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md
return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX);
}
-signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable)
+static signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable)
{
if(!sc || !sc->count)
#ifdef RENEWAL
@@ -5530,22 +5614,25 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc,
#endif
}
-unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
+static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
{
struct map_session_data *sd = BL_CAST(BL_PC, bl);
- int speed_rate;
+ int speed_rate = -1;
if( sc == NULL || ( sd && sd->state.permanent_speed ) )
return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
- if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) )
+ if (sd && sd->ud.skilltimer != INVALID_TIMER)
{
- if( sd->ud.skill_id == LG_EXEEDBREAK )
+ if (sd->ud.skill_id == LG_EXEEDBREAK) {
speed_rate = 160 - 10 * sd->ud.skill_lv;
- else
+ } else if ((skill->get_inf2(sd->ud.skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
+ speed_rate = 175 - 5 * sd->ud.skill_lv;
+ } else if (pc->checkskill(sd, SA_FREECAST) > 0) {
speed_rate = 175 - 5 * pc->checkskill(sd,SA_FREECAST);
+ }
}
- else
+ if (speed_rate == -1)
{
speed_rate = 100;
@@ -5576,9 +5663,9 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
{
int val = 0;
- if( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 )
+ if ( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 ) {
val = 120 - 6 * pc->checkskill(sd,RG_TUNNELDRIVE);
- else
+ } else {
if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 )
val = sc->data[SC_CHASEWALK]->val3;
else
@@ -5644,12 +5731,14 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if (sc->data[SC_DEC_AGI] || sc->data[SC_QUAGMIRE] || sc->data[SC_DONTFORGETME])
return 0;
}
+ if (sc->data[SC_CATNIPPOWDER])
+ val = max(val, sc->data[SC_CATNIPPOWDER]->val3);
if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
}
-
- speed_rate += val;
+ }
+ speed_rate += val;
}
//GetMoveHasteValue1()
@@ -5666,7 +5755,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
val = max( val, 2 * sc->data[SC_WINDWALK]->val1 );
if( sc->data[SC_CARTBOOST] )
val = max( val, 20 );
- if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN && pc->checkskill(sd,TF_MISS) > 0 )
+ if (sd != NULL && (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN && pc->checkskill(sd,TF_MISS) > 0)
val = max( val, 1 * pc->checkskill(sd,TF_MISS) );
if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1 )
val = max( val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3 );
@@ -5694,6 +5783,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
val = max(val, sc->data[SC_MOVHASTE_HORSE]->val1);
if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup
val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) );
+ if (sc->data[SC_ARCLOUSEDASH])
+ val = max(val, sc->data[SC_ARCLOUSEDASH]->val3);
speed_rate -= val;
}
@@ -5726,10 +5817,12 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
// flag&1 - fixed value [malufett]
// flag&2 - percentage value
-short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) {
+static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag)
+{
#ifdef RENEWAL_ASPD
int pots = 0, bonus = 0;
+ nullpo_ret(bl);
if (!sc || !sc->count)
return 0;
@@ -5764,7 +5857,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
if (bl->type != BL_PC) {
bonus = sc->data[SC_ASSNCROS]->val2;
} else {
- switch (BL_UCCAST(BL_PC, bl)->status.weapon) {
+ switch (BL_UCCAST(BL_PC, bl)->weapontype) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
@@ -5848,6 +5941,8 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
bonus += sc->data[SC_BATTLESCROLL]->val1;
if (sc->data[SC_STEAMPACK])
bonus += sc->data[SC_STEAMPACK]->val2;
+ if (sc->data[SC_SKF_ASPD] != NULL)
+ bonus += sc->data[SC_SKF_ASPD]->val1;
}
return (bonus + pots);
@@ -5856,7 +5951,9 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
#endif
}
-short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) {
+static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd)
+{
+ nullpo_ret(bl);
if (!sc || !sc->count)
return cap_value(aspd, 0, 2000);
@@ -5874,10 +5971,11 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int
/// Calculates an object's ASPD modifier (alters the base amotion value).
/// Note that the scale of aspd_rate is 1000 = 100%.
-short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
+static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
{
int i;
+ nullpo_ret(bl);
if(!sc || !sc->count)
return cap_value(aspd_rate,0,SHRT_MAX);
@@ -5922,7 +6020,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
if (bl->type != BL_PC) {
max = sc->data[SC_ASSNCROS]->val2;
} else {
- switch (BL_UCCAST(BL_PC, bl)->status.weapon) {
+ switch (BL_UCCAST(BL_PC, bl)->weapontype) {
case W_BOW:
case W_REVOLVER:
case W_RIFLE:
@@ -6012,12 +6110,15 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
aspd_rate += sc->data[SC_BATTLESCROLL]->val1 * 10;
if (sc->data[SC_STEAMPACK])
aspd_rate += sc->data[SC_STEAMPACK]->val2 * 10;
+ if (sc->data[SC_SKF_ASPD] != NULL)
+ aspd_rate -= sc->data[SC_SKF_ASPD]->val1 * 10;
return (short)cap_value(aspd_rate,0,SHRT_MAX);
}
-unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion)
+static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion)
{
+ nullpo_ret(bl);
// It has been confirmed on official servers that MvP mobs have no dmotion even without endure
if (bl->type == BL_MOB && (BL_UCCAST(BL_MOB, bl)->status.mode&MD_BOSS))
return 0;
@@ -6033,7 +6134,8 @@ unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *
return (unsigned short)cap_value(dmotion,0,USHRT_MAX);
}
-unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp) {
+static unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp)
+{
if (!sc || !sc->count)
return (unsigned int)cap_value(maxhp, 1, UINT_MAX);
@@ -6112,8 +6214,8 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc,
return (unsigned int)cap_value(maxhp, 1, UINT_MAX);
}
-unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) {
-
+static unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp)
+{
if (!sc || !sc->count)
return cap_value(maxsp, 1, UINT_MAX);
@@ -6151,7 +6253,7 @@ unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc,
return cap_value(maxsp, 1, UINT_MAX);
}
-unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element)
+static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element)
{
if(!sc || !sc->count)
return element;
@@ -6172,7 +6274,7 @@ unsigned char status_calc_element(struct block_list *bl, struct status_change *s
return (unsigned char)cap_value(element,0,UCHAR_MAX);
}
-unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv)
+static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv)
{
if(!sc || !sc->count)
return lv;
@@ -6195,7 +6297,7 @@ unsigned char status_calc_element_lv(struct block_list *bl, struct status_change
return (unsigned char)cap_value(lv,1,4);
}
-unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element)
+static unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element)
{
if(!sc || !sc->count)
return element;
@@ -6236,7 +6338,7 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
* @param mode The starting mode.
* @return The calculated mode.
*/
-uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode)
+static uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode)
{
if (sc == NULL || sc->count == 0)
return mode & MD_MASK;
@@ -6257,7 +6359,7 @@ uint32 status_calc_mode(const struct block_list *bl, const struct status_change
* @param bl The requested bl.
* @return The bl's name or NULL if not available.
*/
-const char *status_get_name(const struct block_list *bl)
+static const char *status_get_name(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
@@ -6277,17 +6379,17 @@ const char *status_get_name(const struct block_list *bl)
}
/*==========================================
-* Get the class of the current bl
-* return
-* 0 = fail
-* class_id = success
-*------------------------------------------*/
-int status_get_class(const struct block_list *bl)
+ * Get the class of the current bl
+ * return
+ * 0 = fail
+ * class_id = success
+ *------------------------------------------*/
+static int status_get_class(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
- case BL_PC: return BL_UCCAST(BL_PC, bl)->status.class_;
- case BL_MOB: return BL_UCCAST(BL_MOB, bl)->vd->class_; //Class used on all code should be the view class of the mob.
+ case BL_PC: return BL_UCCAST(BL_PC, bl)->status.class;
+ case BL_MOB: return BL_UCCAST(BL_MOB, bl)->vd->class; //Class used on all code should be the view class of the mob.
case BL_PET: return BL_UCCAST(BL_PET, bl)->pet.class_;
case BL_HOM: return BL_UCCAST(BL_HOM, bl)->homunculus.class_;
case BL_MER: return BL_UCCAST(BL_MER, bl)->mercenary.class_;
@@ -6297,12 +6399,12 @@ int status_get_class(const struct block_list *bl)
return 0;
}
/*==========================================
-* Get the base level of the current bl
-* return
-* 1 = fail
-* level = success
-*------------------------------------------*/
-int status_get_lv(const struct block_list *bl)
+ * Get the base level of the current bl
+ * return
+ * 1 = fail
+ * level = success
+ *------------------------------------------*/
+static int status_get_lv(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
@@ -6317,7 +6419,7 @@ int status_get_lv(const struct block_list *bl)
return 1;
}
-struct regen_data *status_get_regen_data(struct block_list *bl)
+static struct regen_data *status_get_regen_data(struct block_list *bl)
{
nullpo_retr(NULL, bl);
switch (bl->type) {
@@ -6330,7 +6432,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl)
}
}
-struct status_data *status_get_status_data(struct block_list *bl)
+static struct status_data *status_get_status_data(struct block_list *bl)
{
nullpo_retr(&status->dummy, bl);
@@ -6351,7 +6453,7 @@ struct status_data *status_get_status_data(struct block_list *bl)
}
}
-struct status_data *status_get_base_status(struct block_list *bl)
+static struct status_data *status_get_base_status(struct block_list *bl)
{
nullpo_retr(NULL, bl);
switch (bl->type) {
@@ -6374,7 +6476,9 @@ struct status_data *status_get_base_status(struct block_list *bl)
return NULL;
}
}
-defType status_get_def(struct block_list *bl) {
+
+static defType status_get_def(struct block_list *bl)
+{
struct unit_data *ud;
struct status_data *st = status->get_status_data(bl);
int def = st ? st->def : 0;
@@ -6385,14 +6489,15 @@ defType status_get_def(struct block_list *bl) {
return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX);
}
-unsigned short status_get_speed(struct block_list *bl)
+static unsigned short status_get_speed(struct block_list *bl)
{
+ nullpo_ret(bl);
if (bl->type == BL_NPC) //Only BL with speed data but no status_data [Skotlex]
return BL_UCCAST(BL_NPC, bl)->speed;
return status->get_status_data(bl)->speed;
}
-int status_get_party_id(const struct block_list *bl)
+static int status_get_party_id(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
@@ -6448,7 +6553,7 @@ int status_get_party_id(const struct block_list *bl)
return 0;
}
-int status_get_guild_id(const struct block_list *bl)
+static int status_get_guild_id(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
@@ -6514,7 +6619,7 @@ int status_get_guild_id(const struct block_list *bl)
return 0;
}
-int status_get_emblem_id(const struct block_list *bl)
+static int status_get_emblem_id(const struct block_list *bl)
{
nullpo_ret(bl);
switch (bl->type) {
@@ -6576,7 +6681,7 @@ int status_get_emblem_id(const struct block_list *bl)
return 0;
}
-int status_get_mexp(const struct block_list *bl)
+static int status_get_mexp(const struct block_list *bl)
{
nullpo_ret(bl);
if (bl->type == BL_MOB)
@@ -6586,7 +6691,7 @@ int status_get_mexp(const struct block_list *bl)
return 0;
}
-int status_get_race2(const struct block_list *bl)
+static int status_get_race2(const struct block_list *bl)
{
nullpo_ret(bl);
if (bl->type == BL_MOB)
@@ -6596,12 +6701,13 @@ int status_get_race2(const struct block_list *bl)
return 0;
}
-int status_isdead(struct block_list *bl) {
+static int status_isdead(struct block_list *bl)
+{
nullpo_ret(bl);
return status->get_status_data(bl)->hp == 0;
}
-int status_isimmune(struct block_list *bl)
+static int status_isimmune(struct block_list *bl)
{
struct status_change *sc = NULL;
nullpo_ret(bl);
@@ -6618,14 +6724,14 @@ int status_isimmune(struct block_list *bl)
return 0;
}
-struct view_data *status_get_viewdata(struct block_list *bl)
+static struct view_data *status_get_viewdata(struct block_list *bl)
{
nullpo_retr(NULL, bl);
switch (bl->type) {
case BL_PC: return &BL_UCAST(BL_PC, bl)->vd;
case BL_MOB: return BL_UCAST(BL_MOB, bl)->vd;
case BL_PET: return &BL_UCAST(BL_PET, bl)->vd;
- case BL_NPC: return BL_UCAST(BL_NPC, bl)->vd;
+ case BL_NPC: return &BL_UCAST(BL_NPC, bl)->vd;
case BL_HOM: return BL_UCAST(BL_HOM, bl)->vd;
case BL_MER: return BL_UCAST(BL_MER, bl)->vd;
case BL_ELEM: return BL_UCAST(BL_ELEM, bl)->vd;
@@ -6633,7 +6739,7 @@ struct view_data *status_get_viewdata(struct block_list *bl)
return NULL;
}
-void status_set_viewdata(struct block_list *bl, int class_)
+static void status_set_viewdata(struct block_list *bl, int class_)
{
struct view_data* vd;
nullpo_retv(bl);
@@ -6678,36 +6784,33 @@ void status_set_viewdata(struct block_list *bl, int class_)
break;
}
}
- sd->vd.class_ = class_;
+ sd->vd.class = class_;
clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield);
- sd->vd.head_top = sd->status.head_top;
- sd->vd.head_mid = sd->status.head_mid;
- sd->vd.head_bottom = sd->status.head_bottom;
+ sd->vd.head_top = sd->status.look.head_top;
+ sd->vd.head_mid = sd->status.look.head_mid;
+ sd->vd.head_bottom = sd->status.look.head_bottom;
sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style);
sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color);
sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color);
- sd->vd.robe = sd->status.robe;
+ sd->vd.robe = sd->status.look.robe;
sd->vd.body_style = sd->status.body;
sd->vd.sex = sd->status.sex;
if (sd->vd.cloth_color) {
- if (sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette)
- sd->vd.cloth_color = 0;
- if (sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette)
- sd->vd.cloth_color = 0;
- if (sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette)
- sd->vd.cloth_color = 0;
- if (sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette)
- sd->vd.cloth_color = 0;
- if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */)
+ if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true)
+ sd->vd.cloth_color = 0;
+ if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true)
+ sd->vd.cloth_color = 0;
+ if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true)
+ sd->vd.cloth_color = 0;
+ if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true)
+ sd->vd.cloth_color = 0;
+ if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true)
+ sd->vd.cloth_color = 0;
+ if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true)
sd->vd.cloth_color = 0;
}
- if (sd->vd.body_style
- && (sd->sc.option&OPTION_WEDDING
- || sd->sc.option&OPTION_XMAS
- || sd->sc.option&OPTION_SUMMER
- || sd->sc.option&OPTION_HANBOK
- || sd->sc.option&OPTION_OKTOBERFEST))
+ if (sd->vd.body_style != 0 && (sd->sc.option & OPTION_COSTUME) != 0)
sd->vd.body_style = 0;
} else if (vd != NULL) {
memcpy(&sd->vd, vd, sizeof(struct view_data));
@@ -6730,7 +6833,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
struct pet_data *pd = BL_UCAST(BL_PET, bl);
if (vd != NULL) {
memcpy(&pd->vd, vd, sizeof(struct view_data));
- if (!pc->db_checkid(vd->class_)) {
+ if (!pc->db_checkid(vd->class)) {
pd->vd.hair_style = battle_config.pet_hair_style;
if(pd->pet.equip) {
pd->vd.head_bottom = itemdb_viewid(pd->pet.equip);
@@ -6746,10 +6849,14 @@ void status_set_viewdata(struct block_list *bl, int class_)
case BL_NPC:
{
struct npc_data *nd = BL_UCAST(BL_NPC, bl);
- if (vd != NULL)
- nd->vd = vd;
- else
+ if (vd != NULL) {
+ memcpy(&nd->vd, vd, sizeof(struct view_data));
+ } else if (pc->db_checkid(class_)) {
+ memset(&nd->vd, 0, sizeof(struct view_data));
+ nd->vd.class = class_;
+ } else {
ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name);
+ }
}
break;
case BL_HOM: //[blackhole89]
@@ -6783,7 +6890,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
}
/// Returns the status_change data of bl or NULL if it doesn't exist.
-struct status_change *status_get_sc(struct block_list *bl)
+static struct status_change *status_get_sc(struct block_list *bl)
{
if (bl != NULL) {
switch (bl->type) {
@@ -6798,7 +6905,8 @@ struct status_change *status_get_sc(struct block_list *bl)
return NULL;
}
-void status_change_init(struct block_list *bl) {
+static void status_change_init(struct block_list *bl)
+{
struct status_change *sc = status->get_sc(bl);
nullpo_retv(sc);
memset(sc, 0, sizeof (struct status_change));
@@ -6810,7 +6918,8 @@ void status_change_init(struct block_list *bl) {
* @see status_change_start for the expected parameters.
* @return the adjusted duration based on flag values.
*/
-int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) {
+static int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag)
+{
//Percentual resistance: 10000 = 100% Resist
//Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms
int sc_def = 0, tick_def = -1; //-1 = use sc_def
@@ -6864,6 +6973,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sd = BL_CAST(BL_PC,bl);
st = status->get_status_data(bl);
bst = status->get_base_status(bl);
+ nullpo_ret(bst);
sc = status->get_sc(bl);
if( sc && !sc->count )
sc = NULL;
@@ -7157,6 +7267,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_NETHERWORLD:
tick = max(tick, 4000);
break;
+ case SC_SIREN:
+ tick = max(tick, 10000); // Minimum duration 10s
+ break;
default:
//Skills need to trigger even if the duration is reduced below 1ms
tick = max(tick, 1);
@@ -7167,11 +7280,14 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
#undef SCDEF_LVL_CAP
#undef SCDEF_LVL_DIFF
}
+
/* [Ind/Hercules] fast-checkin sc-display array */
-void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) {
+static void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3)
+{
struct sc_display_entry *entry;
int i;
+ nullpo_retv(sd);
for( i = 0; i < sd->sc_display_count; i++ ) {
if( sd->sc_display[i]->type == type )
break;
@@ -7194,9 +7310,12 @@ void status_display_add(struct map_session_data *sd, enum sc_type type, int dval
RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count);
sd->sc_display[ sd->sc_display_count - 1 ] = entry;
}
-void status_display_remove(struct map_session_data *sd, enum sc_type type) {
+
+static void status_display_remove(struct map_session_data *sd, enum sc_type type)
+{
int i;
+ nullpo_retv(sd);
for( i = 0; i < sd->sc_display_count; i++ ) {
if( sd->sc_display[i]->type == type )
break;
@@ -7226,8 +7345,9 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
}
}
}
+
/**
- * Starts a status change.
+ * Starts a status change with a set remaining time.
*
* @param src Status change source bl.
* @param bl Status change target bl.
@@ -7237,13 +7357,15 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
* @param val2 Additional value (meaning depends on type).
* @param val3 Additional value (meaning depends on type).
* @param val4 Additional value (meaning depends on type).
- * @param tick Base duration (milliseconds).
+ * @param tick Remaining duration (miliseconds). (if flag doesn't contain SCFLAG_LOADED, it will become the final total_tick)
+ * @param total_tick Base duration (milliseconds).
* @param flag Special flags (@see enum scstart_flag).
*
* @retval 0 if no status change happened.
* @retval 1 if the status change was successfully applied.
*/
-int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) {
+static int status_change_start_sub(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int total_tick, int flag)
+{
struct map_session_data *sd = NULL;
struct status_change* sc;
struct status_change_entry* sce;
@@ -7256,7 +7378,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
st = status->get_status_data(bl);
if (type <= SC_NONE || type >= SC_MAX) {
- ShowError("status_change_start: invalid status change (%d)!\n", type);
+ ShowError("status_change_start_sub: invalid status change (%d)!\n", type);
return 0;
}
@@ -7276,84 +7398,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
#endif // 0
}
- if( sc->data[SC_REFRESH] ) {
- if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
- return 0; // Immune to status ailements
- switch( type ) {
- case SC_DEEP_SLEEP:
- case SC__CHAOS:
- case SC_BURNING:
- case SC_STUN:
- case SC_SLEEP:
- case SC_CURSE:
- case SC_STONE:
- case SC_POISON:
- case SC_BLIND:
- case SC_SILENCE:
- case SC_BLOODING:
- case SC_FREEZE:
- case SC_FROSTMISTY:
- case SC_COLD:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_MARSHOFABYSS:
- case SC_MANDRAGORA:
- return 0;
- }
- } else if( sc->data[SC_INSPIRATION] ) {
- if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX )
- return 0; // Immune to status ailements
- switch( type ) {
- case SC_POISON:
- case SC_BLIND:
- case SC_STUN:
- case SC_SILENCE:
- case SC__CHAOS:
- case SC_STONE:
- case SC_SLEEP:
- case SC_BLOODING:
- case SC_CURSE:
- case SC_BURNING:
- case SC_FROSTMISTY:
- case SC_FREEZE:
- case SC_COLD:
- case SC_FEAR:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- case SC_DEEP_SLEEP:
- case SC_SATURDAY_NIGHT_FEVER:
- case SC__BODYPAINT:
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__IGNORANCE:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
- return 0;
- }
- }
+ if (status->is_immune_to_status(sc, type))
+ return 0;
sd = BL_CAST(BL_PC, bl);
- //Adjust tick according to status resistances
+ //Adjust total_tick according to status resistances
if( !(flag&(SCFLAG_NOAVOID|SCFLAG_LOADED)) ) {
- tick = status->get_sc_def(src, bl, type, rate, tick, flag);
- if( !tick ) return 0;
+ total_tick = status->get_sc_def(src, bl, type, rate, total_tick, flag);
+ if( !total_tick ) return 0;
}
- undead_flag = battle->check_undead(st->race,st->def_ele);
- //Check for inmunities / sc fails
+ undead_flag = battle->check_undead(st->race, st->def_ele);
+ // Check for inmunities / sc fails
switch (type) {
case SC_DRUMBATTLE:
case SC_NIBELUNGEN:
@@ -7366,8 +7423,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_GOLDENE_FERSE:
if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS])
|| (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
- )
+ ) {
return 0;
+ }
+ FALLTHROUGH
case SC_VACUUM_EXTREME:
if(sc->data[SC_HALLUCINATIONWALK])
return 0;
@@ -7375,10 +7434,15 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_STONE:
if(sc->data[SC_POWER_OF_GAIA])
return 0;
+ FALLTHROUGH
case SC_FREEZE:
//Undead are immune to Freeze/Stone
if (undead_flag && !(flag&SCFLAG_NOAVOID))
return 0;
+ // SC_LEXAETERNA should be removed when applying SC_STONE or SC_FREEZE
+ if (sc->data[SC_LEXAETERNA] != NULL)
+ status_change_end(bl, SC_LEXAETERNA, INVALID_TIMER);
+ FALLTHROUGH
case SC_SLEEP:
case SC_STUN:
case SC_FROSTMISTY:
@@ -7405,12 +7469,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
break;
case SC_KYRIE:
+ case SC_TUNAPARTY:
if (bl->type == BL_MOB)
return 0;
break;
case SC_OVERTHRUST:
if (sc->data[SC_OVERTHRUSTMAX])
return 0; // Overthrust can't take effect if under Max Overthrust. [Skotlex]
+ FALLTHROUGH
case SC_OVERTHRUSTMAX:
if (sc->option&OPTION_MADOGEAR)
return 0; // Overthrust and Overthrust Max cannot be used on Mado Gear [Ind]
@@ -7428,7 +7494,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
break;
case SC_MAGNIFICAT:
- if (sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR) // Mado is immune to magnificat
+ if (sc->option&OPTION_MADOGEAR) // Mado is immune to magnificat
return 0;
break;
case SC_ONEHANDQUICKEN:
@@ -7436,6 +7502,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_TWOHANDQUICKEN:
if (sc->data[SC_DEC_AGI])
return 0;
+ FALLTHROUGH
case SC_CONCENTRATION:
case SC_SPEARQUICKEN:
case SC_TRUESIGHT:
@@ -7444,6 +7511,7 @@ 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]
+ FALLTHROUGH
case SC_INC_AGI:
if (sc->data[SC_QUAGMIRE])
return 0;
@@ -7492,11 +7560,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
if (!opt_flag) return 0;
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPSHIELD:
- if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
- else
+ if (val2 == 1) {
+ val2 = 0; //GX effect. Do not take shield off..
+ } else {
if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_SHIELD)
@@ -7506,8 +7575,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
+ }
+ if (total_tick == 1)
+ return 1; //Minimal duration: Only strip without causing the SC
+ break;
case SC_NOEQUIPARMOR:
if (sd && !(flag&SCFLAG_LOADED)) {
int i;
@@ -7518,7 +7589,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPHELM:
if (sd && !(flag&SCFLAG_LOADED)) {
@@ -7530,7 +7601,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_MER_FLEE:
case SC_MER_ATK:
@@ -7564,30 +7635,6 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1)
return 0;
break;
- case SC_FOOD_STR_CASH:
- if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_AGI_CASH:
- if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_VIT_CASH:
- if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_INT_CASH:
- if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_DEX_CASH:
- if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_LUK_CASH:
- if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1)
- return 0;
- break;
case SC_CAMOUFLAGE:
if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) )
return 0;
@@ -7608,7 +7655,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if( i < 0 )
return 0;
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_TOXIN:
case SC_PARALYSE:
@@ -7628,305 +7675,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if(sc->data[SC_HOVERING])
return 0;
break;
- case SC_OFFERTORIUM:
- if (sc->data[SC_MAGNIFICAT])
- return 0;
- break;
}
//Check for BOSS resistances
- if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) {
- if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ if (st->mode & MD_BOSS && !(flag & SCFLAG_NOAVOID)) {
+ if (status->is_boss_resist_sc(type))
return 0;
- switch (type) {
- case SC_BLESSING:
- case SC_DEC_AGI:
- case SC_PROVOKE:
- case SC_COMA:
- case SC_GRAVITATION:
- case SC_NJ_SUITON:
- case SC_RICHMANKIM:
- case SC_ROKISWEIL:
- case SC_FOGWALL:
- case SC_FROSTMISTY:
- case SC_BURNING:
- case SC_MARSHOFABYSS:
- case SC_ADORAMUS:
- case SC_NEEDLE_OF_PARALYZE:
- case SC_DEEP_SLEEP:
- case SC_COLD:
-
- // Exploit prevention - kRO Fix
- case SC_PYREXIA:
- case SC_DEATHHURT:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
-
- // Ranger Effects
- case SC_WUGBITE:
- case SC_ELECTRICSHOCKER:
- case SC_MAGNETICFIELD:
-
- // Masquerades
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
- case SC__IGNORANCE:
-
- // Other Effects
- case SC_VACUUM_EXTREME:
- case SC_NETHERWORLD:
-
- return 0;
- }
}
//Before overlapping fail, one must check for status cured.
- switch (type) {
- case SC_BLESSING:
- //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
- //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
- if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) {
- status_change_end(bl, SC_CURSE, INVALID_TIMER);
- if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
- status_change_end(bl, SC_STONE, INVALID_TIMER);
- }
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_INC_AGI:
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_QUAGMIRE:
- status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- //Also blocks the ones below...
- case SC_DEC_AGI:
- case SC_ADORAMUS:
- status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
- //Also blocks the ones below...
- case SC_DONTFORGETME:
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
- status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
- break;
- case SC_ONEHANDQUICKEN:
- //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- case SC_OVERTHRUSTMAX:
- //Cancels Normal Overthrust. [Skotlex]
- status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
- break;
- case SC_KYRIE:
- //Cancels Assumptio
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_DELUGE:
- if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
- status_change_end(bl, SC_BLIND, INVALID_TIMER);
- break;
- case SC_SILENCE:
- if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
- status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
- break;
- case SC_HIDING:
- status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
- status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- break;
- case SC_BERSERK:
- if( val3 == SC__BLOODYLUST )
- break;
- if(battle_config.berserk_cancels_buffs) {
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_PARRYING, INVALID_TIMER);
- status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
- status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- }
- #ifdef RENEWAL
- else {
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- }
- #endif
- break;
- case SC_ASSUMPTIO:
- status_change_end(bl, SC_KYRIE, INVALID_TIMER);
- status_change_end(bl, SC_KAITE, INVALID_TIMER);
- break;
- case SC_KAITE:
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_CARTBOOST:
- if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) {
- //Cancel Decrease Agi, but take no further effect [Skotlex]
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
- return 0;
- }
- break;
- case SC_FUSION:
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_GS_ADJUSTMENT:
- status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
- break;
- case SC_GS_MADNESSCANCEL:
- status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
- break;
- //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
- case SC_PROPERTYUNDEAD:
- status_change_end(bl, SC_BLESSING, INVALID_TIMER);
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_STR:
- status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_AGI:
- status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_VIT:
- status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_INT:
- status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_DEX:
- status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_LUK:
- status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_STR_CASH:
- status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
- break;
- case SC_FOOD_AGI_CASH:
- status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_VIT_CASH:
- status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
- break;
- case SC_FOOD_INT_CASH:
- status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
- break;
- case SC_FOOD_DEX_CASH:
- status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
- break;
- case SC_FOOD_LUK_CASH:
- status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
- break;
- case SC_GM_BATTLE:
- status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER);
- break;
- case SC_GM_BATTLE2:
- status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER);
- break;
- case SC_ENDURE:
- if( val4 == 1 )
- 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:
- status_change_end(bl, SC_INCAGI, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- //Group A Status (doesn't overlap)
- case SC_SWING:
- case SC_SYMPHONY_LOVE:
- case SC_MOONLIT_SERENADE:
- case SC_RUSH_WINDMILL:
- case SC_ECHOSONG:
- case SC_HARMONIZE:
- case SC_FRIGG_SONG:
- if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
- if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
- if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
- if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
- if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
- if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
- if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
- break;
- //Group B Status
- case SC_SIREN:
- case SC_DEEP_SLEEP:
- case SC_SIRCLEOFNATURE:
- case SC_LERADS_DEW:
- case SC_MELODYOFSINK:
- case SC_BEYOND_OF_WARCRY:
- case SC_UNLIMITED_HUMMING_VOICE:
- case SC_GLOOMYDAY:
- case SC_SONG_OF_MANA:
- case SC_DANCE_WITH_WUG:
- if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
- if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
- if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
- if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
- if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
- if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
- if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
- if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
- if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- break;
- case SC_REFLECTSHIELD:
- status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
- break;
- case SC_LG_REFLECTDAMAGE:
- status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
- break;
- case SC_SHIELDSPELL_DEF:
- case SC_SHIELDSPELL_MDEF:
- case SC_SHIELDSPELL_REF:
- status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
- break;
- case SC_GENTLETOUCH_ENERGYGAIN:
- case SC_GENTLETOUCH_CHANGE:
- case SC_GENTLETOUCH_REVITALIZE:
- if( type != SC_GENTLETOUCH_REVITALIZE )
- status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_ENERGYGAIN )
- status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_CHANGE )
- status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
- break;
- case SC_INVINCIBLE:
- status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
- break;
- case SC_INVINCIBLEOFF:
- status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
- break;
- case SC_MAGICPOWER:
- status_change_end(bl, type, INVALID_TIMER);
- break;
- }
+ if (status->end_sc_before_start(bl, st, sc, type, undead_flag, val1, val2, val3, val4))
+ return 0;
//Check for overlapping fails
if( (sce = sc->data[type]) ) {
@@ -8026,6 +7785,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_LERADS_DEW:
if (sc && sc->data[SC_BERSERK])
return 0;
+ FALLTHROUGH
case SC_SHAPESHIFT:
case SC_PROPERTYWALK:
break;
@@ -8038,6 +7798,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_JOINTBEAT:
val2 |= sce->val2; // stackable ailments
+ FALLTHROUGH
default:
if(sce->val1 > val1)
return 1; //Return true to not mess up skill animations. [Skotlex]
@@ -8048,9 +7809,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
calc_flag = status->dbs->ChangeFlagTable[type];
if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs
switch(type) {
+ case SC_AUTOTRADE:
+ case SC_KSPROTECTED:
+ break; // Prevent calling status_change_start_unknown_sc().
case SC_ADORAMUS:
sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
// Fall through to SC_INC_AGI
+ FALLTHROUGH
case SC_DEC_AGI:
case SC_INC_AGI:
val2 = 2 + val1; //Agi change
@@ -8063,33 +7828,33 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
int i;
for( i = 0; i < MAX_PC_DEVOTION; i++ ) {
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL)
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
} else if (bl->type == BL_MER) {
struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
if (mc->devotion_flag && (tsd = mc->master) != NULL) {
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
}
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if (val4)
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_AUTOBERSERK:
if (st->hp < st->max_hp>>2 &&
(!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0))
sc_start4(src,bl,SC_PROVOKE,100,10,1,0,0,60000);
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_CRUCIS:
val2 = 10 + 4*val1; //Def reduction
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
clif->emotion(bl,E_SWT);
break;
case SC_MAXIMIZEPOWER:
- tick_time = val2 = tick>0?tick:60000;
- tick = INFINITE_DURATION; // duration sent to the client should be infinite
+ tick_time = val2 = total_tick>0?total_tick:60000;
+ total_tick = INFINITE_DURATION; // duration sent to the client should be infinite
break;
case SC_EDP: // [Celest]
//Chance to Poison enemies.
@@ -8100,7 +7865,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
#endif
val3 = 50 * (val1 + 1); //Damage increase (+50 +50*lv%)
if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds
- tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000;
+ total_tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000;
break;
case SC_POISONREACT:
val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex]
@@ -8130,10 +7895,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_SACRIFICE:
val2 = 5; //Lasts 5 hits
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_ENCHANTPOISON:
val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate
+ FALLTHROUGH
case SC_ASPERSIO:
case SC_PROPERTYFIRE:
case SC_PROPERTYWATER:
@@ -8166,12 +7932,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
int i;
for( i = 0; i < MAX_PC_DEVOTION; i++ ) {
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL)
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
} else if (bl->type == BL_MER) {
struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
if (mc->devotion_flag && (tsd = mc->master) != NULL) {
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
}
}
@@ -8220,7 +7986,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
#endif
break;
case SC_NJ_SUITON:
- if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) {
+ if (val2 == 0 || (sd != NULL && (sd->job & MAPID_BASEMASK) == MAPID_NINJA)) {
//No penalties.
val2 = 0; //Agi penalty
val3 = 0; //Walk speed penalty
@@ -8250,9 +8016,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//val3 : Brings the skill_lv (merged into val1 here)
//val4 : Partner
if (val1 == CG_MOONLIT)
- clif->status_change(bl,SI_MOON,1,tick,0, 0, 0);
+ clif->status_change(bl, status->get_sc_icon(SC_MOON), status->get_sc_relevant_bl_types(SC_MOON), 1, total_tick, 0, 0, 0);
val1|= (val3<<16);
- val3 = tick/1000; //Tick duration
+ val3 = total_tick/1000; //Tick duration
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_LONGING:
@@ -8278,8 +8044,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_SUMMER:
case SC_HANBOK:
case SC_OKTOBERFEST:
- if (!vd) return 0;
- //Store previous values as they could be removed.
+ case SC_DRESS_UP:
+ if (vd == NULL)
+ return 0;
+ // Store previous values as they could be removed.
unit->stop_attack(bl);
break;
case SC_NOCHAT:
@@ -8287,8 +8055,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
// mmocharstatus.manner, each negative point results in 1 minute with this status activated
// This is done this way because the message that the client displays is hardcoded, and only
// shows how many minutes are remaining. [Panikon]
- tick = 60000;
- val1 = battle_config.manner_system; //Mute filters.
+ total_tick = 60000;
if (sd)
{
clif->changestatus(sd,SP_MANNER,sd->status.manner);
@@ -8297,11 +8064,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_STONE:
- val3 = tick/1000; //Petrified HP-damage iterations.
+ val3 = total_tick/1000; //Petrified HP-damage iterations.
if(val3 < 1) val3 = 1;
- tick = val4; //Petrifying time.
+ total_tick = val4; //Petrifying time.
if(val4 > 500) // not with WL_SIENNAEXECRATE
- tick = max(tick, 1000); //Min time
+ total_tick = max(total_tick, 1000); //Min time
calc_flag = 0; //Actual status changes take effect on petrified state.
break;
@@ -8320,7 +8087,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
// fall through
case SC_POISON:
- val3 = tick/1000; //Damage iterations
+ val3 = total_tick/1000; //Damage iterations
if(val3 < 1) val3 = 1;
tick_time = 1000; // [GodLesZ] tick time
//val4: HP damage
@@ -8334,7 +8101,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
clif->emotion(bl,E_WHAT);
break;
case SC_BLOODING:
- val4 = tick/10000;
+ val4 = total_tick/10000;
if (!val4) val4 = 1;
tick_time = 10000; // [GodLesZ] tick time
break;
@@ -8347,7 +8114,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
// val2 = seconds between heals
// val4 = total of heals
if (val2 < 1) val2 = 1;
- if ((val4 = tick / (val2 * 1000)) < 1)
+ if ((val4 = total_tick / (val2 * 1000)) < 1)
val4 = 1;
tick_time = val2 * 1000; // [GodLesZ] tick time
break;
@@ -8360,19 +8127,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0; // No need to start SC
}
val1 = boss_md->bl.id;
- if( (val4 = tick/1000) < 1 )
+ if( (val4 = total_tick/1000) < 1 )
val4 = 1;
tick_time = 1000; // [GodLesZ] tick time
}
break;
case SC_HIDING:
- val2 = tick/1000;
+ val2 = total_tick/1000;
tick_time = 1000; // [GodLesZ] tick time
val3 = 0; // unused, previously speed adjustment
val4 = val1+3; //Seconds before SP substraction happen.
break;
case SC_CHASEWALK:
- val2 = tick>0?tick:10000; //Interval at which SP is drained.
+ val2 = total_tick>0?total_tick:10000; //Interval at which SP is drained.
val3 = 35 - 5 * val1; //Speed adjustment.
if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE)
val3 -= 40;
@@ -8382,8 +8149,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_CLOAKING:
if (!sd) //Monsters should be able to walk with no penalties. [Skotlex]
val1 = 10;
- tick_time = val2 = tick>0?tick:60000; //SP consumption rate.
- tick = INFINITE_DURATION; // duration sent to the client should be infinite
+ tick_time = val2 = total_tick>0?total_tick:60000; //SP consumption rate.
+ total_tick = INFINITE_DURATION; // duration sent to the client should be infinite
val3 = 0; // unused, previously walk speed adjustment
//val4&1 signals the presence of a wall.
//val4&2 makes cloak not end on normal attacks [Skotlex]
@@ -8397,7 +8164,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_RUWACH:
case SC_WZ_SIGHTBLASTER:
val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id.
- val2 = tick/20;
+ val2 = total_tick/20;
tick_time = 20; // [GodLesZ] tick time
break;
@@ -8414,7 +8181,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_TURNKICK_READY:
case SC_DODGE_READY:
case SC_PUSH_CART:
- tick = INFINITE_DURATION;
+ case SC_DAILYSENDMAILCNT:
+ total_tick = INFINITE_DURATION;
break;
case SC_AUTOGUARD:
@@ -8430,12 +8198,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if( sd ) {
for( i = 0; i < MAX_PC_DEVOTION; i++ ) {
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL)
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
} else if (bl->type == BL_MER) {
struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
if (mc->devotion_flag && (tsd = mc->master) != NULL) {
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON);
}
}
}
@@ -8454,7 +8222,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
for (i = 0; i < MAX_PC_DEVOTION; i++) {
//See if there are devoted characters, and pass the status to them. [Skotlex]
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL)
- status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID);
+ status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,total_tick,SCFLAG_NOAVOID);
}
}
}
@@ -8467,8 +8235,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
val2 = 12; //SP cost
val4 = 10000; //Decrease at 10secs intervals.
- val3 = tick/val4;
- tick = INFINITE_DURATION; // duration sent to the client should be infinite
+ val3 = total_tick/val4;
+ total_tick = INFINITE_DURATION; // duration sent to the client should be infinite
tick_time = val4; // [GodLesZ] tick time
break;
case SC_PARRYING:
@@ -8486,21 +8254,21 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_BERSERK:
if( val3 == SC__BLOODYLUST )
- sc_start(src,bl,(sc_type)val3,100,val1,tick);
+ sc_start(src,bl,(sc_type)val3,100,val1,total_tick);
if (!val3 && (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4))
- sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, tick);
+ sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, total_tick);
//HP healing is performing after the calc_status call.
//Val2 holds HP penalty
if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1);
if (!val4) val4 = 10000; //Val4 holds damage interval
- val3 = tick/val4; //val3 holds skill duration
+ val3 = total_tick/val4; //val3 holds skill duration
tick_time = val4; // [GodLesZ] tick time
break;
case SC_GOSPEL:
if(val4 == BCT_SELF) {
// self effect
- val2 = tick/10000;
+ val2 = total_tick/10000;
tick_time = 10000; // [GodLesZ] tick time
status->change_clear_buffs(bl,3); //Remove buffs/debuffs
}
@@ -8553,23 +8321,23 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = 0;
val4 = 0;
max_stat = (status->get_lv(bl)-10<50)?status->get_lv(bl)-10:50;
- stat = max(0, max_stat - status2->str ); val3 |= cap_value(stat,0,0xFF)<<16;
- stat = max(0, max_stat - status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
- stat = max(0, max_stat - status2->vit ); val3 |= cap_value(stat,0,0xFF);
- stat = max(0, max_stat - status2->int_); val4 |= cap_value(stat,0,0xFF)<<16;
- stat = max(0, max_stat - status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
- stat = max(0, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF);
+ stat = max(0, max_stat - (int)status2->str ); val3 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - (int)status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - (int)status2->vit ); val3 |= cap_value(stat,0,0xFF);
+ stat = max(0, max_stat - (int)status2->int_); val4 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - (int)status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - (int)status2->luk ); val4 |= cap_value(stat,0,0xFF);
}
break;
case SC_SWORDREJECT:
val2 = 15*val1; //Reflect chance
val3 = 3; //Reflections
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_MEMORIZE:
val2 = 5; //Memorized casts.
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_GRAVITATION:
@@ -8623,11 +8391,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL;
if (src2 && sc2) {
if (!sce2) //Start lock on caster.
- sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000);
+ sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,total_tick+1000);
else { //Increase count of locked enemies and refresh time.
(sce2->val2)++;
timer->delete(sce2->timer, status->change_timer);
- sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M);
+ sce2->timer = timer->add(timer->gettick()+total_tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M);
}
} else //Status failed.
return 0;
@@ -8640,6 +8408,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
switch (val1) {
case 3: //33*3 + 1 -> 100%
val2++;
+ FALLTHROUGH
case 1:
case 2: //33, 66%
val2 += 33*val1;
@@ -8662,13 +8431,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//val4: TK: Combo time
struct unit_data *ud = unit->bl2ud(bl);
if( ud && (!val3 || val3 == 2) ) {
- tick += 300 * battle_config.combo_delay_rate/100;
- ud->attackabletime = timer->gettick()+tick;
+ total_tick += 300 * battle_config.combo_delay_rate/100;
+ ud->attackabletime = timer->gettick()+total_tick;
if( !val3 )
- unit->set_walkdelay(bl, timer->gettick(), tick, 1);
+ unit->set_walkdelay(bl, timer->gettick(), total_tick, 1);
}
val3 = 0;
- val4 = tick;
+ val4 = total_tick;
break;
}
case SC_EARTHSCROLL:
@@ -8682,7 +8451,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = (int)(currenttick&0x00000000ffffffffLL);
val4 = (int)((currenttick&0xffffffff00000000LL)>>32);
}
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_KAAHI:
val2 = 200*val1; //HP heal
@@ -8697,7 +8466,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_TRICKDEAD:
if (vd) vd->dead_sit = 1;
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_CONCENTRATION:
val2 = 2 + val1;
@@ -8715,20 +8484,21 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//val2 holds if it was casted on self, or is bonus received from others
val3 = 5*val1; //Power increase
if(sd && pc->checkskill(sd,BS_HILTBINDING)>0)
- tick += tick / 10;
+ total_tick += total_tick / 10;
break;
case SC_ADRENALINE2:
case SC_ADRENALINE:
val3 = (val2) ? 300 : 200; // aspd increase
+ FALLTHROUGH
case SC_WEAPONPERFECT:
if(sd && pc->checkskill(sd,BS_HILTBINDING)>0)
- tick += tick / 10;
+ total_tick += total_tick / 10;
break;
case SC_LKCONCENTRATION:
val2 = 5*val1; //Batk/Watk Increase
val3 = 10*val1; //Hit Increase
val4 = 5*val1; //Def reduction
- sc_start(src, bl, SC_ENDURE, 100, 1, tick); //Endure effect
+ sc_start(src, bl, SC_ENDURE, 100, 1, total_tick); //Endure effect
break;
case SC_ANGELUS:
val2 = 5*val1; //def increase
@@ -8798,7 +8568,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = 12*val1; //mdef2 reduction.
break;
case SC_SKA:
- val2 = tick/1000;
+ val2 = total_tick/1000;
val3 = rnd()%100; //Def changes randomly every second...
tick_time = 1000; // [GodLesZ] tick time
break;
@@ -8811,7 +8581,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
// When renewing status' information
// val3 Return map_index
// val4 return coordinates
- tick = val1>0?1000:250;
+ total_tick = val1>0?1000:250;
if (sd)
{
if (sd->mapindex != val2)
@@ -8846,11 +8616,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_SWOO:
if(st->mode&MD_BOSS)
- tick /= 5; //TODO: Reduce skill's duration. But for how long?
+ total_tick /= 5; //TODO: Reduce skill's duration. But for how long?
break;
case SC_SPIDERWEB:
if( bl->type == BL_PC )
- tick /= 2;
+ total_tick /= 2;
break;
case SC_ARMOR:
//NPC_DEFENDER:
@@ -8915,7 +8685,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_KAIZEL:
val2 = 10*val1; //% of life to be revived with
break;
- // case SC_ARMORPROPERTY:
+ case SC_ARMORPROPERTY:
+ {
+ int ele = (val1 > 0 ? SC_RESIST_PROPERTY_WATER :
+ (val2 > 0 ? SC_RESIST_PROPERTY_GROUND :
+ (val3 > 0 ? SC_RESIST_PROPERTY_FIRE :
+ (val4 > 0 ? SC_RESIST_PROPERTY_WIND : SI_BLANK))));
+ clif->status_change(bl, status->get_sc_icon(ele), status->get_sc_relevant_bl_types(ele), 1, total_tick, 0, 0, 0);
+ break;
// case SC_ARMOR_RESIST:
// Mod your resistance against elements:
// val1 = water | val2 = earth | val3 = fire | val4 = wind
@@ -8924,7 +8701,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//Place here SCs that have no SCB_* data, no skill associated, no ICON
//associated, and yet are not wrong/unknown. [Skotlex]
//break;
-
+ }
case SC_MER_FLEE:
case SC_MER_ATK:
case SC_MER_HIT:
@@ -8956,11 +8733,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
**/
case SC_FEAR:
val2 = 2;
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_BURNING:
- val4 = tick / 3000; // Total Ticks to Burn!!
+ val4 = total_tick / 3000; // Total Ticks to Burn!!
tick_time = 3000; // [GodLesZ] tick time
break;
/**
@@ -8974,14 +8751,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val1 = sd->status.job_level * pc->checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase
break;
case SC_ABUNDANCE:
- val4 = tick / 10000;
+ val4 = total_tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
/**
* Arch Bishop
**/
case SC_RENOVATIO:
- val4 = tick / 5000;
+ val4 = total_tick / 5000;
tick_time = 5000;
break;
case SC_SECRAMENT:
@@ -8992,28 +8769,28 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_WEAPONBLOCKING:
val2 = 10 + 2 * val1; // Chance
- val4 = tick / 5000;
+ val4 = total_tick / 5000;
tick_time = 5000; // [GodLesZ] tick time
break;
case SC_TOXIN:
- val4 = tick / 10000;
+ val4 = total_tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
case SC_MAGICMUSHROOM:
- val4 = tick / 4000;
+ val4 = total_tick / 4000;
tick_time = 4000; // [GodLesZ] tick time
break;
case SC_PYREXIA:
status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); // Blind status that last for 30 seconds
- val4 = tick / 3000;
+ val4 = total_tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
case SC_LEECHESEND:
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_OBLIVIONCURSE:
- val4 = tick / 3000;
+ val4 = total_tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
case SC_CLOAKINGEXCEED:
@@ -9052,7 +8829,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_SUMMON3:
case SC_SUMMON4:
case SC_SUMMON5:
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
if( val4 < 1 )
val4 = 1;
tick_time = 1000; // [GodLesZ] tick time
@@ -9067,19 +8844,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
break;
case SC_STEALTHFIELD_MASTER:
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 2000 + (1000 * val1);
break;
case SC_ELECTRICSHOCKER:
case SC_COLD:
case SC_MEIKYOUSISUI:
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
if( val4 < 1 )
val4 = 1;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_CAMOUFLAGE:
- val4 = tick/1000;
+ val4 = total_tick/1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_WUGDASH:
@@ -9090,17 +8867,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = (int)(currenttick&0x00000000ffffffffLL);
val4 = (int)((currenttick&0xffffffff00000000LL)>>32);
}
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC__REPRODUCE:
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000;
break;
case SC__SHADOWFORM: {
struct map_session_data * s_sd = map->id2sd(val2);
if( s_sd )
s_sd->shadowform_id = bl->id;
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
}
break;
@@ -9111,7 +8888,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC__INVISIBILITY:
val2 = 50 - 10 * val1; // ASPD
val3 = 200 * val1; // CRITICAL
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC__ENERVATION:
@@ -9138,7 +8915,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (sd->status.pet_id > 0)
pet->menu(sd, 3);
if (homun_alive(sd->hd))
- homun->vaporize(sd,HOM_ST_REST);
+ homun->vaporize(sd, HOM_ST_REST, true);
if (sd->md)
mercenary->delete(sd->md,3);
}
@@ -9153,8 +8930,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC__WEAKNESS:
val2 = 10 * val1;
// bypasses coating protection and MADO
- sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,tick);
- sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,tick);
+ sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,total_tick);
+ sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,total_tick);
break;
case SC_GN_CARTBOOST:
if( val1 < 3 )
@@ -9174,7 +8951,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_STRIKING:
val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1)
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_BLOOD_SUCKER:
@@ -9183,7 +8960,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = 1;
if(src2)
val3 = 200 + 100 * val1 + status_get_int(src2);
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
}
break;
@@ -9204,22 +8981,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 5 + 5 * val1;
break;
case SC_SIREN:
- val4 = tick / 2000;
+ val4 = total_tick / 2000;
tick_time = 2000; // [GodLesZ] tick time
break;
case SC_DEEP_SLEEP:
- val4 = tick / 2000;
+ val4 = total_tick / 2000;
tick_time = 2000; // [GodLesZ] tick time
break;
case SC_SIRCLEOFNATURE:
val2 = 40 * val1;//HP recovery
val3 = 4 * val1;//SP drain
- val4 = tick / 1000;
+ val4 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_SONG_OF_MANA:
val3 = 10 + 5 * val2;
- val4 = tick/5000;
+ val4 = total_tick/5000;
tick_time = 5000; // [GodLesZ] tick time
break;
case SC_SATURDAY_NIGHT_FEVER:
@@ -9227,7 +9004,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if ( val2 < 1000 )
val2 = 1000;//Added to prevent val3 from dividing by 0 when using level 6 or higher through commands. [Rytech]
val3 = tick/val2;*/
- val3 = tick / 3000;
+ val3 = total_tick / 3000;
tick_time = 3000;// [GodLesZ] tick time
break;
case SC_GLOOMYDAY:
@@ -9263,7 +9040,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_MELODYOFSINK:
val3 = val1 * (2 + val2);//INT Reduction. Formula Includes Caster And 2nd Performer.
- val4 = tick/1000;
+ val4 = total_tick/1000;
tick_time = 1000;
break;
case SC_BEYOND_OF_WARCRY:
@@ -9281,13 +9058,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_LG_REFLECTDAMAGE:
val2 = 15 + 5 * val1;
val3 = 25 + 5 * val1; //Number of Reflects
- val4 = tick/1000;
+ val4 = total_tick/1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_FORCEOFVANGUARD:
val2 = 8 + 12 * val1; // Chance
val3 = 5 + 2 * val1; // Max rage counters
- tick = INFINITE_DURATION; //endless duration in the client
+ total_tick = INFINITE_DURATION; //endless duration in the client
break;
case SC_EXEEDBREAK:
if( sd ){
@@ -9310,7 +9087,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = 5000; // [GodLesZ] tick time
break;
case SC_MAGNETICFIELD:
- val3 = tick / 1000;
+ val3 = total_tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_INSPIRATION:
@@ -9318,7 +9095,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 40 * val1 + 3 * sd->status.job_level;// ATK bonus
val3 = sd->status.base_level / 10 + sd->status.job_level / 5;// All stat bonus
}
- val4 = tick / 5000;
+ val4 = total_tick / 5000;
tick_time = 5000; // [GodLesZ] tick time
status->change_clear_buffs(bl,3); //Remove buffs/debuffs
break;
@@ -9329,7 +9106,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1;
break;
case SC_RAISINGDRAGON:
- val3 = tick / 5000;
+ val3 = total_tick / 5000;
tick_time = 5000; // [GodLesZ] tick time
break;
case SC_GENTLETOUCH_CHANGE:
@@ -9415,17 +9192,20 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_WILD_STORM:
case SC_UPHEAVAL:
val2 += 10;
+ FALLTHROUGH
case SC_HEATER:
case SC_COOLER:
case SC_BLAST:
case SC_CURSED_SOIL:
val2 += 10;
+ FALLTHROUGH
case SC_PYROTECHNIC:
case SC_AQUAPLAY:
case SC_GUST:
case SC_PETROLOGY:
val2 += 5;
val3 += 9000;
+ FALLTHROUGH
case SC_CIRCLE_OF_FIRE:
case SC_WATER_SCREEN:
case SC_WIND_STEP:
@@ -9436,7 +9216,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_STONE_SHIELD:
val2 += 5;
val3 += 1000;
- val4 = tick;
+ val4 = total_tick;
tick_time = val3;
break;
case SC_WATER_BARRIER:
@@ -9459,18 +9239,18 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_STOMACHACHE:
val3 = 8; // SP consume.
- val4 = tick / 10000;
+ val4 = total_tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
case SC_STEAMPACK: // [Frost]
val3 = 100; // HP Consume.
- val4 = tick / 10000;
+ val4 = total_tick / 10000;
tick_time = 10000;
- sc_start(src, bl, SC_ENDURE, 100, 10, tick); // Endure effect
+ sc_start(src, bl, SC_ENDURE, 100, 10, total_tick); // Endure effect
break;
case SC_MAGIC_CANDY: // [Frost]
val3 = 90; // SP Consume.
- val4 = tick / 10000;
+ val4 = total_tick / 10000;
tick_time = 10000;
break;
case SC_PROMOTE_HEALTH_RESERCH:
@@ -9507,8 +9287,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_KAGEMUSYA:
val3 = val1 * 2;
+ FALLTHROUGH
case SC_IZAYOI:
- val2 = tick/1000;
+ val2 = total_tick/1000;
tick_time = 1000;
break;
case SC_ZANGETSU:
@@ -9538,22 +9319,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
PER( 100 / (status_get_max_hp(bl) / hp), lv );
- status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1);
+ status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, STATUS_HEAL_FORCED);
PER( 100 / (status_get_max_sp(bl) / sp), lv );
- status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1);
+ status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), STATUS_HEAL_FORCED);
}
#undef PER
break;
case SC_ANGRIFFS_MODUS:
val2 = 50 + 20 * val1; //atk bonus
val3 = 40 + 20 * val1; // Flee reduction.
- val4 = tick/1000; // hp/sp reduction timer
+ val4 = total_tick/1000; // hp/sp reduction timer
tick_time = 1000;
break;
case SC_NEUTRALBARRIER:
- tick_time = tick;
- tick = INFINITE_DURATION;
+ tick_time = total_tick;
+ total_tick = INFINITE_DURATION;
break;
case SC_GOLDENE_FERSE:
val2 = 10 + 10*val1; //max hp bonus
@@ -9582,10 +9363,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 2*val1; //aspd reduction %
val3 = 2*val1; //dmg reduction %
if(sc->data[SC_NEEDLE_OF_PARALYZE])
- sc_start(src, bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
+ sc_start(src, bl, SC_ENDURE, 100, val1, total_tick); //start endure for same duration
break;
case SC_STYLE_CHANGE: //[Lighta] need real info
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING;
else val2 = MH_MD_FIGHTING;
break;
@@ -9593,12 +9374,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
status_percent_heal(bl,100,0);
val2 = 7 - val1;
tick_time = 1000;
- val4 = tick / tick_time;
+ val4 = total_tick / tick_time;
break;
case SC_KINGS_GRACE:
val2 = 3 + val1;
tick_time = 1000;
- val4 = tick / tick_time;
+ val4 = total_tick / tick_time;
break;
case SC_TELEKINESIS_INTENSE:
val2 = 10 * val1;
@@ -9611,7 +9392,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 5 * val1;
val3 = (20 * val1) + 80;
tick_time = 1000;
- val4 = tick / tick_time;
+ val4 = total_tick / tick_time;
break;
case SC_DARKCROW:
val2 = 30 * val1;
@@ -9620,8 +9401,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (!mob->db_checkid(val1))
val1 = MOBID_PORING;
break;
+ case SC_SPRITEMABLE:
case SC_ALL_RIDING:
- tick = INFINITE_DURATION;
+ total_tick = INFINITE_DURATION;
break;
case SC_FLASHCOMBO:
/**
@@ -9630,26 +9412,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
**/
val2 = 20+(20*val1);
break;
+ /**
+ * Summoner
+ */
+ case SC_FRESHSHRIMP:
+ val4 = total_tick / (10000 - ((val1 - 1) * 1000));
+ tick_time = 10000 - ((val1 - 1) * 1000);
+ if (val4 <= 0) // Prevents a negeative value from happening
+ val4 = 0;
+ break;
+ case SC_ARCLOUSEDASH:
+ val2 = 15 + 5 * val1; // AGI
+ val3 = 25; // Move speed increase
+ if (sd != NULL && (sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)
+ val4 = 10; // Ranged ATK increase
+ break;
+ case SC_TUNAPARTY:
+ val2 = (st->max_hp * (val1 * 10) / 100); // %Max HP to absorb
+ break;
+ case SC_BITESCAR:
+ val2 = 2 * val1; // MHP% damage
+ val4 = total_tick / 1000;
+ tick_time = 1000;
+ break;
+ case SC_SHRIMP:
+ val2 = 10; // BATK%, MATK%
+ break;
+ case SC_CATNIPPOWDER:
+ val2 = 50; // WATK%, MATK%
+ val3 = 25 * val1; // Move speed reduction
+ break;
default:
- if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) {
- //Status change with no calc, no icon, and no skill associated...?
- ShowError("UnknownStatusChange [%d]\n", type);
+ if (status->change_start_unknown_sc(src, bl, type, calc_flag, rate, val1, val2, val3, val4, total_tick, flag)) {
return 0;
}
}
- } else { //Special considerations when loading SC data.
- switch( type ) {
+ } else { // Special considerations when loading SC data.
+ switch (type) {
case SC_WEDDING:
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
case SC_OKTOBERFEST:
- if( !vd ) break;
- clif->changelook(bl,LOOK_BASE,vd->class_);
- clif->changelook(bl,LOOK_WEAPON,0);
- clif->changelook(bl,LOOK_SHIELD,0);
- clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
- clif->changelook(bl,LOOK_BODY2,0);
+ case SC_DRESS_UP:
+ if (vd == NULL)
+ break;
+ clif->changelook(bl, LOOK_BASE, vd->class);
+ clif->changelook(bl, LOOK_WEAPON, 0);
+ clif->changelook(bl, LOOK_SHIELD, 0);
+ clif->changelook(bl, LOOK_CLOTHES_COLOR, vd->cloth_color);
+ clif->changelook(bl, LOOK_BODY2, 0);
break;
case SC_KAAHI:
val4 = INVALID_TIMER;
@@ -9658,27 +9470,272 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
/* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */
- switch(type) {
+ val_flag = status->get_val_flag(type);
+
+ /* [Ind/Hercules] */
+ status->change_start_display(sd, type, val1, val2, val3, val4);
+
+ //Those that make you stop attacking/walking....
+ status->change_start_stop_action(bl, type);
+
+ // Set option as needed.
+ opt_flag = status->change_start_set_option(bl, sc, type, val1, val2, val3, val4);
+
+ //On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
+ if(opt_flag) {
+ clif->changeoption(bl);
+ if( sd && opt_flag&0x4 ) {
+ if (vd)
+ clif->changelook(bl, LOOK_BASE, vd->class);
+ clif->changelook(bl,LOOK_WEAPON,0);
+ clif->changelook(bl,LOOK_SHIELD,0);
+ if (vd)
+ clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
+ }
+ }
+ if (calc_flag&SCB_DYE) {
+ //Reset DYE color
+ if (vd && vd->cloth_color) {
+ val4 = vd->cloth_color;
+ clif->changelook(bl,LOOK_CLOTHES_COLOR,0);
+ }
+ calc_flag&=~SCB_DYE;
+ }
+
+#if 0 //Currently No SC's use this
+ if (calc_flag&SCB_BODY) {
+ //Reset Body Style
+ if (vd && vd->body_style) {
+ val4 = vd->body_style;
+ clif->changelook(bl,LOOK_BODY2,0);
+ }
+ calc_flag&=~SCB_BODY;
+ }
+#endif
+
+ if (!(flag & SCFLAG_LOADED))
+ tick = total_tick; // When starting a new SC (not loading), its remaining duration is the same as the total
+ if(!(flag & SCFLAG_NOICON) && !(flag & SCFLAG_LOADED && status->dbs->DisplayType[type]))
+ clif->status_change_sub(bl, status->get_sc_icon(type), status->get_sc_relevant_bl_types(type), 1, tick, total_tick, (val_flag & 1) ? val1 : 1, (val_flag & 2) ? val2 : 0, (val_flag & 4) ? val3 : 0);
+
+ /**
+ * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
+ **/
+ if(tick_time)
+ tick = tick_time;
+
+ //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
+ if((sce=sc->data[type])) {// reuse old sc
+ if( sce->timer != INVALID_TIMER )
+ timer->delete(sce->timer, status->change_timer);
+ } else {// new sc
+ ++(sc->count);
+ sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry);
+ }
+
+ sce->val1 = val1;
+ sce->val2 = val2;
+ sce->val3 = val3;
+ sce->val4 = val4;
+ sce->total_tick = total_tick;
+
+ if (tick >= 0) {
+ sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type);
+ sce->infinite_duration = false;
+ } else {
+ sce->timer = INVALID_TIMER; //Infinite duration
+ sce->infinite_duration = true;
+ if( sd )
+ chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce);
+ }
+
+ if (calc_flag)
+ status_calc_bl(bl,calc_flag);
+
+ if(sd && sd->pd)
+ pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing
+
+ switch (type) {
+ case SC_BERSERK:
+ if (!(sce->val2)) { //don't heal if already set
+ status->heal(bl, st->max_hp, 0, STATUS_HEAL_FORCED); //Do not use percent_heal as this healing must override BERSERK's block.
+ status->set_sp(bl, 0, STATUS_HEAL_DEFAULT); //Damage all SP
+ }
+ sce->val2 = 5 * st->max_hp / 100;
+ break;
+ case SC_HLIF_CHANGE:
+ status_percent_heal(bl, 100, 100);
+ break;
+ case SC_RUN:
+ {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if( ud )
+ ud->state.running = unit->run(bl, NULL, SC_RUN);
+ }
+ break;
+ case SC_CASH_BOSS_ALARM:
+ if( sd )
+ clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message
+ break;
+ case SC_MER_HP:
+ status_percent_heal(bl, 100, 0); // Recover Full HP
+ break;
+ case SC_MER_SP:
+ status_percent_heal(bl, 0, 100); // Recover Full SP
+ break;
+ case SC_PROMOTE_HEALTH_RESERCH:
+ status_percent_heal(bl, sce->val4, 0);
+ break;
+ case SC_ENERGY_DRINK_RESERCH:
+ status_percent_heal(bl, 0, sce->val4);
+ break;
+ /**
+ * Ranger
+ **/
+ case SC_WUGDASH:
+ {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if( ud )
+ ud->state.running = unit->run(bl, sd, SC_WUGDASH);
+ }
+ break;
+ case SC_COMBOATTACK:
+ switch (sce->val1) {
+ case TK_STORMKICK:
+ clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
+ break;
+ case TK_DOWNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
+ break;
+ case TK_TURNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
+ break;
+ case TK_COUNTER:
+ clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
+ break;
+ case MO_COMBOFINISH:
+ case CH_TIGERFIST:
+ case CH_CHAINCRUSH:
+ if (sd)
+ clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
+ break;
+ case TK_JUMPKICK:
+ if (sd)
+ clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
+ break;
+ case MO_TRIPLEATTACK:
+ if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
+ clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
+ break;
+ case SR_FALLENEMPIRE:
+ if (sd){
+ clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
+ clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
+ }
+ break;
+ }
+ break;
+ case SC_RAISINGDRAGON:
+ sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
+ break;
+ }
+
+ if( opt_flag&2 && sd && sd->touching_id )
+ npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
+
+ return 1;
+}
+
+static bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag)
+{
+ Assert_retr(false, type >= SC_NONE && type < SC_MAX);
+ if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->get_sc_icon(type) == SI_BLANK) {
+ //Status change with no calc, no icon, and no skill associated...?
+ ShowError("UnknownStatusChange [%d]\n", type);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Starts a status change in its full duration.
+ *
+ * @param src Status change source bl.
+ * @param bl Status change target bl.
+ * @param type Status change type.
+ * @param rate Base success rate. 1 means 0.01%, 10000 means 100%.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ * @param tick Base duration (milliseconds).
+ * @param flag Special flags (@see enum scstart_flag).
+ *
+ * @retval 0 if no status change happened.
+ * @retval 1 if the status change was successfully applied.
+ */
+static int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag)
+{
+ return status->change_start_sub(src, bl, type, rate, val1, val2, val3, val4, 0, tick, flag);
+}
+
+static void status_change_start_display(struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4)
+{
+ Assert_retv(type >= SC_NONE && type < SC_MAX);
+
+ if (sd && status->dbs->DisplayType[type]) {
+ int dval1 = 0, dval2 = 0, dval3 = 0;
+ switch (type) {
+ case SC_ALL_RIDING:
+ dval1 = 1;
+ break;
+ case SC_CLAN_INFO:
+ dval1 = val1;
+ dval2 = val2;
+ dval3 = val3;
+ break;
+ default: /* all others: just copy val1 */
+ dval1 = val1;
+ break;
+ }
+ status->display_add(sd, type, dval1, dval2, dval3);
+ }
+}
+
+/**
+ * Return val_flag based on sc type.
+ *
+ * @param type Status change type.
+ *
+ * @retval val_flag.
+ */
+static int status_get_val_flag(enum sc_type type)
+{
+ int val_flag = 0;
+ switch (type) {
+ case SC_CLAN_INFO:
+ val_flag |= 1 | 2;
+ break;
case SC_FIGHTINGSPIRIT:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_VENOMIMPRESS:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_POISONINGWEAPON:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_WEAPONBLOCKING:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_ROLLINGCUTTER:
val_flag |= 1;
break;
case SC_CLOAKINGEXCEED:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_HALLUCINATIONWALK:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_SUMMON1:
case SC_SUMMON2:
@@ -9688,34 +9745,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val_flag |= 1;
break;
case SC__SHADOWFORM:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__INVISIBILITY:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC__ENERVATION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC__GROOMY:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__LAZINESS:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__UNLUCKY:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__WEAKNESS:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_PROPERTYWALK:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_FORCEOFVANGUARD:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_PRESTIGE:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_BANDING:
val_flag |= 1;
@@ -9723,56 +9780,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_SHIELDSPELL_DEF:
case SC_SHIELDSPELL_MDEF:
case SC_SHIELDSPELL_REF:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_SPELLFIST:
case SC_CURSEDCIRCLE_ATKER:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CRESCENTELBOW:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_LIGHTNINGWALK:
val_flag |= 1;
break;
case SC_PYROTECHNIC_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_HEATER_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_AQUAPLAY_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_COOLER_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CHILLY_AIR_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_GUST_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_BLAST_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_WILD_STORM_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_PETROLOGY_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CURSED_SOIL_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_UPHEAVAL_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_CIRCLE_OF_FIRE_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_WATER_BARRIER:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_KYOUGAKU:
val_flag |= 1;
@@ -9784,86 +9841,36 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_OVERLAPEXPUP:
val_flag |= 1;
break;
- }
-
- /* [Ind/Hercules] */
- if( sd && status->dbs->DisplayType[type] ) {
- int dval1 = 0, dval2 = 0, dval3 = 0;
- switch( type ) {
- case SC_ALL_RIDING:
- dval1 = 1;
- break;
- default: /* all others: just copy val1 */
- dval1 = val1;
- break;
- }
- status->display_add(sd,type,dval1,dval2,dval3);
- }
-
- //Those that make you stop attacking/walking....
- switch (type) {
- case SC_VACUUM_EXTREME:
- if(!map_flag_gvg(bl->m))
- unit->stop_walking(bl,1);
- break;
- case SC_FREEZE:
- case SC_STUN:
- case SC_SLEEP:
- case SC_STONE:
- case SC_DEEP_SLEEP:
- if (sd && pc_issit(sd)) //Avoid sprite sync problems.
- pc->setstand(sd);
- case SC_TRICKDEAD:
- status_change_end(bl, SC_DANCING, INVALID_TIMER);
- // Cancel cast when get status [LuzZza]
- if (battle_config.sc_castcancel&bl->type)
- unit->skillcastcancel(bl, 0);
- case SC_FALLENEMPIRE:
- case SC_WHITEIMPRISON:
- unit->stop_attack(bl);
- case SC_STOP:
- case SC_CONFUSION:
- case SC_RG_CCONFINE_M:
- case SC_RG_CCONFINE_S:
- case SC_SPIDERWEB:
- case SC_ELECTRICSHOCKER:
- case SC_WUGBITE:
- case SC_THORNS_TRAP:
- case SC__MANHOLE:
- case SC__CHAOS:
- case SC_COLD:
- case SC_CURSEDCIRCLE_ATKER:
- case SC_CURSEDCIRCLE_TARGET:
- case SC_FEAR:
- case SC_MEIKYOUSISUI:
- case SC_NEEDLE_OF_PARALYZE:
- case SC_DEATHBOUND:
- case SC_NETHERWORLD:
- unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
- break;
- case SC_ANKLESNARE:
- if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) )
- unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
- break;
- case SC_HIDING:
- case SC_CLOAKING:
- case SC_CLOAKINGEXCEED:
- case SC_CHASEWALK:
- case SC_WEIGHTOVER90:
- case SC_CAMOUFLAGE:
- case SC_SIREN:
- case SC_ALL_RIDING:
- unit->stop_attack(bl);
+ case SC_DAILYSENDMAILCNT:
+ val_flag |= 1 | 2;
break;
- case SC_SILENCE:
- if (battle_config.sc_castcancel&bl->type)
- unit->skillcastcancel(bl, 0);
+ case SC_MADOGEAR:
+ val_flag |= 1;
break;
}
+ return val_flag;
+}
- // Set option as needed.
- opt_flag = 1;
- switch(type) {
+/**
+ * Set new status values.
+ *
+ * @param bl Status change target bl.
+ * @param sc Current statuses.
+ * @param type Status change type.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ *
+ * @retval option flag.
+ */
+static int status_change_start_set_option(struct block_list *bl, struct status_change *sc, enum sc_type type, int val1, int val2, int val3, int val4)
+{
+ int opt_flag = 1;
+
+ nullpo_retr(true, bl);
+ nullpo_retr(true, sc);
+ switch (type) {
//OPT1
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
@@ -9912,6 +9919,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
opt_flag = 0;
break;
}
+ FALLTHROUGH
case SC_EXPLOSIONSPIRITS:
sc->opt3 |= OPT3_EXPLOSIONSPIRITS;
opt_flag = 0;
@@ -9940,7 +9948,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
#endif // 0
case SC_DANCING:
- if ((val1&0xFFFF) == CG_MOONLIT)
+ if ((val1 & 0xFFFF) == CG_MOONLIT)
sc->opt3 |= OPT3_MOONLIT;
opt_flag = 0;
break;
@@ -10026,6 +10034,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
sc->option |= OPTION_OKTOBERFEST;
opt_flag |= 0x4;
break;
+ case SC_DRESS_UP:
+ sc->option |= OPTION_SUMMER2;
+ opt_flag |= 0x4;
+ break;
case SC__FEINTBOMB_MASTER:
sc->option |= OPTION_INVISIBLE;
opt_flag |= 0x4;
@@ -10033,178 +10045,464 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
default:
opt_flag = 0;
}
+ return opt_flag;
+}
- //On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
- if(opt_flag) {
- clif->changeoption(bl);
- if( sd && opt_flag&0x4 ) {
- if (vd)
- clif->changelook(bl,LOOK_BASE,vd->class_);
- clif->changelook(bl,LOOK_WEAPON,0);
- clif->changelook(bl,LOOK_SHIELD,0);
- if (vd)
- clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
- }
- }
- if (calc_flag&SCB_DYE) {
- //Reset DYE color
- if (vd && vd->cloth_color) {
- val4 = vd->cloth_color;
- clif->changelook(bl,LOOK_CLOTHES_COLOR,0);
- }
- calc_flag&=~SCB_DYE;
- }
-
-#if 0 //Currently No SC's use this
- if (calc_flag&SCB_BODY) {
- //Reset Body Style
- if (vd && vd->body_style) {
- val4 = vd->body_style;
- clif->changelook(bl,LOOK_BODY2,0);
+/**
+ * Stop actions before start new sc.
+ *
+ * @param bl Status change target bl.
+ * @param type Status change type.
+ */
+static void status_change_start_stop_action(struct block_list *bl, enum sc_type type)
+{
+ nullpo_retv(bl);
+ switch (type) {
+ case SC_VACUUM_EXTREME:
+ if (!map_flag_gvg(bl->m))
+ unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
+ break;
+ case SC_FREEZE:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_STONE:
+ case SC_DEEP_SLEEP: {
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ if (sd && pc_issit(sd)) //Avoid sprite sync problems.
+ pc->setstand(sd);
+ FALLTHROUGH
}
- calc_flag&=~SCB_BODY;
- }
-#endif
-
- if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type]))
- clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
-
- /**
- * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
- **/
- if( tick_time )
- tick = tick_time;
-
- //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
- if((sce=sc->data[type])) {// reuse old sc
- if( sce->timer != INVALID_TIMER )
- timer->delete(sce->timer, status->change_timer);
- } else {// new sc
- ++(sc->count);
- sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry);
- }
-
- sce->val1 = val1;
- sce->val2 = val2;
- sce->val3 = val3;
- sce->val4 = val4;
-
- if (tick >= 0) {
- sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type);
- sce->infinite_duration = false;
- } else {
- sce->timer = INVALID_TIMER; //Infinite duration
- sce->infinite_duration = true;
- if( sd )
- chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce);
+ case SC_TRICKDEAD:
+ status_change_end(bl, SC_DANCING, INVALID_TIMER);
+ // Cancel cast when get status [LuzZza]
+ if (battle_config.sc_castcancel&bl->type)
+ unit->skillcastcancel(bl, 0);
+ FALLTHROUGH
+ case SC_FALLENEMPIRE:
+ case SC_WHITEIMPRISON:
+ unit->stop_attack(bl);
+ FALLTHROUGH
+ case SC_STOP:
+ case SC_CONFUSION:
+ case SC_RG_CCONFINE_M:
+ case SC_RG_CCONFINE_S:
+ case SC_SPIDERWEB:
+ case SC_ELECTRICSHOCKER:
+ case SC_WUGBITE:
+ case SC_THORNS_TRAP:
+ case SC__MANHOLE:
+ case SC__CHAOS:
+ case SC_COLD:
+ case SC_CURSEDCIRCLE_ATKER:
+ case SC_CURSEDCIRCLE_TARGET:
+ case SC_FEAR:
+ case SC_MEIKYOUSISUI:
+ case SC_NEEDLE_OF_PARALYZE:
+ case SC_DEATHBOUND:
+ case SC_NETHERWORLD:
+ case SC_SV_ROOTTWIST:
+ unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
+ break;
+ case SC_ANKLESNARE:
+ if (battle_config.skill_trap_type || !map_flag_gvg(bl->m))
+ unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
+ break;
+ case SC_HIDING:
+ case SC_CLOAKING:
+ case SC_CLOAKINGEXCEED:
+ case SC_CHASEWALK:
+ case SC_WEIGHTOVER90:
+ case SC_CAMOUFLAGE:
+ case SC_SIREN:
+ case SC_ALL_RIDING:
+ case SC_SUHIDE:
+ unit->stop_attack(bl);
+ break;
+ case SC_SILENCE:
+ if (battle_config.sc_castcancel & bl->type)
+ unit->skillcastcancel(bl, 0);
+ break;
}
+}
- if (calc_flag)
- status_calc_bl(bl,calc_flag);
-
- if(sd && sd->pd)
- pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing
+/**
+ * End sc before starting other sc.
+ *
+ * @param bl Status change target bl.
+ * @param st Status change data.
+ * @param sc Current statuses.
+ * @param type Status change type.
+ * @param undead_flag is bl undead.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ *
+ * @retval false if no status change happened, or the other sc can be started regardless.
+ * @retval true if the status change was successfully applied and the other sc shouldn't be started.
+ */
+static bool status_end_sc_before_start(struct block_list *bl, struct status_data *st, struct status_change *sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4)
+{
+ nullpo_retr(true, bl);
+ nullpo_retr(true, st);
+ nullpo_retr(true, sc);
switch (type) {
- case SC_BERSERK:
- if (!(sce->val2)) { //don't heal if already set
- status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
- status->set_sp(bl, 0, 0); //Damage all SP
+ case SC_BLESSING:
+ // TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
+ // but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
+ if ((undead_flag == 0 && st->race != RC_DEMON) || bl->type == BL_PC) {
+ bool prevent_start = false;
+ if (sc->data[SC_CURSE] != NULL) {
+ prevent_start = true;
+ status_change_end(bl, SC_CURSE, INVALID_TIMER);
+ }
+ if (sc->data[SC_STONE] != NULL && sc->opt1 == OPT1_STONE) {
+ prevent_start = true;
+ status_change_end(bl, SC_STONE, INVALID_TIMER);
+ }
+ if (prevent_start)
+ return true;
}
- sce->val2 = 5 * st->max_hp / 100;
+ if (sc->data[SC_SOULLINK] != NULL && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
- case SC_HLIF_CHANGE:
- status_percent_heal(bl, 100, 100);
+ case SC_INC_AGI:
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
- case SC_RUN:
- {
- struct unit_data *ud = unit->bl2ud(bl);
- if( ud )
- ud->state.running = unit->run(bl, NULL, SC_RUN);
- }
+ case SC_QUAGMIRE:
+ status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ FALLTHROUGH
+ //Also blocks the ones below...
+ case SC_DEC_AGI:
+ case SC_ADORAMUS:
+ status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
+ //Also blocks the ones below...
+ FALLTHROUGH
+ case SC_DONTFORGETME:
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
+ status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
break;
- case SC_CASH_BOSS_ALARM:
- if( sd )
- clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message
+ case SC_ONEHANDQUICKEN:
+ //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
break;
- case SC_MER_HP:
- status_percent_heal(bl, 100, 0); // Recover Full HP
+ case SC_OVERTHRUSTMAX:
+ //Cancels Normal Overthrust. [Skotlex]
+ status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
break;
- case SC_MER_SP:
- status_percent_heal(bl, 0, 100); // Recover Full SP
+ case SC_KYRIE:
+ //Cancels Assumptio
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
break;
- case SC_PROMOTE_HEALTH_RESERCH:
- status_percent_heal(bl, sce->val4, 0);
+ case SC_MAGNIFICAT:
+ //Cancels Offertorium
+ status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER);
break;
- case SC_ENERGY_DRINK_RESERCH:
- status_percent_heal(bl, 0, sce->val4);
+ case SC_OFFERTORIUM:
+ //Cancels Magnificat
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
break;
- /**
- * Ranger
- **/
- case SC_WUGDASH:
- {
- struct unit_data *ud = unit->bl2ud(bl);
- if( ud )
- ud->state.running = unit->run(bl, sd, SC_WUGDASH);
- }
+ case SC_DELUGE:
+ if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
+ status_change_end(bl, SC_BLIND, INVALID_TIMER);
break;
- case SC_COMBOATTACK:
- switch (sce->val1) {
- case TK_STORMKICK:
- clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
- break;
- case TK_DOWNKICK:
- clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
- break;
- case TK_TURNKICK:
- clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
- break;
- case TK_COUNTER:
- clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
- break;
- case MO_COMBOFINISH:
- case CH_TIGERFIST:
- case CH_CHAINCRUSH:
- if (sd)
- clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
- break;
- case TK_JUMPKICK:
- if (sd)
- clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
- break;
- case MO_TRIPLEATTACK:
- if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
- clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
- break;
- case SR_FALLENEMPIRE:
- if (sd){
- clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
- clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
- }
+ case SC_SILENCE:
+ if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
+ status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
+ break;
+ case SC_HIDING:
+ status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
+ status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
+ break;
+ case SC_BERSERK:
+ if (val3 == SC__BLOODYLUST)
break;
+ if (battle_config.berserk_cancels_buffs) {
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_PARRYING, INVALID_TIMER);
+ status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
+ status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
}
+ #ifdef RENEWAL
+ else {
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ }
+ #endif
break;
- case SC_RAISINGDRAGON:
- sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
+ case SC_ASSUMPTIO:
+ status_change_end(bl, SC_KYRIE, INVALID_TIMER);
+ status_change_end(bl, SC_KAITE, INVALID_TIMER);
+ break;
+ case SC_KAITE:
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ break;
+ case SC_CARTBOOST:
+ if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) {
+ //Cancel Decrease Agi, but take no further effect [Skotlex]
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
+ return true;
+ }
+ break;
+ case SC_FUSION:
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
+ break;
+ case SC_GS_ADJUSTMENT:
+ status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
+ break;
+ case SC_GS_MADNESSCANCEL:
+ status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
+ break;
+ //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
+ case SC_PROPERTYUNDEAD:
+ status_change_end(bl, SC_BLESSING, INVALID_TIMER);
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR:
+ status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI:
+ status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT:
+ status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT:
+ status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX:
+ status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK:
+ status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR_CASH:
+ status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI_CASH:
+ status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT_CASH:
+ status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT_CASH:
+ status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX_CASH:
+ status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK_CASH:
+ status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
+ break;
+ case SC_GM_BATTLE:
+ status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER);
+ break;
+ case SC_GM_BATTLE2:
+ status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER);
+ break;
+ case SC_ENDURE:
+ if (val4 == 1)
+ 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:
+ status_change_end(bl, SC_INCAGI, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
+ break;
+ //Group A Status (doesn't overlap)
+ case SC_SWING:
+ case SC_SYMPHONY_LOVE:
+ case SC_MOONLIT_SERENADE:
+ case SC_RUSH_WINDMILL:
+ case SC_ECHOSONG:
+ case SC_HARMONIZE:
+ case SC_FRIGG_SONG:
+ if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
+ if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
+ if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
+ if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
+ if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
+ if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
+ break;
+ //Group B Status
+ case SC_SIREN:
+ case SC_DEEP_SLEEP:
+ case SC_SIRCLEOFNATURE:
+ case SC_LERADS_DEW:
+ case SC_MELODYOFSINK:
+ case SC_BEYOND_OF_WARCRY:
+ case SC_UNLIMITED_HUMMING_VOICE:
+ case SC_GLOOMYDAY:
+ case SC_SONG_OF_MANA:
+ case SC_DANCE_WITH_WUG:
+ if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
+ if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
+ if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
+ if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
+ if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
+ if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
+ if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ break;
+ case SC_REFLECTSHIELD:
+ status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ break;
+ case SC_LG_REFLECTDAMAGE:
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ break;
+ case SC_SHIELDSPELL_DEF:
+ case SC_SHIELDSPELL_MDEF:
+ case SC_SHIELDSPELL_REF:
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
+ break;
+ case SC_GENTLETOUCH_ENERGYGAIN:
+ case SC_GENTLETOUCH_CHANGE:
+ case SC_GENTLETOUCH_REVITALIZE:
+ if (type != SC_GENTLETOUCH_REVITALIZE)
+ status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
+ if (type != SC_GENTLETOUCH_ENERGYGAIN)
+ status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
+ if (type != SC_GENTLETOUCH_CHANGE)
+ status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLE:
+ status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLEOFF:
+ status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
+ break;
+ case SC_MAGICPOWER:
+ status_change_end(bl, type, INVALID_TIMER);
break;
}
- if( opt_flag&2 && sd && sd->touching_id )
- npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
+ return false;
+}
- return 1;
+/**
+ * Check is boss resist to given sc.
+ *
+ * @param type Status change type.
+ *
+ * @retval true if boss resist.
+ * @retval false if boss not resist.
+ */
+static bool status_is_boss_resist_sc(enum sc_type type)
+{
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ return true;
+
+ if (status->get_sc_type(type) & SC_NO_BOSS)
+ return true;
+
+ return false;
+}
+
+/**
+ * Initial check for current statuses immune to given sc.
+ *
+ * @param sc Current statuses.
+ * @param type Status change type.
+ *
+ * @retval true if immune resist.
+ * @retval false if not immune resist.
+ */
+static bool status_is_immune_to_status(struct status_change *sc, enum sc_type type)
+{
+ nullpo_retr(true, sc);
+ if (sc->data[SC_REFRESH]) {
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
+ return true; // Immune to status ailements
+ switch (type) {
+ case SC__CHAOS:
+ case SC_STONE:
+ case SC_FROSTMISTY:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_MARSHOFABYSS:
+ case SC_MANDRAGORA:
+ return true;
+ }
+ } else if (sc->data[SC_INSPIRATION]) {
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ return true; // Immune to status ailements
+ switch (type) {
+ case SC__CHAOS:
+ case SC_STONE:
+ case SC_FROSTMISTY:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+ case SC_SATURDAY_NIGHT_FEVER:
+ case SC__BODYPAINT:
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__IGNORANCE:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ return true;
+ }
+ }
+ return false;
}
+
/*==========================================
-* Ending all status except those listed.
-* @TODO maybe usefull for dispel instead reseting a liste there.
-* type:
-* 0 - PC killed -> Place here statuses that do not dispel on death.
-* 1 - If for some reason status_change_end decides to still keep the status when quitting.
-* 2 - Do clif
-* 3 - Do not remove some permanent/time-independent effects
-*------------------------------------------*/
-int status_change_clear(struct block_list* bl, int type) {
+ * Ending all status except those listed.
+ * @TODO maybe usefull for dispel instead reseting a liste there.
+ * type:
+ * 0 - PC killed -> Place here statuses that do not dispel on death.
+ * 1 - If for some reason status_change_end decides to still keep the status when quitting.
+ * 2 - Do clif
+ * 3 - Do not remove some permanent/time-independent effects
+ *------------------------------------------*/
+static int status_change_clear(struct block_list *bl, int type)
+{
struct status_change* sc;
int i;
@@ -10223,6 +10521,7 @@ int status_change_clear(struct block_list* bl, int type) {
case SC_ARMOR_PROPERTY://Only when its Holy or Dark that it doesn't dispell on death
if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK )
break;
+ FALLTHROUGH
default:
continue;
}
@@ -10259,18 +10558,17 @@ int status_change_clear(struct block_list* bl, int type) {
}
/*==========================================
-* Special condition we want to effectuate, check before ending a status.
-*------------------------------------------*/
-int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) {
+ * Special condition we want to effectuate, check before ending a status.
+ *------------------------------------------*/
+static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line)
+{
struct map_session_data *sd;
struct status_change *sc;
struct status_change_entry *sce;
struct status_data *st;
struct view_data *vd;
int opt_flag=0, calc_flag;
-#ifdef ANTI_MAYAP_CHEAT
bool invisible = false;
-#endif
nullpo_ret(bl);
@@ -10302,6 +10600,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
//trigger when it also removed one
case SC_STONE:
sce->val3 = 0; //Petrify time counter.
+ FALLTHROUGH
case SC_FREEZE:
case SC_STUN:
case SC_SLEEP:
@@ -10324,10 +10623,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
status->display_remove(sd,type);
}
-#ifdef ANTI_MAYAP_CHEAT
- if (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))
+ if ((sc->option & (OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE)) != 0)
invisible = true;
-#endif
vd = status->get_viewdata(bl);
calc_flag = status->dbs->ChangeFlagTable[type];
@@ -10361,7 +10658,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
if (begin_spurt && sce->val1 >= 7
&& DIFF_TICK(timer->gettick(), starttick) <= 1000
- && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0))
+ && (!sd || (sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST))
)
sc_start(bl, bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1));
}
@@ -10379,10 +10676,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
struct map_session_data *tsd;
if( bl->type == BL_PC ) {
// Clear Status from others
- int i;
- for( i = 0; i < MAX_PC_DEVOTION; i++ ) {
- if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL && tsd->sc.data[type])
- status_change_end(&tsd->bl, type, INVALID_TIMER);
+ if (sd != NULL ) {
+ int i;
+ for( i = 0; i < MAX_PC_DEVOTION; i++ ) {
+ if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL && tsd->sc.data[type])
+ status_change_end(&tsd->bl, type, INVALID_TIMER);
+ }
}
} else if (bl->type == BL_MER) {
struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
@@ -10476,7 +10775,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
if ((sce->val1&0xFFFF) == CG_MOONLIT)
- clif->sc_end(bl,bl->id,AREA,SI_MOON);
+ clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_MOON));
status_change_end(bl, SC_LONGING, INVALID_TIMER);
}
@@ -10562,7 +10861,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
status_percent_heal(bl, 100, 0);
status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER);
} else if(st->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex]
- status->set_hp(bl, 100, 0);
+ status->set_hp(bl, 100, STATUS_HEAL_DEFAULT);
if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) {
sc->data[SC_ENDURE]->val4 = 0;
status_change_end(bl, SC_ENDURE, INVALID_TIMER);
@@ -10614,8 +10913,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if (tid == INVALID_TIMER)
break;
// "lose almost all their HP and SP" on natural expiration.
- status->set_hp(bl, 10, 0);
- status->set_sp(bl, 10, 0);
+ status->set_hp(bl, 10, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, 10, STATUS_HEAL_DEFAULT);
break;
case SC_AUTOTRADE:
if (tid == INVALID_TIMER)
@@ -10688,10 +10987,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_NEUTRALBARRIER_MASTER:
case SC_STEALTHFIELD_MASTER:
- if( sce->val2 ) {
+ case SC_SV_ROOTTWIST:
+ if (sce->val2) {
struct skill_unit_group* group = skill->id2group(sce->val2);
sce->val2 = 0;
- if( group ) /* might have been cleared before status ended, e.g. land protector */
+ if (group) /* might have been cleared before status ended, e.g. land protector */
skill->del_unitgroup(group,ALC_MARK);
}
break;
@@ -10826,6 +11126,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->option &= ~OPTION_OKTOBERFEST;
opt_flag |= 0x4;
break;
+ case SC_DRESS_UP:
+ sc->option &= ~OPTION_SUMMER2;
+ opt_flag |= 0x4;
+ break;
case SC__FEINTBOMB_MASTER:
sc->option &= ~OPTION_INVISIBLE;
opt_flag |= 0x4;
@@ -10868,6 +11172,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
opt_flag = 0;
break;
}
+ FALLTHROUGH
case SC_EXPLOSIONSPIRITS:
sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS;
opt_flag = 0;
@@ -10946,6 +11251,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
#endif
+ // update HP bar when becoming visible again
+ if (invisible && (sc->option & (OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE)) == 0) {
+ if (sd != NULL && battle_config.party_hp_mode == 0 && sd->status.party_id != 0)
+ clif->party_hp(sd);
+ }
+
if (calc_flag&SCB_DYE) { //Restore DYE color
if (vd && !vd->cloth_color && sce->val4)
clif->changelook(bl,LOOK_CLOTHES_COLOR,sce->val4);
@@ -10961,14 +11272,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
#endif
//On Aegis, when turning off a status change, first goes the sc packet, then the option packet.
- clif->sc_end(bl,bl->id,AREA,status->dbs->IconChangeTable[type]);
+ clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(type));
if( opt_flag&8 ) //bugreport:681
clif->changeoption2(bl);
else if(opt_flag) {
clif->changeoption(bl);
if( sd && opt_flag&0x4 ) {
- clif->changelook(bl,LOOK_BASE,sd->vd.class_);
+ clif->changelook(bl, LOOK_BASE, sd->vd.class);
clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield);
clif->changelook(bl,LOOK_WEAPON,sd->vd.weapon);
clif->changelook(bl,LOOK_SHIELD,sd->vd.shield);
@@ -10994,7 +11305,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
return 1;
}
-int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) {
+static int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl;
struct status_change *sc;
struct status_change_entry *sce;
@@ -11019,17 +11331,18 @@ int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) {
hp = st->max_hp - st->hp;
if (hp > sce->val2)
hp = sce->val2;
- if (hp)
- status->heal(bl, hp, 0, 2);
+ if (hp != 0)
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
sce->val4 = INVALID_TIMER;
return 1;
}
/*==========================================
-* For recusive status, like for each 5s we drop sp etc.
-* Reseting the end timer.
-*------------------------------------------*/
-int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
+ * For recusive status, like for each 5s we drop sp etc.
+ * Reseting the end timer.
+ *------------------------------------------*/
+static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
+{
enum sc_type type = (sc_type)data;
struct block_list *bl;
struct map_session_data *sd;
@@ -11150,23 +11463,26 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_POISON:
- if(st->hp <= max(st->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left.
+ if (st->hp <= max(st->max_hp / 4, sce->val4)) //Stop damaging after 25% HP left.
break;
+ FALLTHROUGH
case SC_DPOISON:
if (--(sce->val3) > 0) {
- if (!sc->data[SC_SLOWPOISON]) {
- if( sce->val2 && bl->type == BL_MOB ) {
- struct block_list* src = map->id2bl(sce->val2);
- if (src != NULL)
- mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4);
- }
- map->freeblock_lock();
- status_zap(bl, sce->val4, 0);
- if (sc->data[type]) { // Check if the status still last ( can be dead since then ).
- sc_timer_next(1000 + tick, status->change_timer, bl->id, data );
- }
- map->freeblock_unlock();
+ if (sc->data[SC_SLOWPOISON] != NULL) {
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ if (sce->val2 != 0 && bl->type == BL_MOB) {
+ struct block_list* src = map->id2bl(sce->val2);
+ if (src != NULL)
+ mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4);
+ }
+ map->freeblock_lock();
+ status_zap(bl, sce->val4, 0);
+ if (sc->data[type] != NULL) { // Check if the status still last (can be dead since then).
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
}
+ map->freeblock_unlock();
return 0;
}
break;
@@ -11222,7 +11538,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
int hp = 0;
if (st->hp < st->max_hp)
hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ;
- status->heal(bl, hp, 0, 2);
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
sc_timer_next((sce->val2 * 1000) + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11282,6 +11598,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
//Moonlit's cost is 4sp*skill_lv [Skotlex]
sp= 4*(sce->val1>>16);
//Upkeep is also every 10 secs.
+ FALLTHROUGH
case DC_DONTFORGETME:
s=10;
break;
@@ -11319,10 +11636,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_SPLASHER:
#if 0 // custom Venom Splasher countdown timer
- if (sce->val4 % 1000 == 0) {
+ if (sce->val4 % 1000 == 0 && bl && bl->type == BL_PC) {
char counter[10];
snprintf (counter, 10, "%d", sce->val4/1000);
- clif->message(bl, counter);
+ clif->message(BL_UCCAST(BL_PC, bl)->fd, counter);
}
#endif // 0
if((sce->val4 -= 500) > 0) {
@@ -11370,7 +11687,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_ABUNDANCE:
if(--(sce->val4) > 0) {
- status->heal(bl,0,60,0);
+ status->heal(bl, 0, 60, STATUS_HEAL_DEFAULT);
sc_timer_next(10000+tick, status->change_timer, bl->id, data);
}
break;
@@ -11429,17 +11746,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
mushroom_skill_id = skill->dbs->magicmushroom_db[i].skill_id;
} while (mushroom_skill_id == 0);
- switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage
- case CAST_GROUND:
- skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
- }
+ skill->castend_type(skill->get_casttype(mushroom_skill_id), bl, bl, mushroom_skill_id, 1, tick, 0);
}
clif->emotion(bl,E_HEH);
@@ -11496,7 +11803,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
heal = ~heal + 1;
map->freeblock_lock();
- status->heal(bl, heal, 0, 2);
+ status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT);
if( sc->data[type] ) {
sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
}
@@ -11610,7 +11917,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if( --(sce->val4) > 0 ) {
struct block_list *src = map->id2bl(sce->val2);
int damage;
- if( !src || (src && (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) )
+ if (src == NULL || (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12))
break;
map->freeblock_lock();
damage = sce->val3;
@@ -11619,7 +11926,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if ( sc->data[type] ) {
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
}
- status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level
+ status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, STATUS_HEAL_DEFAULT); // 5 + 5% per level
map->freeblock_unlock();
return 0;
}
@@ -11636,7 +11943,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_DEEP_SLEEP:
if( --(sce->val4) >= 0 )
{// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds.
- status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2);
+ status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, STATUS_HEAL_SHOWEFFECT);
sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11646,7 +11953,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if( --(sce->val4) >= 0 ) {
if( !status->charge(bl,0,sce->val3) )
break;
- status->heal(bl, sce->val2, 0, 1);
+ status->heal(bl, sce->val2, 0, STATUS_HEAL_FORCED);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11654,7 +11961,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_SONG_OF_MANA:
if( --(sce->val4) >= 0 ) {
- status->heal(bl,0,sce->val3,3);
+ status->heal(bl, 0, sce->val3, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11848,7 +12155,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
case SC_MEIKYOUSISUI:
if( --(sce->val4) > 0 ) {
- status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, 0);
+ status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, STATUS_HEAL_DEFAULT);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11884,7 +12191,20 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_FRIGG_SONG:
if( --(sce->val4) > 0 ) {
- status->heal(bl, sce->val3, 0, 0);
+ status->heal(bl, sce->val3, 0, STATUS_HEAL_DEFAULT);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_FRESHSHRIMP:
+ if (--(sce->val4) >= 0) {
+ status_heal(bl, st->max_hp / 100, 0, 2);
+ sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick, status->change_timer, bl->id, data);
+ }
+ break;
+ case SC_BITESCAR:
+ if (--(sce->val4) >= 0) {
+ status_percent_damage(bl, bl, -(sce->val2), 0, 0);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11897,9 +12217,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
}
/*==========================================
-* Foreach iteration of repetitive status
-*------------------------------------------*/
-int status_change_timer_sub(struct block_list* bl, va_list ap) {
+ * Foreach iteration of repetitive status
+ *------------------------------------------*/
+static int status_change_timer_sub(struct block_list *bl, va_list ap)
+{
struct status_change* tsc;
struct block_list* src = va_arg(ap,struct block_list*);
@@ -11907,6 +12228,8 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int
int64 tick = va_arg(ap, int64);
+ nullpo_ret(bl);
+
if (status->isdead(bl))
return 0;
@@ -11957,13 +12280,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
break;
case SC_RG_CCONFINE_M:
//Lock char has released the hold on everyone...
- if (tsc && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) {
+ if (tsc != NULL && src != NULL && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) {
tsc->data[SC_RG_CCONFINE_S]->val2 = 0;
status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
}
break;
case SC_CURSEDCIRCLE_TARGET:
- if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) {
+ if (tsc != NULL && src != NULL && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id) {
clif->bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0);
status_change_end(bl, type, INVALID_TIMER);
}
@@ -11972,14 +12295,24 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
return 0;
}
-int status_get_total_def(struct block_list *src) { return status->get_status_data(src)->def2 + (short)status->get_def(src); }
-int status_get_total_mdef(struct block_list *src) { return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); }
-int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag)
+static int status_get_total_def(struct block_list *src)
+{
+ return status->get_status_data(src)->def2 + (short)status->get_def(src);
+}
+
+static int status_get_total_mdef(struct block_list *src)
+{
+ return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src);
+}
+
+static int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag)
{
#ifdef RENEWAL
int min = 0, max = 0;
struct status_change *sc = status->get_sc(bl);
+ nullpo_ret(bl);
+ nullpo_ret(watk);
if (bl->type == BL_PC && watk->atk) {
float strdex_bonus, variance;
int dstr;
@@ -12014,10 +12347,10 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
if ( bl->type == BL_PC && !(flag & 2) ) {
const struct map_session_data *sd = BL_UCCAST(BL_PC, bl);
- short index = sd->equip_index[EQI_HAND_R], refine;
+ short index = sd->equip_index[EQI_HAND_R], refine_level;
if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON
- && (refine = sd->status.inventory[index].refine) < 16 && refine ) {
- int r = status->dbs->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100;
+ && (refine_level = sd->status.inventory[index].refine) < 16 && refine_level) {
+ int r = refine->get_randombonus_max(watk->wlv, refine_level + (4 - watk->wlv) + 1) / 100;
if ( r )
max += (rnd() % 100) % r + 1;
}
@@ -12035,13 +12368,14 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
}
/**
-* 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) {
+ * 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
+ */
+static 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;
@@ -12068,6 +12402,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
// Any +MATK you get from skills and cards, including cards in weapon, is added here.
if ( sd && sd->bonus.ematk > 0 && flag != 3 )
*matk_min += sd->bonus.ematk;
+ if (sd && pc->checkskill(sd, SU_POWEROFLAND) > 0) {
+ if (pc->checkskill(sd, SU_SV_STEMSPEAR) == 5 && pc->checkskill(sd, SU_CN_POWDERING) == 5 && pc->checkskill(sd, SU_CN_METEOR) == 5 && pc->checkskill(sd, SU_SV_ROOTTWIST) == 5)
+ *matk_min += *matk_min * 20 / 100;
+ }
if ( flag != 3 )
*matk_min = status->calc_ematk(bl, sc, *matk_min);
@@ -12079,6 +12417,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
if ( (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
+ if (sc != NULL && sc->data[SC_CATNIPPOWDER])
+ wMatk -= wMatk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
*matk_min += wMatk - variance;
*matk_max += wMatk + variance;
}
@@ -12107,8 +12447,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
}
#else // not RENEWAL
- *matk_min = status_base_matk_min(st) + (sd ? sd->bonus.ematk : 0);
- *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 ) {
@@ -12122,10 +12462,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
#ifdef RENEWAL
if ( sd && !(flag & 2) ) {
- short index = sd->equip_index[EQI_HAND_R], refine;
+ short index = sd->equip_index[EQI_HAND_R], refine_level;
if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON
- && (refine = sd->status.inventory[index].refine) < 16 && refine ) {
- int r = status->dbs->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100;
+ && (refine_level = sd->status.inventory[index].refine) < 16 && refine_level) {
+ int r = refine->get_randombonus_max(sd->inventory_data[index]->wlv, refine_level + (4 - sd->inventory_data[index]->wlv) + 1) / 100;
if ( r )
*matk_max += (rnd() % 100) % r + 1;
}
@@ -12146,9 +12486,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
#undef status_get_homluk
/**
-* 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) {
+ * Gets a random matk value depending on min matk and max matk
+ */
+static 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
@@ -12156,17 +12497,18 @@ unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk
}
/**
-* 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) {
+ * 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]
+ */
+static int status_get_matk(struct block_list *bl, int flag)
+{
struct status_data *st;
unsigned short matk_max, matk_min;
@@ -12192,9 +12534,10 @@ int status_get_matk(struct block_list *bl, int flag) {
}
/**
-* Updates bl's MATK values
-**/
-void status_update_matk(struct block_list *bl) {
+ * Updates bl's MATK values
+ */
+static void status_update_matk(struct block_list *bl)
+{
struct status_data *st;
struct status_change *sc;
unsigned short matk_max, matk_min;
@@ -12218,11 +12561,12 @@ void status_update_matk(struct block_list *bl) {
}
/*==========================================
-* Clears buffs/debuffs of a character.
-* type&1 -> buffs, type&2 -> debuffs
-* type&4 -> especific debuffs(implemented with refresh)
-*------------------------------------------*/
-int status_change_clear_buffs (struct block_list* bl, int type) {
+ * Clears buffs/debuffs of a character.
+ * type&1 -> buffs, type&2 -> debuffs
+ * type&4 -> especific debuffs(implemented with refresh)
+ *------------------------------------------*/
+static int status_change_clear_buffs(struct block_list *bl, int type)
+{
int i;
struct status_change *sc= status->get_sc(bl);
@@ -12283,7 +12627,8 @@ int status_change_clear_buffs (struct block_list* bl, int type) {
return 0;
}
-int status_change_spread( struct block_list *src, struct block_list *bl ) {
+static int status_change_spread(struct block_list *src, struct block_list *bl)
+{
int i, flag = 0;
struct status_change *sc = status->get_sc(src);
int64 tick;
@@ -12373,7 +12718,8 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
}
//Natural regen related stuff.
-int status_natural_heal(struct block_list* bl, va_list args) {
+static int status_natural_heal(struct block_list *bl, va_list args)
+{
struct regen_data *regen;
struct status_data *st;
struct status_change *sc;
@@ -12383,6 +12729,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
struct map_session_data *sd;
int val,rate,bonus = 0,flag;
+ nullpo_ret(bl);
regen = status->get_regen_data(bl);
if (!regen) return 0;
st = status->get_status_data(bl);
@@ -12426,7 +12773,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
sregen->tick.hp += val;
while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) {
+ if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) {
//Full
flag&=~(RGN_HP|RGN_SHP);
break;
@@ -12441,7 +12788,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
sregen->tick.sp += val;
while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, 0, sregen->sp, 3) < sregen->sp) {
+ if (status->heal(bl, 0, sregen->sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->sp) {
//Full
flag&=~(RGN_SP|RGN_SSP);
break;
@@ -12490,7 +12837,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
val += regen->hp;
regen->tick.hp -= battle_config.natural_healhp_interval;
} while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval);
- if (status->heal(bl, val, 0, 1) < val)
+ if (status->heal(bl, val, 0, STATUS_HEAL_FORCED) < val)
flag&=~RGN_SHP; //full.
}
}
@@ -12509,7 +12856,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
val += regen->sp;
regen->tick.sp -= battle_config.natural_healsp_interval;
} while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval);
- if (status->heal(bl, 0, val, 1) < val)
+ if (status->heal(bl, 0, val, STATUS_HEAL_FORCED) < val)
flag&=~RGN_SSP; //full.
}
}
@@ -12526,7 +12873,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp)
+ if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp)
break; //Full
}
}
@@ -12541,7 +12888,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
if ((rate = pc->checkskill(sd,TK_SPTIME)))
sc_start(bl,bl,status->skill2sc(TK_SPTIME),
100,rate,skill->get_time(TK_SPTIME, rate));
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
&&rnd()%10000 < battle_config.sg_angel_skill_ratio
) {
//Angel of the Sun/Moon/Star
@@ -12551,7 +12898,7 @@ int status_natural_heal(struct block_list* bl, va_list args) {
}
}
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, 0, val, 3) < val)
+ if (status->heal(bl, 0, val, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < val)
break; //Full
}
}
@@ -12559,7 +12906,8 @@ int status_natural_heal(struct block_list* bl, va_list args) {
}
//Natural heal main timer.
-int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) {
+static int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data)
+{
// This difference is always positive and lower than UINT_MAX (~24 days)
status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX);
map->foreachregen(status->natural_heal);
@@ -12567,21 +12915,8 @@ int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-/**
-* Get the chance to upgrade a piece of equipment.
-* @param wlv The weapon type of the item to refine (see see enum refine_type)
-* @param refine The target refine level
-* @return The chance to refine the item, in percent (0~100)
-**/
-int status_get_refine_chance(enum refine_type wlv, int refine) {
-
- if ( refine < 0 || refine >= MAX_REFINE)
- return 0;
-
- return status->dbs->refine_info[wlv].chance[refine];
-}
-
-int status_get_sc_type(sc_type type) {
+static int status_get_sc_type(sc_type type)
+{
if( type <= SC_NONE || type >= SC_MAX )
return 0;
@@ -12589,10 +12924,11 @@ int status_get_sc_type(sc_type type) {
return status->dbs->sc_conf[type];
}
-void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb)
+static void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb)
{
struct config_setting_t *temp = NULL;
int i32 = 0;
+ const char *str = NULL;
struct {
const char *name;
@@ -12627,6 +12963,38 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
#endif
};
+ /**
+ * @field BaseExpGroup must be read before any other that deal with exp tables.
+ */
+ if (libconfig->setting_lookup_string(jdb, "BaseExpGroup", &str) != 0) {
+ int i = 0;
+ ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i).name) == 0);
+ if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE])) {
+ ShowError("status_read_job_db: Unknown Base Exp Group '%s' provided for entry '%s'\n", str, name);
+ } else {
+ pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i);
+ }
+ } else {
+ ShowError("status_read_job_db: BaseExpGroup setting not found for entry '%s', skipping..\n", name);
+ return;
+ }
+
+ /**
+ * @field JobExpGroup must be read before any other that deal with exp tables.
+ */
+ if (libconfig->setting_lookup_string(jdb, "JobExpGroup", &str) != 0) {
+ int i = 0;
+ ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i).name) == 0);
+ if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB])) {
+ ShowError("status_read_job_db: Unknown Job Exp Group '%s' provided for entry '%s'\n", str, name);
+ } else {
+ pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_JOB] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i);
+ }
+ } else {
+ ShowError("status_read_job_db: JobExpGroup setting not found for entry '%s', skipping..\n", name);
+ return;
+ }
+
if ((temp = libconfig->setting_get_member(jdb, "Inherit"))) {
int nidx = 0;
const char *iname;
@@ -12651,7 +13019,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 5;
}
- for ( ; i <= pc->max_level[idx][0]; i++) {
+ for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) {
status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp);
}
@@ -12666,7 +13034,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 1;
}
- for ( ; i <= pc->max_level[idx][0]; i++) {
+ for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) {
status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp);
}
}
@@ -12692,7 +13060,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 5;
}
- for ( ; i <= pc->max_level[idx][0]; i++) {
+ for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) {
status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp);
}
}
@@ -12718,7 +13086,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 1;
}
- for ( ; i <= pc->max_level[idx][0]; i++) {
+ for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) {
status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp);
}
}
@@ -12760,7 +13128,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 5;
}
- for (++level; level <= pc->max_level[idx][0]; ++level) { /* limit only to possible maximum level of the given class */
+ for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; ++level) { /* limit only to possible maximum level of the given class */
status->dbs->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */
}
}
@@ -12780,60 +13148,65 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
} else {
avg_increment = 1;
}
- for (++level; level <= pc->max_level[idx][0]; level++ ) {
+ for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; level++) {
status->dbs->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp);
}
}
}
+/* [malufett/Hercules] */
/*------------------------------------------
-* DB reading.
-* job_db.conf - weight, hp, sp, aspd
-* job_db2.txt - job level stat bonuses
-* size_fix.txt - size adjustment table for weapons
-* refine_db.txt - refining data table
-*------------------------------------------*/
-void status_read_job_db(void) { /* [malufett/Hercules] */
+ * DB reading.
+ * job_db.conf - weight, hp, sp, aspd
+ * job_db2.txt - job level stat bonuses
+ * size_fix.txt - size adjustment table for weapons
+ * refine_db.txt - refining data table
+ *------------------------------------------*/
+static void status_read_job_db(void)
+{
int i = 0;
struct config_t job_db_conf;
struct config_setting_t *jdb = NULL;
+ char config_filename[256];
+
#ifdef RENEWAL_ASPD
- const char *config_filename = "db/re/job_db.conf";
+ libconfig->format_db_path(DBPATH_RE"job_db.conf", config_filename, sizeof(config_filename));
#else
- const char *config_filename = "db/pre-re/job_db.conf";
+ libconfig->format_db_path(DBPATH_PRE"job_db.conf", config_filename, sizeof(config_filename));
#endif
if (!libconfig->load_file(&job_db_conf, config_filename))
return;
- while ( (jdb = libconfig->setting_get_elem(job_db_conf.root, i++)) ) {
- int class_, idx;
+ while ((jdb = libconfig->setting_get_elem(job_db_conf.root, i++))) {
+ int class, idx;
const char *name = config_setting_name(jdb);
- if ( (class_ = pc->check_job_name(name)) == -1 ) {
+ if ((class = pc->check_job_name(name)) == -1) {
ShowWarning("pc_read_job_db: '%s' unknown job name!\n", name);
continue;
}
- idx = pc->class2idx(class_);
+ idx = pc->class2idx(class);
status->read_job_db_sub(idx, name, jdb);
}
+
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename);
libconfig->destroy(&job_db_conf);
}
-bool status_readdb_job2(char* fields[], int columns, int current)
+static bool status_readdb_job2(char *fields[], int columns, int current)
{
- int idx, class_, i;
+ int idx, class, i;
- class_ = atoi(fields[0]);
+ nullpo_retr(false, fields);
+ class = atoi(fields[0]);
- if(!pc->db_checkid(class_))
- {
- ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_);
+ if (!pc->db_checkid(class)) {
+ ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class);
return false;
}
- idx = pc->class2idx(class_);
+ idx = pc->class2idx(class);
for(i = 1; i < columns; i++)
{
@@ -12842,10 +13215,11 @@ bool status_readdb_job2(char* fields[], int columns, int current)
return true;
}
-bool status_readdb_sizefix(char* fields[], int columns, int current)
+static bool status_readdb_sizefix(char *fields[], int columns, int current)
{
unsigned int i;
+ nullpo_retr(false, fields);
for(i = 0; i < MAX_SINGLE_WEAPON_TYPE; i++)
{
status->dbs->atkmods[current][i] = atoi(fields[i]);
@@ -12853,150 +13227,114 @@ bool status_readdb_sizefix(char* fields[], int columns, int current)
return true;
}
-/**
- * Processes a refine_db.conf entry.
- *
- * @param r Libconfig setting entry. It is expected to be valid and it
- * won't be freed (it is care of the caller to do so if
- * necessary)
- * @param n Ordinal number of the entry, to be displayed in case of
- * validation errors.
- * @param source Source of the entry (file name), to be displayed in case of
- * validation errors.
- * @return # of the validated entry, or 0 in case of failure.
- */
-int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source)
-{
- struct config_setting_t *rate = NULL;
- int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0;
- char lv[4];
- nullpo_ret(r);
- nullpo_ret(name);
- nullpo_ret(source);
-
- if (strncmp(name, "Armors", 6) == 0) {
- type = REFINE_TYPE_ARMOR;
- } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) {
- ShowError("status_readdb_refine_libconfig_sub: Invalid key name for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
- if (type < REFINE_TYPE_ARMOR || type >= REFINE_TYPE_MAX) {
- ShowError("status_readdb_refine_libconfig_sub: Out of range level for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
- if (!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) {
- ShowWarning("status_readdb_refine_libconfig_sub: Missing StatsPerLevel for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
- if (!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) {
- ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusStartLevel for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
- if (!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) {
- ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusValue for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
-
- if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) {
- struct config_setting_t *t = NULL;
- bool duplicate[MAX_REFINE];
- int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE];
- int i;
- memset(&duplicate, 0, sizeof(duplicate));
- memset(&bonus, 0, sizeof(bonus));
- memset(&rnd_bonus, 0, sizeof(rnd_bonus));
-
- for (i = 0; i < MAX_REFINE; i++) {
- chance[i] = 100;
- }
- i = 0;
- while ((t = libconfig->setting_get_elem(rate,i++)) != NULL && config_setting_is_group(t)) {
- int level = 0, i32;
- char *rlvl = config_setting_name(t);
- memset(&lv, 0, sizeof(lv));
- if (!strspn(&rlvl[strlen(rlvl)-1], "0123456789") || (level = atoi(strncpy(lv, rlvl+2, 3))) <= 0) {
- ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source);
- continue;
- }
- if (level <= 0 || level > MAX_REFINE) {
- ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source);
- continue;
- }
- level--;
- if (duplicate[level]) {
- ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source);
- } else {
- duplicate[level] = true;
- }
- if (libconfig->setting_lookup_int(t, "Chance", &i32))
- chance[level] = i32;
- else
- chance[level] = 100;
- if (libconfig->setting_lookup_int(t, "Bonus", &i32))
- bonus[level] += i32;
- if (level >= rnd_bonus_lv - 1)
- rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2);
- }
- for (i = 0; i < MAX_REFINE; i++) {
- status->dbs->refine_info[type].chance[i] = chance[i];
- status->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i];
- bonus[i] += bonus_per_level + (i > 0 ? bonus[i-1] : 0);
- status->dbs->refine_info[type].bonus[i] = bonus[i];
- }
- } else {
- ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source);
- return 0;
- }
- return type+1;
-}
-
-/**
- * Reads from a libconfig-formatted refine_db.conf file.
- *
- * @param *filename File name, relative to the database path.
- * @return The number of found entries.
- */
-int status_readdb_refine_libconfig(const char *filename) {
- bool duplicate[REFINE_TYPE_MAX];
- struct config_t refine_db_conf;
- struct config_setting_t *r;
+static bool status_read_scdb_libconfig(void)
+{
+ struct config_t status_conf;
char filepath[256];
- int i = 0, count = 0,type = 0;
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, "sc_config.conf");
- sprintf(filepath, "%s/%s", map->db_path, filename);
- if (!libconfig->load_file(&refine_db_conf, filepath))
- return 0;
+ if (libconfig->load_file(&status_conf, filepath) == CONFIG_FALSE) {
+ ShowError("status_read_scdb_libconfig: can't read %s\n", filepath);
+ return false;
+ }
- memset(&duplicate,0,sizeof(duplicate));
+ int i = 0;
+ int count = 0;
+ struct config_setting_t *it = NULL;
- while((r = libconfig->setting_get_elem(refine_db_conf.root,i++))) {
- char *name = config_setting_name(r);
- if((type=status->readdb_refine_libconfig_sub(r, name, filename))) {
- if( duplicate[type-1] ) {
- ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename);
- } else duplicate[type-1] = true;
- count++;
- }
+ while ((it = libconfig->setting_get_elem(status_conf.root, i++)) != NULL) {
+ if (status->read_scdb_libconfig_sub(it, i - 1, filepath))
+ ++count;
}
- libconfig->destroy(&refine_db_conf);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
- return count;
+ // @TODO: find a better way of handling this
+ if (!battle_config.display_hallucination) //Disable Hallucination.
+ status->dbs->IconChangeTable[SC_ILLUSION].id = SI_BLANK;
+
+ libconfig->destroy(&status_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath);
+ return true;
}
-bool status_readdb_scconfig(char* fields[], int columns, int current) {
- int val = 0;
- char* type = fields[0];
+static bool status_read_scdb_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
+
+ int i32;
+ int status_id;
+ const char *name = config_setting_name(it);
- if( !script->get_constant(type, &val) ){
- ShowWarning("status_readdb_sc_conf: Invalid status type %s specified.\n", type);
+ if (!script->get_constant(name, &status_id) || status_id <= SC_NONE || status_id >= SC_MAX) {
+ ShowWarning("status_read_scdb_libconfig_sub: Invalid status type (%s) in \"%s\" entry #%d, skipping.\n", name, source, idx);
return false;
}
- status->dbs->sc_conf[val] = (int)strtol(fields[1], NULL, 0);
+ libconfig->setting_lookup_bool_real(it, "Visible", &status->dbs->DisplayType[status_id]);
+
+ struct config_setting_t *fg = libconfig->setting_get_member(it, "Flags");
+ if (fg != NULL)
+ status->read_scdb_libconfig_sub_flag(fg, status_id, source);
+ if (itemdb->lookup_const(it, "Icon", &i32) && i32 >= 0)
+ status->dbs->IconChangeTable[status_id].id = i32;
+ else
+ status->dbs->IconChangeTable[status_id].id = SI_BLANK;
+ return true;
+}
+
+static bool status_read_scdb_libconfig_sub_flag(struct config_setting_t *it, int type, const char *source)
+{
+ nullpo_retr(false, it);
+ nullpo_retr(false, source);
+ Assert_retr(false, type > SC_NONE && type < SC_MAX);
+
+ int i = 0;
+ struct config_setting_t *t = NULL;
+ while ((t = libconfig->setting_get_elem(it, i++)) != NULL) {
+ const char *flag = config_setting_name(t);
+ bool on = libconfig->setting_get_bool_real(t);
+ int j;
+
+ struct {
+ const char *name;
+ enum sc_conf_type value;
+ } flags[] = {
+ { "NoDeathReset", SC_NO_REM_DEATH },
+ { "NoSave", SC_NO_SAVE },
+ { "NoDispelReset", SC_NO_DISPELL },
+ { "NoClearanceReset", SC_NO_CLEARANCE },
+ { "Buff", SC_BUFF },
+ { "Debuff", SC_DEBUFF },
+ { "NoMadoReset", SC_MADO_NO_RESET },
+ { "NoAllReset", SC_NO_CLEAR },
+ { "NoBoss", SC_NO_BOSS },
+ };
+
+ ARR_FIND(0, ARRAYLENGTH(flags), j, strcmpi(flag, flags[j].name) == 0);
+ if (j != ARRAYLENGTH(flags)) {
+ if (strcmp(flag, flags[j].name) != 0) {
+ ShowWarning("status_read_scdb_libconfig_sub_flag: flag (%s) for status effect (%d) is casesensitive, correct it to (%s).", flag, type, flags[i].name);
+ }
+ if (on) {
+ status->dbs->sc_conf[type] |= flags[j].value;
+ } else {
+ status->dbs->sc_conf[type] &= ~flags[j].value;
+ }
+ } else {
+ if (!status->read_scdb_libconfig_sub_flag_additional(it, type, source))
+ ShowWarning("status_read_scdb_libconfig_sub_flag: invalid flag (%s) for status effect (%d).", flag, type);
+ }
+ }
return true;
}
+
+static bool status_read_scdb_libconfig_sub_flag_additional(struct config_setting_t *it, int type, const char *source)
+{
+ // to be used by plugins
+ return false;
+}
+
/**
* Read status db
* job1.txt
@@ -13004,7 +13342,7 @@ bool status_readdb_scconfig(char* fields[], int columns, int current) {
* size_fixe.txt
* refine_db.txt
**/
-int status_readdb(void)
+static int status_readdb(void)
{
int i, j;
@@ -13031,30 +13369,23 @@ int status_readdb(void)
for(j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++)
status->dbs->atkmods[i][j] = 100;
- // refine_db.txt
- for(i=0;i<ARRAYLENGTH(status->dbs->refine_info);i++) {
- for(j=0;j<MAX_REFINE; j++) {
- status->dbs->refine_info[i].chance[j] = 100;
- status->dbs->refine_info[i].bonus[j] = 0;
- status->dbs->refine_info[i].randombonus_max[j] = 0;
- }
- }
-
// read databases
//
sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2);
sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_SINGLE_WEAPON_TYPE, MAX_SINGLE_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix);
- status->readdb_refine_libconfig(DBPATH"refine_db.conf");
- sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig);
+ status->read_scdb_libconfig();
status->read_job_db();
+ pc->validate_levels();
+
return 0;
}
/*==========================================
-* Status db init and destroy.
-*------------------------------------------*/
-int do_init_status(bool minimal) {
+ * Status db init and destroy.
+ *------------------------------------------*/
+static int do_init_status(bool minimal)
+{
if (minimal)
return 0;
@@ -13069,16 +13400,19 @@ int do_init_status(bool minimal) {
timer->add_interval(status->natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status->natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
return 0;
}
-void do_final_status(void) {
+
+static void do_final_status(void)
+{
ers_destroy(status->data_ers);
}
/*=====================================
-* Default Functions : status.h
-* Generated by HerculesInterfaceMaker
-* created by Susu
-*-------------------------------------*/
-void status_defaults(void) {
+ * Default Functions : status.h
+ * Generated by HerculesInterfaceMaker
+ * created by Susu
+ *-------------------------------------*/
+void status_defaults(void)
+{
status = &status_s;
status->dbs = &statusdbs;
@@ -13096,13 +13430,13 @@ void status_defaults(void) {
status->natural_heal_prev_tick = 0;
status->natural_heal_diff_tick = 0;
/* funcs */
- status->get_refine_chance = status_get_refine_chance;
// for looking up associated data
status->skill2sc = status_skill2sc;
status->sc2skill = status_sc2skill;
status->sc2scb_flag = status_sc2scb_flag;
- status->type2relevant_bl_types = status_type2relevant_bl_types;
+ status->get_sc_relevant_bl_types = status_get_sc_relevant_bl_types;
status->get_sc_type = status_get_sc_type;
+ status->get_sc_icon = status_get_sc_icon;
status->damage = status_damage;
//Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
@@ -13140,6 +13474,7 @@ void status_defaults(void) {
status->get_sc_def = status_get_sc_def;
status->change_start = status_change_start;
+ status->change_start_sub = status_change_start_sub;
status->change_end_ = status_change_end_;
status->kaahi_heal_timer = kaahi_heal_timer;
status->change_timer = status_change_timer;
@@ -13147,11 +13482,18 @@ void status_defaults(void) {
status->change_clear = status_change_clear;
status->change_clear_buffs = status_change_clear_buffs;
+ status->is_immune_to_status = status_is_immune_to_status;
+ status->is_boss_resist_sc = status_is_boss_resist_sc;
+ status->end_sc_before_start = status_end_sc_before_start;
+ status->change_start_stop_action = status_change_start_stop_action;
+ status->change_start_set_option = status_change_start_set_option;
+ status->get_val_flag = status_get_val_flag;
status->calc_bl_ = status_calc_bl_;
status->calc_mob_ = status_calc_mob_;
status->calc_pet_ = status_calc_pet_;
status->calc_pc_ = status_calc_pc_;
status->calc_pc_additional = status_calc_pc_additional;
+ status->calc_pc_recover_hp = status_calc_pc_recover_hp;
status->calc_homunculus_ = status_calc_homunculus_;
status->calc_mercenary_ = status_calc_mercenary_;
status->calc_elemental_ = status_calc_elemental_;
@@ -13188,6 +13530,8 @@ void status_defaults(void) {
status->base_atk = status_base_atk;
status->get_base_maxhp = status_get_base_maxhp;
status->get_base_maxsp = status_get_base_maxsp;
+ status->get_restart_hp = status_get_restart_hp;
+ status->get_restart_sp = status_get_restart_sp;
status->calc_npc_ = status_calc_npc_;
status->calc_str = status_calc_str;
status->calc_agi = status_calc_agi;
@@ -13214,14 +13558,21 @@ void status_defaults(void) {
status->calc_ematk = status_calc_ematk;
status->calc_bl_main = status_calc_bl_main;
status->display_add = status_display_add;
+ status->change_start_display = status_change_start_display;
+ status->change_start_unknown_sc = status_change_start_unknown_sc;
status->display_remove = status_display_remove;
status->natural_heal = status_natural_heal;
status->natural_heal_timer = status_natural_heal_timer;
status->readdb_job2 = status_readdb_job2;
status->readdb_sizefix = status_readdb_sizefix;
- status->readdb_refine_libconfig = status_readdb_refine_libconfig;
- status->readdb_refine_libconfig_sub = status_readdb_refine_libconfig_sub;
- status->readdb_scconfig = status_readdb_scconfig;
+ status->read_scdb_libconfig = status_read_scdb_libconfig;
+ status->read_scdb_libconfig_sub = status_read_scdb_libconfig_sub;
+ status->read_scdb_libconfig_sub_flag = status_read_scdb_libconfig_sub_flag;
+ status->read_scdb_libconfig_sub_flag_additional = status_read_scdb_libconfig_sub_flag_additional;
status->read_job_db = status_read_job_db;
status->read_job_db_sub = status_read_job_db_sub;
+ status->set_sc = status_set_sc;
+ status->copy = status_copy;
+ status->base_matk_min = status_base_matk_min;
+ status->base_matk_max = status_base_matk_max;
}
diff --git a/src/map/status.h b/src/map/status.h
index 2b932b149..d5cb3da75 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,37 +49,20 @@ struct pet_data;
)
/**
- * Max Refine available to your server
- * Changing this limit requires edits to refine_db.txt
- **/
-#ifdef RENEWAL
- #define MAX_REFINE 20
-#else
- #define MAX_REFINE 10
-#endif
-
-enum refine_type {
- REFINE_TYPE_ARMOR = 0,
- REFINE_TYPE_WEAPON1 = 1,
- REFINE_TYPE_WEAPON2 = 2,
- REFINE_TYPE_WEAPON3 = 3,
- REFINE_TYPE_WEAPON4 = 4,
- REFINE_TYPE_MAX = 5
-};
-
-/**
* SC configuration type
- * @see db/sc_config.txt for more information
+ * @see db/sc_config.conf for more information
**/
typedef enum sc_conf_type {
- SC_NO_REM_DEATH = 0x01,
- SC_NO_SAVE = 0x02,
- SC_NO_DISPELL = 0x04,
- SC_NO_CLEARANCE = 0x08,
- SC_BUFF = 0x10,
- SC_DEBUFF = 0x20,
- SC_MADO_NO_RESET = 0x40,
- SC_NO_CLEAR = 0x80,
+ SC_NO_REM_DEATH = 0x001,
+ SC_NO_SAVE = 0x002,
+ SC_NO_DISPELL = 0x004,
+ SC_NO_CLEARANCE = 0x008,
+ SC_BUFF = 0x010,
+ SC_DEBUFF = 0x020,
+ SC_MADO_NO_RESET = 0x040,
+ SC_NO_CLEAR = 0x080,
+ SC_VISIBLE = 0x100,
+ SC_NO_BOSS = 0x200
} sc_conf_type;
/**
@@ -96,6 +79,16 @@ enum scstart_flag {
SCFLAG_ALL = SCFLAG_NONE|SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE|SCFLAG_NOICON
};
+/**
+ * Flags to be used with status->heal() and related functions.
+ */
+enum status_heal_flag {
+ STATUS_HEAL_DEFAULT = 0x00, ///< Default
+ STATUS_HEAL_FORCED = 0x01, ///< Forced healing (bypassing Berserk and similar)
+ STATUS_HEAL_SHOWEFFECT = 0x02, ///< Show the HP/SP heal effect
+ STATUS_HEAL_ALLOWREVIVE = 0x04, ///< Force resurrection in case of dead targets.
+};
+
// Status changes listing. These code are for use by the server.
typedef enum sc_type {
SC_NONE = -1,
@@ -826,974 +819,56 @@ typedef enum sc_type {
SC_G_LIFEPOTION, // 640
SC_MYSTICPOWDER,
+ // Summoner
+ SC_SUHIDE,
+ SC_SU_STOOP,
+ SC_SPRITEMABLE,
+ SC_CATNIPPOWDER,
+ SC_SV_ROOTTWIST,
+ SC_BITESCAR,
+ SC_ARCLOUSEDASH,
+ SC_TUNAPARTY,
+ SC_SHRIMP, // 650
+ SC_FRESHSHRIMP,
+
+ SC_DRESS_UP,
+
+ // Rodex
+ SC_DAILYSENDMAILCNT,
+
+ // Clan System
+ SC_CLAN_INFO,
+
+ SC_SIT,
+ SC_MOON,
+ SC_TING,
+ SC_DEVIL1,
+ SC_RIDING,
+ SC_FALCON,
+ SC_WUGRIDER,
+ SC_POSTDELAY,
+ SC_ON_PUSH_CART,
+ SC_RESIST_PROPERTY_WATER,
+ SC_RESIST_PROPERTY_GROUND,
+ SC_RESIST_PROPERTY_FIRE,
+ SC_RESIST_PROPERTY_WIND,
+ SC_CLIENT_ONLY_EQUIP_ARROW,
+ SC_MADOGEAR,
+ SC_POPECOOKIE,
+ SC_VITALIZE_POTION,
+ SC_SKF_MATK,
+ SC_SKF_ATK,
+ SC_SKF_ASPD,
+ SC_SKF_CAST,
+ SC_ALMIGHTY,
+#ifndef SC_MAX
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
+#endif
} sc_type;
/// 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,
- //SI_SG_MOON_WARM = 166, // The three show the exact same display: ultra red character (165, 166, 167)
- //SI_SG_STAR_WARM = 167,
- //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_ = 586,
- //SI_ = 587,
- //SI_ = 588,
- //SI_ = 589,
- //SI_ = 590,
- //SI_ = 591,
- //SI_ = 592,
- //SI_ = 593,
- //SI_ = 594,
- //SI_ = 595,
- 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_WIDEWEB = 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_S_HEALPOTION = 800,
- //SI_REUSE_LIMIT_S_HEAL_POTION = 801,
- //SI_PLAYTIME_STATISTICS = 802,
- //SI_GN_CHANGEMATERIAL_OPERATOR = 803,
- //SI_GN_MIX_COOKING_OPERATOR = 804,
- //SI_GN_MAKEBOMB_OPERATOR = 805,
- //SI_GN_S_PHARMACY_OPERATOR = 806,
- //SI_SO_EL_ANALYSIS_DISASSEMBLY_OPERATOR = 807,
- //SI_SO_EL_ANALYSIS_COMBINATION_OPERATOR = 808,
- //SI_NC_MAGICDECOY_OPERATOR = 809,
- //SI_GUILD_STORAGE = 810,
- //SI_GC_POISONINGWEAPON_OPERATOR = 811,
- //SI_WS_WEAPONREFINE_OPERATOR = 812,
- //SI_BS_REPAIRWEAPON_OPERATOR = 813,
- //SI_GET_MAILBOX = 814,
- //SI_JUMPINGCLAN = 815,
- //SI_JP_OTP = 816,
- //SI_HANDICAPTOLERANCE_LEVELGAP = 817,
- //SI_MTF_RANGEATK2 = 818,
- //SI_MTF_ASPD2 = 819,
- //SI_MTF_MATK2 = 820,
- //SI_SHOW_NPCHPBAR = 821,
- SI_FLOWERSMOKE = 822,
- SI_FSTONE = 823,
- //SI_DAILYSENDMAILCNT = 824,
- //SI_QSCARABA = 825,
- SI_LJOSALFAR = 826,
- //SI_PAD_READER_KNIGHT = 827,
- //SI_PAD_READER_CRUSADER = 828,
- //SI_PAD_READER_BLACKSMITH = 829,
- //SI_PAD_READER_ALCHEMIST = 830,
- //SI_PAD_READER_ASSASSIN = 831,
- //SI_PAD_READER_ROGUE = 832,
- //SI_PAD_READER_WIZARD = 833,
- //SI_PAD_READER_SAGE = 834,
- //SI_PAD_READER_PRIEST = 835,
- //SI_PAD_READER_MONK = 836,
- //SI_PAD_READER_HUNTER = 837,
- //SI_PAD_READER_BARD = 838,
- //SI_PAD_READER_DANCER = 839,
- //SI_PAD_READER_TAEKWON = 840,
- //SI_PAD_READER_NINJA = 841,
- //SI_PAD_READER_GUNSLINGER = 842,
- //SI_PAD_READER_SUPERNOVICE = 843,
- //SI_ESSENCE_OF_TIME = 844,
- //SI_MINIGAME_ROULETTE = 845,
- //SI_MINIGAME_GOLD_POINT = 846,
- //SI_MINIGAME_SILVER_POINT = 847,
- //SI_MINIGAME_BRONZE_POINT = 848,
- SI_HAPPINESS_STAR = 849,
-
- //SI_SUMMEREVENT01 = 850,
- //SI_SUMMEREVENT02 = 851,
- //SI_SUMMEREVENT03 = 852,
- //SI_SUMMEREVENT04 = 853,
- //SI_SUMMEREVENT05 = 854,
- //SI_MINIGAME_ROULETTE_BONUS_ITEM = 855,
- //SI_DRESS_UP = 856,
- SI_MAPLE_FALLS = 857,
- //SI_ALL_NIFLHEIM_RECALL = 858,
- //SI_ = 859,
- //SI_MTF_MARIONETTE = 860,
- //SI_MTF_LUDE = 861,
- //SI_MTF_CRUISER = 862,
- SI_MERMAID_LONGING = 863,
- SI_MAGICAL_FEATHER = 864,
- //SI_DRACULA_CARD = 865,
- //SI_ = 866,
- //SI_LIMIT_POWER_BOOSTER = 867,
- //SI_ = 868,
- //SI_ = 869,
- //SI_ = 870,
- //SI_ = 871,
- SI_TIME_ACCESSORY = 872,
- //SI_EP16_DEF = 873,
- //SI_NORMAL_ATKED_SP = 874,
- //SI_BODYSTATE_STONECURSE = 875,
- //SI_BODYSTATE_FREEZING = 876,
- //SI_BODYSTATE_STUN = 877,
- //SI_BODYSTATE_SLEEP = 878,
- //SI_BODYSTATE_UNDEAD = 879,
- //SI_BODYSTATE_STONECURSE_ING = 880,
- //SI_BODYSTATE_BURNNING = 881,
- //SI_BODYSTATE_IMPRISON = 882,
- //SI_HEALTHSTATE_POISON = 883,
- //SI_HEALTHSTATE_CURSE = 884,
- //SI_HEALTHSTATE_SILENCE = 885,
- //SI_HEALTHSTATE_CONFUSION = 886,
- //SI_HEALTHSTATE_BLIND = 887,
- //SI_HEALTHSTATE_ANGELUS = 888,
- //SI_HEALTHSTATE_BLOODING = 889,
- //SI_HEALTHSTATE_HEAVYPOISON = 890,
- //SI_HEALTHSTATE_FEAR = 891,
- //SI_CHERRY_BLOSSOM_CAKE = 892,
- //SI_SU_STOOP = 893,
- //SI_CATNIPPOWDER = 894,
- SI_BLOSSOM_FLUTTERING = 895,
- //SI_SV_ROOTTWIST = 896,
- //SI_ATTACK_PROPERTY_NOTHING = 897,
- //SI_ATTACK_PROPERTY_WATER = 898,
- //SI_ATTACK_PROPERTY_GROUND = 899,
-
- //SI_ATTACK_PROPERTY_FIRE = 900,
- //SI_ATTACK_PROPERTY_WIND = 901,
- //SI_ATTACK_PROPERTY_POISON = 902,
- //SI_ATTACK_PROPERTY_SAINT = 903,
- //SI_ATTACK_PROPERTY_DARKNESS = 904,
- //SI_ATTACK_PROPERTY_TELEKINESIS = 905,
- //SI_ATTACK_PROPERTY_UNDEAD = 906,
- //SI_RESIST_PROPERTY_NOTHING = 907,
- //SI_RESIST_PROPERTY_WATER = 908,
- //SI_RESIST_PROPERTY_GROUND = 909,
- //SI_RESIST_PROPERTY_FIRE = 910,
- //SI_RESIST_PROPERTY_WIND = 911,
- //SI_RESIST_PROPERTY_POISON = 912,
- //SI_RESIST_PROPERTY_SAINT = 913,
- //SI_RESIST_PROPERTY_DARKNESS = 914,
- //SI_RESIST_PROPERTY_TELEKINESIS = 915,
- //SI_RESIST_PROPERTY_UNDEAD = 916,
- //SI_BITESCAR = 917,
- //SI_ARCLOUSEDASH = 918,
- //SI_TUNAPARTY = 919,
- //SI_SHRIMP = 920,
- //SI_FRESHSHRIMP = 921,
- //SI_PERIOD_RECEIVEITEM = 922,
- //SI_PERIOD_PLUSEXP = 923,
- //SI_PERIOD_PLUSJOBEXP = 924,
- //SI_RUNEHELM = 925,
- //SI_HELM_VERKANA = 926,
- //SI_HELM_RHYDO = 927,
- //SI_HELM_TURISUS = 928,
- //SI_HELM_HAGALAS = 929,
- //SI_HELM_ISIA = 930,
- //SI_HELM_ASIR = 931,
- //SI_HELM_URJ = 932,
- //SI_SUHIDE = 933,
- //SI_ = 934,
- //SI_DORAM_BUF_01 = 935,
- //SI_DORAM_BUF_02 = 936,
- //SI_SPRITEMABLE = 937,
- //SI_EP16_2_BUFF_SS = 963,
- //SI_EP16_2_BUFF_SC = 964,
- //SI_EP16_2_BUFF_AC = 965,
-
- SI_MAX,
+ SI_BLANK = -1,
};
// JOINTBEAT stackable ailments
@@ -1811,7 +886,7 @@ enum e_joint_break
/**
* Mob mode definitions. [Skotlex]
*
- * @see doc/mob_db_mode_list.txt for a description of each mode.
+ * @see doc/mob_db_mode_list.md for a description of each mode.
*/
enum e_mode
{
@@ -1841,7 +916,7 @@ enum e_mode
//who were not on your field of sight when it happened)
//opt1: Non stackable status changes.
-enum {
+enum e_opt1 {
OPT1_STONE = 1, //Petrified
OPT1_FREEZE,
OPT1_STUN,
@@ -1854,7 +929,7 @@ enum {
};
//opt2: Stackable status changes.
-enum {
+enum e_opt2 {
OPT2_POISON = 0x0001,
OPT2_CURSE = 0x0002,
OPT2_SILENCE = 0x0004,
@@ -1867,7 +942,7 @@ enum {
};
//opt3: (SHOW_EFST_*)
-enum {
+enum e_opt3 {
OPT3_NORMAL = 0x00000000,
OPT3_QUICKEN = 0x00000001,
OPT3_OVERTHRUST = 0x00000002,
@@ -1967,29 +1042,28 @@ enum e_status_calc_opt {
//Required because players have two of these, one in status_data
//and another for their left hand weapon.
typedef struct weapon_atk {
- unsigned short atk, atk2;
+ unsigned int atk, atk2;
unsigned short range;
unsigned char ele;
#ifdef RENEWAL
- unsigned short matk;
+ unsigned int matk;
unsigned char wlv;
#endif
} weapon_atk;
//For holding basic status (which can be modified by status changes)
struct status_data {
- unsigned int
+ uint32
hp, sp, // see status_cpy before adding members before hp and sp
max_hp, max_sp;
- unsigned short
- str, agi, vit, int_, dex, luk,
+ uint16 str, agi, vit, int_, dex, luk;
+ uint32
batk,
matk_min, matk_max,
speed,
- amotion, adelay, dmotion;
- uint32 mode;
- short
- hit, flee, cri, flee2,
+ amotion, adelay, dmotion,
+ mode;
+ int32 hit, flee, cri, flee2,
def2, mdef2,
#ifdef RENEWAL_ASPD
aspd_rate2,
@@ -2061,6 +1135,7 @@ struct sc_display_entry {
struct status_change_entry {
int timer;
+ int total_tick;
int val1,val2,val3,val4;
bool infinite_duration;
};
@@ -2150,28 +1225,21 @@ struct status_change {
#define status_calc_elemental(ed, opt) (status->calc_bl_(&(ed)->bl, SCB_ALL, (opt)))
#define status_calc_npc(nd, opt) (status->calc_bl_(&(nd)->bl, SCB_ALL, (opt)))
-// bonus values and upgrade chances for refining equipment
-struct s_refine_info {
- int chance[MAX_REFINE]; // success chance
- int bonus[MAX_REFINE]; // cumulative fixed bonus damage
- int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage
-};
-
struct s_status_dbs {
BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */
int max_weight_base[CLASS_COUNT];
int HP_table[CLASS_COUNT][MAX_LEVEL + 1];
int SP_table[CLASS_COUNT][MAX_LEVEL + 1];
int aspd_base[CLASS_COUNT][MAX_SINGLE_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)
+ sc_type Skill2SCTable[MAX_SKILL_DB]; // skill -> status
+ struct {
+ int id;
+ int relevant_bl_types;
+ } IconChangeTable[SC_MAX];
unsigned int ChangeFlagTable[SC_MAX]; // status -> flags
int SkillChangeTable[SC_MAX]; // status -> skill
- int RelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets)
bool DisplayType[SC_MAX];
/* */
- struct s_refine_info refine_info[REFINE_TYPE_MAX];
- /* */
int atkmods[3][MAX_SINGLE_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt)
char job_bonus[CLASS_COUNT][MAX_LEVEL];
sc_conf_type sc_conf[SC_MAX];
@@ -2188,6 +1256,7 @@ struct status_interface {
/* vars */
int current_equip_item_index;
int current_equip_card_id;
+ int current_equip_option_index;
struct s_status_dbs *dbs;
@@ -2199,21 +1268,21 @@ struct status_interface {
int (*init) (bool minimal);
void (*final) (void);
/* funcs */
- int (*get_refine_chance) (enum refine_type wlv, int refine);
// for looking up associated data
sc_type (*skill2sc) (int skill_id);
int (*sc2skill) (sc_type sc);
unsigned int (*sc2scb_flag) (sc_type sc);
- int (*type2relevant_bl_types) (int type);
+ int (*get_sc_relevant_bl_types) (sc_type type);
int (*get_sc_type) (sc_type idx);
+ int (*get_sc_icon) (sc_type type);
int (*damage) (struct block_list *src,struct block_list *target,int64 hp,int64 sp, int walkdelay, int flag);
//Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
int (*charge) (struct block_list* bl, int64 hp, int64 sp);
int (*percent_change) (struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
//Used to set the hp/sp of an object to an absolute value (can't kill)
- int (*set_hp) (struct block_list *bl, unsigned int hp, int flag);
- int (*set_sp) (struct block_list *bl, unsigned int sp, int flag);
- int (*heal) (struct block_list *bl,int64 hp,int64 sp, int flag);
+ int (*set_hp) (struct block_list *bl, unsigned int hp, enum status_heal_flag flag);
+ int (*set_sp) (struct block_list *bl, unsigned int sp, enum status_heal_flag flag);
+ int (*heal) (struct block_list *bl,int64 hp,int64 sp, enum status_heal_flag flag);
int (*revive) (struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
int (*fixed_revive) (struct block_list *bl, unsigned int per_hp, unsigned int per_sp);
struct regen_data * (*get_regen_data) (struct block_list *bl);
@@ -2238,7 +1307,16 @@ struct status_interface {
int (*isimmune) (struct block_list *bl);
int (*get_sc_def) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
int (*change_start) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
+ int (*change_start_sub) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int total_tick, int flag);
int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
+ bool (*is_immune_to_status) (struct status_change* sc, enum sc_type type);
+ bool (*is_boss_resist_sc) (enum sc_type type);
+ bool (*end_sc_before_start) (struct block_list *bl, struct status_data *st, struct status_change* sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4);
+ void (*change_start_stop_action) (struct block_list *bl, enum sc_type type);
+ int (*change_start_set_option) (struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4);
+ int (*get_val_flag) (enum sc_type type);
+ void (*change_start_display) (struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4);
+ bool (*change_start_unknown_sc) (struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag);
int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data);
int (*change_timer) (int tid, int64 tick, int id, intptr_t data);
int (*change_timer_sub) (struct block_list* bl, va_list ap);
@@ -2249,6 +1327,7 @@ struct status_interface {
int (*calc_pet_) (struct pet_data* pd, enum e_status_calc_opt opt);
int (*calc_pc_) (struct map_session_data* sd, enum e_status_calc_opt opt);
void (*calc_pc_additional) (struct map_session_data* sd, enum e_status_calc_opt opt);
+ void (*calc_pc_recover_hp) (struct map_session_data* sd, struct status_data *bstatus);
int (*calc_homunculus_) (struct homun_data *hd, enum e_status_calc_opt opt);
int (*calc_mercenary_) (struct mercenary_data *md, enum e_status_calc_opt opt);
int (*calc_elemental_) (struct elemental_data *ed, enum e_status_calc_opt opt);
@@ -2262,8 +1341,8 @@ struct status_interface {
short (*calc_def2) (struct block_list *bl, struct status_change *sc, int def2, bool viewable);
defType (*calc_mdef) (struct block_list *bl, struct status_change *sc, int mdef, bool viewable);
short (*calc_mdef2) (struct block_list *bl, struct status_change *sc, int mdef2, bool viewable);
- unsigned short (*calc_batk)(struct block_list *bl, struct status_change *sc, int batk, bool viewable);
- unsigned short(*base_matk) (struct block_list *bl, const struct status_data *st, int level);
+ int (*calc_batk)(struct block_list *bl, struct status_change *sc, int batk, bool viewable);
+ int (*base_matk) (struct block_list *bl, const struct status_data *st, int level);
int (*get_weapon_atk) (struct block_list *src, struct weapon_atk *watk, int flag);
int (*get_total_mdef) (struct block_list *src);
int (*get_total_def) (struct block_list *src);
@@ -2274,9 +1353,11 @@ struct status_interface {
void (*initChangeTables) (void);
void (*initDummyData) (void);
int (*base_amotion_pc) (struct map_session_data *sd, struct status_data *st);
- unsigned short (*base_atk) (const struct block_list *bl, const struct status_data *st);
+ int (*base_atk) (const struct block_list *bl, const struct status_data *st);
unsigned int (*get_base_maxhp) (const struct map_session_data *sd, const struct status_data *st);
unsigned int (*get_base_maxsp) (const struct map_session_data *sd, const struct status_data *st);
+ unsigned int (*get_restart_hp) (const struct map_session_data *sd, const struct status_data *st);
+ unsigned int (*get_restart_sp) (const struct map_session_data *sd, const struct status_data *st);
int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt);
unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str);
unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi);
@@ -2284,12 +1365,12 @@ struct status_interface {
unsigned short (*calc_int) (struct block_list *bl, struct status_change *sc, int int_);
unsigned short (*calc_dex) (struct block_list *bl, struct status_change *sc, int dex);
unsigned short (*calc_luk) (struct block_list *bl, struct status_change *sc, int luk);
- unsigned short (*calc_watk) (struct block_list *bl, struct status_change *sc, int watk, bool viewable);
- unsigned short (*calc_matk) (struct block_list *bl, struct status_change *sc, int matk, bool viewable);
- signed short (*calc_hit) (struct block_list *bl, struct status_change *sc, int hit, bool viewable);
- signed short (*calc_critical) (struct block_list *bl, struct status_change *sc, int critical, bool viewable);
- signed short (*calc_flee) (struct block_list *bl, struct status_change *sc, int flee, bool viewable);
- signed short (*calc_flee2) (struct block_list *bl, struct status_change *sc, int flee2, bool viewable);
+ int (*calc_watk) (struct block_list *bl, struct status_change *sc, int watk, bool viewable);
+ int (*calc_matk) (struct block_list *bl, struct status_change *sc, int matk, bool viewable);
+ signed int (*calc_hit) (struct block_list *bl, struct status_change *sc, int hit, bool viewable);
+ signed int (*calc_critical) (struct block_list *bl, struct status_change *sc, int critical, bool viewable);
+ signed int (*calc_flee) (struct block_list *bl, struct status_change *sc, int flee, bool viewable);
+ signed int (*calc_flee2) (struct block_list *bl, struct status_change *sc, int flee2, bool viewable);
unsigned short (*calc_speed) (struct block_list *bl, struct status_change *sc, int speed);
short (*calc_aspd_rate) (struct block_list *bl, struct status_change *sc, int aspd_rate);
unsigned short (*calc_dmotion) (struct block_list *bl, struct status_change *sc, int dmotion);
@@ -2300,7 +1381,7 @@ struct status_interface {
unsigned char (*calc_element) (struct block_list *bl, struct status_change *sc, int element);
unsigned char (*calc_element_lv) (struct block_list *bl, struct status_change *sc, int lv);
uint32 (*calc_mode) (const struct block_list *bl, const struct status_change *sc, uint32 mode);
- unsigned short (*calc_ematk) (struct block_list *bl, struct status_change *sc, int matk);
+ int (*calc_ematk) (struct block_list *bl, struct status_change *sc, int matk);
void (*calc_bl_main) (struct block_list *bl, int flag);
void (*display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3);
void (*display_remove) (struct map_session_data *sd, enum sc_type type);
@@ -2308,11 +1389,16 @@ struct status_interface {
int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data);
bool (*readdb_job2) (char *fields[], int columns, int current);
bool (*readdb_sizefix) (char *fields[], int columns, int current);
- int (*readdb_refine_libconfig) (const char *filename);
- int (*readdb_refine_libconfig_sub) (struct config_setting_t *r, const char *name, const char *source);
- bool (*readdb_scconfig) (char *fields[], int columns, int current);
+ bool (*read_scdb_libconfig) (void);
+ bool (*read_scdb_libconfig_sub) (struct config_setting_t *it, int idx, const char *source);
+ bool (*read_scdb_libconfig_sub_flag) (struct config_setting_t *it, int type, const char *source);
+ bool (*read_scdb_libconfig_sub_flag_additional) (struct config_setting_t *it, int type, const char *source);
void (*read_job_db) (void);
void (*read_job_db_sub) (int idx, const char *name, struct config_setting_t *jdb);
+ void (*set_sc) (uint16 skill_id, sc_type sc, unsigned int flag);
+ void (*copy) (struct status_data *a, const struct status_data *b);
+ int (*base_matk_min) (const struct status_data *st);
+ int (*base_matk_max) (const struct status_data *st);
};
#ifdef HERCULES_CORE
diff --git a/src/map/storage.c b/src/map/storage.c
index 91b37eb19..b83bd8489 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,8 +41,8 @@
#include <stdlib.h>
#include <string.h>
-struct storage_interface storage_s;
-struct guild_storage_interface gstorage_s;
+static struct storage_interface storage_s;
+static struct guild_storage_interface gstorage_s;
struct storage_interface *storage;
struct guild_storage_interface *gstorage;
@@ -50,7 +50,7 @@ struct guild_storage_interface *gstorage;
/*==========================================
* Sort items in the warehouse
*------------------------------------------*/
-int storage_comp_item(const void *i1_, const void *i2_)
+static int storage_comp_item(const void *i1_, const void *i2_)
{
const struct item *i1 = i1_;
const struct item *i2 = i2_;
@@ -65,7 +65,7 @@ int storage_comp_item(const void *i1_, const void *i2_)
}
//Sort item by storage_comp_item (nameid)
-void storage_sortitem(struct item* items, unsigned int size)
+static void storage_sortitem(struct item *items, unsigned int size)
{
nullpo_retv(items);
@@ -79,9 +79,10 @@ void storage_sortitem(struct item* items, unsigned int size)
* Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
* @see DBApply
*/
-int storage_reconnect_sub(union DBKey key, struct DBData *data, va_list ap)
+static int storage_reconnect_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild_storage *stor = DB->data2ptr(data);
+ nullpo_ret(stor);
if (stor->dirty && stor->storage_status == 0) //Save closed storages.
gstorage->save(0, stor->guild_id,0);
@@ -89,7 +90,8 @@ int storage_reconnect_sub(union DBKey key, struct DBData *data, va_list ap)
}
//Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex]
-void do_reconnect_storage(void) {
+static void do_reconnect_storage(void)
+{
gstorage->db->foreach(gstorage->db, storage->reconnect_sub);
}
@@ -98,30 +100,39 @@ void do_reconnect_storage(void) {
* 0 - success
* 1 - fail
*------------------------------------------*/
-int storage_storageopen(struct map_session_data *sd)
+static int storage_storageopen(struct map_session_data *sd)
{
nullpo_ret(sd);
if (sd->state.storage_flag != STORAGE_FLAG_CLOSED)
return 1; //Already open?
+ if (sd->storage.received == false) {
+ clif->message(sd->fd, msg_sd(sd, 27)); // Storage has not been loaded yet.
+ return 1;
+ }
+
if( !pc_can_give_items(sd) ) {
//check is this GM level is allowed to put items to storage
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
return 1;
}
sd->state.storage_flag = STORAGE_FLAG_NORMAL;
- storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
- clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+
+ if (sd->storage.aggregate > 0) {
+ storage->sortitem(VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item));
+ }
+ clif->storageList(sd, VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item));
+
+ clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE);
return 0;
}
/* helper function
* checking if 2 item structure are identique
*/
-int compare_item(struct item *a, struct item *b)
+static int compare_item(struct item *a, struct item *b)
{
if( a->nameid == b->nameid &&
a->identify == b->identify &&
@@ -131,9 +142,12 @@ int compare_item(struct item *a, struct item *b)
a->bound == b->bound &&
a->unique_id == b->unique_id)
{
- int i;
- for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++);
- return (i == MAX_SLOTS);
+ int i = 0, k = 0;
+ ARR_FIND(0, MAX_SLOTS, i, a->card[i] != b->card[i]);
+ ARR_FIND(0, MAX_ITEM_OPTIONS, k, a->option[k].index != b->option[k].index || a->option[k].value != b->option[k].value);
+
+ if (i == MAX_SLOTS && k == MAX_ITEM_OPTIONS)
+ return 1;
}
return 0;
}
@@ -141,59 +155,82 @@ int compare_item(struct item *a, struct item *b)
/*==========================================
* Internal add-item function.
*------------------------------------------*/
-int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) {
- struct storage_data* stor = &sd->status.storage;
- struct item_data *data;
+static int storage_additem(struct map_session_data *sd, struct item *item_data, int amount)
+{
+ struct item_data *data = NULL;
+ struct item *it = NULL;
int i;
- if( item_data->nameid <= 0 || amount <= 0 )
- return 1;
+ nullpo_retr(1, sd);
+ Assert_retr(1, sd->storage.received == true);
+
+ nullpo_retr(1, item_data);
+ Assert_retr(1, item_data->nameid > 0);
+
+ Assert_retr(1, amount > 0);
data = itemdb->search(item_data->nameid);
- if( data->stack.storage && amount > data->stack.amount )
- {// item stack limitation
+ if (data->stack.storage && amount > data->stack.amount) // item stack limitation
return 1;
- }
if (!itemdb_canstore(item_data, pc_get_group_level(sd))) {
//Check if item is storable. [Skotlex]
- clif->message (sd->fd, msg_sd(sd,264));
+ clif->message (sd->fd, msg_sd(sd, 264)); // This item cannot be stored.
return 1;
}
- if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) {
- clif->message(sd->fd, msg_sd(sd,294));
+ if (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd)) {
+ clif->message(sd->fd, msg_sd(sd, 294)); // This bound item cannot be stored there.
return 1;
}
- if( itemdb->isstackable2(data) )
- {//Stackable
- for( i = 0; i < MAX_STORAGE; i++ )
- {
- if( compare_item(&stor->items[i], item_data) )
- {// existing items found, stack them
- if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) )
+ if (itemdb->isstackable2(data)) {//Stackable
+ for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) {
+ it = &VECTOR_INDEX(sd->storage.item, i);
+
+ if (it->nameid == 0)
+ continue;
+
+ if (compare_item(it, item_data)) { // existing items found, stack them
+ if (amount > MAX_AMOUNT - it->amount || (data->stack.storage && amount > data->stack.amount - it->amount))
return 1;
- stor->items[i].amount += amount;
- clif->storageitemadded(sd,&stor->items[i],i,amount);
+ it->amount += amount;
+
+ clif->storageitemadded(sd, it, i, amount);
+
+ sd->storage.save = true; // set a save flag.
+
return 0;
}
}
}
- // find free slot
- ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 );
- if( i >= MAX_STORAGE )
+ // Check if storage exceeds limit.
+ if (sd->storage.aggregate >= MAX_STORAGE)
return 1;
- // add item to slot
- memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
- stor->storage_amount++;
- stor->items[i].amount = amount;
- clif->storageitemadded(sd,&stor->items[i],i,amount);
- clif->updatestorageamount(sd, stor->storage_amount, MAX_STORAGE);
+ ARR_FIND(0, VECTOR_LENGTH(sd->storage.item), i, VECTOR_INDEX(sd->storage.item, i).nameid == 0);
+
+ if (i == VECTOR_LENGTH(sd->storage.item)) {
+ VECTOR_ENSURE(sd->storage.item, 1, 1);
+ VECTOR_PUSH(sd->storage.item, *item_data);
+ it = &VECTOR_LAST(sd->storage.item);
+ } else {
+ it = &VECTOR_INDEX(sd->storage.item, i);
+ *it = *item_data;
+ }
+
+ it->amount = amount;
+
+ sd->storage.aggregate++;
+
+ clif->storageitemadded(sd, it, i, amount);
+
+ clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE);
+
+ sd->storage.save = true; // set a save flag.
return 0;
}
@@ -201,21 +238,34 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
/*==========================================
* Internal del-item function
*------------------------------------------*/
-int storage_delitem(struct map_session_data* sd, int n, int amount)
+static int storage_delitem(struct map_session_data *sd, int n, int amount)
{
- if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount )
- return 1;
+ struct item *it = NULL;
- sd->status.storage.items[n].amount -= amount;
- if( sd->status.storage.items[n].amount == 0 )
- {
- memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0]));
- sd->status.storage.storage_amount--;
- if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
- clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+ nullpo_retr(1, sd);
+
+ Assert_retr(1, sd->storage.received == true);
+
+ Assert_retr(1, n >= 0 && n < VECTOR_LENGTH(sd->storage.item));
+
+ it = &VECTOR_INDEX(sd->storage.item, n);
+
+ Assert_retr(1, amount <= it->amount);
+
+ Assert_retr(1, it->nameid > 0);
+
+ it->amount -= amount;
+
+ if (it->amount == 0) {
+ memset(it, 0, sizeof(struct item));
+ clif->updatestorageamount(sd, --sd->storage.aggregate, MAX_STORAGE);
}
- if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
- clif->storageitemremoved(sd,n,amount);
+
+ sd->storage.save = true;
+
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
+ clif->storageitemremoved(sd, n, amount);
+
return 0;
}
@@ -226,25 +276,28 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageadd(struct map_session_data* sd, int index, int amount) {
+static int storage_add_from_inventory(struct map_session_data *sd, int index, int amount)
+{
nullpo_ret(sd);
- if( sd->status.storage.storage_amount > MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (sd->storage.aggregate > MAX_STORAGE)
return 0; // storage full
- if( index < 0 || index >= MAX_INVENTORY )
+ if (index < 0 || index >= sd->status.inventorySize)
return 0;
- if( sd->status.inventory[index].nameid <= 0 )
+ if (sd->status.inventory[index].nameid <= 0)
return 0; // No item on that spot
- if( amount < 1 || amount > sd->status.inventory[index].amount )
+ if (amount < 1 || amount > sd->status.inventory[index].amount)
return 0;
- if( storage->additem(sd,&sd->status.inventory[index],amount) == 0 )
+ if (storage->additem(sd, &sd->status.inventory[index], amount) == 0)
pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_STORAGE);
else
- clif->dropitem(sd, index, 0);
+ clif->item_movefailed(sd, index);
return 1;
}
@@ -256,23 +309,30 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) {
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageget(struct map_session_data* sd, int index, int amount)
+static int storage_add_to_inventory(struct map_session_data *sd, int index, int amount)
{
int flag;
+ struct item *it = NULL;
+
+ nullpo_ret(sd);
+
+ Assert_ret(sd->storage.received == true);
- if( index < 0 || index >= MAX_STORAGE )
+ if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item))
return 0;
- if( sd->status.storage.items[index].nameid <= 0 )
+ it = &VECTOR_INDEX(sd->storage.item, index);
+
+ if (it->nameid <= 0)
return 0; //Nothing there
- if( amount < 1 || amount > sd->status.storage.items[index].amount )
+ if (amount < 1 || amount > it->amount)
return 0;
- if( (flag = pc->additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
- storage->delitem(sd,index,amount);
+ if ((flag = pc->additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0)
+ storage->delitem(sd, index, amount);
else
- clif->additem(sd,0,0,flag);
+ clif->additem(sd, 0, 0, flag);
return 1;
}
@@ -284,23 +344,25 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount)
+static int storage_storageaddfromcart(struct map_session_data *sd, int index, int amount)
{
nullpo_ret(sd);
- if( sd->status.storage.storage_amount > MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (sd->storage.aggregate > MAX_STORAGE)
return 0; // storage full / storage closed
- if( index < 0 || index >= MAX_CART )
+ if (index < 0 || index >= MAX_CART)
return 0;
if( sd->status.cart[index].nameid <= 0 )
return 0; //No item there.
- if( amount < 1 || amount > sd->status.cart[index].amount )
+ if (amount < 1 || amount > sd->status.cart[index].amount)
return 0;
- if( storage->additem(sd,&sd->status.cart[index],amount) == 0 )
+ if (storage->additem(sd,&sd->status.cart[index],amount) == 0)
pc->cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE);
return 1;
@@ -313,24 +375,33 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storagegettocart(struct map_session_data* sd, int index, int amount) {
+static int storage_storagegettocart(struct map_session_data *sd, int index, int amount)
+{
int flag = 0;
+ struct item *it = NULL;
+
nullpo_ret(sd);
- if( index < 0 || index >= MAX_STORAGE )
+ Assert_ret(sd->storage.received == true);
+
+ if (index < 0 || index >= VECTOR_LENGTH(sd->storage.item))
return 0;
- if( sd->status.storage.items[index].nameid <= 0 )
+ it = &VECTOR_INDEX(sd->storage.item, index);
+
+ if (it->nameid <= 0)
return 0; //Nothing there.
- if( amount < 1 || amount > sd->status.storage.items[index].amount )
+ if (amount < 1 || amount > it->amount)
return 0;
- if( (flag = pc->cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
- storage->delitem(sd,index,amount);
+ if ((flag = pc->cart_additem(sd, it, amount, LOG_TYPE_STORAGE)) == 0)
+ storage->delitem(sd, index, amount);
else {
+ // probably this line is useless? it remove inventory lock but not storage [4144]
clif->dropitem(sd, index,0);
- clif->cart_additem_ack(sd,flag == 1?0x0:0x1);
+
+ clif->cart_additem_ack(sd, flag == 1?0x0:0x1);
}
return 1;
@@ -340,13 +411,28 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
/*==========================================
* Modified By Valaris to save upon closing [massdriller]
*------------------------------------------*/
-void storage_storageclose(struct map_session_data* sd) {
+static void storage_storageclose(struct map_session_data *sd)
+{
+ int i = 0;
+
nullpo_retv(sd);
+ Assert_retv(sd->storage.received == true);
+
clif->storageclose(sd);
- if( map->save_settings&4 )
- chrif->save(sd,0); //Invokes the storage saving as well.
+ if (map->save_settings & 4)
+ chrif->save(sd, 0); //Invokes the storage saving as well.
+
+ /* Erase deleted account storage items from memory
+ * and resize the vector. */
+ while (i < VECTOR_LENGTH(sd->storage.item)) {
+ if (VECTOR_INDEX(sd->storage.item, i).nameid == 0) {
+ VECTOR_ERASE(sd->storage.item, i);
+ } else {
+ i++;
+ }
+ }
sd->state.storage_flag = STORAGE_FLAG_CLOSED;
}
@@ -354,7 +440,8 @@ void storage_storageclose(struct map_session_data* sd) {
/*==========================================
* When quitting the game.
*------------------------------------------*/
-void storage_storage_quit(struct map_session_data* sd, int flag) {
+static void storage_storage_quit(struct map_session_data *sd, int flag)
+{
nullpo_retv(sd);
if (map->save_settings&4)
@@ -366,7 +453,7 @@ void storage_storage_quit(struct map_session_data* sd, int flag) {
/**
* @see DBCreateData
*/
-struct DBData create_guildstorage(union DBKey key, va_list args)
+static struct DBData create_guildstorage(union DBKey key, va_list args)
{
struct guild_storage *gs = NULL;
gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1);
@@ -374,7 +461,7 @@ struct DBData create_guildstorage(union DBKey key, va_list args)
return DB->ptr2data(gs);
}
-struct guild_storage *guild2storage_ensure(int guild_id)
+static struct guild_storage *guild2storage_ensure(int guild_id)
{
struct guild_storage *gs = NULL;
if(guild->search(guild_id) != NULL)
@@ -382,19 +469,20 @@ struct guild_storage *guild2storage_ensure(int guild_id)
return gs;
}
-int guild_storage_delete(int guild_id) {
+static int guild_storage_delete(int guild_id)
+{
idb_remove(gstorage->db,guild_id);
return 0;
}
/*==========================================
-* Attempt to open guild storage for sd
-* return
-* 0 : success (open or req to create a new one)
-* 1 : fail
-* 2 : no guild for sd
+ * Attempt to open guild storage for sd
+ * return
+ * 0 : success (open or req to create a new one)
+ * 1 : fail
+ * 2 : no guild for sd
*------------------------------------------*/
-int storage_guild_storageopen(struct map_session_data* sd)
+static int storage_guild_storageopen(struct map_session_data *sd)
{
struct guild_storage *gstor;
@@ -407,7 +495,7 @@ int storage_guild_storageopen(struct map_session_data* sd)
return 1; //Can't open both storages at a time.
if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus]
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
return 1;
}
@@ -424,18 +512,18 @@ int storage_guild_storageopen(struct map_session_data* sd)
gstor->storage_status = 1;
sd->state.storage_flag = STORAGE_FLAG_GUILD;
storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items));
- clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items));
+ clif->guildStorageList(sd, gstor->items, ARRAYLENGTH(gstor->items));
clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE);
return 0;
}
/*==========================================
-* Attempt to add an item in guild storage, then refresh it
-* return
-* 0 : success
-* 1 : fail
+ * Attempt to add an item in guild storage, then refresh it
+ * return
+ * 0 : success
+ * 1 : fail
*------------------------------------------*/
-int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
+static int guild_storage_additem(struct map_session_data *sd, struct guild_storage *stor, struct item *item_data, int amount)
{
struct item_data *data;
int i;
@@ -456,12 +544,12 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
if (!itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time) {
//Check if item is storable. [Skotlex]
- clif->message (sd->fd, msg_sd(sd,264));
+ clif->message (sd->fd, msg_sd(sd,264)); // This item cannot be stored.
return 1;
}
if( item_data->bound && item_data->bound != IBT_GUILD && !pc_can_give_bound_items(sd) ) {
- clif->message(sd->fd, msg_sd(sd,294));
+ clif->message(sd->fd, msg_sd(sd,294)); // This bound item cannot be stored there.
return 1;
}
@@ -493,16 +581,17 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
}
/*==========================================
-* Attempt to delete an item in guild storage, then refresh it
-* return
-* 0 : success
-* 1 : fail
+ * Attempt to delete an item in guild storage, then refresh it
+ * return
+ * 0 : success
+ * 1 : fail
*------------------------------------------*/
-int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount)
+static int guild_storage_delitem(struct map_session_data *sd, struct guild_storage *stor, int n, int amount)
{
nullpo_retr(1, sd);
nullpo_retr(1, stor);
+ Assert_retr(1, n >= 0 && n < MAX_GUILD_STORAGE);
if(stor->items[n].nameid==0 || stor->items[n].amount<amount)
return 1;
@@ -518,13 +607,13 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto
}
/*==========================================
-* Attempt to add an item in guild storage from inventory, then refresh it
-* @index : inventory idx
-* return
-* 0 : fail
-* 1 : succes
+ * Attempt to add an item in guild storage from inventory, then refresh it
+ * @index : inventory idx
+ * return
+ * 0 : fail
+ * 1 : succes
*------------------------------------------*/
-int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
+static int storage_guild_storageadd(struct map_session_data *sd, int index, int amount)
{
struct guild_storage *stor;
@@ -534,7 +623,7 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE )
return 0;
- if( index<0 || index>=MAX_INVENTORY )
+ if (index < 0 || index >= sd->status.inventorySize)
return 0;
if( sd->status.inventory[index].nameid <= 0 )
@@ -551,19 +640,19 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
if( gstorage->additem(sd,stor,&sd->status.inventory[index],amount) == 0 )
pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_GSTORAGE);
else
- clif->dropitem(sd, index, 0);
+ clif->item_movefailed(sd, index);
return 1;
}
/*==========================================
-* Attempt to retrieve an item from guild storage to inventory, then refresh it
-* @index : storage idx
-* return
-* 0 : fail
-* 1 : success
+ * Attempt to retrieve an item from guild storage to inventory, then refresh it
+ * @index : storage idx
+ * return
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
-int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
+static int storage_guild_storageget(struct map_session_data *sd, int index, int amount)
{
struct guild_storage *stor;
int flag;
@@ -598,13 +687,13 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
}
/*==========================================
-* Attempt to add an item in guild storage from cart, then refresh it
-* @index : cart inventory idx
-* return
-* 0 : fail
-* 1 : success
+ * Attempt to add an item in guild storage from cart, then refresh it
+ * @index : cart inventory idx
+ * return
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
-int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount)
+static int storage_guild_storageaddfromcart(struct map_session_data *sd, int index, int amount)
{
struct guild_storage *stor;
@@ -630,13 +719,13 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
}
/*==========================================
-* Attempt to retrieve an item from guild storage to cart, then refresh it
-* @index : storage idx
-* return
-* 0 : fail
-* 1 : success
+ * Attempt to retrieve an item from guild storage to cart, then refresh it
+ * @index : storage idx
+ * return
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
-int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount)
+static int storage_guild_storagegettocart(struct map_session_data *sd, int index, int amount)
{
struct guild_storage *stor;
@@ -662,12 +751,12 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
}
/*==========================================
-* Request to save guild storage
-* return
-* 0 : fail (no storage)
-* 1 : success
+ * Request to save guild storage
+ * return
+ * 0 : fail (no storage)
+ * 1 : success
*------------------------------------------*/
-int storage_guild_storagesave(int account_id, int guild_id, int flag)
+static int storage_guild_storagesave(int account_id, int guild_id, int flag)
{
struct guild_storage *stor = idb_get(gstorage->db,guild_id);
@@ -683,12 +772,12 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag)
}
/*==========================================
-* ACK save of guild storage
-* return
-* 0 : fail (no storage)
-* 1 : success
+ * ACK save of guild storage
+ * return
+ * 0 : fail (no storage)
+ * 1 : success
*------------------------------------------*/
-int storage_guild_storagesaved(int guild_id)
+static int storage_guild_storagesaved(int guild_id)
{
struct guild_storage *stor;
@@ -703,7 +792,8 @@ int storage_guild_storagesaved(int guild_id)
}
//Close storage for sd and save it
-int storage_guild_storageclose(struct map_session_data* sd) {
+static int storage_guild_storageclose(struct map_session_data *sd)
+{
struct guild_storage *stor;
nullpo_ret(sd);
@@ -722,7 +812,8 @@ int storage_guild_storageclose(struct map_session_data* sd) {
return 0;
}
-int storage_guild_storage_quit(struct map_session_data* sd, int flag) {
+static int storage_guild_storage_quit(struct map_session_data *sd, int flag)
+{
struct guild_storage *stor;
nullpo_ret(sd);
@@ -749,15 +840,21 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) {
return 0;
}
-void do_init_gstorage(bool minimal) {
+
+static void do_init_gstorage(bool minimal)
+{
if (minimal)
return;
gstorage->db = idb_alloc(DB_OPT_RELEASE_DATA);
}
-void do_final_gstorage(void) {
+
+static void do_final_gstorage(void)
+{
db_destroy(gstorage->db);
}
-void storage_defaults(void) {
+
+void storage_defaults(void)
+{
storage = &storage_s;
/* */
@@ -765,8 +862,8 @@ void storage_defaults(void) {
/* */
storage->delitem = storage_delitem;
storage->open = storage_storageopen;
- storage->add = storage_storageadd;
- storage->get = storage_storageget;
+ storage->add = storage_add_from_inventory;
+ storage->get = storage_add_to_inventory;
storage->additem = storage_additem;
storage->addfromcart = storage_storageaddfromcart;
storage->gettocart = storage_storagegettocart;
@@ -776,7 +873,9 @@ void storage_defaults(void) {
storage->sortitem = storage_sortitem;
storage->reconnect_sub = storage_reconnect_sub;
}
-void gstorage_defaults(void) {
+
+void gstorage_defaults(void)
+{
gstorage = &gstorage_s;
/* */
diff --git a/src/map/storage.h b/src/map/storage.h
index 94512c456..7a342efb2 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/stylist.c b/src/map/stylist.c
new file mode 100644
index 000000000..8b4180971
--- /dev/null
+++ b/src/map/stylist.c
@@ -0,0 +1,229 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2018-2020 Hercules Dev Team
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#define HERCULES_CORE
+
+#include "map/stylist.h"
+
+#include "common/conf.h"
+#include "common/db.h"
+#include "common/memmgr.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+
+#include "map/clif.h"
+#include "map/intif.h"
+#include "map/itemdb.h"
+#include "map/pc.h"
+#include "map/script.h"
+
+static struct stylist_interface stylist_s;
+struct stylist_interface *stylist;
+
+static bool stylist_read_db_libconfig(void)
+{
+ struct config_t stylist_conf;
+ struct config_setting_t *stylist_db = NULL, *it = NULL;
+ char config_filename[256];
+ libconfig->format_db_path("stylist_db.conf", config_filename, sizeof(config_filename));
+ int i = 0;
+
+ if (!libconfig->load_file(&stylist_conf, config_filename))
+ return false;
+
+ if ((stylist_db = libconfig->setting_get_member(stylist_conf.root, "stylist_db")) == NULL) {
+ ShowError("can't read %s\n", config_filename);
+ return false;
+ }
+
+ stylist->vector_clear();
+
+ while ((it = libconfig->setting_get_elem(stylist_db, i++))) {
+ stylist->read_db_libconfig_sub(it, i - 1, config_filename);
+ }
+
+ libconfig->destroy(&stylist_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename);
+ return true;
+}
+
+static bool stylist_read_db_libconfig_sub(struct config_setting_t *it, int idx, const char *source)
+{
+ struct stylist_data_entry entry = { 0 };
+ int i32 = 0, type = 0;
+ int64 i64 = 0;
+
+ nullpo_ret(it);
+ nullpo_ret(source);
+
+ if (!itemdb->lookup_const(it, "Type", &type) || type >= MAX_STYLIST_TYPE || type < 0) {
+ ShowWarning("stylist_read_db_libconfig_sub: Invalid or missing Type (%d) in \"%s\", entry #%d, skipping.\n", type, source, idx);
+ return false;
+ }
+ if (!itemdb->lookup_const(it, "Id", &i32) || i32 < 0) {
+ ShowWarning("stylist_read_db_libconfig_sub: Invalid or missing Id (%d) in \"%s\", entry #%d, skipping.\n", i32, source, idx);
+ return false;
+ }
+ entry.id = i32;
+
+ if (libconfig->setting_lookup_int64(it, "Zeny", &i64)) {
+ if (i64 > MAX_ZENY) {
+ ShowWarning("stylist_read_db_libconfig_sub: zeny is too big in \"%s\", entry #%d, capping to MAX_ZENY.\n", source, idx);
+ entry.zeny = MAX_ZENY;
+ } else {
+ entry.zeny = (int)i64;
+ }
+ }
+
+ if (itemdb->lookup_const(it, "ItemID", &i32))
+ entry.itemid = i32;
+
+ if (itemdb->lookup_const(it, "BoxItemID", &i32))
+ entry.boxid = i32;
+
+ if (libconfig->setting_lookup_bool(it, "AllowDoram", &i32))
+ entry.allow_doram = (i32 == 0) ? false : true;
+
+ VECTOR_ENSURE(stylist->data[type], 1, 1);
+ VECTOR_PUSH(stylist->data[type], entry);
+ return true;
+}
+
+static bool stylist_validate_requirements(struct map_session_data *sd, int type, int16 idx)
+{
+ struct item it;
+ struct stylist_data_entry *entry;
+
+ nullpo_retr(false, sd);
+ Assert_retr(false, type >= 0 && type < MAX_STYLIST_TYPE);
+ Assert_retr(false, idx >= 0 && idx < VECTOR_LENGTH(stylist->data[type]));
+
+ entry = &VECTOR_INDEX(stylist->data[type], idx);
+
+ if (sd->status.class == JOB_SUMMONER && (entry->allow_doram == false))
+ return false;
+
+ if (entry->id >= 0) {
+ if (entry->zeny != 0) {
+ if (sd->status.zeny < entry->zeny)
+ return false;
+
+ sd->status.zeny -= entry->zeny;
+ clif->updatestatus(sd, SP_ZENY);
+ } else if (entry->itemid != 0) {
+ it.nameid = entry->itemid;
+ it.amount = 1;
+ return script->buildin_delitem_search(sd, &it, false);
+ } else if (entry->boxid != 0) {
+ it.nameid = entry->boxid;
+ it.amount = 1;
+ return script->buildin_delitem_search(sd, &it, false);
+ }
+ return true;
+ }
+ return false;
+}
+
+static void stylist_send_rodexitem(struct map_session_data *sd, int itemid)
+{
+ struct rodex_message msg = { 0 };
+
+ nullpo_retv(sd);
+
+ msg.receiver_id = sd->status.char_id;
+ msg.items[0].item.nameid = itemid;
+ msg.items[0].item.amount = 1;
+ msg.items[0].item.identify = 1;
+ msg.type = MAIL_TYPE_NPC | MAIL_TYPE_ITEM;
+
+ safestrncpy(msg.sender_name, msg_txt(366), NAME_LENGTH);
+ safestrncpy(msg.title, msg_txt(367), RODEX_TITLE_LENGTH);
+ safestrncpy(msg.body, msg_txt(368), MAIL_BODY_LENGTH);
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+}
+
+static void stylist_request_style_change(struct map_session_data *sd, int type, int16 idx, bool isitem)
+{
+ struct stylist_data_entry *entry;
+
+ nullpo_retv(sd);
+ Assert_retv(idx > 0);
+ Assert_retv(type >= 0 && type < MAX_STYLIST_TYPE);
+
+ if ((idx - 1) < VECTOR_LENGTH(stylist->data[type])) {
+ entry = &VECTOR_INDEX(stylist->data[type], idx - 1);
+ if (stylist->validate_requirements(sd, type, idx - 1)) {
+ if (isitem == false)
+ pc->changelook(sd, type, entry->id);
+ else
+ stylist->send_rodexitem(sd, entry->id);
+ }
+ }
+}
+
+static void stylist_vector_init(void)
+{
+ for (int i = 0; i < MAX_STYLIST_TYPE; i++)
+ VECTOR_INIT(stylist->data[i]);
+}
+static void stylist_vector_clear(void)
+{
+ for (int i = 0; i < MAX_STYLIST_TYPE; i++)
+ VECTOR_CLEAR(stylist->data[i]);
+}
+
+static void do_init_stylist(bool minimal)
+{
+ if (minimal)
+ return;
+
+ // Initialize the db
+ stylist->vector_init();
+
+ // Load the db
+ stylist->read_db_libconfig();
+}
+
+static void do_final_stylist(void)
+{
+ // Clear the db
+ stylist->vector_clear();
+}
+
+void stylist_defaults(void)
+{
+ stylist = &stylist_s;
+
+ /* core */
+ stylist->init = do_init_stylist;
+ stylist->final = do_final_stylist;
+ /* */
+ stylist->vector_init = stylist_vector_init;
+ stylist->vector_clear = stylist_vector_clear;
+ /* database */
+ stylist->read_db_libconfig = stylist_read_db_libconfig;
+ stylist->read_db_libconfig_sub = stylist_read_db_libconfig_sub;
+ /* */
+ stylist->request_style_change = stylist_request_style_change;
+ stylist->validate_requirements = stylist_validate_requirements;
+ stylist->send_rodexitem = stylist_send_rodexitem;
+}
diff --git a/src/map/stylist.h b/src/map/stylist.h
new file mode 100644
index 000000000..1b8e20616
--- /dev/null
+++ b/src/map/stylist.h
@@ -0,0 +1,69 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_STYLIST_H
+#define MAP_STYLIST_H
+
+#include "common/hercules.h"
+#include "map/map.h" // LOOK_MAX
+
+struct map_session_data;
+
+/* Maximum available types for stylist */
+#ifndef MAX_STYLIST_TYPE
+#define MAX_STYLIST_TYPE LOOK_MAX
+#endif
+
+/* Stylist data [Asheraf/Hercules]*/
+struct stylist_data_entry {
+ int16 id;
+ int32 zeny;
+ int itemid;
+ int boxid;
+ bool allow_doram;
+};
+
+/**
+ * stylist.c Interface
+ **/
+struct stylist_interface {
+ VECTOR_DECL(struct stylist_data_entry) data[MAX_STYLIST_TYPE];
+
+ void (*init) (bool minimal);
+ void (*final) (void);
+
+ void (*vector_init) (void);
+ void (*vector_clear) (void);
+
+ bool (*read_db_libconfig) (void);
+ bool (*read_db_libconfig_sub) (struct config_setting_t *it, int idx, const char *source);
+
+ void (*request_style_change) (struct map_session_data *sd, int type, int16 idx, bool isitem);
+ bool (*validate_requirements) (struct map_session_data *sd, int type, int16 idx);
+ void (*send_rodexitem) (struct map_session_data *sd, int itemid);
+
+};
+
+#ifdef HERCULES_CORE
+void stylist_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct stylist_interface *stylist; ///< Pointer to the stylist interface.
+
+#endif /* MAP_STYLIST_H */
diff --git a/src/map/trade.c b/src/map/trade.c
index 6352c3a4d..e727c3c70 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,19 +40,22 @@
#include <stdio.h>
#include <string.h>
-struct trade_interface trade_s;
+static struct trade_interface trade_s;
struct trade_interface *trade;
/*==========================================
* Initiates a trade request.
*------------------------------------------*/
-void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd)
+static void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd)
{
nullpo_retv(sd);
+ if (sd == target_sd)
+ return;
+
if (map->list[sd->bl.m].flag.notrade) {
- clif->message (sd->fd, msg_sd(sd,272));
- return; //Can't trade in notrade mapflag maps.
+ clif->message (sd->fd, msg_sd(sd,272)); // You can't trade in this map
+ return;
}
if (target_sd == NULL || sd == target_sd) {
@@ -90,7 +93,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade
{
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
clif->tradestart(sd, 2); // GM is not allowed to trade
return;
}
@@ -118,7 +121,8 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
* Weird enough, the client should only send 3/4
* and the server is the one that can reply 0~2
*------------------------------------------*/
-void trade_tradeack(struct map_session_data *sd, int type) {
+static void trade_tradeack(struct map_session_data *sd, int type)
+{
struct map_session_data *tsd;
nullpo_retv(sd);
@@ -162,8 +166,8 @@ void trade_tradeack(struct map_session_data *sd, int type) {
}
//Check if you can start trade.
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED
- || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED
+ if (sd->npc_id || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED
+ || tsd->npc_id || tsd->state.vending || tsd->state.prevend || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED
) {
//Fail
clif->tradestart(sd, 2);
@@ -191,7 +195,7 @@ void trade_tradeack(struct map_session_data *sd, int type) {
* @retval 0 The trade can continue
* @retval 1 Hack attempt
**/
-int impossible_trade_check(struct map_session_data *sd)
+static int impossible_trade_check(struct map_session_data *sd)
{
struct item inventory[MAX_INVENTORY];
char message_to_gm[200];
@@ -208,7 +212,7 @@ int impossible_trade_check(struct map_session_data *sd)
// remove this part: arrows can be trade and equipped
// re-added! [celest]
// remove equipped items (they can not be trade)
- for (i = 0; i < MAX_INVENTORY; i++)
+ for (i = 0; i < sd->status.inventorySize; i++)
if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO))
memset(&inventory[i], 0, sizeof(struct item));
@@ -217,12 +221,14 @@ int impossible_trade_check(struct map_session_data *sd)
if (!sd->deal.item[i].amount)
continue;
index = sd->deal.item[i].index;
+ if (index < 0 || index >= sd->status.inventorySize)
+ return 1;
if (inventory[index].amount < sd->deal.item[i].amount) {
// if more than the player have -> hack
snprintf(message_to_gm, sizeof(message_to_gm), msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
- intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
snprintf(message_to_gm, sizeof(message_to_gm), msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
- intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
// if we block people
if (battle_config.ban_hack_trade < 0) {
chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0);
@@ -239,7 +245,7 @@ int impossible_trade_check(struct map_session_data *sd)
// message about the ban
safestrncpy(message_to_gm, msg_txt(508), sizeof(message_to_gm)); // This player hasn't been banned (Ban option is disabled).
- intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
return 1;
}
inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
@@ -250,13 +256,15 @@ int impossible_trade_check(struct map_session_data *sd)
/*==========================================
* Checks if trade is possible (against zeny limits, inventory limits, etc)
*------------------------------------------*/
-int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
+static int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
{
struct item inventory[MAX_INVENTORY];
struct item inventory2[MAX_INVENTORY];
struct item_data *data;
int trade_i, i, n;
+ nullpo_ret(sd);
+ nullpo_ret(tsd);
// check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then.
if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny))
return 0;
@@ -276,9 +284,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
return 0; //qty Exploit?
data = itemdb->search(inventory[n].nameid);
- i = MAX_INVENTORY;
+ i = tsd->status.inventorySize;
if (itemdb->isstackable2(data)) { //Stackable item.
- for(i = 0; i < MAX_INVENTORY; i++)
+ for(i = 0; i < tsd->status.inventorySize; i++)
if (inventory2[i].nameid == inventory[n].nameid &&
inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] &&
inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) {
@@ -290,9 +298,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
}
}
- if (i == MAX_INVENTORY) {// look for an empty slot.
- for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
- if (i == MAX_INVENTORY)
+ if (i == tsd->status.inventorySize) {// look for an empty slot.
+ for (i = 0; i < tsd->status.inventorySize && inventory2[i].nameid; i++);
+ if (i == tsd->status.inventorySize)
return 0;
memcpy(&inventory2[i], &inventory[n], sizeof(struct item));
inventory2[i].amount = amount;
@@ -303,13 +311,15 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
if (!amount)
continue;
n = tsd->deal.item[trade_i].index;
+ if (n < 0 || n >= tsd->status.inventorySize)
+ return 0;
if (amount > inventory2[n].amount)
return 0;
// search if it's possible to add item (for full inventory)
data = itemdb->search(inventory2[n].nameid);
- i = MAX_INVENTORY;
+ i = sd->status.inventorySize;
if (itemdb->isstackable2(data)) {
- for(i = 0; i < MAX_INVENTORY; i++)
+ for(i = 0; i < sd->status.inventorySize; i++)
if (inventory[i].nameid == inventory2[n].nameid &&
inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] &&
inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) {
@@ -320,9 +330,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
break;
}
}
- if (i == MAX_INVENTORY) {
- for(i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++);
- if (i == MAX_INVENTORY)
+ if (i == sd->status.inventorySize) {
+ for(i = 0; i < sd->status.inventorySize && inventory[i].nameid; i++);
+ if (i == sd->status.inventorySize)
return 0;
memcpy(&inventory[i], &inventory2[n], sizeof(struct item));
inventory[i].amount = amount;
@@ -336,7 +346,8 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
/*==========================================
* Adds an item/qty to the trade window
*------------------------------------------*/
-void trade_tradeadditem(struct map_session_data *sd, short index, short amount) {
+static void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
+{
struct map_session_data *target_sd;
struct item *item;
int trade_i, trade_weight;
@@ -361,7 +372,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
index -= 2; // 0 is for zeny, 1 is unknown. Gravity, go figure...
//Item checks...
- if( index < 0 || index >= MAX_INVENTORY )
+ if (index < 0 || index >= sd->status.inventorySize)
return;
if( amount < 0 || amount > sd->status.inventory[index].amount )
return;
@@ -372,14 +383,14 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade
(pc->get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade
{
- clif->message (sd->fd, msg_sd(sd,260));
+ clif->message (sd->fd, msg_sd(sd,260)); // This item cannot be traded.
clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
if( item->expire_time )
{ // Rental System
- clif->message (sd->fd, msg_sd(sd,260));
+ clif->message (sd->fd, msg_sd(sd,260)); // This item cannot be traded.
clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
@@ -388,7 +399,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
!( item->bound == IBT_GUILD && sd->status.guild_id == target_sd->status.guild_id ) &&
!( item->bound == IBT_PARTY && sd->status.party_id == target_sd->status.party_id )
&& !pc_can_give_bound_items(sd) ) {
- clif->message(sd->fd, msg_sd(sd,293));
+ clif->message(sd->fd, msg_sd(sd,293)); // This bound item cannot be traded to that character.
clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
@@ -430,7 +441,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
/*==========================================
* Adds the specified amount of zeny to the trade window
*------------------------------------------*/
-void trade_tradeaddzeny(struct map_session_data* sd, int amount)
+static void trade_tradeaddzeny(struct map_session_data *sd, int amount)
{
struct map_session_data* target_sd;
nullpo_retv(sd);
@@ -456,9 +467,11 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount)
/*==========================================
* 'Ok' button on the trade window is pressed.
*------------------------------------------*/
-void trade_tradeok(struct map_session_data *sd) {
+static void trade_tradeok(struct map_session_data *sd)
+{
struct map_session_data *target_sd;
+ nullpo_retv(sd);
if(sd->state.deal_locked || !sd->state.trading)
return;
@@ -475,10 +488,12 @@ void trade_tradeok(struct map_session_data *sd) {
/*==========================================
* 'Cancel' is pressed. (or trade was force-canceled by the code)
*------------------------------------------*/
-void trade_tradecancel(struct map_session_data *sd) {
+static void trade_tradecancel(struct map_session_data *sd)
+{
struct map_session_data *target_sd;
int trade_i;
+ nullpo_retv(sd);
target_sd = map->id2sd(sd->trade_partner);
if(!sd->state.trading)
@@ -533,11 +548,13 @@ void trade_tradecancel(struct map_session_data *sd) {
/*==========================================
* lock sd and tsd trade data, execute the trade, clear, then save players
*------------------------------------------*/
-void trade_tradecommit(struct map_session_data *sd) {
+static void trade_tradecommit(struct map_session_data *sd)
+{
struct map_session_data *tsd;
int trade_i;
int flag;
+ nullpo_retv(sd);
if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade.
return;
diff --git a/src/map/trade.h b/src/map/trade.h
index eba91a1d9..da55f5057 100644
--- a/src/map/trade.h
+++ b/src/map/trade.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/map/unit.c b/src/map/unit.c
index 9a698b77e..19f09f83c 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include "map/battleground.h"
#include "map/chat.h"
#include "map/chrif.h"
+#include "map/clan.h"
#include "map/clif.h"
#include "map/duel.h"
#include "map/elemental.h"
@@ -56,34 +57,84 @@
#include "common/showmsg.h"
#include "common/socket.h"
#include "common/timer.h"
+#include "common/utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-const short dirx[8]={0,-1,-1,-1,0,1,1,1};
-const short diry[8]={1,1,0,-1,-1,-1,0,1};
+const short dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+const short diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-struct unit_interface unit_s;
+static struct unit_interface unit_s;
struct unit_interface *unit;
/**
* Returns the unit_data for the given block_list. If the object is using
* shared unit_data (i.e. in case of BL_NPC), it returns the shared data.
- * @param bl block_list to process
+ *
+ * __Warning:__ if bl->type is not known or NULL,
+ * an assertion will be triggered and NULL returned.
+ * @param bl block_list to process, it is expected to be not NULL.
* @return a pointer to the given object's unit_data
**/
-struct unit_data* unit_bl2ud(struct block_list *bl)
+static struct unit_data *unit_bl2ud(struct block_list *bl)
{
- if (bl == NULL) return NULL;
- if (bl->type == BL_PC) return &BL_UCAST(BL_PC, bl)->ud;
- if (bl->type == BL_MOB) return &BL_UCAST(BL_MOB, bl)->ud;
- if (bl->type == BL_PET) return &BL_UCAST(BL_PET, bl)->ud;
- if (bl->type == BL_NPC) return BL_UCAST(BL_NPC, bl)->ud;
- if (bl->type == BL_HOM) return &BL_UCAST(BL_HOM, bl)->ud;
- if (bl->type == BL_MER) return &BL_UCAST(BL_MER, bl)->ud;
- if (bl->type == BL_ELEM) return &BL_UCAST(BL_ELEM, bl)->ud;
- return NULL;
+ Assert_retr(NULL, bl != NULL);
+ switch (bl->type) {
+ case BL_PC:
+ return &BL_UCAST(BL_PC, bl)->ud;
+ case BL_MOB:
+ return &BL_UCAST(BL_MOB, bl)->ud;
+ case BL_PET:
+ return &BL_UCAST(BL_PET, bl)->ud;
+ case BL_NPC:
+ return BL_UCAST(BL_NPC, bl)->ud;
+ case BL_HOM:
+ return &BL_UCAST(BL_HOM, bl)->ud;
+ case BL_MER:
+ return &BL_UCAST(BL_MER, bl)->ud;
+ case BL_ELEM:
+ return &BL_UCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
+ default:
+ Assert_retr(NULL, false);
+ }
+}
+
+/**
+ * Returns the const unit_data for the given const block_list. If the object is using
+ * shared unit_data (i.e. in case of BL_NPC), it returns the shared data.
+ *
+ * __Warning:__ if bl->type is not known or NULL,
+ * an assertion will be triggered and NULL returned.
+ * @param bl block_list to process, it is expected to be not NULL.
+ * @return a pointer to the given object's unit_data
+ **/
+static const struct unit_data *unit_cbl2ud(const struct block_list *bl)
+{
+ Assert_retr(NULL, bl != NULL);
+ switch (bl->type) {
+ case BL_PC:
+ return &BL_UCCAST(BL_PC, bl)->ud;
+ case BL_MOB:
+ return &BL_UCCAST(BL_MOB, bl)->ud;
+ case BL_PET:
+ return &BL_UCCAST(BL_PET, bl)->ud;
+ case BL_NPC:
+ return BL_UCCAST(BL_NPC, bl)->ud;
+ case BL_HOM:
+ return &BL_UCCAST(BL_HOM, bl)->ud;
+ case BL_MER:
+ return &BL_UCCAST(BL_MER, bl)->ud;
+ case BL_ELEM:
+ return &BL_UCCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
+ default:
+ Assert_retr(NULL, false);
+ }
}
/**
@@ -93,7 +144,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
* @param bl block_list to process
* @return a pointer to the given object's unit_data
*/
-struct unit_data *unit_bl2ud2(struct block_list *bl)
+static struct unit_data *unit_bl2ud2(struct block_list *bl)
{
struct npc_data *nd = BL_CAST(BL_NPC, bl);
if (nd != NULL && nd->ud == &npc->base_ud) {
@@ -104,42 +155,46 @@ struct unit_data *unit_bl2ud2(struct block_list *bl)
return unit->bl2ud(bl);
}
-int unit_walktoxy_sub(struct block_list *bl)
+/**
+ * TODO: understand purpose of this function
+ * @param bl block_list to process
+ * @return 0: success, 1: fail, 2: nullpointer
+ */
+static int unit_walk_toxy_sub(struct block_list *bl)
{
- int i;
- struct walkpath_data wpd;
- struct unit_data *ud = NULL;
-
- nullpo_retr(1, bl);
- ud = unit->bl2ud(bl);
- if(ud == NULL) return 0;
+ nullpo_retr(2, bl);
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 2;
- memset(&wpd, 0, sizeof(wpd));
+ struct walkpath_data wpd = {0};
- if( !path->search(&wpd,bl,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
- return 0;
+ if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, ud->state.walk_easy, CELL_CHKNOPASS))
+ return 1;
#ifdef OFFICIAL_WALKPATH
- if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
- && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
- && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
- return 0;
+ if (bl->type != BL_NPC // If type is an NPC, disregard.
+ && !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
+ && wpd.path_len > 14) { // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ return 1;
+ }
#endif
- memcpy(&ud->walkpath,&wpd,sizeof(wpd));
+ ud->walkpath = wpd;
- if (ud->target_to && ud->chaserange>1) {
- //Generally speaking, the walk path is already to an adjacent tile
- //so we only need to shorten the path if the range is greater than 1.
+ if (ud->target_to != 0 && ud->chaserange > 1) {
+ // Generally speaking, the walk path is already to an adjacent tile
+ // so we only need to shorten the path if the range is greater than 1.
- //Trim the last part of the path to account for range,
- //but always move at least one cell when requested to move.
- for (i = (ud->chaserange*10)-10; i > 0 && ud->walkpath.path_len>1;) {
- uint8 dir;
+ // Trim the last part of the path to account for range,
+ // but always move at least one cell when requested to move.
+ for (int i = ud->chaserange * 10 - 10; i > 0 && ud->walkpath.path_len > 1;) {
+ enum unit_dir dir;
ud->walkpath.path_len--;
dir = ud->walkpath.path[ud->walkpath.path_len];
- if (dir&1)
- i -= MOVE_COST*20; //When chasing, units will target a diamond-shaped area in range [Playtester]
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ if (unit_is_diagonal_dir(dir))
+ i -= MOVE_COST * 20; // When chasing, units will target a diamond-shaped area in range [Playtester]
else
i -= MOVE_COST;
ud->to_x -= dirx[dir];
@@ -147,7 +202,7 @@ int unit_walktoxy_sub(struct block_list *bl)
}
}
- ud->state.change_walk_target=0;
+ ud->state.change_walk_target = 0;
if (bl->type == BL_PC) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
@@ -156,15 +211,17 @@ int unit_walktoxy_sub(struct block_list *bl)
}
clif->move(ud);
- if(ud->walkpath.path_pos>=ud->walkpath.path_len)
- i = -1;
- else if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status->get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST;
+ int timer_delay;
+ if (ud->walkpath.path_pos >= ud->walkpath.path_len)
+ timer_delay = -1;
+ else if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * MOVE_DIAGONAL_COST / MOVE_COST;
else
- i = status->get_speed(bl);
- if( i > 0)
- ud->walktimer = timer->add(timer->gettick()+i,unit->walktoxy_timer,bl->id,i);
- return 1;
+ timer_delay = status->get_speed(bl);
+
+ if (timer_delay > 0)
+ ud->walktimer = timer->add(timer->gettick() + timer_delay, unit->walk_toxy_timer, bl->id, 0); //TODO: check if unit->walk_toxy_timer uses any intptr data
+ return 0;
}
/**
@@ -172,422 +229,463 @@ int unit_walktoxy_sub(struct block_list *bl)
* @param tid: Timer ID
* @param tick: Unused
* @param id: ID of bl to do the action
- * @param data: Not used
- * @return 1: Success 0: Fail (No valid bl)
+ * @param data: Unused
+ * @return 0: success, 1: fail, 2: nullpointer
*/
-int unit_step_timer(int tid, int64 tick, int id, intptr_t data)
+static int unit_steptimer(int tid, int64 tick, int id, intptr_t data)
{
- struct block_list *bl;
- struct unit_data *ud;
- int target_id;
-
- bl = map->id2bl(id);
-
- if (!bl || bl->prev == NULL)
- return 0;
-
- ud = unit->bl2ud(bl);
-
- if(!ud)
- return 0;
+ struct block_list *bl = map->id2bl(id);
+ if (bl == NULL || bl->prev == NULL)
+ return 2;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 2;
- if(ud->steptimer != tid) {
- ShowError("unit_step_timer mismatch %d != %d\n",ud->steptimer,tid);
- return 0;
+ if (ud->steptimer != tid) {
+ ShowError("unit_steptimer mismatch %d != %d\n", ud->steptimer, tid);
+ return 1;
}
ud->steptimer = INVALID_TIMER;
- if(!ud->stepaction)
- return 0;
+ if (!ud->stepaction)
+ return 1;
- //Set to false here because if an error occurs, it should not be executed again
+ // Set to false here because if an error occurs, it should not be executed again
ud->stepaction = false;
- if(!ud->target_to)
- return 0;
+ if (ud->target_to == 0)
+ return 1;
- //Flush target_to as it might contain map coordinates which should not be used by other functions
- target_id = ud->target_to;
+ // Flush target_to as it might contain map coordinates which should not be used by other functions
+ int target_id = ud->target_to;
ud->target_to = 0;
- //If stepaction is set then we remembered a client request that should be executed on the next step
- //Execute request now if target is in attack range
- if(ud->stepskill_id && skill->get_inf(ud->stepskill_id) & INF_GROUND_SKILL) {
- //Execute ground skill
+ // If stepaction is set then we remembered a client request that should be executed on the next step
+ // Execute request now if target is in attack range
+ if (ud->stepskill_id != 0 && (skill->get_inf(ud->stepskill_id) & INF_GROUND_SKILL) != 0) {
+ // Execute ground skill
struct map_data *md = &map->list[bl->m];
- unit->skilluse_pos(bl, target_id%md->xs, target_id/md->xs, ud->stepskill_id, ud->stepskill_lv);
+ unit->skilluse_pos(bl, target_id % md->xs, target_id / md->xs, ud->stepskill_id, ud->stepskill_lv);
} else {
- //If a player has target_id set and target is in range, attempt attack
+ // If a player has target_id set and target is in range, attempt attack
struct block_list *tbl = map->id2bl(target_id);
- if (!tbl || !status->check_visibility(bl, tbl)) {
- return 0;
- }
- if(ud->stepskill_id == 0) {
- //Execute normal attack
- unit->attack(bl, tbl->id, (ud->state.attack_continue) + 2);
- } else {
- //Execute non-ground skill
- unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv);
- }
+ nullpo_retr(2, tbl);
+ if (status->check_visibility(bl, tbl) == 0) // Target not visible
+ return 1;
+ if (ud->stepskill_id == 0)
+ unit->attack(bl, tbl->id, ud->state.attack_continue + 2); // Execute normal attack
+ else
+ unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv); // Execute non-ground skill
}
- return 1;
+ return 0;
}
+/**
+ * Warps homunculus or mercenary towards his master in case he's too far away for 3 seconds.
+ * @param master_bl: block_list of master
+ * @param slave_bl: block_list of homunculus/mercenary master owns
+ * @return 0: success, 1: fail
+ */
+static int unit_warpto_master(struct block_list *master_bl, struct block_list *slave_bl)
+{
+ nullpo_retr(1, master_bl);
+ nullpo_retr(1, slave_bl);
+ int64 *masterteleport_timer;
+ struct homun_data *hd = BL_CAST(BL_HOM, slave_bl);
+ struct mercenary_data *md = BL_CAST(BL_MER, slave_bl);
+
+ bool check = true;
+ if (hd != NULL) {
+ masterteleport_timer = &hd->masterteleport_timer;
+ check = homun_alive(hd);
+ } else if (md != NULL) {
+ masterteleport_timer = &md->masterteleport_timer;
+ } else {
+ return 1;
+ }
-int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
- int i;
- int x,y,dx,dy;
- unsigned char icewall_walk_block;
- uint8 dir;
- struct block_list *bl;
- struct map_session_data *sd;
- struct mob_data *md;
- struct unit_data *ud;
- struct mercenary_data *mrd;
+ if (check && !check_distance_bl(master_bl, slave_bl, MAX_MER_DISTANCE)) {
+ if (*masterteleport_timer == 0) {
+ *masterteleport_timer = timer->gettick();
+ return 0;
+ } else if (DIFF_TICK(timer->gettick(), *masterteleport_timer) > 3000) {
+ unit->warp(slave_bl, master_bl->m, master_bl->x, master_bl->y, CLR_TELEPORT);
+ }
+ }
+ *masterteleport_timer = 0; // resets tick in case he isn't far anymore.
- bl = map->id2bl(id);
- if(bl == NULL)
- return 0;
- sd = BL_CAST(BL_PC, bl);
- md = BL_CAST(BL_MOB, bl);
- mrd = BL_CAST(BL_MER, bl);
- ud = unit->bl2ud(bl);
+ return 0;
+}
- if(ud == NULL) return 0;
+/**
+ * Timer for walking to target coordinates or object.
+ * @param tid: timer id
+ * @param tick: tick
+ * @param id: id of bl to do the action
+ * @param data: unused
+ * @return 0: success, 1: fail
+ */
+static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct block_list *bl = map->id2bl(id);
+ if (bl == NULL)
+ return 1;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
- if(ud->walktimer != tid){
+ if (ud->walktimer != tid) {
ShowError("unit_walk_timer mismatch %d != %d\n",ud->walktimer,tid);
- return 0;
+ return 1;
}
+
ud->walktimer = INVALID_TIMER;
- if (bl->prev == NULL) return 0; // Stop moved because it is missing from the block_list
- if(ud->walkpath.path_pos>=ud->walkpath.path_len)
- return 0;
+ if (bl->prev == NULL) // Stop moved because it is missing from the block_list.
+ return 1;
- if(ud->walkpath.path[ud->walkpath.path_pos]>=8)
+ if (ud->walkpath.path_pos >= ud->walkpath.path_len)
return 1;
- x = bl->x;
- y = bl->y;
- dir = ud->walkpath.path[ud->walkpath.path_pos];
+ enum unit_dir dir = ud->walkpath.path[ud->walkpath.path_pos];
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ int x = bl->x;
+ int y = bl->y;
+
ud->dir = dir;
- dx = dirx[(int)dir];
- dy = diry[(int)dir];
+ int dx = dirx[dir];
+ int dy = diry[dir];
- //Get icewall walk block depending on boss mode (players can't be trapped)
- if(md && md->status.mode&MD_BOSS)
- icewall_walk_block = battle_config.boss_icewall_walk_block;
- else if(md)
- icewall_walk_block = battle_config.mob_icewall_walk_block;
- else
- icewall_walk_block = 0;
+ // Get icewall walk block depending on boss mode (players can't be trapped)
+ unsigned char icewall_walk_block = 0;
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if (md != NULL) {
+ if ((md->status.mode & MD_BOSS) != 0)
+ icewall_walk_block = battle_config.boss_icewall_walk_block;
+ else
+ icewall_walk_block = battle_config.mob_icewall_walk_block;
+ }
- //Monsters will walk into an icewall from the west and south if they already started walking
+ // Monsters will walk into an icewall from the west and south if they already started walking
if (map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKNOPASS)
&& (icewall_walk_block == 0 || !map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKICEWALL) || dx < 0 || dy < 0))
- return unit->walktoxy_sub(bl);
+ return unit->walk_toxy_sub(bl);
- //Monsters can only leave icewalls to the west and south
- //But if movement fails more than icewall_walk_block times, they can ignore this rule
- if (md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m, bl, x, y, CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
- //Needs to be done here so that rudeattack skills are invoked
+ // Monsters can only leave icewalls to the west and south
+ // But if movement fails more than icewall_walk_block times, they can ignore this rule
+ if (md != NULL && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m, bl, x, y, CELL_CHKICEWALL) != 0 && (dx > 0 || dy > 0)) {
+ // Needs to be done here so that rudeattack skills are invoked
md->walktoxy_fail_count++;
clif->fixpos(bl);
- //Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
- if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ // Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
+ if ((++ud->walk_count % WALK_SKILL_INTERVAL) == 0)
mob->skill_use(md, tick, -1);
mob->unlocktarget(md, tick);
- if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ if ((++ud->walk_count % WALK_SKILL_INTERVAL) != 0)
mob->skill_use(md, tick, -1);
- return 0;
+ return 1;
}
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
//Refresh view for all those we lose sight
- map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, (sd != NULL ? BL_ALL : BL_PC), bl);
x += dx;
y += dy;
map->moveblock(bl, x, y, tick);
- ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex]
+ ud->walk_count++; // walked cell counter, to be used for walk-triggered skills. [Skotlex]
status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); //If you move, you lose your counters. [malufett]
if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER)
- return 0; //map->moveblock has altered the object beyond what we expected (moved/warped it)
+ return 1; // map->moveblock has altered the object beyond what we expected (moved/warped it)
ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets
- map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, (sd != NULL ? BL_ALL : BL_PC), bl);
ud->walktimer = INVALID_TIMER;
- if(sd) {
- if( sd->touching_id )
- npc->touchnext_areanpc(sd,false);
+ struct mercenary_data *mrd = BL_CAST(BL_MER, bl);
+ if (sd != NULL) {
+ if (sd->touching_id != 0)
+ npc->touchnext_areanpc(sd, false);
if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC)) {
- npc->touch_areanpc(sd,bl->m,x,y);
+ npc->touch_areanpc(sd, bl->m, x, y);
if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
return 0;
- } else
+ } else {
npc->untouch_areanpc(sd, bl->m, x, y);
-
- if( sd->md ) { // mercenary should be warped after being 3 seconds too far from the master [greenbox]
- if( !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) {
- if (sd->md->masterteleport_timer == 0)
- sd->md->masterteleport_timer = timer->gettick();
- else if (DIFF_TICK(timer->gettick(), sd->md->masterteleport_timer) > 3000) {
- sd->md->masterteleport_timer = 0;
- unit->warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
- }
- } else // reset the tick, he is not far anymore
- sd->md->masterteleport_timer = 0;
- }
- if( sd->hd ) {
- if( homun_alive(sd->hd) && !check_distance_bl(&sd->bl, &sd->hd->bl, MAX_MER_DISTANCE) ) {
- if (sd->hd->masterteleport_timer == 0)
- sd->hd->masterteleport_timer = timer->gettick();
- else if (DIFF_TICK(timer->gettick(), sd->hd->masterteleport_timer) > 3000) {
- sd->hd->masterteleport_timer = 0;
- unit->warp( &sd->hd->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
- }
- } else
- sd->hd->masterteleport_timer = 0;
}
+
+ if (sd->md != NULL) // mercenary should be warped after being 3 seconds too far from the master [greenbox]
+ unit->warpto_master(bl, &sd->md->bl);
+ if (sd->hd != NULL)
+ unit->warpto_master(bl, &sd->hd->bl);
} else if (md) {
- //Movement was successful, reset walktoxy_fail_count
+ // Movement was successful, reset walktoxy_fail_count
md->walktoxy_fail_count = 0;
- if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC)) {
- if( npc->touch_areanpc2(md) ) return 0; // Warped
- } else
+
+ if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC) != 0 && npc->touch_areanpc2(md))
+ return 0; // Warped
+ else
md->areanpc_id = 0;
- if (md->min_chase > md->db->range3) md->min_chase--;
- //Walk skills are triggered regardless of target due to the idle-walk mob state.
- //But avoid triggering on stop-walk calls.
- if (tid != INVALID_TIMER
- && !(ud->walk_count%WALK_SKILL_INTERVAL)
- && map->list[bl->m].users > 0
- && mob->skill_use(md, tick, -1)
- ) {
+
+ if (md->min_chase > md->db->range3)
+ md->min_chase--;
+ // Walk skills are triggered regardless of target due to the idle-walk mob state.
+ // But avoid triggering on stop-walk calls.
+ if (tid != INVALID_TIMER && (ud->walk_count % WALK_SKILL_INTERVAL) == 0
+ && map->list[bl->m].users > 0 && mob->skill_use(md, tick, -1) == 0) {
+ // Walk skills are supposed to be used while walking
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
- && md->state.skillstate != MSS_WALK //Walk skills are supposed to be used while walking
- ) {
- //Skill used, abort walking
- clif->fixpos(bl); //Fix position as walk has been canceled.
- return 0;
+ && md->state.skillstate != MSS_WALK) {
+ // Skill used, abort walking
+ clif->fixpos(bl); // Fix position as walk has been canceled.
+ return 1;
}
- //Resend walk packet for proper Self Destruction display.
+ // Resend walk packet for proper Self Destruction display.
clif->move(ud);
}
- }
- else if( mrd && mrd->master )
- {
- if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE))
- {
- // mercenary should be warped after being 3 seconds too far from the master [greenbox]
- if (mrd->masterteleport_timer == 0)
- {
- mrd->masterteleport_timer = timer->gettick();
- }
- else if (DIFF_TICK(timer->gettick(), mrd->masterteleport_timer) > 3000)
- {
- mrd->masterteleport_timer = 0;
- unit->warp( bl, mrd->master->bl.m, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
- }
- }
- else
- {
- mrd->masterteleport_timer = 0;
- }
+ } else if (mrd != NULL && mrd->master != NULL) {
+ unit->warpto_master(&mrd->master->bl, bl);
}
- if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
+ if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
return 0;
- //If stepaction is set then we remembered a client request that should be executed on the next step
- if (ud->stepaction && ud->target_to) {
- //Delete old stepaction even if not executed yet, the latest command is what counts
- if(ud->steptimer != INVALID_TIMER) {
- timer->delete(ud->steptimer, unit->step_timer);
+ // If stepaction is set then we remembered a client request that should be executed on the next step
+ if (ud->stepaction && ud->target_to != 0) {
+ // Delete old stepaction even if not executed yet, the latest command is what counts
+ if (ud->steptimer != INVALID_TIMER) {
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
- //Delay stepactions by half a step (so they are executed at full step)
- if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status->get_speed(bl)*14/20;
+ // Delay stepactions by half a step (so they are executed at full step)
+ int timer_delay;
+ if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * 14 / 20;
else
- i = status->get_speed(bl)/2;
- ud->steptimer = timer->add(tick+i, unit->step_timer, bl->id, 0);
+ timer_delay = status->get_speed(bl) / 2;
+ ud->steptimer = timer->add(tick + timer_delay, unit->steptimer, bl->id, 0);
}
- if(ud->state.change_walk_target) {
- if(unit->walktoxy_sub(bl)) {
- return 1;
- } else {
- clif->fixpos(bl);
+ if (ud->state.change_walk_target) {
+ if (unit->walk_toxy_sub(bl) == 0)
return 0;
- }
+ clif->fixpos(bl);
+ return 1;
}
+ int timer_delay;
ud->walkpath.path_pos++;
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
- i = -1;
- else if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status->get_speed(bl)*14/10;
+ timer_delay = -1;
+ else if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * 14 / 10;
else
- i = status->get_speed(bl);
+ timer_delay = status->get_speed(bl);
- if(i > 0) {
- ud->walktimer = timer->add(tick+i,unit->walktoxy_timer,id,i);
- if( md && DIFF_TICK(tick,md->dmgtick) < 3000 )//not required not damaged recently
+ if (timer_delay > 0) {
+ ud->walktimer = timer->add(tick + timer_delay, unit->walk_toxy_timer, id, 0);
+ if (md != NULL && DIFF_TICK(tick, md->dmgtick) < 3000) // not required not damaged recently
clif->move(ud);
- } else if(ud->state.running) {
- //Keep trying to run.
- if ( !(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)) )
+ } else if (ud->state.running != 0) {
+ // Keep trying to run.
+ if (!(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)))
ud->state.running = 0;
- } else if (!ud->stepaction && ud->target_to) {
- //Update target trajectory.
+ } else if (!ud->stepaction && ud->target_to != 0) {
+ // Update target trajectory.
struct block_list *tbl = map->id2bl(ud->target_to);
- if (!tbl || !status->check_visibility(bl, tbl)) {
- //Cancel chase.
+ if (tbl == NULL || status->check_visibility(bl, tbl) == 0) { // not visible
+ // Cancel chase.
ud->to_x = bl->x;
ud->to_y = bl->y;
- if (tbl && bl->type == BL_MOB && mob->warpchase(BL_UCAST(BL_MOB, bl), tbl))
+ if (tbl != NULL && bl->type == BL_MOB && mob->warpchase(BL_UCAST(BL_MOB, bl), tbl) != 0)
return 0;
ud->target_to = 0;
- return 0;
+ return 1;
}
if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) {
//Reached destination.
+ ud->target_to = 0;
if (ud->state.attack_continue) {
//Aegis uses one before every attack, we should
//only need this one for syncing purposes. [Skotlex]
- ud->target_to = 0;
clif->fixpos(bl);
unit->attack(bl, tbl->id, ud->state.attack_continue);
}
- } else { //Update chase-path
- unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue? 1 : 0));
+ } else { // Update chase-path
+ unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy | ud->state.attack_continue);
return 0;
}
} else {
- //Stopped walking. Update to_x and to_y to current location [Skotlex]
+ // Stopped walking. Update to_x and to_y to current location [Skotlex]
ud->to_x = bl->x;
ud->to_y = bl->y;
- if(battle_config.official_cell_stack_limit && map->count_oncell(bl->m, x, y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
- //Walked on occupied cell, call unit_walktoxy again
- if(ud->steptimer != INVALID_TIMER) {
- //Execute step timer on next step instead
- timer->delete(ud->steptimer, unit->step_timer);
+ if (battle_config.official_cell_stack_limit != 0 && map->count_oncell(bl->m, x, y, BL_CHAR | BL_NPC, 0x1 | 0x2) > battle_config.official_cell_stack_limit) {
+ // Walked on occupied cell, call unit->walk_toxy again
+ if (ud->steptimer != INVALID_TIMER) {
+ // Execute step timer on next step instead
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
- return unit->walktoxy(bl, x, y, 8);
+ return unit->walk_toxy(bl, x, y, 8);
}
}
return 0;
}
-int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
+/**
+ * Timer for delayed execution of unit->walk_toxy once triggered
+ * @param tid: Timer ID, unused
+ * @param tick: Tick, unused
+ * @param id: ID of block_list to execute the action
+ * @param data: uint32 data cast to intptr_t with x-coord in lowest 16 bits and y-coord in highest 16 bits
+ * @return 0: success, 1: failure
+ */
+static int unit_delay_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl = map->id2bl(id);
-
- if (!bl || bl->prev == NULL)
- return 0;
- unit->walktoxy(bl, (short)((data>>16)&0xffff), (short)(data&0xffff), 0);
- return 1;
+ if (bl == NULL || bl->prev == NULL)
+ return 1;
+ short x = (short)GetWord((uint32)data, 0);
+ short y = (short)GetWord((uint32)data, 1);
+ unit->walk_toxy(bl, x, y, 0);
+ return 0;
}
-//flag parameter:
-//&1 -> 1/0 = easy/hard
-//&2 -> force walking
-//&4 -> Delay walking if the reason you can't walk is the canwalk delay
-//&8 -> Search for an unoccupied cell and cancel if none available
-int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
+/**
+ * Makes a unit walk to (x, y) coordinates
+ * @param bl: block_list of unit to move
+ * @param x: x-coordinate
+ * @param y: y-coordinate
+ * @param flag: flag paramater with following options:
+ * - `& 1` -> 1/0 = easy / hard
+ * - `& 2` -> Force walking
+ * - `& 4` -> Delay walking, if the reason you can't walk is the `canwalk delay`
+ * - `& 8` -> Search for an unoccupied cell and cancel if none available
+ * .
+ * @return 0: success, 1: failure
+ */
+static int unit_walk_toxy(struct block_list *bl, short x, short y, int flag)
{
+ // TODO: change flag to enum? [skyleo]
struct unit_data* ud = NULL;
struct status_change* sc = NULL;
struct walkpath_data wpd;
- nullpo_ret(bl);
+ nullpo_retr(1, bl);
ud = unit->bl2ud(bl);
- if( ud == NULL) return 0;
+ if (ud == NULL)
+ return 1;
- if (battle_config.check_occupied_cells && (flag&8) && !map->closest_freecell(bl->m, bl, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y
- return 0;
+ if ((flag & 8) != 0 && battle_config.check_occupied_cells != 0) {
+ if (!map->closest_freecell(bl->m, bl, &x, &y, BL_CHAR | BL_NPC, 1)) // This might change x and y
+ return 1;
+ }
- if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
- return 0;
+ if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, x, y, flag & 1, CELL_CHKNOPASS)) // Count walk path cells
+ return 1;
+ if (bl->type != BL_NPC) {
#ifdef OFFICIAL_WALKPATH
- if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between
- && (wpd.path_len > (battle_config.max_walk_path/17)*14) // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
- && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
- return 0;
+ // Check if there is an obstacle between
+ // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ if (!path->search_long(NULL, bl, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS)
+ && (wpd.path_len > (battle_config.max_walk_path / 17) * 14))
+ return 1;
#endif
- if ((wpd.path_len > battle_config.max_walk_path) && (bl->type != BL_NPC))
- return 0;
+ if (wpd.path_len > battle_config.max_walk_path)
+ return 1;
+ }
- if (flag&4 && DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0 &&
- DIFF_TICK(ud->canmove_tick, timer->gettick()) < 2000) {
+ if ((flag & 4) != 0 && DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0
+ && DIFF_TICK(ud->canmove_tick, timer->gettick()) < 2000) {
// Delay walking command. [Skotlex]
- timer->add(ud->canmove_tick+1, unit->delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF));
- return 1;
+ timer->add(ud->canmove_tick + 1, unit->delay_walk_toxy_timer, bl->id,
+ (intptr_t)MakeDWord((uint16)x, (uint16)y));
+ return 0;
}
- if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit->can_move(bl)))
- return 0;
+ if ((flag & 2) == 0 && ((status_get_mode(bl) & MD_CANMOVE) == 0 || unit->can_move(bl) == 0))
+ return 1;
- ud->state.walk_easy = flag&1;
+ ud->state.walk_easy = flag & 1;
ud->to_x = x;
ud->to_y = y;
unit->stop_attack(bl); //Sets target to 0
+ if ((flag & 8) == 0) // Stepaction might be delayed due to occupied cell
+ unit->stop_stepaction(bl); // unit->walktoxy removes any remembered stepaction and resets ud->target_to
sc = status->get_sc(bl);
- if( sc ) {
- if( sc->data[SC_CONFUSION] || sc->data[SC__CHAOS] ) //Randomize the target position
+ if (sc != NULL) {
+ if (sc->data[SC_CONFUSION] != NULL || sc->data[SC__CHAOS] != NULL) // Randomize the target position
map->random_dir(bl, &ud->to_x, &ud->to_y);
- if( sc->data[SC_COMBOATTACK] )
+ if (sc->data[SC_COMBOATTACK] != NULL)
status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER);
}
- if(ud->walktimer != 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
- // Call a function from a timer unit->walktoxy_sub
+ // Call a function from a timer unit->walk_toxy_sub
ud->state.change_walk_target = 1;
- return 1;
+ return 0;
}
- return unit->walktoxy_sub(bl);
+ return unit->walk_toxy_sub(bl);
}
-//To set Mob's CHASE/FOLLOW states (shouldn't be done if there's no path to reach)
-static inline void set_mobstate(struct block_list* bl, int flag)
+/**
+ * Sets CHASE / FOLLOW states, in case bl is a mob.
+ * WARNING: This shouldn't be done if there's no path to reach
+ * @param bl: block_list of mob
+ */
+static inline void set_mobstate(struct block_list *bl)
{
- struct mob_data* md = BL_CAST(BL_MOB,bl);
+ struct mob_data* md = BL_CAST(BL_MOB, bl);
- if( md && flag )
- md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH;
+ if (md != NULL) {
+ if (md->state.aggressive != 0)
+ md->state.skillstate = MSS_FOLLOW;
+ else
+ md->state.skillstate = MSS_RUSH;
+ }
}
-int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) {
+/**
+ * Timer used for when a unit can't walk towards its target yet due to it's canmove_tick,
+ * keeps retrying until it works or target changes.
+ * @param tid: Timer ID, unused
+ * @param tick: Tick, unused
+ * @param id: ID of block_list to execute the action
+ * @param data: ID of block_list to walk towards
+ * @return 0: success, 1: failure
+ */
+static int unit_walktobl_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl = map->id2bl(id);
- struct unit_data *ud = bl?unit->bl2ud(bl):NULL;
-
- if (ud && ud->walktimer == INVALID_TIMER && ud->target == data) {
- if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting?
- timer->add(ud->canmove_tick+1, unit->walktobl_sub, id, data);
- else if (unit->can_move(bl)) {
- if (unit->walktoxy_sub(bl))
- set_mobstate(bl, ud->state.attack_continue);
- }
+ if (bl == NULL)
+ return 1;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
+
+ if (ud->walktimer == INVALID_TIMER && ud->target == data) {
+ if (DIFF_TICK(ud->canmove_tick, tick) > 0) // Keep waiting?
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, id, data);
+ else if (unit->can_move(bl) != 0 && unit->walk_toxy_sub(bl) == 0 && ud->state.attack_continue != 0)
+ set_mobstate(bl);
}
return 0;
}
// Chases a tbl. If the flag&1, use hard-path seek,
// if flag&2, start attacking upon arrival within range, otherwise just walk to that character.
-int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag)
+static int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag)
{
struct unit_data *ud = NULL;
struct status_change *sc = NULL;
@@ -624,23 +722,27 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
if(ud->walktimer != INVALID_TIMER) {
ud->state.change_walk_target = 1;
- set_mobstate(bl, flag&2);
+ if ((flag & 2) != 0)
+ set_mobstate(bl);
return 1;
}
if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0) {
//Can't move, wait a bit before invoking the movement.
- timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, bl->id, ud->target);
return 1;
}
if(!unit->can_move(bl))
return 0;
- if (unit->walktoxy_sub(bl)) {
- set_mobstate(bl, flag&2);
+ if (unit->walk_toxy_sub(bl) == 0) {
+ if ((flag & 2) != 0)
+ set_mobstate(bl);
+
return 1;
}
+
return 0;
}
@@ -649,22 +751,29 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
* 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;
+static void unit_run_hit(struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type)
+{
+ int lv;
+ struct unit_data *ud;
+ Assert_retv(type >= 0 && type < SC_MAX);
+ lv = sc->data[type]->val1;
//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);
+ clif->sc_load(bl, bl->id, AREA, status->get_sc_icon(SC_TING), 0, 0, 0);
+ ud = unit->bl2ud(bl);
+ nullpo_retv(ud);
//Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
- unit->bl2ud(bl)->state.running = 0;
+ ud->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);
+ if (type == SC_RUN) {
+ if (lv > 0)
+ 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);
- } else if( sd ) {
+ clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_TING));
+ } else if (sd) {
clif->fixpos(bl);
skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL);
}
@@ -677,7 +786,8 @@ void unit_run_hit( struct block_list *bl, struct status_change *sc, struct map_s
* @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 ) {
+static 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 i;
@@ -719,14 +829,14 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type
return false;
}
- if( unit->walktoxy(bl, to_x, to_y, 1) )
+ if (unit->walk_toxy(bl, to_x, to_y, 1) == 0)
return true;
//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));
+ } while (--i > 0 && unit->walk_toxy(bl, to_x, to_y, 1) != 0);
if ( i == 0 ) {
unit->run_hit(bl, sc, sd, type);
@@ -737,17 +847,23 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type
}
//Makes bl attempt to run dist cells away from target. Uses hard-paths.
-int unit_escape(struct block_list *bl, struct block_list *target, short dist) {
- uint8 dir = map->calc_dir(target, bl->x, bl->y);
+static int unit_escape(struct block_list *bl, struct block_list *target, short dist)
+{
+ nullpo_ret(bl);
+ enum unit_dir dir = map->calc_dir(target, bl->x, bl->y);
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
while (dist > 0 && map->getcell(bl->m, bl, bl->x + dist * dirx[dir], bl->y + dist * diry[dir], CELL_CHKNOREACH))
dist--;
- return ( dist > 0 && unit->walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) );
+ if (dist > 0 && unit->walk_toxy(bl, bl->x + dist * dirx[dir], bl->y + dist * diry[dir], 0) == 0)
+ return 1;
+ else
+ return 0;
}
//Instant warp function.
-int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) {
+static int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath)
+{
short dx,dy;
- uint8 dir;
struct unit_data *ud = NULL;
struct map_session_data *sd = NULL;
@@ -766,7 +882,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
ud->to_x = dst_x;
ud->to_y = dst_y;
- dir = map->calc_dir(bl, dst_x, dst_y);
+ enum unit_dir dir = map->calc_dir(bl, dst_x, dst_y);
ud->dir = dir;
dx = dst_x - bl->x;
@@ -790,7 +906,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
} else
npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);
- if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
+ if (sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > PET_INTIMACY_NONE)
{ // Check if pet needs to be teleported. [Skotlex]
int flag = 0;
struct block_list* pbl = &sd->pd->bl;
@@ -808,12 +924,18 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
return 1;
}
-int unit_setdir(struct block_list *bl,unsigned char dir)
+/**
+ * Sets the facing direction of a unit
+ * @param bl: unit to modify
+ * @param dir: the facing direction @see enum unit_dir
+ * @return 0: success, 1: failure
+ */
+static int unit_set_dir(struct block_list *bl, enum unit_dir dir)
{
- struct unit_data *ud;
- nullpo_ret(bl );
- ud = unit->bl2ud(bl);
- if (!ud) return 0;
+ nullpo_retr(1, bl);
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
ud->dir = dir;
if (bl->type == BL_PC)
BL_UCAST(BL_PC, bl)->head_dir = 0;
@@ -821,14 +943,20 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
return 0;
}
-uint8 unit_getdir(struct block_list *bl) {
- struct unit_data *ud;
- nullpo_ret(bl);
+/**
+ * Get the facing direction of a unit
+ * @param bl: unit to request data from
+ * @return the facing direction @see enum unit_dir
+ */
+static enum unit_dir unit_getdir(const struct block_list *bl)
+{
+ nullpo_retr(UNIT_DIR_NORTH, bl);
- if( bl->type == BL_NPC )
+ if (bl->type == BL_NPC)
return BL_UCCAST(BL_NPC, bl)->dir;
- ud = unit->bl2ud(bl);
- if (!ud) return 0;
+ const struct unit_data *ud = unit->cbl2ud(bl);
+ if (ud == NULL)
+ return UNIT_DIR_NORTH;
return ud->dir;
}
@@ -836,7 +964,7 @@ uint8 unit_getdir(struct block_list *bl) {
// map cell restrictions are respected.
// flag:
// &1 Do not send position update packets.
-int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
+static int unit_blown(struct block_list *bl, int dx, int dy, int count, int flag)
{
if(count) {
struct map_session_data* sd;
@@ -902,7 +1030,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
//Warps a unit/ud to a given map/position.
//In the case of players, pc->setpos is used.
//it respects the no warp flags, so it is safe to call this without doing nowarpto/nowarp checks.
-int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
+static int unit_warp(struct block_list *bl, short m, short x, short y, enum clr_type type)
{
struct unit_data *ud;
nullpo_ret(bl);
@@ -941,7 +1069,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
return 2;
}
- } else if (map->getcell(m, bl, x, y, CELL_CHKNOREACH)) {
+ } else if (bl->type != BL_NPC && map->getcell(m, bl, x, y, CELL_CHKNOREACH)) {
//Invalid target cell
ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map->list[m].name, x,y);
@@ -978,7 +1106,8 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
* Flag values: @see unit_stopwalking_flag.
* Upper bytes may be used for other purposes depending on the unit type.
*------------------------------------------*/
-int unit_stop_walking(struct block_list *bl, int flag) {
+static int unit_stop_walking(struct block_list *bl, int flag)
+{
struct unit_data *ud;
const struct TimerData* td;
int64 tick;
@@ -991,7 +1120,7 @@ int unit_stop_walking(struct block_list *bl, int flag) {
//timer->delete function does not messes with it. If the function's
//behavior changes in the future, this code could break!
td = timer->get(ud->walktimer);
- timer->delete(ud->walktimer, unit->walktoxy_timer);
+ timer->delete(ud->walktimer, unit->walk_toxy_timer);
ud->walktimer = INVALID_TIMER;
ud->state.change_walk_target = 0;
tick = timer->gettick();
@@ -999,7 +1128,7 @@ int unit_stop_walking(struct block_list *bl, int flag) {
|| (flag&STOPWALKING_FLAG_NEXTCELL && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell
) {
ud->walkpath.path_len = ud->walkpath.path_pos+1;
- unit->walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
+ unit->walk_toxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
}
if(flag&STOPWALKING_FLAG_FIXPOS)
@@ -1020,16 +1149,22 @@ int unit_stop_walking(struct block_list *bl, int flag) {
return 1;
}
-int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
+static int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
{
- return unit->skilluse_id2(
- src, target_id, skill_id, skill_lv,
- skill->cast_fix(src, skill_id, skill_lv),
- skill->get_castcancel(skill_id)
- );
+ int casttime = skill->cast_fix(src, skill_id, skill_lv);
+ int castcancel = skill->get_castcancel(skill_id);
+ int ret = unit->skilluse_id2(src, target_id, skill_id, skill_lv, casttime, castcancel);
+ struct map_session_data *sd = BL_CAST(BL_PC, src);
+
+ if (sd != NULL && ret == 0)
+ pc->autocast_clear(sd); // Error in unit_skilluse_id2().
+ else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
+ skill->validate_autocast_data(sd, skill_id, skill_lv);
+
+ return ret;
}
-int unit_is_walking(struct block_list *bl)
+static int unit_is_walking(struct block_list *bl)
{
struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(bl);
@@ -1040,7 +1175,8 @@ int unit_is_walking(struct block_list *bl)
/*==========================================
* Determines if the bl can move based on status changes. [Skotlex]
*------------------------------------------*/
-int unit_can_move(struct block_list *bl) {
+static int unit_can_move(struct block_list *bl)
+{
struct map_session_data *sd;
struct unit_data *ud;
struct status_change *sc;
@@ -1053,8 +1189,18 @@ int unit_can_move(struct block_list *bl) {
if (!ud)
return 0;
- if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc->checkskill(sd, SA_FREECAST) || skill->get_inf2(ud->skill_id)&INF2_GUILD_SKILL))
- return 0; // prevent moving while casting
+ if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK) {
+ // Prevent moving while casting
+ if (sd == NULL)
+ return 0; // Only players are affected by SA_FREECAST and similar
+ if ((skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0) {
+ // Skills with an explicit free cast setting always allow walking regardless of SA_FREECAST
+ if ((skill->get_inf2(ud->skill_id) & INF2_GUILD_SKILL) != 0)
+ return 0; // SA_FREECAST doesn't affect guild skills
+ if (pc->checkskill(sd, SA_FREECAST) == 0)
+ return 0; // SA_FREECAST not available
+ }
+ }
if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0)
return 0;
@@ -1062,8 +1208,9 @@ int unit_can_move(struct block_list *bl) {
if (sd && (
pc_issit(sd) ||
sd->state.vending ||
+ sd->state.prevend ||
sd->state.buyingstore ||
- sd->state.blockedmove
+ sd->block_action.move
))
return 0; //Can't move
@@ -1101,6 +1248,7 @@ int unit_can_move(struct block_list *bl) {
|| sc->data[SC_VACUUM_EXTREME]
|| (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
|| sc->data[SC_NETHERWORLD]
+ || sc->data[SC_SUHIDE]
|| (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
|| (sc->data[SC_CLOAKING] && sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) //Need wall at level 1-2
|| (
@@ -1140,11 +1288,12 @@ int unit_can_move(struct block_list *bl) {
* Resume running after a walk delay
*------------------------------------------*/
-int unit_resume_running(int tid, int64 tick, int id, intptr_t data) {
-
+static int unit_resume_running(int tid, int64 tick, int id, intptr_t data)
+{
struct unit_data *ud = (struct unit_data *)data;
struct map_session_data *sd = map->id2sd(id);
+ nullpo_ret(ud);
if(sd && pc_isridingwug(sd))
clif->skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv,
sc_start4(ud->bl,ud->bl,status->skill2sc(RA_WUGDASH),100,ud->skill_lv,unit->getdir(ud->bl),0,0,1));
@@ -1164,10 +1313,12 @@ int unit_resume_running(int tid, int64 tick, int id, intptr_t data) {
* if type is 0, this is a damage induced delay: if previous delay is active, do not change it.
* if type is 1, this is a skill induced delay: walk-delay may only be increased, not decreased.
*------------------------------------------*/
-int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
+static int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type)
+{
struct unit_data *ud = unit->bl2ud(bl);
if (delay <= 0 || !ud) return 0;
+ nullpo_ret(bl);
if (type) {
//Bosses can ignore skill induced walkdelay (but not damage induced)
if (bl->type == BL_MOB && (BL_UCCAST(BL_MOB, bl)->status.mode&MD_BOSS))
@@ -1196,14 +1347,16 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
} else {
unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL);
if (ud->target)
- timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, bl->id, ud->target);
}
}
}
return 1;
}
-int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) {
+//-------------- stop here
+static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
+{
struct unit_data *ud;
struct status_data *tstatus;
struct status_change *sc;
@@ -1220,6 +1373,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
ud = unit->bl2ud(src);
if(ud == NULL) return 0;
+
sc = status->get_sc(src);
if (sc && !sc->count)
sc = NULL; //Unneeded
@@ -1268,7 +1422,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
return 0;
p_sd = map->charid2sd(sd->status.partner_id);
if (p_sd == NULL) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
target = &p_sd->bl;
@@ -1277,11 +1431,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case GC_WEAPONCRUSH:
if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING ) {
if( (target=map->id2bl(sc->data[SC_COMBOATTACK]->val2)) == NULL ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0, 0);
return 0;
}
} else {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0, 0);
return 0;
}
break;
@@ -1292,6 +1446,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (src->type==BL_HOM)
switch(skill_id) { //Homun-auto-target skills.
+ case HVAN_CHAOTIC:
+ target_id = ud->target; // Choose attack target for now
+ target = map->id2bl(target_id);
+ if (target != NULL)
+ break;
+ FALLTHROUGH // Attacking nothing, choose master as default target instead
case HLIF_HEAL:
case HLIF_AVOID:
case HAMI_DEFENCE:
@@ -1340,13 +1500,13 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (sd) {
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);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
switch (skill_id){
case SA_CASTCANCEL:
- if (ud->skill_id != skill_id){
+ if (ud->skill_id != skill_id) {
sd->skill_id_old = ud->skill_id;
sd->skill_lv_old = ud->skill_lv;
}
@@ -1354,14 +1514,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case BD_ENCORE:
//Prevent using the dance skill if you no longer have the skill in your tree.
if (!sd->skill_id_dance || pc->checkskill(sd, sd->skill_id_dance) <= 0){
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
sd->skill_id_old = skill_id;
break;
case WL_WHITEIMPRISON:
if (battle->check_target(src, target, BCT_SELF | BCT_ENEMY) < 0) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0, 0);
return 0;
}
break;
@@ -1374,22 +1534,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
}
- if (src->type == BL_HOM) {
- // In case of homunuculus, set the sd to the homunculus' master, as needed below
- struct block_list *master = battle->get_master(src);
- if (master)
- sd = map->id2sd(master->id);
- }
-
- if (sd) {
- /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
-#if 0
- if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv))
-#else
- if (!skill->check_condition_castbegin(sd, skill_id, skill_lv))
-#endif
- return 0;
- }
+ if (sd != NULL && skill->check_condition_castbegin(sd, skill_id, skill_lv) == 0)
+ return 0;
if (src->type == BL_MOB) {
const struct mob_data *src_md = BL_UCCAST(BL_MOB, src);
@@ -1416,7 +1562,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
ud->target_to = target_id;
ud->stepskill_id = skill_id;
ud->stepskill_lv = skill_lv;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
//Check range when not using skill on yourself or is a combo-skill during attack
@@ -1428,7 +1574,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
} else if( src->type == BL_MER && skill_id == MA_REMOVETRAP ) {
if( !battle->check_range(battle->get_master(src), target, range + 1) )
return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O
- } else if( !battle->check_range(src, target, range + (skill_id == RG_CLOSECONFINE?0:2)) ) {
+ } else if (!battle->check_range(src, target, range)) {
return 0; // Arrow-path check failed.
}
}
@@ -1469,15 +1615,15 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (i == count) {
ARR_FIND(0, count, i, sd->devotion[i] == 0);
if(i == count) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0; // Can't cast on other characters when limit is reached
}
}
}
break;
case AB_CLEARANCE:
- if( target->type != BL_MOB && battle->check_target(src,target,BCT_PARTY) <= 0 && sd ) {
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0);
+ if (target->type != BL_MOB && battle->check_target(src, target, BCT_PARTY) <= 0 && sd) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0, 0);
return 0;
}
break;
@@ -1511,7 +1657,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
break;
case GD_EMERGENCYCALL: //Emergency Call double cast when the user has learned Leap [Daegaladh]
- if( sd && pc->checkskill(sd,TK_HIGHJUMP) )
+ if (sd && (pc->checkskill(sd,TK_HIGHJUMP) || pc->checkskill(sd,SU_LOPE) >= 3))
casttime *= 2;
break;
case RA_WUGDASH:
@@ -1536,7 +1682,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
break;
case NC_DISJOINT:
- if( target->type == BL_PC ){
+ if (target->type == BL_PC) {
struct mob_data *md;
if( (md = map->id2md(target->id)) && md->master_id != src->id )
casttime <<= 1;
@@ -1572,8 +1718,11 @@ 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, STOPWALKING_FLAG_FIXPOS);// even though this is not how official works but this will do the trick. bugreport:6829
+ if (sd != NULL && sd->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
+ casttime = 0;
+
// 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);
+ clif->useskill(src, src->id, target_id, 0,0, skill_id, skill_lv, casttime);
if( casttime > 0 || temp )
{
if (sd != NULL && target->type == BL_MOB) {
@@ -1607,7 +1756,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if( casttime <= 0 )
ud->state.skillcastcancel = 0;
- if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) )
+ if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
if( sd )
{
@@ -1626,26 +1775,35 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if( casttime > 0 ) {
if (src->id != target->id) // self-targeted skills shouldn't show different direction
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 );
- if( sd && (pc->checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) )
+ if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
} else
skill->castend_id(ud->skilltimer,tick,src->id,0);
+ if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL)
+ sd->canlog_tick = timer->gettick();
+
return 1;
}
-int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv)
+static int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv)
{
- return unit->skilluse_pos2(
- src, skill_x, skill_y, skill_id, skill_lv,
- skill->cast_fix(src, skill_id, skill_lv),
- skill->get_castcancel(skill_id)
- );
+ int casttime = skill->cast_fix(src, skill_id, skill_lv);
+ int castcancel = skill->get_castcancel(skill_id);
+ int ret = unit->skilluse_pos2(src, skill_x, skill_y, skill_id, skill_lv, casttime, castcancel);
+ struct map_session_data *sd = BL_CAST(BL_PC, src);
+
+ if (sd != NULL && ret == 0)
+ pc->autocast_clear(sd); // Error in unit_skilluse_pos2().
+ else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
+ skill->validate_autocast_data(sd, skill_id, skill_lv);
+
+ return ret;
}
-int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
+static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
{
struct map_session_data *sd = NULL;
struct unit_data *ud = NULL;
@@ -1687,7 +1845,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
if (map->getcell(src->m, src, skill_x, skill_y, CELL_CHKWALL)) {
// can't cast ground targeted spells on wall cells
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
return 0;
}
@@ -1713,7 +1871,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
ud->target_to = (skill_x + skill_y*md->xs);
ud->stepskill_id = skill_id;
ud->stepskill_lv = skill_lv;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) {
@@ -1737,7 +1895,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
}
ud->state.skillcastcancel = castcancel&&casttime>0?1:0;
- if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) )
+ if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
#if 0
if (sd) {
@@ -1767,25 +1925,33 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
}
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
+
+ if (sd != NULL && sd->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
+ casttime = 0;
+
// in official this is triggered even if no cast time.
- clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime);
+ clif->useskill(src, src->id, 0, skill_x, skill_y, skill_id, skill_lv, casttime);
if( casttime > 0 ) {
- unit->setdir(src, map->calc_dir(src, skill_x, skill_y));
+ unit->set_dir(src, map->calc_dir(src, skill_x, skill_y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 );
- if ( (sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK ) {
+ if ((sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
}
} else {
ud->skilltimer = INVALID_TIMER;
skill->castend_pos(ud->skilltimer,tick,src->id,0);
}
+
+ if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL)
+ sd->canlog_tick = timer->gettick();
+
return 1;
}
/*========================================
* update a block's attack target
*----------------------------------------*/
-int unit_set_target(struct unit_data* ud, int target_id)
+static int unit_set_target(struct unit_data *ud, int target_id)
{
nullpo_ret(ud);
@@ -1794,7 +1960,7 @@ int unit_set_target(struct unit_data* ud, int target_id)
struct block_list* target;
if (ud->target && (target = map->id2bl(ud->target)) != NULL && (ux = unit->bl2ud(target)) != NULL && ux->target_count > 0)
--ux->target_count;
- if (target_id && (target = map->id2bl(target_id)) != NULL && (ux = unit->bl2ud(target)) != NULL)
+ if (target_id && (target = map->id2bl(target_id)) != NULL && (ux = unit->bl2ud(target)) != NULL && ux->target_count < UCHAR_MAX)
++ux->target_count;
}
@@ -1806,7 +1972,7 @@ int unit_set_target(struct unit_data* ud, int target_id)
* Stop a unit's attacks
* @param bl: Object to stop
*/
-void unit_stop_attack(struct block_list *bl)
+static void unit_stop_attack(struct block_list *bl)
{
struct unit_data *ud;
nullpo_retv(bl);
@@ -1828,7 +1994,7 @@ void unit_stop_attack(struct block_list *bl)
* Stop a unit's step action
* @param bl: Object to stop
*/
-void unit_stop_stepaction(struct block_list *bl)
+static void unit_stop_stepaction(struct block_list *bl)
{
struct unit_data *ud;
nullpo_retv(bl);
@@ -1845,14 +2011,15 @@ void unit_stop_stepaction(struct block_list *bl)
return;
//Clear timer
- timer->delete(ud->steptimer, unit->step_timer);
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
//Means current target is unattackable. For now only unlocks mobs.
-int unit_unattackable(struct block_list *bl)
+static int unit_unattackable(struct block_list *bl)
{
struct unit_data *ud = unit->bl2ud(bl);
+ nullpo_ret(bl);
if (ud) {
ud->state.attack_continue = 0;
ud->state.step_attack = 0;
@@ -1870,11 +2037,13 @@ int unit_unattackable(struct block_list *bl)
* Attack request
* If type is an ongoing attack
*------------------------------------------*/
-int unit_attack(struct block_list *src,int target_id,int continuous) {
+static int unit_attack(struct block_list *src, int target_id, int continuous)
+{
struct block_list *target;
struct unit_data *ud;
int range;
+ nullpo_ret(src);
nullpo_ret(ud = unit->bl2ud(src));
target = map->id2bl(target_id);
@@ -1885,8 +2054,10 @@ int unit_attack(struct block_list *src,int target_id,int continuous) {
if (src->type == BL_PC) {
struct map_session_data *sd = BL_UCAST(BL_PC, src);
- if( target->type == BL_NPC ) { // monster npcs [Valaris]
- npc->click(sd, BL_UCAST(BL_NPC, target)); // submitted by leinsirk10 [Celest]
+ if (target->type == BL_NPC) { // monster npcs [Valaris]
+ if (sd->block_action.npc == 0) { // *pcblock script command
+ npc->click(sd, BL_UCAST(BL_NPC, target)); // submitted by leinsirk10 [Celest]
+ }
return 0;
}
if( pc_is90overweight(sd) || pc_isridingwug(sd) ) { // overweight or mounted on warg - stop attacking
@@ -1924,7 +2095,7 @@ int unit_attack(struct block_list *src,int target_id,int continuous) {
ud->target_to = ud->target;
ud->stepskill_id = 0;
ud->stepskill_lv = 0;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
if(DIFF_TICK(ud->attackabletime, timer->gettick()) > 0)
@@ -1938,10 +2109,11 @@ int unit_attack(struct block_list *src,int target_id,int continuous) {
//Cancels an ongoing combo, resets attackable time and restarts the
//attack timer to resume attacking after amotion time. [Skotlex]
-int unit_cancel_combo(struct block_list *bl)
+static int unit_cancel_combo(struct block_list *bl)
{
struct unit_data *ud;
+ nullpo_ret(bl);
if (!status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER))
return 0; //Combo wasn't active.
@@ -1960,7 +2132,7 @@ int unit_cancel_combo(struct block_list *bl)
/*==========================================
*
*------------------------------------------*/
-bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
+static bool unit_can_reach_pos(struct block_list *bl, int x, int y, int easy)
{
nullpo_retr(false, bl);
@@ -1973,7 +2145,7 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
/*==========================================
*
*------------------------------------------*/
-bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y)
+static bool unit_can_reach_bl(struct block_list *bl, struct block_list *tbl, int range, int easy, short *x, short *y)
{
short dx,dy;
struct walkpath_data wpd;
@@ -2012,7 +2184,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
#ifdef OFFICIAL_WALKPATH
if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, tbl->x-dx, tbl->y-dy, CELL_CHKNOPASS) // Check if there is an obstacle between
- && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
&& (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
return false;
#endif
@@ -2024,14 +2196,13 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
/*==========================================
* Calculates position of Pet/Mercenary/Homunculus/Elemental
*------------------------------------------*/
-int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
+static int unit_calc_pos(struct block_list *bl, int tx, int ty, enum unit_dir dir)
{
int dx, dy, x, y;
struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(ud);
- if(dir > 7)
- return 1;
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
ud->to_x = tx;
ud->to_y = ty;
@@ -2048,7 +2219,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
if (!unit->can_reach_pos(bl, x, y, 0)) {
int i;
for (i = 0; i < 12; i++) {
- int k = rnd()%8; // Pick a Random Dir
+ enum unit_dir k = rnd() % UNIT_DIR_MAX; // Pick a Random Dir
dx = -dirx[k] * 2;
dy = -diry[k] * 2;
x = tx + dx;
@@ -2078,7 +2249,8 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
/*==========================================
* Continuous Attack (function timer)
*------------------------------------------*/
-int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
+static int unit_attack_timer_sub(struct block_list *src, int tid, int64 tick)
+{
struct block_list *target;
struct unit_data *ud;
struct status_data *sstatus;
@@ -2117,13 +2289,13 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
return 0;
}
- if( ud->skilltimer != INVALID_TIMER && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) )
+ if (ud->skilltimer != INVALID_TIMER && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0)))
return 0; // can't attack while casting
- if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) )
+ if (!battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick, tick) > 0 && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0)))
{ // attacking when under cast delay has restrictions:
if( tid == INVALID_TIMER ) { //requested attack.
- if(sd) clif->skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0);
+ if(sd) clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return 0;
}
//Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex]
@@ -2163,6 +2335,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
//Non-players use the sync packet on the walk timer. [Skotlex]
if (tid == INVALID_TIMER && sd) clif->fixpos(src);
+ map->freeblock_lock();
if( DIFF_TICK(ud->attackabletime,tick) <= 0 ) {
if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) {
ud->dir = map->calc_dir(src, target->x,target->y );
@@ -2172,8 +2345,10 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
if(md) {
//First attack is always a normal attack
if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) {
- if (mob->skill_use(md,tick,-1))
+ if (mob->skill_use(md, tick, -1) == 0) {
+ map->freeblock_unlock();
return 1;
+ }
} else {
// Set mob's ANGRY/BERSERK states.
md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
@@ -2185,21 +2360,23 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
map->foreachinrange(mob->linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick);
}
}
- if (src->type == BL_PET && pet->attackskill(BL_UCAST(BL_PET, src), target->id))
+ if (src->type == BL_PET && pet->attackskill(BL_UCAST(BL_PET, src), target->id)) {
+ map->freeblock_unlock();
return 1;
+ }
- map->freeblock_lock();
ud->attacktarget_lv = battle->weapon_attack(src,target,tick,0);
if(sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support)
pet->target_check(sd,target,0);
- map->freeblock_unlock();
/**
* Applied when you're unable to attack (e.g. out of ammo)
* We should stop here otherwise timer keeps on and this happens endlessly
**/
- if( ud->attacktarget_lv == ATK_NONE )
+ if (ud->attacktarget_lv == ATK_NONE) {
+ map->freeblock_unlock();
return 1;
+ }
ud->attackabletime = tick + sstatus->adelay;
// You can't move if you can't attack neither.
@@ -2208,16 +2385,21 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
}
if(ud->state.attack_continue) {
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
if( src->type == BL_PC )
pc->update_idle_time(sd, BCIDLE_ATTACK);
ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0);
}
+ map->freeblock_unlock();
+
+ if (sd != NULL && battle_config.prevent_logout_trigger & PLT_ATTACK)
+ sd->canlog_tick = timer->gettick();
return 1;
}
-int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) {
+static int unit_attack_timer(int tid, int64 tick, int id, intptr_t data)
+{
struct block_list *bl;
bl = map->id2bl(id);
if(bl && unit->attack_timer_sub(bl, tid, tick) == 0)
@@ -2230,7 +2412,7 @@ int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) {
* flag&1: Cast-Cancel invoked.
* flag&2: Cancel only if skill is can be cancel.
*------------------------------------------*/
-int unit_skillcastcancel(struct block_list *bl,int type)
+static int unit_skillcastcancel(struct block_list *bl, int type)
{
struct map_session_data *sd = NULL;
struct unit_data *ud = unit->bl2ud( bl);
@@ -2269,7 +2451,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
ud->skilltimer = INVALID_TIMER;
- if( sd && pc->checkskill(sd,SA_FREECAST) > 0 )
+ if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
if( sd ) {
@@ -2288,12 +2470,20 @@ int unit_skillcastcancel(struct block_list *bl,int type)
}
// unit_data initialization process
-void unit_dataset(struct block_list *bl) {
- struct unit_data *ud;
- nullpo_retv(ud = unit->bl2ud(bl));
+static void unit_dataset(struct block_list *bl)
+{
+ struct unit_data *ud = unit->bl2ud(bl);
+ nullpo_retv(ud);
+
+ unit->init_ud(ud);
+ ud->bl = bl;
+}
+
+static void unit_init_ud(struct unit_data *ud)
+{
+ nullpo_retv(ud);
- memset( ud, 0, sizeof( struct unit_data) );
- ud->bl = bl;
+ memset (ud, 0, sizeof(struct unit_data));
ud->walktimer = INVALID_TIMER;
ud->skilltimer = INVALID_TIMER;
ud->attacktimer = INVALID_TIMER;
@@ -2306,7 +2496,7 @@ void unit_dataset(struct block_list *bl) {
/*==========================================
* Counts the number of units attacking 'bl'
*------------------------------------------*/
-int unit_counttargeted(struct block_list* bl)
+static int unit_counttargeted(struct block_list *bl)
{
struct unit_data* ud;
if (bl && (ud = unit->bl2ud(bl)) != NULL)
@@ -2317,7 +2507,8 @@ int unit_counttargeted(struct block_list* bl)
/*==========================================
*
*------------------------------------------*/
-int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2) {
+static int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2)
+{
nullpo_ret(target);
if(damage+damage2 <= 0)
@@ -2329,7 +2520,7 @@ int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay
/*==========================================
* To change the size of the char (player or mob only)
*------------------------------------------*/
-int unit_changeviewsize(struct block_list *bl,short size)
+static int unit_changeviewsize(struct block_list *bl, short size)
{
nullpo_ret(bl);
@@ -2353,9 +2544,11 @@ int unit_changeviewsize(struct block_list *bl,short size)
* Otherwise it is assumed bl is being warped.
* On-Kill specific stuff is not performed here, look at status->damage for that.
*------------------------------------------*/
-int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) {
+static int unit_remove_map(struct block_list *bl, enum clr_type clrtype, const char *file, int line, const char *func)
+{
struct unit_data *ud = unit->bl2ud(bl);
struct status_change *sc = status->get_sc(bl);
+ nullpo_ret(bl);
nullpo_ret(ud);
if(bl->prev == NULL)
@@ -2415,6 +2608,8 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); //callme before warp
status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER);
+ status_change_end(bl, SC_SUHIDE, INVALID_TIMER);
+ status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
}
if (bl->type&(BL_CHAR|BL_PET)) {
@@ -2433,7 +2628,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER);
}
//Leave/reject all invitations.
- if(sd->chatID)
+ if (sd->chat_id != 0)
chat->leave(sd, false);
if(sd->trade_partner)
trade->cancel(sd);
@@ -2535,7 +2730,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
case BL_PET:
{
struct pet_data *pd = BL_UCAST(BL_PET, bl);
- if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) {
+ if (pd->pet.intimate <= PET_INTIMACY_NONE && !(pd->msd && !pd->msd->state.active)) {
//If logging out, this is deleted on unit->free
clif->clearunit_area(bl,clrtype);
map->delblock(bl);
@@ -2595,8 +2790,9 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
return 1;
}
-void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
+static void unit_remove_map_pc(struct map_session_data *sd, enum clr_type clrtype)
{
+ nullpo_retv(sd);
unit->remove_map(&sd->bl,clrtype,ALC_MARK);
//CLR_RESPAWN is the warp from logging out, CLR_TELEPORT is the warp from teleporting, but pets/homunc need to just 'vanish' instead of showing the warping animation.
@@ -2612,8 +2808,9 @@ void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
unit->remove_map(&sd->ed->bl, clrtype, ALC_MARK);
}
-void unit_free_pc(struct map_session_data *sd)
+static void unit_free_pc(struct map_session_data *sd)
{
+ nullpo_retv(sd);
if (sd->pd) unit->free(&sd->pd->bl,CLR_OUTSIGHT);
if (sd->hd) unit->free(&sd->hd->bl,CLR_OUTSIGHT);
if (sd->md) unit->free(&sd->md->bl,CLR_OUTSIGHT);
@@ -2625,8 +2822,10 @@ void unit_free_pc(struct map_session_data *sd)
* Function to free all related resources to the bl
* if unit is on map, it is removed using the clrtype specified
*------------------------------------------*/
-int unit_free(struct block_list *bl, clr_type clrtype) {
+static int unit_free(struct block_list *bl, enum clr_type clrtype)
+{
struct unit_data *ud = unit->bl2ud( bl );
+ nullpo_ret(bl);
nullpo_ret(ud);
map->freeblock_lock();
@@ -2658,6 +2857,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
party->send_logout(sd);
guild->send_memberinfoshort(sd,0);
+ clan->member_offline(sd);
pc->cleareventtimer(sd);
pc->inventory_rental_clear(sd);
pc->delspiritball(sd,sd->spiritball,1);
@@ -2689,7 +2889,13 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
aFree(sd->instance);
sd->instance = NULL;
}
+ VECTOR_CLEAR(sd->channels);
VECTOR_CLEAR(sd->script_queues);
+ VECTOR_CLEAR(sd->achievement); // Achievement [Smokexyz/Hercules]
+ VECTOR_CLEAR(sd->storage.item);
+ VECTOR_CLEAR(sd->hatEffectId);
+ VECTOR_CLEAR(sd->title_ids); // Title [Dastgir/Hercules]
+ sd->storage.received = false;
if( sd->quest_log != NULL ) {
aFree(sd->quest_log);
sd->quest_log = NULL;
@@ -2738,7 +2944,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
aFree (pd->loot);
pd->loot = NULL;
}
- if (pd->pet.intimate > 0) {
+ if (pd->pet.intimate > PET_INTIMACY_NONE) {
intif->save_petdata(pd->pet.account_id,&pd->pet);
} else {
//Remove pet.
@@ -2870,49 +3076,55 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
return 0;
}
-int do_init_unit(bool minimal) {
+static int do_init_unit(bool minimal)
+{
if (minimal)
return 0;
timer->add_func_list(unit->attack_timer, "unit_attack_timer");
- timer->add_func_list(unit->walktoxy_timer,"unit_walktoxy_timer");
- timer->add_func_list(unit->walktobl_sub, "unit_walktobl_sub");
- timer->add_func_list(unit->delay_walktoxy_timer,"unit_delay_walktoxy_timer");
- timer->add_func_list(unit->step_timer,"unit_step_timer");
+ timer->add_func_list(unit->walk_toxy_timer, "unit_walk_toxy_timer");
+ timer->add_func_list(unit->walktobl_timer, "unit_walktobl_timer");
+ timer->add_func_list(unit->delay_walk_toxy_timer, "unit_delay_walk_toxy_timer");
+ timer->add_func_list(unit->steptimer, "unit_steptimer");
return 0;
}
-int do_final_unit(void) {
+static int do_final_unit(void)
+{
// nothing to do
return 0;
}
-void unit_defaults(void) {
+void unit_defaults(void)
+{
unit = &unit_s;
unit->init = do_init_unit;
unit->final = do_final_unit;
/* */
unit->bl2ud = unit_bl2ud;
+ unit->cbl2ud = unit_cbl2ud;
unit->bl2ud2 = unit_bl2ud2;
+ unit->init_ud = unit_init_ud;
unit->attack_timer = unit_attack_timer;
- unit->walktoxy_timer = unit_walktoxy_timer;
- unit->walktoxy_sub = unit_walktoxy_sub;
- unit->delay_walktoxy_timer = unit_delay_walktoxy_timer;
- unit->walktoxy = unit_walktoxy;
- unit->walktobl_sub = unit_walktobl_sub;
+ unit->walk_toxy_timer = unit_walk_toxy_timer;
+ unit->walk_toxy_sub = unit_walk_toxy_sub;
+ unit->delay_walk_toxy_timer = unit_delay_walk_toxy_timer;
+ unit->walk_toxy = unit_walk_toxy;
+ unit->walktobl_timer = unit_walktobl_timer;
unit->walktobl = unit_walktobl;
unit->run = unit_run;
unit->run_hit = unit_run_hit;
unit->escape = unit_escape;
unit->movepos = unit_movepos;
- unit->setdir = unit_setdir;
+ unit->set_dir = unit_set_dir;
unit->getdir = unit_getdir;
unit->blown = unit_blown;
unit->warp = unit_warp;
+ unit->warpto_master = unit_warpto_master;
unit->stop_walking = unit_stop_walking;
unit->skilluse_id = unit_skilluse_id;
- unit->step_timer = unit_step_timer;
+ unit->steptimer = unit_steptimer;
unit->stop_stepaction = unit_stop_stepaction;
unit->is_walking = unit_is_walking;
unit->can_move = unit_can_move;
diff --git a/src/map/unit.h b/src/map/unit.h
index 0279d73c1..3f288e0d3 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
#include "map/clif.h" // clr_type
#include "map/path.h" // struct walkpath_data
#include "map/skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset
+#include "map/unitdefines.h" // enum unit_dir
#include "common/hercules.h"
struct map_session_data;
@@ -44,6 +45,7 @@ enum unit_stopwalking_flag {
struct unit_data {
struct block_list *bl;
+ char title[NAME_LENGTH];
struct walkpath_data walkpath;
struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL];
struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP];
@@ -61,11 +63,12 @@ struct unit_data {
int chaserange;
bool stepaction; //Action should be executed on step [Playtester]
int steptimer; //Timer that triggers the action [Playtester]
+ int groupId; // id of client side group (works for npc and may be other) [4144]
uint16 stepskill_id,stepskill_lv; //Remembers skill that should be casted on step [Playtester]
int64 attackabletime;
int64 canact_tick;
int64 canmove_tick;
- uint8 dir;
+ enum unit_dir dir;
unsigned char walk_count;
unsigned char target_count;
struct {
@@ -80,21 +83,17 @@ struct unit_data {
};
struct view_data {
-#ifdef __64BIT__
- uint32 class_; // FIXME: This shouldn't really depend on the architecture.
-#else // not __64BIT__
- uint16 class_;
-#endif // __64BIT__
- uint16 weapon,
+ int16 class;
+ int weapon,
shield, //Or left-hand weapon.
robe,
head_top,
head_mid,
head_bottom,
hair_style,
- hair_color,
- cloth_color,
body_style;
+ uint16 hair_color,
+ cloth_color;
char sex;
unsigned dead_sit : 2;
};
@@ -104,25 +103,28 @@ struct unit_interface {
int (*final) (void);
/* */
struct unit_data* (*bl2ud) (struct block_list *bl);
+ const struct unit_data* (*cbl2ud) (const struct block_list *bl);
struct unit_data* (*bl2ud2) (struct block_list *bl);
+ void (*init_ud) (struct unit_data *ud);
int (*attack_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*walktoxy_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*walktoxy_sub) (struct block_list *bl);
- int (*delay_walktoxy_timer) (int tid, int64 tick, int id, intptr_t data);
- 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 (*walk_toxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walk_toxy_sub) (struct block_list *bl);
+ int (*delay_walk_toxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walk_toxy) (struct block_list *bl, short x, short y, int flag);
+ int (*walktobl_timer) (int tid, int64 tick, int id, intptr_t data);
int (*walktobl) (struct block_list *bl, struct block_list *tbl, int range, int flag);
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);
- uint8 (*getdir) (struct block_list *bl);
+ int (*set_dir) (struct block_list *bl, enum unit_dir dir);
+ enum unit_dir (*getdir) (const struct block_list *bl);
int (*blown) (struct block_list *bl, int dx, int dy, int count, int flag);
- int (*warp) (struct block_list *bl, short m, short x, short y, clr_type type);
+ int (*warp) (struct block_list *bl, short m, short x, short y, enum clr_type type);
+ int (*warpto_master) (struct block_list *master_bl, struct block_list *slave_bl);
int (*stop_walking) (struct block_list *bl, int type);
int (*skilluse_id) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
- int (*step_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*steptimer) (int tid, int64 tick, int id, intptr_t data);
void (*stop_stepaction) (struct block_list *bl);
int (*is_walking) (struct block_list *bl);
int (*can_move) (struct block_list *bl);
@@ -138,17 +140,17 @@ struct unit_interface {
int (*cancel_combo) (struct block_list *bl);
bool (*can_reach_pos) (struct block_list *bl, int x, int y, int easy);
bool (*can_reach_bl) (struct block_list *bl, struct block_list *tbl, int range, int easy, short *x, short *y);
- int (*calc_pos) (struct block_list *bl, int tx, int ty, uint8 dir);
+ int (*calc_pos) (struct block_list *bl, int tx, int ty, enum unit_dir dir);
int (*attack_timer_sub) (struct block_list *src, int tid, int64 tick);
int (*skillcastcancel) (struct block_list *bl, int type);
void (*dataset) (struct block_list *bl);
int (*counttargeted) (struct block_list *bl);
int (*fixdamage) (struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2);
int (*changeviewsize) (struct block_list *bl, short size);
- int (*remove_map) (struct block_list *bl, clr_type clrtype, const char *file, int line, const char *func);
- void (*remove_map_pc) (struct map_session_data *sd, clr_type clrtype);
+ int (*remove_map) (struct block_list *bl, enum clr_type clrtype, const char *file, int line, const char *func);
+ void (*remove_map_pc) (struct map_session_data *sd, enum clr_type clrtype);
void (*free_pc) (struct map_session_data *sd);
- int (*free) (struct block_list *bl, clr_type clrtype);
+ int (*free) (struct block_list *bl, enum clr_type clrtype);
};
#ifdef HERCULES_CORE
diff --git a/src/map/unitdefines.h b/src/map/unitdefines.h
new file mode 100644
index 000000000..0ee30998c
--- /dev/null
+++ b/src/map/unitdefines.h
@@ -0,0 +1,58 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2012-2019 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_UNITDEFINES_H
+#define MAP_UNITDEFINES_H
+
+/**
+ * Used for directions, @see unit_data.dir
+ */
+enum unit_dir {
+ UNIT_DIR_UNDEFINED = -1,
+ UNIT_DIR_FIRST = 0,
+ UNIT_DIR_NORTH = 0,
+ UNIT_DIR_NORTHWEST = 1,
+ UNIT_DIR_WEST = 2,
+ UNIT_DIR_SOUTHWEST = 3,
+ UNIT_DIR_SOUTH = 4,
+ UNIT_DIR_SOUTHEAST = 5,
+ UNIT_DIR_EAST = 6,
+ UNIT_DIR_NORTHEAST = 7,
+ UNIT_DIR_MAX = 8,
+ /* IMPORTANT: Changing the order would break the above macros
+ * and several usages of directions anywhere */
+};
+
+/* Returns the opposite of the facing direction */
+#define unit_get_opposite_dir(dir) ( ((dir) + 4) % UNIT_DIR_MAX )
+
+/* Returns true when direction is diagonal/combined (ex. UNIT_DIR_NORTHWEST, UNIT_DIR_SOUTHWEST, ...) */
+#define unit_is_diagonal_dir(dir) ( ((dir) % 2) == UNIT_DIR_NORTHWEST )
+
+/* Returns true if direction equals val or the opposite direction of val */
+#define unit_is_dir_or_opposite(dir, val) ( ((dir) % 4) == (val) )
+
+/* Returns the next direction after 90° CCW on a compass */
+#define unit_get_ccw90_dir(dir) ( ((dir) + 2) % UNIT_DIR_MAX )
+
+/* Returns a random diagonal direction */
+#define unit_get_rnd_diagonal_dir() ( UNIT_DIR_NORTHWEST + 2 * (rnd() % 4) )
+
+#endif /* MAP_UNITDEFINES_H */
diff --git a/src/map/vending.c b/src/map/vending.c
index d9001f6f5..4fd009025 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,18 +40,20 @@
#include <stdio.h>
#include <string.h>
-struct vending_interface vending_s;
+static struct vending_interface vending_s;
struct vending_interface *vending;
/// Returns an unique vending shop id.
-static inline unsigned int getid(void) {
+static inline unsigned int getid(void)
+{
return vending->next_id++;
}
/*==========================================
* Close shop
*------------------------------------------*/
-void vending_closevending(struct map_session_data* sd) {
+static void vending_closevending(struct map_session_data *sd)
+{
nullpo_retv(sd);
if( sd->state.vending ) {
@@ -64,7 +66,8 @@ void vending_closevending(struct map_session_data* sd) {
/*==========================================
* Request a shop's item list
*------------------------------------------*/
-void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) {
+static void vending_vendinglistreq(struct map_session_data *sd, unsigned int id)
+{
struct map_session_data* vsd;
nullpo_retv(sd);
@@ -74,8 +77,7 @@ void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) {
return; // not vending
if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade
- // GM is not allowed to trade
- clif->message(sd->fd, msg_sd(sd,246));
+ clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
return;
}
@@ -87,13 +89,15 @@ void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) {
/*==========================================
* Purchase item(s) from a shop
*------------------------------------------*/
-void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count) {
+static void vending_purchasereq(struct map_session_data *sd, int aid, unsigned int uid, const uint8 *data, int count)
+{
int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING];
int64 z;
struct s_vending vend[MAX_VENDING]; // against duplicate packets
struct map_session_data* vsd = map->id2sd(aid);
nullpo_retv(sd);
+ nullpo_retv(data);
if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id )
return; // invalid shop
@@ -192,14 +196,14 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
// vending item
pc->additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING);
vsd->vending[vend_list[i]].amount -= amount;
+ clif->vendingreport(vsd, idx, amount, sd->status.char_id, (int)z);
pc->cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING);
- clif->vendingreport(vsd, idx, amount);
//print buyer's name
if( battle_config.buyer_name ) {
char temp[256];
sprintf(temp, msg_sd(vsd,265), sd->status.name);
- clif_disp_onlyself(vsd,temp,strlen(temp));
+ clif_disp_onlyself(vsd, temp);
}
}
@@ -241,7 +245,8 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
* Open shop
* data := {<index>.w <amount>.w <value>.l}[count]
*------------------------------------------*/
-void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
+static void vending_openvending(struct map_session_data *sd, const char *message, const uint8 *data, int count)
+{
int i, j;
int vending_skill_lvl;
nullpo_retv(sd);
@@ -252,14 +257,14 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
vending_skill_lvl = pc->checkskill(sd, MC_VENDING);
// skill level and cart check
if( !vending_skill_lvl || !pc_iscarton(sd) ) {
- clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
// check number of items in shop
if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) {
// invalid item count
- clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
+ clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0);
return;
}
@@ -276,7 +281,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
|| pc->cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
//NOTE: official server does not do any of the following checks!
|| !sd->status.cart[index].identify // unidentified item
- || sd->status.cart[index].attribute == 1 // broken item
+ || (sd->status.cart[index].attribute & ATTR_BROKEN) != 0 // broken item
|| sd->status.cart[index].expire_time // It should not be in the cart but just in case
|| (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // can't trade bound items w/o permission
|| !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
@@ -293,7 +298,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
clif->message (sd->fd, msg_sd(sd,266)); //"Some of your items cannot be vended and were removed from the shop."
if( i == 0 ) { // no valid item found
- clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
+ clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); // custom reply packet
return;
}
sd->state.prevend = sd->state.workinprogress = 0;
@@ -310,14 +315,16 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
/// Checks if an item is being sold in given player's vending.
-bool vending_search(struct map_session_data* sd, unsigned short nameid) {
+static bool vending_search(struct map_session_data *sd, int nameid)
+{
int i;
+ nullpo_retr(false, sd);
if( !sd->state.vending ) { // not vending
return false;
}
- ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid );
+ ARR_FIND(0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == nameid);
if( i == sd->vend_num ) { // not found
return false;
}
@@ -328,16 +335,19 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid) {
/// Searches for all items in a vending, that match given ids, price and possible cards.
/// @return Whether or not the search should be continued.
-bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) {
+static bool vending_searchall(struct map_session_data *sd, const struct s_search_store_search *s)
+{
int i, c, slot;
unsigned int idx, cidx;
struct item* it;
+ nullpo_retr(false, sd);
+ nullpo_retr(false, s);
if( !sd->state.vending ) // not vending
return true;
for( idx = 0; idx < s->item_count; idx++ ) {
- ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] );
+ ARR_FIND(0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == s->itemlist[idx]);
if( i == sd->vend_num ) {// not found
continue;
}
@@ -370,7 +380,7 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
}
}
- if( !searchstore->result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) )
+ if (!searchstore->result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine, it->option))
{// result set full
return false;
}
@@ -378,16 +388,20 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
return true;
}
-void final(void) {
+
+static void final(void)
+{
db_destroy(vending->db);
}
-void init(bool minimal) {
+static void init(bool minimal)
+{
vending->db = idb_alloc(DB_OPT_BASE);
vending->next_id = 0;
}
-void vending_defaults(void) {
+void vending_defaults(void)
+{
vending = &vending_s;
vending->init = init;
diff --git a/src/map/vending.h b/src/map/vending.h
index 1d2135076..fcf80aef0 100644
--- a/src/map/vending.h
+++ b/src/map/vending.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2012-2015 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
+ * Copyright (C) 2012-2020 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ struct vending_interface {
void (*open) (struct map_session_data* sd, const char* message, const uint8* data, int count);
void (*list) (struct map_session_data* sd, unsigned int id);
void (*purchase) (struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count);
- bool (*search) (struct map_session_data* sd, unsigned short nameid);
+ bool (*search) (struct map_session_data* sd, int nameid);
bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s);
};